From patchwork Mon Aug 1 18:01:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frederick Lawler X-Patchwork-Id: 12933966 X-Patchwork-Delegate: paul@paul-moore.com 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 6E29DC00144 for ; Mon, 1 Aug 2022 18:02:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234088AbiHASC0 (ORCPT ); Mon, 1 Aug 2022 14:02:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41962 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233909AbiHASCV (ORCPT ); Mon, 1 Aug 2022 14:02:21 -0400 Received: from mail-oa1-x32.google.com (mail-oa1-x32.google.com [IPv6:2001:4860:4864:20::32]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C6CD02613F for ; Mon, 1 Aug 2022 11:02:17 -0700 (PDT) Received: by mail-oa1-x32.google.com with SMTP id 586e51a60fabf-10e615a36b0so13045592fac.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=RJIapkK3Kh9P8n6xylZHvyot5x2W2GhUwVZbNec8drstJo1A9qU5g4foPHddtZ5Uu8 Y6VdYGFggUwBjTW+beHkUiqJxCcpYuPUEw3dzEjK/yYXaCUtb+MK1a4JMZPcUWRPKg1R N961IGVDgnF4RFs61QvgqCrIfi12PMjx5neqkiXPHU/WcsKjGOKkvFbJBz/VHJgHdppS tziPZ6AoeSGXpvgzdBChkHX1MtDnIhA1gEsAQcGvrD2WbpA5YgrZvZoh4y4kx/IAz6Fd gpM3S/EbgBQal05qcsRAs/rEzCFWjSxivG1ColvqavqRumtYyPLS1AbHOaDc9RcWSiaN TNXw== X-Gm-Message-State: AJIora8CEbDFfCRJ/C7fOu5dtqGzJyycqEcgesaIXzBgkhmWIkO1DMTm eqcoLppIcb0lNqgNAeX13t/3LA== X-Google-Smtp-Source: AGRyM1sD4g9Y9q/qyaXFCXmpcHuPT+pZOrtXQ6KE1YfTchLBWdjWov0aG3GFbThSnBywcxw6nVYfgw== 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 Precedence: bulk List-ID: X-Mailing-List: selinux@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) Reviewed-by: KP Singh --- 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); From patchwork Mon Aug 1 18:01:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frederick Lawler X-Patchwork-Id: 12933967 X-Patchwork-Delegate: paul@paul-moore.com 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 ECFD8C19F2C for ; Mon, 1 Aug 2022 18:02:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234275AbiHASCq (ORCPT ); Mon, 1 Aug 2022 14:02:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42102 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234053AbiHASCV (ORCPT ); Mon, 1 Aug 2022 14:02:21 -0400 Received: from mail-oo1-xc2e.google.com (mail-oo1-xc2e.google.com [IPv6:2607:f8b0:4864:20::c2e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7FC6827CD0 for ; Mon, 1 Aug 2022 11:02:19 -0700 (PDT) Received: by mail-oo1-xc2e.google.com with SMTP id c203-20020a4a4fd4000000b0043566a4e265so2153911oob.2 for ; Mon, 01 Aug 2022 11:02:19 -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=5eI4oBHRscjr08ZHNzQwOqsOD+3+F4rjZrnwT2lhjk8=; b=uLJivFt0JrijlTz4WiJCVuEF8oDRzf5Y7+H6eH45jC4nOYPshmi66MEhwrgCTE8YjQ yODopqvVSRyhcT85GJMk/fAiiPPldOdUR5F7OuR5KoOm4IRWjSJfjRi8lsTM6R3QM+QD UTvK9WXbkNelJtyCDqvAY/Rpe445Qz2Gi9NSI= 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=5eI4oBHRscjr08ZHNzQwOqsOD+3+F4rjZrnwT2lhjk8=; b=AD98mAJaULtgWu9u7OYB5nVToytZTHDRlI4WP9o7BxtpaahTV0hRz5M/vRLaga0PEU /NZiF9TyFp5CBZQiGWZZlxq6JY6O/zbZZjdTyiiZh67Bio83c51QitaNOPfWzSik8y1f hEs6pbtCdp7RloMz1Z69z9TcfK81aV+MbIIwb7koOFAegoVgjzfe6xyXYCzChhxBc8OF OxvHPoWRr/xNHkJCIRDc0FOMLvbjnRDmoM7JqoUi78f/N5Ut9tudwmDy+dagQC7b7P2P n8SMkuqhWPZyfklO9AXaAq5gNMrWLvzZp7O1YrPQKI85bboDNf3QbNtLtIjcN9pVRZuY R3bw== X-Gm-Message-State: AJIora9m1MDez8aFQjpRh24Mad8NRgZqW2RSvXIi/OVmiU4xdLTAbmQA z36Mda2SjQB7vSjhIaUOEEjtCQ== X-Google-Smtp-Source: AGRyM1vzfAiBBDDyxwIMaZa0k2G9WulhjNQ80UDh1E2ApA6+RCreR0vgWj58f08ozl+TDSXb29hD7w== X-Received: by 2002:a4a:e7d8:0:b0:435:9a05:58b5 with SMTP id y24-20020a4ae7d8000000b004359a0558b5mr5600538oov.54.1659376938810; Mon, 01 Aug 2022 11:02:18 -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.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 01 Aug 2022 11:02:18 -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 2/4] bpf-lsm: Make bpf_lsm_userns_create() sleepable Date: Mon, 1 Aug 2022 13:01:44 -0500 Message-Id: <20220801180146.1157914-3-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 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org 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) Acked-by: Alexei Starovoitov Acked-by: KP Singh --- Changes since v3: - None 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) bool bpf_lsm_is_sleepable_hook(u32 btf_id) From patchwork Mon Aug 1 18:01:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frederick Lawler X-Patchwork-Id: 12933968 X-Patchwork-Delegate: paul@paul-moore.com 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 3017AC19F2D for ; Mon, 1 Aug 2022 18:02:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234335AbiHASCy (ORCPT ); Mon, 1 Aug 2022 14:02:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42078 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233925AbiHASCe (ORCPT ); Mon, 1 Aug 2022 14:02:34 -0400 Received: from mail-oi1-x235.google.com (mail-oi1-x235.google.com [IPv6:2607:f8b0:4864:20::235]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 122F329822 for ; Mon, 1 Aug 2022 11:02:23 -0700 (PDT) Received: by mail-oi1-x235.google.com with SMTP id n133so13985578oib.0 for ; Mon, 01 Aug 2022 11:02:23 -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=DFM28j1evovVIesF7892uqGHd1qTcmZDuJXeotitcvA=; b=tdpMqQ74ueJhZLF3PIkmfBOR4X5EIhlmdyEmHxx+mu54Z6yJXe905lrBIGf829wdcd tYpmmTMjMmz7GxFo+CRUNBPdt4bBxoSbOmputKkrcxGKaZI4C9Uy1WXSZSgUgiWoIa+d NX+fsqqialFm/ytOY0K3SyPgKSeuyk+nIGJ5A= 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=DFM28j1evovVIesF7892uqGHd1qTcmZDuJXeotitcvA=; b=rrPBlNKsBcnkVFa9L+VBdHsC+h+dwjwtI8l4pDd+wXo/yles095Kbi2NfHWYHCVzeu gLJ9UR/AW7Hrxdi8FQm+PadkX2CoCPrHf8iOttbpj6HpH4WFYYEocV6OwZXXr7mq67NB CFJUe8lOJxK0t3jbOqlUMENVQRpyw2OACGyYoPbUfi3iVQpiJa5x1Hg2RtMryArgruS5 mgnvuAeSzbrX2JZrHBdNXGbCVYL0TwxyatAQFs+7lDJTT2ngVzMq6KQPv8p7u2CyKoHQ kxKiURRXSmmDaDZbLXZooCTsE76goC/wtR0PG5Cl7/5iKSPRjo2K2vsDqNuvQTkDpv0Z z9nw== X-Gm-Message-State: AJIora8FeHFjsGHuvnxyzODEKxJ+W6RxEwhIfPochmoihb+hmXiBj6Hx 6tI/wNU1QMhq2rCaHpO8kWDmug== X-Google-Smtp-Source: AGRyM1vjtPI/ODQpeiZyl8o+45Ndqv7M6XyWUy/E58LADXIUQntSE06XmvHEQbKpW8EldE0lx9iJCA== X-Received: by 2002:a05:6808:171c:b0:334:9342:63ef with SMTP id bc28-20020a056808171c00b00334934263efmr6997799oib.63.1659376940639; Mon, 01 Aug 2022 11:02:20 -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.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 01 Aug 2022 11:02:20 -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 3/4] selftests/bpf: Add tests verifying bpf lsm userns_create hook Date: Mon, 1 Aug 2022 13:01:45 -0500 Message-Id: <20220801180146.1157914-4-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 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org 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 3 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. Signed-off-by: Frederick Lawler Acked-by: KP Singh --- 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 v3: - Explicitly set CAP_SYS_ADMIN to test namespace is created given permission - Simplify BPF test to use sleepable hook only - Prefer unshare() over clone() for tests Changes since v2: - Rename create_user_ns hook to userns_create Changes since v1: - Introduce this patch --- .../selftests/bpf/prog_tests/deny_namespace.c | 102 ++++++++++++++++++ .../selftests/bpf/progs/test_deny_namespace.c | 33 ++++++ 2 files changed, 135 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/tools/testing/selftests/bpf/prog_tests/deny_namespace.c new file mode 100644 index 000000000000..1bc6241b755b --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/deny_namespace.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE +#include +#include "test_deny_namespace.skel.h" +#include +#include "cap_helpers.h" +#include + +static int wait_for_pid(pid_t pid) +{ + int status, ret; + +again: + ret = waitpid(pid, &status, 0); + if (ret == -1) { + if (errno == EINTR) + goto again; + + return -1; + } + + if (!WIFEXITED(status)) + return -1; + + return WEXITSTATUS(status); +} + +/* negative return value -> some internal error + * positive return value -> userns creation failed + * 0 -> userns creation succeeded + */ +static int create_user_ns(void) +{ + pid_t pid; + + pid = fork(); + if (pid < 0) + return -1; + + if (pid == 0) { + if (unshare(CLONE_NEWUSER)) + _exit(EXIT_FAILURE); + _exit(EXIT_SUCCESS); + } + + return wait_for_pid(pid); +} + +static void test_userns_create_bpf(void) +{ + __u32 cap_mask = 1ULL << CAP_SYS_ADMIN; + __u64 old_caps = 0; + + cap_enable_effective(cap_mask, &old_caps); + + ASSERT_OK(create_user_ns(), "priv new user ns"); + + cap_disable_effective(cap_mask, &old_caps); + + ASSERT_EQ(create_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 = 1ULL << CAP_SYS_ADMIN; + __u64 old_caps = 0; + + cap_disable_effective(cap_mask, &old_caps); + + ASSERT_OK(create_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 = NULL; + int err; + + if (test__start_subtest("unpriv_userns_create_no_bpf")) + test_unpriv_userns_create_no_bpf(); + + skel = test_deny_namespace__open_and_load(); + if (!ASSERT_OK_PTR(skel, "skel load")) + goto close_prog; + + err = 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/tools/testing/selftests/bpf/progs/test_deny_namespace.c new file mode 100644 index 000000000000..09ad5a4ebd1f --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_deny_namespace.c @@ -0,0 +1,33 @@ +// 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") = "GPL"; + +SEC("lsm.s/userns_create") +int BPF_PROG(test_userns_create, const struct cred *cred, int ret) +{ + struct kernel_cap_struct caps = cred->cap_effective; + int cap_index = CAP_TO_INDEX(CAP_SYS_ADMIN); + __u32 cap_mask = CAP_TO_MASK(CAP_SYS_ADMIN); + + if (ret) + return 0; + + ret = -EPERM; + if (caps.cap[cap_index] & cap_mask) + return 0; + + return -EPERM; +} From patchwork Mon Aug 1 18:01:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frederick Lawler X-Patchwork-Id: 12933969 X-Patchwork-Delegate: paul@paul-moore.com 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 AB091C00144 for ; Mon, 1 Aug 2022 18:03:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234377AbiHASC7 (ORCPT ); Mon, 1 Aug 2022 14:02:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42252 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234268AbiHASCp (ORCPT ); Mon, 1 Aug 2022 14:02:45 -0400 Received: from mail-oi1-x22f.google.com (mail-oi1-x22f.google.com [IPv6:2607:f8b0:4864:20::22f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5A6082A704 for ; Mon, 1 Aug 2022 11:02:25 -0700 (PDT) Received: by mail-oi1-x22f.google.com with SMTP id s204so13921397oif.5 for ; Mon, 01 Aug 2022 11:02:25 -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=bttyVQI+o0yCdSSwfTGsmfJypexzzz/Ptc7wrcpVb94=; b=i4ToQg1x5/k2OuSwcs5fz8zHz6WBhwfxswzE6nWWdWaeEdPc6pv10CDx0N+HMBM9Yj apKtW+hsRPgAXYA0BTvzit4oSXA5q0fwJgMIOswGMI+7uQRvQtuNrIn2Q8ZTP+qQUF4U PXAMRMONfHRrue6t5Oi+zRbQrpqKUBZwty/Yw= 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=bttyVQI+o0yCdSSwfTGsmfJypexzzz/Ptc7wrcpVb94=; b=D0AzEwng0ohkAkiE/VMrrCwNKuXT/QW1fuIvqKpFKMN+85mTsI35QSmtllHZ3LuQHq ZoHG5BxoxdfJo61noTxSsMjix+lZibo6hGQVQrS0fWSf8sqGL9z0t18QArD/yzuRvFe1 AMnO7Vu564ZfE5+Ozl8odBNN0MUcdvaKWHEaO93A4fZV7Kp8cKEScDHOp4sw8b8NXlwj 7guYzSATRnMy00Sr/UGnUTpY9GiSdnWxE2+LZKoBIThVFkC4pbiHxWiTFh6llEibOrjD Zanjd8cePRkkmH7fyos2Aq1KNl+CaXH7JBFScRLFU1x2dO4CdxqufJ6ScnPsq761c1aW Ec+A== X-Gm-Message-State: AJIora9vGRzBj8STP+RAjvGLhX2fypgAjizKYWXRshpWlcR+MlRBuyw6 Uhw9LivcuE1fbmZvY6PFwLItiQ== X-Google-Smtp-Source: AGRyM1tirTjWfZIcvEpccIMwd00O49IfF8uA6bm3mVQLc9R6zclPg5zxqFpIZPvVpdHR1RhSA9mPug== X-Received: by 2002:a05:6808:302b:b0:2f9:eeef:f03 with SMTP id ay43-20020a056808302b00b002f9eeef0f03mr6998147oib.128.1659376942519; Mon, 01 Aug 2022 11:02:22 -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.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 01 Aug 2022 11:02:22 -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 4/4] selinux: Implement userns_create hook Date: Mon, 1 Aug 2022 13:01:46 -0500 Message-Id: <20220801180146.1157914-5-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 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org 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 --- Changes since v3: - None 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); } +static int selinux_userns_create(const struct cred *cred) +{ + u32 sid = 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[] __lsm_ro_after_init = { 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), 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[] = { { COMMON_FILE_PERMS, NULL } }, { "io_uring", { "override_creds", "sqpoll", NULL } }, + { "user_namespace", + { "create", NULL } }, { NULL } };