Merge branch 'vfs.idmap' into vfs.all

Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Christian Brauner 2024-08-28 19:08:22 +02:00
commit 4d07d6a6f1
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2
9 changed files with 148 additions and 63 deletions

View File

@ -12,7 +12,6 @@
#include <linux/posix_acl_xattr.h>
static struct posix_acl *__fuse_get_acl(struct fuse_conn *fc,
struct mnt_idmap *idmap,
struct inode *inode, int type, bool rcu)
{
int size;
@ -74,7 +73,7 @@ struct posix_acl *fuse_get_acl(struct mnt_idmap *idmap,
if (fuse_no_acl(fc, inode))
return ERR_PTR(-EOPNOTSUPP);
return __fuse_get_acl(fc, idmap, inode, type, false);
return __fuse_get_acl(fc, inode, type, false);
}
struct posix_acl *fuse_get_inode_acl(struct inode *inode, int type, bool rcu)
@ -90,8 +89,7 @@ struct posix_acl *fuse_get_inode_acl(struct inode *inode, int type, bool rcu)
*/
if (!fc->posix_acl)
return NULL;
return __fuse_get_acl(fc, &nop_mnt_idmap, inode, type, rcu);
return __fuse_get_acl(fc, inode, type, rcu);
}
int fuse_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
@ -146,8 +144,8 @@ int fuse_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
* be stripped.
*/
if (fc->posix_acl &&
!in_group_or_capable(&nop_mnt_idmap, inode,
i_gid_into_vfsgid(&nop_mnt_idmap, inode)))
!in_group_or_capable(idmap, inode,
i_gid_into_vfsgid(idmap, inode)))
extra_flags |= FUSE_SETXATTR_ACL_KILL_SGID;
ret = fuse_setxattr(inode, name, value, size, 0, extra_flags);

View File

