From nobody Fri Apr 17 22:31:35 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8C136C433EF for ; Thu, 21 Jul 2022 17:28:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231565AbiGUR2c (ORCPT ); Thu, 21 Jul 2022 13:28:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54242 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229915AbiGUR2S (ORCPT ); Thu, 21 Jul 2022 13:28:18 -0400 Received: from mail-oa1-x2e.google.com (mail-oa1-x2e.google.com [IPv6:2001:4860:4864:20::2e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2618789EB4 for ; Thu, 21 Jul 2022 10:28:17 -0700 (PDT) Received: by mail-oa1-x2e.google.com with SMTP id 586e51a60fabf-f2a4c51c45so3281097fac.9 for ; Thu, 21 Jul 2022 10:28:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=oSkp5XL8evSozcL3p6dp5pf7REvcEIJL7/dJNXUU/iU=; b=RTsFkn4w9Q+1HCvSArxhpw/M593UnODTkZBs5Hm875j+xZWAZK2wghDB3V5snivDg4 tzHaqxbKYm6pxwHgiND9geYCossCSEx8bRK0ORYhiwb1saYA/q0uDPWsU3k9njgcxZlw ScwEL0YCfwv6neSRlCeBxuwSJu1QYy7+NV1lc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=oSkp5XL8evSozcL3p6dp5pf7REvcEIJL7/dJNXUU/iU=; b=WXcBmLMrv33091vsx7OU/zSTTMrPKCAvlHAAulDmVygr1mpJOZE//U3AlkS1OuQODt JoYxi/WwOvIu3JiJscpa/uHNR8NEGjGBZ7i7ChPa2ZPJTMwZgqeZpIAC/jRGi7HldeOf 4CMfAlrIrTJ38fz2qt3pAbUs37tS0MeWakhySlGvKgifkTpMR/VLj/0pCBAYlPAFvz3V ITG5UlcK1rQcJnaZbpbA7YqsqeW0WzFd0H2qW6d7QbauTnUPLzqS5et2XYGvIBREdve5 VLANNoCUfKNxyHmisRiKO5+lk6aNDOEJiLlZD+OCPVHzVD5pIS+AunFWlwzvcqJlpwPl axkA== X-Gm-Message-State: AJIora+VOtRe0lVELdPZ/UXXaGwwxlqzsO+zvw6dQu33OWZvvLAAG7XO E58rbge2mu+aTvi7AxugNd8b1A== X-Google-Smtp-Source: AGRyM1vn8iYdneqMQSfU5E7rKtCDDTFXE6gJ/E+orOgcQYDydQBDRlFTXDgzTF2YYM6Rsw5HvyJSJg== X-Received: by 2002:a05:6870:c353:b0:101:e7e4:9388 with SMTP id e19-20020a056870c35300b00101e7e49388mr5620686oak.45.1658424496479; Thu, 21 Jul 2022 10:28:16 -0700 (PDT) Received: from localhost.localdomain ([184.4.90.121]) by smtp.gmail.com with ESMTPSA id du24-20020a0568703a1800b00101c83352c6sm1106207oab.34.2022.07.21.10.28.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Jul 2022 10:28: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 v3 1/4] security, lsm: Introduce security_create_user_ns() Date: Thu, 21 Jul 2022 12:28:05 -0500 Message-Id: <20220721172808.585539-2-fred@cloudflare.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220721172808.585539-1-fred@cloudflare.com> References: <20220721172808.585539-1-fred@cloudflare.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" 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 =3D 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) reviewed-by before accepting this.=20 --- 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 ke= rnel_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, un= signed long arg2, static inline void security_task_to_inode(struct task_struct *p, struct in= ode *inode) { } =20 +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; =20 + ret =3D security_create_user_ns(new); + if (ret < 0) + goto fail_dec; + ret =3D -ENOMEM; ns =3D 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, s= truct inode *inode) call_void_hook(task_to_inode, p, inode); } =20 +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); --=20 2.30.2 From nobody Fri Apr 17 22:31:35 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 448D0C43334 for ; Thu, 21 Jul 2022 17:28:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229507AbiGUR2n (ORCPT ); Thu, 21 Jul 2022 13:28:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54674 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231489AbiGUR22 (ORCPT ); Thu, 21 Jul 2022 13:28:28 -0400 Received: from mail-oa1-x34.google.com (mail-oa1-x34.google.com [IPv6:2001:4860:4864:20::34]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F183C8AEC7 for ; Thu, 21 Jul 2022 10:28:18 -0700 (PDT) Received: by mail-oa1-x34.google.com with SMTP id 586e51a60fabf-f2a4c51c45so3281205fac.9 for ; Thu, 21 Jul 2022 10:28:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=g6LYDJ5GUZQ1KxKmuQvjM8e+PjJ6MYTVNoyEg+XMI5E=; b=F39o6zdL20qsFmVOEom+uZ7fZ1c6R3EBwJRsLcWhmxXYO27c6yuW+TxLtfux5NlgDH irmniKptcO3EquVJiLXT4swrivgKEjFsVwhHaOVwvQVf4TU8rP/Px4s8VIliE+DPGanH T7MHIVfNsMtTbYomDDw28omIpxiFgcqexK0jY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=g6LYDJ5GUZQ1KxKmuQvjM8e+PjJ6MYTVNoyEg+XMI5E=; b=T2Xu7uknrZsXqN6jQgmMsyqOUsD+Rc/mI3rrYAFNFpTgqha92BEzU0W37ovJ+U/3v7 s0pk12RFaQeCWiZ2lhCcIEWNv6C6X99KrDZb+4Jnous7+hzx0WQovWsMqv2pw6EllZ/h OwED3z0bwwNYHiVXsF3KTWAham0clP4rHH7lyU4Qoic6Pyqpn/z4wPZhEn63zcWXejKk ctQ1w7/qqeCS03ABW+eyYwRoQ+etg5H7zi0vDeUTbuTP4w3htOFbojBo9aAIyeZxyHDe b0A0aAd0VSj9Pne415BbCRqfIJx++I29jzOBPx5tylILl9hIN9GeB638vkHwbNSI8Mgb 13fg== X-Gm-Message-State: AJIora+vIYLwiNDqh5x9b9Dn+jjUfGRxGneYP/jmujPxLc84lGNti1jS IGFNSizf92UvSZYviIfxGRQ4Og== X-Google-Smtp-Source: AGRyM1uMOCDd3dpPREZw9AxRpt6f809MJwj0HOOSGYMg4yruTLyaIlx1XyM20S/Pw+ozM4Rqwgc/dg== X-Received: by 2002:a05:6870:b398:b0:10d:67e:c615 with SMTP id w24-20020a056870b39800b0010d067ec615mr5426833oap.203.1658424498275; Thu, 21 Jul 2022 10:28:18 -0700 (PDT) Received: from localhost.localdomain ([184.4.90.121]) by smtp.gmail.com with ESMTPSA id du24-20020a0568703a1800b00101c83352c6sm1106207oab.34.2022.07.21.10.28.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Jul 2022 10:28:17 -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 v3 2/4] bpf-lsm: Make bpf_lsm_userns_create() sleepable Date: Thu, 21 Jul 2022 12:28:06 -0500 Message-Id: <20220721172808.585539-3-fred@cloudflare.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220721172808.585539-1-fred@cloudflare.com> References: <20220721172808.585539-1-fred@cloudflare.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Users may want to audit calls to security_create_user_ns() and access user space memory. Also create_user_ns() runs without pagefault_disabled(). Therefore, make bpf_lsm_userns_create() sleepable for mandatory access control policies. Signed-off-by: Frederick Lawler Acked-by: Christian Brauner (Microsoft) reviewed-by before accepting this.=20 --- Changes since v2: - Rename create_user_ns hook to userns_create Changes since v1: - None --- kernel/bpf/bpf_lsm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c index c1351df9f7ee..4593437809cc 100644 --- a/kernel/bpf/bpf_lsm.c +++ b/kernel/bpf/bpf_lsm.c @@ -250,6 +250,7 @@ BTF_ID(func, bpf_lsm_task_getsecid_obj) BTF_ID(func, bpf_lsm_task_prctl) BTF_ID(func, bpf_lsm_task_setscheduler) BTF_ID(func, bpf_lsm_task_to_inode) +BTF_ID(func, bpf_lsm_userns_create) BTF_SET_END(sleepable_lsm_hooks) =20 bool bpf_lsm_is_sleepable_hook(u32 btf_id) --=20 2.30.2 From nobody Fri Apr 17 22:31:35 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 788BEC433EF for ; Thu, 21 Jul 2022 17:28:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231955AbiGUR2t (ORCPT ); Thu, 21 Jul 2022 13:28:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54406 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229673AbiGUR2c (ORCPT ); Thu, 21 Jul 2022 13:28:32 -0400 Received: from mail-oa1-x2c.google.com (mail-oa1-x2c.google.com [IPv6:2001:4860:4864:20::2c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6E3598AEFF for ; Thu, 21 Jul 2022 10:28:20 -0700 (PDT) Received: by mail-oa1-x2c.google.com with SMTP id 586e51a60fabf-10d867a8358so3277033fac.10 for ; Thu, 21 Jul 2022 10:28:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=DDUrciOiWPS12pMfDzHR0QWKvrVADVqrg238UND6/6k=; b=PVCt8IkXNmzVX/uc6ya8bkYX0e9fl24bayGiIk1x14nKbBagTPU3Ptt2JJXdPMlO85 12cNDzBYSZCw8OtBNQqKKCEU4r2rcBnVENIXy4RF9NnywMQX5OvKHOols3UKsNfMscdm CaxupZgwvLbU5eQrXzoQ+7vBNCWXwhKr3KSVU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=DDUrciOiWPS12pMfDzHR0QWKvrVADVqrg238UND6/6k=; b=lLTTewSuGqkVKC5Ob56eoR506A0Y8kqJo1zkp0dyFz9pVQ5KINL+rNShw3g2URjAtP RyaeH+VoFJon+pj9HVl7d8fSdzqsUDDy1TQbHmdjm7czrqe+vDXGKMEJEDwKmolVAT8m eUcTmaQpYJ/m4AWQ/6idnHUvXb3RBdZ5H6MoWtwwuyQFTFaIURP7+SCTaWaVgtqD7IBD D7vrdELh76Gh2/eqUHDm5UWPNYH4yThhg8fd+lPigKbSCYMBOJPeryLf2oOV2pet4vBf c4m6h3w0BpdZ4DBqqxQUe7pmyiGNGE2EacHs98waZ8GUnsLnTlbHQJqbkAUXUOAzsqOz OQDw== X-Gm-Message-State: AJIora/JgZ27Cj0TnW/qTTfh0Y047bQkcv3objVZIYstzAbmq72FY8p9 btCFMQ5yQfzNXrHvYIFLjoNSgQ== X-Google-Smtp-Source: AGRyM1vxESDsPtIrONW7Ys2w4N7FenuuR8XS0fA2zPxLvr9jts48tPFbchJ6aya0gahguJLwVoCt9Q== X-Received: by 2002:a05:6870:c889:b0:10c:7f1:c6b8 with SMTP id er9-20020a056870c88900b0010c07f1c6b8mr5644044oab.280.1658424500003; Thu, 21 Jul 2022 10:28:20 -0700 (PDT) Received: from localhost.localdomain ([184.4.90.121]) by smtp.gmail.com with ESMTPSA id du24-20020a0568703a1800b00101c83352c6sm1106207oab.34.2022.07.21.10.28.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Jul 2022 10:28:19 -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 v3 3/4] selftests/bpf: Add tests verifying bpf lsm userns_create hook Date: Thu, 21 Jul 2022 12:28:07 -0500 Message-Id: <20220721172808.585539-4-fred@cloudflare.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220721172808.585539-1-fred@cloudflare.com> References: <20220721172808.585539-1-fred@cloudflare.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The LSM hook userns_create was introduced to provide LSM's an opportunity to block or allow unprivileged user namespace creation. This test serves two purposes: it provides a test eBPF implementation, and tests the hook successfully blocks or allows user namespace creation. This tests 4 cases: 1. Unattached bpf program does not block unpriv user namespace creation. 2. Attached bpf program allows user namespace creation given CAP_SYS_ADMIN privileges. 3. Attached bpf program denies user namespace creation for a user without CAP_SYS_ADMIN. 4. The sleepable implementation loads Signed-off-by: Frederick Lawler Acked-by: Christian Brauner (Microsoft) reviewed-by before accepting this.=20 --- The generic deny_namespace file name is used for future namespace expansion. I didn't want to limit these files to just the create_user_ns hook. Changes since v2: - Rename create_user_ns hook to userns_create Changes since v1: - Introduce this patch --- .../selftests/bpf/prog_tests/deny_namespace.c | 88 +++++++++++++++++++ .../selftests/bpf/progs/test_deny_namespace.c | 39 ++++++++ 2 files changed, 127 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/deny_namespace.c create mode 100644 tools/testing/selftests/bpf/progs/test_deny_namespace.c diff --git a/tools/testing/selftests/bpf/prog_tests/deny_namespace.c b/tool= s/testing/selftests/bpf/prog_tests/deny_namespace.c new file mode 100644 index 000000000000..9e4714295008 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/deny_namespace.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE +#include +#include "test_deny_namespace.skel.h" +#include +#include "cap_helpers.h" + +#define STACK_SIZE (1024 * 1024) +static char child_stack[STACK_SIZE]; + +int clone_callback(void *arg) +{ + return 0; +} + +static int create_new_user_ns(void) +{ + int status; + pid_t cpid; + + cpid =3D clone(clone_callback, child_stack + STACK_SIZE, + CLONE_NEWUSER | SIGCHLD, NULL); + + if (cpid =3D=3D -1) + return errno; + + if (cpid =3D=3D 0) + return 0; + + waitpid(cpid, &status, 0); + if (WIFEXITED(status)) + return WEXITSTATUS(status); + + return -1; +} + +static void test_userns_create_bpf(void) +{ + __u32 cap_mask =3D 1ULL << CAP_SYS_ADMIN; + __u64 old_caps =3D 0; + + ASSERT_OK(create_new_user_ns(), "priv new user ns"); + + cap_disable_effective(cap_mask, &old_caps); + + ASSERT_EQ(create_new_user_ns(), EPERM, "unpriv new user ns"); + + if (cap_mask & old_caps) + cap_enable_effective(cap_mask, NULL); +} + +static void test_unpriv_userns_create_no_bpf(void) +{ + __u32 cap_mask =3D 1ULL << CAP_SYS_ADMIN; + __u64 old_caps =3D 0; + + cap_disable_effective(cap_mask, &old_caps); + + ASSERT_OK(create_new_user_ns(), "no-bpf unpriv new user ns"); + + if (cap_mask & old_caps) + cap_enable_effective(cap_mask, NULL); +} + +void test_deny_namespace(void) +{ + struct test_deny_namespace *skel =3D NULL; + int err; + + if (test__start_subtest("unpriv_userns_create_no_bpf")) + test_unpriv_userns_create_no_bpf(); + + skel =3D test_deny_namespace__open_and_load(); + if (!ASSERT_OK_PTR(skel, "skel load")) + goto close_prog; + + err =3D test_deny_namespace__attach(skel); + if (!ASSERT_OK(err, "attach")) + goto close_prog; + + if (test__start_subtest("userns_create_bpf")) + test_userns_create_bpf(); + + test_deny_namespace__detach(skel); + +close_prog: + test_deny_namespace__destroy(skel); +} diff --git a/tools/testing/selftests/bpf/progs/test_deny_namespace.c b/tool= s/testing/selftests/bpf/progs/test_deny_namespace.c new file mode 100644 index 000000000000..9ec9dabc8372 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_deny_namespace.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include + +struct kernel_cap_struct { + __u32 cap[_LINUX_CAPABILITY_U32S_3]; +} __attribute__((preserve_access_index)); + +struct cred { + struct kernel_cap_struct cap_effective; +} __attribute__((preserve_access_index)); + +char _license[] SEC("license") =3D "GPL"; + +SEC("lsm/userns_create") +int BPF_PROG(test_userns_create, const struct cred *cred, int ret) +{ + struct kernel_cap_struct caps =3D cred->cap_effective; + int cap_index =3D CAP_TO_INDEX(CAP_SYS_ADMIN); + __u32 cap_mask =3D CAP_TO_MASK(CAP_SYS_ADMIN); + + if (ret) + return 0; + + ret =3D -EPERM; + if (caps.cap[cap_index] & cap_mask) + return 0; + + return -EPERM; +} + +SEC("lsm.s/userns_create") +int BPF_PROG(test_sleepable_userns_create, const struct cred *cred, int re= t) +{ + return 0; +} --=20 2.30.2 From nobody Fri Apr 17 22:31:35 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 19DDEC433EF for ; Thu, 21 Jul 2022 17:29:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231799AbiGUR3I (ORCPT ); Thu, 21 Jul 2022 13:29:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54670 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229449AbiGUR2k (ORCPT ); Thu, 21 Jul 2022 13:28:40 -0400 Received: from mail-oa1-x36.google.com (mail-oa1-x36.google.com [IPv6:2001:4860:4864:20::36]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5E7DB8B49A for ; Thu, 21 Jul 2022 10:28:22 -0700 (PDT) Received: by mail-oa1-x36.google.com with SMTP id 586e51a60fabf-10cf9f5b500so3318780fac.2 for ; Thu, 21 Jul 2022 10:28:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=9XmM5ZEm+shFY9USkb0JIud5sKeKc0ztWjPwdUbLtVM=; b=VxN5mqJJldqCTmzCQx2+zgcmh2YQ/eQWRZOCH3SSk/wgcplWOs9zda4bzFvX0e/y3I w3O6v0xE9QlSb5O7mcwsd7nUKfGQMW+kAGmKMdQ3s/MptadnTYQWw5YHyzVxhn0Qdra7 /HkKK7hh0AG+o5x79m4ZlAOsEEJPLxCywqt50= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=9XmM5ZEm+shFY9USkb0JIud5sKeKc0ztWjPwdUbLtVM=; b=WwaQnCFyGttyJcwg0S8Z4epHzMwmFgzM7QJGrFociu0lqbASav1/D8j05xbVdy3i91 tqMp01GE9J3qGYeNPcP3dmdCxjuY8gEdeEpmDlKk254c0cf5X9XNGvrd0CwAGC4GCfda ab9s149LqDRfKtVsU9wtrNgu7Y6lkYVDj2cNbLZ44ujxQwcf3n+IOw7/TdpmWWuj+9bh 4lH21YCkU2dfTRf5PGNgjg6kOwKwnrJEeNifCJBAnuGNdnnMjpfTGtmRTGJW1Cu4MXGq +hMkQ7WIxIa4Q9M6vyBsUZ3lvJ/gr6K5KX3vbnMghIQr75VYkYcOC67NfNRdRLoRuKTh xS+w== X-Gm-Message-State: AJIora88NiXHKhcIXrBZfJECJMcWKCnZCHMpHnxoWQ5YIIwxKK3BL88T zS8U8BSdbU/DQ6y0WSccUV6ajg== X-Google-Smtp-Source: AGRyM1szrijCIIxZinJ6E7J+5pSN+ES88nSt3CyPGl/JIMkRcNEV5/3s7Tb0OdikxMeqWkjS76rHQg== X-Received: by 2002:a05:6870:709e:b0:10d:752a:9ce7 with SMTP id v30-20020a056870709e00b0010d752a9ce7mr5876067oae.233.1658424501678; Thu, 21 Jul 2022 10:28:21 -0700 (PDT) Received: from localhost.localdomain ([184.4.90.121]) by smtp.gmail.com with ESMTPSA id du24-20020a0568703a1800b00101c83352c6sm1106207oab.34.2022.07.21.10.28.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Jul 2022 10:28:21 -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 v3 4/4] selinux: Implement userns_create hook Date: Thu, 21 Jul 2022 12:28:08 -0500 Message-Id: <20220721172808.585539-5-fred@cloudflare.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220721172808.585539-1-fred@cloudflare.com> References: <20220721172808.585539-1-fred@cloudflare.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Unprivileged user namespace creation is an intended feature to enable sandboxing, however this feature is often used to as an initial step to perform a privilege escalation attack. This patch implements a new user_namespace { create } access control permission to restrict which domains allow or deny user namespace creation. This is necessary for system administrators to quickly protect their systems while waiting for vulnerability patches to be applied. This permission can be used in the following way: allow domA_t domA_t : user_namespace { create }; Signed-off-by: Frederick Lawler reviewed-by before accepting this.=20 --- Changes since v2: - Rename create_user_ns hook to userns_create - Use user_namespace as an object opposed to a generic namespace object - s/domB_t/domA_t in commit message Changes since v1: - Introduce this patch --- security/selinux/hooks.c | 9 +++++++++ security/selinux/include/classmap.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index beceb89f68d9..afc9da0249e7 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4227,6 +4227,14 @@ static void selinux_task_to_inode(struct task_struct= *p, spin_unlock(&isec->lock); } =20 +static int selinux_userns_create(const struct cred *cred) +{ + u32 sid =3D current_sid(); + + return avc_has_perm(&selinux_state, sid, sid, SECCLASS_USER_NAMESPACE, + USER_NAMESPACE__CREATE, NULL); +} + /* Returns error only if unable to parse addresses */ static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct common_audit_data *ad, u8 *proto) @@ -7117,6 +7125,7 @@ static struct security_hook_list selinux_hooks[] __ls= m_ro_after_init =3D { LSM_HOOK_INIT(task_movememory, selinux_task_movememory), LSM_HOOK_INIT(task_kill, selinux_task_kill), LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode), + LSM_HOOK_INIT(userns_create, selinux_userns_create), =20 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission), LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid), diff --git a/security/selinux/include/classmap.h b/security/selinux/include= /classmap.h index ff757ae5f253..0bff55bb9cde 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -254,6 +254,8 @@ const struct security_class_mapping secclass_map[] =3D { { COMMON_FILE_PERMS, NULL } }, { "io_uring", { "override_creds", "sqpoll", NULL } }, + { "user_namespace", + { "create", NULL } }, { NULL } }; =20 --=20 2.30.2