All of lore.kernel.org
 help / color / mirror / Atom feed
From: Luis Henriques <lhenriques@suse.de>
To: Christian Brauner <brauner@kernel.org>
Cc: Eric Sandeen <sandeen@sandeen.net>,
	 Theodore Ts'o <tytso@mit.edu>,
	Andreas Dilger <adilger.kernel@dilger.ca>,
	 Alexander Viro <viro@zeniv.linux.org.uk>,
	 Jan Kara <jack@suse.cz>,  Miklos Szeredi <miklos@szeredi.hu>,
	 Amir Goldstein <amir73il@gmail.com>,
	linux-ext4@vger.kernel.org,  linux-fsdevel@vger.kernel.org,
	linux-unionfs@vger.kernel.org,  linux-kernel@vger.kernel.org
Subject: Re: [PATCH 1/3] fs_parser: handle parameters that can be empty and don't have a value
Date: Sun, 03 Mar 2024 21:17:25 +0000	[thread overview]
Message-ID: <871q8r9fru.fsf@suse.de> (raw)
In-Reply-To: <20240302-avancieren-sehtest-90eb364bfcd5@brauner> (Christian Brauner's message of "Sat, 2 Mar 2024 12:46:41 +0100")

Christian Brauner <brauner@kernel.org> writes:

> On Fri, Mar 01, 2024 at 03:45:27PM +0000, Luis Henriques wrote:
>> Christian Brauner <brauner@kernel.org> writes:
>> 
>> > On Thu, Feb 29, 2024 at 04:30:08PM +0000, Luis Henriques wrote:
>> >> Currently, only parameters that have the fs_parameter_spec 'type' set to
>> >> NULL are handled as 'flag' types.  However, parameters that have the
>> >> 'fs_param_can_be_empty' flag set and their value is NULL should also be
>> >> handled as 'flag' type, as their type is set to 'fs_value_is_flag'.
>> >> 
>> >> Signed-off-by: Luis Henriques <lhenriques@suse.de>
>> >> ---
>> >>  fs/fs_parser.c | 3 ++-
>> >>  1 file changed, 2 insertions(+), 1 deletion(-)
>> >> 
>> >> diff --git a/fs/fs_parser.c b/fs/fs_parser.c
>> >> index edb3712dcfa5..53f6cb98a3e0 100644
>> >> --- a/fs/fs_parser.c
>> >> +++ b/fs/fs_parser.c
>> >> @@ -119,7 +119,8 @@ int __fs_parse(struct p_log *log,
>> >>  	/* Try to turn the type we were given into the type desired by the
>> >>  	 * parameter and give an error if we can't.
>> >>  	 */
>> >> -	if (is_flag(p)) {
>> >> +	if (is_flag(p) ||
>> >> +	    (!param->string && (p->flags & fs_param_can_be_empty))) {
>> >>  		if (param->type != fs_value_is_flag)
>> >>  			return inval_plog(log, "Unexpected value for '%s'",
>> >>  				      param->key);
>> >
>> > If the parameter was derived from FSCONFIG_SET_STRING in fsconfig() then
>> > param->string is guaranteed to not be NULL. So really this is only
>> > about:
>> >
>> > FSCONFIG_SET_FD
>> > FSCONFIG_SET_BINARY
>> > FSCONFIG_SET_PATH
>> > FSCONFIG_SET_PATH_EMPTY
>> >
>> > and those values being used without a value. What filesystem does this?
>> > I don't see any.
>> >
>> > The tempting thing to do here is to to just remove fs_param_can_be_empty
>> > from every helper that isn't fs_param_is_string() until we actually have
>> > a filesystem that wants to use any of the above as flags. Will lose a
>> > lot of code that isn't currently used.
>> 
>> Right, I find it quite confusing and I may be fixing the issue in the
>> wrong place.  What I'm seeing with ext4 when I mount a filesystem using
>> the option '-o usrjquota' is that fs_parse() will get:
>> 
>>  * p->type is set to fs_param_is_string
>>    ('p' is a struct fs_parameter_spec, ->type is a function)
>>  * param->type is set to fs_value_is_flag
>>    ('param' is a struct fs_parameter, ->type is an enum)
>> 
>> This is because ext4 will use the __fsparam macro to set define a
>> fs_param_spec as a fs_param_is_string but will also set the
>> fs_param_can_be_empty; and the fsconfig() syscall will get that parameter
>> as a flag.  That's why param->string will be NULL in this case.
>
> Thanks for the details. Let me see if I get this right. So you're saying that
> someone is doing:
>
> fsconfig(..., FSCONFIG_SET_FLAG, "usrjquota", NULL, 0); // [1]
>
> ? Is so that is a vital part of the explanation. So please put that in the
> commit message.

Right, I guess I should have added a simple usecase for that in the commit
message.  I.e. add a simple 'mount' command with this parameter without
any value.

> Then ext4 defines:
>
> 	fsparam_string_empty ("usrjquota",		Opt_usrjquota),
>
> So [1] gets us:
>
>         param->type == fs_value_is_flag
>         param->string == NULL
>
> Now we enter into
> fs_parse()
> -> __fs_parse()
>    -> fs_lookup_key() for @param and that does:
>
>         bool want_flag = param->type == fs_value_is_flag;
>
>         *negated = false;
>         for (p = desc; p->name; p++) {
>                 if (strcmp(p->name, name) != 0)
>                         continue;
>                 if (likely(is_flag(p) == want_flag))
>                         return p;
>                 other = p;
>         }
>
> So we don't have a flag parameter defined so the only real match we get is
> @other for:
>
>         fsparam_string_empty ("usrjquota",		Opt_usrjquota),
>
> What happens now is that you call p->type == fs_param_is_string() and that
> rejects it as bad parameter because param->type == fs_value_is_flag !=
> fs_value_is_string as required. So you dont end up getting Opt_userjquota
> called with param->string NULL, right? So there's not NULL deref or anything,
> right?
>
> You just fail to set usrjquota. Ok, so I think the correct fix is to do
> something like the following in ext4:
>
>         fsparam_string_empty ("usrjquota",      Opt_usrjquota),
>         fs_param_flag        ("usrjquota",      Opt_usrjquota_flag),
>
> and then in the switch you can do:
>
> switch (opt)
> case Opt_usrjquota:
>         // string thing
> case Opt_usrjquota_flag:
>         // flag thing
>
> And I really think we should kill all empty handling for non-string types and
> only add that when there's a filesystem that actually needs it.

Yeah, that looks like the right fix.  I see you sent out a patch doing
something like this, so I'll comment there instead.

Cheers,
-- 
Luís

  parent reply	other threads:[~2024-03-03 21:17 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-29 16:30 [PATCH 0/3] fs_parser: handle parameters that can be empty and don't have a value Luis Henriques
2024-02-29 16:30 ` [PATCH 1/3] " Luis Henriques
2024-03-01 13:31   ` Christian Brauner
2024-03-01 15:45     ` Luis Henriques
2024-03-02 11:46       ` Christian Brauner
2024-03-02 17:56         ` Christian Brauner
2024-03-03 21:31           ` Luis Henriques
2024-03-04  9:04             ` Christian Brauner
2024-03-03 21:17         ` Luis Henriques [this message]
2024-03-07 15:13       ` Jan Kara
2024-03-08  9:53         ` Christian Brauner
2024-03-08 10:12           ` Luis Henriques
2024-03-08 23:09             ` Jan Kara
2024-03-11 10:26               ` Luis Henriques
2024-03-11 16:01                 ` Jan Kara
2024-02-29 16:30 ` [PATCH 2/3] ext4: fix mount parameters check for empty values Luis Henriques
2024-03-01 13:36   ` Christian Brauner
2024-03-01 15:47     ` Luis Henriques
2024-02-29 16:30 ` [PATCH 3/3] overlay: " Luis Henriques
2024-03-01 13:37   ` Christian Brauner
2024-03-01 13:12 ` [PATCH 0/3] fs_parser: handle parameters that can be empty and don't have a value Christian Brauner
2024-03-01 14:54   ` Eric Sandeen

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=871q8r9fru.fsf@suse.de \
    --to=lhenriques@suse.de \
    --cc=adilger.kernel@dilger.ca \
    --cc=amir73il@gmail.com \
    --cc=brauner@kernel.org \
    --cc=jack@suse.cz \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-unionfs@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=sandeen@sandeen.net \
    --cc=tytso@mit.edu \
    --cc=viro@zeniv.linux.org.uk \
    /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.