From: Konstantin Khlebnikov <khlebni...@openvz.org>

This patch patch adds lightweight virualization for sysctl entries:

                with S_ISVTX    without S_ISVTX
init_pid_ns     read-write      read-write
container       read-write      read-only

https://jira.sw.ru/browse/PSBM-18022

Signed-off-by: Konstantin Khlebnikov <khlebni...@openvz.org>

+++
VE/PROC/SYSCTL: show real permissions in stat

This patch calls ->permissions() callback from ->getattr() method,
as result stat() for proc entries in /proc/sys will show real permissions.
Also this patch hides sticky-bit (S_ISVTX).

Signed-off-by: Konstantin Khlebnikov <khlebni...@openvz.org>

+++
ve/fs: Fix invalid dereference in proc_sys_getattr()

grab_header() may return -ENOENT. In this case root in the below

        struct ctl_table_header *head = grab_header(inode);
        struct ctl_table_root *root = head->root;

dereferences (void *)-ENOENT, that leads to page fault and crash.
Fix that.

https://jira.sw.ru/browse/PSBM-56704

Signed-off-by: Kirill Tkhai <ktk...@virtuozzo.com>

mFixes (to merge): ac555dd ("VE/PROC/SYSCTL: show real permissions in stat")
+ hunk from 95c9cb3 ("SYSCTL: fix compilation")

+++
VE: use ve environtment for sysctl restrictions

https://jira.sw.ru/browse/PSBM-18032
https://jira.sw.ru/browse/PSBM-18030

Signed-off-by: Konstantin Khlebnikov <khlebni...@openvz.org>

(cherry picked from commit 57c6f66050d2176f8a9847f8284cb3d345863a88)
Signed-off-by: Konstantin Khorenko <khore...@virtuozzo.com>

Moving root variable to make proc_sys_getattr code more solid.
Note: sysctl_root_permissions check does not affect /proc/sys/user
/proc/sys/net sysctls, they have their own ->permissions handlers.

(cherry picked from vz8 commit bdc26f95dd3371b8b80fa943215065e0836f7fb5)
Signed-off-by: Pavel Tikhomirov <ptikhomi...@virtuozzo.com>
---
 fs/proc/proc_sysctl.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 5d66faecd4ef..f6415add610e 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -11,6 +11,7 @@
 #include <linux/sched.h>
 #include <linux/cred.h>
 #include <linux/namei.h>
+#include <linux/nsproxy.h>
 #include <linux/mm.h>
 #include <linux/uio.h>
 #include <linux/module.h>
@@ -66,6 +67,16 @@ static struct ctl_table root_table[] = {
        },
        { }
 };
+
+static int sysctl_root_permissions(struct ctl_table_header *head,
+               struct ctl_table *table)
+{
+       if (ve_is_super(get_exec_env()) || (table->mode & S_ISVTX))
+               return table->mode;
+
+       return table->mode & ~S_IWUGO;
+}
+
 static struct ctl_table_root sysctl_table_root = {
        .default_set.dir.header = {
                {{.count = 1,
@@ -75,6 +86,7 @@ static struct ctl_table_root sysctl_table_root = {
                .root = &sysctl_table_root,
                .set = &sysctl_table_root.default_set,
        },
+       .permissions = sysctl_root_permissions,
 };
 
 static DEFINE_SPINLOCK(sysctl_lock);
@@ -452,7 +464,7 @@ static struct inode *proc_sys_make_inode(struct super_block 
*sb,
        spin_unlock(&sysctl_lock);
 
        inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
-       inode->i_mode = table->mode;
+       inode->i_mode = table->mode & S_IRWXUGO;
        if (!S_ISDIR(table->mode)) {
                inode->i_mode |= S_IFREG;
                inode->i_op = &proc_sys_inode_operations;
@@ -839,8 +851,16 @@ static int proc_sys_getattr(struct user_namespace 
*mnt_userns,
                return PTR_ERR(head);
 
        generic_fillattr(&init_user_ns, inode, stat);
-       if (table)
-               stat->mode = (stat->mode & S_IFMT) | table->mode;
+
+       if (table) {
+               struct ctl_table_root *root = head->root;
+               umode_t mode = table->mode;
+
+               if (root->permissions)
+                       mode = root->permissions(head, table);
+
+               stat->mode = (stat->mode & S_IFMT) | (mode & S_IRWXUGO);
+       }
 
        sysctl_head_finish(head);
        return 0;
@@ -1135,11 +1155,13 @@ static int sysctl_check_table(const char *path, struct 
ctl_table *table)
                                err |= sysctl_err(path, table, "No maxlen");
                        else
                                err |= sysctl_check_table_array(path, table);
+                       if (table->mode & S_ISVTX)
+                               err |= sysctl_err(path, table, "Unsafe v12n");
                }
                if (!table->proc_handler)
                        err |= sysctl_err(path, table, "No proc_handler");
 
-               if ((table->mode & (S_IRUGO|S_IWUGO)) != table->mode)
+               if ((table->mode & (S_IRUGO|S_IWUGO|S_ISVTX)) != table->mode)
                        err |= sysctl_err(path, table, "bogus .mode 0%o",
                                table->mode);
        }
-- 
2.31.1

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to