From patchwork Mon Aug 15 16:20:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frederick Lawler X-Patchwork-Id: 12943800 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 C8E0FC00140 for ; Mon, 15 Aug 2022 16:20:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232412AbiHOQUs (ORCPT ); Mon, 15 Aug 2022 12:20:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39512 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232625AbiHOQUm (ORCPT ); Mon, 15 Aug 2022 12:20:42 -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 193CE13EBA for ; Mon, 15 Aug 2022 09:20:37 -0700 (PDT) Received: by mail-oa1-x33.google.com with SMTP id 586e51a60fabf-f2a4c51c45so8655541fac.9 for ; Mon, 15 Aug 2022 09:20:37 -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=lHIcVgvWJN3OdYYSsC7RBMC65yCdGzXPq7WonvXuURg=; b=RvEV/vtBES4QRTvsEVNe4a5Hi5zkKvoQo4b6nwm41wBEK6GofgwjNoYoz10qjXdup+ MvGKBgcg8caPoHTuStaUp/U5En+8Hy9TjJ4WRUDbgB47RU/ULRTbNYYa1ZoiPDqGDqeE ytBifsdreKSg5RvG/bMzaPl3czA5/79GcxKJU= 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=lHIcVgvWJN3OdYYSsC7RBMC65yCdGzXPq7WonvXuURg=; b=p7wAJkwWQEiMUUq3az/2+cehNB/fXe22a3NQhm/l2+zICvHYkZYk8nMk9PK1M0qJAz BUE7S6zJ7jCp8iteAm6sV7oABRaLdTtqdo1DUqy3V2Wa1UsaLpodSMGJALl3SDuI23b6 ewyiWMZbBbvufLtAbGLSOUGv+NJ5RSiE2G38+LyXRM+8YbXMd0f3EjHGrCf4FcYNn1wJ TH0K6So8JUfq3Cc9Yc+mW7OctXNeoLTdB1jVPKdqY2+YCr7Q58A+repYKE6inB6yJWPD oEQ8C0A2m/ernAHVpmZnDsb7d/0lOe7eiw6grJNl/Dx8DstZEayqqWaWbX3SWji/xddg CDcw== X-Gm-Message-State: ACgBeo3DVcevtKyLW8lzWKUxY/pq5TpO6MIyl37sNZU5h/coCSx20CMM wL+nSx57fMYwVX9Ghzpcij8gpA== X-Google-Smtp-Source: AA6agR650fvSfcKdkYWoRVUrzHcgjSsjMtiAbKZqBqqTc2hdtVBGXw6xkiFF2LwUv+jWcic87SCttg== X-Received: by 2002:a05:6870:8984:b0:10d:d981:151f with SMTP id f4-20020a056870898400b0010dd981151fmr11077864oaq.212.1660580437137; Mon, 15 Aug 2022 09:20:37 -0700 (PDT) Received: from localhost.localdomain ([184.4.90.121]) by smtp.gmail.com with ESMTPSA id x91-20020a9d37e4000000b00636ee04e7aesm2163371otb.67.2022.08.15.09.20.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Aug 2022 09:20:36 -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, tixxdz@gmail.com, Frederick Lawler Subject: [PATCH v5 1/4] security, lsm: Introduce security_create_user_ns() Date: Mon, 15 Aug 2022 11:20:25 -0500 Message-Id: <20220815162028.926858-2-fred@cloudflare.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220815162028.926858-1-fred@cloudflare.com> References: <20220815162028.926858-1-fred@cloudflare.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org User namespaces are an effective tool to allow programs to run with permission without requiring the need for a program to run as root. User namespaces may also be used as a sandboxing technique. However, attackers sometimes leverage user namespaces as an initial attack vector to perform some exploit. [1,2,3] While it is not the unprivileged user namespace functionality, which causes the kernel to be exploitable, users/administrators might want to more granularly limit or at least monitor how various processes use this functionality, while vulnerable kernel subsystems are being patched. Preventing user namespace already creation comes in a few of forms in order of granularity: 1. /proc/sys/user/max_user_namespaces sysctl 2. Distro specific patch(es) 3. CONFIG_USER_NS To block a task based on its attributes, the LSM hook cred_prepare is a decent 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. [4] Further, security_prepare_creds() will always return a ENOMEM if the hook returns any non-zero error code. This hook also does not handle the clone3 case which requires us to access a user space pointer to know if we're in the CLONE_NEW_USER call path which may be subject to a TOCTTOU attack. Lastly, cred_prepare is called in many call paths, and a targeted hook further limits the frequency of calls which is a beneficial outcome. Therefore introduce a new function security_create_user_ns() with an accompanying userns_create LSM hook. With the new userns_create hook, users will have more control over the observability and access control over user namespace creation. Users should expect that normal operation of user namespaces will behave as usual, and only be impacted when controls are implemented by users or administrators. 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. Links: 1. https://nvd.nist.gov/vuln/detail/CVE-2022-0492 2. https://nvd.nist.gov/vuln/detail/CVE-2022-25636 3. https://nvd.nist.gov/vuln/detail/CVE-2022-34918 4. https://lore.kernel.org/all/1c4b1c0d-12f6-6e9e-a6a3-cdce7418110c@schaufler-ca.com/ Reviewed-by: Christian Brauner (Microsoft) Reviewed-by: KP Singh Signed-off-by: Frederick Lawler --- Changes since v4: - Update commit description 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 806448173033..aa7272e83626 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -224,6 +224,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 84a0d7e02176..2e11a2a22ed1 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -806,6 +806,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 1bc362cb413f..767802fe9bfa 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -437,6 +437,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); @@ -1194,6 +1195,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 14d30fec8a00..1e60c4b570ec 100644 --- a/security/security.c +++ b/security/security.c @@ -1909,6 +1909,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 15 16:20:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frederick Lawler X-Patchwork-Id: 12943801 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 0469CC00140 for ; Mon, 15 Aug 2022 16:20:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232930AbiHOQU5 (ORCPT ); Mon, 15 Aug 2022 12:20:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39600 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232721AbiHOQUo (ORCPT ); Mon, 15 Aug 2022 12:20:44 -0400 Received: from mail-ot1-x32f.google.com (mail-ot1-x32f.google.com [IPv6:2607:f8b0:4864:20::32f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 23B9413D6E for ; Mon, 15 Aug 2022 09:20:39 -0700 (PDT) Received: by mail-ot1-x32f.google.com with SMTP id h9-20020a9d5549000000b0063727299bb4so5762266oti.9 for ; Mon, 15 Aug 2022 09:20:39 -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=MJrznwOS4iDI2OpucHPY/z4vNYitgwRbWuSlr+3wOv0=; b=x58yM22xkTNeiyCqG9ou9XMvzSvlhZ8QkCbKqqdIi6Y5OLHHn3dXB0vhofX7kY1wxk /Aj/rFeOrOZuEA7qcwZW9Kk/unT4g2j/6pvMojj0ncqsuof+qm+EMz5425ppDkeoBpVN MedvwhyTdPSPm50RlayssJ3m4WqnH/KJq6UUA= 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=MJrznwOS4iDI2OpucHPY/z4vNYitgwRbWuSlr+3wOv0=; b=VPuOri2g5S16+98Go05fRqGDBUCx+dzxa6cpjCZBzlYsniG9MvmfdjbwLEXVTz9JJF BNcYWeQF9sQO+L/T9tjzh3vei/87yk7nRZvvJOqn1NDLSk/rA8OcNXPHRmD5WNhU+91K YxQHvWzjy4mq0o+8b1csjaklLXTzfAO4sII2YRvRAlX7wBKnayJ5nCvlawYJxs1kmECJ o2WSEzPsSj0DcH6ZF9/BLGo07dST6T9zGZTu7mk36Uhn6VxvgEx3dgHuzU3QHfjPFxbO EQDHC8fXcaeCKwRiL44vEiONIr7//ZvulBwcfSI2O5ej62NJngjWwtl3KzuTha9uzEAX 4uFA== X-Gm-Message-State: ACgBeo1IAF9iSid6HC2X5SUiVDpl4QghA7TeiICgX1KipLA0darYGwcs F2dfw/1IrcsnLHbHysejA8WlVg== X-Google-Smtp-Source: AA6agR6g7xKSXJLfRY1lzp/6aAIs7KluhqFOW4lJXq/4FCo8B9qkAgTWY1rxcsZlrxFZ3LAM+8JUnA== X-Received: by 2002:a9d:6294:0:b0:638:b817:7c87 with SMTP id x20-20020a9d6294000000b00638b8177c87mr1168939otk.378.1660580438743; Mon, 15 Aug 2022 09:20:38 -0700 (PDT) Received: from localhost.localdomain ([184.4.90.121]) by smtp.gmail.com with ESMTPSA id x91-20020a9d37e4000000b00636ee04e7aesm2163371otb.67.2022.08.15.09.20.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Aug 2022 09:20:38 -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, tixxdz@gmail.com, Frederick Lawler Subject: [PATCH v5 2/4] bpf-lsm: Make bpf_lsm_userns_create() sleepable Date: Mon, 15 Aug 2022 11:20:26 -0500 Message-Id: <20220815162028.926858-3-fred@cloudflare.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220815162028.926858-1-fred@cloudflare.com> References: <20220815162028.926858-1-fred@cloudflare.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@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. Acked-by: Alexei Starovoitov Acked-by: Christian Brauner (Microsoft) Acked-by: KP Singh Signed-off-by: Frederick Lawler --- Changes since v4: - None 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 fa71d58b7ded..761998fda762 100644 --- a/kernel/bpf/bpf_lsm.c +++ b/kernel/bpf/bpf_lsm.c @@ -335,6 +335,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 15 16:20:27 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frederick Lawler X-Patchwork-Id: 12943802 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 78744C282E7 for ; Mon, 15 Aug 2022 16:21:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232329AbiHOQVI (ORCPT ); Mon, 15 Aug 2022 12:21:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39732 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232740AbiHOQUo (ORCPT ); Mon, 15 Aug 2022 12:20:44 -0400 Received: from mail-oa1-x29.google.com (mail-oa1-x29.google.com [IPv6:2001:4860:4864:20::29]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CB3991DA6C for ; Mon, 15 Aug 2022 09:20:40 -0700 (PDT) Received: by mail-oa1-x29.google.com with SMTP id 586e51a60fabf-10ea30a098bso8659145fac.8 for ; Mon, 15 Aug 2022 09:20:40 -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=nNZ0u0nBC2KeSEEdxzbAi0SK8J2Us1DLDDPRqND6hEc=; b=wiyRKMkRQYcjM+XE8VvKwvEwd5ICt1r9/rWYFwD6PoeyS6/CWGyYYqvm1hLPRa7KQo CedPLMamRHO3+nPkfBlXB3yE/NlnkeHoDwvX3nbTX9AbdDhSbNYbd1jXw8xURlwSDBoM cPfEiQsKYdXRWHhZ7duUb1aXWIAUigxsUdrKc= 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=nNZ0u0nBC2KeSEEdxzbAi0SK8J2Us1DLDDPRqND6hEc=; b=oYe0wEhK4FgI+6bb83872S+ODLM680t//dMjIaBCriPXtDZDelfh7bkZ0l4Hy0pXwq whykaZxdPQzbBhNrr8lPbSTwXCoCg28m1nfH3wQf+5RCLVvcZk0awqck4Mg4S9dygrTZ 4Dg9PMSpsVCYAaqpMAf2GWo+KQS83F26+HdPnSdURrj4EQwBYriebG792gpB8Vw2lJFd 6c7rTji0ivKkVq394eGuO5K4/ld1LlBN2oeOwAXjz+ob2AqFp3hk/z4ylqXvuDOwHqA/ DxpZt/QKWtQDh/DFYL4LOfFwm8gXhebp3mopUA/rD3R0UhOg00bQ+Mkj1q09hmMwk9ct h8Zg== X-Gm-Message-State: ACgBeo2RXg/FgupVhWH255d50qWK0vplrSPTlCzZ78LVfblyCWSV78VG NoBM/U/COajU5lPzYdKV7QWmqw== X-Google-Smtp-Source: AA6agR5z0VLGcfMA+TlVlAJ5FuhbsicrvataQG5IVwelNQavaXDKjyccdLVSkfGXOab7dIekf8LuQQ== X-Received: by 2002:a05:6870:7099:b0:116:ccda:ac1c with SMTP id v25-20020a056870709900b00116ccdaac1cmr7048070oae.153.1660580440363; Mon, 15 Aug 2022 09:20:40 -0700 (PDT) Received: from localhost.localdomain ([184.4.90.121]) by smtp.gmail.com with ESMTPSA id x91-20020a9d37e4000000b00636ee04e7aesm2163371otb.67.2022.08.15.09.20.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Aug 2022 09:20:40 -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, tixxdz@gmail.com, Frederick Lawler Subject: [PATCH v5 3/4] selftests/bpf: Add tests verifying bpf lsm userns_create hook Date: Mon, 15 Aug 2022 11:20:27 -0500 Message-Id: <20220815162028.926858-4-fred@cloudflare.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220815162028.926858-1-fred@cloudflare.com> References: <20220815162028.926858-1-fred@cloudflare.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@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. Acked-by: KP Singh Signed-off-by: Frederick Lawler --- 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 v4: - None 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 15 16:20:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frederick Lawler X-Patchwork-Id: 12943803 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 6D949C00140 for ; Mon, 15 Aug 2022 16:21:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233196AbiHOQVi (ORCPT ); Mon, 15 Aug 2022 12:21:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39424 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232888AbiHOQUq (ORCPT ); Mon, 15 Aug 2022 12:20:46 -0400 Received: from mail-ot1-x329.google.com (mail-ot1-x329.google.com [IPv6:2607:f8b0:4864:20::329]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CD86313CE0 for ; Mon, 15 Aug 2022 09:20:42 -0700 (PDT) Received: by mail-ot1-x329.google.com with SMTP id o15-20020a9d718f000000b00638c1348012so748907otj.2 for ; Mon, 15 Aug 2022 09:20:42 -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=U3OK8Oqnf2K0vdWXT1jn4LVlcHC3Qy4QXRttGxzPtuo=; b=XU3mICcICTtNu7uN8K5AA/UUF9eGokgmjP4mS51xOSo4TbR6mIgICfjf3JleWSCsnD 3bKxTlmLlhl3CdsgdqLQhB63ngHK/3WAjkc9apGYatsqocuIO2tLcXn8aGkf/AKiaTLs sTT1sq/iMyXBWFfe2c4PBoNmB/mESTtAqL4LQ= 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=U3OK8Oqnf2K0vdWXT1jn4LVlcHC3Qy4QXRttGxzPtuo=; b=cgXy+fcYYgp2JGyQLoMLd6a9pxdFvqwpXf+ud5z7uaBLQRfBD13wRiqcxpSa2iA0WW cTDhu5QXz6tUZ0wehbfNmJb8M8kzzcMwcxwROodf1d5zwEQuKSHGrhtQJo7FEKSf4okH r/EAkjDFfH80hG7KCZU20QE5yTHy2gvgUOBxjbDOdUjHhOrhkGGLYLtjGFnZIZJnHPkz lh8q1myqr/VeSVXThY14ZwqylEZOpcsG0pb7npQosQQ+VLKQhi7lUpwU9L61kfM3me0s tbVzDtpnKMKS3lnOoljh+FXcsA/n+yOX0o1CnImz82ETePl7+Gebi7B7AR0z99z0EQTc DcrQ== X-Gm-Message-State: ACgBeo1R4C5de14kNzyUeDPmIXOcXfTwRzdv/OpNeiZoXFjHVmiL1eiw g/SQTkYTpwokT12xxOtPaiRkuQ== X-Google-Smtp-Source: AA6agR4zqUyCOz7UeYx3gb/1BVfk3brb7qMNS9yuuT17I/dl5o+tdGlomKfd9D9Qo+BAH1l8rlRK4A== X-Received: by 2002:a05:6830:10c9:b0:636:d88f:1299 with SMTP id z9-20020a05683010c900b00636d88f1299mr6217405oto.134.1660580441763; Mon, 15 Aug 2022 09:20:41 -0700 (PDT) Received: from localhost.localdomain ([184.4.90.121]) by smtp.gmail.com with ESMTPSA id x91-20020a9d37e4000000b00636ee04e7aesm2163371otb.67.2022.08.15.09.20.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Aug 2022 09:20:41 -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, tixxdz@gmail.com, Frederick Lawler Subject: [PATCH v5 4/4] selinux: Implement userns_create hook Date: Mon, 15 Aug 2022 11:20:28 -0500 Message-Id: <20220815162028.926858-5-fred@cloudflare.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220815162028.926858-1-fred@cloudflare.com> References: <20220815162028.926858-1-fred@cloudflare.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@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 v4: - None 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 79573504783b..b9f1078450b3 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4221,6 +4221,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) @@ -7111,6 +7119,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 } };