Commit b8fc1bd7 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'vfs-6.11.mount.api' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs mount API updates from Christian Brauner:

 - Add a generic helper to parse uid and gid mount options.

   Currently we open-code the same logic in various filesystems which is
   error prone, especially since the verification of uid and gid mount
   options is a sensitive operation in the face of idmappings.

   Add a generic helper and convert all filesystems over to it. Make
   sure that filesystems that are mountable in unprivileged containers
   verify that the specified uid and gid can be represented in the
   owning namespace of the filesystem.

 - Convert hostfs to the new mount api.

* tag 'vfs-6.11.mount.api' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
  fuse: Convert to new uid/gid option parsing helpers
  fuse: verify {g,u}id mount options correctly
  fat: Convert to new uid/gid option parsing helpers
  fat: Convert to new mount api
  fat: move debug into fat_mount_options
  vboxsf: Convert to new uid/gid option parsing helpers
  tracefs: Convert to new uid/gid option parsing helpers
  smb: client: Convert to new uid/gid option parsing helpers
  tmpfs: Convert to new uid/gid option parsing helpers
  ntfs3: Convert to new uid/gid option parsing helpers
  isofs: Convert to new uid/gid option parsing helpers
  hugetlbfs: Convert to new uid/gid option parsing helpers
  ext4: Convert to new uid/gid option parsing helpers
  exfat: Convert to new uid/gid option parsing helpers
  efivarfs: Convert to new uid/gid option parsing helpers
  debugfs: Convert to new uid/gid option parsing helpers
  autofs: Convert to new uid/gid option parsing helpers
  fs_parse: add uid & gid option option parsing helpers
  hostfs: Add const qualifier to host_root in hostfs_fill_super()
  hostfs: convert hostfs to use the new mount API
parents 4a051e4c eea6a832
......@@ -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
......
......@@ -126,7 +126,7 @@ enum {
const struct fs_parameter_spec autofs_param_specs[] = {
fsparam_flag ("direct", Opt_direct),
fsparam_fd ("fd", Opt_fd),
fsparam_u32 ("gid", Opt_gid),
fsparam_gid ("gid", Opt_gid),
fsparam_flag ("ignore", Opt_ignore),
fsparam_flag ("indirect", Opt_indirect),
fsparam_u32 ("maxproto", Opt_maxproto),
......@@ -134,7 +134,7 @@ const struct fs_parameter_spec autofs_param_specs[] = {
fsparam_flag ("offset", Opt_offset),
fsparam_u32 ("pgrp", Opt_pgrp),
fsparam_flag ("strictexpire", Opt_strictexpire),
fsparam_u32 ("uid", Opt_uid),
fsparam_uid ("uid", Opt_uid),
{}
};
......@@ -193,8 +193,6 @@ static int autofs_parse_param(struct fs_context *fc, struct fs_parameter *param)
struct autofs_fs_context *ctx = fc->fs_private;
struct autofs_sb_info *sbi = fc->s_fs_info;
struct fs_parse_result result;
kuid_t uid;
kgid_t gid;
int opt;
opt = fs_parse(fc, autofs_param_specs, param, &result);
......@@ -205,16 +203,10 @@ static int autofs_parse_param(struct fs_context *fc, struct fs_parameter *param)
case Opt_fd:
return autofs_parse_fd(fc, sbi, param, &result);
case Opt_uid:
uid = make_kuid(current_user_ns(), result.uint_32);
if (!uid_valid(uid))
return invalfc(fc, "Invalid uid");
ctx->uid = uid;
ctx->uid = result.uid;
break;
case Opt_gid:
gid = make_kgid(current_user_ns(), result.uint_32);
if (!gid_valid(gid))
return invalfc(fc, "Invalid gid");
ctx->gid = gid;
ctx->gid = result.gid;
break;
case Opt_pgrp:
ctx->pgrp = result.uint_32;
......
......@@ -92,9 +92,9 @@ enum {
};
static const struct fs_parameter_spec debugfs_param_specs[] = {
fsparam_u32 ("gid", Opt_gid),
fsparam_gid ("gid", Opt_gid),
fsparam_u32oct ("mode", Opt_mode),
fsparam_u32 ("uid", Opt_uid),
fsparam_uid ("uid", Opt_uid),
{}
};
......@@ -102,8 +102,6 @@ static int debugfs_parse_param(struct fs_context *fc, struct fs_parameter *param
{
struct debugfs_fs_info *opts = fc->s_fs_info;
struct fs_parse_result result;
kuid_t uid;
kgid_t gid;
int opt;
opt = fs_parse(fc, debugfs_param_specs, param, &result);
......@@ -120,16 +118,10 @@ static int debugfs_parse_param(struct fs_context *fc, struct fs_parameter *param
switch (opt) {
case Opt_uid:
uid = make_kuid(current_user_ns(), result.uint_32);
if (!uid_valid(uid))
return invalf(fc, "Unknown uid");
opts->uid = uid;
opts->uid = result.uid;
break;
case Opt_gid:
gid = make_kgid(current_user_ns(), result.uint_32);
if (!gid_valid(gid))
return invalf(fc, "Unknown gid");
opts->gid = gid;
opts->gid = result.gid;
break;
case Opt_mode:
opts->mode = result.uint_32 & S_IALLUGO;
......
......@@ -275,8 +275,8 @@ enum {
};
static const struct fs_parameter_spec efivarfs_parameters[] = {
fsparam_u32("uid", Opt_uid),
fsparam_u32("gid", Opt_gid),
fsparam_uid("uid", Opt_uid),
fsparam_gid("gid", Opt_gid),
{},
};
......@@ -293,14 +293,10 @@ static int efivarfs_parse_param(struct fs_context *fc, struct fs_parameter *para
switch (opt) {
case Opt_uid:
opts->uid = make_kuid(current_user_ns(), result.uint_32);
if (!uid_valid(opts->uid))
return -EINVAL;
opts->uid = result.uid;
break;
case Opt_gid:
opts->gid = make_kgid(current_user_ns(), result.uint_32);
if (!gid_valid(opts->gid))
return -EINVAL;
opts->gid = result.gid;
break;
default:
return -EINVAL;
......
......@@ -225,8 +225,8 @@ static const struct constant_table exfat_param_enums[] = {
};
static const struct fs_parameter_spec exfat_parameters[] = {
fsparam_u32("uid", Opt_uid),
fsparam_u32("gid", Opt_gid),
fsparam_uid("uid", Opt_uid),
fsparam_gid("gid", Opt_gid),
fsparam_u32oct("umask", Opt_umask),
fsparam_u32oct("dmask", Opt_dmask),
fsparam_u32oct("fmask", Opt_fmask),
......@@ -262,10 +262,10 @@ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
switch (opt) {
case Opt_uid:
opts->fs_uid = make_kuid(current_user_ns(), result.uint_32);
opts->fs_uid = result.uid;
break;
case Opt_gid:
opts->fs_gid = make_kgid(current_user_ns(), result.uint_32);
opts->fs_gid = result.gid;
break;
case Opt_umask:
opts->fs_fmask = result.uint_32;
......
......@@ -1721,8 +1721,8 @@ static const struct fs_parameter_spec ext4_param_specs[] = {
fsparam_flag ("bsdgroups", Opt_grpid),
fsparam_flag ("nogrpid", Opt_nogrpid),
fsparam_flag ("sysvgroups", Opt_nogrpid),
fsparam_u32 ("resgid", Opt_resgid),
fsparam_u32 ("resuid", Opt_resuid),
fsparam_gid ("resgid", Opt_resgid),
fsparam_uid ("resuid", Opt_resuid),
fsparam_u32 ("sb", Opt_sb),
fsparam_enum ("errors", Opt_errors, ext4_param_errors),
fsparam_flag ("nouid32", Opt_nouid32),
......@@ -2127,8 +2127,6 @@ static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param)
struct fs_parse_result result;
const struct mount_opts *m;
int is_remount;
kuid_t uid;
kgid_t gid;
int token;
token = fs_parse(fc, ext4_param_specs, param, &result);
......@@ -2270,23 +2268,11 @@ static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param)
ctx->spec |= EXT4_SPEC_s_stripe;
return 0;
case Opt_resuid:
uid = make_kuid(current_user_ns(), result.uint_32);
if (!uid_valid(uid)) {
ext4_msg(NULL, KERN_ERR, "Invalid uid value %d",
result.uint_32);
return -EINVAL;
}
ctx->s_resuid = uid;
ctx->s_resuid = result.uid;
ctx->spec |= EXT4_SPEC_s_resuid;
return 0;
case Opt_resgid:
gid = make_kgid(current_user_ns(), result.uint_32);
if (!gid_valid(gid)) {
ext4_msg(NULL, KERN_ERR, "Invalid gid value %d",
result.uint_32);
return -EINVAL;
}
ctx->s_resgid = gid;
ctx->s_resgid = result.gid;
ctx->spec |= EXT4_SPEC_s_resgid;
return 0;
case Opt_journal_dev:
......
......@@ -7,6 +7,8 @@
#include <linux/hash.h>
#include <linux/ratelimit.h>
#include <linux/msdos_fs.h>
#include <linux/fs_context.h>
#include <linux/fs_parser.h>
/*
* vfat shortname flags
......@@ -51,7 +53,8 @@ struct fat_mount_options {
tz_set:1, /* Filesystem timestamps' offset set */
rodir:1, /* allow ATTR_RO for directory */
discard:1, /* Issue discard requests on deletions */
dos1xfloppy:1; /* Assume default BPB for DOS 1.x floppies */
dos1xfloppy:1, /* Assume default BPB for DOS 1.x floppies */
debug:1; /* Not currently used */
};
#define FAT_HASH_BITS 8
......@@ -415,12 +418,21 @@ extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos);
extern struct inode *fat_build_inode(struct super_block *sb,
struct msdos_dir_entry *de, loff_t i_pos);
extern int fat_sync_inode(struct inode *inode);
extern int fat_fill_super(struct super_block *sb, void *data, int silent,
int isvfat, void (*setup)(struct super_block *));
extern int fat_fill_super(struct super_block *sb, struct fs_context *fc,
void (*setup)(struct super_block *));
extern int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de);
extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
struct inode *i2);
extern const struct fs_parameter_spec fat_param_spec[];
int fat_init_fs_context(struct fs_context *fc, bool is_vfat);
void fat_free_fc(struct fs_context *fc);
int fat_parse_param(struct fs_context *fc, struct fs_parameter *param,
bool is_vfat);
int fat_reconfigure(struct fs_context *fc);
static inline unsigned long fat_dir_hash(int logstart)
{
return hash_32(logstart, FAT_HASH_BITS);
......
This diff is collapsed.
......@@ -650,24 +650,48 @@ static void setup(struct super_block *sb)
sb->s_flags |= SB_NOATIME;
}
static int msdos_fill_super(struct super_block *sb, void *data, int silent)
static int msdos_fill_super(struct super_block *sb, struct fs_context *fc)
{
return fat_fill_super(sb, data, silent, 0, setup);
return fat_fill_super(sb, fc, setup);
}
static struct dentry *msdos_mount(struct file_system_type *fs_type,
int flags, const char *dev_name,
void *data)
static int msdos_get_tree(struct fs_context *fc)
{
return mount_bdev(fs_type, flags, dev_name, data, msdos_fill_super);
return get_tree_bdev(fc, msdos_fill_super);
}
static int msdos_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
return fat_parse_param(fc, param, false);
}
static const struct fs_context_operations msdos_context_ops = {
.parse_param = msdos_parse_param,
.get_tree = msdos_get_tree,
.reconfigure = fat_reconfigure,
.free = fat_free_fc,
};
static int msdos_init_fs_context(struct fs_context *fc)
{
int err;
/* Initialize with is_vfat == false */
err = fat_init_fs_context(fc, false);
if (err)
return err;
fc->ops = &msdos_context_ops;
return 0;
}
static struct file_system_type msdos_fs_type = {
.owner = THIS_MODULE,
.name = "msdos",
.mount = msdos_mount,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
.init_fs_context = msdos_init_fs_context,
.parameters = fat_param_spec,
};
MODULE_ALIAS_FS("msdos");
......
......@@ -1195,24 +1195,48 @@ static void setup(struct super_block *sb)
sb->s_d_op = &vfat_dentry_ops;
}
static int vfat_fill_super(struct super_block *sb, void *data, int silent)
static int vfat_fill_super(struct super_block *sb, struct fs_context *fc)
{
return fat_fill_super(sb, data, silent, 1, setup);
return fat_fill_super(sb, fc, setup);
}
static struct dentry *vfat_mount(struct file_system_type *fs_type,
int flags, const char *dev_name,
void *data)
static int vfat_get_tree(struct fs_context *fc)
{
return mount_bdev(fs_type, flags, dev_name, data, vfat_fill_super);
return get_tree_bdev(fc, vfat_fill_super);
}
static int vfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
return fat_parse_param(fc, param, true);
}
static const struct fs_context_operations vfat_context_ops = {
.parse_param = vfat_parse_param,
.get_tree = vfat_get_tree,
.reconfigure = fat_reconfigure,
.free = fat_free_fc,
};
static int vfat_init_fs_context(struct fs_context *fc)
{
int err;
/* Initialize with is_vfat == true */
err = fat_init_fs_context(fc, true);
if (err)
return err;
fc->ops = &vfat_context_ops;
return 0;
}
static struct file_system_type vfat_fs_type = {
.owner = THIS_MODULE,
.name = "vfat",
.mount = vfat_mount,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
.init_fs_context = vfat_init_fs_context,
.parameters = fat_param_spec,
};
MODULE_ALIAS_FS("vfat");
......
......@@ -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, "Invalid 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, "Invalid 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)
{
......
......@@ -740,8 +740,8 @@ static const struct fs_parameter_spec fuse_fs_parameters[] = {
fsparam_string ("source", OPT_SOURCE),
fsparam_u32 ("fd", OPT_FD),
fsparam_u32oct ("rootmode", OPT_ROOTMODE),
fsparam_u32 ("user_id", OPT_USER_ID),
fsparam_u32 ("group_id", OPT_GROUP_ID),
fsparam_uid ("user_id", OPT_USER_ID),
fsparam_gid ("group_id", OPT_GROUP_ID),
fsparam_flag ("default_permissions", OPT_DEFAULT_PERMISSIONS),
fsparam_flag ("allow_other", OPT_ALLOW_OTHER),
fsparam_u32 ("max_read", OPT_MAX_READ),
......@@ -755,6 +755,8 @@ static int fuse_parse_param(struct fs_context *fsc, struct fs_parameter *param)
struct fs_parse_result result;
struct fuse_fs_context *ctx = fsc->fs_private;
int opt;
kuid_t kuid;
kgid_t kgid;
if (fsc->purpose == FS_CONTEXT_FOR_RECONFIGURE) {
/*
......@@ -799,16 +801,26 @@ static int fuse_parse_param(struct fs_context *fsc, struct fs_parameter *param)
break;
case OPT_USER_ID:
ctx->user_id = make_kuid(fsc->user_ns, result.uint_32);
if (!uid_valid(ctx->user_id))
kuid = result.uid;
/*
* The requested uid must be representable in the
* filesystem's idmapping.
*/
if (!kuid_has_mapping(fsc->user_ns, kuid))
return invalfc(fsc, "Invalid user_id");
ctx->user_id = kuid;
ctx->user_id_present = true;
break;
case OPT_GROUP_ID:
ctx->group_id = make_kgid(fsc->user_ns, result.uint_32);
if (!gid_valid(ctx->group_id))
kgid = result.gid;
/*
* The requested gid must be representable in the
* filesystem's idmapping.
*/
if (!kgid_has_mapping(fsc->user_ns, kgid))
return invalfc(fsc, "Invalid group_id");
ctx->group_id = kgid;
ctx->group_id_present = true;
break;
......
......@@ -16,11 +16,16 @@
#include <linux/seq_file.h>
#include <linux/writeback.h>
#include <linux/mount.h>
#include <linux/fs_context.h>
#include <linux/namei.h>
#include "hostfs.h"
#include <init.h>
#include <kern.h>
struct hostfs_fs_info {
char *host_root_path;
};
struct hostfs_inode_info {
int fd;
fmode_t mode;
......@@ -90,8 +95,10 @@ static char *__dentry_name(struct dentry *dentry, char *name)
char *p = dentry_path_raw(dentry, name, PATH_MAX);
char *root;
size_t len;
struct hostfs_fs_info *fsi;
root = dentry->d_sb->s_fs_info;
fsi = dentry->d_sb->s_fs_info;
root = fsi->host_root_path;
len = strlen(root);
if (IS_ERR(p)) {
__putname(name);
......@@ -196,8 +203,10 @@ static int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf)
long long f_bavail;
long long f_files;
long long f_ffree;
struct hostfs_fs_info *fsi;
err = do_statfs(dentry->d_sb->s_fs_info,
fsi = dentry->d_sb->s_fs_info;
err = do_statfs(fsi->host_root_path,
&sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
&f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
&sf->f_namelen);
......@@ -245,7 +254,11 @@ static void hostfs_free_inode(struct inode *inode)
static int hostfs_show_options(struct seq_file *seq, struct dentry *root)
{
const char *root_path = root->d_sb->s_fs_info;
struct hostfs_fs_info *fsi;
const char *root_path;
fsi = root->d_sb->s_fs_info;
root_path = fsi->host_root_path;
size_t offset = strlen(root_ino) + 1;
if (strlen(root_path) > offset)
......@@ -911,10 +924,11 @@ static const struct inode_operations hostfs_link_iops = {
.get_link = hostfs_get_link,
};
static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
static int hostfs_fill_super(struct super_block *sb, struct fs_context *fc)
{
struct hostfs_fs_info *fsi = sb->s_fs_info;
const char *host_root = fc->source;
struct inode *root_inode;
char *host_root_path, *req_root = d;
int err;
sb->s_blocksize = 1024;
......@@ -928,15 +942,15 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
return err;
/* NULL is printed as '(null)' by printf(): avoid that. */
if (req_root == NULL)
req_root = "";
if (fc->source == NULL)
host_root = "";
sb->s_fs_info = host_root_path =
kasprintf(GFP_KERNEL, "%s/%s", root_ino, req_root);
if (host_root_path == NULL)
fsi->host_root_path =
kasprintf(GFP_KERNEL, "%s/%s", root_ino, host_root);
if (fsi->host_root_path == NULL)
return -ENOMEM;
root_inode = hostfs_iget(sb, host_root_path);
root_inode = hostfs_iget(sb, fsi->host_root_path);
if (IS_ERR(root_inode))
return PTR_ERR(root_inode);
......@@ -944,7 +958,7 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
char *name;
iput(root_inode);
name = follow_link(host_root_path);
name = follow_link(fsi->host_root_path);
if (IS_ERR(name))
return PTR_ERR(name);
......@@ -961,11 +975,38 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
return 0;
}
static struct dentry *hostfs_read_sb(struct file_system_type *type,
int flags, const char *dev_name,
void *data)
static int hostfs_fc_get_tree(struct fs_context *fc)
{
return mount_nodev(type, flags, data, hostfs_fill_sb_common);
return get_tree_nodev(fc, hostfs_fill_super);
}
static void hostfs_fc_free(struct fs_context *fc)
{
struct hostfs_fs_info *fsi = fc->s_fs_info;
if (!fsi)
return;
kfree(fsi->host_root_path);
kfree(fsi);
}
static const struct fs_context_operations hostfs_context_ops = {
.get_tree = hostfs_fc_get_tree,
.free = hostfs_fc_free,
};
static int hostfs_init_fs_context(struct fs_context *fc)
{
struct hostfs_fs_info *fsi;
fsi = kzalloc(sizeof(*fsi), GFP_KERNEL);
if (!fsi)
return -ENOMEM;
fc->s_fs_info = fsi;
fc->ops = &hostfs_context_ops;
return 0;
}
static void hostfs_kill_sb(struct super_block *s)
......@@ -975,11 +1016,11 @@ static void hostfs_kill_sb(struct super_block *s)
}
static struct file_system_type hostfs_type = {
.owner = THIS_MODULE,
.name = "hostfs",
.mount = hostfs_read_sb,
.kill_sb = hostfs_kill_sb,
.fs_flags = 0,
.owner = THIS_MODULE,
.name = "hostfs",
.init_fs_context = hostfs_init_fs_context,
.kill_sb = hostfs_kill_sb,
.fs_flags = 0,
};
MODULE_ALIAS_FS("hostfs");
......
......@@ -73,13 +73,13 @@ enum hugetlb_param {
};
static const struct fs_parameter_spec hugetlb_fs_parameters[] = {
fsparam_u32 ("gid", Opt_gid),
fsparam_gid ("gid", Opt_gid),
fsparam_string("min_size", Opt_min_size),
fsparam_u32oct("mode", Opt_mode),
fsparam_string("nr_inodes", Opt_nr_inodes),
fsparam_string("pagesize", Opt_pagesize),
fsparam_string("size", Opt_size),
fsparam_u32 ("uid", Opt_uid),
fsparam_uid ("uid", Opt_uid),
{}
};
......@@ -1376,15 +1376,11 @@ static int hugetlbfs_parse_param(struct fs_context *fc, struct fs_parameter *par
switch (opt) {
case Opt_uid:
ctx->uid = make_kuid(current_user_ns(), result.uint_32);
if (!uid_valid(ctx->uid))
goto bad_val;
ctx->uid = result.uid;
return 0;
case Opt_gid:
ctx->gid = make_kgid(current_user_ns(), result.uint_32);
if (!gid_valid(ctx->gid))
goto bad_val;
ctx->gid = result.gid;
return 0;
case Opt_mode:
......
......@@ -326,8 +326,8 @@ static const struct fs_parameter_spec isofs_param_spec[] = {
fsparam_u32 ("session", Opt_session),
fsparam_u32 ("sbsector", Opt_sb),
fsparam_enum ("check", Opt_check, isofs_param_check),
fsparam_u32 ("uid", Opt_uid),
fsparam_u32 ("gid", Opt_gid),
fsparam_uid ("uid", Opt_uid),
fsparam_gid ("gid", Opt_gid),
/* Note: mode/dmode historically accepted %u not strictly %o */
fsparam_u32 ("mode", Opt_mode),
fsparam_u32 ("dmode", Opt_dmode),
......@@ -344,8 +344,6 @@ static int isofs_parse_param(struct fs_context *fc,
struct isofs_options *popt = fc->fs_private;
struct fs_parse_result result;
int opt;
kuid_t uid;
kgid_t gid;
unsigned int n;
/* There are no remountable options */
......@@ -409,17 +407,11 @@ static int isofs_parse_param(struct fs_context *fc,
case Opt_ignore:
break;
case Opt_uid:
uid = make_kuid(current_user_ns(), result.uint_32);
if (!uid_valid(uid))
return -EINVAL;
popt->uid = uid;
popt->uid = result.uid;
popt->uid_set = 1;
break;
case Opt_gid:
gid = make_kgid(current_user_ns(), result.uint_32);
if (!gid_valid(gid))
return -EINVAL;
popt->gid = gid;
popt->gid = result.gid;
popt->gid_set = 1;
break;
case Opt_mode:
......
......@@ -259,8 +259,8 @@ enum Opt {
// clang-format off
static const struct fs_parameter_spec ntfs_fs_parameters[] = {
fsparam_u32("uid", Opt_uid),
fsparam_u32("gid", Opt_gid),
fsparam_uid("uid", Opt_uid),
fsparam_gid("gid", Opt_gid),
fsparam_u32oct("umask", Opt_umask),
fsparam_u32oct("dmask", Opt_dmask),
fsparam_u32oct("fmask", Opt_fmask),
......@@ -319,14 +319,10 @@ static int ntfs_fs_parse_param(struct fs_context *fc,
switch (opt) {
case Opt_uid:
opts->fs_uid = make_kuid(current_user_ns(), result.uint_32);
if (!uid_valid(opts->fs_uid))
return invalf(fc, "ntfs3: Invalid value for uid.");
opts->fs_uid = result.uid;
break;
case Opt_gid:
opts->fs_gid = make_kgid(current_user_ns(), result.uint_32);
if (!gid_valid(opts->fs_gid))
return invalf(fc, "ntfs3: Invalid value for gid.");
opts->fs_gid = result.gid;
break;
case Opt_umask:
if (result.uint_32 & ~07777)
......
......@@ -128,12 +128,14 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
fsparam_flag("compress", Opt_compress),
fsparam_flag("witness", Opt_witness),
/* Mount options which take uid or gid */
fsparam_uid("backupuid", Opt_backupuid),
fsparam_gid("backupgid", Opt_backupgid),
fsparam_uid("uid", Opt_uid),
fsparam_uid("cruid", Opt_cruid),
fsparam_gid("gid", Opt_gid),
/* Mount options which take numeric value */
fsparam_u32("backupuid", Opt_backupuid),
fsparam_u32("backupgid", Opt_backupgid),
fsparam_u32("uid", Opt_uid),
fsparam_u32("cruid", Opt_cruid),
fsparam_u32("gid", Opt_gid),
fsparam_u32("file_mode", Opt_file_mode),
fsparam_u32("dirmode", Opt_dirmode),
fsparam_u32("dir_mode", Opt_dirmode),
......@@ -951,8 +953,6 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
int i, opt;
bool is_smb3 = !strcmp(fc->fs_type->name, "smb3");
bool skip_parsing = false;
kuid_t uid;
kgid_t gid;
cifs_dbg(FYI, "CIFS: parsing cifs mount option '%s'\n", param->key);
......@@ -1083,38 +1083,23 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
}
break;
case Opt_uid:
uid = make_kuid(current_user_ns(), result.uint_32);
if (!uid_valid(uid))
goto cifs_parse_mount_err;
ctx->linux_uid = uid;
ctx->linux_uid = result.uid;
ctx->uid_specified = true;
break;
case Opt_cruid:
uid = make_kuid(current_user_ns(), result.uint_32);
if (!uid_valid(uid))
goto cifs_parse_mount_err;
ctx->cred_uid = uid;
ctx->cred_uid = result.uid;
ctx->cruid_specified = true;
break;
case Opt_backupuid:
uid = make_kuid(current_user_ns(), result.uint_32);
if (!uid_valid(uid))
goto cifs_parse_mount_err;
ctx->backupuid = uid;
ctx->backupuid = result.uid;
ctx->backupuid_specified = true;
break;
case Opt_backupgid:
gid = make_kgid(current_user_ns(), result.uint_32);
if (!gid_valid(gid))
goto cifs_parse_mount_err;
ctx->backupgid = gid;
ctx->backupgid = result.gid;
ctx->backupgid_specified = true;
break;
case Opt_gid:
gid = make_kgid(current_user_ns(), result.uint_32);
if (!gid_valid(gid))
goto cifs_parse_mount_err;
ctx->linux_gid = gid;
ctx->linux_gid = result.gid;
ctx->gid_specified = true;
break;
case Opt_port:
......
......@@ -296,9 +296,9 @@ enum {
};
static const struct fs_parameter_spec tracefs_param_specs[] = {
fsparam_u32 ("gid", Opt_gid),
fsparam_gid ("gid", Opt_gid),
fsparam_u32oct ("mode", Opt_mode),
fsparam_u32 ("uid", Opt_uid),
fsparam_uid ("uid", Opt_uid),
{}
};
......@@ -306,8 +306,6 @@ static int tracefs_parse_param(struct fs_context *fc, struct fs_parameter *param
{
struct tracefs_fs_info *opts = fc->s_fs_info;
struct fs_parse_result result;
kuid_t uid;
kgid_t gid;
int opt;
opt = fs_parse(fc, tracefs_param_specs, param, &result);
......@@ -316,16 +314,10 @@ static int tracefs_parse_param(struct fs_context *fc, struct fs_parameter *param
switch (opt) {
case Opt_uid:
uid = make_kuid(current_user_ns(), result.uint_32);
if (!uid_valid(uid))
return invalf(fc, "Unknown uid");
opts->uid = uid;
opts->uid = result.uid;
break;
case Opt_gid:
gid = make_kgid(current_user_ns(), result.uint_32);
if (!gid_valid(gid))
return invalf(fc, "Unknown gid");
opts->gid = gid;
opts->gid = result.gid;
break;
case Opt_mode:
opts->mode = result.uint_32 & S_IALLUGO;
......
......@@ -41,8 +41,8 @@ enum { opt_nls, opt_uid, opt_gid, opt_ttl, opt_dmode, opt_fmode,
static const struct fs_parameter_spec vboxsf_fs_parameters[] = {
fsparam_string ("nls", opt_nls),
fsparam_u32 ("uid", opt_uid),
fsparam_u32 ("gid", opt_gid),
fsparam_uid ("uid", opt_uid),
fsparam_gid ("gid", opt_gid),
fsparam_u32 ("ttl", opt_ttl),
fsparam_u32oct ("dmode", opt_dmode),
fsparam_u32oct ("fmode", opt_fmode),
......@@ -55,8 +55,6 @@ static int vboxsf_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
struct vboxsf_fs_context *ctx = fc->fs_private;
struct fs_parse_result result;
kuid_t uid;
kgid_t gid;
int opt;
opt = fs_parse(fc, vboxsf_fs_parameters, param, &result);
......@@ -73,16 +71,10 @@ static int vboxsf_parse_param(struct fs_context *fc, struct fs_parameter *param)
param->string = NULL;
break;
case opt_uid:
uid = make_kuid(current_user_ns(), result.uint_32);
if (!uid_valid(uid))
return -EINVAL;
ctx->o.uid = uid;
ctx->o.uid = result.uid;
break;
case opt_gid:
gid = make_kgid(current_user_ns(), result.uint_32);
if (!gid_valid(gid))
return -EINVAL;
ctx->o.gid = gid;
ctx->o.gid = result.gid;
break;
case opt_ttl:
ctx->o.ttl = msecs_to_jiffies(result.uint_32);
......
......@@ -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) \
......
......@@ -3917,14 +3917,14 @@ static const struct constant_table shmem_param_enums_huge[] = {
};
const struct fs_parameter_spec shmem_fs_parameters[] = {
fsparam_u32 ("gid", Opt_gid),
fsparam_gid ("gid", Opt_gid),
fsparam_enum ("huge", Opt_huge, shmem_param_enums_huge),
fsparam_u32oct("mode", Opt_mode),
fsparam_string("mpol", Opt_mpol),
fsparam_string("nr_blocks", Opt_nr_blocks),
fsparam_string("nr_inodes", Opt_nr_inodes),
fsparam_string("size", Opt_size),
fsparam_u32 ("uid", Opt_uid),
fsparam_uid ("uid", Opt_uid),
fsparam_flag ("inode32", Opt_inode32),
fsparam_flag ("inode64", Opt_inode64),
fsparam_flag ("noswap", Opt_noswap),
......@@ -3984,9 +3984,7 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param)
ctx->mode = result.uint_32 & 07777;
break;
case Opt_uid:
kuid = make_kuid(current_user_ns(), result.uint_32);
if (!uid_valid(kuid))
goto bad_value;
kuid = result.uid;
/*
* The requested uid must be representable in the
......@@ -3998,9 +3996,7 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param)
ctx->uid = kuid;
break;
case Opt_gid:
kgid = make_kgid(current_user_ns(), result.uint_32);
if (!gid_valid(kgid))
goto bad_value;
kgid = result.gid;
/*
* The requested gid must be representable in the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment