diff --git a/kmod/src/Makefile.kernelcompat b/kmod/src/Makefile.kernelcompat index 68812985..1a9c0da1 100644 --- a/kmod/src/Makefile.kernelcompat +++ b/kmod/src/Makefile.kernelcompat @@ -283,6 +283,30 @@ ifneq (,$(shell grep 'extern void .__vmalloc.unsigned long size, gfp_t gfp_mask, ccflags-y += -DKC_VMALLOC_PGPROT_T endif +# v6.2-rc1-18-g01beba7957a2 +# +# fs: port inode_owner_or_capable() to mnt_idmap +ifneq (,$(shell grep 'bool inode_owner_or_capable.struct user_namespace .mnt_userns' include/linux/fs.h)) +ccflags-y += -DKC_INODE_OWNER_OR_CAPABLE_USERNS +endif + +# +# v5.11-rc4-5-g47291baa8ddf +# +# namei: make permission helpers idmapped mount aware +ifneq (,$(shell grep 'int inode_permission.struct user_namespace' include/linux/fs.h)) +ccflags-y += -DKC_INODE_PERMISSION_USERNS +endif + +# +# v5.11-rc4-24-g549c7297717c +# +# fs: make helpers idmap mount aware +# Enlarges the VFS API methods to include user namespace argument. +ifneq (,$(shell grep 'int ..mknod. .struct user_namespace' include/linux/fs.h)) +ccflags-y += -DKC_VFS_METHOD_USER_NAMESPACE_ARG +endif + # # v5.17-rc2-21-g07888c665b40 # diff --git a/kmod/src/acl.c b/kmod/src/acl.c index 86d398ab..8e371fb2 100644 --- a/kmod/src/acl.c +++ b/kmod/src/acl.c @@ -265,7 +265,7 @@ int scoutfs_acl_set_xattr(struct dentry *dentry, const char *name, const void *v struct posix_acl *acl = NULL; int ret; - if (!inode_owner_or_capable(dentry->d_inode)) + if (!inode_owner_or_capable(KC_VFS_INIT_NS dentry->d_inode)) return -EPERM; if (!IS_POSIXACL(dentry->d_inode)) diff --git a/kmod/src/data.c b/kmod/src/data.c index 64859706..49ab801d 100644 --- a/kmod/src/data.c +++ b/kmod/src/data.c @@ -1305,8 +1305,8 @@ int scoutfs_data_move_blocks(struct inode *from, u64 from_off, goto out; } - ret = inode_permission(from, MAY_WRITE) ?: - inode_permission(to, MAY_WRITE); + ret = inode_permission(KC_VFS_INIT_NS from, MAY_WRITE) ?: + inode_permission(KC_VFS_INIT_NS to, MAY_WRITE); if (ret < 0) goto out; diff --git a/kmod/src/dir.c b/kmod/src/dir.c index ca23d3a6..6634cbf4 100644 --- a/kmod/src/dir.c +++ b/kmod/src/dir.c @@ -703,8 +703,9 @@ out_unlock: return inode; } -static int scoutfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, - dev_t rdev) +static int scoutfs_mknod(KC_VFS_NS_DEF + struct inode *dir, + struct dentry *dentry, umode_t mode, dev_t rdev) { struct super_block *sb = dir->i_sb; struct inode *inode = NULL; @@ -773,15 +774,20 @@ out: } /* XXX hmm, do something with excl? */ -static int scoutfs_create(struct inode *dir, struct dentry *dentry, - umode_t mode, bool excl) +static int scoutfs_create(KC_VFS_NS_DEF + struct inode *dir, + struct dentry *dentry, umode_t mode, bool excl) { - return scoutfs_mknod(dir, dentry, mode | S_IFREG, 0); + return scoutfs_mknod(KC_VFS_NS + dir, dentry, mode | S_IFREG, 0); } -static int scoutfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +static int scoutfs_mkdir(KC_VFS_NS_DEF + struct inode *dir, + struct dentry *dentry, umode_t mode) { - return scoutfs_mknod(dir, dentry, mode | S_IFDIR, 0); + return scoutfs_mknod(KC_VFS_NS + dir, dentry, mode | S_IFDIR, 0); } static int scoutfs_link(struct dentry *old_dentry, @@ -1176,7 +1182,8 @@ static const char *scoutfs_get_link(struct dentry *dentry, struct inode *inode, * Symlink target paths can be annoyingly large. We store relatively * rare large paths in multiple items. */ -static int scoutfs_symlink(struct inode *dir, struct dentry *dentry, +static int scoutfs_symlink(KC_VFS_NS_DEF + struct inode *dir, struct dentry *dentry, const char *symname) { struct super_block *sb = dir->i_sb; @@ -1563,7 +1570,8 @@ static int verify_ancestors(struct super_block *sb, u64 p1, u64 p2, * from using parent/child locking orders as two groups can have both * parent and child relationships to each other. */ -static int scoutfs_rename_common(struct inode *old_dir, +static int scoutfs_rename_common(KC_VFS_NS_DEF + struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags) { @@ -1840,18 +1848,21 @@ static int scoutfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { - return scoutfs_rename_common(old_dir, old_dentry, new_dir, new_dentry, 0); + return scoutfs_rename_common(KC_VFS_INIT_NS + old_dir, old_dentry, new_dir, new_dentry, 0); } #endif -static int scoutfs_rename2(struct inode *old_dir, +static int scoutfs_rename2(KC_VFS_NS_DEF + struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags) { if (flags & ~RENAME_NOREPLACE) return -EINVAL; - return scoutfs_rename_common(old_dir, old_dentry, new_dir, new_dentry, flags); + return scoutfs_rename_common(KC_VFS_NS + old_dir, old_dentry, new_dir, new_dentry, flags); } #ifdef KC_FMODE_KABI_ITERATE @@ -1863,7 +1874,8 @@ static int scoutfs_dir_open(struct inode *inode, struct file *file) } #endif -static int scoutfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) +static int scoutfs_tmpfile(KC_VFS_NS_DEF + struct inode *dir, struct dentry *dentry, umode_t mode) { struct super_block *sb = dir->i_sb; struct inode *inode = NULL; diff --git a/kmod/src/file.c b/kmod/src/file.c index d44cd822..15158a2b 100644 --- a/kmod/src/file.c +++ b/kmod/src/file.c @@ -267,7 +267,8 @@ out: } #endif -int scoutfs_permission(struct inode *inode, int mask) +int scoutfs_permission(KC_VFS_NS_DEF + struct inode *inode, int mask) { struct super_block *sb = inode->i_sb; struct scoutfs_lock *inode_lock = NULL; @@ -281,7 +282,8 @@ int scoutfs_permission(struct inode *inode, int mask) if (ret) return ret; - ret = generic_permission(inode, mask); + ret = generic_permission(KC_VFS_INIT_NS + inode, mask); scoutfs_unlock(sb, inode_lock, SCOUTFS_LOCK_READ); diff --git a/kmod/src/file.h b/kmod/src/file.h index 82829ef5..1009b11f 100644 --- a/kmod/src/file.h +++ b/kmod/src/file.h @@ -10,7 +10,8 @@ ssize_t scoutfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, ssize_t scoutfs_file_read_iter(struct kiocb *, struct iov_iter *); ssize_t scoutfs_file_write_iter(struct kiocb *, struct iov_iter *); #endif -int scoutfs_permission(struct inode *inode, int mask); +int scoutfs_permission(KC_VFS_NS_DEF + struct inode *inode, int mask); loff_t scoutfs_file_llseek(struct file *file, loff_t offset, int whence); #endif /* _SCOUTFS_FILE_H_ */ diff --git a/kmod/src/inode.c b/kmod/src/inode.c index 04c088c2..5e3f724f 100644 --- a/kmod/src/inode.c +++ b/kmod/src/inode.c @@ -373,7 +373,8 @@ int scoutfs_getattr(struct vfsmount *mnt, struct dentry *dentry, { struct inode *inode = dentry->d_inode; #else -int scoutfs_getattr(const struct path *path, struct kstat *stat, +int scoutfs_getattr(KC_VFS_NS_DEF + const struct path *path, struct kstat *stat, u32 request_mask, unsigned int query_flags) { struct inode *inode = d_inode(path->dentry); @@ -385,7 +386,8 @@ int scoutfs_getattr(const struct path *path, struct kstat *stat, ret = scoutfs_lock_inode(sb, SCOUTFS_LOCK_READ, SCOUTFS_LKF_REFRESH_INODE, inode, &lock); if (ret == 0) { - generic_fillattr(inode, stat); + generic_fillattr(KC_VFS_INIT_NS + inode, stat); scoutfs_unlock(sb, lock, SCOUTFS_LOCK_READ); } return ret; @@ -483,7 +485,8 @@ int scoutfs_complete_truncate(struct inode *inode, struct scoutfs_lock *lock) * re-acquire it. Ideally we'd fix this so that we can acquire the lock * instead of the caller. */ -int scoutfs_setattr(struct dentry *dentry, struct iattr *attr) +int scoutfs_setattr(KC_VFS_NS_DEF + struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; struct super_block *sb = inode->i_sb; @@ -501,7 +504,8 @@ retry: SCOUTFS_LKF_REFRESH_INODE, inode, &lock); if (ret) return ret; - ret = setattr_prepare(dentry, attr); + ret = setattr_prepare(KC_VFS_INIT_NS + dentry, attr); if (ret) goto out; @@ -565,7 +569,8 @@ retry: if (ret < 0) goto release; - setattr_copy(inode, attr); + setattr_copy(KC_VFS_INIT_NS + inode, attr); inode_inc_iversion(inode); scoutfs_update_inode_item(inode, lock, &ind_locks); @@ -1562,7 +1567,8 @@ int scoutfs_new_inode(struct super_block *sb, struct inode *dir, umode_t mode, d scoutfs_inode_set_data_seq(inode); inode->i_ino = ino; /* XXX overflow */ - inode_init_owner(inode, dir, mode); + inode_init_owner(KC_VFS_INIT_NS + inode, dir, mode); inode_set_bytes(inode, 0); inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); inode->i_rdev = rdev; diff --git a/kmod/src/inode.h b/kmod/src/inode.h index e068cee5..fcead8fb 100644 --- a/kmod/src/inode.h +++ b/kmod/src/inode.h @@ -135,10 +135,12 @@ int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock); int scoutfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); #else -int scoutfs_getattr(const struct path *path, struct kstat *stat, +int scoutfs_getattr(KC_VFS_NS_DEF + const struct path *path, struct kstat *stat, u32 request_mask, unsigned int query_flags); #endif -int scoutfs_setattr(struct dentry *dentry, struct iattr *attr); +int scoutfs_setattr(KC_VFS_NS_DEF + struct dentry *dentry, struct iattr *attr); int scoutfs_inode_orphan_create(struct super_block *sb, u64 ino, struct scoutfs_lock *lock, struct scoutfs_lock *primary); diff --git a/kmod/src/ioctl.c b/kmod/src/ioctl.c index 45fc0e51..9480d339 100644 --- a/kmod/src/ioctl.c +++ b/kmod/src/ioctl.c @@ -716,7 +716,8 @@ static long scoutfs_ioc_listxattr_hidden(struct file *file, unsigned long arg) int total = 0; int ret; - ret = inode_permission(inode, MAY_READ); + ret = inode_permission(KC_VFS_INIT_NS + inode, MAY_READ); if (ret < 0) goto out; diff --git a/kmod/src/kernelcompat.h b/kmod/src/kernelcompat.h index 1d7acee7..247aa4e1 100644 --- a/kmod/src/kernelcompat.h +++ b/kmod/src/kernelcompat.h @@ -290,6 +290,16 @@ typedef unsigned int blk_opf_t; #define kc__vmalloc __vmalloc #endif +#ifdef KC_VFS_METHOD_USER_NAMESPACE_ARG +#define KC_VFS_NS_DEF struct user_namespace *mnt_user_ns, +#define KC_VFS_NS mnt_user_ns, +#define KC_VFS_INIT_NS &init_user_ns, +#else +#define KC_VFS_NS_DEF +#define KC_VFS_NS +#define KC_VFS_INIT_NS +#endif + #ifdef KC_BIO_ALLOC_DEV_OPF_ARGS #define kc_bio_alloc bio_alloc #else