From: Al Viro <viro@zeniv.linux.org.uk>
To: Laura Abbott <labbott@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
Ilya Dryomov <idryomov@gmail.com>,
David Howells <dhowells@redhat.com>,
Jeremi Piotrowski <jeremi.piotrowski@gmail.com>,
Linux FS Devel <linux-fsdevel@vger.kernel.org>,
Phillip Lougher <phillip@squashfs.org.uk>,
LKML <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH] vfs: Don't reject unknown parameters
Date: Thu, 12 Dec 2019 21:36:09 +0000 [thread overview]
Message-ID: <20191212213609.GK4203@ZenIV.linux.org.uk> (raw)
In-Reply-To: <cf4c9634-1503-d182-cb12-810fb969bc96@redhat.com>
On Thu, Dec 12, 2019 at 03:01:56PM -0500, Laura Abbott wrote:
> +static const struct fs_parameter_spec no_opt_fs_param_specs[] = {
> + fsparam_string ("source", NO_OPT_SOURCE),
> + {}
> +};
> +
> +const struct fs_parameter_description no_opt_fs_parameters = {
> + .name = "no_opt_fs",
> + .specs = no_opt_fs_param_specs,
> +};
> +
> +int fs_no_opt_parse_param(struct fs_context *fc, struct fs_parameter *param)
> +{
> + struct fs_parse_result result;
> + int opt;
> +
> + opt = fs_parse(fc, &no_opt_fs_parameters, param, &result);
> + if (opt < 0) {
> + /* Just log an error for backwards compatibility */
> + errorf(fc, "%s: Unknown parameter '%s'",
> + fc->fs_type->name, param->key);
> + return 0;
> + }
> +
> + switch (opt) {
> + case NO_OPT_SOURCE:
> + if (param->type != fs_value_is_string)
> + return invalf(fc, "%s: Non-string source",
> + fc->fs_type->name);
> + if (fc->source)
> + return invalf(fc, "%s: Multiple sources specified",
> + fc->fs_type->name);
> + fc->source = param->string;
> + param->string = NULL;
> + break;
> + }
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(fs_no_opt_parse_param);
Yecchhhh... Could you explain why do you want to bother with fs_parse()
here? Seriously, look at it.
{
const struct fs_parameter_spec *p;
const struct fs_parameter_enum *e;
int ret = -ENOPARAM, b;
result->has_value = !!param->string;
result->negated = false;
result->uint_64 = 0;
p = fs_lookup_key(desc, param->key);
OK, that's
if (strcmp(param->key, "source") == 0)
p = no_opt_fs_param_specs;
else
p = NULL;
if (!p) {
not "source"
/* If we didn't find something that looks like "noxxx", see if
* "xxx" takes the "no"-form negative - but only if there
* wasn't an value.
*/
if (result->has_value)
goto unknown_parameter;
if param->string is non-NULL - piss off
if (param->key[0] != 'n' || param->key[1] != 'o' || !param->key[2])
goto unknown_parameter;
if not "no"<something> - ditto
p = fs_lookup_key(desc, param->key + 2);
if (!p)
goto unknown_parameter;
if not "nosource" - ditto
if (!(p->flags & fs_param_neg_with_no))
goto unknown_parameter;
... and since ->flags doesn't have that bit, the same for "nosource" anyway.
result->boolean = false;
result->negated = true;
won't get here
}
OK, so the above is simply 'piss off unless param->key is "source"'. And
p is no_opt_fs_param_specs.
if (p->flags & fs_param_deprecated)
nope
warnf(fc, "%s: Deprecated parameter '%s'",
desc->name, param->key);
if (result->negated)
goto okay;
nope - set to false, never changed
/* Certain parameter types only take a string and convert it. */
switch (p->type) {
that'd be fs_param_is_string
...
case fs_param_is_string:
if (param->type != fs_value_is_string)
goto bad_value;
if (!result->has_value) {
if param->string is NULL...
if (p->flags & fs_param_v_optional)
nope
goto okay;
goto bad_value;
}
/* Fall through */
default:
break;
}
/* Try to turn the type we were given into the type desired by the
* parameter and give an error if we can't.
*/
switch (p->type) {
again, fs_param_is_string
...
case fs_param_is_string:
goto okay;
...
okay:
return p->opt;
bad_value:
return invalf(fc, "%s: Bad value for '%s'", desc->name, param->key);
unknown_parameter:
return -ENOPARAM;
In other words, that thing is equivalent to
if (strcmp(param->key, "source")) {
errorf(fc, "%s: Unknown parameter '%s'",
fc->fs_type->name, param->key);
return 0;
}
if (param->type != fs_value_is_string || !param->value) {
invalf(fc, "%s: Bad value for '%s'", fc->fs_type->name, param->key);
errorf(fc, "%s: Unknown parameter '%s'",
fc->fs_type->name, param->key);
return 0; // almost certainly not what you intended for that case
}
if (fc->source)
return invalf(fc, "%s: Multiple sources specified", fc->fs_type->name);
fc->source = param->string;
param->string = NULL;
return 0;
And that - without the boilerplate from hell. But if you look at the caller of
that method, you'll see this:
if (fc->ops->parse_param) {
ret = fc->ops->parse_param(fc, param);
if (ret != -ENOPARAM)
return ret;
}
/* If the filesystem doesn't take any arguments, give it the
* default handling of source.
*/
if (strcmp(param->key, "source") == 0) {
if (param->type != fs_value_is_string)
return invalf(fc, "VFS: Non-string source");
if (fc->source)
return invalf(fc, "VFS: Multiple sources");
fc->source = param->string;
param->string = NULL;
return 0;
}
return invalf(fc, "%s: Unknown parameter '%s'",
fc->fs_type->name, param->key);
}
So you could bloody well just leave recognition (and handling) of "source"
to the caller, leaving you with just this:
if (strcmp(param->key, "source") == 0)
return -ENOPARAM;
/* Just log an error for backwards compatibility */
errorf(fc, "%s: Unknown parameter '%s'", fc->fs_type->name, param->key);
return 0;
and that's it.
next prev parent reply other threads:[~2019-12-12 21:36 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-12 14:50 [PATCH] vfs: Don't reject unknown parameters Laura Abbott
2019-12-12 17:13 ` Ilya Dryomov
2019-12-12 17:47 ` Laura Abbott
2019-12-12 17:56 ` Linus Torvalds
2019-12-12 20:01 ` Laura Abbott
2019-12-12 21:36 ` Al Viro [this message]
2019-12-13 9:15 ` Miklos Szeredi
2019-12-13 9:30 ` Miklos Szeredi
2019-12-17 17:46 ` Al Viro
2019-12-17 17:49 ` David Howells
2019-12-17 18:08 ` Miklos Szeredi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191212213609.GK4203@ZenIV.linux.org.uk \
--to=viro@zeniv.linux.org.uk \
--cc=dhowells@redhat.com \
--cc=idryomov@gmail.com \
--cc=jeremi.piotrowski@gmail.com \
--cc=labbott@redhat.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=phillip@squashfs.org.uk \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).