Received: by 10.223.164.202 with SMTP id h10csp5957570wrb; Tue, 21 Nov 2017 19:25:02 -0800 (PST) X-Google-Smtp-Source: AGs4zMZNFtVRlgZXs6YK098LQUXVTjIAQSne4WbnRye0egV0xSYXfkKCFkAydbnmBLZV0yXlg+Ni X-Received: by 10.101.81.202 with SMTP id i10mr768903pgq.23.1511321102715; Tue, 21 Nov 2017 19:25:02 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1511321102; cv=none; d=google.com; s=arc-20160816; b=w3pieXibtfrYvuukKuamfPWbmgG4Gk9/FNZmTkrR6i5dtN7YMZAMoKneYQrG4OwmhI OjkOEEQums3b+r6fidT18ijp7R0NMVXTcAUQ0HqLEvTHlG2gZMlZTHyHlfOtPRa9mkSd oSf88k8qP9evT3wu8vZtEaVX4Zk+HPTw+5lnQsa8L30QNE9uf/4t0XJnLjw7o8MDIvzP zsREzfDToVeYKwYrQt9GCuV/vwpWaPbjb0B19bUymrL/wJu6Xz/5ZkUrhieFJMfO6CMO +hb030FUrqehove21y57PZpPKADtd2+slxJ+wf5MWsGgzCBOL0o1amOjhKG3lldin0E9 C+7A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=gB9mGZN+sLSbGig4NXS4etESK8lXN8AirxMgbOXoGc4=; b=1KTffNexKzI45YxeOskIHQudG/aYZlfhIlO5g28vIUNLRKQwV2zXsg5NSdRfnwrj65 ypr+u7XwMEo3LekTtRpNOVzOVfLeL5VZusJ6ftCwrf0eBFvtB4F0Aklmg5Kmr2Nw+2nx eyFzbj89x5vsbltqmKTyBI9cTYSXre+5mlT9JrtGudeKo8CNDtHf/q8UsqOuCYqbOkpP jlvdMvNlcWsVzUZj5CJxoInwkPkbRHO8Oo1kNEpOwWgmIuzkBRUhP4bKxEtnM8AxHpp3 12QIoFgr9JaHIhn/xT6Jp3SPSZ4E0bJuK1xtGFROjSQTC2Y3JAInnAZfLJpCva16fBjD 1IQg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n9si12151931pgf.425.2017.11.21.19.24.51; Tue, 21 Nov 2017 19:25:02 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751893AbdKVDYB (ORCPT + 76 others); Tue, 21 Nov 2017 22:24:01 -0500 Received: from mail.cn.fujitsu.com ([183.91.158.132]:36868 "EHLO heian.cn.fujitsu.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751770AbdKVDX7 (ORCPT ); Tue, 21 Nov 2017 22:23:59 -0500 X-IronPort-AV: E=Sophos;i="5.43,368,1503331200"; d="scan'208";a="30360602" Received: from bogon (HELO cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 22 Nov 2017 11:23:57 +0800 Received: from G08CNEXCHPEKD03.g08.fujitsu.local (unknown [10.167.33.85]) by cn.fujitsu.com (Postfix) with ESMTP id 36EA0487F162; Wed, 22 Nov 2017 11:23:54 +0800 (CST) Received: from localhost.localdomain (10.167.226.73) by G08CNEXCHPEKD03.g08.fujitsu.local (10.167.33.89) with Microsoft SMTP Server (TLS) id 14.3.361.1; Wed, 22 Nov 2017 11:23:53 +0800 From: Cao Shufeng To: CC: , , , , , , , , , Subject: [PATCH_v4.1 2/3] Limit dump_pipe program's permission to init for container Date: Wed, 22 Nov 2017 11:24:17 +0800 Message-ID: <1511321058-6089-3-git-send-email-caosf.fnst@cn.fujitsu.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1511321058-6089-1-git-send-email-caosf.fnst@cn.fujitsu.com> References: <1501655849-9149-1-git-send-email-caosf.fnst@cn.fujitsu.com> <1511321058-6089-1-git-send-email-caosf.fnst@cn.fujitsu.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.167.226.73] X-yoursite-MailScanner-ID: 36EA0487F162.ABBF4 X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: caosf.fnst@cn.fujitsu.com X-Spam-Status: No Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Currently when we set core_pattern to a pipe, the pipe program is forked by kthread running with root's permission, and write dumpfile into host's filesystem. Same thing happened for container, the dumper and dumpfile are also in host(not in container). It have following program: 1: Not consistent with file_type core_pattern When we set core_pattern to a file, the container will write dump into container's filesystem instead of host. 2: Not safe for privileged container In a privileged container, user can destroy host system by following command: # # In a container # echo "|/bin/dd of=/boot/vmlinuz" >/proc/sys/kernel/core_pattern # make_dump This patch switch dumper program's environment to init task, so, for container, dumper program have same environment with init task in container, which make dumper program put in container's filesystem, and write coredump into container's filesystem. The dumper's permission is also limited into subset of container's init process. Suggested-by: Eric W. Biederman Suggested-by: KOSAKI Motohiro Signed-off-by: Cao ShuFeng --- fs/coredump.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++- include/linux/binfmts.h | 2 + 2 files changed, 126 insertions(+), 2 deletions(-) diff --git a/fs/coredump.c b/fs/coredump.c index 84c2b8a..41448bd 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -508,6 +508,45 @@ static void wait_for_dump_helpers(struct file *file) } /* + * umh_ns_setup + * set the namesapces to the bask task of a container. + * we need to switch back to the original namespaces + * so that the thread of workqueue is not influlenced. + * + * this method runs in workqueue kernel thread. + */ +static void umh_ns_setup(struct subprocess_info *info) +{ + struct coredump_params *cp = (struct coredump_params *)info->data; + struct task_struct *base_task = cp->base_task; + + if (base_task) { + cp->current_task_nsproxy = current->nsproxy; + //prevent current namespace from being freed + get_nsproxy(current->nsproxy); + /* Set namespaces to base_task */ + get_nsproxy(base_task->nsproxy); + switch_task_namespaces(current, base_task->nsproxy); + } +} + +/* + * umh_ns_cleanup + * cleanup what we have done in umh_ns_setup. + * + * this method runs in workqueue kernel thread. + */ +static void umh_ns_cleanup(struct subprocess_info *info) +{ + struct coredump_params *cp = (struct coredump_params *)info->data; + struct nsproxy *current_task_nsproxy = cp->current_task_nsproxy; + if (current_task_nsproxy) { + /* switch workqueue's original namespace back */ + switch_task_namespaces(current, current_task_nsproxy); + } +} + +/* * umh_pipe_setup * helper function to customize the process used * to collect the core in userspace. Specifically @@ -522,6 +561,8 @@ static int umh_pipe_setup(struct subprocess_info *info, struct cred *new) { struct file *files[2]; struct coredump_params *cp = (struct coredump_params *)info->data; + struct task_struct *base_task; + int err = create_pipe_files(files, 0); if (err) return err; @@ -530,10 +571,76 @@ static int umh_pipe_setup(struct subprocess_info *info, struct cred *new) err = replace_fd(0, files[0], 0); fput(files[0]); + if (err) + return err; + /* and disallow core files too */ current->signal->rlim[RLIMIT_CORE] = (struct rlimit){1, 1}; - return err; + base_task = cp->base_task; + if (base_task) { + const struct cred *base_cred; + + /* Set fs_root to base_task */ + spin_lock(&base_task->fs->lock); + set_fs_root(current->fs, &base_task->fs->root); + set_fs_pwd(current->fs, &base_task->fs->pwd); + spin_unlock(&base_task->fs->lock); + + /* Set cgroup to base_task */ + current->flags &= ~PF_NO_SETAFFINITY; + err = cgroup_attach_task_all(base_task, current); + if (err < 0) + return err; + + /* Set cred to base_task */ + base_cred = get_task_cred(base_task); + + new->uid = base_cred->uid; + new->gid = base_cred->gid; + new->suid = base_cred->suid; + new->sgid = base_cred->sgid; + new->euid = base_cred->euid; + new->egid = base_cred->egid; + new->fsuid = base_cred->fsuid; + new->fsgid = base_cred->fsgid; + + new->securebits = base_cred->securebits; + + new->cap_inheritable = base_cred->cap_inheritable; + new->cap_permitted = base_cred->cap_permitted; + new->cap_effective = base_cred->cap_effective; + new->cap_bset = base_cred->cap_bset; + new->cap_ambient = base_cred->cap_ambient; + + security_cred_free(new); +#ifdef CONFIG_SECURITY + new->security = NULL; +#endif + err = security_prepare_creds(new, base_cred, GFP_KERNEL); + if (err < 0) { + put_cred(base_cred); + return err; + } + + free_uid(new->user); + new->user = base_cred->user; + get_uid(new->user); + + put_user_ns(new->user_ns); + new->user_ns = base_cred->user_ns; + get_user_ns(new->user_ns); + + put_group_info(new->group_info); + new->group_info = base_cred->group_info; + get_group_info(new->group_info); + + put_cred(base_cred); + + validate_creds(new); + } + + return 0; } void do_coredump(const siginfo_t *siginfo) @@ -596,6 +703,7 @@ void do_coredump(const siginfo_t *siginfo) if (ispipe) { int dump_count; + struct task_struct *vinit_task; char **helper_argv; struct subprocess_info *sub_info; @@ -637,6 +745,15 @@ void do_coredump(const siginfo_t *siginfo) goto fail_dropcount; } + rcu_read_lock(); + vinit_task = find_task_by_vpid(1); + rcu_read_unlock(); + if (!vinit_task) { + printk(KERN_WARNING "failed getting init task info, skipping core dump\n"); + goto fail_dropcount; + } + + helper_argv = argv_split(GFP_KERNEL, cn.corename, NULL); if (!helper_argv) { printk(KERN_WARNING "%s failed to allocate memory\n", @@ -644,15 +761,20 @@ void do_coredump(const siginfo_t *siginfo) goto fail_dropcount; } + get_task_struct(vinit_task); + + cprm.base_task = vinit_task; + retval = -ENOMEM; sub_info = call_usermodehelper_setup(helper_argv[0], helper_argv, NULL, GFP_KERNEL, - NULL, NULL, umh_pipe_setup, + umh_ns_setup, umh_ns_cleanup, umh_pipe_setup, NULL, &cprm); if (sub_info) retval = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC); + put_task_struct(vinit_task); argv_free(helper_argv); if (retval) { printk(KERN_INFO "Core dump to |%s pipe failed\n", diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index b0abe21..e69d5e5 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -76,6 +76,8 @@ struct linux_binprm { /* Function parameter for binfmt->coredump */ struct coredump_params { + struct task_struct *base_task; + struct nsproxy *current_task_nsproxy; const siginfo_t *siginfo; struct pt_regs *regs; struct file *file; -- 2.1.0 From 1574600328539219777@xxx Wed Aug 02 06:38:11 +0000 2017 X-GM-THRID: 1574600328539219777 X-Gmail-Labels: Inbox,Category Forums