[PATCH] 3.8: access permission filesystem

From: Olaf Dietsche
Date: Wed Mar 19 2014 - 15:59:04 EST


I am in the process of catching up with the last two years or so.
Right now, I am at the changes involving user namespaces.

I have two possible implementations, both working equally well in a
shared environment. Since I am not familiar with namespaces in general
and user namespaces in particular, I would like you to look over the
patches and tell me, what you think.

Are the patches good so far? Are there are any things I missed and must
consider? Maybe, I am completely off track? Anything else?

I included both patches inline below. The patches are also available as
separate branches at github

https://github.com/olafdietsche/linux-accessfs/tree/tmp-user-ns-1
https://github.com/olafdietsche/linux-accessfs/tree/tmp-user-ns-2

I am leaning toward the second patch. Although it is a little bit longer
than the first one, it involves no user id conversions.

fs/accessfs/inode.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/accessfs/inode.c b/fs/accessfs/inode.c
index e02c275..ce62ff0 100644
--- a/fs/accessfs/inode.c
+++ b/fs/accessfs/inode.c
@@ -122,8 +122,8 @@ static void accessfs_init_inode(struct inode *inode, struct accessfs_entry *pe)
{
static const struct timespec epoch = {0, 0};
inode->i_private = pe;
- inode->i_uid = pe->attr->uid;
- inode->i_gid = pe->attr->gid;
+ i_uid_write(inode, pe->attr->uid);
+ i_gid_write(inode, pe->attr->gid);
inode->i_mode = pe->attr->mode;
/*
inode->i_blksize = PAGE_CACHE_SIZE;
@@ -269,8 +269,8 @@ static int accessfs_notify_change(struct dentry *dentry, struct iattr *iattr)
setattr_copy(i, iattr);

pe = (struct accessfs_entry *) i->i_private;
- pe->attr->uid = i->i_uid;
- pe->attr->gid = i->i_gid;
+ pe->attr->uid = i_uid_read(i);
+ pe->attr->gid = i_gid_read(i);
pe->attr->mode = i->i_mode;
return 0;
}
@@ -363,9 +363,9 @@ static struct dentry *accessfs_mount(struct file_system_type *fs_type,
int accessfs_permitted(struct access_attr *p, int mask)
{
mode_t mode = p->mode;
- if (current_fsuid() == p->uid)
+ if (uid_eq(current_fsuid(), make_kuid(current_user_ns(), p->uid)))
mode >>= 6;
- else if (in_group_p(p->gid))
+ else if (in_group_p(make_kgid(current_user_ns(), p->gid)))
mode >>= 3;

return (mode & mask) == mask;
fs/accessfs/capabilities.c | 4 ++--
fs/accessfs/inode.c | 8 ++++----
fs/accessfs/ip.c | 4 ++--
include/linux/accessfs_fs.h | 4 ++--
4 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/fs/accessfs/capabilities.c b/fs/accessfs/capabilities.c
index a8b52b3..d60b16f 100644
--- a/fs/accessfs/capabilities.c
+++ b/fs/accessfs/capabilities.c
@@ -83,8 +83,8 @@ static int __init init_capabilities(void)
return -ENOTDIR;

for (i = 0; i < ARRAY_SIZE(caps); ++i) {
- caps[i].uid = 0;
- caps[i].gid = 0;
+ caps[i].uid = GLOBAL_ROOT_UID;
+ caps[i].gid = GLOBAL_ROOT_GID;
caps[i].mode = S_IXUSR;
err = accessfs_register(dir, names[i], &caps[i]);
if (err) {
diff --git a/fs/accessfs/inode.c b/fs/accessfs/inode.c
index e02c275..4e4867d 100644
--- a/fs/accessfs/inode.c
+++ b/fs/accessfs/inode.c
@@ -115,7 +115,7 @@ static struct accessfs_direntry accessfs_rootdir = {
LIST_HEAD_INIT(accessfs_rootdir.node.siblings),
1, &accessfs_rootdir.attr },
NULL, LIST_HEAD_INIT(accessfs_rootdir.children),
- { 0, 0, S_IFDIR | 0755 }
+ { GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, S_IFDIR | 0755 }
};

static void accessfs_init_inode(struct inode *inode, struct accessfs_entry *pe)
@@ -174,8 +174,8 @@ static int accessfs_node_init(struct accessfs_direntry *parent,
de->name[len] = 0;
de->ino = ++ino;
de->attr = attr;
- de->attr->uid = 0;
- de->attr->gid = 0;
+ de->attr->uid = GLOBAL_ROOT_UID;
+ de->attr->gid = GLOBAL_ROOT_GID;
de->attr->mode = mode;

list_add_tail(&de->hash, &hash);
@@ -363,7 +363,7 @@ static struct dentry *accessfs_mount(struct file_system_type *fs_type,
int accessfs_permitted(struct access_attr *p, int mask)
{
mode_t mode = p->mode;
- if (current_fsuid() == p->uid)
+ if (uid_eq(current_fsuid(), p->uid))
mode >>= 6;
else if (in_group_p(p->gid))
mode >>= 3;
diff --git a/fs/accessfs/ip.c b/fs/accessfs/ip.c
index a6c0ee0..493a2ca 100644
--- a/fs/accessfs/ip.c
+++ b/fs/accessfs/ip.c
@@ -66,8 +66,8 @@ static int __init init_ip(void)

for (i = 1; i < max_prot_sock; ++i) {
char buf[sizeof("65536")];
- bind_to_port[i].uid = 0;
- bind_to_port[i].gid = 0;
+ bind_to_port[i].uid = GLOBAL_ROOT_UID;
+ bind_to_port[i].gid = GLOBAL_ROOT_GID;
bind_to_port[i].mode = i < PROT_SOCK ? S_IXUSR : S_IXUGO;
sprintf(buf, "%d", i);
accessfs_register(dir, buf, &bind_to_port[i]);
diff --git a/include/linux/accessfs_fs.h b/include/linux/accessfs_fs.h
index ecd914e..8ebc24a 100644
--- a/include/linux/accessfs_fs.h
+++ b/include/linux/accessfs_fs.h
@@ -14,8 +14,8 @@
#include <net/sock.h>

struct access_attr {
- uid_t uid;
- gid_t gid;
+ kuid_t uid;
+ kgid_t gid;
mode_t mode;
};