[Devel] [PATCH vz8 v4 2/5] trusted/ve/fs/exec: Don't allow a privileged user to execute untrusted files

Konstantin Khorenko khorenko at virtuozzo.com
Tue Jun 8 14:40:50 MSK 2021


From: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>

If we run some binary (exploit) from CT on host, it can easily give a
user in these CT an ability to do anything on host sending commands
through unix socket to the exploit. Such an exploit can mimic to bash,
ip, systemd, ping or some other "trusted" utility.

I've tested with these patch that we don't call from VE0 any binaries
from CT-fs on start, stop, enter, suspend, resume or migration. But to
be on the safe side, so that in future we don't become affected, lets
prohibit running any binary from ploop disks and from CT mounts if the
caller is from VE0.

Also we protect admins of our customer from unintentionally calling such
an exploit:

[root at kuchy ~]# strace -e trace=execve /vz/root/58a2c524-b486-42c8-849\
  b-c659bf165a91/bin/ls
execve("/vz/root/58a2c524-b486-42c8-849b-c659bf165a91/bin/ls",\
  ["/vz/root/58a2c524-b486-42c8-849b"...], [/* 27 vars */]) = -1\
  EACCES (Permission denied)
strace: exec: Permission denied
+++ exited with 1 +++

We need same check in sys_uselib as process from host can also try to
load shared library from the file in CT's ploop, which cannot be trusted
too.

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

Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
Acked-by: Konstantin Khorenko <khorenko at virtuozzo.com>

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

Based on vz7 commit 29154b5e5af9 ("ve/fs/exec: don't allow a privileged
user to execute untrusted files")

Signed-off-by: Valeriy Vdovin <valeriy.vdovin at virtuozzo.com>
Reviewed-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
Reviewed-by: Konstantin Khorenko <khorenko at virtuozzo.com>

khorenko@: the patch does not cover the case of execution a binary from
a mount done from inside a Container. TODO
---
 fs/exec.c          | 16 ++++++++++++++--
 include/linux/ve.h |  1 +
 kernel/ve/ve.c     | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index c036db0323e0..0f4c741e19db 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -62,6 +62,7 @@
 #include <linux/oom.h>
 #include <linux/compat.h>
 #include <linux/vmalloc.h>
+#include <linux/ve.h>
 
 #include <linux/uaccess.h>
 #include <asm/mmu_context.h>
@@ -134,10 +135,9 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
 		goto out;
 
 	file = do_filp_open(AT_FDCWD, tmp, &uselib_flags);
-	putname(tmp);
 	error = PTR_ERR(file);
 	if (IS_ERR(file))
-		goto out;
+		goto put;
 
 	error = -EINVAL;
 	if (!S_ISREG(file_inode(file)->i_mode))
@@ -147,6 +147,12 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
 	if (path_noexec(&file->f_path))
 		goto exit;
 
+	if (!ve_check_trusted_exec(file, tmp))
+		goto exit;
+
+	putname(tmp);
+	tmp = NULL;
+
 	fsnotify_open(file);
 
 	error = -ENOEXEC;
@@ -167,6 +173,9 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
 	read_unlock(&binfmt_lock);
 exit:
 	fput(file);
+put:
+	if (tmp)
+		putname(tmp);
 out:
   	return error;
 }
@@ -861,6 +870,9 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
 	if (path_noexec(&file->f_path))
 		goto exit;
 
+	if (!ve_check_trusted_exec(file, name))
+		goto exit;
+
 	err = deny_write_access(file);
 	if (err)
 		goto exit;
diff --git a/include/linux/ve.h b/include/linux/ve.h
index 9c553ac96072..edf4e95d97e7 100644
--- a/include/linux/ve.h
+++ b/include/linux/ve.h
@@ -162,6 +162,7 @@ extern void put_ve(struct ve_struct *ve);
 
 void ve_stop_ns(struct pid_namespace *ns);
 void ve_exit_ns(struct pid_namespace *ns);
+bool ve_check_trusted_exec(struct file *file, struct filename *name);
 
 #ifdef CONFIG_TTY
 #define MAX_NR_VTTY_CONSOLES	(12)
diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c
index 12e91e6ee1a1..1635a08f4dd1 100644
--- a/kernel/ve/ve.c
+++ b/kernel/ve/ve.c
@@ -28,6 +28,7 @@
 #include <linux/task_work.h>
 #include <linux/ctype.h>
 #include <linux/tty.h>
+#include <linux/genhd.h>
 
 #include <uapi/linux/vzcalluser.h>
 #include <net/rtnetlink.h>
@@ -1781,6 +1782,38 @@ static int __init ve_subsys_init(void)
 }
 late_initcall(ve_subsys_init);
 
+static bool ve_check_trusted_file(struct file *file)
+{
+	struct block_device *bdev = file->f_inode->i_sb->s_bdev;
+	bool exec_from_ct = !ve_is_super(get_exec_env());
+	bool file_on_trusted_disk = true;
+
+	if (exec_from_ct)
+		return true;
+
+	if (bdev && bdev->bd_disk)
+		file_on_trusted_disk = bdev->bd_disk->vz_trusted_exec;
+
+	if (file_on_trusted_disk)
+		return true;
+
+	return false;
+}
+
+/*
+ * We don't want a VE0-privileged user intentionally or by mistake
+ * to execute files of container, these files are untrusted.
+ */
+bool ve_check_trusted_exec(struct file *file, struct filename *name)
+{
+	if (ve_check_trusted_file(file))
+		return true;
+
+	WARN_ONCE(1, "VE0's %s tried to execute untrusted file %s from VEX\n",
+		     current->comm, name->name);
+	return false;
+}
+
 #ifdef CONFIG_CGROUP_SCHED
 int cpu_cgroup_proc_stat(struct cgroup_subsys_state *cpu_css,
 			 struct cgroup_subsys_state *cpuacct_css,
-- 
2.28.0



More information about the Devel mailing list