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

Valeriy Vdovin valeriy.vdovin at virtuozzo.com
Wed Jun 9 11:50:59 MSK 2021


On Tue, Jun 08, 2021 at 07:31:27PM +0300, Konstantin Khorenko wrote:
> 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>
> ---
>  fs/exec.c          | 16 ++++++++++++++--
>  include/linux/ve.h |  1 +
>  kernel/ve/ve.c     | 47 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 62 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..6594772a10dd 100644
> --- a/kernel/ve/ve.c
> +++ b/kernel/ve/ve.c
> @@ -28,10 +28,12 @@
>  #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>
>  
> +#include "../fs/mount.h"
>  #include "../cgroup/cgroup-internal.h" /* For cgroup_task_count() */
>  
>  struct per_cgroot_data {
> @@ -1781,6 +1783,51 @@ 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;
> +	bool exec_from_ct;
> +	bool file_on_host_mount;
> +
> +	/* The current process does not belong to ve0. */
> +	exec_from_ct = !ve_is_super(get_exec_env());
> +	if (exec_from_ct)
> +		return true;
> +
> +	/* The current process belongs to ve0. */
> +	bdev = file->f_inode->i_sb->s_bdev;
> +	if (bdev) {
> +		/* The file to execute is stored on trusted block device. */
> +		if (bdev->bd_disk->vz_trusted_exec)
> +			return true;
> +	} else {
> +		/*
> +		 * bdev can be NULL if the file is on tmpfs, for example.
> +		 * If this is a host's tmpfs - execution is allowed.
> +		 */
> +		file_on_host_mount = ve_is_super(
> +				     real_mount(file->f_path.mnt)->ve_owner);
> +		if (file_on_host_mount)
> +			return true;
> +	}
> +
> +	return false;
> +}

I've tested this version of ve_check_trusted_file, it works great.
Lets commit it that way.
> +
> +/*
> + * 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