From: Alin Dobre <[email protected]>

The fsuid mapping should replaces modifying the inode directly for
read/write operations.

Signed-off-by: Alin Dobre <[email protected]>
---
 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
[email protected]
http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

Reply via email to