Skip to content

Commit

Permalink
namei: prepare for idmapped mounts
Browse files Browse the repository at this point in the history
The various vfs_*() helpers are called by filesystems or by the vfs
itself to perform core operations such as create, link, mkdir, mknod, rename,
rmdir, tmpfile and unlink. Enable them to handle idmapped mounts. If the
inode is accessed through an idmapped mount map it into the
mount's user namespace and pass it down. Afterwards the checks and
operations are identical to non-idmapped mounts. If the initial user
namespace is passed nothing changes so non-idmapped mounts will see
identical behavior as before.

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 9fe6145 commit 6521f89
Show file tree
Hide file tree
Showing 12 changed files with 279 additions and 105 deletions.
11 changes: 7 additions & 4 deletions drivers/base/devtmpfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ static int dev_mkdir(const char *name, umode_t mode)
if (IS_ERR(dentry))
return PTR_ERR(dentry);

err = vfs_mkdir(d_inode(path.dentry), dentry, mode);
err = vfs_mkdir(&init_user_ns, d_inode(path.dentry), dentry, mode);
if (!err)
/* mark as kernel-created inode */
d_inode(dentry)->i_private = &thread;
Expand Down Expand Up @@ -212,7 +212,8 @@ static int handle_create(const char *nodename, umode_t mode, kuid_t uid,
if (IS_ERR(dentry))
return PTR_ERR(dentry);

err = vfs_mknod(d_inode(path.dentry), dentry, mode, dev->devt);
err = vfs_mknod(&init_user_ns, d_inode(path.dentry), dentry, mode,
dev->devt);
if (!err) {
struct iattr newattrs;

Expand Down Expand Up @@ -242,7 +243,8 @@ static int dev_rmdir(const char *name)
return PTR_ERR(dentry);
if (d_really_is_positive(dentry)) {
if (d_inode(dentry)->i_private == &thread)
err = vfs_rmdir(d_inode(parent.dentry), dentry);
err = vfs_rmdir(&init_user_ns, d_inode(parent.dentry),
dentry);
else
err = -EPERM;
} else {
Expand Down Expand Up @@ -330,7 +332,8 @@ static int handle_remove(const char *nodename, struct device *dev)
inode_lock(d_inode(dentry));
notify_change(&init_user_ns, dentry, &newattrs, NULL);
inode_unlock(d_inode(dentry));
err = vfs_unlink(d_inode(parent.dentry), dentry, NULL);
err = vfs_unlink(&init_user_ns, d_inode(parent.dentry),
dentry, NULL);
if (!err || err == -ENOENT)
deleted = 1;
}
Expand Down
12 changes: 8 additions & 4 deletions fs/cachefiles/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,8 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
cachefiles_io_error(cache, "Unlink security error");
} else {
trace_cachefiles_unlink(object, rep, why);
ret = vfs_unlink(d_inode(dir), rep, NULL);
ret = vfs_unlink(&init_user_ns, d_inode(dir), rep,
NULL);

if (preemptive)
cachefiles_mark_object_buried(cache, rep, why);
Expand Down Expand Up @@ -413,8 +414,10 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
cachefiles_io_error(cache, "Rename security error %d", ret);
} else {
struct renamedata rd = {
.old_mnt_userns = &init_user_ns,
.old_dir = d_inode(dir),
.old_dentry = rep,
.new_mnt_userns = &init_user_ns,
.new_dir = d_inode(cache->graveyard),
.new_dentry = grave,
};
Expand Down Expand Up @@ -566,7 +569,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
if (ret < 0)
goto create_error;
start = jiffies;
ret = vfs_mkdir(d_inode(dir), next, 0);
ret = vfs_mkdir(&init_user_ns, d_inode(dir), next, 0);
cachefiles_hist(cachefiles_mkdir_histogram, start);
if (!key)
trace_cachefiles_mkdir(object, next, ret);
Expand Down Expand Up @@ -602,7 +605,8 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
if (ret < 0)
goto create_error;
start = jiffies;
ret = vfs_create(d_inode(dir), next, S_IFREG, true);
ret = vfs_create(&init_user_ns, d_inode(dir), next,
S_IFREG, true);
cachefiles_hist(cachefiles_create_histogram, start);
trace_cachefiles_create(object, next, ret);
if (ret < 0)
Expand Down Expand Up @@ -796,7 +800,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
ret = security_path_mkdir(&path, subdir, 0700);
if (ret < 0)
goto mkdir_error;
ret = vfs_mkdir(d_inode(dir), subdir, 0700);
ret = vfs_mkdir(&init_user_ns, d_inode(dir), subdir, 0700);
if (ret < 0)
goto mkdir_error;

Expand Down
33 changes: 20 additions & 13 deletions fs/ecryptfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ static int ecryptfs_do_unlink(struct inode *dir, struct dentry *dentry,
else if (d_unhashed(lower_dentry))
rc = -EINVAL;
else
rc = vfs_unlink(lower_dir_inode, lower_dentry, NULL);
rc = vfs_unlink(&init_user_ns, lower_dir_inode, lower_dentry,
NULL);
if (rc) {
printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
goto out_unlock;
Expand Down Expand Up @@ -180,7 +181,8 @@ ecryptfs_do_create(struct inode *directory_inode,

lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
lower_dir_dentry = lock_parent(lower_dentry);
rc = vfs_create(d_inode(lower_dir_dentry), lower_dentry, mode, true);
rc = vfs_create(&init_user_ns, d_inode(lower_dir_dentry), lower_dentry,
mode, true);
if (rc) {
printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
"rc = [%d]\n", __func__, rc);
Expand All @@ -190,7 +192,8 @@ ecryptfs_do_create(struct inode *directory_inode,
inode = __ecryptfs_get_inode(d_inode(lower_dentry),
directory_inode->i_sb);
if (IS_ERR(inode)) {
vfs_unlink(d_inode(lower_dir_dentry), lower_dentry, NULL);
vfs_unlink(&init_user_ns, d_inode(lower_dir_dentry),
lower_dentry, NULL);
goto out_lock;
}
fsstack_copy_attr_times(directory_inode, d_inode(lower_dir_dentry));
Expand Down Expand Up @@ -436,8 +439,8 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,
dget(lower_old_dentry);
dget(lower_new_dentry);
lower_dir_dentry = lock_parent(lower_new_dentry);
rc = vfs_link(lower_old_dentry, d_inode(lower_dir_dentry),
lower_new_dentry, NULL);
rc = vfs_link(lower_old_dentry, &init_user_ns,
d_inode(lower_dir_dentry), lower_new_dentry, NULL);
if (rc || d_really_is_negative(lower_new_dentry))
goto out_lock;
rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb);
Expand Down Expand Up @@ -481,7 +484,7 @@ static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,
strlen(symname));
if (rc)
goto out_lock;
rc = vfs_symlink(d_inode(lower_dir_dentry), lower_dentry,
rc = vfs_symlink(&init_user_ns, d_inode(lower_dir_dentry), lower_dentry,
encoded_symname);
kfree(encoded_symname);
if (rc || d_really_is_negative(lower_dentry))
Expand All @@ -507,7 +510,8 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode

lower_dentry = ecryptfs_dentry_to_lower(dentry);
lower_dir_dentry = lock_parent(lower_dentry);
rc = vfs_mkdir(d_inode(lower_dir_dentry), lower_dentry, mode);
rc = vfs_mkdir(&init_user_ns, d_inode(lower_dir_dentry), lower_dentry,
mode);
if (rc || d_really_is_negative(lower_dentry))
goto out;
rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);
Expand Down Expand Up @@ -541,7 +545,7 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
else if (d_unhashed(lower_dentry))
rc = -EINVAL;
else
rc = vfs_rmdir(lower_dir_inode, lower_dentry);
rc = vfs_rmdir(&init_user_ns, lower_dir_inode, lower_dentry);
if (!rc) {
clear_nlink(d_inode(dentry));
fsstack_copy_attr_times(dir, lower_dir_inode);
Expand All @@ -563,7 +567,8 @@ ecryptfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev

lower_dentry = ecryptfs_dentry_to_lower(dentry);
lower_dir_dentry = lock_parent(lower_dentry);
rc = vfs_mknod(d_inode(lower_dir_dentry), lower_dentry, mode, dev);
rc = vfs_mknod(&init_user_ns, d_inode(lower_dir_dentry), lower_dentry,
mode, dev);
if (rc || d_really_is_negative(lower_dentry))
goto out;
rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);
Expand Down Expand Up @@ -621,10 +626,12 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
goto out_lock;
}

rd.old_dir = d_inode(lower_old_dir_dentry);
rd.old_dentry = lower_old_dentry;
rd.new_dir = d_inode(lower_new_dir_dentry);
rd.new_dentry = lower_new_dentry;
rd.old_mnt_userns = &init_user_ns;
rd.old_dir = d_inode(lower_old_dir_dentry);
rd.old_dentry = lower_old_dentry;
rd.new_mnt_userns = &init_user_ns;
rd.new_dir = d_inode(lower_new_dir_dentry);
rd.new_dentry = lower_new_dentry;
rc = vfs_rename(&rd);
if (rc)
goto out_lock;
Expand Down
14 changes: 8 additions & 6 deletions fs/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ int __init init_mknod(const char *filename, umode_t mode, unsigned int dev)
mode &= ~current_umask();
error = security_path_mknod(&path, dentry, mode, dev);
if (!error)
error = vfs_mknod(path.dentry->d_inode, dentry, mode,
new_decode_dev(dev));
error = vfs_mknod(&init_user_ns, path.dentry->d_inode, dentry,
mode, new_decode_dev(dev));
done_path_create(&path, dentry);
return error;
}
Expand Down Expand Up @@ -187,8 +187,8 @@ int __init init_link(const char *oldname, const char *newname)
error = security_path_link(old_path.dentry, &new_path, new_dentry);
if (error)
goto out_dput;
error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry,
NULL);
error = vfs_link(old_path.dentry, &init_user_ns,
new_path.dentry->d_inode, new_dentry, NULL);
out_dput:
done_path_create(&new_path, new_dentry);
out:
Expand All @@ -207,7 +207,8 @@ int __init init_symlink(const char *oldname, const char *newname)
return PTR_ERR(dentry);
error = security_path_symlink(&path, dentry, oldname);
if (!error)
error = vfs_symlink(path.dentry->d_inode, dentry, oldname);
error = vfs_symlink(&init_user_ns, path.dentry->d_inode, dentry,
oldname);
done_path_create(&path, dentry);
return error;
}
Expand All @@ -230,7 +231,8 @@ int __init init_mkdir(const char *pathname, umode_t mode)
mode &= ~current_umask();
error = security_path_mkdir(&path, dentry, mode);
if (!error)
error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
error = vfs_mkdir(&init_user_ns, path.dentry->d_inode, dentry,
mode);
done_path_create(&path, dentry);
return error;
}
Expand Down
Loading

0 comments on commit 6521f89

Please sign in to comment.