>From nobody Mon Sep 17 00:00:00 2001
From: Serge Hallyn <[EMAIL PROTECTED]>
Date: Wed, 28 Mar 2007 13:11:19 -0500
Subject: [PATCH 6/6] userns strict: hook ext3

Add a user namespace pointer to the ext3 superblock and inode.

Signed-off-by: Serge E. Hallyn <[EMAIL PROTECTED]>

---

 fs/ext3/acl.c              |    4 +++-
 fs/ext3/balloc.c           |   13 ++++++++++---
 fs/ext3/ialloc.c           |    5 +++++
 fs/ext3/inode.c            |    2 ++
 fs/ext3/ioctl.c            |   18 +++++++++++-------
 fs/ext3/super.c            |    4 ++++
 fs/ext3/xattr_trusted.c    |    3 ++-
 include/linux/ext3_fs_sb.h |    1 +
 8 files changed, 38 insertions(+), 12 deletions(-)

d51e324bced6f12d2fc7906dbfc355f4cd2bc8bc
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 1e5038d..35b64a9 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -11,6 +11,7 @@ #include <linux/capability.h>
 #include <linux/fs.h>
 #include <linux/ext3_jbd.h>
 #include <linux/ext3_fs.h>
+#include <linux/user_namespace.h>
 #include "xattr.h"
 #include "acl.h"
 
@@ -489,7 +490,8 @@ ext3_xattr_set_acl(struct inode *inode, 
 
        if (!test_opt(inode->i_sb, POSIX_ACL))
                return -EOPNOTSUPP;
-       if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+       if (!task_inode_same_fsuid(current, inode) &&
+                       !task_ino_capable(inode, CAP_FOWNER))
                return -EPERM;
 
        if (value) {
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index ca8aee6..ab4076d 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -19,6 +19,7 @@ #include <linux/ext3_fs.h>
 #include <linux/ext3_jbd.h>
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
+#include <linux/user_namespace.h>
 
 /*
  * balloc.c contains the blocks allocation and deallocation routines
@@ -1359,9 +1360,15 @@ static int ext3_has_free_blocks(struct e
 
        free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
        root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
-       if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
-               sbi->s_resuid != current->fsuid &&
-               (sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
+       if (free_blocks < root_blocks + 1) {
+               if (sbi->s_resuidns != task_user_ns(current))
+                       return 0;
+               if (capable(CAP_SYS_RESOURCE))
+                       return 1;
+               if (sbi->s_resuid == current->fsuid)
+                       return 1;
+               if (sbi->s_resgid != 0 && in_group_p (sbi->s_resgid))
+                       return 1;
                return 0;
        }
        return 1;
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index e45dbd6..eb31b83 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -23,6 +23,7 @@ #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
 #include <linux/random.h>
 #include <linux/bitops.h>
+#include <linux/user_namespace.h>
 
 #include <asm/byteorder.h>
 
@@ -133,6 +134,9 @@ void ext3_free_inode (handle_t *handle, 
        /* Do this BEFORE marking the inode not in use or returning an error */
        clear_inode (inode);
 
+       put_user_ns(inode->i_userns);
+       inode->i_userns = NULL;
+
        es = EXT3_SB(sb)->s_es;
        if (ino < EXT3_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
                ext3_error (sb, "ext3_free_inode",
@@ -547,6 +551,7 @@ got:
        sb->s_dirt = 1;
 
        inode->i_uid = current->fsuid;
+       inode->i_userns = get_task_user_ns(current);
        if (test_opt (sb, GRPID))
                inode->i_gid = dir->i_gid;
        else if (dir->i_mode & S_ISGID) {
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 535c5a5..2ec63bb 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -37,6 +37,7 @@ #include <linux/writeback.h>
 #include <linux/mpage.h>
 #include <linux/uio.h>
 #include <linux/bio.h>
+#include <linux/user_namespace.h>
 #include "xattr.h"
 #include "acl.h"
 
@@ -2667,6 +2668,7 @@ #endif
        inode->i_mode = le16_to_cpu(raw_inode->i_mode);
        inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
        inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
+       inode->i_userns = get_task_user_ns(current);
        if(!(test_opt (inode->i_sb, NO_UID32))) {
                inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
                inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index 9b8090d..6874367 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -15,6 +15,7 @@ #include <linux/ext3_jbd.h>
 #include <linux/time.h>
 #include <linux/compat.h>
 #include <linux/smp_lock.h>
+#include <linux/user_namespace.h>
 #include <asm/uaccess.h>
 
 int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
@@ -40,7 +41,8 @@ int ext3_ioctl (struct inode * inode, st
                if (IS_RDONLY(inode))
                        return -EROFS;
 
-               if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+               if (!task_inode_same_fsuid(current, inode) &&
+                               !task_ino_capable(inode, CAP_FOWNER))
                        return -EACCES;
 
                if (get_user(flags, (int __user *) arg))
@@ -62,7 +64,7 @@ int ext3_ioctl (struct inode * inode, st
                 * This test looks nicer. Thanks to Pauline Middelink
                 */
                if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) {
-                       if (!capable(CAP_LINUX_IMMUTABLE)) {
+                       if (!task_ino_capable(inode, CAP_LINUX_IMMUTABLE)) {
                                mutex_unlock(&inode->i_mutex);
                                return -EPERM;
                        }
@@ -73,7 +75,7 @@ int ext3_ioctl (struct inode * inode, st
                 * the relevant capability.
                 */
                if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) {
-                       if (!capable(CAP_SYS_RESOURCE)) {
+                       if (!task_ino_capable(inode, CAP_SYS_RESOURCE)) {
                                mutex_unlock(&inode->i_mutex);
                                return -EPERM;
                        }
@@ -121,7 +123,8 @@ flags_err:
                __u32 generation;
                int err;
 
-               if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+               if (!task_inode_same_fsuid(current, inode) &&
+                               !task_ino_capable(inode, CAP_FOWNER))
                        return -EPERM;
                if (IS_RDONLY(inode))
                        return -EROFS;
@@ -180,7 +183,8 @@ #endif
                if (IS_RDONLY(inode))
                        return -EROFS;
 
-               if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+               if (!task_inode_same_fsuid(current, inode) &&
+                               !task_ino_capable(inode, CAP_FOWNER))
                        return -EACCES;
 
                if (get_user(rsv_window_size, (int __user *)arg))
@@ -209,7 +213,7 @@ #endif
                struct super_block *sb = inode->i_sb;
                int err;
 
-               if (!capable(CAP_SYS_RESOURCE))
+               if (!task_ino_capable(inode, CAP_SYS_RESOURCE))
                        return -EPERM;
 
                if (IS_RDONLY(inode))
@@ -230,7 +234,7 @@ #endif
                struct super_block *sb = inode->i_sb;
                int err;
 
-               if (!capable(CAP_SYS_RESOURCE))
+               if (!task_ino_capable(inode, CAP_SYS_RESOURCE))
                        return -EPERM;
 
                if (IS_RDONLY(inode))
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 80dfa27..19e32ee 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -35,6 +35,7 @@ #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/quotaops.h>
 #include <linux/seq_file.h>
+#include <linux/user_namespace.h>
 
 #include <asm/uaccess.h>
 
@@ -403,6 +404,7 @@ static void ext3_put_super (struct super
        for (i = 0; i < sbi->s_gdb_count; i++)
                brelse(sbi->s_group_desc[i]);
        kfree(sbi->s_group_desc);
+       put_user_ns(sbi->s_resuidns);
        percpu_counter_destroy(&sbi->s_freeblocks_counter);
        percpu_counter_destroy(&sbi->s_freeinodes_counter);
        percpu_counter_destroy(&sbi->s_dirs_counter);
@@ -1417,6 +1419,7 @@ static int ext3_fill_super (struct super
        sbi->s_mount_opt = 0;
        sbi->s_resuid = EXT3_DEF_RESUID;
        sbi->s_resgid = EXT3_DEF_RESGID;
+       sbi->s_resuidns = get_task_user_ns(current);
 
        unlock_kernel();
 
@@ -1825,6 +1828,7 @@ #endif
        brelse(bh);
 out_fail:
        sb->s_fs_info = NULL;
+       put_user_ns(sbi->s_resuidns);
        kfree(sbi);
        lock_kernel();
        return -EINVAL;
diff --git a/fs/ext3/xattr_trusted.c b/fs/ext3/xattr_trusted.c
index 86d91f1..d37bfdd 100644
--- a/fs/ext3/xattr_trusted.c
+++ b/fs/ext3/xattr_trusted.c
@@ -12,6 +12,7 @@ #include <linux/fs.h>
 #include <linux/smp_lock.h>
 #include <linux/ext3_jbd.h>
 #include <linux/ext3_fs.h>
+#include <linux/user_namespace.h>
 #include "xattr.h"
 
 #define XATTR_TRUSTED_PREFIX "trusted."
@@ -23,7 +24,7 @@ ext3_xattr_trusted_list(struct inode *in
        const size_t prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1;
        const size_t total_len = prefix_len + name_len + 1;
 
-       if (!capable(CAP_SYS_ADMIN))
+       if (!task_ino_capable(inode, CAP_SYS_ADMIN))
                return 0;
 
        if (list && total_len <= list_size) {
diff --git a/include/linux/ext3_fs_sb.h b/include/linux/ext3_fs_sb.h
index f61309c..2a68a21 100644
--- a/include/linux/ext3_fs_sb.h
+++ b/include/linux/ext3_fs_sb.h
@@ -44,6 +44,7 @@ struct ext3_sb_info {
        unsigned long  s_mount_opt;
        uid_t s_resuid;
        gid_t s_resgid;
+       struct user_namespace *s_resuidns;
        unsigned short s_mount_state;
        unsigned short s_pad;
        int s_addr_per_block_bits;
-- 
1.3.2

_______________________________________________
Devel mailing list
[email protected]
https://openvz.org/mailman/listinfo/devel

Reply via email to