[PATCH 3/3] Mapping read/write with fsuid
Alin Dobre
alin.dobre at elastichosts.com
Wed Oct 2 10:47:35 EDT 2013
From: Alin Dobre <alinmd at gmail.com>
The fsuid mapping should replaces modifying the inode directly for
read/write operations.
Signed-off-by: Alin Dobre <alinmd at gmail.com>
---
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
More information about the Kernelnewbies
mailing list