@ -572,7 +572,33 @@ static int get_create_supp_group(struct inode *dir, struct fuse_in_arg *ext)
return 0;
}
static int get_create_ext(struct fuse_args *args,
static int get_owner_uid_gid(struct mnt_idmap *idmap, struct fuse_conn *fc, struct fuse_in_arg *ext)
{
struct fuse_ext_header *xh;
struct fuse_owner_uid_gid *owner_creds;
u32 owner_creds_len = fuse_ext_size(sizeof(*owner_creds));
kuid_t owner_fsuid;
kgid_t owner_fsgid;
xh = extend_arg(ext, owner_creds_len);
if (!xh)
return -ENOMEM;
xh->size = owner_creds_len;
xh->type = FUSE_EXT_OWNER_UID_GID;
owner_creds = (struct fuse_owner_uid_gid *) &xh[1];
owner_fsuid = mapped_fsuid(idmap, fc->user_ns);
owner_fsgid = mapped_fsgid(idmap, fc->user_ns);
owner_creds->uid = from_kuid(fc->user_ns, owner_fsuid);
owner_creds->gid = from_kgid(fc->user_ns, owner_fsgid);
return 0;
}
static int get_create_ext(struct mnt_idmap *idmap,
struct fuse_args *args,
struct inode *dir, struct dentry *dentry,
umode_t mode)
{
@ -584,6 +610,8 @@ static int get_create_ext(struct fuse_args *args,
err = get_security_context(dentry, mode, &ext);
if (!err && fc->create_supp_group)
err = get_create_supp_group(dir, &ext);
if (!err && fc->owner_uid_gid_ext)
err = get_owner_uid_gid(idmap, fc, &ext);
if (!err && ext.size) {
WARN_ON(args->in_numargs >= ARRAY_SIZE(args->in_args));
@ -609,9 +637,9 @@ static void free_ext_value(struct fuse_args *args)
* If the filesystem doesn't support this, then fall back to separate
* 'mknod' + 'open' requests.
*/
static int fuse_create_open(struct inode *dir, struct dentry *entry,
struct file *file, unsigned int flags,
umode_t mode, u32 opcode)
static int fuse_create_open(struct mnt_idmap *idmap, struct inode *dir,
struct dentry *entry, struct file *file,
unsigned int flags, umode_t mode, u32 opcode)
{
int err;
struct inode *inode;
@ -668,7 +696,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
args.out_args[1].size = sizeof(*outopenp);
args.out_args[1].value = outopenp;
err = get_create_ext(&args, dir, entry, mode);
err = get_create_ext(idmap, &args, dir, entry, mode);
if (err)
goto out_put_forget_req;
@ -729,6 +757,7 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
umode_t mode)
{
int err;
struct mnt_idmap *idmap = file_mnt_idmap(file);
struct fuse_conn *fc = get_fuse_conn(dir);
struct dentry *res = NULL;
@ -753,7 +782,7 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
if (fc->no_create)
goto mknod;
err = fuse_create_open(dir, entry, file, flags, mode, FUSE_CREATE);
err = fuse_create_open(idmap, dir, entry, file, flags, mode, FUSE_CREATE);
if (err == -ENOSYS) {
fc->no_create = 1;
goto mknod;
@ -764,7 +793,7 @@ out_dput:
return err;
mknod:
err = fuse_mknod(&nop_mnt_idmap, dir, entry, mode, 0);
err = fuse_mknod(idmap, dir, entry, mode, 0);
if (err)
goto out_dput;
no_open:
@ -774,9 +803,9 @@ no_open:
/*
* Code shared between mknod, mkdir, symlink and link
*/
static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args,
struct inode *dir, struct dentry *entry,
umode_t mode)
static int create_new_entry(struct mnt_idmap *idmap, struct fuse_mount *fm,
struct fuse_args *args, struct inode *dir,
struct dentry *entry, umode_t mode)
{
struct fuse_entry_out outarg;
struct inode *inode;
@ -798,7 +827,7 @@ static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args,
args->out_args[0].value = &outarg;
if (args->opcode != FUSE_LINK) {
err = get_create_ext(args, dir, entry, mode);
err = get_create_ext(idmap, args, dir, entry, mode);
if (err)
goto out_put_forget_req;
}
@ -864,13 +893,13 @@ static int fuse_mknod(struct mnt_idmap *idmap, struct inode *dir,
args.in_args[0].value = &inarg;
args.in_args[1].size = entry->d_name.len + 1;
args.in_args[1].value = entry->d_name.name;
return create_new_entry(fm, &args, dir, entry, mode);
return create_new_entry(idmap, fm, &args, dir, entry, mode);
}
static int fuse_create(struct mnt_idmap *idmap, struct inode *dir,
struct dentry *entry, umode_t mode, bool excl)
{
return fuse_mknod(&nop_mnt_idmap, dir, entry, mode, 0);
return fuse_mknod(idmap, dir, entry, mode, 0);
}
static int fuse_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
@ -882,7 +911,7 @@ static int fuse_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
if (fc->no_tmpfile)
return -EOPNOTSUPP;
err = fuse_create_open(dir, file->f_path.dentry, file, file->f_flags, mode, FUSE_TMPFILE);
err = fuse_create_open(idmap, dir, file->f_path.dentry, file, file->f_flags, mode, FUSE_TMPFILE);
if (err == -ENOSYS) {
fc->no_tmpfile = 1;
err = -EOPNOTSUPP;
@ -909,7 +938,7 @@ static int fuse_mkdir(struct mnt_idmap *idmap, struct inode *dir,
args.in_args[0].value = &inarg;
args.in_args[1].size = entry->d_name.len + 1;
args.in_args[1].value = entry->d_name.name;
return create_new_entry(fm, &args, dir, entry, S_IFDIR);
return create_new_entry(idmap, fm, &args, dir, entry, S_IFDIR);
}
static int fuse_symlink(struct mnt_idmap *idmap, struct inode *dir,
@ -925,7 +954,7 @@ static int fuse_symlink(struct mnt_idmap *idmap, struct inode *dir,
args.in_args[0].value = entry->d_name.name;
args.in_args[1].size = len;
args.in_args[1].value = link;
return create_new_entry(fm, &args, dir, entry, S_IFLNK);
return create_new_entry(idmap, fm, &args, dir, entry, S_IFLNK);
}
void fuse_flush_time_update(struct inode *inode)
@ -1082,6 +1111,9 @@ static int fuse_rename2(struct mnt_idmap *idmap, struct inode *olddir,
if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
return -EINVAL;
if ((flags & RENAME_WHITEOUT) && (idmap != &nop_mnt_idmap))
return -EINVAL;
if (flags) {
if (fc->no_rename2 || fc->minor < 23)
return -EINVAL;
@ -1119,7 +1151,7 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
args.in_args[0].value = &inarg;
args.in_args[1].size = newent->d_name.len + 1;
args.in_args[1].value = newent->d_name.name;
err = create_new_entry(fm, &args, newdir, newent, inode->i_mode);
err = create_new_entry(&nop_mnt_idmap, fm, &args, newdir, newent, inode->i_mode);
if (!err)
fuse_update_ctime_in_cache(inode);
else if (err == -EINTR)
@ -1128,18 +1160,22 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
return err;
}
static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
struct kstat *stat)
static void fuse_fillattr(struct mnt_idmap *idmap, struct inode *inode,
struct fuse_attr *attr, struct kstat *stat)
{
unsigned int blkbits;
struct fuse_conn *fc = get_fuse_conn(inode);
vfsuid_t vfsuid = make_vfsuid(idmap, fc->user_ns,
make_kuid(fc->user_ns, attr->uid));
vfsgid_t vfsgid = make_vfsgid(idmap, fc->user_ns,
make_kgid(fc->user_ns, attr->gid));
stat->dev = inode->i_sb->s_dev;
stat->ino = attr->ino;
stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
stat->nlink = attr->nlink;
stat->uid = make_kuid(fc->user_ns, attr->uid);
stat->gid = make_kgid(fc->user_ns, attr->gid);
stat->uid = vfsuid_into_kuid(vfsuid);
stat->gid = vfsgid_into_kgid(vfsgid);
stat->rdev = inode->i_rdev;
stat->atime.tv_sec = attr->atime;
stat->atime.tv_nsec = attr->atimensec;
@ -1178,8 +1214,8 @@ static void fuse_statx_to_attr(struct fuse_statx *sx, struct fuse_attr *attr)
attr->blksize = sx->blksize;
}
static int fuse_do_statx(struct inode *inode, struct file *file,
struct kstat *stat)
static int fuse_do_statx(struct mnt_idmap *idmap, struct inode *inode,
struct file *file, struct kstat *stat)
{
int err;
struct fuse_attr attr;
@ -1232,15 +1268,15 @@ static int fuse_do_statx(struct inode *inode, struct file *file,
stat->result_mask = sx->mask & (STATX_BASIC_STATS | STATX_BTIME);
stat->btime.tv_sec = sx->btime.tv_sec;
stat->btime.tv_nsec = min_t(u32, sx->btime.tv_nsec, NSEC_PER_SEC - 1);
fuse_fillattr(inode, &attr, stat);
fuse_fillattr(idmap, inode, &attr, stat);
stat->result_mask |= STATX_TYPE;
}
return 0;
}
static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
struct file *file)
static int fuse_do_getattr(struct mnt_idmap *idmap, struct inode *inode,
struct kstat *stat, struct file *file)
{
int err;
struct fuse_getattr_in inarg;
@ -1279,15 +1315,15 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
ATTR_TIMEOUT(&outarg),
attr_version);
if (stat)
fuse_fillattr(inode, &outarg.attr, stat);
fuse_fillattr(idmap, inode, &outarg.attr, stat);
}
}
return err;
}
static int fuse_update_get_attr(struct inode *inode, struct file *file,
struct kstat *stat, u32 request_mask,
unsigned int flags)
static int fuse_update_get_attr(struct mnt_idmap *idmap, struct inode *inode,
struct file *file, struct kstat *stat,
u32 request_mask, unsigned int flags)
{
struct fuse_inode *fi = get_fuse_inode(inode);
struct fuse_conn *fc = get_fuse_conn(inode);
@ -1318,17 +1354,17 @@ retry:
forget_all_cached_acls(inode);
/* Try statx if BTIME is requested */
if (!fc->no_statx && (request_mask & ~STATX_BASIC_STATS)) {
err = fuse_do_statx(inode, file, stat);
err = fuse_do_statx(idmap, inode, file, stat);
if (err == -ENOSYS) {
fc->no_statx = 1;
err = 0;
goto retry;
}
} else {
err = fuse_do_getattr(inode, stat, file);
err = fuse_do_getattr(idmap, inode, stat, file);
}
} else if (stat) {
generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
generic_fillattr(idmap, request_mask, inode, stat);
stat->mode = fi->orig_i_mode;
stat->ino = fi->orig_ino;
if (test_bit(FUSE_I_BTIME, &fi->state)) {
@ -1342,7 +1378,7 @@ retry:
int fuse_update_attributes(struct inode *inode, struct file *file, u32 mask)
{
return fuse_update_get_attr(inode, file, NULL, mask, 0);
return fuse_update_get_attr(&nop_mnt_idmap, inode, file, NULL, mask, 0);
}
int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
@ -1486,7 +1522,7 @@ static int fuse_perm_getattr(struct inode *inode, int mask)
return -ECHILD;
forget_all_cached_acls(inode);
return fuse_do_getattr(inode, NULL, NULL);
return fuse_do_getattr(&nop_mnt_idmap, inode, NULL, NULL);
}
/*
@ -1534,7 +1570,7 @@ static int fuse_permission(struct mnt_idmap *idmap,
}
if (fc->default_permissions) {
err = generic_permission(&nop_mnt_idmap, inode, mask);
err = generic_permission(idmap, inode, mask);
/* If permission is denied, try to refresh file
attributes. This is also needed, because the root
@ -1542,7 +1578,7 @@ static int fuse_permission(struct mnt_idmap *idmap,
if (err == -EACCES && !refreshed) {
err = fuse_perm_getattr(inode, mask);
if (!err)
err = generic_permission(&nop_mnt_idmap,
err = generic_permission(idmap,
inode, mask);
}
@ -1738,17 +1774,27 @@ static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
return true;
}
static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
struct fuse_setattr_in *arg, bool trust_local_cmtime)
static void iattr_to_fattr(struct mnt_idmap *idmap, struct fuse_conn *fc,
struct iattr *iattr, struct fuse_setattr_in *arg,
bool trust_local_cmtime)
{
unsigned ivalid = iattr->ia_valid;
if (ivalid & ATTR_MODE)
arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
if (ivalid & ATTR_UID)
arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid);
if (ivalid & ATTR_GID)
arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid);
if (ivalid & ATTR_UID) {
kuid_t fsuid = from_vfsuid(idmap, fc->user_ns, iattr->ia_vfsuid);
arg->valid |= FATTR_UID;
arg->uid = from_kuid(fc->user_ns, fsuid);
}
if (ivalid & ATTR_GID) {
kgid_t fsgid = from_vfsgid(idmap, fc->user_ns, iattr->ia_vfsgid);
arg->valid |= FATTR_GID;
arg->gid = from_kgid(fc->user_ns, fsgid);
}
if (ivalid & ATTR_SIZE)
arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
if (ivalid & ATTR_ATIME) {
@ -1868,8 +1914,8 @@ int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
* vmtruncate() doesn't allow for this case, so do the rlimit checking
* and the actual truncation by hand.
*/
int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
struct file *file)
int fuse_do_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
struct iattr *attr, struct file *file)
{
struct inode *inode = d_inode(dentry);
struct fuse_mount *fm = get_fuse_mount(inode);
@ -1889,7 +1935,7 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
if (!fc->default_permissions)
attr->ia_valid |= ATTR_FORCE;
err = setattr_prepare(&nop_mnt_idmap, dentry, attr);
err = setattr_prepare(idmap, dentry, attr);
if (err)
return err;
@ -1948,7 +1994,7 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
memset(&inarg, 0, sizeof(inarg));
memset(&outarg, 0, sizeof(outarg));
iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime);
iattr_to_fattr(idmap, fc, attr, &inarg, trust_local_cmtime);
if (file) {
struct fuse_file *ff = file->private_data;
inarg.valid |= FATTR_FH;
@ -2065,7 +2111,7 @@ static int fuse_setattr(struct mnt_idmap *idmap, struct dentry *entry,
* ia_mode calculation may have used stale i_mode.
* Refresh and recalculate.
*/
ret = fuse_do_getattr(inode, NULL, file);
ret = fuse_do_getattr(idmap, inode, NULL, file);
if (ret)
return ret;
@ -2083,7 +2129,7 @@ static int fuse_setattr(struct mnt_idmap *idmap, struct dentry *entry,
if (!attr->ia_valid)
return 0;
ret = fuse_do_setattr(entry, attr, file);
ret = fuse_do_setattr(idmap, entry, attr, file);
if (!ret) {
/*
* If filesystem supports acls it may have updated acl xattrs in
@ -2122,7 +2168,7 @@ static int fuse_getattr(struct mnt_idmap *idmap,
return -EACCES;
}
return fuse_update_get_attr(inode, NULL, stat, request_mask, flags);
return fuse_update_get_attr(idmap, inode, NULL, stat, request_mask, flags);
}
static const struct inode_operations fuse_dir_inode_operations = {

View File

@ -2967,7 +2967,7 @@ static void fuse_do_truncate(struct file *file)
attr.ia_file = file;
attr.ia_valid |= ATTR_FILE;
fuse_do_setattr(file_dentry(file), &attr, file);
fuse_do_setattr(file_mnt_idmap(file), file_dentry(file), &attr, file);
}
static inline loff_t fuse_round_up(struct fuse_conn *fc, loff_t off)

View File

@ -845,6 +845,9 @@ struct fuse_conn {
/* Add supplementary group info when creating a new inode */
unsigned int create_supp_group:1;
/* Add owner_{u,g}id info when creating a new inode */
unsigned int owner_uid_gid_ext:1;
/* Does the filesystem support per inode DAX? */
unsigned int inode_dax:1;
@ -1330,8 +1333,8 @@ bool fuse_write_update_attr(struct inode *inode, loff_t pos, ssize_t written);
int fuse_flush_times(struct inode *inode, struct fuse_file *ff);
int fuse_write_inode(struct inode *inode, struct writeback_control *wbc);
int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
struct file *file);
int fuse_do_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
struct iattr *attr, struct file *file);
void fuse_set_initialized(struct fuse_conn *fc);

View File

@ -1343,6 +1343,14 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
}
if (flags & FUSE_NO_EXPORT_SUPPORT)
fm->sb->s_export_op = &fuse_export_fid_operations;
if (flags & FUSE_OWNER_UID_GID_EXT)
fc->owner_uid_gid_ext = 1;
if (flags & FUSE_ALLOW_IDMAP) {
if (fc->owner_uid_gid_ext && fc->default_permissions)
fm->sb->s_iflags &= ~SB_I_NOIDMAP;
else
ok = false;
}
} else {
ra_pages = fc->max_read / PAGE_SIZE;
fc->no_lock = 1;
@ -1390,7 +1398,8 @@ void fuse_send_init(struct fuse_mount *fm)
FUSE_HANDLE_KILLPRIV_V2 | FUSE_SETXATTR_EXT | FUSE_INIT_EXT |
FUSE_SECURITY_CTX | FUSE_CREATE_SUPP_GROUP |
FUSE_HAS_EXPIRE_ONLY | FUSE_DIRECT_IO_ALLOW_MMAP |
FUSE_NO_EXPORT_SUPPORT | FUSE_HAS_RESEND;
FUSE_NO_EXPORT_SUPPORT | FUSE_HAS_RESEND | FUSE_OWNER_UID_GID_EXT |
FUSE_ALLOW_IDMAP;
#ifdef CONFIG_FUSE_DAX
if (fm->fc->dax)
flags |= FUSE_MAP_ALIGNMENT;
@ -1567,6 +1576,7 @@ static void fuse_sb_defaults(struct super_block *sb)
sb->s_time_gran = 1;
sb->s_export_op = &fuse_export_operations;
sb->s_iflags |= SB_I_IMA_UNVERIFIABLE_SIGNATURE;
sb->s_iflags |= SB_I_NOIDMAP;
if (sb->s_user_ns != &init_user_ns)
sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER;
sb->s_flags &= ~(SB_NOSEC | SB_I_VERSION);
@ -1979,7 +1989,7 @@ static void fuse_kill_sb_anon(struct super_block *sb)
static struct file_system_type fuse_fs_type = {
.owner = THIS_MODULE,
.name = "fuse",
.fs_flags = FS_HAS_SUBTYPE | FS_USERNS_MOUNT,
.fs_flags = FS_HAS_SUBTYPE | FS_USERNS_MOUNT | FS_ALLOW_IDMAP,
.init_fs_context = fuse_init_fs_context,
.parameters = fuse_fs_parameters,
.kill_sb = fuse_kill_sb_anon,
@ -2000,7 +2010,7 @@ static struct file_system_type fuseblk_fs_type = {
.init_fs_context = fuse_init_fs_context,
.parameters = fuse_fs_parameters,
.kill_sb = fuse_kill_sb_blk,
.fs_flags = FS_REQUIRES_DEV | FS_HAS_SUBTYPE,
.fs_flags = FS_REQUIRES_DEV | FS_HAS_SUBTYPE | FS_ALLOW_IDMAP,
};
MODULE_ALIAS_FS("fuseblk");

View File

@ -1628,6 +1628,7 @@ static struct file_system_type virtio_fs_type = {
.name = "virtiofs",
.init_fs_context = virtio_fs_init_fs_context,
.kill_sb = virtio_kill_sb,
.fs_flags = FS_ALLOW_IDMAP,
};
static int virtio_fs_uevent(const struct kobject *kobj, struct kobj_uevent_env *env)

View File

@ -4471,6 +4471,10 @@ static int can_idmap_mount(const struct mount_kattr *kattr, struct mount *mnt)
if (!(m->mnt_sb->s_type->fs_flags & FS_ALLOW_IDMAP))
return -EINVAL;
/* The filesystem has turned off idmapped mounts. */
if (m->mnt_sb->s_iflags & SB_I_NOIDMAP)
return -EINVAL;
/* We're not controlling the superblock. */
if (!ns_capable(fs_userns, CAP_SYS_ADMIN))
return -EPERM;

View File

@ -1204,6 +1204,7 @@ extern int send_sigurg(struct fown_struct *fown);
#define SB_I_TS_EXPIRY_WARNED 0x00000400 /* warned about timestamp range expiry */
#define SB_I_RETIRED 0x00000800 /* superblock shouldn't be reused */
#define SB_I_NOUMASK 0x00001000 /* VFS does not apply umask */
#define SB_I_NOIDMAP 0x00002000 /* No idmapped mounts on this superblock */
/* Possible states of 'frozen' field */
enum {

View File

@ -217,6 +217,11 @@
* - add backing_id to fuse_open_out, add FOPEN_PASSTHROUGH open flag
* - add FUSE_NO_EXPORT_SUPPORT init flag
* - add FUSE_NOTIFY_RESEND, add FUSE_HAS_RESEND init flag
*
* 7.41
* - add FUSE_EXT_OWNER_UID_GID
* - add FUSE_OWNER_UID_GID_EXT
* - add FUSE_ALLOW_IDMAP
*/
#ifndef _LINUX_FUSE_H
@ -252,7 +257,7 @@
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
#define FUSE_KERNEL_MINOR_VERSION 40
#define FUSE_KERNEL_MINOR_VERSION 41
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
@ -421,6 +426,9 @@ struct fuse_file_lock {
* FUSE_NO_EXPORT_SUPPORT: explicitly disable export support
* FUSE_HAS_RESEND: kernel supports resending pending requests, and the high bit
* of the request ID indicates resend requests
* FUSE_OWNER_UID_GID_EXT: add inode owner UID/GID info to create, mkdir,
* symlink and mknod
* FUSE_ALLOW_IDMAP: allow creation of idmapped mounts
*/
#define FUSE_ASYNC_READ (1 << 0)
#define FUSE_POSIX_LOCKS (1 << 1)
@ -466,6 +474,8 @@ struct fuse_file_lock {
/* Obsolete alias for FUSE_DIRECT_IO_ALLOW_MMAP */
#define FUSE_DIRECT_IO_RELAX FUSE_DIRECT_IO_ALLOW_MMAP
#define FUSE_OWNER_UID_GID_EXT (1ULL << 40)
#define FUSE_ALLOW_IDMAP (1ULL << 41)
/**
* CUSE INIT request/reply flags
@ -575,11 +585,13 @@ struct fuse_file_lock {
* extension type
* FUSE_MAX_NR_SECCTX: maximum value of &fuse_secctx_header.nr_secctx
* FUSE_EXT_GROUPS: &fuse_supp_groups extension
* FUSE_EXT_OWNER_UID_GID: &fuse_owner_uid_gid extension
*/
enum fuse_ext_type {
/* Types 0..31 are reserved for fuse_secctx_header */
FUSE_MAX_NR_SECCTX = 31,
FUSE_EXT_GROUPS = 32,
FUSE_EXT_OWNER_UID_GID = 33,
};
enum fuse_opcode {
@ -1186,4 +1198,14 @@ struct fuse_supp_groups {
uint32_t groups[];
};
/**
* struct fuse_owner_uid_gid - Inode owner UID/GID extension
* @uid: inode owner UID
* @gid: inode owner GID
*/
struct fuse_owner_uid_gid {
uint32_t uid;
uint32_t gid;
};
#endif /* _LINUX_FUSE_H */