From: Alin Dobre <alinmd@xxxxxxxxx> The fsuid mapping should replaces modifying the inode directly for read/write operations. Signed-off-by: Alin Dobre <alinmd@xxxxxxxxx> --- fs/idmapfs/file.c | 42 ++++++++++++++++++++++++++++++++++++------ fs/idmapfs/inode.c | 6 +++--- fs/idmapfs/lookup.c | 2 +- fs/idmapfs/wrapfs.h | 2 ++ 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/fs/idmapfs/file.c b/fs/idmapfs/file.c index df44994..88697a0 100644 --- a/fs/idmapfs/file.c +++ b/fs/idmapfs/file.c @@ -11,6 +11,34 @@ #include "wrapfs.h" +int map_fsuid(void) { + struct cred *mapped_cred; + + mapped_cred = prepare_creds(); + if (!mapped_cred) + return -ENOMEM; + if (mapped_cred->fsuid != 1000) { + abort_creds(mapped_cred); + return 0; + } + mapped_cred->fsuid = 1001; + return commit_creds(mapped_cred); +} + +int unmap_fsuid(void) { + struct cred *mapped_cred; + + mapped_cred = prepare_creds(); + if (!mapped_cred) + return -ENOMEM; + if (mapped_cred->fsuid != 1001) { + abort_creds(mapped_cred); + return 0; + } + mapped_cred->fsuid = 1000; + return commit_creds(mapped_cred); +} + static ssize_t wrapfs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { @@ -19,9 +47,9 @@ static ssize_t wrapfs_read(struct file *file, char __user *buf, struct dentry *dentry = file->f_path.dentry; lower_file = wrapfs_lower_file(file); - lower_file->f_inode->i_uid=map_id(lower_file->f_inode->i_uid); + map_fsuid(); err = vfs_read(lower_file, buf, count, ppos); - lower_file->f_inode->i_uid=unmap_id(lower_file->f_inode->i_uid); + unmap_fsuid(); /* update our inode atime upon a successful lower read */ if (err >= 0) fsstack_copy_attr_atime(dentry->d_inode, @@ -38,9 +66,9 @@ static ssize_t wrapfs_write(struct file *file, const char __user *buf, struct dentry *dentry = file->f_path.dentry; lower_file = wrapfs_lower_file(file); - lower_file->f_inode->i_uid=map_id(lower_file->f_inode->i_uid); + map_fsuid(); err = vfs_write(lower_file, buf, count, ppos); - lower_file->f_inode->i_uid=unmap_id(lower_file->f_inode->i_uid); + unmap_fsuid(); /* update our inode times+sizes upon a successful lower write */ if (err >= 0) { fsstack_copy_inode_size(dentry->d_inode, @@ -59,9 +87,9 @@ static int wrapfs_readdir(struct file *file, void *dirent, filldir_t filldir) struct dentry *dentry = file->f_path.dentry; lower_file = wrapfs_lower_file(file); - lower_file->f_inode->i_uid=map_id(lower_file->f_inode->i_uid); + map_fsuid(); err = vfs_readdir(lower_file, filldir, dirent); - lower_file->f_inode->i_uid=unmap_id(lower_file->f_inode->i_uid); + unmap_fsuid(); file->f_pos = lower_file->f_pos; if (err >= 0) /* copy the atime */ fsstack_copy_attr_atime(dentry->d_inode, @@ -174,6 +202,7 @@ static int wrapfs_open(struct inode *inode, struct file *file) struct file *lower_file = NULL; struct path lower_path; + map_fsuid(); /* don't open unhashed/deleted files */ if (d_unhashed(file->f_path.dentry)) { err = -ENOENT; @@ -207,6 +236,7 @@ static int wrapfs_open(struct inode *inode, struct file *file) else fsstack_copy_attr_all(inode, wrapfs_lower_inode(inode)); out_err: + unmap_fsuid(); return err; } diff --git a/fs/idmapfs/inode.c b/fs/idmapfs/inode.c index 2b80e00..d38a5df1 100644 --- a/fs/idmapfs/inode.c +++ b/fs/idmapfs/inode.c @@ -24,11 +24,10 @@ static int wrapfs_create(struct inode *dir, struct dentry *dentry, lower_parent_dentry = lock_parent(lower_dentry); lower_dentry->d_inode->i_uid = map_id(lower_dentry->d_inode->i_uid); - lower_parent_dentry->d_inode->i_uid = map_id(lower_parent_dentry->d_inode->i_uid); + //lower_parent_dentry->d_inode->i_uid = map_id(lower_parent_dentry->d_inode->i_uid); err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, want_excl); - lower_dentry->d_inode->i_uid = unmap_id(lower_dentry->d_inode->i_uid); - lower_parent_dentry->d_inode->i_uid = unmap_id(lower_parent_dentry->d_inode->i_uid); + //lower_parent_dentry->d_inode->i_uid = unmap_id(lower_parent_dentry->d_inode->i_uid); if (err) goto out; err = wrapfs_interpose(dentry, dir->i_sb, &lower_path); @@ -36,6 +35,7 @@ static int wrapfs_create(struct inode *dir, struct dentry *dentry, goto out; fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir)); fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode); + lower_dentry->d_inode->i_uid = unmap_id(lower_dentry->d_inode->i_uid); out: unlock_dir(lower_parent_dentry); diff --git a/fs/idmapfs/lookup.c b/fs/idmapfs/lookup.c index 999b227..92816e3 100644 --- a/fs/idmapfs/lookup.c +++ b/fs/idmapfs/lookup.c @@ -205,13 +205,13 @@ int wrapfs_interpose(struct dentry *dentry, struct super_block *sb, /* inherit lower inode number for wrapfs's inode */ lower_inode->i_uid=map_id(lower_inode->i_uid); inode = wrapfs_iget(sb, lower_inode); - lower_inode->i_uid=unmap_id(lower_inode->i_uid); if (IS_ERR(inode)) { err = PTR_ERR(inode); goto out; } d_add(dentry, inode); + lower_inode->i_uid=unmap_id(lower_inode->i_uid); out: return err; diff --git a/fs/idmapfs/wrapfs.h b/fs/idmapfs/wrapfs.h index 59f46bc..a089862 100644 --- a/fs/idmapfs/wrapfs.h +++ b/fs/idmapfs/wrapfs.h @@ -63,6 +63,8 @@ extern int wrapfs_interpose(struct dentry *dentry, struct super_block *sb, /* UID/GID mapping */ int map_id(int id); int unmap_id(int id); +int map_fsuid(void); +int unmap_fsuid(void); /* file private data */ struct wrapfs_file_info { -- 1.8.3.2 _______________________________________________ Kernelnewbies mailing list Kernelnewbies@xxxxxxxxxxxxxxxxx http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies