Skip to content

Commit

Permalink
fs: make helpers idmap mount aware
Browse files Browse the repository at this point in the history
Extend some inode methods with an additional user namespace argument. A
filesystem that is aware of idmapped mounts will receive the user
namespace the mount has been marked with. This can be used for
additional permission checking and also to enable filesystems to
translate between uids and gids if they need to. We have implemented all
relevant helpers in earlier patches.

As requested we simply extend the exisiting inode method instead of
introducing new ones. This is a little more code churn but it's mostly
mechanical and doesnt't leave us with additional inode methods.

Link: https://lore.kernel.org/r/[email protected]
Cc: Christoph Hellwig <[email protected]>
Cc: David Howells <[email protected]>
Cc: Al Viro <[email protected]>
Cc: [email protected]
Reviewed-by: Christoph Hellwig <[email protected]>
Signed-off-by: Christian Brauner <[email protected]>
  • Loading branch information
Christian Brauner committed Jan 24, 2021
1 parent 1ab2996 commit 549c729
Show file tree
Hide file tree
Showing 182 changed files with 1,121 additions and 756 deletions.
19 changes: 10 additions & 9 deletions Documentation/filesystems/vfs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -415,28 +415,29 @@ As of kernel 2.6.22, the following members are defined:
.. code-block:: c
struct inode_operations {
int (*create) (struct inode *,struct dentry *, umode_t, bool);
int (*create) (struct user_namespace *, struct inode *,struct dentry *, umode_t, bool);
struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
int (*link) (struct dentry *,struct inode *,struct dentry *);
int (*unlink) (struct inode *,struct dentry *);
int (*symlink) (struct inode *,struct dentry *,const char *);
int (*mkdir) (struct inode *,struct dentry *,umode_t);
int (*symlink) (struct user_namespace *, struct inode *,struct dentry *,const char *);
int (*mkdir) (struct user_namespace *, struct inode *,struct dentry *,umode_t);
int (*rmdir) (struct inode *,struct dentry *);
int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t);
int (*rename) (struct inode *, struct dentry *,
int (*mknod) (struct user_namespace *, struct inode *,struct dentry *,umode_t,dev_t);
int (*rename) (struct user_namespace *, struct inode *, struct dentry *,
struct inode *, struct dentry *, unsigned int);
int (*readlink) (struct dentry *, char __user *,int);
const char *(*get_link) (struct dentry *, struct inode *,
struct delayed_call *);
int (*permission) (struct inode *, int);
int (*permission) (struct user_namespace *, struct inode *, int);
int (*get_acl)(struct inode *, int);
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (const struct path *, struct kstat *, u32, unsigned int);
int (*setattr) (struct user_namespace *, struct dentry *, struct iattr *);
int (*getattr) (struct user_namespace *, const struct path *, struct kstat *, u32, unsigned int);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
void (*update_time)(struct inode *, struct timespec *, int);
int (*atomic_open)(struct inode *, struct dentry *, struct file *,
unsigned open_flag, umode_t create_mode);
int (*tmpfile) (struct inode *, struct dentry *, umode_t);
int (*tmpfile) (struct user_namespace *, struct inode *, struct dentry *, umode_t);
int (*set_acl)(struct user_namespace *, struct inode *, struct posix_acl *, int);
};
Again, all methods are called without any locks being held, unless
Expand Down
3 changes: 2 additions & 1 deletion arch/powerpc/platforms/cell/spufs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ spufs_new_inode(struct super_block *sb, umode_t mode)
}

static int
spufs_setattr(struct dentry *dentry, struct iattr *attr)
spufs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
struct iattr *attr)
{
struct inode *inode = d_inode(dentry);

Expand Down
6 changes: 4 additions & 2 deletions drivers/android/binderfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,15 +355,17 @@ static inline bool is_binderfs_control_device(const struct dentry *dentry)
return info->control_dentry == dentry;
}

static int binderfs_rename(struct inode *old_dir, struct dentry *old_dentry,
static int binderfs_rename(struct user_namespace *mnt_userns,
struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags)
{
if (is_binderfs_control_device(old_dentry) ||
is_binderfs_control_device(new_dentry))
return -EPERM;

return simple_rename(old_dir, old_dentry, new_dir, new_dentry, flags);
return simple_rename(&init_user_ns, old_dir, old_dentry, new_dir,
new_dentry, flags);
}

static int binderfs_unlink(struct inode *dir, struct dentry *dentry)
Expand Down
4 changes: 2 additions & 2 deletions fs/9p/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
struct iattr iattr = { 0 };
struct posix_acl *old_acl = acl;

retval = posix_acl_update_mode(mnt_userns, inode,
retval = posix_acl_update_mode(&init_user_ns, inode,
&iattr.ia_mode, &acl);
if (retval)
goto err_out;
Expand All @@ -299,7 +299,7 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
* What is the following setxattr update the
* mode ?
*/
v9fs_vfs_setattr_dotl(dentry, &iattr);
v9fs_vfs_setattr_dotl(&init_user_ns, dentry, &iattr);
}
break;
case ACL_TYPE_DEFAULT:
Expand Down
3 changes: 2 additions & 1 deletion fs/9p/v9fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ extern struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
unsigned int flags);
extern int v9fs_vfs_unlink(struct inode *i, struct dentry *d);
extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d);
extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
extern int v9fs_vfs_rename(struct user_namespace *mnt_userns,
struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags);
extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses,
Expand Down
3 changes: 2 additions & 1 deletion fs/9p/v9fs_vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat);
int v9fs_uflags2omode(int uflags, int extended);

void v9fs_blank_wstat(struct p9_wstat *wstat);
int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *);
int v9fs_vfs_setattr_dotl(struct user_namespace *, struct dentry *,
struct iattr *);
int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end,
int datasync);
int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode);
Expand Down
26 changes: 15 additions & 11 deletions fs/9p/vfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -676,8 +676,8 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
*/

static int
v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
bool excl)
v9fs_vfs_create(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *dentry, umode_t mode, bool excl)
{
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
u32 perm = unixmode2p9mode(v9ses, mode);
Expand All @@ -702,7 +702,8 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
*
*/

static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
static int v9fs_vfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *dentry, umode_t mode)
{
int err;
u32 perm;
Expand Down Expand Up @@ -907,9 +908,9 @@ int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
*/

int
v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags)
v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
struct dentry *old_dentry, struct inode *new_dir,
struct dentry *new_dentry, unsigned int flags)
{
int retval;
struct inode *old_inode;
Expand Down Expand Up @@ -1016,8 +1017,8 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
*/

static int
v9fs_vfs_getattr(const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int flags)
v9fs_vfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
struct kstat *stat, u32 request_mask, unsigned int flags)
{
struct dentry *dentry = path->dentry;
struct v9fs_session_info *v9ses;
Expand Down Expand Up @@ -1054,7 +1055,8 @@ v9fs_vfs_getattr(const struct path *path, struct kstat *stat,
*
*/

static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
static int v9fs_vfs_setattr(struct user_namespace *mnt_userns,
struct dentry *dentry, struct iattr *iattr)
{
int retval, use_dentry = 0;
struct v9fs_session_info *v9ses;
Expand Down Expand Up @@ -1295,7 +1297,8 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
*/

static int
v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
v9fs_vfs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *dentry, const char *symname)
{
p9_debug(P9_DEBUG_VFS, " %lu,%pd,%s\n",
dir->i_ino, dentry, symname);
Expand Down Expand Up @@ -1348,7 +1351,8 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
*/

static int
v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
v9fs_vfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *dentry, umode_t mode, dev_t rdev)
{
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
int retval;
Expand Down
31 changes: 17 additions & 14 deletions fs/9p/vfs_inode_dotl.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
#include "acl.h"

static int
v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
dev_t rdev);
v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *dentry, umode_t omode, dev_t rdev);

/**
* v9fs_get_fsgid_for_create - Helper function to get the gid for creating a
Expand Down Expand Up @@ -218,10 +218,10 @@ int v9fs_open_to_dotl_flags(int flags)
*/

static int
v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
bool excl)
v9fs_vfs_create_dotl(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *dentry, umode_t omode, bool excl)
{
return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0);
return v9fs_vfs_mknod_dotl(mnt_userns, dir, dentry, omode, 0);
}

static int
Expand Down Expand Up @@ -367,8 +367,9 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
*
*/

static int v9fs_vfs_mkdir_dotl(struct inode *dir,
struct dentry *dentry, umode_t omode)
static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
struct inode *dir, struct dentry *dentry,
umode_t omode)
{
int err;
struct v9fs_session_info *v9ses;
Expand Down Expand Up @@ -457,8 +458,9 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
}

static int
v9fs_vfs_getattr_dotl(const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int flags)
v9fs_vfs_getattr_dotl(struct user_namespace *mnt_userns,
const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int flags)
{
struct dentry *dentry = path->dentry;
struct v9fs_session_info *v9ses;
Expand Down Expand Up @@ -540,7 +542,8 @@ static int v9fs_mapped_iattr_valid(int iattr_valid)
*
*/

int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns,
struct dentry *dentry, struct iattr *iattr)
{
int retval, use_dentry = 0;
struct p9_fid *fid = NULL;
Expand Down Expand Up @@ -684,8 +687,8 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode,
}

