Received: by 2002:ac0:e350:0:0:0:0:0 with SMTP id g16csp2118028imn; Mon, 1 Aug 2022 11:46:11 -0700 (PDT) X-Google-Smtp-Source: AGRyM1tXzM9LRDRyV1JchliabMFvh31Wg5D2ZtG2yGOcC/k5cH5VSEQHEfxodub+GBewwmzBoNZs X-Received: by 2002:a05:6a00:1248:b0:52b:ca7:f2b6 with SMTP id u8-20020a056a00124800b0052b0ca7f2b6mr17545510pfi.82.1659379571327; Mon, 01 Aug 2022 11:46:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1659379571; cv=none; d=google.com; s=arc-20160816; b=OrgbHFrQ8aGGM5Qb9+QisOcjmzErXjkKZFno6DTqjsgcnNGvzXpiEtY7JvLk5IyvfJ w3wprhELEVY9mJLL86a0TmauhuPk+iRRG8TEbVIHpX9xrVy+sdgoBKNGFxAIqfpiAryl Z4YjRC8XBqV+6xksdDnmd2TDPGJvQvh+E7lARq9284Sqd8FF4DscTMhkhUq/Kbkem9ZZ ZYvaC953F9rmGoIoVMuIDnQ2cMzrFxcxD4g/bM8uklGCCu2lj5dQB8fMrUsR06ukSW+7 hy6nabjQnTf1RCmkN/tmClwIvI0pFzB5mzbwnhhlfdGchdv+2anX52ZCuW1FCL7jkQwi 17mg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=qEASjFQgHEXoxjCsMlwe3mWZuEgE+ke0lwJ4HSwmC1o=; b=L5Ltk51VFUadsaz+IZ7IyxgLoJCZ2hBfPFEsdNeiThFxe9P/5Gf521uYW3dd9WAnVK CLv0m4SzZCcjwZE98HyBM1FNr+s4o8bFhUWxMTNMmPf2EKtADMhxJ9l4CP0HxNv8zr5H 88AEbVRYsUDfM4sXtW+P5bvP3fDrSD27/lMEQmxQtLtoudIqDGkLnUnoM8TMJimebOju qTf4gzFzrnxeyeC4E3mbjnty/rJ3C+DNdaMoJDp5u9k/ZJ9yzmMm5RBchUSPO5Qn0iCF DE9+CLg+nYdcaNszvRPhO0s67fIBzWJ/h50a354WCSiYKSkZ7pHLtH21AV3n19IBFstz dHuQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cloudflare.com header.s=google header.b=IfFAjRq+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cloudflare.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id p14-20020a635b0e000000b0041a4a97d588si13063248pgb.588.2022.08.01.11.45.54; Mon, 01 Aug 2022 11:46:11 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@cloudflare.com header.s=google header.b=IfFAjRq+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cloudflare.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233869AbiHASCY (ORCPT + 99 others); Mon, 1 Aug 2022 14:02:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42048 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232577AbiHASCU (ORCPT ); Mon, 1 Aug 2022 14:02:20 -0400 Received: from mail-oa1-x33.google.com (mail-oa1-x33.google.com [IPv6:2001:4860:4864:20::33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C715427B19 for ; Mon, 1 Aug 2022 11:02:17 -0700 (PDT) Received: by mail-oa1-x33.google.com with SMTP id 586e51a60fabf-10e615a36b0so13045593fac.1 for ; Mon, 01 Aug 2022 11:02:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=qEASjFQgHEXoxjCsMlwe3mWZuEgE+ke0lwJ4HSwmC1o=; b=IfFAjRq+tt0+0QkOil6iDkdm5PR1dhXxMMxF03kiwCYv+F35KXZll/Aos3m0bfnTPi ovfmDfsxJ2/RIRYdW+e+N27wxkP57PDcj+IKBbsr/h0smuJR0MFpmf3MmZUA0r9ow4fk 1RWQ/JoDadNY0VcpELObOrpway7EKWAzd/7Us= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=qEASjFQgHEXoxjCsMlwe3mWZuEgE+ke0lwJ4HSwmC1o=; b=7gVZgo0ROZwJzgK8DaDYoSZBqLWRNebNYqkP9MJh28kyMhMQoadfXG6uv9kkvMYvpH h1Ev4n05fRi7Sxl7T0DyqxwfI+xRVB8ViFMzs6UV6V/bqrbdV9XThTgX2LfXxMOVw81Y 5FAXhmMepC7uuKt0IGIiqSNArCaBDSSXuvcSuJt80EbN5cDnWSq/LxcIA0indMw46pWs YEJsEVyxlkxRQCfTGAk0JYatRBJp3OYMGgE7aWQDzowYr6mJsufpor/vUH9F+hauK5l2 oaW/NJXxB+ivPFrbZYXJr15I/aAUIUZsEXlZH8K4X5TSnGEymP+boxJ5tD431+R/C8bm dsSg== X-Gm-Message-State: AJIora/2xiv+wHFmCIJBlz/TTJO/OeBHSr51Jld6nI5XYnVV73skkZJg MUWwBHIoCqczxkZG79dqasLl8g== X-Received: by 2002:a05:6870:d59c:b0:101:7e59:d723 with SMTP id u28-20020a056870d59c00b001017e59d723mr8156224oao.165.1659376936978; Mon, 01 Aug 2022 11:02:16 -0700 (PDT) Received: from localhost.localdomain ([184.4.90.121]) by smtp.gmail.com with ESMTPSA id n14-20020a9d64ce000000b00618fa37308csm2881348otl.35.2022.08.01.11.02.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 01 Aug 2022 11:02:16 -0700 (PDT) From: Frederick Lawler To: kpsingh@kernel.org, revest@chromium.org, jackmanb@chromium.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, kafai@fb.com, songliubraving@fb.com, yhs@fb.com, john.fastabend@gmail.com, jmorris@namei.org, serge@hallyn.com, paul@paul-moore.com, stephen.smalley.work@gmail.com, eparis@parisplace.org, shuah@kernel.org, brauner@kernel.org, casey@schaufler-ca.com, ebiederm@xmission.com, bpf@vger.kernel.org, linux-security-module@vger.kernel.org, selinux@vger.kernel.org, linux-kselftest@vger.kernel.org Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, kernel-team@cloudflare.com, cgzones@googlemail.com, karl@bigbadwolfsecurity.com, Frederick Lawler Subject: [PATCH v4 1/4] security, lsm: Introduce security_create_user_ns() Date: Mon, 1 Aug 2022 13:01:43 -0500 Message-Id: <20220801180146.1157914-2-fred@cloudflare.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220801180146.1157914-1-fred@cloudflare.com> References: <20220801180146.1157914-1-fred@cloudflare.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Preventing user namespace (privileged or otherwise) creation comes in a few of forms in order of granularity: 1. /proc/sys/user/max_user_namespaces sysctl 2. OS specific patch(es) 3. CONFIG_USER_NS To block a task based on its attributes, the LSM hook cred_prepare is a good candidate for use because it provides more granular control, and it is called before create_user_ns(): cred = prepare_creds() security_prepare_creds() call_int_hook(cred_prepare, ... if (cred) create_user_ns(cred) Since security_prepare_creds() is meant for LSMs to copy and prepare credentials, access control is an unintended use of the hook. Therefore introduce a new function security_create_user_ns() with an accompanying userns_create LSM hook. This hook takes the prepared creds for LSM authors to write policy against. On success, the new namespace is applied to credentials, otherwise an error is returned. Signed-off-by: Frederick Lawler Reviewed-by: Christian Brauner (Microsoft) --- Changes since v3: - No changes Changes since v2: - Rename create_user_ns hook to userns_create Changes since v1: - Changed commit wording - Moved execution to be after id mapping check - Changed signature to only accept a const struct cred * --- include/linux/lsm_hook_defs.h | 1 + include/linux/lsm_hooks.h | 4 ++++ include/linux/security.h | 6 ++++++ kernel/user_namespace.c | 5 +++++ security/security.c | 5 +++++ 5 files changed, 21 insertions(+) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index eafa1d2489fd..7ff93cb8ca8d 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -223,6 +223,7 @@ LSM_HOOK(int, -ENOSYS, task_prctl, int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) LSM_HOOK(void, LSM_RET_VOID, task_to_inode, struct task_struct *p, struct inode *inode) +LSM_HOOK(int, 0, userns_create, const struct cred *cred) LSM_HOOK(int, 0, ipc_permission, struct kern_ipc_perm *ipcp, short flag) LSM_HOOK(void, LSM_RET_VOID, ipc_getsecid, struct kern_ipc_perm *ipcp, u32 *secid) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 91c8146649f5..54fe534d0e01 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -799,6 +799,10 @@ * security attributes, e.g. for /proc/pid inodes. * @p contains the task_struct for the task. * @inode contains the inode structure for the inode. + * @userns_create: + * Check permission prior to creating a new user namespace. + * @cred points to prepared creds. + * Return 0 if successful, otherwise < 0 error code. * * Security hooks for Netlink messaging. * diff --git a/include/linux/security.h b/include/linux/security.h index 7fc4e9f49f54..a195bf33246a 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -435,6 +435,7 @@ int security_task_kill(struct task_struct *p, struct kernel_siginfo *info, int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5); void security_task_to_inode(struct task_struct *p, struct inode *inode); +int security_create_user_ns(const struct cred *cred); int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag); void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid); int security_msg_msg_alloc(struct msg_msg *msg); @@ -1185,6 +1186,11 @@ static inline int security_task_prctl(int option, unsigned long arg2, static inline void security_task_to_inode(struct task_struct *p, struct inode *inode) { } +static inline int security_create_user_ns(const struct cred *cred) +{ + return 0; +} + static inline int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag) { diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 5481ba44a8d6..3f464bbda0e9 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -113,6 +114,10 @@ int create_user_ns(struct cred *new) !kgid_has_mapping(parent_ns, group)) goto fail_dec; + ret = security_create_user_ns(new); + if (ret < 0) + goto fail_dec; + ret = -ENOMEM; ns = kmem_cache_zalloc(user_ns_cachep, GFP_KERNEL); if (!ns) diff --git a/security/security.c b/security/security.c index 188b8f782220..ec9b4696e86c 100644 --- a/security/security.c +++ b/security/security.c @@ -1903,6 +1903,11 @@ void security_task_to_inode(struct task_struct *p, struct inode *inode) call_void_hook(task_to_inode, p, inode); } +int security_create_user_ns(const struct cred *cred) +{ + return call_int_hook(userns_create, 0, cred); +} + int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag) { return call_int_hook(ipc_permission, 0, ipcp, flag); -- 2.30.2