Re: [PATCH RFC] fs_parse: add uid & gid option parsing helpers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Jun 04, 2024 at 12:17:39PM -0500, Eric Sandeen wrote:
> Multiple filesystems take uid and gid as options, and the code to
> create the ID from an integer and validate it is standard boilerplate
> that can be moved into common parsing helper functions, so do that for
> consistency and less cut&paste.
> 
> This also helps avoid the buggy pattern noted by Seth Jenkins at
> https://lore.kernel.org/lkml/CALxfFW4BXhEwxR0Q5LSkg-8Vb4r2MONKCcUCVioehXQKr35eHg@xxxxxxxxxxxxxx/
> because uid/gid parsing will fail before any assignment in most
> filesystems.
> 
> With this in place, filesystem parsing is simplified, as in
> the patch at
> https://git.kernel.org/pub/scm/linux/kernel/git/sandeen/linux.git/commit/?h=mount-api-uid-helper&id=480d0d3c6699abfbb174b1bf2ab2bbeeec4fe911
> 
> Note that FS_USERNS_MOUNT filesystems still need to do additional
> checking with k[ug]id_has_mapping(), I think.
> 
> Thoughts? Is this useful / worthwhile? If so I can send a proper
> 2-patch series ccing the dozen or so filesystems the 2nd patch will
> touch. :)
> 
> Signed-off-by: Eric Sandeen <sandeen@xxxxxxxxxx>
> ---

Seems worthwhile to me. Ideally you'd funnel through the fc->user_ns smh
so we can do the k[ug]id_has_mapping() checks right in these parsing
helpers.