static int
v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
const char *symname)
v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *dentry, const char *symname)
{
int err;
kgid_t gid;
Expand Down Expand Up @@ -824,8 +827,8 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
*
*/
static int
v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
dev_t rdev)
v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *dentry, umode_t omode, dev_t rdev)
{
int err;
kgid_t gid;
Expand Down
3 changes: 2 additions & 1 deletion fs/adfs/adfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ struct adfs_discmap {
/* Inode stuff */
struct inode *adfs_iget(struct super_block *sb, struct object_info *obj);
int adfs_write_inode(struct inode *inode, struct writeback_control *wbc);
int adfs_notify_change(struct dentry *dentry, struct iattr *attr);
int adfs_notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
struct iattr *attr);

/* map.c */
int adfs_map_lookup(struct super_block *sb, u32 frag_id, unsigned int offset);
Expand Down
3 changes: 2 additions & 1 deletion fs/adfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ adfs_iget(struct super_block *sb, struct object_info *obj)
* later.
*/
int
adfs_notify_change(struct dentry *dentry, struct iattr *attr)
adfs_notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
struct iattr *attr)
{
struct inode *inode = d_inode(dentry);
struct super_block *sb = inode->i_sb;
Expand Down
24 changes: 15 additions & 9 deletions fs/affs/affs.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,27 +167,33 @@ extern const struct export_operations affs_export_ops;
extern int affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len);
extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int);
extern int affs_unlink(struct inode *dir, struct dentry *dentry);
extern int affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool);
extern int affs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
extern int affs_create(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *dentry, umode_t mode, bool);
extern int affs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *dentry, umode_t mode);
extern int affs_rmdir(struct inode *dir, struct dentry *dentry);
extern int affs_link(struct dentry *olddentry, struct inode *dir,
struct dentry *dentry);
extern int affs_symlink(struct inode *dir, struct dentry *dentry,
const char *symname);
extern int affs_rename2(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags);
extern int affs_symlink(struct user_namespace *mnt_userns,
struct inode *dir, struct dentry *dentry,
const char *symname);
extern int affs_rename2(struct user_namespace *mnt_userns,
struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags);

/* inode.c */

extern struct inode *affs_new_inode(struct inode *dir);
extern int affs_notify_change(struct dentry *dentry, struct iattr *attr);
extern int affs_notify_change(struct user_namespace *mnt_userns,
struct dentry *dentry, struct iattr *attr);
extern void affs_evict_inode(struct inode *inode);
extern struct inode *affs_iget(struct super_block *sb,
unsigned long ino);
extern int affs_write_inode(struct inode *inode,
struct writeback_control *wbc);
extern int affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s32 type);
extern int affs_add_entry(struct inode *dir, struct inode *inode,
struct dentry *dentry, s32 type);

/* file.c */

Expand Down
3 changes: 2 additions & 1 deletion fs/affs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,8 @@ affs_write_inode(struct inode *inode, struct writeback_control *wbc)
}

int
affs_notify_change(struct dentry *dentry, struct iattr *attr)
affs_notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
struct iattr *attr)
{
struct inode *inode = d_inode(dentry);
int error;
Expand Down
15 changes: 9 additions & 6 deletions fs/affs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,8 @@ affs_unlink(struct inode *dir, struct dentry *dentry)
}

int
affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
affs_create(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *dentry, umode_t mode, bool excl)
{
struct super_block *sb = dir->i_sb;
struct inode *inode;
Expand Down Expand Up @@ -273,7 +274,8 @@ affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
}

int
affs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
affs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *dentry, umode_t mode)
{
struct inode *inode;
int error;
Expand Down Expand Up @@ -311,7 +313,8 @@ affs_rmdir(struct inode *dir, struct dentry *dentry)
}

int
affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
affs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *dentry, const char *symname)
{
struct super_block *sb = dir->i_sb;
struct buffer_head *bh;
Expand Down Expand Up @@ -498,9 +501,9 @@ affs_xrename(struct inode *old_dir, struct dentry *old_dentry,
return retval;
}

int affs_rename2(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags)
int affs_rename2(struct user_namespace *mnt_userns, struct inode *old_dir,
struct dentry *old_dentry, struct inode *new_dir,
struct dentry *new_dentry, unsigned int flags)
{

if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
Expand Down
Loading

0 comments on commit 549c729

Please sign in to comment.