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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.