From patchwork Thu Jul 11 11:18:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730496 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4A22916B392; Thu, 11 Jul 2024 11:14:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696447; cv=none; b=n7AtKVriJHJ8Z3c3Qf9YFQAfPVzLMuwUusYZBNVA53sj9UWPIpNXMxpRp7bBiAPgHzYos6OSRLq7JOUDlM/s9F3usKv3YozSYx1A6iCgJF5sJuJ3IpuC2f7K/3zd9hkm5wZ+CVChFC00TUaqVAJjLltQg2k0e9Pakr7OffKe+ik= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696447; c=relaxed/simple; bh=F2DBOYAey1NBHWQhzeFhHSb9csczr8YPT8WbPlwEQb8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Q9qXJ8nuAWzDi1gG86V1vEtBhUpiB1e2CaoIn/ywzpq5K+I3e4ofbX3ZCUUeDJlKFgPL2BLDUgU94IG8XxtUCi0h05pQ4IGgin8ReBLQCxPGHGVGlG2Fg/yoAza3RtSSD/sjEZXFPmsGG00R3XItd4znS7mDRmgFxDEm5UHxmUk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.93.142]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTP id 4WKXCr713pz4f3jrw; Thu, 11 Jul 2024 19:13:44 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 9C8D41A0187; Thu, 11 Jul 2024 19:13:56 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgCHjPVxvo9mulQgBw--.25300S3; Thu, 11 Jul 2024 19:13:56 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 01/20] lsm: Refactor return value of LSM hook vm_enough_memory Date: Thu, 11 Jul 2024 19:18:49 +0800 Message-Id: <20240711111908.3817636-2-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711111908.3817636-1-xukuohai@huaweicloud.com> References: <20240711111908.3817636-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgCHjPVxvo9mulQgBw--.25300S3 X-Coremail-Antispam: 1UD129KBjvJXoWxur48GF1DAw17Kr47ur1rWFg_yoW7Gr4kpF s5Ka13KrWvkFyxZrs7GanxC3W3t34fWF4UGrWUu34Fk3ZFvr17KF4UAw1Y9r1UtrW8tasF qFW29rs3Ca1qq37anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBFb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUGw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV W8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMc Ij6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_ Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2Ij64 vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8G jcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42IY6x IIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVWxJVW8Jr1lIxAIcVCF 04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r1j6r4UMIIF0xvEx4A2jsIEc7 CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x07UAHUDUUUUU= X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai To be consistent with most LSM hooks, convert the return value of hook vm_enough_memory to 0 or a negative error code. Before: - Hook vm_enough_memory returns 1 if permission is granted, 0 if not. - LSM_RET_DEFAULT(vm_enough_memory_mm) is 1. After: - Hook vm_enough_memory reutrns 0 if permission is granted, negative error code if not. - LSM_RET_DEFAULT(vm_enough_memory_mm) is 0. Signed-off-by: Xu Kuohai --- include/linux/lsm_hook_defs.h | 2 +- include/linux/security.h | 2 +- security/commoncap.c | 11 +++-------- security/security.c | 11 +++++------ security/selinux/hooks.c | 15 ++++----------- 5 files changed, 14 insertions(+), 27 deletions(-) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 44488b1ab9a9..e6e6f8473955 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -48,7 +48,7 @@ LSM_HOOK(int, 0, quota_on, struct dentry *dentry) LSM_HOOK(int, 0, syslog, int type) LSM_HOOK(int, 0, settime, const struct timespec64 *ts, const struct timezone *tz) -LSM_HOOK(int, 1, vm_enough_memory, struct mm_struct *mm, long pages) +LSM_HOOK(int, 0, vm_enough_memory, struct mm_struct *mm, long pages) LSM_HOOK(int, 0, bprm_creds_for_exec, struct linux_binprm *bprm) LSM_HOOK(int, 0, bprm_creds_from_file, struct linux_binprm *bprm, const struct file *file) LSM_HOOK(int, 0, bprm_check_security, struct linux_binprm *bprm) diff --git a/include/linux/security.h b/include/linux/security.h index de3af33e6ff5..454f96307cb9 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -634,7 +634,7 @@ static inline int security_settime64(const struct timespec64 *ts, static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) { - return __vm_enough_memory(mm, pages, cap_vm_enough_memory(mm, pages)); + return __vm_enough_memory(mm, pages, !cap_vm_enough_memory(mm, pages)); } static inline int security_bprm_creds_for_exec(struct linux_binprm *bprm) diff --git a/security/commoncap.c b/security/commoncap.c index 162d96b3a676..cefad323a0b1 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -1396,17 +1396,12 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, * Determine whether the allocation of a new virtual mapping by the current * task is permitted. * - * Return: 1 if permission is granted, 0 if not. + * Return: 0 if permission granted, negative error code if not. */ int cap_vm_enough_memory(struct mm_struct *mm, long pages) { - int cap_sys_admin = 0; - - if (cap_capable(current_cred(), &init_user_ns, - CAP_SYS_ADMIN, CAP_OPT_NOAUDIT) == 0) - cap_sys_admin = 1; - - return cap_sys_admin; + return cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN, + CAP_OPT_NOAUDIT); } /** diff --git a/security/security.c b/security/security.c index e5ca08789f74..3475f0cab3da 100644 --- a/security/security.c +++ b/security/security.c @@ -1115,15 +1115,14 @@ int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) int rc; /* - * The module will respond with a positive value if - * it thinks the __vm_enough_memory() call should be - * made with the cap_sys_admin set. If all of the modules - * agree that it should be set it will. If any module - * thinks it should not be set it won't. + * The module will respond with 0 if it thinks the __vm_enough_memory() + * call should be made with the cap_sys_admin set. If all of the modules + * agree that it should be set it will. If any module thinks it should + * not be set it won't. */ hlist_for_each_entry(hp, &security_hook_heads.vm_enough_memory, list) { rc = hp->hook.vm_enough_memory(mm, pages); - if (rc <= 0) { + if (rc < 0) { cap_sys_admin = 0; break; } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 7eed331e90f0..9cd5a8f1f6a3 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2202,23 +2202,16 @@ static int selinux_syslog(int type) } /* - * Check that a process has enough memory to allocate a new virtual - * mapping. 0 means there is enough memory for the allocation to - * succeed and -ENOMEM implies there is not. + * Check permission for allocating a new virtual mapping. Returns + * 0 if permission is granted, negative error code if not. * * Do not audit the selinux permission check, as this is applied to all * processes that allocate mappings. */ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) { - int rc, cap_sys_admin = 0; - - rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN, - CAP_OPT_NOAUDIT, true); - if (rc == 0) - cap_sys_admin = 1; - - return cap_sys_admin; + return cred_has_capability(current_cred(), CAP_SYS_ADMIN, + CAP_OPT_NOAUDIT, true); } /* binprm security operations */ From patchwork Thu Jul 11 11:18:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730489 Received: from dggsgout11.his.huawei.com (dggsgout11.his.huawei.com [45.249.212.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 40AA415CD61; Thu, 11 Jul 2024 11:14:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696442; cv=none; b=G88jRs4+rb9jeqcGiYBB9mo8hRzeAutvXE0HFDXfp1Wi/VBOTnycuT55eOQs+sAvXxagjRw+g3ajDBLAj8ffrTEZ+RuDfMPSLR5FxrT47plL5aO2ApoYb/p+iBKaUM8Z0dSaUo+A4w2xTrLXiRzcqvwNv718ELBhMDimyEI6/Og= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696442; c=relaxed/simple; bh=Hg9ese+3RioISfNTgvRm6HlDHVGrAICdXCleHqiZp3o=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=dOJCi2z6Za/FQgW/GlftM/LQjonui5CnOdYy1muaDE7uNY0XkCUrERhDU8DQ+CkVq5LZizjZNHVgksvCGyZktMkD2k/8C34OuBoQnkXlWx//5UriXmyfQty2PtAQyY+J69jfFCqbJbXScJZUXWnM8cok0H6N9a1yJnimpeN9JbI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.235]) by dggsgout11.his.huawei.com (SkyGuard) with ESMTP id 4WKXCq6g8rz4f3m6w; Thu, 11 Jul 2024 19:13:43 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id CA1321A0572; Thu, 11 Jul 2024 19:13:56 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgCHjPVxvo9mulQgBw--.25300S4; Thu, 11 Jul 2024 19:13:56 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 02/20] lsm: Refactor return value of LSM hook inode_need_killpriv Date: Thu, 11 Jul 2024 19:18:50 +0800 Message-Id: <20240711111908.3817636-3-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711111908.3817636-1-xukuohai@huaweicloud.com> References: <20240711111908.3817636-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgCHjPVxvo9mulQgBw--.25300S4 X-Coremail-Antispam: 1UD129KBjvJXoW3AFWfGw4xWFW5Ary7Gr4xXrb_yoW3XFy7pF 4UKF13Gws5XFy7Wrn7tFsru34SvFWfWrW7JFZ09w12yFnrJr1xKr4ak3yUCryrCr1j9rnI v3ZFkw4rCr15JrUanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBIb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUXw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV W8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMc Ij6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_ Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2Ij64 vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8G jcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42IY6x IIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF0xvE 42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42IY6I8E87Iv6x kF7I0E14v26r4UJVWxJrUvcSsGvfC2KfnxnUUI43ZEXa7IU1sa9DUUUUU== X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai To be consistent with most LSM hooks, convert the return value of hook inode_need_killpriv to 0 or a negative error code. Before: - Both hook inode_need_killpriv and func security_inode_need_killpriv return > 0 if security_inode_killpriv is required, 0 if not, and < 0 to abort the operation. After: - Both hook inode_need_killpriv and func security_inode_need_killpriv return 0 on success and a negative error code on failure. On success, hook inode_need_killpriv sets output param @need to true if security_inode_killpriv is required, and false if not. When @need is true, func security_inode_need_killpriv sets ATTR_KILL_PRIV flag in @attr; when false, it clears the flag. On failure, @need and @attr remains unchanged. Signed-off-by: Xu Kuohai --- fs/attr.c | 5 ++--- fs/inode.c | 4 +--- include/linux/lsm_hook_defs.h | 2 +- include/linux/security.h | 20 ++++++++++++++++---- security/commoncap.c | 12 ++++++++---- security/security.c | 29 ++++++++++++++++++++++++----- 6 files changed, 52 insertions(+), 20 deletions(-) diff --git a/fs/attr.c b/fs/attr.c index 960a310581eb..aaadc721c982 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -427,11 +427,10 @@ int notify_change(struct mnt_idmap *idmap, struct dentry *dentry, attr->ia_mtime = timestamp_truncate(attr->ia_mtime, inode); if (ia_valid & ATTR_KILL_PRIV) { - error = security_inode_need_killpriv(dentry); + error = security_inode_need_killpriv(dentry, &ia_valid); if (error < 0) return error; - if (error == 0) - ia_valid = attr->ia_valid &= ~ATTR_KILL_PRIV; + attr->ia_valid = ia_valid; } /* diff --git a/fs/inode.c b/fs/inode.c index 3a41f83a4ba5..cd335dc3a3bc 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -2012,11 +2012,9 @@ int dentry_needs_remove_privs(struct mnt_idmap *idmap, return 0; mask = setattr_should_drop_suidgid(idmap, inode); - ret = security_inode_need_killpriv(dentry); + ret = security_inode_need_killpriv(dentry, &mask); if (ret < 0) return ret; - if (ret) - mask |= ATTR_KILL_PRIV; return mask; } diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index e6e6f8473955..964849de424b 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -165,7 +165,7 @@ LSM_HOOK(int, 0, inode_remove_acl, struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name) LSM_HOOK(void, LSM_RET_VOID, inode_post_remove_acl, struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name) -LSM_HOOK(int, 0, inode_need_killpriv, struct dentry *dentry) +LSM_HOOK(int, 0, inode_need_killpriv, struct dentry *dentry, bool *need) LSM_HOOK(int, 0, inode_killpriv, struct mnt_idmap *idmap, struct dentry *dentry) LSM_HOOK(int, -EOPNOTSUPP, inode_getsecurity, struct mnt_idmap *idmap, diff --git a/include/linux/security.h b/include/linux/security.h index 454f96307cb9..1614ef5b2dd2 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -161,7 +161,7 @@ int cap_inode_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); int cap_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, const char *name); -int cap_inode_need_killpriv(struct dentry *dentry); +int cap_inode_need_killpriv(struct dentry *dentry, bool *need); int cap_inode_killpriv(struct mnt_idmap *idmap, struct dentry *dentry); int cap_inode_getsecurity(struct mnt_idmap *idmap, struct inode *inode, const char *name, void **buffer, @@ -389,7 +389,7 @@ int security_inode_listxattr(struct dentry *dentry); int security_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, const char *name); void security_inode_post_removexattr(struct dentry *dentry, const char *name); -int security_inode_need_killpriv(struct dentry *dentry); +int security_inode_need_killpriv(struct dentry *dentry, int *attr); int security_inode_killpriv(struct mnt_idmap *idmap, struct dentry *dentry); int security_inode_getsecurity(struct mnt_idmap *idmap, struct inode *inode, const char *name, @@ -971,9 +971,21 @@ static inline void security_inode_post_removexattr(struct dentry *dentry, const char *name) { } -static inline int security_inode_need_killpriv(struct dentry *dentry) +static inline int security_inode_need_killpriv(struct dentry *dentry, int *attr) { - return cap_inode_need_killpriv(dentry); + int rc; + bool need = false; + + rc = cap_inode_need_killpriv(dentry, &need); + if (rc < 0) + return rc; + + if (need) + *attr |= ATTR_KILL_PRIV; + else + *attr &= ~ATTR_KILL_PRIV; + + return 0; } static inline int security_inode_killpriv(struct mnt_idmap *idmap, diff --git a/security/commoncap.c b/security/commoncap.c index cefad323a0b1..17d6188d22cf 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -286,21 +286,25 @@ int cap_capset(struct cred *new, /** * cap_inode_need_killpriv - Determine if inode change affects privileges * @dentry: The inode/dentry in being changed with change marked ATTR_KILL_PRIV + * @need: If inode_killpriv() is needed * * Determine if an inode having a change applied that's marked ATTR_KILL_PRIV * affects the security markings on that inode, and if it is, should * inode_killpriv() be invoked or the change rejected. * - * Return: 1 if security.capability has a value, meaning inode_killpriv() - * is required, 0 otherwise, meaning inode_killpriv() is not required. + * Return: Always returns 0. If security.capability has a value, meaning + * inode_killpriv() is required, @need is set to true. */ -int cap_inode_need_killpriv(struct dentry *dentry) +int cap_inode_need_killpriv(struct dentry *dentry, bool *need) { struct inode *inode = d_backing_inode(dentry); int error; error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0); - return error > 0; + if (error > 0) + *need = true; + + return 0; } /** diff --git a/security/security.c b/security/security.c index 3475f0cab3da..a4abcd86eb36 100644 --- a/security/security.c +++ b/security/security.c @@ -2490,17 +2490,36 @@ void security_inode_post_removexattr(struct dentry *dentry, const char *name) /** * security_inode_need_killpriv() - Check if security_inode_killpriv() required * @dentry: associated dentry + * @attr: attribute flags * * Called when an inode has been changed to determine if * security_inode_killpriv() should be called. * - * Return: Return <0 on error to abort the inode change operation, return 0 if - * security_inode_killpriv() does not need to be called, return >0 if - * security_inode_killpriv() does need to be called. + * Return: Return 0 on success, negative error code on failure. + * On success, set ATTR_KILL_PRIV flag in @attr when @need is true, + * clears it when false. */ -int security_inode_need_killpriv(struct dentry *dentry) +int security_inode_need_killpriv(struct dentry *dentry, int *attr) { - return call_int_hook(inode_need_killpriv, dentry); + int rc; + bool need = false; + struct security_hook_list *hp; + + hlist_for_each_entry(hp, &security_hook_heads.inode_need_killpriv, + list) { + rc = hp->hook.inode_need_killpriv(dentry, &need); + if (rc < 0) + return rc; + if (need) + break; + } + + if (need) + *attr |= ATTR_KILL_PRIV; + else + *attr &= ~ATTR_KILL_PRIV; + + return 0; } /** From patchwork Thu Jul 11 11:18:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730495 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4A1E116B38F; Thu, 11 Jul 2024 11:14:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696447; cv=none; b=IG9LHpgeZ1ZhzCUiFp/i/kj6YZPXpy5dGc575JBOrNWqRIjg1BbanQKv4Q+PwDjiWGIHfssy3sH0/UKOtMaWY1wrP2Jm0UR3urh2PahmseY4wJn17srAe5Pe6QVXngTFj4bL0DhiooAhFGJmSGZu/AZpIxP3lOza9ZkS9qAhkp0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696447; c=relaxed/simple; bh=PM8AFPWlS6LkP5AL3p5RSlFkj5rPkUtAUSQ60pJZkWo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=PrlSZE8nYwUo5q+C+Xla3cIFFdXmcLhAZHW/FB/zmJEspSJVa6d/701Tkd8x+SbRFDCEGujHSxD+zjeOy9w6IwQBy8ATBq3iS66L2uolTNi9JW9EVRC+oB3oQ4/SG0mYvdaIyIZtVOg2BRibLled4DUfdqZ9wC9DcJfz1iiI9mU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.216]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTP id 4WKXCs2JkNz4f3jsL; Thu, 11 Jul 2024 19:13:45 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 011CB1A0170; Thu, 11 Jul 2024 19:13:56 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgCHjPVxvo9mulQgBw--.25300S5; Thu, 11 Jul 2024 19:13:56 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 03/20] lsm: Refactor return value of LSM hook inode_getsecurity Date: Thu, 11 Jul 2024 19:18:51 +0800 Message-Id: <20240711111908.3817636-4-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711111908.3817636-1-xukuohai@huaweicloud.com> References: <20240711111908.3817636-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgCHjPVxvo9mulQgBw--.25300S5 X-Coremail-Antispam: 1UD129KBjvJXoWxtry5AryUJF1fKF1xXryrZwb_yoWfuF4kpF 45KanxGr4fXFyUWrn2yF17u3WSvFWfGrWUCrWq9wnxAFnFvr10qF12kF17CF1rGrW8Cr12 q3ZF9wsxCw4UJrDanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBIb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUWw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV W8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMc Ij6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_ Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2Ij64 vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8G jcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42IY6x IIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF0xvE 42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42IY6I8E87Iv6x kF7I0E14v26r4UJVWxJrUvcSsGvfC2KfnxnUUI43ZEXa7IU1c4S7UUUUU== X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai To be consistent with most LSM hooks, convert the return value of hook inode_getsecurity to 0 or a negative error code. Before: - Hook inode_getsecurity returns size of buffer on success or a negative error code on failure. After: - Hook inode_getsecurity returns 0 on success or a negative error code on failure. An output parameter @len is introduced to hold the buffer size on success. Signed-off-by: Xu Kuohai --- fs/xattr.c | 19 ++++++++++--------- include/linux/lsm_hook_defs.h | 3 ++- include/linux/security.h | 12 ++++++------ security/commoncap.c | 9 ++++++--- security/security.c | 11 ++++++----- security/selinux/hooks.c | 16 ++++++---------- security/smack/smack_lsm.c | 14 +++++++------- 7 files changed, 43 insertions(+), 41 deletions(-) diff --git a/fs/xattr.c b/fs/xattr.c index f8b643f91a98..f4e3bedf7272 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -339,27 +339,28 @@ xattr_getsecurity(struct mnt_idmap *idmap, struct inode *inode, const char *name, void *value, size_t size) { void *buffer = NULL; - ssize_t len; + int error; + u32 len; if (!value || !size) { - len = security_inode_getsecurity(idmap, inode, name, - &buffer, false); + error = security_inode_getsecurity(idmap, inode, name, + false, &buffer, &len); goto out_noalloc; } - len = security_inode_getsecurity(idmap, inode, name, &buffer, - true); - if (len < 0) - return len; + error = security_inode_getsecurity(idmap, inode, name, true, + &buffer, &len); + if (error) + return error; if (size < len) { - len = -ERANGE; + error = -ERANGE; goto out; } memcpy(value, buffer, len); out: kfree(buffer); out_noalloc: - return len; + return error < 0 ? error : len; } /* diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 964849de424b..4f056f2613af 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -169,7 +169,8 @@ LSM_HOOK(int, 0, inode_need_killpriv, struct dentry *dentry, bool *need) LSM_HOOK(int, 0, inode_killpriv, struct mnt_idmap *idmap, struct dentry *dentry) LSM_HOOK(int, -EOPNOTSUPP, inode_getsecurity, struct mnt_idmap *idmap, - struct inode *inode, const char *name, void **buffer, bool alloc) + struct inode *inode, const char *name, bool alloc, void **buffer, + u32 *len) LSM_HOOK(int, -EOPNOTSUPP, inode_setsecurity, struct inode *inode, const char *name, const void *value, size_t size, int flags) LSM_HOOK(int, 0, inode_listsecurity, struct inode *inode, char *buffer, diff --git a/include/linux/security.h b/include/linux/security.h index 1614ef5b2dd2..b6d296d21438 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -164,8 +164,8 @@ int cap_inode_removexattr(struct mnt_idmap *idmap, int cap_inode_need_killpriv(struct dentry *dentry, bool *need); int cap_inode_killpriv(struct mnt_idmap *idmap, struct dentry *dentry); int cap_inode_getsecurity(struct mnt_idmap *idmap, - struct inode *inode, const char *name, void **buffer, - bool alloc); + struct inode *inode, const char *name, bool alloc, + void **buffer, u32 *len); extern int cap_mmap_addr(unsigned long addr); extern int cap_mmap_file(struct file *file, unsigned long reqprot, unsigned long prot, unsigned long flags); @@ -393,7 +393,7 @@ int security_inode_need_killpriv(struct dentry *dentry, int *attr); int security_inode_killpriv(struct mnt_idmap *idmap, struct dentry *dentry); int security_inode_getsecurity(struct mnt_idmap *idmap, struct inode *inode, const char *name, - void **buffer, bool alloc); + bool alloc, void **buffer, u32 *len); int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags); int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size); void security_inode_getsecid(struct inode *inode, u32 *secid); @@ -996,10 +996,10 @@ static inline int security_inode_killpriv(struct mnt_idmap *idmap, static inline int security_inode_getsecurity(struct mnt_idmap *idmap, struct inode *inode, - const char *name, void **buffer, - bool alloc) + const char *name, bool alloc, + void **buffer, u32 *len) { - return cap_inode_getsecurity(idmap, inode, name, buffer, alloc); + return cap_inode_getsecurity(idmap, inode, name, alloc, buffer, len); } static inline int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) diff --git a/security/commoncap.c b/security/commoncap.c index 17d6188d22cf..ff82e2ab6f8f 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -383,8 +383,8 @@ static bool is_v3header(int size, const struct vfs_cap_data *cap) * so that's good. */ int cap_inode_getsecurity(struct mnt_idmap *idmap, - struct inode *inode, const char *name, void **buffer, - bool alloc) + struct inode *inode, const char *name, + bool alloc, void **buffer, u32 *len) { int size; kuid_t kroot; @@ -485,7 +485,10 @@ int cap_inode_getsecurity(struct mnt_idmap *idmap, } out_free: kfree(tmpbuf); - return size; + if (size < 0) + return size; + *len = size; + return 0; } /** diff --git a/security/security.c b/security/security.c index a4abcd86eb36..614f14cbfff7 100644 --- a/security/security.c +++ b/security/security.c @@ -2544,8 +2544,9 @@ int security_inode_killpriv(struct mnt_idmap *idmap, * @idmap: idmap of the mount * @inode: inode * @name: xattr name - * @buffer: security label buffer * @alloc: allocation flag + * @buffer: security label buffer + * @len: security label length * * Retrieve a copy of the extended attribute representation of the security * label associated with @name for @inode via @buffer. Note that @name is the @@ -2553,17 +2554,17 @@ int security_inode_killpriv(struct mnt_idmap *idmap, * @alloc is used to specify if the call should return a value via the buffer * or just the value length. * - * Return: Returns size of buffer on success. + * Return: Returns 0 on success or a negative error code on failure. */ int security_inode_getsecurity(struct mnt_idmap *idmap, struct inode *inode, const char *name, - void **buffer, bool alloc) + bool alloc, void **buffer, u32 *len) { if (unlikely(IS_PRIVATE(inode))) return LSM_RET_DEFAULT(inode_getsecurity); - return call_int_hook(inode_getsecurity, idmap, inode, name, buffer, - alloc); + return call_int_hook(inode_getsecurity, idmap, inode, name, alloc, + buffer, len); } /** diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9cd5a8f1f6a3..70792bba24d9 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3407,7 +3407,7 @@ static int selinux_path_notify(const struct path *path, u64 mask, */ static int selinux_inode_getsecurity(struct mnt_idmap *idmap, struct inode *inode, const char *name, - void **buffer, bool alloc) + bool alloc, void **buffer, u32 *len) { u32 size; int error; @@ -3440,14 +3440,14 @@ static int selinux_inode_getsecurity(struct mnt_idmap *idmap, &context, &size); if (error) return error; - error = size; + *len = size; if (alloc) { *buffer = context; goto out_nofree; } kfree(context); out_nofree: - return error; + return 0; } static int selinux_inode_setsecurity(struct inode *inode, const char *name, @@ -6644,13 +6644,9 @@ static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) { - int len = 0; - len = selinux_inode_getsecurity(&nop_mnt_idmap, inode, - XATTR_SELINUX_SUFFIX, ctx, true); - if (len < 0) - return len; - *ctxlen = len; - return 0; + return selinux_inode_getsecurity(&nop_mnt_idmap, inode, + XATTR_SELINUX_SUFFIX, + true, ctx, ctxlen); } #ifdef CONFIG_KEYS diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index f5cbec1e6a92..e7a5f6fd9a2d 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1543,14 +1543,15 @@ static int smack_inode_remove_acl(struct mnt_idmap *idmap, * @idmap: idmap of the mount * @inode: the object * @name: attribute name - * @buffer: where to put the result * @alloc: duplicate memory + * @buffer: where to put the result + * @len: where to put the result length * - * Returns the size of the attribute or an error code + * Returns 0 on success or a negative error code on failure */ static int smack_inode_getsecurity(struct mnt_idmap *idmap, struct inode *inode, const char *name, - void **buffer, bool alloc) + bool alloc, void **buffer, u32 *len) { struct socket_smack *ssp; struct socket *sock; @@ -1558,7 +1559,6 @@ static int smack_inode_getsecurity(struct mnt_idmap *idmap, struct inode *ip = inode; struct smack_known *isp; struct inode_smack *ispp; - size_t label_len; char *label = NULL; if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { @@ -1594,15 +1594,15 @@ static int smack_inode_getsecurity(struct mnt_idmap *idmap, if (!label) label = isp->smk_known; - label_len = strlen(label); - if (alloc) { *buffer = kstrdup(label, GFP_KERNEL); if (*buffer == NULL) return -ENOMEM; } - return label_len; + *len = strlen(label); + + return 0; } From patchwork Thu Jul 11 11:18:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730494 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4A19E16B38E; Thu, 11 Jul 2024 11:14:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696447; cv=none; b=bLWfE9gTQJrYgf0bfx6qq8yQR4F5GwblPqhdzEvFMfqMTg2x3CS2idO8z7i/s5sB4mwDF77sdlk9tCxkeDRE7eeNwFmDQ+EuZ0XtV/s+qQl7/CABQKIaNaPG/G9FbDi5+yVnTC26Yu3lCHKLsPcexeCTQKYNolWFPs2oELz+ZII= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696447; c=relaxed/simple; bh=RYfGu/7aP6JIgSpGZxYMDl39rhFU2E3iLOaQK5oD8W0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=uW6zIk0CIBqYJdmMcBx6eu8D1hDcgDWGjlJhMy6lf9CU++z4vAgMfZFcK3Bub0Bqzm3AbPC/wN9ctIlJp9KzbtjSTH+hRB6DgZIt2E81vCNdrPufz0fYX7kvF37/LuqEXVz1YtEqXAPMTtL+qh2W12YzTVULC8q1CJqDeFwz//Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.235]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTP id 4WKXCs3mLgz4f3jHg; Thu, 11 Jul 2024 19:13:45 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 2E1A21A0568; Thu, 11 Jul 2024 19:13:57 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgCHjPVxvo9mulQgBw--.25300S6; Thu, 11 Jul 2024 19:13:56 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 04/20] lsm: Refactor return value of LSM hook inode_listsecurity Date: Thu, 11 Jul 2024 19:18:52 +0800 Message-Id: <20240711111908.3817636-5-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711111908.3817636-1-xukuohai@huaweicloud.com> References: <20240711111908.3817636-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgCHjPVxvo9mulQgBw--.25300S6 X-Coremail-Antispam: 1UD129KBjvJXoWxKrWUuw4xury3ArykJr15XFb_yoW3Zw15pF 45Ka15Jr1rJFyxWrn7t3Zxu3WS9FZ5GrWUG393Cw13AF1kJw1vqF1FkFyY9FyrJr18Gr10 qanrursxGw4UZr7anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBqb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E 14v26rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7 xfMcIj6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Y z7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2 Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s02 6x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42 IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF 0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42IY6I8E87 Iv6xkF7I0E14v26r4UJVWxJrUvcSsGvfC2KfnxnUUI43ZEXa7IU13l1DUUUUU== X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai To be consistent with most LSM hooks, convert the return value of hook inode_listsecurity to 0 or a negative error code. Before: - Hook inode_listsecurity returns number of bytes used/required on success or a negative error code on failure. After: - Hook inode_listsecurity returns 0 on success or a negative error code on failure. An output parameter @bytes is introduced to hold the number of bytes used/required on success. Signed-off-by: Xu Kuohai --- fs/nfs/nfs4proc.c | 5 ++++- fs/xattr.c | 5 ++++- include/linux/lsm_hook_defs.h | 2 +- include/linux/security.h | 7 ++++--- net/socket.c | 9 +++++---- security/security.c | 29 +++++++++++++++++++++++++---- security/selinux/hooks.c | 8 +++++--- security/smack/smack_lsm.c | 6 ++++-- 8 files changed, 52 insertions(+), 19 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index a691fa10b3e9..6d75758ba3d5 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -7848,10 +7848,13 @@ static int nfs4_xattr_get_nfs4_label(const struct xattr_handler *handler, static ssize_t nfs4_listxattr_nfs4_label(struct inode *inode, char *list, size_t list_len) { + size_t bytes; int len = 0; if (nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL)) { - len = security_inode_listsecurity(inode, list, list_len); + len = security_inode_listsecurity(inode, list, list_len, &bytes); + if (!len) + len = bytes; if (len >= 0 && list_len && len > list_len) return -ERANGE; } diff --git a/fs/xattr.c b/fs/xattr.c index f4e3bedf7272..ab7d7123a016 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -485,6 +485,7 @@ vfs_listxattr(struct dentry *dentry, char *list, size_t size) { struct inode *inode = d_inode(dentry); ssize_t error; + size_t bytes; error = security_inode_listxattr(dentry); if (error) @@ -493,7 +494,9 @@ vfs_listxattr(struct dentry *dentry, char *list, size_t size) if (inode->i_op->listxattr) { error = inode->i_op->listxattr(dentry, list, size); } else { - error = security_inode_listsecurity(inode, list, size); + error = security_inode_listsecurity(inode, list, size, &bytes); + if (!error) + error = bytes; if (size && error > size) error = -ERANGE; } diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 4f056f2613af..1b7761ae2777 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -174,7 +174,7 @@ LSM_HOOK(int, -EOPNOTSUPP, inode_getsecurity, struct mnt_idmap *idmap, LSM_HOOK(int, -EOPNOTSUPP, inode_setsecurity, struct inode *inode, const char *name, const void *value, size_t size, int flags) LSM_HOOK(int, 0, inode_listsecurity, struct inode *inode, char *buffer, - size_t buffer_size) + size_t buffer_size, size_t *bytes) LSM_HOOK(void, LSM_RET_VOID, inode_getsecid, struct inode *inode, u32 *secid) LSM_HOOK(int, 0, inode_copy_up, struct dentry *src, struct cred **new) LSM_HOOK(int, -EOPNOTSUPP, inode_copy_up_xattr, struct dentry *src, diff --git a/include/linux/security.h b/include/linux/security.h index b6d296d21438..0ed53e232c4d 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -395,7 +395,7 @@ int security_inode_getsecurity(struct mnt_idmap *idmap, struct inode *inode, const char *name, bool alloc, void **buffer, u32 *len); int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags); -int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size); +int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size, size_t *bytes); void security_inode_getsecid(struct inode *inode, u32 *secid); int security_inode_copy_up(struct dentry *src, struct cred **new); int security_inode_copy_up_xattr(struct dentry *src, const char *name); @@ -1007,9 +1007,10 @@ static inline int security_inode_setsecurity(struct inode *inode, const char *na return -EOPNOTSUPP; } -static inline int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size) +static inline int security_inode_listsecurity(struct inode *inode, char *buffer, + size_t buffer_size, size_t *bytes) { - return 0; + return *bytes = 0; } static inline void security_inode_getsecid(struct inode *inode, u32 *secid) diff --git a/net/socket.c b/net/socket.c index e416920e9399..43f0e3c9a6e0 100644 --- a/net/socket.c +++ b/net/socket.c @@ -571,12 +571,13 @@ static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer, size_t size) { - ssize_t len; + int err; + size_t len; ssize_t used = 0; - len = security_inode_listsecurity(d_inode(dentry), buffer, size); - if (len < 0) - return len; + err = security_inode_listsecurity(d_inode(dentry), buffer, size, &len); + if (err < 0) + return err; used += len; if (buffer) { if (size < used) diff --git a/security/security.c b/security/security.c index 614f14cbfff7..26eea8f4cd74 100644 --- a/security/security.c +++ b/security/security.c @@ -2597,20 +2597,41 @@ int security_inode_setsecurity(struct inode *inode, const char *name, * @inode: inode * @buffer: buffer * @buffer_size: size of buffer + * @bytes: number of bytes used/required * * Copy the extended attribute names for the security labels associated with * @inode into @buffer. The maximum size of @buffer is specified by * @buffer_size. @buffer may be NULL to request the size of the buffer * required. * - * Return: Returns number of bytes used/required on success. + * Return: Returns 0 on success or a negative error code on failure. */ int security_inode_listsecurity(struct inode *inode, - char *buffer, size_t buffer_size) + char *buffer, size_t buffer_size, + size_t *bytes) { + int rc; + size_t used; + struct security_hook_list *hp; + if (unlikely(IS_PRIVATE(inode))) - return 0; - return call_int_hook(inode_listsecurity, inode, buffer, buffer_size); + return *bytes = 0; + + used = 0; + hlist_for_each_entry(hp, &security_hook_heads.inode_listsecurity, + list) { + rc = hp->hook.inode_listsecurity(inode, buffer, buffer_size, + &used); + if (rc < 0) + return rc; + if (used != 0) + break; + } + + *bytes = used; + + return 0; + } EXPORT_SYMBOL(security_inode_listsecurity); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 70792bba24d9..5dedd3917d57 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3481,16 +3481,18 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, return 0; } -static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size) +static int selinux_inode_listsecurity(struct inode *inode, char *buffer, + size_t buffer_size, size_t *bytes) { const int len = sizeof(XATTR_NAME_SELINUX); if (!selinux_initialized()) - return 0; + return *bytes = 0; if (buffer && len <= buffer_size) memcpy(buffer, XATTR_NAME_SELINUX, len); - return len; + *bytes = len; + return 0; } static void selinux_inode_getsecid(struct inode *inode, u32 *secid) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index e7a5f6fd9a2d..6f73906bf7ea 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1611,16 +1611,18 @@ static int smack_inode_getsecurity(struct mnt_idmap *idmap, * @inode: the object * @buffer: where they go * @buffer_size: size of buffer + * @bytes: number of data bytes in buffer */ static int smack_inode_listsecurity(struct inode *inode, char *buffer, - size_t buffer_size) + size_t buffer_size, size_t *bytes) { int len = sizeof(XATTR_NAME_SMACK); if (buffer != NULL && len <= buffer_size) memcpy(buffer, XATTR_NAME_SMACK, len); - return len; + *bytes = len; + return 0; } /** From patchwork Thu Jul 11 11:18:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730490 Received: from dggsgout11.his.huawei.com (dggsgout11.his.huawei.com [45.249.212.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 635D415CD60; Thu, 11 Jul 2024 11:14:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696442; cv=none; b=CoxrBPdtlHZ1fs1K8TdigvkdVAJ3y/aqjAPdSYP5lLKJlQPWC2QlQCmCTJlW+7pblTqDst+9ksHDBsoX074sQRQeaig8tSai3ri+T2IYaCjjM2cOzhWY3NXUp2esBziyG4j4J38rMIbDCGhM6GxE6y/dkeBKXKDmzGqIbn4w+44= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696442; c=relaxed/simple; bh=4bixJwGuTWgSqOvL6zwccNF+B7ZssgQCR776AYlaV+M=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Qsi8POpOA004fBnWVw3B93FheoRkkXHq9njUEyjYtTq1fhcCsJT5B5g9t8pAlVAc9jhjUtskP/cYcmifBAGkC7AGtE16hiYycKnqgPuhvwTtYVTP0/L+P/GVxd7iHFTe4CY4VQSZiHPYCF82urM8qkXFbTZfrZTZ4zYyHmWRjIw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.216]) by dggsgout11.his.huawei.com (SkyGuard) with ESMTP id 4WKXCx55ZQz4f3kK5; Thu, 11 Jul 2024 19:13:49 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 59B001A0170; Thu, 11 Jul 2024 19:13:57 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgCHjPVxvo9mulQgBw--.25300S7; Thu, 11 Jul 2024 19:13:56 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 05/20] lsm: Refactor return value of LSM hook inode_copy_up_xattr Date: Thu, 11 Jul 2024 19:18:53 +0800 Message-Id: <20240711111908.3817636-6-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711111908.3817636-1-xukuohai@huaweicloud.com> References: <20240711111908.3817636-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgCHjPVxvo9mulQgBw--.25300S7 X-Coremail-Antispam: 1UD129KBjvJXoWxAw1kXF4DJFWkXFWrJF1fJFb_yoWruw4fpa 1Dtan2qr1rJFy7ZFykJF47ua1F93yfGFWUCa9xuw12yFZ3Xrn3Wryayr12gr45Wry8JF4k tanFvrs8C3WYy3DanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBqb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E 14v26rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7 xfMcIj6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Y z7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2 Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s02 6x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42 IY6xIIjxv20xvE14v26r1I6r4UMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF 0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42IY6I8E87 Iv6xkF7I0E14v26r4UJVWxJrUvcSsGvfC2KfnxnUUI43ZEXa7IU13l1DUUUUU== X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai To be consistent with most LSM hooks, convert the return value of hook inode_copy_up_xattr to 0 or a negative error code. Before: - Hook inode_copy_up_xattr returns 0 when accepting xattr, 1 when discarding xattr, -EOPNOTSUPP if it does not know xattr, or any other negative error code otherwise. After: - Hook inode_copy_up_xattr returns 0 when accepting xattr, *-ECANCELED* when discarding xattr, -EOPNOTSUPP if it does not know xattr, or any other negative error code otherwise. Signed-off-by: Xu Kuohai --- fs/overlayfs/copy_up.c | 6 +++--- security/integrity/evm/evm_main.c | 2 +- security/security.c | 12 ++++++------ security/selinux/hooks.c | 4 ++-- security/smack/smack_lsm.c | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index a5ef2005a2cc..337a5be99ac9 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -115,12 +115,12 @@ int ovl_copy_xattr(struct super_block *sb, const struct path *oldpath, struct de continue; error = security_inode_copy_up_xattr(old, name); - if (error < 0 && error != -EOPNOTSUPP) - break; - if (error == 1) { + if (error == -ECANCELED) { error = 0; continue; /* Discard */ } + if (error < 0 && error != -EOPNOTSUPP) + break; if (is_posix_acl_xattr(name)) { error = ovl_copy_acl(OVL_FS(sb), oldpath, new, name); diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 62fe66dd53ce..6924ed508ebd 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -1000,7 +1000,7 @@ static int evm_inode_copy_up_xattr(struct dentry *src, const char *name) case EVM_XATTR_HMAC: case EVM_IMA_XATTR_DIGSIG: default: - rc = 1; /* discard */ + rc = -ECANCELED; /* discard */ } kfree(xattr_data); diff --git a/security/security.c b/security/security.c index 26eea8f4cd74..12215ca286af 100644 --- a/security/security.c +++ b/security/security.c @@ -2675,18 +2675,18 @@ EXPORT_SYMBOL(security_inode_copy_up); * lower layer to the union/overlay layer. The caller is responsible for * reading and writing the xattrs, this hook is merely a filter. * - * Return: Returns 0 to accept the xattr, 1 to discard the xattr, -EOPNOTSUPP - * if the security module does not know about attribute, or a negative - * error code to abort the copy up. + * Return: Returns 0 to accept the xattr, -ECANCELED to discard the xattr, + * -EOPNOTSUPP if the security module does not know about attribute, + * or a negative error code to abort the copy up. */ int security_inode_copy_up_xattr(struct dentry *src, const char *name) { int rc; /* - * The implementation can return 0 (accept the xattr), 1 (discard the - * xattr), -EOPNOTSUPP if it does not know anything about the xattr or - * any other error code in case of an error. + * The implementation can return 0 (accept the xattr), -ECANCELED + * (discard the xattr), -EOPNOTSUPP if it does not know anything + * about the xattr or any other error code in case of an error. */ rc = call_int_hook(inode_copy_up_xattr, src, name); if (rc != LSM_RET_DEFAULT(inode_copy_up_xattr)) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5dedd3917d57..f9a6637dfd78 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3528,8 +3528,8 @@ static int selinux_inode_copy_up_xattr(struct dentry *dentry, const char *name) * xattrs up. Instead, filter out SELinux-related xattrs following * policy load. */ - if (selinux_initialized() && strcmp(name, XATTR_NAME_SELINUX) == 0) - return 1; /* Discard */ + if (selinux_initialized() && !strcmp(name, XATTR_NAME_SELINUX)) + return -ECANCELED; /* Discard */ /* * Any other attribute apart from SELINUX is not claimed, supported * by selinux. diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 6f73906bf7ea..ae8f1c2d0ca6 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4893,10 +4893,10 @@ static int smack_inode_copy_up(struct dentry *dentry, struct cred **new) static int smack_inode_copy_up_xattr(struct dentry *src, const char *name) { /* - * Return 1 if this is the smack access Smack attribute. + * Return -ECANCELED if this is the smack access Smack attribute. */ - if (strcmp(name, XATTR_NAME_SMACK) == 0) - return 1; + if (!strcmp(name, XATTR_NAME_SMACK)) + return -ECANCELED; return -EOPNOTSUPP; } From patchwork Thu Jul 11 11:18:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730498 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 39E8C166315; Thu, 11 Jul 2024 11:14:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696448; cv=none; b=RlMXBmJmcD5MAztyoMctPrej/MsQ3Flb75rkbWN09cOgxPAkJ/ORgF961tc/9tDE3G1bWDoJWAGBkH/MkhfVNB5zZevINEfcGcDfTWC8XPJdmRbRip+FKn+pQrkdNktl9kQESP7bfb3B1l3xplBN4py6jLvlP6/GL8OQvvgUDoo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696448; c=relaxed/simple; bh=sPPRJbcKUJ4f+xzo34ctXcJ2De278zOWocfbBBnM/nU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=DYUB+EgDkb9713tbN3zsq3kwS4SW6iY2N/HhX0KB274qsBBzg+k6MpYVEqobX0LhiGw6hHo9kO+1clVp964hK+4EBYlFkTzMZjCWVJSnqxsF62OLNMBPtfH95EgYkCrgZgjsBGTYM1oQ80fpcZax1RqJi4vfYmPP+OtuwuSmK3Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.216]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTP id 4WKXCs67JWz4f3jY1; Thu, 11 Jul 2024 19:13:45 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 82EF91A0170; Thu, 11 Jul 2024 19:13:57 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgCHjPVxvo9mulQgBw--.25300S8; Thu, 11 Jul 2024 19:13:57 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 06/20] lsm: Refactor return value of LSM hook getselfattr Date: Thu, 11 Jul 2024 19:18:54 +0800 Message-Id: <20240711111908.3817636-7-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711111908.3817636-1-xukuohai@huaweicloud.com> References: <20240711111908.3817636-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgCHjPVxvo9mulQgBw--.25300S8 X-Coremail-Antispam: 1UD129KBjvJXoWxKFWxXFW5tr4fKrWxJFWUurg_yoWfJw4UpF n5K3Zrtr40yF97WFWkAF47Ca1a9rySgry7J39xGw4SyFy5tr1xWFy3Ja4jkrWUGw1DCF4F yanF9r45CrsrC3DanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBqb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E 14v26rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7 xfMcIj6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Y z7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2 Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s02 6x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42 IY6xIIjxv20xvE14v26r1I6r4UMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF 0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42IY6I8E87 Iv6xkF7I0E14v26r4UJVWxJrUvcSsGvfC2KfnxnUUI43ZEXa7IU13l1DUUUUU== X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai To be consistent with most LSM hooks, convert the return value of hook getselfattr to 0 or a negative error code. Before: - Hook getselfattr returns number of attributes found on success or a negative error code on failure. After: - Hook getselfattr returns 0 on success or a negative error code on failure. An output parameter @nattr is introduced to hold the number of attributes found on success. Signed-off-by: Xu Kuohai --- include/linux/lsm_hook_defs.h | 2 +- include/linux/security.h | 5 +++-- security/apparmor/lsm.c | 5 +++-- security/lsm_syscalls.c | 6 +++++- security/security.c | 18 +++++++++++------- security/selinux/hooks.c | 13 +++++++++---- security/smack/smack_lsm.c | 13 +++++++++---- 7 files changed, 41 insertions(+), 21 deletions(-) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 1b7761ae2777..dbc16f14f42f 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -282,7 +282,7 @@ LSM_HOOK(int, 0, netlink_send, struct sock *sk, struct sk_buff *skb) LSM_HOOK(void, LSM_RET_VOID, d_instantiate, struct dentry *dentry, struct inode *inode) LSM_HOOK(int, -EOPNOTSUPP, getselfattr, unsigned int attr, - struct lsm_ctx __user *ctx, u32 *size, u32 flags) + struct lsm_ctx __user *ctx, u32 *size, u32 flags, u32 *nattr) LSM_HOOK(int, -EOPNOTSUPP, setselfattr, unsigned int attr, struct lsm_ctx *ctx, u32 size, u32 flags) LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name, diff --git a/include/linux/security.h b/include/linux/security.h index 0ed53e232c4d..96a63e132abf 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -491,7 +491,7 @@ int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops, unsigned nsops, int alter); void security_d_instantiate(struct dentry *dentry, struct inode *inode); int security_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, - u32 __user *size, u32 flags); + u32 __user *size, u32 flags, u32 *nattr); int security_setselfattr(unsigned int attr, struct lsm_ctx __user *ctx, u32 size, u32 flags); int security_getprocattr(struct task_struct *p, int lsmid, const char *name, @@ -1420,7 +1420,8 @@ static inline void security_d_instantiate(struct dentry *dentry, static inline int security_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, - size_t __user *size, u32 flags) + size_t __user *size, u32 flags, + u32 *nattr) { return -EOPNOTSUPP; } diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 6239777090c4..72dd09993f28 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -779,7 +779,7 @@ static int apparmor_sb_pivotroot(const struct path *old_path, } static int apparmor_getselfattr(unsigned int attr, struct lsm_ctx __user *lx, - u32 *size, u32 flags) + u32 *size, u32 flags, u32 *nattr) { int error = -ENOENT; struct aa_task_ctx *ctx = task_ctx(current); @@ -815,7 +815,8 @@ static int apparmor_getselfattr(unsigned int attr, struct lsm_ctx __user *lx, if (error < 0) return error; - return 1; + *nattr = 1; + return 0; } static int apparmor_getprocattr(struct task_struct *task, const char *name, diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c index 8440948a690c..845866f94b03 100644 --- a/security/lsm_syscalls.c +++ b/security/lsm_syscalls.c @@ -77,7 +77,11 @@ SYSCALL_DEFINE4(lsm_set_self_attr, unsigned int, attr, struct lsm_ctx __user *, SYSCALL_DEFINE4(lsm_get_self_attr, unsigned int, attr, struct lsm_ctx __user *, ctx, u32 __user *, size, u32, flags) { - return security_getselfattr(attr, ctx, size, flags); + int rc; + u32 nattr; + + rc = security_getselfattr(attr, ctx, size, flags, &nattr); + return rc < 0 ? rc : nattr; } /** diff --git a/security/security.c b/security/security.c index 12215ca286af..095e78efcb32 100644 --- a/security/security.c +++ b/security/security.c @@ -3969,21 +3969,23 @@ EXPORT_SYMBOL(security_d_instantiate); * @flags: special handling options. LSM_FLAG_SINGLE indicates that only * attributes associated with the LSM identified in the passed @ctx be * reported. + * @nattr: number of attributes found on success * * A NULL value for @uctx can be used to get both the number of attributes * and the size of the data. * - * Returns the number of attributes found on success, negative value - * on error. @size is reset to the total size of the data. - * If @size is insufficient to contain the data -E2BIG is returned. + * Returns 0 on success, a negative error code on failure. @size is reset + * to the total size of the data. If @size is insufficient to contain the + * data -E2BIG is returned. */ int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx, - u32 __user *size, u32 flags) + u32 __user *size, u32 flags, u32 *nattr) { struct security_hook_list *hp; struct lsm_ctx lctx = { .id = LSM_ID_UNDEF, }; u8 __user *base = (u8 __user *)uctx; u32 entrysize; + u32 entrycount; u32 total = 0; u32 left; bool toobig = false; @@ -4024,7 +4026,8 @@ int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx, entrysize = left; if (base) uctx = (struct lsm_ctx __user *)(base + total); - rc = hp->hook.getselfattr(attr, uctx, &entrysize, flags); + rc = hp->hook.getselfattr(attr, uctx, &entrysize, flags, + &entrycount); if (rc == -EOPNOTSUPP) { rc = 0; continue; @@ -4039,7 +4042,7 @@ int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx, left -= entrysize; total += entrysize; - count += rc; + count += entrycount; if (single) break; } @@ -4047,9 +4050,10 @@ int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx, return -EFAULT; if (toobig) return -E2BIG; + *nattr = count; if (count == 0) return LSM_RET_DEFAULT(getselfattr); - return count; + return 0; } /* diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index f9a6637dfd78..0d35bb93baca 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6536,15 +6536,17 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size) * @ctx: buffer to receive the result * @size: buffer size (input), buffer size used (output) * @flags: unused + * @nattr: number of attributes found on success. * * Fill the passed user space @ctx with the details of the requested * attribute. * - * Returns the number of attributes on success, an error code otherwise. - * There will only ever be one attribute. + * Returns 0 on success or a negative error code on failure. + * There will only ever be one attribute, so @nattr is set to + * 1 on success. */ static int selinux_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, - u32 *size, u32 flags) + u32 *size, u32 flags, u32 *nattr) { int rc; char *val = NULL; @@ -6555,7 +6557,10 @@ static int selinux_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, return val_len; rc = lsm_fill_user_ctx(ctx, size, val, val_len, LSM_ID_SELINUX, 0); kfree(val); - return (!rc ? 1 : rc); + if (rc < 0) + return rc; + *nattr = 1; + return 0; } static int selinux_setselfattr(unsigned int attr, struct lsm_ctx *ctx, diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index ae8f1c2d0ca6..63d9c5f456c1 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3648,15 +3648,17 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) * @ctx: buffer to receive the result * @size: available size in, actual size out * @flags: unused + * @nattr: number of attributes found on success * * Fill the passed user space @ctx with the details of the requested * attribute. * - * Returns the number of attributes on success, an error code otherwise. - * There will only ever be one attribute. + * Returns 0 on success or a ngetaive error code on failure. + * There will only ever be one attribute, so @nattr is set to + * 1 on success. */ static int smack_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, - u32 *size, u32 flags) + u32 *size, u32 flags, u32 *nattr) { int rc; struct smack_known *skp; @@ -3668,7 +3670,10 @@ static int smack_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, rc = lsm_fill_user_ctx(ctx, size, skp->smk_known, strlen(skp->smk_known) + 1, LSM_ID_SMACK, 0); - return (!rc ? 1 : rc); + if (rc < 0) + return rc; + *nattr = 1; + return 0; } /** From patchwork Thu Jul 11 11:18:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730497 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 39E3E15E5BB; Thu, 11 Jul 2024 11:14:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696448; cv=none; b=gIFCjpzvdl845ISDydvR09MvlSgOebvaj6wlpv8EH66pfctV0Y2BzcYCylXC0Bjavw99Lgy6auElFTYd0aWTOhp+KdHVRaDLtz4NKRoYf+jar7Ooccm3y9P9O5fNVqFLn9VjcC1bjErM9wiQXS5zoY9C39YMWfTuMgj+iqhmdFk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696448; c=relaxed/simple; bh=qrrpdpqqwja83fU2xQi9LV/n3kM40V0F8khJS++VSsY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=jj4tF9NSdWv3VgUvCyBueiEEIZ7vET2YvcBjRnLErxZTyVIDn3EABymfZT3N18WxaDV2phoetX79H+IG0vLUbrwHreXDuY+3OD39KnNMwariUO3SIWBksZ3NpjAUcu9NIb0VS4yif1/Jw3D6xjhHuuWxOpm1x8XH+Y5aSHORcL8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.93.142]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTP id 4WKXCt0NRNz4f3jdn; Thu, 11 Jul 2024 19:13:46 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id B17751A016E; Thu, 11 Jul 2024 19:13:57 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgCHjPVxvo9mulQgBw--.25300S9; Thu, 11 Jul 2024 19:13:57 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 07/20] lsm: Refactor return value of LSM hook setprocattr Date: Thu, 11 Jul 2024 19:18:55 +0800 Message-Id: <20240711111908.3817636-8-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711111908.3817636-1-xukuohai@huaweicloud.com> References: <20240711111908.3817636-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgCHjPVxvo9mulQgBw--.25300S9 X-Coremail-Antispam: 1UD129KBjvJXoW3Ww4fXr4kCw4kAFyrJr48tFb_yoWxuw4DpF s8K3W3Gr48GFy7XF4vyFnxCa1a93yrGr17J39xCwnFyFy7Jw4Igay3GFyjkFWfCw18Wr18 KanFqrW3Cr4UAr7anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBqb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E 14v26rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7 xfMcIj6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Y z7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2 Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s02 6x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42 IY6xIIjxv20xvE14v26r1I6r4UMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF 0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42IY6I8E87 Iv6xkF7I0E14v26r4UJVWxJrUvcSsGvfC2KfnxnUUI43ZEXa7IU13l1DUUUUU== X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai To be consistent with most LSM hooks, convert the return value of hook setprocattr to 0 or a negative error code. Before: - Hook setprocattr returns the number of bytes written on success or a negative error code on failure. After: - Hook setprocattr returns 0 on success or a negative error code on failure. An output parameter @wbytes is introduced to hold the number of bytes written on success. Signed-off-by: Xu Kuohai --- fs/proc/base.c | 5 +++-- include/linux/lsm_hook_defs.h | 3 ++- include/linux/security.h | 5 +++-- security/apparmor/lsm.c | 10 +++++++--- security/security.c | 8 +++++--- security/selinux/hooks.c | 11 ++++++++--- security/smack/smack_lsm.c | 14 ++++++++++---- 7 files changed, 38 insertions(+), 18 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 72a1acd03675..9e1cf6cc674d 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2740,6 +2740,7 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf, { struct inode * inode = file_inode(file); struct task_struct *task; + size_t wbytes; void *page; int rv; @@ -2785,12 +2786,12 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf, rv = security_setprocattr(PROC_I(inode)->op.lsmid, file->f_path.dentry->d_name.name, page, - count); + count, &wbytes); mutex_unlock(¤t->signal->cred_guard_mutex); out_free: kfree(page); out: - return rv; + return rv < 0 ? rv : wbytes; } static const struct file_operations proc_pid_attr_operations = { diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index dbc16f14f42f..2628514bb19c 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -287,7 +287,8 @@ LSM_HOOK(int, -EOPNOTSUPP, setselfattr, unsigned int attr, struct lsm_ctx *ctx, u32 size, u32 flags) LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name, char **value) -LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size) +LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size, + size_t *wbytes) LSM_HOOK(int, 0, ismaclabel, const char *name) LSM_HOOK(int, -EOPNOTSUPP, secid_to_secctx, u32 secid, char **secdata, u32 *seclen) diff --git a/include/linux/security.h b/include/linux/security.h index 96a63e132abf..1f1a9696e65d 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -496,7 +496,8 @@ int security_setselfattr(unsigned int attr, struct lsm_ctx __user *ctx, u32 size, u32 flags); int security_getprocattr(struct task_struct *p, int lsmid, const char *name, char **value); -int security_setprocattr(int lsmid, const char *name, void *value, size_t size); +int security_setprocattr(int lsmid, const char *name, void *value, size_t size, + size_t *wbytes); int security_netlink_send(struct sock *sk, struct sk_buff *skb); int security_ismaclabel(const char *name); int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); @@ -1440,7 +1441,7 @@ static inline int security_getprocattr(struct task_struct *p, int lsmid, } static inline int security_setprocattr(int lsmid, char *name, void *value, - size_t size) + size_t size, size_t *wbytes) { return -EINVAL; } diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 72dd09993f28..6c8b1f8c5781 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -939,13 +939,17 @@ static int apparmor_setselfattr(unsigned int attr, struct lsm_ctx *ctx, } static int apparmor_setprocattr(const char *name, void *value, - size_t size) + size_t size, size_t *wbytes) { + int rc = -EINVAL; int attr = lsm_name_to_attr(name); if (attr) - return do_setattr(attr, value, size); - return -EINVAL; + rc = do_setattr(attr, value, size); + if (rc < 0) + return rc; + *wbytes = rc; + return 0; } /** diff --git a/security/security.c b/security/security.c index 095e78efcb32..9685096dbf16 100644 --- a/security/security.c +++ b/security/security.c @@ -4141,20 +4141,22 @@ int security_getprocattr(struct task_struct *p, int lsmid, const char *name, * @name: attribute name * @value: attribute value * @size: attribute value size + * @wbytes: bytes written on success * * Write (set) the current task's attribute @name to @value, size @size if * allowed. * - * Return: Returns bytes written on success, a negative value otherwise. + * Return: Returns 0 on success, a negative error code otherwise. */ -int security_setprocattr(int lsmid, const char *name, void *value, size_t size) +int security_setprocattr(int lsmid, const char *name, void *value, size_t size, + size_t *wbytes) { struct security_hook_list *hp; hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) { if (lsmid != 0 && lsmid != hp->lsmid->id) continue; - return hp->hook.setprocattr(name, value, size); + return hp->hook.setprocattr(name, value, size, wbytes); } return LSM_RET_DEFAULT(setprocattr); } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 0d35bb93baca..7a73f3710025 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6589,13 +6589,18 @@ static int selinux_getprocattr(struct task_struct *p, return -EINVAL; } -static int selinux_setprocattr(const char *name, void *value, size_t size) +static int selinux_setprocattr(const char *name, void *value, size_t size, + size_t *wbytes) { + int rc = -EINVAL; int attr = lsm_name_to_attr(name); if (attr) - return selinux_lsm_setattr(attr, value, size); - return -EINVAL; + rc = selinux_lsm_setattr(attr, value, size); + if (rc < 0) + return rc; + *wbytes = rc; + return 0; } static int selinux_ismaclabel(const char *name) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 63d9c5f456c1..4265f2639106 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3797,19 +3797,25 @@ static int smack_setselfattr(unsigned int attr, struct lsm_ctx *ctx, * @name: the name of the attribute in /proc/.../attr * @value: the value to set * @size: the size of the value + * @wbytes: the length of the smack label written * * Sets the Smack value of the task. Only setting self * is permitted and only with privilege * - * Returns the length of the smack label or an error code + * Returns 0 on success or a negative error code */ -static int smack_setprocattr(const char *name, void *value, size_t size) +static int smack_setprocattr(const char *name, void *value, size_t size, + size_t *wbytes) { + int rc = -EINVAL; int attr = lsm_name_to_attr(name); if (attr != LSM_ATTR_UNDEF) - return do_setattr(attr, value, size); - return -EINVAL; + rc = do_setattr(attr, value, size); + if (rc < 0) + return rc; + *wbytes = rc; + return 0; } /** From patchwork Thu Jul 11 11:18:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730491 Received: from dggsgout11.his.huawei.com (dggsgout11.his.huawei.com [45.249.212.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C4D66158DC8; Thu, 11 Jul 2024 11:14:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696443; cv=none; b=P78+g7y6tmygFHMdtmq3LMM8/oMguHKN/hzC5Ui+iFOLDCgEzg4hbRGAu8+iwJSRkqnOWINRCxnrmW3t7v/z9HuiZOpgA5AgKnv9z28tHZSYb6Iz98anPeIuPU1ALHg5ZUpAiPjjN+FCZ6D5hSpuEv/z2uwb6q3TWi+xIiDgf2I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696443; c=relaxed/simple; bh=ShKudblWtSVIcHknjFeCbDdWn8i6PCKbPF6Ecli0nrg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=TZrqEG8wRWRkR+tS0yv6MybsPPmqIx2UHVLpRkfXltvFZSuTbQAuJXmnXN37BnJmLoxL8AyQ9kwlBTJ0hymoHaRC0zIfhLpApBvggzxwGA7YV+c7QpzPMLjH7yVpJL4qOYAkaE5V4tZ+Z6UhUZtHKIDwU7Yhs1UydxYEJf0Fisk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.235]) by dggsgout11.his.huawei.com (SkyGuard) with ESMTP id 4WKXCs0Fv9z4f3m6t; Thu, 11 Jul 2024 19:13:45 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id E0E9D1A0568; Thu, 11 Jul 2024 19:13:57 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgCHjPVxvo9mulQgBw--.25300S10; Thu, 11 Jul 2024 19:13:57 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 08/20] lsm: Refactor return value of LSM hook getprocattr Date: Thu, 11 Jul 2024 19:18:56 +0800 Message-Id: <20240711111908.3817636-9-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711111908.3817636-1-xukuohai@huaweicloud.com> References: <20240711111908.3817636-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgCHjPVxvo9mulQgBw--.25300S10 X-Coremail-Antispam: 1UD129KBjvJXoW3GrWUWr4xGFyfGFyfZFy7ZFb_yoWxZw48pF s5K3ZrGrW8WFy7ZF4vyFnxCa1Sv3yrWr13J398Cw1IyFy2qw4xWa45GFyY9rWrCw1DuF1D tanFqr45Cr4DAF7anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBqb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E 14v26rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7 xfMcIj6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Y z7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2 Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s02 6x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42 IY6xIIjxv20xvE14v26r1I6r4UMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF 0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42IY6I8E87 Iv6xkF7I0E14v26r4UJVWxJrUvcSsGvfC2KfnxnUUI43ZEXa7IU13l1DUUUUU== X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai To be consistent with most LSM hooks, convert the return value of hook getprocattr to 0 or a negative error code. Before: - Hook getprocattr returns length of value on success or a negative error code on failure. After: - Hook getprocattr returns 0 on success or a negative error code on failure. An output parameter @len is introduced to hold the length of value on success. Signed-off-by: Xu Kuohai --- fs/proc/base.c | 5 ++++- include/linux/lsm_hook_defs.h | 2 +- include/linux/security.h | 5 +++-- security/apparmor/lsm.c | 7 +++++-- security/security.c | 8 +++++--- security/selinux/hooks.c | 16 +++++++++------- security/smack/smack_lsm.c | 11 ++++++----- 7 files changed, 33 insertions(+), 21 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 9e1cf6cc674d..516a00f6ce36 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2721,13 +2721,16 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf, char *p = NULL; ssize_t length; struct task_struct *task = get_proc_task(inode); + u32 n; if (!task) return -ESRCH; length = security_getprocattr(task, PROC_I(inode)->op.lsmid, file->f_path.dentry->d_name.name, - &p); + &p, &n); + if (!length) + length = n; put_task_struct(task); if (length > 0) length = simple_read_from_buffer(buf, count, ppos, p, length); diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 2628514bb19c..b0e3cf3fc33f 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -286,7 +286,7 @@ LSM_HOOK(int, -EOPNOTSUPP, getselfattr, unsigned int attr, LSM_HOOK(int, -EOPNOTSUPP, setselfattr, unsigned int attr, struct lsm_ctx *ctx, u32 size, u32 flags) LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name, - char **value) + char **value, u32 *len) LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size, size_t *wbytes) LSM_HOOK(int, 0, ismaclabel, const char *name) diff --git a/include/linux/security.h b/include/linux/security.h index 1f1a9696e65d..616047030a89 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -495,7 +495,7 @@ int security_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, int security_setselfattr(unsigned int attr, struct lsm_ctx __user *ctx, u32 size, u32 flags); int security_getprocattr(struct task_struct *p, int lsmid, const char *name, - char **value); + char **value, u32 *len); int security_setprocattr(int lsmid, const char *name, void *value, size_t size, size_t *wbytes); int security_netlink_send(struct sock *sk, struct sk_buff *skb); @@ -1435,7 +1435,8 @@ static inline int security_setselfattr(unsigned int attr, } static inline int security_getprocattr(struct task_struct *p, int lsmid, - const char *name, char **value) + const char *name, char **value, + u32 *len) { return -EINVAL; } diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 6c8b1f8c5781..0454f3f1af06 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -820,7 +820,7 @@ static int apparmor_getselfattr(unsigned int attr, struct lsm_ctx __user *lx, } static int apparmor_getprocattr(struct task_struct *task, const char *name, - char **value) + char **value, u32 *len) { int error = -ENOENT; /* released below */ @@ -843,7 +843,10 @@ static int apparmor_getprocattr(struct task_struct *task, const char *name, aa_put_label(label); put_cred(cred); - return error; + if (error < 0) + return error; + *len = error; + return 0; } static int do_setattr(u64 attr, void *value, size_t size) diff --git a/security/security.c b/security/security.c index 9685096dbf16..9dd2ae6cf763 100644 --- a/security/security.c +++ b/security/security.c @@ -4117,20 +4117,22 @@ int security_setselfattr(unsigned int attr, struct lsm_ctx __user *uctx, * @lsmid: LSM identification * @name: attribute name * @value: attribute value + * @len: length of @value * * Read attribute @name for task @p and store it into @value if allowed. * - * Return: Returns the length of @value on success, a negative value otherwise. + * Return: Returns 0 on success or a negative error code on failure. + * @len is set to the length of @value on success. */ int security_getprocattr(struct task_struct *p, int lsmid, const char *name, - char **value) + char **value, u32 *len) { struct security_hook_list *hp; hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) { if (lsmid != 0 && lsmid != hp->lsmid->id) continue; - return hp->hook.getprocattr(p, name, value); + return hp->hook.getprocattr(p, name, value, len); } return LSM_RET_DEFAULT(getprocattr); } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 7a73f3710025..16cd336aab3d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6574,19 +6574,21 @@ static int selinux_setselfattr(unsigned int attr, struct lsm_ctx *ctx, return rc; } -static int selinux_getprocattr(struct task_struct *p, - const char *name, char **value) +static int selinux_getprocattr(struct task_struct *p, const char *name, + char **value, u32 *len) { unsigned int attr = lsm_name_to_attr(name); - int rc; + int rc = -EINVAL; if (attr) { rc = selinux_lsm_getattr(attr, p, value); - if (rc != -EOPNOTSUPP) - return rc; + if (rc == -EOPNOTSUPP) + rc = -EINVAL; } - - return -EINVAL; + if (rc < 0) + return rc; + *len = rc; + return 0; } static int selinux_setprocattr(const char *name, void *value, size_t size, diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 4265f2639106..8a352bd05565 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3681,16 +3681,17 @@ static int smack_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, * @p: the object task * @name: the name of the attribute in /proc/.../attr * @value: where to put the result + * @len: where to put the length of the result * * Places a copy of the task Smack into value * - * Returns the length of the smack label or an error code + * Returns 0 on success or a negative error code on failure. */ -static int smack_getprocattr(struct task_struct *p, const char *name, char **value) +static int smack_getprocattr(struct task_struct *p, const char *name, + char **value, u32 *len) { struct smack_known *skp = smk_of_task_struct_obj(p); char *cp; - int slen; if (strcmp(name, "current") != 0) return -EINVAL; @@ -3699,9 +3700,9 @@ static int smack_getprocattr(struct task_struct *p, const char *name, char **val if (cp == NULL) return -ENOMEM; - slen = strlen(cp); + *len = strlen(cp); *value = cp; - return slen; + return 0; } /** From patchwork Thu Jul 11 11:18:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730499 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ECA1616CD13; Thu, 11 Jul 2024 11:14:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696450; cv=none; b=ZfdXuHiy/tBwjkEUYXPelaDz/6VOBgQzoX7jcvDvMGPpBu7rS3QhFKyip8v4+kZhTRV1DI5iktMc+PaDBpTHRFOIcppoN5pCEL2huRtOZc2spxVS6CsfXH66HxHDDml2t9Eonan1tOzdpYX9Wo+J5T2FTnCaEVYW4bV3QNWsSOE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696450; c=relaxed/simple; bh=W7sp3ff+hjyuIeSmWYemCbL1+548rrnKCUDBByLaPy8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=BopmfrEpEL2rlH+fffaW/qiGaNXyBee69ZyBWZTkzfzg3ChmTdoOZ2aHFz2omI9UwHAUNrrGV2vDFFF50EbggwG/MU53Oximy8yRYGsNV6g+3Nht6IIupk028svm7vzsNiLSvNPbZDcd2DXUu/kgxQ1jorvGT5Dn85Ybk4T+AS8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.93.142]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTP id 4WKXCt3BV0z4f3jsC; Thu, 11 Jul 2024 19:13:46 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 16A751A0181; Thu, 11 Jul 2024 19:13:58 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgCHjPVxvo9mulQgBw--.25300S11; Thu, 11 Jul 2024 19:13:57 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 09/20] lsm: Refactor return value of LSM hook key_getsecurity Date: Thu, 11 Jul 2024 19:18:57 +0800 Message-Id: <20240711111908.3817636-10-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711111908.3817636-1-xukuohai@huaweicloud.com> References: <20240711111908.3817636-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgCHjPVxvo9mulQgBw--.25300S11 X-Coremail-Antispam: 1UD129KBjvJXoW3Gw1UtF1UuF47Ww45XFy8Grg_yoW3WrW8pF 45KF1xtrW8GFy2vrn7Aa13Kaya9ayFgry7G39xu343tF1vqryUWr1jkF1Ykry5ArWUJr10 yw47Za13CF1qyrJanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBqb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E 14v26rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7 xfMcIj6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Y z7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2 Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s02 6x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42 IY6xIIjxv20xvE14v26r1I6r4UMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF 0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42IY6I8E87 Iv6xkF7I0E14v26r4UJVWxJrUvcSsGvfC2KfnxnUUI43ZEXa7IU13l1DUUUUU== X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai To be consistent with most LSM hooks, convert the return value of hook key_getsecurity to 0 or a negative error code. Before: - Hook key_getsecurity returns length of value on success or a negative error code on failure. After: - Hook key_getsecurity returns 0 on success or a negative error code on failure. An output parameter @len is introduced to hold the length of value on success. Signed-off-by: Xu Kuohai --- include/linux/lsm_hook_defs.h | 3 ++- include/linux/security.h | 6 ++++-- security/keys/keyctl.c | 11 ++++++++--- security/security.c | 26 +++++++++++++++++++++----- security/selinux/hooks.c | 11 +++++------ security/smack/smack_lsm.c | 21 +++++++++++---------- 6 files changed, 51 insertions(+), 27 deletions(-) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index b0e3cf3fc33f..54fec360947c 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -407,7 +407,8 @@ LSM_HOOK(int, 0, key_alloc, struct key *key, const struct cred *cred, LSM_HOOK(void, LSM_RET_VOID, key_free, struct key *key) LSM_HOOK(int, 0, key_permission, key_ref_t key_ref, const struct cred *cred, enum key_need_perm need_perm) -LSM_HOOK(int, 0, key_getsecurity, struct key *key, char **buffer) +LSM_HOOK(int, 0, key_getsecurity, struct key *key, char **buffer, + size_t *len) LSM_HOOK(void, LSM_RET_VOID, key_post_create_or_update, struct key *keyring, struct key *key, const void *payload, size_t payload_len, unsigned long flags, bool create) diff --git a/include/linux/security.h b/include/linux/security.h index 616047030a89..4e64e51a1a86 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -2020,7 +2020,7 @@ int security_key_alloc(struct key *key, const struct cred *cred, unsigned long f void security_key_free(struct key *key); int security_key_permission(key_ref_t key_ref, const struct cred *cred, enum key_need_perm need_perm); -int security_key_getsecurity(struct key *key, char **_buffer); +int security_key_getsecurity(struct key *key, char **_buffer, size_t *_len); void security_key_post_create_or_update(struct key *keyring, struct key *key, const void *payload, size_t payload_len, unsigned long flags, bool create); @@ -2045,9 +2045,11 @@ static inline int security_key_permission(key_ref_t key_ref, return 0; } -static inline int security_key_getsecurity(struct key *key, char **_buffer) +static inline int security_key_getsecurity(struct key *key, char **_buffer, + size_t *_len) { *_buffer = NULL; + *_len = 0; return 0; } diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 4bc3e9398ee3..e9f857620f28 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -1565,6 +1565,7 @@ long keyctl_get_security(key_serial_t keyid, struct key *key, *instkey; key_ref_t key_ref; char *context; + size_t len; long ret; key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_NEED_VIEW); @@ -1586,15 +1587,18 @@ long keyctl_get_security(key_serial_t keyid, } key = key_ref_to_ptr(key_ref); - ret = security_key_getsecurity(key, &context); - if (ret == 0) { + ret = security_key_getsecurity(key, &context, &len); + if (ret < 0) + goto error; + if (len == 0) { /* if no information was returned, give userspace an empty * string */ ret = 1; if (buffer && buflen > 0 && copy_to_user(buffer, "", 1) != 0) ret = -EFAULT; - } else if (ret > 0) { + } else { + ret = len; /* return as much data as there's room for */ if (buffer && buflen > 0) { if (buflen > ret) @@ -1607,6 +1611,7 @@ long keyctl_get_security(key_serial_t keyid, kfree(context); } +error: key_ref_put(key_ref); return ret; } diff --git a/security/security.c b/security/security.c index 9dd2ae6cf763..2c161101074d 100644 --- a/security/security.c +++ b/security/security.c @@ -5338,19 +5338,35 @@ int security_key_permission(key_ref_t key_ref, const struct cred *cred, * security_key_getsecurity() - Get the key's security label * @key: key * @buffer: security label buffer + * @len: the length of @buffer (including terminating NULL) on success * * Get a textual representation of the security context attached to a key for * the purposes of honouring KEYCTL_GETSECURITY. This function allocates the * storage for the NUL-terminated string and the caller should free it. * - * Return: Returns the length of @buffer (including terminating NUL) or -ve if - * an error occurs. May also return 0 (and a NULL buffer pointer) if - * there is no security label assigned to the key. + * Return: Returns 0 on success or -ve if an error occurs. May also return 0 + * (and a NULL buffer pointer) if there is no security label assigned + * to the key. */ -int security_key_getsecurity(struct key *key, char **buffer) +int security_key_getsecurity(struct key *key, char **buffer, size_t *len) { + int rc; + size_t n = 0; + struct security_hook_list *hp; + *buffer = NULL; - return call_int_hook(key_getsecurity, key, buffer); + + hlist_for_each_entry(hp, &security_hook_heads.key_getsecurity, list) { + rc = hp->hook.key_getsecurity(key, buffer, &n); + if (rc < 0) + return rc; + if (n) + break; + } + + *len = n; + + return 0; } /** diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 16cd336aab3d..747ec602dec0 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6737,18 +6737,17 @@ static int selinux_key_permission(key_ref_t key_ref, return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL); } -static int selinux_key_getsecurity(struct key *key, char **_buffer) +static int selinux_key_getsecurity(struct key *key, char **_buffer, + size_t *_len) { struct key_security_struct *ksec = key->security; char *context = NULL; - unsigned len; + u32 context_len; int rc; - rc = security_sid_to_context(ksec->sid, - &context, &len); - if (!rc) - rc = len; + rc = security_sid_to_context(ksec->sid, &context, &context_len); *_buffer = context; + *_len = context_len; return rc; } diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 8a352bd05565..9a121ad53b16 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4585,30 +4585,31 @@ static int smack_key_permission(key_ref_t key_ref, /* * smack_key_getsecurity - Smack label tagging the key * @key points to the key to be queried - * @_buffer points to a pointer that should be set to point to the - * resulting string (if no label or an error occurs). - * Return the length of the string (including terminating NUL) or -ve if - * an error. - * May also return 0 (and a NULL buffer pointer) if there is no label. + * @_buffer points to a pointer that should be set to point to the resulting + * string (if no label or an error occurs). + * @_len the length of the @_buffer (including terminating NUL) + * + * Return 0 on success or -ve if an error. + * If there is no label, @_buffer will be set to NULL and @_len will be set to + * 0. */ -static int smack_key_getsecurity(struct key *key, char **_buffer) +static int smack_key_getsecurity(struct key *key, char **_buffer, size_t *_len) { struct smack_known *skp = key->security; - size_t length; char *copy; if (key->security == NULL) { *_buffer = NULL; + *_len = 0; return 0; } copy = kstrdup(skp->smk_known, GFP_KERNEL); if (copy == NULL) return -ENOMEM; - length = strlen(copy) + 1; - + *_len = strlen(copy) + 1; *_buffer = copy; - return length; + return 0; } From patchwork Thu Jul 11 11:18:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730500 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ECAC116CD15; Thu, 11 Jul 2024 11:14:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696450; cv=none; b=QEvRsAQpY2A8wcvvBRdckmDjGpE69bLx/NJ81Oih4UltDYukU/giO5UcGojiylWKfyiuW1WuHDPXMToLI6fAn9cDfG5Tw1RkPh0FcJcooOSWb5hLupiUm37DL8z9ISwCXinJ3byTS/ATVbM7fFxf6W16IWnij6ggczluO8UGwiY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696450; c=relaxed/simple; bh=N0sDjFXEOLrl+eei12YY3cVHVQCyQtATfXFXgVl4uRU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=W24wm/Aw7d5j9hhImTBRvy/b+7K/7y8OuyjR41iwtzpuy8IAdxW19uYScDeQYYyGQqv0StkrLJxGI5y5kH99BeSJnharq6OeQvVOmMto9H8UqvofafKGgCXEi6LHxzxJMH6hXRZhUmtnPg2/XkKrlBpw1spK+J/I0tzfd5ad1Zs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.216]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTP id 4WKXCt4Svgz4f3kFQ; Thu, 11 Jul 2024 19:13:46 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 4A1A51A0170; Thu, 11 Jul 2024 19:13:58 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgCHjPVxvo9mulQgBw--.25300S12; Thu, 11 Jul 2024 19:13:57 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 10/20] lsm: Refactor return value of LSM hook audit_rule_match Date: Thu, 11 Jul 2024 19:18:58 +0800 Message-Id: <20240711111908.3817636-11-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711111908.3817636-1-xukuohai@huaweicloud.com> References: <20240711111908.3817636-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgCHjPVxvo9mulQgBw--.25300S12 X-Coremail-Antispam: 1UD129KBjvJXoW3Aw4UuF4xKr13Jw1xWw1rZwb_yoWDCw4kpF 1qvF4fArWkGF4xXrn7Ca42gr4Yvry3Cw1DCrZ8Cr1jkF9xJr1kGr48ZF4UGF95Wr45Awsa vanrurZayr4DXrJanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBSb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVWxJr0_GcWl84ACjcxK6I8E87Iv67AKxVW0oVCq3wA2z4x0Y4vEx4A2jsIEc7CjxVAF wI0_GcCE3s1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2 WlYx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkE bVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCF04k20xvY0x 0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E 7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Wrv_Gr1UMIIYrxkI7VAKI48JMIIF0x vE2Ix0cI8IcVAFwI0_Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4UJVWxJr1lIxAI cVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2js IEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvjxUFgAwUUUUU X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai To be consistent with most LSM hooks, convert the return value of hook audit_rule_match to 0 or a negative error code. Before: - Hook audit_rule_match returns 1 if the rule matches, 0 if it not, and negative error code otherwise. After: - Hook audit_rule_match returns 0 on success or a negative error code on failure. An output parameter @match is introduced to hold the match result on success. Signed-off-by: Xu Kuohai --- include/linux/lsm_hook_defs.h | 3 +- security/apparmor/audit.c | 22 ++++++------- security/apparmor/include/audit.h | 2 +- security/security.c | 15 ++++++++- security/selinux/include/audit.h | 8 +++-- security/selinux/ss/services.c | 54 +++++++++++++++++-------------- security/smack/smack_lsm.c | 19 +++++++---- 7 files changed, 75 insertions(+), 48 deletions(-) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 54fec360947c..6b521744a23b 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -418,7 +418,8 @@ LSM_HOOK(void, LSM_RET_VOID, key_post_create_or_update, struct key *keyring, LSM_HOOK(int, 0, audit_rule_init, u32 field, u32 op, char *rulestr, void **lsmrule, gfp_t gfp) LSM_HOOK(int, 0, audit_rule_known, struct audit_krule *krule) -LSM_HOOK(int, 0, audit_rule_match, u32 secid, u32 field, u32 op, void *lsmrule) +LSM_HOOK(int, 0, audit_rule_match, u32 secid, u32 field, u32 op, void *lsmrule, + bool *match) LSM_HOOK(void, LSM_RET_VOID, audit_rule_free, void *lsmrule) #endif /* CONFIG_AUDIT */ diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c index 6b5181c668b5..352a183b3325 100644 --- a/security/apparmor/audit.c +++ b/security/apparmor/audit.c @@ -264,11 +264,11 @@ int aa_audit_rule_known(struct audit_krule *rule) return 0; } -int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule) +int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, bool *match) { struct aa_audit_rule *rule = vrule; struct aa_label *label; - int found = 0; + bool found = false; label = aa_secid_to_label(sid); @@ -276,16 +276,14 @@ int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule) return -ENOENT; if (aa_label_is_subset(label, rule->label)) - found = 1; + found = true; + + if (field == AUDIT_SUBJ_ROLE && op == Audit_equal) + *match = found; + else if (field == AUDIT_SUBJ_ROLE && op == Audit_not_equal) + *match = !found; + else + *match = false; - switch (field) { - case AUDIT_SUBJ_ROLE: - switch (op) { - case Audit_equal: - return found; - case Audit_not_equal: - return !found; - } - } return 0; } diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h index 0c8cc86b417b..a227741f33c8 100644 --- a/security/apparmor/include/audit.h +++ b/security/apparmor/include/audit.h @@ -202,6 +202,6 @@ static inline int complain_error(int error) void aa_audit_rule_free(void *vrule); int aa_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule, gfp_t gfp); int aa_audit_rule_known(struct audit_krule *rule); -int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule); +int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, bool *match); #endif /* __AA_AUDIT_H */ diff --git a/security/security.c b/security/security.c index 2c161101074d..5e9de8d0cdde 100644 --- a/security/security.c +++ b/security/security.c @@ -5450,7 +5450,20 @@ void security_audit_rule_free(void *lsmrule) */ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule) { - return call_int_hook(audit_rule_match, secid, field, op, lsmrule); + int rc; + bool match = false; + struct security_hook_list *hp; + + hlist_for_each_entry(hp, &security_hook_heads.audit_rule_match, list) { + rc = hp->hook.audit_rule_match(secid, field, op, lsmrule, + &match); + if (rc < 0) + return rc; + if (match) + break; + } + + return match; } #endif /* CONFIG_AUDIT */ diff --git a/security/selinux/include/audit.h b/security/selinux/include/audit.h index 29c7d4c86f6d..2d0799270426 100644 --- a/security/selinux/include/audit.h +++ b/security/selinux/include/audit.h @@ -45,11 +45,13 @@ void selinux_audit_rule_free(void *rule); * @field: the field this rule refers to * @op: the operator the rule uses * @rule: pointer to the audit rule to check against + * @match: if the context id matches the rule * - * Returns 1 if the context id matches the rule, 0 if it does not, and - * -errno on failure. + * Returns 0 on success and -errno on failure. @match holds the match + * result. */ -int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule); +int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule, + bool *match); /** * selinux_audit_rule_known - check to see if rule contains selinux fields. diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index e33e55384b75..2946d28a25b1 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -3633,29 +3633,32 @@ int selinux_audit_rule_known(struct audit_krule *rule) return 0; } -int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule) +int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, + bool *match) { struct selinux_state *state = &selinux_state; struct selinux_policy *policy; struct context *ctxt; struct mls_level *level; struct selinux_audit_rule *rule = vrule; - int match = 0; + int rc = 0; if (unlikely(!rule)) { WARN_ONCE(1, "selinux_audit_rule_match: missing rule\n"); return -ENOENT; } - if (!selinux_initialized()) + if (!selinux_initialized()) { + *match = false; return 0; + } rcu_read_lock(); policy = rcu_dereference(state->policy); if (rule->au_seqno < policy->latest_granting) { - match = -ESTALE; + rc = -ESTALE; goto out; } @@ -3663,7 +3666,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule) if (unlikely(!ctxt)) { WARN_ONCE(1, "selinux_audit_rule_match: unrecognized SID %d\n", sid); - match = -ENOENT; + rc = -ENOENT; goto out; } @@ -3674,10 +3677,10 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule) case AUDIT_OBJ_USER: switch (op) { case Audit_equal: - match = (ctxt->user == rule->au_ctxt.user); + rc = (ctxt->user == rule->au_ctxt.user); break; case Audit_not_equal: - match = (ctxt->user != rule->au_ctxt.user); + rc = (ctxt->user != rule->au_ctxt.user); break; } break; @@ -3685,10 +3688,10 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule) case AUDIT_OBJ_ROLE: switch (op) { case Audit_equal: - match = (ctxt->role == rule->au_ctxt.role); + rc = (ctxt->role == rule->au_ctxt.role); break; case Audit_not_equal: - match = (ctxt->role != rule->au_ctxt.role); + rc = (ctxt->role != rule->au_ctxt.role); break; } break; @@ -3696,10 +3699,10 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule) case AUDIT_OBJ_TYPE: switch (op) { case Audit_equal: - match = (ctxt->type == rule->au_ctxt.type); + rc = (ctxt->type == rule->au_ctxt.type); break; case Audit_not_equal: - match = (ctxt->type != rule->au_ctxt.type); + rc = (ctxt->type != rule->au_ctxt.type); break; } break; @@ -3712,39 +3715,42 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule) &ctxt->range.level[0] : &ctxt->range.level[1]); switch (op) { case Audit_equal: - match = mls_level_eq(&rule->au_ctxt.range.level[0], - level); + rc = mls_level_eq(&rule->au_ctxt.range.level[0], + level); break; case Audit_not_equal: - match = !mls_level_eq(&rule->au_ctxt.range.level[0], - level); + rc = !mls_level_eq(&rule->au_ctxt.range.level[0], + level); break; case Audit_lt: - match = (mls_level_dom(&rule->au_ctxt.range.level[0], - level) && + rc = (mls_level_dom(&rule->au_ctxt.range.level[0], + level) && !mls_level_eq(&rule->au_ctxt.range.level[0], level)); break; case Audit_le: - match = mls_level_dom(&rule->au_ctxt.range.level[0], - level); + rc = mls_level_dom(&rule->au_ctxt.range.level[0], + level); break; case Audit_gt: - match = (mls_level_dom(level, - &rule->au_ctxt.range.level[0]) && + rc = (mls_level_dom(level, + &rule->au_ctxt.range.level[0]) && !mls_level_eq(level, &rule->au_ctxt.range.level[0])); break; case Audit_ge: - match = mls_level_dom(level, - &rule->au_ctxt.range.level[0]); + rc = mls_level_dom(level, + &rule->au_ctxt.range.level[0]); break; } } out: rcu_read_unlock(); - return match; + if (rc < 0) + return rc; + *match = !!rc; + return 0; } static int aurule_avc_callback(u32 event) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 9a121ad53b16..ea0f0cf11ff3 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4764,11 +4764,15 @@ static int smack_audit_rule_known(struct audit_krule *krule) * @field: audit rule flags given from user-space * @op: required testing operator * @vrule: smack internal rule presentation + * @match: the match result * * The core Audit hook. It's used to take the decision of * whether to audit or not to audit a given object. + * + * Returns 0 on success or negative error code on failure. */ -static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule) +static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, + bool *match) { struct smack_known *skp; char *rule = vrule; @@ -4778,8 +4782,10 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule) return -ENOENT; } - if (field != AUDIT_SUBJ_USER && field != AUDIT_OBJ_USER) + if (field != AUDIT_SUBJ_USER && field != AUDIT_OBJ_USER) { + *match = false; return 0; + } skp = smack_from_secid(secid); @@ -4789,10 +4795,11 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule) * label. */ if (op == Audit_equal) - return (rule == skp->smk_known); - if (op == Audit_not_equal) - return (rule != skp->smk_known); - + *match = (rule == skp->smk_known); + else if (op == Audit_not_equal) + *match = (rule != skp->smk_known); + else + *match = false; return 0; } From patchwork Thu Jul 11 11:18:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730493 Received: from dggsgout11.his.huawei.com (dggsgout11.his.huawei.com [45.249.212.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B440C15E5BB; Thu, 11 Jul 2024 11:14:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696444; cv=none; b=QKvgbBvK/vZ0SWEjqhWdYliW400KzFuEy48cWYjyTbKvYXBLwDHISMK7Y6unNTQGvpq4cm3zZKAgTZ/yOUo8Ik/9HTLcQHqJvzC+mRqxHaYawcbelfXO5fAwwQmiGtQ05Rf9RMT+Q44oJmTw3yhf/27DqfJkCdrRF+Xp4WtWoJU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696444; c=relaxed/simple; bh=dVFlmX5uBposykYVrBSK4anwD82QJYhrFIH10L94NdM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=l6uokOo41d+iLlBm1uS0i2j4PWdV4PTlxU9bsovB7QvWqUZTU09a5Odh95W0PwyUNsMf56QvIWqrv0u9xsMe8gYSodt7d37dvnH3QEp57WAt23+emlHcyMO0bQSDw1o0smDcDFJ/FxwBJ2xk+9tezFREAkBfewhbzqGXmbpDLZc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.216]) by dggsgout11.his.huawei.com (SkyGuard) with ESMTP id 4WKXCy5ZHkz4f3kJt; Thu, 11 Jul 2024 19:13:50 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 7050D1A0199; Thu, 11 Jul 2024 19:13:58 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgCHjPVxvo9mulQgBw--.25300S13; Thu, 11 Jul 2024 19:13:57 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 11/20] bpf, lsm: Add disabled BPF LSM hook list Date: Thu, 11 Jul 2024 19:18:59 +0800 Message-Id: <20240711111908.3817636-12-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711111908.3817636-1-xukuohai@huaweicloud.com> References: <20240711111908.3817636-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgCHjPVxvo9mulQgBw--.25300S13 X-Coremail-Antispam: 1UD129KBjvJXoW7uFyfWry7KF1fKF1DJF45Awb_yoW8Crykpa 1fJryYkryFqw4a93W5tFs5urW5Jr4vqanrK3W7J34Yyr40vr1kXw1jkrna9r9xuryUJrn3 KF4jgF1Ygry2va7anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBSb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVWxJr0_GcWl84ACjcxK6I8E87Iv67AKxVW0oVCq3wA2z4x0Y4vEx4A2jsIEc7CjxVAF wI0_GcCE3s1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2 WlYx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkE bVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCF04k20xvY0x 0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E 7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Wrv_Gr1UMIIYrxkI7VAKI48JMIIF0x vE2Ix0cI8IcVAFwI0_Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4UJVWxJr1lIxAI cVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2js IEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvjxUFgAwUUUUU X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai Add a disabled hooks list for BPF LSM. progs being attached to the listed hooks will be rejected by the verifier. Suggested-by: KP Singh Signed-off-by: Xu Kuohai --- kernel/bpf/bpf_lsm.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c index 08a338e1f231..e5feb6560fe6 100644 --- a/kernel/bpf/bpf_lsm.c +++ b/kernel/bpf/bpf_lsm.c @@ -36,6 +36,12 @@ BTF_SET_START(bpf_lsm_hooks) #undef LSM_HOOK BTF_SET_END(bpf_lsm_hooks) +BTF_SET_START(bpf_lsm_disabled_hooks) +BTF_ID(func, bpf_lsm_getprocattr) +BTF_ID(func, bpf_lsm_setprocattr) +BTF_ID(func, bpf_lsm_ismaclabel) +BTF_SET_END(bpf_lsm_disabled_hooks) + /* List of LSM hooks that should operate on 'current' cgroup regardless * of function signature. */ @@ -97,15 +103,24 @@ void bpf_lsm_find_cgroup_shim(const struct bpf_prog *prog, int bpf_lsm_verify_prog(struct bpf_verifier_log *vlog, const struct bpf_prog *prog) { + u32 btf_id = prog->aux->attach_btf_id; + const char *func_name = prog->aux->attach_func_name; + if (!prog->gpl_compatible) { bpf_log(vlog, "LSM programs must have a GPL compatible license\n"); return -EINVAL; } - if (!btf_id_set_contains(&bpf_lsm_hooks, prog->aux->attach_btf_id)) { + if (btf_id_set_contains(&bpf_lsm_disabled_hooks, btf_id)) { + bpf_log(vlog, "attach_btf_id %u points to disabled hook %s\n", + btf_id, func_name); + return -EINVAL; + } + + if (!btf_id_set_contains(&bpf_lsm_hooks, btf_id)) { bpf_log(vlog, "attach_btf_id %u points to wrong type name %s\n", - prog->aux->attach_btf_id, prog->aux->attach_func_name); + btf_id, func_name); return -EINVAL; } From patchwork Thu Jul 11 11:19:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730501 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1F67F16CD1D; Thu, 11 Jul 2024 11:14:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696451; cv=none; b=mMOhKwWT3yMGNaSNXFLFUR+Eyl25sNzc871gLr1fjbt9+yBERsJapG7M1uP5np+gRV+sq2d4oomCAGXwv3BCmYRwOfGZmxzTkNPKxeDUnot9sx5evprLxUmwpZVTvFCUDbh2pFqq/eS/GW0zMHGTNNGo74q2mGL6QUwCqqDYkB0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720696451; c=relaxed/simple; bh=4aeLwWNHq/s0RMuojnFjDGBoFx4/hqYrejdNWWtuzgI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=jf6+jDROQRhJYLXe5ape4KUFLmbOioa6RjKiFv2IBbQiT3VG9HrV17+k1b8epAagn+BdY/gb/QZzbLDEVNK4XnXa2wBjSpDovqWvRZxbHp4MY9nhSlUBVVSXxKxeNxaVoctL5Pq2iEkMU7wZ5zT5J6DB30My6qWJF0YDAyOVcYc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.216]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTP id 4WKXCt6f8qz4f3jXw; Thu, 11 Jul 2024 19:13:46 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 9713C1A0189; Thu, 11 Jul 2024 19:13:58 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgCHjPVxvo9mulQgBw--.25300S14; Thu, 11 Jul 2024 19:13:58 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 12/20] bpf, lsm: Enable BPF LSM prog to read/write return value parameters Date: Thu, 11 Jul 2024 19:19:00 +0800 Message-Id: <20240711111908.3817636-13-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711111908.3817636-1-xukuohai@huaweicloud.com> References: <20240711111908.3817636-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgCHjPVxvo9mulQgBw--.25300S14 X-Coremail-Antispam: 1UD129KBjvJXoWxAw47XFWxWF4rtr1UGF4Durg_yoWrKr13pF 4fJryFkr4vvrWag3ZrtFs5uFW5Jw40gw42ka9xXry0vF1jvr1rt3WUGryaqrW3KFyDJr1f Kr429FWY9347ZFJanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBIb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW7JVWDJwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVWxJr0_GcWl84ACjcxK6I8E87Iv67AKxVW0oVCq3wA2z4x0Y4vEx4A2jsIEc7CjxVAF wI0_GcCE3s1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2 WlYx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkE bVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCF04k20xvY0x 0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E 7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Wrv_Gr1UMIIYrxkI7VAKI48JMIIF0x vE2Ix0cI8IcVAFwI0_Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26F4UJVW0owCI42IY 6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aV CY1x0267AKxVWxJr0_GcJvcSsGvfC2KfnxnUUI43ZEXa7IU13l1DUUUUU== X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai Output parameters are used to refactor the LSM hook return values. To make these hooks usable by bpf prog, it is necessary for bpf prog to read and write these output return value parameters. All return value parameters are added as the last parameter and are always pointers to integer types. This patch uses BTF ID list to specify which LMS hooks have return value parameters and enables bpf prog to read/write the last parameters of these hooks in the verifier. Signed-off-by: Xu Kuohai --- include/linux/bpf_lsm.h | 6 ++++++ kernel/bpf/bpf_lsm.c | 15 +++++++++++++++ kernel/bpf/btf.c | 16 +++++++++++++++- kernel/bpf/verifier.c | 33 ++++++++++++++++++++++++++++++++- 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h index 1de7ece5d36d..73e1f6dbec4a 100644 --- a/include/linux/bpf_lsm.h +++ b/include/linux/bpf_lsm.h @@ -45,6 +45,8 @@ void bpf_inode_storage_free(struct inode *inode); void bpf_lsm_find_cgroup_shim(const struct bpf_prog *prog, bpf_func_t *bpf_func); +bool bpf_lsm_has_retval_param(const struct bpf_prog *prog); + #else /* !CONFIG_BPF_LSM */ static inline bool bpf_lsm_is_sleepable_hook(u32 btf_id) @@ -78,6 +80,10 @@ static inline void bpf_lsm_find_cgroup_shim(const struct bpf_prog *prog, { } +static inline bool bpf_lsm_has_retval_param(const struct bpf_prog *prog) +{ + return false; +} #endif /* CONFIG_BPF_LSM */ #endif /* _LINUX_BPF_LSM_H */ diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c index e5feb6560fe6..a8f8358c77e3 100644 --- a/kernel/bpf/bpf_lsm.c +++ b/kernel/bpf/bpf_lsm.c @@ -405,3 +405,18 @@ const struct bpf_verifier_ops lsm_verifier_ops = { .get_func_proto = bpf_lsm_func_proto, .is_valid_access = btf_ctx_access, }; + +BTF_SET_START(retval_param_lsm_hooks) +BTF_ID(func, bpf_lsm_inode_need_killpriv) +BTF_ID(func, bpf_lsm_inode_getsecurity) +BTF_ID(func, bpf_lsm_inode_listsecurity) +BTF_ID(func, bpf_lsm_getselfattr) +BTF_ID(func, bpf_lsm_key_getsecurity) +BTF_ID(func, bpf_lsm_audit_rule_match) +BTF_SET_END(retval_param_lsm_hooks) + +bool bpf_lsm_has_retval_param(const struct bpf_prog *prog) +{ + return btf_id_set_contains(&retval_param_lsm_hooks, + prog->aux->attach_btf_id); +} diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 4ff11779699e..df299d600b10 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -6499,8 +6499,22 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type, */ return true; - if (is_int_ptr(btf, t)) + + if (is_int_ptr(btf, t)) { + /* the retval param for LSM hook is always the last param. */ + if (arg == nr_args - 1 && + prog->expected_attach_type == BPF_LSM_MAC && + bpf_lsm_has_retval_param(prog)) { + u32 id; + + btf_type_skip_modifiers(btf, t->type, &id); + info->btf = btf; + /* the retval param should never be NULL */ + info->reg_type = PTR_TO_BTF_ID | PTR_TRUSTED; + info->btf_id = id; + } return true; + } /* this is a pointer to another type */ for (i = 0; i < prog->aux->ctx_arg_info_size; i++) { diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index c0263fb5ca4b..a0bbef2d14e4 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -6527,7 +6527,38 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, return -EACCES; } - if (env->ops->btf_struct_access && !type_is_alloc(reg->type) && atype == BPF_WRITE) { + if (btf_type_is_int(t)) { + u32 tsize; + const char *tname; + const struct btf_type *err; + const char *access = atype == BPF_READ ? "read" : "write"; + + /* only BPF LSM is allowed */ + if (WARN_ON_ONCE(env->prog->expected_attach_type != BPF_LSM_MAC)) { + verbose(env, "verifier internal error: not BPF LSM\n"); + return -EACCES; + } + + tname = btf_name_by_offset(reg->btf, t->name_off); + if (off != 0) { + verbose(env, "invalid %s offset: %d (expected 0, type=%s)\n", + access, off, tname); + return -EACCES; + } + + err = btf_resolve_size(reg->btf, t, &tsize); + if (IS_ERR(err)) { + verbose(env, "unable to resolve the size of type '%s': %ld\n", + tname, PTR_ERR(err)); + return PTR_ERR(err); + } + if (size != tsize) { + verbose(env, "invalid %s size: %d (expected %u, type=%s)\n", + access, size, tsize, tname); + return -EACCES; + } + ret = SCALAR_VALUE; + } else if (env->ops->btf_struct_access && !type_is_alloc(reg->type) && atype == BPF_WRITE) { if (!btf_is_kernel(reg->btf)) { verbose(env, "verifier internal error: reg->btf must be kernel btf\n"); return -EFAULT; From patchwork Thu Jul 11 11:38:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730579 Received: from dggsgout11.his.huawei.com (dggsgout11.his.huawei.com [45.249.212.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4892F15F318; Thu, 11 Jul 2024 11:33:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720697597; cv=none; b=fAHarFmmwOnf3xW2gfSUk1ovMPW1WDOVpbeXf0a5pmnSl98wUR4Aa3A5WlaIm2v2Ws/VzWqPAjTTB5ztgzmhmeNkrcSKLSCxp175mKYomTd4POfJhk8yoswhfKkkeHOXW3lI2SQB0GlYyo/Lzo/Vq2T8twJU2QQkQ7UpUsEgS2M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720697597; c=relaxed/simple; bh=U/aVWd6GcCcklvM0eKm4aTu1GkOwloBt3ViFsr52kvc=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=p+NqO5Ol6APBE7sqfORSd5tWgKySjzfLxEFiRdEIjbG3LJF0RDfjHpEh3ZH8LI8J2y/YMIaZDasLRO3V3tNgRwU6cKQ8GzPBujjffZp7XuoeciWkn62qNrEE6og/1CvVzOSpz8aBC/yWCNMJtweqskdF8o00Mi/3NYAKFPf/KCw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.235]) by dggsgout11.his.huawei.com (SkyGuard) with ESMTP id 4WKXf70MWFz4f3kKV; Thu, 11 Jul 2024 19:33:03 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id AFA8E1A058E; Thu, 11 Jul 2024 19:33:10 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgDXKvT0wo9mzI8hBw--.25380S2; Thu, 11 Jul 2024 19:33:10 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 13/20] bpf, lsm: Add check for BPF LSM return value Date: Thu, 11 Jul 2024 19:38:21 +0800 Message-Id: <20240711113828.3818398-1-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgDXKvT0wo9mzI8hBw--.25380S2 X-Coremail-Antispam: 1UD129KBjvJXoW3Wr1UAr1rGrykuFW8Ar4xJFb_yoWfArWxpF sxGryDAr4vvrW3uFnrtan7ZF1rJry0g3yIkF9rGryFyFWav3s5XF1qgryjvr1fCrWDCw1x Gr4jgrW5u347ZaDanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUkIb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28lY4IEw2IIxxk0rwA2F7IY1VAKz4 vEj48ve4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Gr0_Xr1l84ACjcxK6xIIjxv20xvEc7Cj xVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I 0E14v26rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40E x7xfMcIj6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x 0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IY c2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s 026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI 42IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwCI42 IY6xAIw20EY4v20xvaj40_Wr1j6rW3Jr1lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2 z280aVCY1x0267AKxVWxJr0_GcJvcSsGvfC2KfnxnUUI43ZEXa7IU1c4S7UUUUU== X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai A bpf prog returning a positive number attached to file_alloc_security hook makes kernel panic. This happens because file system can not filter out the positive number returned by the LSM prog using IS_ERR, and misinterprets this positive number as a file pointer. Given that hook file_alloc_security never returned positive number before the introduction of BPF LSM, and other BPF LSM hooks may encounter similar issues, this patch adds LSM return value check in verifier, to ensure no unexpected value is returned. Fixes: 520b7aa00d8c ("bpf: lsm: Initialize the BPF LSM hooks") Reported-by: Xin Liu Signed-off-by: Xu Kuohai Acked-by: Eduard Zingerman --- include/linux/bpf.h | 1 + include/linux/bpf_lsm.h | 9 +++++++ kernel/bpf/bpf_lsm.c | 30 ++++++++++++++++++++- kernel/bpf/btf.c | 5 +++- kernel/bpf/verifier.c | 60 ++++++++++++++++++++++++++++++++++------- 5 files changed, 94 insertions(+), 11 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 4f1d4a97b9d1..d255201035c4 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -927,6 +927,7 @@ struct bpf_insn_access_aux { }; }; struct bpf_verifier_log *log; /* for verbose logs */ + bool is_retval; /* is accessing function return value ? */ }; static inline void diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h index 73e1f6dbec4a..ca5f2176c940 100644 --- a/include/linux/bpf_lsm.h +++ b/include/linux/bpf_lsm.h @@ -9,6 +9,7 @@ #include #include +#include #include #ifdef CONFIG_BPF_LSM @@ -47,6 +48,8 @@ void bpf_lsm_find_cgroup_shim(const struct bpf_prog *prog, bpf_func_t *bpf_func) bool bpf_lsm_has_retval_param(const struct bpf_prog *prog); +int bpf_lsm_get_retval_range(const struct bpf_prog *prog, + struct bpf_retval_range *range); #else /* !CONFIG_BPF_LSM */ static inline bool bpf_lsm_is_sleepable_hook(u32 btf_id) @@ -84,6 +87,12 @@ static inline bool bpf_lsm_has_retval_param(const struct bpf_prog *prog) { return false; } + +static inline int bpf_lsm_get_retval_range(const struct bpf_prog *prog, + struct bpf_retval_range *range) +{ + return -EOPNOTSUPP; +} #endif /* CONFIG_BPF_LSM */ #endif /* _LINUX_BPF_LSM_H */ diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c index a8f8358c77e3..9dd338099d4a 100644 --- a/kernel/bpf/bpf_lsm.c +++ b/kernel/bpf/bpf_lsm.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -420,3 +419,32 @@ bool bpf_lsm_has_retval_param(const struct bpf_prog *prog) return btf_id_set_contains(&retval_param_lsm_hooks, prog->aux->attach_btf_id); } + +/* hooks return 0 or 1 */ +BTF_SET_START(bool_lsm_hooks) +BTF_ID(func, bpf_lsm_xfrm_state_pol_flow_match) +BTF_ID(func, bpf_lsm_audit_rule_known) +BTF_ID(func, bpf_lsm_inode_xattr_skipcap) +BTF_SET_END(bool_lsm_hooks) + +int bpf_lsm_get_retval_range(const struct bpf_prog *prog, + struct bpf_retval_range *retval_range) +{ + /* no return value range for void hooks */ + if (!prog->aux->attach_func_proto->type) + return -EINVAL; + + if (btf_id_set_contains(&bool_lsm_hooks, prog->aux->attach_btf_id)) { + retval_range->minval = 0; + retval_range->maxval = 1; + } else { + /* All other LSM hooks, except task_prctl, return 0 on success + * and negative error code on failure. + * To keep things simple, we only allow bpf progs to return 0 + * or negative errno for task_prctl. + */ + retval_range->minval = -MAX_ERRNO; + retval_range->maxval = 0; + } + return 0; +} diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index df299d600b10..ce892565367d 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -6416,8 +6416,11 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type, if (arg == nr_args) { switch (prog->expected_attach_type) { - case BPF_LSM_CGROUP: case BPF_LSM_MAC: + /* mark we are accessing the return value */ + info->is_retval = true; + fallthrough; + case BPF_LSM_CGROUP: case BPF_TRACE_FEXIT: /* When LSM programs are attached to void LSM hooks * they use FEXIT trampolines and when attached to diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index a0bbef2d14e4..6f5d8ca995d6 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -2334,6 +2334,25 @@ static void mark_reg_unknown(struct bpf_verifier_env *env, __mark_reg_unknown(env, regs + regno); } +static int __mark_reg_s32_range(struct bpf_verifier_env *env, + struct bpf_reg_state *regs, + u32 regno, + s32 s32_min, + s32 s32_max) +{ + struct bpf_reg_state *reg = regs + regno; + + reg->s32_min_value = max_t(s32, reg->s32_min_value, s32_min); + reg->s32_max_value = min_t(s32, reg->s32_max_value, s32_max); + + reg->smin_value = max_t(s64, reg->smin_value, s32_min); + reg->smax_value = min_t(s64, reg->smax_value, s32_max); + + reg_bounds_sync(reg); + + return reg_bounds_sanity_check(env, reg, "s32_range"); +} + static void __mark_reg_not_init(const struct bpf_verifier_env *env, struct bpf_reg_state *reg) { @@ -5587,11 +5606,12 @@ static int check_packet_access(struct bpf_verifier_env *env, u32 regno, int off, /* check access to 'struct bpf_context' fields. Supports fixed offsets only */ static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off, int size, enum bpf_access_type t, enum bpf_reg_type *reg_type, - struct btf **btf, u32 *btf_id) + struct btf **btf, u32 *btf_id, bool *is_retval) { struct bpf_insn_access_aux info = { .reg_type = *reg_type, .log = &env->log, + .is_retval = false, }; if (env->ops->is_valid_access && @@ -5604,6 +5624,7 @@ static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off, * type of narrower access. */ *reg_type = info.reg_type; + *is_retval = info.is_retval; if (base_type(*reg_type) == PTR_TO_BTF_ID) { *btf = info.btf; @@ -6803,6 +6824,17 @@ static int check_stack_access_within_bounds( return grow_stack_state(env, state, -min_off /* size */); } +static bool get_func_retval_range(struct bpf_prog *prog, + struct bpf_retval_range *range) +{ + if (prog->type == BPF_PROG_TYPE_LSM && + prog->expected_attach_type == BPF_LSM_MAC && + !bpf_lsm_get_retval_range(prog, range)) { + return true; + } + return false; +} + /* check whether memory at (regno + off) is accessible for t = (read | write) * if t==write, value_regno is a register which value is stored into memory * if t==read, value_regno is a register which will receive the value from memory @@ -6907,6 +6939,8 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn if (!err && value_regno >= 0 && (t == BPF_READ || rdonly_mem)) mark_reg_unknown(env, regs, value_regno); } else if (reg->type == PTR_TO_CTX) { + bool is_retval = false; + struct bpf_retval_range range; enum bpf_reg_type reg_type = SCALAR_VALUE; struct btf *btf = NULL; u32 btf_id = 0; @@ -6922,7 +6956,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn return err; err = check_ctx_access(env, insn_idx, off, size, t, ®_type, &btf, - &btf_id); + &btf_id, &is_retval); if (err) verbose_linfo(env, insn_idx, "; "); if (!err && t == BPF_READ && value_regno >= 0) { @@ -6931,7 +6965,14 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn * case, we know the offset is zero. */ if (reg_type == SCALAR_VALUE) { - mark_reg_unknown(env, regs, value_regno); + if (is_retval && get_func_retval_range(env->prog, &range)) { + err = __mark_reg_s32_range(env, regs, value_regno, + range.minval, range.maxval); + if (err) + return err; + } else { + mark_reg_unknown(env, regs, value_regno); + } } else { mark_reg_known_zero(env, regs, value_regno); @@ -15782,12 +15823,13 @@ static int check_return_code(struct bpf_verifier_env *env, int regno, const char case BPF_PROG_TYPE_LSM: if (env->prog->expected_attach_type != BPF_LSM_CGROUP) { - /* Regular BPF_PROG_TYPE_LSM programs can return - * any value. - */ - return 0; - } - if (!env->prog->aux->attach_func_proto->type) { + /* no range found, any return value is allowed */ + if (!get_func_retval_range(env->prog, &range)) + return 0; + /* no restricted range, any return value is allowed */ + if (range.minval == S32_MIN && range.maxval == S32_MAX) + return 0; + } else if (!env->prog->aux->attach_func_proto->type) { /* Make sure programs that attach to void * hooks don't try to modify return value. */ From patchwork Thu Jul 11 11:38:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730578 Received: from dggsgout11.his.huawei.com (dggsgout11.his.huawei.com [45.249.212.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 092B415ECFD; Thu, 11 Jul 2024 11:33:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720697597; cv=none; b=qDaUpkKswsg50CrG/VSHQ5YHJoXL/VMMdTuN8DW5XUR/x6f4qqXZmysfmQL3OVLD2MPo9VJpWdZnNOeioJGYpKVZ3hbHkKgClqGkJFskgftaaolvmYrOVLa/JgacP+99qWCIZeYSAVs/SJ/74qp0ovhNa8CH3cBUxCzFlMw3JSI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720697597; c=relaxed/simple; bh=Nka+bODEYP2N+MN4laCszVqVFo8qBRk8+LNJimzPa2U=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=hmzCmx1zISFDQ9zcJcKEE0QQ06uPq8yQQZM7ewrkdbbyYLHzfohEvkP3x4zHF4xFh7gez1xZFq9qa/Mw/bT6Yj2neg7ZNZixSlQW6mGIu533LojJ9HN7Q3f1cLGdoRBgk/SVJ0Ei4unNXzixde8Pt08NLuU6SE2Jj2O9vVg1Sr0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.216]) by dggsgout11.his.huawei.com (SkyGuard) with ESMTP id 4WKXf205f3z4f3mHV; Thu, 11 Jul 2024 19:32:58 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id E0D301A0189; Thu, 11 Jul 2024 19:33:10 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgDXKvT0wo9mzI8hBw--.25380S3; Thu, 11 Jul 2024 19:33:10 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 14/20] bpf: Prevent tail call between progs attached to different hooks Date: Thu, 11 Jul 2024 19:38:22 +0800 Message-Id: <20240711113828.3818398-2-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711113828.3818398-1-xukuohai@huaweicloud.com> References: <20240711113828.3818398-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgDXKvT0wo9mzI8hBw--.25380S3 X-Coremail-Antispam: 1UD129KBjvJXoWxAF1Dtw45tFWUJF1ktryxXwb_yoWrGrWxpF ZrZry8Cr48ur4xXrWxGw1fZry5Aw48Kw47K348X34YvF4qqrn5KF4jgFWavry5Gry5JrWS g3W2qFZ8CF95Z3DanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBFb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUGw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV W8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMc Ij6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_ Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2Ij64 vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8G jcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42IY6x IIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVWxJVW8Jr1lIxAIcVCF 04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2jsIEc7 CjxVAFwI0_Cr1j6rxdYxBIdaVFxhVjvjDU0xZFpf9x07UAHUDUUUUU= X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai bpf progs can be attached to kernel functions, and the attached functions can take different parameters or return different return values. If prog attached to one kernel function tail calls prog attached to another kernel function, the ctx access or return value verification could be bypassed. For example, if prog1 is attached to func1 which takes only 1 parameter and prog2 is attached to func2 which takes two parameters. Since verifier assumes the bpf ctx passed to prog2 is constructed based on func2's prototype, verifier allows prog2 to access the second parameter from the bpf ctx passed to it. The problem is that verifier does not prevent prog1 from passing its bpf ctx to prog2 via tail call. In this case, the bpf ctx passed to prog2 is constructed from func1 instead of func2, that is, the assumption for ctx access verification is bypassed. Another example, if BPF LSM prog1 is attached to hook file_alloc_security, and BPF LSM prog2 is attached to hook bpf_lsm_audit_rule_known. Verifier knows the return value rules for these two hooks, e.g. it is legal for bpf_lsm_audit_rule_known to return positive number 1, and it is illegal for file_alloc_security to return positive number. So verifier allows prog2 to return positive number 1, but does not allow prog1 to return positive number. The problem is that verifier does not prevent prog1 from calling prog2 via tail call. In this case, prog2's return value 1 will be used as the return value for prog1's hook file_alloc_security. That is, the return value rule is bypassed. This patch adds restriction for tail call to prevent such bypasses. Signed-off-by: Xu Kuohai --- include/linux/bpf.h | 1 + kernel/bpf/core.c | 21 ++++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index d255201035c4..bf71edb260cd 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -294,6 +294,7 @@ struct bpf_map { * same prog type, JITed flag and xdp_has_frags flag. */ struct { + const struct btf_type *attach_func_proto; spinlock_t lock; enum bpf_prog_type type; bool jited; diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 7ee62e38faf0..4e07cc057d6f 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -2302,6 +2302,7 @@ bool bpf_prog_map_compatible(struct bpf_map *map, { enum bpf_prog_type prog_type = resolve_prog_type(fp); bool ret; + struct bpf_prog_aux *aux = fp->aux; if (fp->kprobe_override) return false; @@ -2311,7 +2312,7 @@ bool bpf_prog_map_compatible(struct bpf_map *map, * in the case of devmap and cpumap). Until device checks * are implemented, prohibit adding dev-bound programs to program maps. */ - if (bpf_prog_is_dev_bound(fp->aux)) + if (bpf_prog_is_dev_bound(aux)) return false; spin_lock(&map->owner.lock); @@ -2321,12 +2322,26 @@ bool bpf_prog_map_compatible(struct bpf_map *map, */ map->owner.type = prog_type; map->owner.jited = fp->jited; - map->owner.xdp_has_frags = fp->aux->xdp_has_frags; + map->owner.xdp_has_frags = aux->xdp_has_frags; + map->owner.attach_func_proto = aux->attach_func_proto; ret = true; } else { ret = map->owner.type == prog_type && map->owner.jited == fp->jited && - map->owner.xdp_has_frags == fp->aux->xdp_has_frags; + map->owner.xdp_has_frags == aux->xdp_has_frags; + if (ret && + map->owner.attach_func_proto != aux->attach_func_proto) { + switch (prog_type) { + case BPF_PROG_TYPE_TRACING: + case BPF_PROG_TYPE_LSM: + case BPF_PROG_TYPE_EXT: + case BPF_PROG_TYPE_STRUCT_OPS: + ret = false; + break; + default: + break; + } + } } spin_unlock(&map->owner.lock); From patchwork Thu Jul 11 11:38:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730577 Received: from dggsgout11.his.huawei.com (dggsgout11.his.huawei.com [45.249.212.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0926915ECFA; Thu, 11 Jul 2024 11:33:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720697596; cv=none; b=pNxHQuT7y2vwdUI835gdSJtci6tJdomye3yGktQ0t1a+yax+yi5lGVVFHDvVbqGRChmg1BT5+S0/2xbFKS1FQQmailVn/oYlHF9txrOedo5w8DpsG8ATCU6Kkg8+1lyaxlNbt5qEf39HpeS1OlaIQ2Dg06xj8HjIEepkOkL3mMA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720697596; c=relaxed/simple; bh=ntYK0I6N0/kgYbWR4+EjCtm5jGcxmJ84cb2HnQBybDk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=LDZkNzDvH7cIL7QevqZclewxpGxcZAcILa9lIk6xKtxO4Z5oqtmoxY8ZVu640EddKUVGXqHMMpOWQ5XMpLH1hCVE7/wa1lHN+5zTVWl6nUjbXOhO1tU8RkJ/VG6wIEvcMzTteofsnPyF63F0/l9LoV6GGHV0YUX537cfpAnACL8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.235]) by dggsgout11.his.huawei.com (SkyGuard) with ESMTP id 4WKXf21CnCz4f3mHb; Thu, 11 Jul 2024 19:32:58 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 140911A0572; Thu, 11 Jul 2024 19:33:11 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgDXKvT0wo9mzI8hBw--.25380S4; Thu, 11 Jul 2024 19:33:10 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 15/20] bpf: Fix compare error in function retval_range_within Date: Thu, 11 Jul 2024 19:38:23 +0800 Message-Id: <20240711113828.3818398-3-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711113828.3818398-1-xukuohai@huaweicloud.com> References: <20240711113828.3818398-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgDXKvT0wo9mzI8hBw--.25380S4 X-Coremail-Antispam: 1UD129KBjvJXoWxXw4kWF4rtw1kZw4rtw4UCFg_yoWrXw4rpr 4rG34qyr1DtF4fua12yFs5Aa4Fyr1aqayIkFWkJ3sYyw45trWDXFy7Kw1a9ayFyrW8Gwn2 9F4jva15Gw4UuaDanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUB2b4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUXw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV W8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMc Ij6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_ Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2Ij64 vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8G jcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42IY6x IIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF0xvE 42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6x kF7I0E14v26F4UJVW0obIYCTnIWIevJa73UjIFyTuYvjxUFa9-UUUUU X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai After checking lsm hook return range in verifier, the test case "test_progs -t test_lsm" failed, and the failure log says: libbpf: prog 'test_int_hook': BPF program load failed: Invalid argument libbpf: prog 'test_int_hook': -- BEGIN PROG LOAD LOG -- 0: R1=ctx() R10=fp0 ; int BPF_PROG(test_int_hook, struct vm_area_struct *vma, @ lsm.c:89 0: (79) r0 = *(u64 *)(r1 +24) ; R0_w=scalar(smin=smin32=-4095,smax=smax32=0) R1=ctx() [...] 24: (b4) w0 = -1 ; R0_w=0xffffffff ; int BPF_PROG(test_int_hook, struct vm_area_struct *vma, @ lsm.c:89 25: (95) exit At program exit the register R0 has smin=4294967295 smax=4294967295 should have been in [-4095, 0] It can be seen that instruction "w0 = -1" zero extended -1 to 64-bit register r0, setting both smin and smax values of r0 to 4294967295. This resulted in a false reject when r0 was checked with range [-4095, 0]. Given bpf lsm does not return 64-bit values, this patch fixes it by changing the compare between r0 and return range from 64-bit operation to 32-bit operation for bpf lsm. Fixes: 8fa4ecd49b81 ("bpf: enforce exact retval range on subprog/callback exit") Signed-off-by: Xu Kuohai Acked-by: Shung-Hsi Yu --- kernel/bpf/verifier.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 6f5d8ca995d6..19ef3d27dbb7 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -9995,9 +9995,13 @@ static bool in_rbtree_lock_required_cb(struct bpf_verifier_env *env) return is_rbtree_lock_required_kfunc(kfunc_btf_id); } -static bool retval_range_within(struct bpf_retval_range range, const struct bpf_reg_state *reg) +static bool retval_range_within(struct bpf_retval_range range, const struct bpf_reg_state *reg, + bool return_32bit) { - return range.minval <= reg->smin_value && reg->smax_value <= range.maxval; + if (return_32bit) + return range.minval <= reg->s32_min_value && reg->s32_max_value <= range.maxval; + else + return range.minval <= reg->smin_value && reg->smax_value <= range.maxval; } static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx) @@ -10034,8 +10038,8 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx) if (err) return err; - /* enforce R0 return value range */ - if (!retval_range_within(callee->callback_ret_range, r0)) { + /* enforce R0 return value range, and bpf_callback_t returns 64bit */ + if (!retval_range_within(callee->callback_ret_range, r0, false)) { verbose_invalid_scalar(env, r0, callee->callback_ret_range, "At callback return", "R0"); return -EINVAL; @@ -15718,6 +15722,7 @@ static int check_return_code(struct bpf_verifier_env *env, int regno, const char int err; struct bpf_func_state *frame = env->cur_state->frame[0]; const bool is_subprog = frame->subprogno; + bool return_32bit = false; /* LSM and struct_ops func-ptr's return type could be "void" */ if (!is_subprog || frame->in_exception_callback_fn) { @@ -15829,6 +15834,7 @@ static int check_return_code(struct bpf_verifier_env *env, int regno, const char /* no restricted range, any return value is allowed */ if (range.minval == S32_MIN && range.maxval == S32_MAX) return 0; + return_32bit = true; } else if (!env->prog->aux->attach_func_proto->type) { /* Make sure programs that attach to void * hooks don't try to modify return value. @@ -15859,7 +15865,7 @@ static int check_return_code(struct bpf_verifier_env *env, int regno, const char if (err) return err; - if (!retval_range_within(range, reg)) { + if (!retval_range_within(range, reg, return_32bit)) { verbose_invalid_scalar(env, reg, range, exit_ctx, reg_name); if (!is_subprog && prog->expected_attach_type == BPF_LSM_CGROUP && From patchwork Thu Jul 11 11:38:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730580 Received: from dggsgout11.his.huawei.com (dggsgout11.his.huawei.com [45.249.212.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7FB6715F3E0; Thu, 11 Jul 2024 11:33:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720697597; cv=none; b=snQG0aNXjwWQtySuxtyAHpFBV1UlwADe/cZrKxTJcFkjOcdqA9ZsGo2DRB7ABbbLEyT44JCG/DcCtG0E+1kHDHdL8VDp1P39yGcsY7SLl/DHxowvJ17sknZ18xbzJsVB/3anPpODPsoPuCtlkOE87rvuiFoMVXFPI1bjIn6rXGU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720697597; c=relaxed/simple; bh=zs+2mWRYQI/XTsMgKhZLe2dAzb2JMQ34yleDE47r7Ck=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=nOA8ImqZe0FKNIYpqiO6T4m/jrle7zmLClS+GVQwnWBI+K1VCAflbdNJrocHcCAP17Jnuq2vWB6TJPSDdYUh01teR7xrD+JGD/YlaYYVrtgfLE3SkNK5oHs8LuD8WmkUVBHXgLtTfPPQXVFPTHcp+S+wJazrS0hYMg7njM5DHgA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.235]) by dggsgout11.his.huawei.com (SkyGuard) with ESMTP id 4WKXf86yL9z4f3kKY; Thu, 11 Jul 2024 19:33:04 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 9FBA41A06D6; Thu, 11 Jul 2024 19:33:12 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgDXKvT0wo9mzI8hBw--.25380S5; Thu, 11 Jul 2024 19:33:10 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 16/20] bpf: Add a special case for bitwise AND on range [-1, 0] Date: Thu, 11 Jul 2024 19:38:24 +0800 Message-Id: <20240711113828.3818398-4-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711113828.3818398-1-xukuohai@huaweicloud.com> References: <20240711113828.3818398-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgDXKvT0wo9mzI8hBw--.25380S5 X-Coremail-Antispam: 1UD129KBjvJXoWfGF17ZryrtFyfZF1kWF13CFg_yoWDuFW7pF ZxGrnxWw4kAayUZwnFyan8ArZYvF48Aa18C3srA340vry3WFy5Kr15WFyjyasxAr4kGr4S qFnxX3y2kw4UZFJanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUB2b4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUWw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV W8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMc Ij6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_ Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2Ij64 vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8G jcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42IY6x IIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF0xvE 42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6x kF7I0E14v26F4UJVW0obIYCTnIWIevJa73UjIFyTuYvjxUFYFCUUUUU X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai With lsm return value check, the no-alu32 version test_libbpf_get_fd_by_id_opts is rejected by the verifier, and the log says: 0: R1=ctx() R10=fp0 ; int BPF_PROG(check_access, struct bpf_map *map, fmode_t fmode) @ test_libbpf_get_fd_by_id_opts.c:27 0: (b7) r0 = 0 ; R0_w=0 1: (79) r2 = *(u64 *)(r1 +0) func 'bpf_lsm_bpf_map' arg0 has btf_id 916 type STRUCT 'bpf_map' 2: R1=ctx() R2_w=trusted_ptr_bpf_map() ; if (map != (struct bpf_map *)&data_input) @ test_libbpf_get_fd_by_id_opts.c:29 2: (18) r3 = 0xffff9742c0951a00 ; R3_w=map_ptr(map=data_input,ks=4,vs=4) 4: (5d) if r2 != r3 goto pc+4 ; R2_w=trusted_ptr_bpf_map() R3_w=map_ptr(map=data_input,ks=4,vs=4) ; int BPF_PROG(check_access, struct bpf_map *map, fmode_t fmode) @ test_libbpf_get_fd_by_id_opts.c:27 5: (79) r0 = *(u64 *)(r1 +8) ; R0_w=scalar() R1=ctx() ; if (fmode & FMODE_WRITE) @ test_libbpf_get_fd_by_id_opts.c:32 6: (67) r0 <<= 62 ; R0_w=scalar(smax=0x4000000000000000,umax=0xc000000000000000,smin32=0,smax32=umax32=0,var_off=(0x0; 0xc000000000000000)) 7: (c7) r0 s>>= 63 ; R0_w=scalar(smin=smin32=-1,smax=smax32=0) ; @ test_libbpf_get_fd_by_id_opts.c:0 8: (57) r0 &= -13 ; R0_w=scalar(smax=0x7ffffffffffffff3,umax=0xfffffffffffffff3,smax32=0x7ffffff3,umax32=0xfffffff3,var_off=(0x0; 0xfffffffffffffff3)) ; int BPF_PROG(check_access, struct bpf_map *map, fmode_t fmode) @ test_libbpf_get_fd_by_id_opts.c:27 9: (95) exit And here is the C code of the prog. SEC("lsm/bpf_map") int BPF_PROG(check_access, struct bpf_map *map, fmode_t fmode) { if (map != (struct bpf_map *)&data_input) return 0; if (fmode & FMODE_WRITE) return -EACCES; return 0; } It is clear that the prog can only return either 0 or -EACCESS, and both values are legal. So why is it rejected by the verifier? The verifier log shows that the second if and return value setting statements in the prog is optimized to bitwise operations "r0 s>>= 63" and "r0 &= -13". The verifier correctly deduces that the value of r0 is in the range [-1, 0] after verifing instruction "r0 s>>= 63". But when the verifier proceeds to verify instruction "r0 &= -13", it fails to deduce the correct value range of r0. 7: (c7) r0 s>>= 63 ; R0_w=scalar(smin=smin32=-1,smax=smax32=0) 8: (57) r0 &= -13 ; R0_w=scalar(smax=0x7ffffffffffffff3,umax=0xfffffffffffffff3,smax32=0x7ffffff3,umax32=0xfffffff3,var_off=(0x0; 0xfffffffffffffff3)) So why the verifier fails to deduce the result of 'r0 &= -13'? The verifier uses tnum to track values, and the two ranges "[-1, 0]" and "[0, -1ULL]" are encoded to the same tnum. When verifing instruction "r0 &= -13", the verifier erroneously deduces the result from "[0, -1ULL] AND -13", which is out of the expected return range [-4095, 0]. As explained by Eduard in [0], the clang transformation that generates this pattern is located in DAGCombiner::SimplifySelectCC() method (see [1]). The transformation happens as a part of DAG to DAG rewrites (LLVM uses several internal representations: - generic optimizer uses LLVM IR, most of the work is done using this representation; - before instruction selection IR is converted to Selection DAG, some optimizations are applied at this stage, all such optimizations are a set of pattern replacements; - Selection DAG is converted to machine code, some optimizations are applied at the machine code level). Full pattern is described as follows: // fold (select_cc seteq (and x, y), 0, 0, A) -> (and (sra (shl x)) A) // where y is has a single bit set. // A plaintext description would be, we can turn the SELECT_CC into an AND // when the condition can be materialized as an all-ones register. Any // single bit-test can be materialized as an all-ones register with // shift-left and shift-right-arith. For this particular test case the DAG is converted as follows: .---------------- lhs The meaning of this select_cc is: | .------- rhs `lhs == rhs ? true value : false value` | | .----- true value | | | .-- false value v v v v (select_cc seteq (and X 2) 0 0 -13) ^ -> '---------------. (and (sra (sll X 62) 63) | -13) | | Before pattern is applied, it checks that second 'and' operand has only one bit set, (which is true for '2'). The pattern itself generates logical shift left / arithmetic shift right pair, that ensures that result is either all ones (-1) or all zeros (0). Hence, applying 'and' to shifts result and false value generates a correct result. As suggested by Eduard and Andrii, this patch makes a special case for source or destination register of '&=' operation being in range [-1, 0]. Meaning that one of the '&=' operands is either: - all ones, in which case the counterpart is the result of the operation; - all zeros, in which case zero is the result of the operation. That is, the result is equivalent to adding 0 to the counterpart. And MIN and MAX values could be deduced based on these observations. [0] https://lore.kernel.org/bpf/e62e2971301ca7f2e9eb74fc500c520285cad8f5.camel@gmail.com/ [1] https://github.com/llvm/llvm-project/blob/4523a267829c807f3fc8fab8e5e9613985a51565/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Suggested-by: Eduard Zingerman Suggested-by: Andrii Nakryiko Signed-off-by: Xu Kuohai --- include/linux/tnum.h | 3 ++ kernel/bpf/tnum.c | 25 +++++++++++++++++ kernel/bpf/verifier.c | 64 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) diff --git a/include/linux/tnum.h b/include/linux/tnum.h index 3c13240077b8..5e795d728b9f 100644 --- a/include/linux/tnum.h +++ b/include/linux/tnum.h @@ -52,6 +52,9 @@ struct tnum tnum_mul(struct tnum a, struct tnum b); /* Return a tnum representing numbers satisfying both @a and @b */ struct tnum tnum_intersect(struct tnum a, struct tnum b); +/* Return a tnum representing numbers satisfying either @a or @b */ +struct tnum tnum_union(struct tnum a, struct tnum b); + /* Return @a with all but the lowest @size bytes cleared */ struct tnum tnum_cast(struct tnum a, u8 size); diff --git a/kernel/bpf/tnum.c b/kernel/bpf/tnum.c index 9dbc31b25e3d..8028ce06fc1e 100644 --- a/kernel/bpf/tnum.c +++ b/kernel/bpf/tnum.c @@ -150,6 +150,31 @@ struct tnum tnum_intersect(struct tnum a, struct tnum b) return TNUM(v & ~mu, mu); } +/* Each bit has 3 states: unknown, known 0, known 1. Using x to represent + * unknown state, the result of the union of two bits is as follows: + * + * | x 0 1 + * -----+------------ + * x | x x x + * 0 | x 0 x + * 1 | x x 1 + * + * For tnum a and b, only the bits that are both known 0 or known 1 in a + * and b are known in the result of union a and b. + */ +struct tnum tnum_union(struct tnum a, struct tnum b) +{ + u64 v0, v1, mu; + + /* unknown bits either in a or b */ + mu = a.mask | b.mask; + /* "known 1" bits in both a and b */ + v1 = (a.value & b.value) & ~mu; + /* "known 0" bits in both a and b */ + v0 = (~a.value & ~b.value) & ~mu; + return TNUM(v1, ~(v0 | v1)); +} + struct tnum tnum_cast(struct tnum a, u8 size) { a.value &= (1ULL << (size * 8)) - 1; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 19ef3d27dbb7..7f4ee3b95f4e 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -13632,6 +13632,39 @@ static void scalar32_min_max_and(struct bpf_reg_state *dst_reg, return; } + /* special case: dst_reg is in range [-1, 0] */ + if (dst_reg->s32_min_value == -1 && dst_reg->s32_max_value == 0) { + /* the result is equivalent to adding 0 to src_reg */ + var32_off = tnum_union(src_reg->var_off, tnum_const(0)); + dst_reg->var_off = tnum_with_subreg(dst_reg->var_off, var32_off); + /* update signed min/max to include 0 */ + dst_reg->s32_min_value = min_t(s32, src_reg->s32_min_value, 0); + dst_reg->s32_max_value = max_t(s32, src_reg->s32_max_value, 0); + /* since we're adding 0 to src_reg and 0 is the smallest + * unsigned integer, dst_reg->u32_min_value should be 0, + * and dst->u32_max_value should be src_reg->u32_max_value. + */ + dst_reg->u32_min_value = 0; + dst_reg->u32_max_value = src_reg->u32_max_value; + return; + } + + /* special case: src_reg is in range [-1, 0] */ + if (src_reg->s32_min_value == -1 && src_reg->s32_max_value == 0) { + /* the result is equivalent to adding 0 to dst_reg */ + var32_off = tnum_union(dst_reg->var_off, tnum_const(0)); + dst_reg->var_off = tnum_with_subreg(dst_reg->var_off, var32_off); + /* update signed min/max to include 0 */ + dst_reg->s32_min_value = min_t(s32, dst_reg->s32_min_value, 0); + dst_reg->s32_max_value = max_t(s32, dst_reg->s32_max_value, 0); + /* since we're adding 0 to dst_reg and 0 is the smallest + * unsigned integer, dst_reg->u32_min_value should be 0, + * and dst->u32_max_value should remain unchanged. + */ + dst_reg->u32_min_value = 0; + return; + } + /* We get our minimum from the var_off, since that's inherently * bitwise. Our maximum is the minimum of the operands' maxima. */ @@ -13662,6 +13695,37 @@ static void scalar_min_max_and(struct bpf_reg_state *dst_reg, return; } + /* special case: dst_reg is in range [-1, 0] */ + if (dst_reg->smin_value == -1 && dst_reg->smax_value == 0) { + /* the result is equivalent to adding 0 to src_reg */ + dst_reg->var_off = tnum_union(src_reg->var_off, tnum_const(0)); + /* update signed min/max to include 0 */ + dst_reg->smin_value = min_t(s64, src_reg->smin_value, 0); + dst_reg->smax_value = max_t(s64, src_reg->smax_value, 0); + /* since we're adding 0 to src_reg and 0 is the smallest + * unsigned integer, dst_reg->umin_value should be 0, + * and dst->umax_value should be src_reg->umax_value. + */ + dst_reg->umin_value = 0; + dst_reg->umax_value = src_reg->umax_value; + return; + } + + /* special case: src_reg is in range [-1, 0] */ + if (src_reg->smin_value == -1 && src_reg->smax_value == 0) { + /* the result is equivalent to adding 0 to dst_reg */ + dst_reg->var_off = tnum_union(dst_reg->var_off, tnum_const(0)); + /* update signed min/max to include 0 */ + dst_reg->smin_value = min_t(s64, dst_reg->smin_value, 0); + dst_reg->smax_value = max_t(s64, dst_reg->smax_value, 0); + /* since we're adding 0 to dst_reg and 0 is the smallest + * unsigned integer, dst_reg->min_value should be 0, + * and dst->umax_value should remain unchanged. + */ + dst_reg->umin_value = 0; + return; + } + /* We get our minimum from the var_off, since that's inherently * bitwise. Our maximum is the minimum of the operands' maxima. */ From patchwork Thu Jul 11 11:38:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730581 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B99C21607A1; Thu, 11 Jul 2024 11:33:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720697597; cv=none; b=vEKodCAOOUWlFS5tx6m9JaiU0SHYbQ9ATruZ0HJzrRT4TrWQ4KuDewpUOwovVKQIDthnsnBL+JsH901j657hs3PMkWznZmgTTMvgvq5knqScLsnNs1Zi49HV0kxNG1q0ZtIgP2PuM2g2FskN1CsqbGu2Qt8zxkFxDzeuNlNtpm0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720697597; c=relaxed/simple; bh=USl+GS8SjbfAG9TdaFkQ19+FupY8gk0c9UWuJ1wPhLY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=g0/RIoc3uAPcZd8z67HaI7I+V4eRlEkd8Ve4Y1+yrikqxxuQpxQY77Q+Iv40+iz+DWGmheqA8hvCEyk6gxFvn9NC3D2jimBurMd5c+GyHM8bcQHlej1MqsszViSRVWBxBAVVcRpx8ubvUslFggzrSjwoSBRKnSbzn1L7fC2hzMs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.93.142]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTP id 4WKXf51cd7z4f3js4; Thu, 11 Jul 2024 19:33:01 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id DB39C1A0181; Thu, 11 Jul 2024 19:33:12 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgDXKvT0wo9mzI8hBw--.25380S6; Thu, 11 Jul 2024 19:33:12 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 17/20] selftests/bpf: Avoid load failure for token_lsm.c Date: Thu, 11 Jul 2024 19:38:25 +0800 Message-Id: <20240711113828.3818398-5-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711113828.3818398-1-xukuohai@huaweicloud.com> References: <20240711113828.3818398-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgDXKvT0wo9mzI8hBw--.25380S6 X-Coremail-Antispam: 1UD129KBjvJXoWxCw1rJr4DJry7XFy7Jr1UJrb_yoW5CF48pF 95W3429rWkJFy2kr1xXF13KryYqFs2va17JF1UCry0q3y7Kw4UXry7GFWakF95Grsayrsa vF95XFZ0qr12kaUanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBSb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E 14v26rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7 xfMcIj6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Y z7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2 Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s02 6x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42 IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF 0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87 Iv6xkF7I0E14v26F4UJVW0obIYCTnIWIevJa73UjIFyTuYvjxUFgAwUUUUU X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai The compiler optimized the two bpf progs in token_lsm.c to make return value from the bool variable in the "return -1" path, causing an unexpected rejection: 0: R1=ctx() R10=fp0 ; int BPF_PROG(bpf_token_capable, struct bpf_token *token, int cap) @ bpf_lsm.c:17 0: (b7) r6 = 0 ; R6_w=0 ; if (my_pid == 0 || my_pid != (bpf_get_current_pid_tgid() >> 32)) @ bpf_lsm.c:19 1: (18) r1 = 0xffffc9000102a000 ; R1_w=map_value(map=bpf_lsm.bss,ks=4,vs=5) 3: (61) r7 = *(u32 *)(r1 +0) ; R1_w=map_value(map=bpf_lsm.bss,ks=4,vs=5) R7_w=scalar(smin=0,smax=umax=0xffffffff,var_off=(0x0; 0xffffffff)) 4: (15) if r7 == 0x0 goto pc+11 ; R7_w=scalar(smin=umin=umin32=1,smax=umax=0xffffffff,var_off=(0x0; 0xffffffff)) 5: (67) r7 <<= 32 ; R7_w=scalar(smax=0x7fffffff00000000,umax=0xffffffff00000000,smin32=0,smax32=umax32=0,var_off=(0x0; 0xffffffff00000000)) 6: (c7) r7 s>>= 32 ; R7_w=scalar(smin=0xffffffff80000000,smax=0x7fffffff) 7: (85) call bpf_get_current_pid_tgid#14 ; R0=scalar() 8: (77) r0 >>= 32 ; R0_w=scalar(smin=0,smax=umax=0xffffffff,var_off=(0x0; 0xffffffff)) 9: (5d) if r0 != r7 goto pc+6 ; R0_w=scalar(smin=smin32=0,smax=umax=umax32=0x7fffffff,var_off=(0x0; 0x7fffffff)) R7=scalar(smin=smin32=0,smax=umax=umax32=0x7fffffff,var_off=(0x0; 0x7fffffff)) ; if (reject_capable) @ bpf_lsm.c:21 10: (18) r1 = 0xffffc9000102a004 ; R1_w=map_value(map=bpf_lsm.bss,ks=4,vs=5,off=4) 12: (71) r6 = *(u8 *)(r1 +0) ; R1_w=map_value(map=bpf_lsm.bss,ks=4,vs=5,off=4) R6_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=255,var_off=(0x0; 0xff)) ; @ bpf_lsm.c:0 13: (87) r6 = -r6 ; R6_w=scalar() 14: (67) r6 <<= 56 ; R6_w=scalar(smax=0x7f00000000000000,umax=0xff00000000000000,smin32=0,smax32=umax32=0,var_off=(0x0; 0xff00000000000000)) 15: (c7) r6 s>>= 56 ; R6_w=scalar(smin=smin32=-128,smax=smax32=127) ; int BPF_PROG(bpf_token_capable, struct bpf_token *token, int cap) @ bpf_lsm.c:17 16: (bf) r0 = r6 ; R0_w=scalar(id=1,smin=smin32=-128,smax=smax32=127) R6_w=scalar(id=1,smin=smin32=-128,smax=smax32=127) 17: (95) exit At program exit the register R0 has smin=-128 smax=127 should have been in [-4095, 0] To avoid this failure, change the variable type from bool to int. Signed-off-by: Xu Kuohai --- tools/testing/selftests/bpf/progs/token_lsm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/bpf/progs/token_lsm.c b/tools/testing/selftests/bpf/progs/token_lsm.c index e4d59b6ba743..a6002d073b1b 100644 --- a/tools/testing/selftests/bpf/progs/token_lsm.c +++ b/tools/testing/selftests/bpf/progs/token_lsm.c @@ -8,8 +8,8 @@ char _license[] SEC("license") = "GPL"; int my_pid; -bool reject_capable; -bool reject_cmd; +int reject_capable; +int reject_cmd; SEC("lsm/bpf_token_capable") int BPF_PROG(token_capable, struct bpf_token *token, int cap) From patchwork Thu Jul 11 11:38:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730582 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D5C101607AA; Thu, 11 Jul 2024 11:33:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720697597; cv=none; b=d46C0JlyjEu0cC8RnSJeraHDnTVDDmCf8iXHFQFELGvMPsvYKrRVunCh/xapwmBAj5D09+WBc+Eokx24Y2Ynhsl8LVrtW7T2R/Fx3TcAD0zGaiDZfEU14yLbW96o88cTprKkEL1wPY+LzOcxr4RP0kw6l7C6wvdNSaJKAXsLXXw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720697597; c=relaxed/simple; bh=WHsYV4fWQ1SKrc2VdfUxUlEo1NTw+En+rcCSDDxq04U=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=oQyKPWWY+I690PS+nOtWAn4lX276UFodg5ub1tbsJvXE2IFp8QP6LIVYHZh1EmQiFsuMLFKa1swnFUHhuNJ1X1nOCQ/+q+fG0LTS/A4gp/tE0Dd14x9dLFKRfzJhpNtQxIPbGkVWOjnggJ4RxkKn7e2BMABqAUb24vMN+XlAxoM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.216]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTP id 4WKXf52y2Fz4f3jsH; Thu, 11 Jul 2024 19:33:01 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 15C211A0189; Thu, 11 Jul 2024 19:33:13 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgDXKvT0wo9mzI8hBw--.25380S7; Thu, 11 Jul 2024 19:33:12 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 18/20] selftests/bpf: Add return value checks for failed tests Date: Thu, 11 Jul 2024 19:38:26 +0800 Message-Id: <20240711113828.3818398-6-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711113828.3818398-1-xukuohai@huaweicloud.com> References: <20240711113828.3818398-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgDXKvT0wo9mzI8hBw--.25380S7 X-Coremail-Antispam: 1UD129KBjvJXoWxWw1UXF4ftrW7Xr43uFy5twb_yoWrWw45pa 4kZ3s2krySgF13Xw1xAr4xXFWFgws2q3yUArWxX34xZ3W7Jr97Xr4IgF45Xrn8JrZYyws5 Zay2qrZxZr48Z3DanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBSb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E 14v26rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7 xfMcIj6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Y z7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2 Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s02 6x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42 IY6xIIjxv20xvE14v26r1I6r4UMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF 0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87 Iv6xkF7I0E14v26F4UJVW0obIYCTnIWIevJa73UjIFyTuYvjxUFgAwUUUUU X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai The return ranges of some bpf lsm test progs can not be deduced by the verifier accurately. To avoid erroneous rejections, add explicit return value checks for these progs. Signed-off-by: Xu Kuohai --- tools/testing/selftests/bpf/progs/err.h | 10 ++++++++++ tools/testing/selftests/bpf/progs/test_sig_in_xattr.c | 4 ++++ .../selftests/bpf/progs/test_verify_pkcs7_sig.c | 8 ++++++-- .../selftests/bpf/progs/verifier_global_subprogs.c | 7 ++++++- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/bpf/progs/err.h b/tools/testing/selftests/bpf/progs/err.h index d66d283d9e59..38529779a236 100644 --- a/tools/testing/selftests/bpf/progs/err.h +++ b/tools/testing/selftests/bpf/progs/err.h @@ -5,6 +5,16 @@ #define MAX_ERRNO 4095 #define IS_ERR_VALUE(x) (unsigned long)(void *)(x) >= (unsigned long)-MAX_ERRNO +#define __STR(x) #x + +#define set_if_not_errno_or_zero(x, y) \ +({ \ + asm volatile ("if %0 s< -4095 goto +1\n" \ + "if %0 s<= 0 goto +1\n" \ + "%0 = " __STR(y) "\n" \ + : "+r"(x)); \ +}) + static inline int IS_ERR_OR_NULL(const void *ptr) { return !ptr || IS_ERR_VALUE((unsigned long)ptr); diff --git a/tools/testing/selftests/bpf/progs/test_sig_in_xattr.c b/tools/testing/selftests/bpf/progs/test_sig_in_xattr.c index 2f0eb1334d65..8ef6b39335b6 100644 --- a/tools/testing/selftests/bpf/progs/test_sig_in_xattr.c +++ b/tools/testing/selftests/bpf/progs/test_sig_in_xattr.c @@ -6,6 +6,7 @@ #include #include #include "bpf_kfuncs.h" +#include "err.h" char _license[] SEC("license") = "GPL"; @@ -79,5 +80,8 @@ int BPF_PROG(test_file_open, struct file *f) ret = bpf_verify_pkcs7_signature(&digest_ptr, &sig_ptr, trusted_keyring); bpf_key_put(trusted_keyring); + + set_if_not_errno_or_zero(ret, -EFAULT); + return ret; } diff --git a/tools/testing/selftests/bpf/progs/test_verify_pkcs7_sig.c b/tools/testing/selftests/bpf/progs/test_verify_pkcs7_sig.c index f42e9f3831a1..12034a73ee2d 100644 --- a/tools/testing/selftests/bpf/progs/test_verify_pkcs7_sig.c +++ b/tools/testing/selftests/bpf/progs/test_verify_pkcs7_sig.c @@ -11,6 +11,7 @@ #include #include #include "bpf_kfuncs.h" +#include "err.h" #define MAX_DATA_SIZE (1024 * 1024) #define MAX_SIG_SIZE 1024 @@ -55,12 +56,12 @@ int BPF_PROG(bpf, int cmd, union bpf_attr *attr, unsigned int size) ret = bpf_probe_read_kernel(&value, sizeof(value), &attr->value); if (ret) - return ret; + goto out; ret = bpf_copy_from_user(data_val, sizeof(struct data), (void *)(unsigned long)value); if (ret) - return ret; + goto out; if (data_val->data_len > sizeof(data_val->data)) return -EINVAL; @@ -84,5 +85,8 @@ int BPF_PROG(bpf, int cmd, union bpf_attr *attr, unsigned int size) bpf_key_put(trusted_keyring); +out: + set_if_not_errno_or_zero(ret, -EFAULT); + return ret; } diff --git a/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c b/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c index a9fc30ed4d73..20904cd2baa2 100644 --- a/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c +++ b/tools/testing/selftests/bpf/progs/verifier_global_subprogs.c @@ -7,6 +7,7 @@ #include "bpf_misc.h" #include "xdp_metadata.h" #include "bpf_kfuncs.h" +#include "err.h" /* The compiler may be able to detect the access to uninitialized memory in the routines performing out of bound memory accesses and @@ -331,7 +332,11 @@ SEC("?lsm/bpf") __success __log_level(2) int BPF_PROG(arg_tag_ctx_lsm) { - return tracing_subprog_void(ctx) + tracing_subprog_u64(ctx); + int ret; + + ret = tracing_subprog_void(ctx) + tracing_subprog_u64(ctx); + set_if_not_errno_or_zero(ret, -1); + return ret; } SEC("?struct_ops/test_1") From patchwork Thu Jul 11 11:38:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730583 Received: from dggsgout11.his.huawei.com (dggsgout11.his.huawei.com [45.249.212.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 31EBF1607B3; Thu, 11 Jul 2024 11:33:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720697598; cv=none; b=J4jwP5HoHP2RY+fuDyeM+oH5xTUWl2Iqu84G3ldu4yLpjIcXqCZBf0s0KL1JUeYsBd0Ye+DftmjrtKZbX5385w2vBwsNpIQ675KKQ+DVquj8bQSTtCmH1ziHFcx0tbI5rwR6+dU9p6RP+f4hjkS7WMovC6IlQTpySBaDXDUh2jQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720697598; c=relaxed/simple; bh=vtjp7xT4YXwZ4iYQIFComZgrWpTRVHT6wKNCkqf+1eA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=OGE7XS6DDnuXKhzL9VoAE2uZgyHD1mcL5uWFKFQVb2sNZK+UBrki0nAeLumexUaZarXH2V700yP0/jl/F/th6izIZKU04D6vH//TdWJ7N0L+GIlmtV52OSPDQxE+rW4iViaSnLv+AQw1oEfoctf9liFCho1YyucmiEOgMMfcYQg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.216]) by dggsgout11.his.huawei.com (SkyGuard) with ESMTP id 4WKXf9408pz4f3kKD; Thu, 11 Jul 2024 19:33:05 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 3B76A1A01D2; Thu, 11 Jul 2024 19:33:13 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgDXKvT0wo9mzI8hBw--.25380S8; Thu, 11 Jul 2024 19:33:12 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 19/20] selftests/bpf: Add test for lsm tail call Date: Thu, 11 Jul 2024 19:38:27 +0800 Message-Id: <20240711113828.3818398-7-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711113828.3818398-1-xukuohai@huaweicloud.com> References: <20240711113828.3818398-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgDXKvT0wo9mzI8hBw--.25380S8 X-Coremail-Antispam: 1UD129KBjvJXoWxXrWkXw1UtF4UCr15AFy7Jrb_yoW5urW7pa 48W345KryFvFy3Xw43KF4xuF4Sya1kuryUArW7XryYvrn7Arn7GF1xKFWUtFnxJFWruwn5 Zas7trs7Cr48Z3DanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBSb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E 14v26rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7 xfMcIj6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Y z7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2 Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s02 6x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42 IY6xIIjxv20xvE14v26r1I6r4UMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF 0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87 Iv6xkF7I0E14v26F4UJVW0obIYCTnIWIevJa73UjIFyTuYvjxUFgAwUUUUU X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai Add test for lsm tail call to ensure tail call can only be used between bpf lsm progs attached to the same hook. Signed-off-by: Xu Kuohai --- .../selftests/bpf/prog_tests/test_lsm.c | 46 ++++++++++++++++++- .../selftests/bpf/progs/lsm_tailcall.c | 34 ++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/bpf/progs/lsm_tailcall.c diff --git a/tools/testing/selftests/bpf/prog_tests/test_lsm.c b/tools/testing/selftests/bpf/prog_tests/test_lsm.c index 16175d579bc7..2a27f3714f5c 100644 --- a/tools/testing/selftests/bpf/prog_tests/test_lsm.c +++ b/tools/testing/selftests/bpf/prog_tests/test_lsm.c @@ -12,6 +12,7 @@ #include #include "lsm.skel.h" +#include "lsm_tailcall.skel.h" char *CMD_ARGS[] = {"true", NULL}; @@ -95,7 +96,7 @@ static int test_lsm(struct lsm *skel) return 0; } -void test_test_lsm(void) +static void test_lsm_basic(void) { struct lsm *skel = NULL; int err; @@ -114,3 +115,46 @@ void test_test_lsm(void) close_prog: lsm__destroy(skel); } + +static void test_lsm_tailcall(void) +{ + struct lsm_tailcall *skel = NULL; + int map_fd, prog_fd; + int err, key; + + skel = lsm_tailcall__open_and_load(); + if (!ASSERT_OK_PTR(skel, "lsm_tailcall__skel_load")) + goto close_prog; + + map_fd = bpf_map__fd(skel->maps.jmp_table); + if (CHECK_FAIL(map_fd < 0)) + goto close_prog; + + prog_fd = bpf_program__fd(skel->progs.lsm_file_permission_prog); + if (CHECK_FAIL(prog_fd < 0)) + goto close_prog; + + key = 0; + err = bpf_map_update_elem(map_fd, &key, &prog_fd, BPF_ANY); + if (CHECK_FAIL(!err)) + goto close_prog; + + prog_fd = bpf_program__fd(skel->progs.lsm_file_alloc_security_prog); + if (CHECK_FAIL(prog_fd < 0)) + goto close_prog; + + err = bpf_map_update_elem(map_fd, &key, &prog_fd, BPF_ANY); + if (CHECK_FAIL(err)) + goto close_prog; + +close_prog: + lsm_tailcall__destroy(skel); +} + +void test_test_lsm(void) +{ + if (test__start_subtest("lsm_basic")) + test_lsm_basic(); + if (test__start_subtest("lsm_tailcall")) + test_lsm_tailcall(); +} diff --git a/tools/testing/selftests/bpf/progs/lsm_tailcall.c b/tools/testing/selftests/bpf/progs/lsm_tailcall.c new file mode 100644 index 000000000000..49c075ce2d4c --- /dev/null +++ b/tools/testing/selftests/bpf/progs/lsm_tailcall.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Huawei Technologies Co., Ltd */ + +#include "vmlinux.h" +#include +#include + +char _license[] SEC("license") = "GPL"; + +struct { + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); + __uint(max_entries, 1); + __uint(key_size, sizeof(__u32)); + __uint(value_size, sizeof(__u32)); +} jmp_table SEC(".maps"); + +SEC("lsm/file_permission") +int lsm_file_permission_prog(void *ctx) +{ + return 0; +} + +SEC("lsm/file_alloc_security") +int lsm_file_alloc_security_prog(void *ctx) +{ + return 0; +} + +SEC("lsm/file_alloc_security") +int lsm_file_alloc_security_entry(void *ctx) +{ + bpf_tail_call_static(ctx, &jmp_table, 0); + return 0; +} From patchwork Thu Jul 11 11:38:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xu Kuohai X-Patchwork-Id: 13730584 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B6B24167D83; Thu, 11 Jul 2024 11:33:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720697599; cv=none; b=QX/0d6rwzxK3Qa9HWOUpCjG9NHQ3yk9I2XaG8//PfZAxp64oIKbnuFbE7K0XxhoR0uhx8w0GRPUDtFq0aI/ZvEv6IvMDJt5Sc/hbyK6wAv9u6k+lhUEgUzKdTq16HkBTrftKBU9CRxRjZGotfFpj0tFiE0rN0nl0+H+q1PDnPUs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720697599; c=relaxed/simple; bh=0D4+hn+mqXg4MVrSEI33bDzLl/YLMPl+CrCDwuSiJlg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=snCey3iWj7wnYHYHy1zQMyKDPEcz75nXMstrdiH/to8zBKplECHYojovRdB7feIlBOQKLBl7oI382gIsS5fiB3uhEvJ7LRkL4exO+B8wfPUreRgWe8GbEZ9/d//7mcnopbDN8HWscMJV8WSr2DzmgtUCecbQHbtb2/7DrTQX5AE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.235]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTP id 4WKXf55G9Mz4f3jrs; Thu, 11 Jul 2024 19:33:01 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.128]) by mail.maildlp.com (Postfix) with ESMTP id 632061A0572; Thu, 11 Jul 2024 19:33:13 +0800 (CST) Received: from k01.huawei.com (unknown [10.67.174.197]) by APP4 (Coremail) with SMTP id gCh0CgDXKvT0wo9mzI8hBw--.25380S9; Thu, 11 Jul 2024 19:33:12 +0800 (CST) From: Xu Kuohai To: bpf@vger.kernel.org, netdev@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-integrity@vger.kernel.org, apparmor@lists.ubuntu.com, selinux@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Matt Bobrowski , Brendan Jackman , Paul Moore , James Morris , "Serge E . Hallyn" , Khadija Kamran , Casey Schaufler , Ondrej Mosnacek , Kees Cook , John Johansen , Lukas Bulwahn , Roberto Sassu , Shung-Hsi Yu , Edward Cree , Alexander Viro , Christian Brauner , Trond Myklebust , Anna Schumaker , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Stephen Smalley Subject: [PATCH bpf-next v4 20/20] selftests/bpf: Add verifier tests for bpf lsm Date: Thu, 11 Jul 2024 19:38:28 +0800 Message-Id: <20240711113828.3818398-8-xukuohai@huaweicloud.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240711113828.3818398-1-xukuohai@huaweicloud.com> References: <20240711113828.3818398-1-xukuohai@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: gCh0CgDXKvT0wo9mzI8hBw--.25380S9 X-Coremail-Antispam: 1UD129KBjvJXoW3WFykZw4UXFWDJr43Ww47XFb_yoW3try3pF nFk34DGF95Ar9xWFWxCFWxuF1fGFn2qF1rXa1FvF1jyFs3Jr97XFW8GF1DX34fJ3Z3uw4Y vFZIyayakr1UuaDanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBSb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E 14v26rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7 xfMcIj6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Y z7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2 Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s02 6x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42 IY6xIIjxv20xvE14v26r1I6r4UMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF 0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87 Iv6xkF7I0E14v26F4UJVW0obIYCTnIWIevJa73UjIFyTuYvjxUFgAwUUUUU X-CM-SenderInfo: 50xn30hkdlqx5xdzvxpfor3voofrz/ From: Xu Kuohai Add verifier tests to check bpf lsm return values, output parameter access and disabled hooks. Signed-off-by: Xu Kuohai --- .../selftests/bpf/prog_tests/verifier.c | 2 + .../selftests/bpf/progs/verifier_lsm.c | 274 ++++++++++++++++++ 2 files changed, 276 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/verifier_lsm.c diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c index 9dc3687bc406..ff1c7da1d06e 100644 --- a/tools/testing/selftests/bpf/prog_tests/verifier.c +++ b/tools/testing/selftests/bpf/prog_tests/verifier.c @@ -88,6 +88,7 @@ #include "verifier_xdp.skel.h" #include "verifier_xdp_direct_packet_access.skel.h" #include "verifier_bits_iter.skel.h" +#include "verifier_lsm.skel.h" #define MAX_ENTRIES 11 @@ -206,6 +207,7 @@ void test_verifier_xadd(void) { RUN(verifier_xadd); } void test_verifier_xdp(void) { RUN(verifier_xdp); } void test_verifier_xdp_direct_packet_access(void) { RUN(verifier_xdp_direct_packet_access); } void test_verifier_bits_iter(void) { RUN(verifier_bits_iter); } +void test_verifier_lsm(void) { RUN(verifier_lsm); } static int init_test_val_map(struct bpf_object *obj, char *map_name) { diff --git a/tools/testing/selftests/bpf/progs/verifier_lsm.c b/tools/testing/selftests/bpf/progs/verifier_lsm.c new file mode 100644 index 000000000000..fcc74efe46c6 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/verifier_lsm.c @@ -0,0 +1,274 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include "bpf_misc.h" + +SEC("lsm/file_alloc_security") +__description("lsm bpf prog with -4095~0 retval. test 1") +__success +__naked int errno_zero_retval_test1(void *ctx) +{ + asm volatile ( + "r0 = 0;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/file_alloc_security") +__description("lsm bpf prog with -4095~0 retval. test 2") +__success +__naked int errno_zero_retval_test2(void *ctx) +{ + asm volatile ( + "r0 = -4095;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/file_alloc_security") +__description("lsm bpf prog with -4095~0 retval. test 3") +__success +__naked int errno_zero_retval_test3(void *ctx) +{ + asm volatile ( + "call %[bpf_get_prandom_u32];" + "r0 <<= 63;" + "r0 s>>= 63;" + "r0 &= -13;" + "exit;" + : + : __imm(bpf_get_prandom_u32) + : __clobber_all); +} + +SEC("lsm/file_mprotect") +__description("lsm bpf prog with -4095~0 retval. test 4") +__failure __msg("R0 has smin=-4096 smax=-4096 should have been in [-4095, 0]") +__naked int errno_zero_retval_test4(void *ctx) +{ + asm volatile ( + "r0 = -4096;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/file_mprotect") +__description("lsm bpf prog with -4095~0 retval. test 5") +__failure __msg("R0 has smin=4096 smax=4096 should have been in [-4095, 0]") +__naked int errno_zero_retval_test5(void *ctx) +{ + asm volatile ( + "r0 = 4096;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/vm_enough_memory") +__description("lsm bpf prog with -4095~0 retval. test 6") +__failure __msg("R0 has smin=1 smax=1 should have been in [-4095, 0]") +__naked int errno_zero_retval_test6(void *ctx) +{ + asm volatile ( + "r0 = 1;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/audit_rule_known") +__description("lsm bpf prog with bool retval. test 1") +__success +__naked int bool_retval_test1(void *ctx) +{ + asm volatile ( + "r0 = 1;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/audit_rule_known") +__description("lsm bpf prog with bool retval. test 2") +__success +__success +__naked int bool_retval_test2(void *ctx) +{ + asm volatile ( + "r0 = 0;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/audit_rule_known") +__description("lsm bpf prog with bool retval. test 3") +__failure __msg("R0 has smin=-1 smax=-1 should have been in [0, 1]") +__naked int bool_retval_test3(void *ctx) +{ + asm volatile ( + "r0 = -1;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/audit_rule_known") +__description("lsm bpf prog with bool retval. test 4") +__failure __msg("R0 has smin=2 smax=2 should have been in [0, 1]") +__naked int bool_retval_test4(void *ctx) +{ + asm volatile ( + "r0 = 2;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/file_free_security") +__success +__description("lsm bpf prog with void retval. test 1") +__naked int void_retval_test1(void *ctx) +{ + asm volatile ( + "r0 = -4096;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/file_free_security") +__success +__description("lsm bpf prog with void retval. test 2") +__naked int void_retval_test2(void *ctx) +{ + asm volatile ( + "r0 = 4096;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/audit_rule_match") +__description("lsm bpf prog read write valid output parameter success") +__success +__naked int outparam_valid_test(void *ctx) +{ + asm volatile ( + "r1 = *(u64 *)(r1 + 0x20);" + "r2 = *(u8 *)(r1 + 0x0);" + "r2 &= 0x1;" + "*(u8 *)(r1 + 0x0) = r2;" + "r0 = 0;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/audit_rule_match") +__description("lsm bpf prog read write output parameter, invalid read offset") +__failure __msg("invalid read offset: 1 (expected 0, type=_Bool)") +__naked int outparam_invalid_read_offset(void *ctx) +{ + asm volatile ( + "r1 = *(u64 *)(r1 + 0x20);" + "r2 = *(u8 *)(r1 + 0x1);" + "r2 &= 0x1;" + "*(u8 *)(r1 + 0x0) = r2;" + "r0 = 0;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/audit_rule_match") +__description("lsm bpf prog read write invalid output parameter, invalid read size") +__failure __msg("invalid read size: 2 (expected 1, type=_Bool)") +__naked int outparam_invalid_read_size(void *ctx) +{ + asm volatile ( + "r1 = *(u64 *)(r1 + 0x20);" + "r2 = *(u16 *)(r1 + 0x0);" + "r2 &= 0x1;" + "*(u8 *)(r1 + 0x0) = r2;" + "r0 = 0;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/audit_rule_match") +__description("lsm bpf prog read write invalid output parameter, invalid write offset") +__failure __msg("invalid write offset: 1 (expected 0, type=_Bool)") +__naked int outparam_invalid_write_offset(void *ctx) +{ + asm volatile ( + "r1 = *(u64 *)(r1 + 0x20);" + "r2 = *(u8 *)(r1 + 0x0);" + "r2 &= 0x1;" + "*(u8 *)(r1 + 0x1) = r2;" + "r0 = 0;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/audit_rule_match") +__description("lsm bpf prog read write invalid output parameter, invalid write size") +__failure __msg("invalid write size: 2 (expected 1, type=_Bool)") +__naked int outparam_invalid_write_size(void *ctx) +{ + asm volatile ( + "r1 = *(u64 *)(r1 + 0x20);" + "r2 = *(u8 *)(r1 + 0x0);" + "r2 &= 0x1;" + "*(u16 *)(r1 + 0x0) = r2;" + "r0 = 0;" + "exit;" + ::: __clobber_all); +} + +/* hook prototype: + * int bpf_lsm_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) + * + * although the last param is a pointer to u32, it iss not the output param for + * return value. + */ +SEC("lsm/secctx_to_secid") +__description("lsm bpf prog read write invalid output parameter, not output param hook") +__failure __msg("invalid mem access 'scalar'") +__naked int outparam_invalid_hook(void *ctx) +{ + asm volatile ( + "r1 = *(u64 *)(r1 + 0x10);" + "r2 = *(u32 *)(r1 + 0x0);" + "r2 &= 0x1;" + "*(u32 *)(r1 + 0x0) = r2;" + "r0 = 0;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/getprocattr") +__description("lsm disabled hook: getprocattr") +__failure __msg("points to disabled hook") +__naked int disabled_hook_test1(void *ctx) +{ + asm volatile ( + "r0 = 0;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/setprocattr") +__description("lsm disabled hook: setprocattr") +__failure __msg("points to disabled hook") +__naked int disabled_hook_test2(void *ctx) +{ + asm volatile ( + "r0 = 0;" + "exit;" + ::: __clobber_all); +} + +SEC("lsm/ismaclabel") +__description("lsm disabled hook: ismaclabel") +__failure __msg("points to disabled hook") +__naked int disabled_hook_test3(void *ctx) +{ + asm volatile ( + "r0 = 0;" + "exit;" + ::: __clobber_all); +} + +char _license[] SEC("license") = "GPL";