>  Documentation/filesystems/mount_api.rst |  9 +++++++--
>  fs/fs_parser.c                          | 34 +++++++++++++++++++++++++++++++++
>  include/linux/fs_parser.h               |  6 +++++-
>  3 files changed, 46 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/filesystems/mount_api.rst b/Documentation/filesystems/mount_api.rst
> index 9aaf6ef75eb53b..317934c9e8fcac 100644
> --- a/Documentation/filesystems/mount_api.rst
> +++ b/Documentation/filesystems/mount_api.rst
> @@ -645,6 +645,8 @@ The members are as follows:
>  	fs_param_is_blockdev	Blockdev path		* Needs lookup
>  	fs_param_is_path	Path			* Needs lookup
>  	fs_param_is_fd		File descriptor		result->int_32
> +	fs_param_is_uid		User ID (u32)           result->uid
> +	fs_param_is_gid		Group ID (u32)          result->gid
>  	=======================	=======================	=====================
>  
>       Note that if the value is of fs_param_is_bool type, fs_parse() will try
> @@ -678,6 +680,8 @@ The members are as follows:
>  	fsparam_bdev()		fs_param_is_blockdev
>  	fsparam_path()		fs_param_is_path
>  	fsparam_fd()		fs_param_is_fd
> +	fsparam_uid()		fs_param_is_uid
> +	fsparam_gid()		fs_param_is_gid
>  	=======================	===============================================
>  
>       all of which take two arguments, name string and option number - for
> @@ -784,8 +788,9 @@ process the parameters it is given.
>       option number (which it returns).
>  
>       If successful, and if the parameter type indicates the result is a
> -     boolean, integer or enum type, the value is converted by this function and
> -     the result stored in result->{boolean,int_32,uint_32,uint_64}.
> +     boolean, integer, enum, uid, or gid type, the value is converted by this
> +     function and the result stored in
> +     result->{boolean,int_32,uint_32,uint_64,uid,gid}.
>  
>       If a match isn't initially made, the key is prefixed with "no" and no
>       value is present then an attempt will be made to look up the key with the
> diff --git a/fs/fs_parser.c b/fs/fs_parser.c
> index a4d6ca0b8971e6..9c4e4984aae8a4 100644
> --- a/fs/fs_parser.c
> +++ b/fs/fs_parser.c
> @@ -308,6 +308,40 @@ int fs_param_is_fd(struct p_log *log, const struct fs_parameter_spec *p,
>  }
>  EXPORT_SYMBOL(fs_param_is_fd);
>  
> +int fs_param_is_uid(struct p_log *log, const struct fs_parameter_spec *p,
> +		    struct fs_parameter *param, struct fs_parse_result *result)
> +{
> +	kuid_t uid;
> +
> +	if (fs_param_is_u32(log, p, param, result) != 0)
> +		return fs_param_bad_value(log, param);
> +
> +	uid = make_kuid(current_user_ns(), result->uint_32);
> +	if (!uid_valid(uid))
> +		return inval_plog(log, "Bad uid '%s'", param->string);
> +
> +	result->uid = uid;
> +	return 0;
> +}
> +EXPORT_SYMBOL(fs_param_is_uid);
> +
> +int fs_param_is_gid(struct p_log *log, const struct fs_parameter_spec *p,
> +		    struct fs_parameter *param, struct fs_parse_result *result)
> +{
> +	kgid_t gid;
> +
> +	if (fs_param_is_u32(log, p, param, result) != 0)
> +		return fs_param_bad_value(log, param);
> +
> +	gid = make_kgid(current_user_ns(), result->uint_32);
> +	if (!gid_valid(gid))
> +		return inval_plog(log, "Bad gid '%s'", param->string);
> +
> +	result->gid = gid;
> +	return 0;
> +}
> +EXPORT_SYMBOL(fs_param_is_gid);
> +
>  int fs_param_is_blockdev(struct p_log *log, const struct fs_parameter_spec *p,
>  		  struct fs_parameter *param, struct fs_parse_result *result)
>  {
> diff --git a/include/linux/fs_parser.h b/include/linux/fs_parser.h
> index d3350979115f0a..6cf713a7e6c6fc 100644
> --- a/include/linux/fs_parser.h
> +++ b/include/linux/fs_parser.h
> @@ -28,7 +28,7 @@ typedef int fs_param_type(struct p_log *,
>   */
>  fs_param_type fs_param_is_bool, fs_param_is_u32, fs_param_is_s32, fs_param_is_u64,
>  	fs_param_is_enum, fs_param_is_string, fs_param_is_blob, fs_param_is_blockdev,
> -	fs_param_is_path, fs_param_is_fd;
> +	fs_param_is_path, fs_param_is_fd, fs_param_is_uid, fs_param_is_gid;
>  
>  /*
>   * Specification of the type of value a parameter wants.
> @@ -57,6 +57,8 @@ struct fs_parse_result {
>  		int		int_32;		/* For spec_s32/spec_enum */
>  		unsigned int	uint_32;	/* For spec_u32{,_octal,_hex}/spec_enum */
>  		u64		uint_64;	/* For spec_u64 */
> +		kuid_t		uid;
> +		kgid_t		gid;
>  	};
>  };
>  
> @@ -131,6 +133,8 @@ static inline bool fs_validate_description(const char *name,
>  #define fsparam_bdev(NAME, OPT)	__fsparam(fs_param_is_blockdev, NAME, OPT, 0, NULL)
>  #define fsparam_path(NAME, OPT)	__fsparam(fs_param_is_path, NAME, OPT, 0, NULL)
>  #define fsparam_fd(NAME, OPT)	__fsparam(fs_param_is_fd, NAME, OPT, 0, NULL)
> +#define fsparam_uid(NAME, OPT) __fsparam(fs_param_is_uid, NAME, OPT, 0, NULL)
> +#define fsparam_gid(NAME, OPT) __fsparam(fs_param_is_gid, NAME, OPT, 0, NULL)
>  
>  /* String parameter that allows empty argument */
>  #define fsparam_string_empty(NAME, OPT) \
> -- 
> cgit 1.2.3-korg
> 




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux