[Devel] [PATCH RH9 01/16] ve/sysctl: write permission restriction
Pavel Tikhomirov
ptikhomirov at virtuozzo.com
Tue Sep 28 15:40:51 MSK 2021
From: Konstantin Khlebnikov <khlebnikov at 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 <khlebnikov at 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 <khlebnikov at 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 <ktkhai at 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 <khlebnikov at openvz.org>
(cherry picked from commit 57c6f66050d2176f8a9847f8284cb3d345863a88)
Signed-off-by: Konstantin Khorenko <khorenko at 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 <ptikhomirov at 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
More information about the Devel
mailing list