From patchwork Wed Dec 7 17:24:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13067434 X-Patchwork-Delegate: paul@paul-moore.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A928AC4708E for ; Wed, 7 Dec 2022 17:25:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229782AbiLGRZd (ORCPT ); Wed, 7 Dec 2022 12:25:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33244 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229793AbiLGRZ3 (ORCPT ); Wed, 7 Dec 2022 12:25:29 -0500 Received: from frasgout12.his.huawei.com (frasgout12.his.huawei.com [14.137.139.154]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5D14B62EA3; Wed, 7 Dec 2022 09:25:27 -0800 (PST) Received: from mail02.huawei.com (unknown [172.18.147.227]) by frasgout12.his.huawei.com (SkyGuard) with ESMTP id 4NS3sZ72yPz9xFrq; Thu, 8 Dec 2022 01:18:42 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwD34m9YzJBjc9DJAA--.62662S3; Wed, 07 Dec 2022 18:25:03 +0100 (CET) From: Roberto Sassu To: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, song@kernel.org, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com, haoluo@google.com, jolsa@kernel.org, revest@chromium.org, jackmanb@chromium.org, mykolal@fb.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, shuah@kernel.org Cc: bpf@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Roberto Sassu Subject: [RFC][PATCH v2 1/7] bpf: Remove superfluous btf_id_set_contains() declaration Date: Wed, 7 Dec 2022 18:24:28 +0100 Message-Id: <20221207172434.435893-2-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221207172434.435893-1-roberto.sassu@huaweicloud.com> References: <20221207172434.435893-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwD34m9YzJBjc9DJAA--.62662S3 X-Coremail-Antispam: 1UD129KBjvdXoW7Xw17Wr1kJw17AF18ZF4ruFg_yoWfArg_A3 4xJry7Cr45WryfXw18KFWftFyfKw1xJr1kX3WFqr13GFsxCws8Gwn7AF9xXrW7Gwn7Cws7 XF1ku3yrXr17WjkaLaAFLSUrUUUUjb8apTn2vfkv8UJUUUU8Yxn0WfASr-VFAUDa7-sFnT 9fnUUIcSsGvfJTRUUUbg8YFVCjjxCrM7AC8VAFwI0_Wr0E3s1l1xkIjI8I6I8E6xAIw20E Y4v20xvaj40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l82xGYIkIc2x26280x7IE14v26r18M2 8IrcIa0xkI8VCY1x0267AKxVW5JVCq3wA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK 021l84ACjcxK6xIIjxv20xvE14v26r1I6r4UM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26r 4UJVWxJr1l84ACjcxK6I8E87Iv67AKxVW8JVWxJwA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_ Gr1j6F4UJwAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ew Av7VC0I7IYx2IY67AKxVWUGVWUXwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY 6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxkF7I0En4kS14 v26r4a6rW5MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8C rVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVW8ZVWrXw CIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1I6r4UMIIF0xvE2Ix0cI8IcVCY1x02 67AKxVW8Jr0_Cr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxV W8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26r4UJVWxJrUvcSsGvfC2KfnxnUUI43ZEXa7I U0U8n5UUUUU== X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgATBF1jj4JqngABsT X-CFilter-Loop: Reflected Precedence: bulk List-ID: From: Roberto Sassu Commit 8ffa5cc142137 ("bpf: Recognize lock and list fields in allocated objects") moved btf_id_set_contains() and btf_id8_set_contains() implementations from kernel/bpf/verifier.c to include/linux/btf.h. Thus, remove the declaration in include/linux/bpf.h. Signed-off-by: Roberto Sassu --- include/linux/bpf.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 4920ac252754..681614f1fa8c 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -2792,7 +2792,6 @@ void *bpf_arch_text_copy(void *dst, void *src, size_t len); int bpf_arch_text_invalidate(void *dst, size_t len); struct btf_id_set; -bool btf_id_set_contains(const struct btf_id_set *set, u32 id); #define MAX_BPRINTF_VARARGS 12 From patchwork Wed Dec 7 17:24:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13067435 X-Patchwork-Delegate: paul@paul-moore.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E7895C47089 for ; Wed, 7 Dec 2022 17:25:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229770AbiLGRZp (ORCPT ); Wed, 7 Dec 2022 12:25:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33360 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229793AbiLGRZh (ORCPT ); Wed, 7 Dec 2022 12:25:37 -0500 Received: from frasgout11.his.huawei.com (frasgout11.his.huawei.com [14.137.139.23]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BD28C5AE36; Wed, 7 Dec 2022 09:25:36 -0800 (PST) Received: from mail02.huawei.com (unknown [172.18.147.227]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4NS3sG3fLCz9xHw7; Thu, 8 Dec 2022 01:18:26 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwD34m9YzJBjc9DJAA--.62662S4; Wed, 07 Dec 2022 18:25:13 +0100 (CET) From: Roberto Sassu To: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, song@kernel.org, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com, haoluo@google.com, jolsa@kernel.org, revest@chromium.org, jackmanb@chromium.org, mykolal@fb.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, shuah@kernel.org Cc: bpf@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Roberto Sassu Subject: [RFC][PATCH v2 2/7] bpf: Mark ALU32 operations in bpf_reg_state structure Date: Wed, 7 Dec 2022 18:24:29 +0100 Message-Id: <20221207172434.435893-3-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221207172434.435893-1-roberto.sassu@huaweicloud.com> References: <20221207172434.435893-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwD34m9YzJBjc9DJAA--.62662S4 X-Coremail-Antispam: 1UD129KBjvJXoWxAF1UAr1UKry7Wr1UAF48tFb_yoW5tFW5pF s5GrsxGr4kZF4xuasrZa15AF9YkF10v3WUuFWUA347Ar13Wry5Xr4DKFyjyas0yrW0vw4S y3Wq9rW2qw1UZaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPqb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUXw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV W8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6r4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2 WlYx0E2Ix0cI8IcVAFwI0_JrI_JrylYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkE bVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262kKe7 AKxVW8ZVWrXwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02 F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GFv_Wr ylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVW8JVW5JwCI42IY6xIIjxv20xvEc7Cj xVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI 0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZFpf9x 07j7hLnUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgATBF1jj4JqngACsQ X-CFilter-Loop: Reflected Precedence: bulk List-ID: From: Roberto Sassu BPF LSM needs a reliable source of information to determine if the return value given by eBPF programs is acceptable or not. At the moment, choosing either the 64 bit or the 32 bit one does not seem to be an option (selftests fail). If we choose the 64 bit one, the following happens. 14: 61 10 00 00 00 00 00 00 r0 = *(u32 *)(r1 + 0) 15: 74 00 00 00 15 00 00 00 w0 >>= 21 16: 54 00 00 00 01 00 00 00 w0 &= 1 17: 04 00 00 00 ff ff ff ff w0 += -1 This is the last part of test_deny_namespace. After #16, the register values are: smin_value = 0x0, smax_value = 0x1, s32_min_value = 0x0, s32_max_value = 0x1, After #17, they become: smin_value = 0x0, smax_value = 0xffffffff, s32_min_value = 0xffffffff, s32_max_value = 0x0 where only the 32 bit values are correct. If we choose the 32 bit ones, the following happens. 0000000000000000 : 0: 79 12 00 00 00 00 00 00 r2 = *(u64 *)(r1 + 0) 1: 79 10 08 00 00 00 00 00 r0 = *(u64 *)(r1 + 8) 2: 67 00 00 00 3e 00 00 00 r0 <<= 62 3: c7 00 00 00 3f 00 00 00 r0 s>>= 63 This is part of test_libbpf_get_fd_by_id_opts (no_alu32 version). In this case, 64 bit register values should be used (for the 32 bit ones, there is no precise information from the verifier). As the examples above suggest that which register values to use depends on the specific case, mark ALU32 operations in bpf_reg_state structure, so that BPF LSM can choose the proper ones. Signed-off-by: Roberto Sassu --- include/linux/bpf_verifier.h | 1 + kernel/bpf/verifier.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h index 70d06a99f0b8..29c9cf6b0d01 100644 --- a/include/linux/bpf_verifier.h +++ b/include/linux/bpf_verifier.h @@ -181,6 +181,7 @@ struct bpf_reg_state { enum bpf_reg_liveness live; /* if (!precise && SCALAR_VALUE) min/max/tnum don't affect safety */ bool precise; + bool alu32; }; enum bpf_stack_slot_type { diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 8c5f0adbbde3..edce85c425a2 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -10524,9 +10524,13 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env, break; } + dst_reg->alu32 = false; + /* ALU32 ops are zero extended into 64bit register */ - if (alu32) + if (alu32) { zext_32_to_64(dst_reg); + dst_reg->alu32 = true; + } reg_bounds_sync(dst_reg); return 0; } @@ -10700,6 +10704,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn) *dst_reg = *src_reg; dst_reg->live |= REG_LIVE_WRITTEN; dst_reg->subreg_def = DEF_NOT_SUBREG; + dst_reg->alu32 = false; } else { /* R1 = (u32) R2 */ if (is_pointer_value(env, insn->src_reg)) { @@ -10716,6 +10721,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn) dst_reg->id = 0; dst_reg->live |= REG_LIVE_WRITTEN; dst_reg->subreg_def = env->insn_idx + 1; + dst_reg->alu32 = true; } else { mark_reg_unknown(env, regs, insn->dst_reg); @@ -10733,9 +10739,11 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn) if (BPF_CLASS(insn->code) == BPF_ALU64) { __mark_reg_known(regs + insn->dst_reg, insn->imm); + regs[insn->dst_reg].alu32 = false; } else { __mark_reg_known(regs + insn->dst_reg, (u32)insn->imm); + regs[insn->dst_reg].alu32 = true; } } From patchwork Wed Dec 7 17:24:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13067436 X-Patchwork-Delegate: paul@paul-moore.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2FB9BC47089 for ; Wed, 7 Dec 2022 17:26:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229844AbiLGRZ7 (ORCPT ); Wed, 7 Dec 2022 12:25:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33334 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229811AbiLGRZw (ORCPT ); Wed, 7 Dec 2022 12:25:52 -0500 Received: from frasgout12.his.huawei.com (frasgout12.his.huawei.com [14.137.139.154]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0085169A95; Wed, 7 Dec 2022 09:25:48 -0800 (PST) Received: from mail02.huawei.com (unknown [172.18.147.229]) by frasgout12.his.huawei.com (SkyGuard) with ESMTP id 4NS3t01X4lz9v7Y8; Thu, 8 Dec 2022 01:19:04 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwD34m9YzJBjc9DJAA--.62662S5; Wed, 07 Dec 2022 18:25:24 +0100 (CET) From: Roberto Sassu To: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, song@kernel.org, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com, haoluo@google.com, jolsa@kernel.org, revest@chromium.org, jackmanb@chromium.org, mykolal@fb.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, shuah@kernel.org Cc: bpf@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Roberto Sassu Subject: [RFC][PATCH v2 3/7] lsm: Redefine LSM_HOOK() macro to add return value flags as argument Date: Wed, 7 Dec 2022 18:24:30 +0100 Message-Id: <20221207172434.435893-4-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221207172434.435893-1-roberto.sassu@huaweicloud.com> References: <20221207172434.435893-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwD34m9YzJBjc9DJAA--.62662S5 X-Coremail-Antispam: 1UD129KBjvAXoWfKrW7tr45uryUJw48uFyxuFg_yoW7CF13Ko W2gasrZw4rKw1kAayrKr4fJFZ2v34UZr48tr1DW34DXFs2kw1DCws3tr1UJF47XF4rG398 AFy7J3s5CF4DX3Z8n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUO57kC6x804xWl14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK 8VAvwI8IcIk0rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_Jr Wl82xGYIkIc2x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Gr0_Xr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIE14v26r4j6F4UM28EF7xvwVC2z280aVCY1x0267AK xVW8Jr0_Cr1UM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7 xfMcIj6xIIjxv20xvE14v26r106r15McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Y z7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1lc7CjxVAaw2 AFwI0_GFv_Wryl42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAq x4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r4a6r W5MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF 7I0E14v26r4UJVWxJr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14 v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuY vjxU4R6zUUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQATBF1jj4ZoqwAAsi X-CFilter-Loop: Reflected Precedence: bulk List-ID: From: Roberto Sassu Define four return value flags (LSM_RET_NEG, LSM_RET_ZERO, LSM_RET_ONE, LSM_RET_GT_ONE), one for each interval of interest (<0, 0, 1, >1). Redefine the LSM_HOOK() macro to add return value flags as argument, and set the correct flags for each LSM hook. Implementors of new LSM hooks should do the same as well. Signed-off-by: Roberto Sassu --- include/linux/bpf_lsm.h | 2 +- include/linux/lsm_hook_defs.h | 780 ++++++++++++++++++++-------------- include/linux/lsm_hooks.h | 9 +- kernel/bpf/bpf_lsm.c | 5 +- security/bpf/hooks.c | 2 +- security/security.c | 4 +- 6 files changed, 466 insertions(+), 336 deletions(-) diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h index 1de7ece5d36d..2f5757085dfd 100644 --- a/include/linux/bpf_lsm.h +++ b/include/linux/bpf_lsm.h @@ -13,7 +13,7 @@ #ifdef CONFIG_BPF_LSM -#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ +#define LSM_HOOK(RET, DEFAULT, RET_FLAGS, NAME, ...) \ RET bpf_lsm_##NAME(__VA_ARGS__); #include #undef LSM_HOOK diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 6abde829b6e5..0b1442b26627 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -18,395 +18,519 @@ * The macro LSM_HOOK is used to define the data structures required by * the LSM framework using the pattern: * - * LSM_HOOK(, , , args...) + * LSM_HOOK(, , , , args...) * * struct security_hook_heads { - * #define LSM_HOOK(RET, DEFAULT, NAME, ...) struct hlist_head NAME; + * #define LSM_HOOK(RET, DEFAULT, RET_FLAGS, NAME, ...) struct hlist_head NAME; * #include * #undef LSM_HOOK * }; */ -LSM_HOOK(int, 0, binder_set_context_mgr, const struct cred *mgr) -LSM_HOOK(int, 0, binder_transaction, const struct cred *from, - const struct cred *to) -LSM_HOOK(int, 0, binder_transfer_binder, const struct cred *from, - const struct cred *to) -LSM_HOOK(int, 0, binder_transfer_file, const struct cred *from, - const struct cred *to, struct file *file) -LSM_HOOK(int, 0, ptrace_access_check, struct task_struct *child, - unsigned int mode) -LSM_HOOK(int, 0, ptrace_traceme, struct task_struct *parent) -LSM_HOOK(int, 0, capget, struct task_struct *target, kernel_cap_t *effective, - kernel_cap_t *inheritable, kernel_cap_t *permitted) -LSM_HOOK(int, 0, capset, struct cred *new, const struct cred *old, - const kernel_cap_t *effective, const kernel_cap_t *inheritable, - const kernel_cap_t *permitted) -LSM_HOOK(int, 0, capable, const struct cred *cred, struct user_namespace *ns, - int cap, unsigned int opts) -LSM_HOOK(int, 0, quotactl, int cmds, int type, int id, struct super_block *sb) -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, 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, struct file *file) -LSM_HOOK(int, 0, bprm_check_security, struct linux_binprm *bprm) -LSM_HOOK(void, LSM_RET_VOID, bprm_committing_creds, struct linux_binprm *bprm) -LSM_HOOK(void, LSM_RET_VOID, bprm_committed_creds, struct linux_binprm *bprm) -LSM_HOOK(int, 0, fs_context_dup, struct fs_context *fc, - struct fs_context *src_sc) -LSM_HOOK(int, -ENOPARAM, fs_context_parse_param, struct fs_context *fc, - struct fs_parameter *param) -LSM_HOOK(int, 0, sb_alloc_security, struct super_block *sb) -LSM_HOOK(void, LSM_RET_VOID, sb_delete, struct super_block *sb) -LSM_HOOK(void, LSM_RET_VOID, sb_free_security, struct super_block *sb) -LSM_HOOK(void, LSM_RET_VOID, sb_free_mnt_opts, void *mnt_opts) -LSM_HOOK(int, 0, sb_eat_lsm_opts, char *orig, void **mnt_opts) -LSM_HOOK(int, 0, sb_mnt_opts_compat, struct super_block *sb, void *mnt_opts) -LSM_HOOK(int, 0, sb_remount, struct super_block *sb, void *mnt_opts) -LSM_HOOK(int, 0, sb_kern_mount, struct super_block *sb) -LSM_HOOK(int, 0, sb_show_options, struct seq_file *m, struct super_block *sb) -LSM_HOOK(int, 0, sb_statfs, struct dentry *dentry) -LSM_HOOK(int, 0, sb_mount, const char *dev_name, const struct path *path, - const char *type, unsigned long flags, void *data) -LSM_HOOK(int, 0, sb_umount, struct vfsmount *mnt, int flags) -LSM_HOOK(int, 0, sb_pivotroot, const struct path *old_path, - const struct path *new_path) -LSM_HOOK(int, 0, sb_set_mnt_opts, struct super_block *sb, void *mnt_opts, - unsigned long kern_flags, unsigned long *set_kern_flags) -LSM_HOOK(int, 0, sb_clone_mnt_opts, const struct super_block *oldsb, - struct super_block *newsb, unsigned long kern_flags, + +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, binder_set_context_mgr, + const struct cred *mgr) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, binder_transaction, + const struct cred *from, const struct cred *to) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, binder_transfer_binder, + const struct cred *from, const struct cred *to) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, binder_transfer_file, + const struct cred *from, const struct cred *to, struct file *file) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, ptrace_access_check, + struct task_struct *child, unsigned int mode) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, ptrace_traceme, + struct task_struct *parent) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, capget, struct task_struct *target, + kernel_cap_t *effective, kernel_cap_t *inheritable, + kernel_cap_t *permitted) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, capset, struct cred *new, + const struct cred *old, const kernel_cap_t *effective, + const kernel_cap_t *inheritable, const kernel_cap_t *permitted) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, capable, const struct cred *cred, + struct user_namespace *ns, int cap, unsigned int opts) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, quotactl, int cmds, int type, + int id, struct super_block *sb) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, quota_on, struct dentry *dentry) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, syslog, int type) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, settime, + const struct timespec64 *ts, const struct timezone *tz) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO | LSM_RET_ONE | LSM_RET_GT_ONE, + vm_enough_memory, struct mm_struct *mm, long pages) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, bprm_creds_for_exec, + struct linux_binprm *bprm) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, bprm_creds_from_file, + struct linux_binprm *bprm, struct file *file) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, bprm_check_security, + struct linux_binprm *bprm) +LSM_HOOK(void, LSM_RET_VOID, 0, bprm_committing_creds, struct linux_binprm *bprm) +LSM_HOOK(void, LSM_RET_VOID, 0, bprm_committed_creds, struct linux_binprm *bprm) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, fs_context_dup, + struct fs_context *fc, struct fs_context *src_sc) +LSM_HOOK(int, -ENOPARAM, LSM_RET_NEG | LSM_RET_ZERO, fs_context_parse_param, + struct fs_context *fc, struct fs_parameter *param) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sb_alloc_security, + struct super_block *sb) +LSM_HOOK(void, LSM_RET_VOID, 0, sb_delete, struct super_block *sb) +LSM_HOOK(void, LSM_RET_VOID, 0, sb_free_security, struct super_block *sb) +LSM_HOOK(void, LSM_RET_VOID, 0, sb_free_mnt_opts, void *mnt_opts) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sb_eat_lsm_opts, char *orig, + void **mnt_opts) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sb_mnt_opts_compat, + struct super_block *sb, void *mnt_opts) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sb_remount, struct super_block *sb, + void *mnt_opts) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sb_kern_mount, + struct super_block *sb) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sb_show_options, + struct seq_file *m, struct super_block *sb) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sb_statfs, struct dentry *dentry) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sb_mount, const char *dev_name, + const struct path *path, const char *type, unsigned long flags, + void *data) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sb_umount, struct vfsmount *mnt, + int flags) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sb_pivotroot, + const struct path *old_path, const struct path *new_path) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sb_set_mnt_opts, + struct super_block *sb, void *mnt_opts, unsigned long kern_flags, unsigned long *set_kern_flags) -LSM_HOOK(int, 0, move_mount, const struct path *from_path, - const struct path *to_path) -LSM_HOOK(int, -EOPNOTSUPP, dentry_init_security, struct dentry *dentry, - int mode, const struct qstr *name, const char **xattr_name, - void **ctx, u32 *ctxlen) -LSM_HOOK(int, 0, dentry_create_files_as, struct dentry *dentry, int mode, - struct qstr *name, const struct cred *old, struct cred *new) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sb_clone_mnt_opts, + const struct super_block *oldsb, struct super_block *newsb, + unsigned long kern_flags, unsigned long *set_kern_flags) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, move_mount, + const struct path *from_path, const struct path *to_path) +LSM_HOOK(int, -EOPNOTSUPP, LSM_RET_NEG | LSM_RET_ZERO, dentry_init_security, + struct dentry *dentry, int mode, const struct qstr *name, + const char **xattr_name, void **ctx, u32 *ctxlen) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, dentry_create_files_as, + struct dentry *dentry, int mode, struct qstr *name, + const struct cred *old, struct cred *new) #ifdef CONFIG_SECURITY_PATH -LSM_HOOK(int, 0, path_unlink, const struct path *dir, struct dentry *dentry) -LSM_HOOK(int, 0, path_mkdir, const struct path *dir, struct dentry *dentry, - umode_t mode) -LSM_HOOK(int, 0, path_rmdir, const struct path *dir, struct dentry *dentry) -LSM_HOOK(int, 0, path_mknod, const struct path *dir, struct dentry *dentry, - umode_t mode, unsigned int dev) -LSM_HOOK(int, 0, path_truncate, const struct path *path) -LSM_HOOK(int, 0, path_symlink, const struct path *dir, struct dentry *dentry, - const char *old_name) -LSM_HOOK(int, 0, path_link, struct dentry *old_dentry, - const struct path *new_dir, struct dentry *new_dentry) -LSM_HOOK(int, 0, path_rename, const struct path *old_dir, +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, path_unlink, + const struct path *dir, struct dentry *dentry) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, path_mkdir, const struct path *dir, + struct dentry *dentry, umode_t mode) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, path_rmdir, const struct path *dir, + struct dentry *dentry) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, path_mknod, const struct path *dir, + struct dentry *dentry, umode_t mode, unsigned int dev) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, path_truncate, + const struct path *path) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, path_symlink, + const struct path *dir, struct dentry *dentry, const char *old_name) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, path_link, struct dentry *old_dentry, const struct path *new_dir, - struct dentry *new_dentry, unsigned int flags) -LSM_HOOK(int, 0, path_chmod, const struct path *path, umode_t mode) -LSM_HOOK(int, 0, path_chown, const struct path *path, kuid_t uid, kgid_t gid) -LSM_HOOK(int, 0, path_chroot, const struct path *path) + struct dentry *new_dentry) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, path_rename, + const struct path *old_dir, struct dentry *old_dentry, + const struct path *new_dir, struct dentry *new_dentry, + unsigned int flags) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, path_chmod, + const struct path *path, umode_t mode) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, path_chown, + const struct path *path, kuid_t uid, kgid_t gid) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, path_chroot, + const struct path *path) #endif /* CONFIG_SECURITY_PATH */ /* Needed for inode based security check */ -LSM_HOOK(int, 0, path_notify, const struct path *path, u64 mask, - unsigned int obj_type) -LSM_HOOK(int, 0, inode_alloc_security, struct inode *inode) -LSM_HOOK(void, LSM_RET_VOID, inode_free_security, struct inode *inode) -LSM_HOOK(int, 0, inode_init_security, struct inode *inode, - struct inode *dir, const struct qstr *qstr, const char **name, - void **value, size_t *len) -LSM_HOOK(int, 0, inode_init_security_anon, struct inode *inode, - const struct qstr *name, const struct inode *context_inode) -LSM_HOOK(int, 0, inode_create, struct inode *dir, struct dentry *dentry, - umode_t mode) -LSM_HOOK(int, 0, inode_link, struct dentry *old_dentry, struct inode *dir, +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, path_notify, + const struct path *path, u64 mask, unsigned int obj_type) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_alloc_security, + struct inode *inode) +LSM_HOOK(void, LSM_RET_VOID, 0, inode_free_security, struct inode *inode) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_init_security, + struct inode *inode, struct inode *dir, const struct qstr *qstr, + const char **name, void **value, size_t *len) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_init_security_anon, + struct inode *inode, const struct qstr *name, + const struct inode *context_inode) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_create, struct inode *dir, + struct dentry *dentry, umode_t mode) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_link, + struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) -LSM_HOOK(int, 0, inode_unlink, struct inode *dir, struct dentry *dentry) -LSM_HOOK(int, 0, inode_symlink, struct inode *dir, struct dentry *dentry, - const char *old_name) -LSM_HOOK(int, 0, inode_mkdir, struct inode *dir, struct dentry *dentry, - umode_t mode) -LSM_HOOK(int, 0, inode_rmdir, struct inode *dir, struct dentry *dentry) -LSM_HOOK(int, 0, inode_mknod, struct inode *dir, struct dentry *dentry, - umode_t mode, dev_t dev) -LSM_HOOK(int, 0, inode_rename, struct inode *old_dir, struct dentry *old_dentry, +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_unlink, struct inode *dir, + struct dentry *dentry) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_symlink, struct inode *dir, + struct dentry *dentry, const char *old_name) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_mkdir, struct inode *dir, + struct dentry *dentry, umode_t mode) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_rmdir, struct inode *dir, + struct dentry *dentry) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_mknod, struct inode *dir, + struct dentry *dentry, umode_t mode, dev_t dev) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_rename, + struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) -LSM_HOOK(int, 0, inode_readlink, struct dentry *dentry) -LSM_HOOK(int, 0, inode_follow_link, struct dentry *dentry, struct inode *inode, - bool rcu) -LSM_HOOK(int, 0, inode_permission, struct inode *inode, int mask) -LSM_HOOK(int, 0, inode_setattr, struct dentry *dentry, struct iattr *attr) -LSM_HOOK(int, 0, inode_getattr, const struct path *path) -LSM_HOOK(int, 0, inode_setxattr, struct user_namespace *mnt_userns, - struct dentry *dentry, const char *name, const void *value, - size_t size, int flags) -LSM_HOOK(void, LSM_RET_VOID, inode_post_setxattr, struct dentry *dentry, +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_readlink, + struct dentry *dentry) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_follow_link, + struct dentry *dentry, struct inode *inode, bool rcu) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_permission, + struct inode *inode, int mask) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_setattr, + struct dentry *dentry, struct iattr *attr) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_getattr, + const struct path *path) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_setxattr, + struct user_namespace *mnt_userns, struct dentry *dentry, + const char *name, const void *value, size_t size, int flags) +LSM_HOOK(void, LSM_RET_VOID, 0, inode_post_setxattr, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) -LSM_HOOK(int, 0, inode_getxattr, struct dentry *dentry, const char *name) -LSM_HOOK(int, 0, inode_listxattr, struct dentry *dentry) -LSM_HOOK(int, 0, inode_removexattr, struct user_namespace *mnt_userns, +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_getxattr, struct dentry *dentry, const char *name) -LSM_HOOK(int, 0, inode_need_killpriv, struct dentry *dentry) -LSM_HOOK(int, 0, inode_killpriv, struct user_namespace *mnt_userns, +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_listxattr, struct dentry *dentry) -LSM_HOOK(int, -EOPNOTSUPP, inode_getsecurity, struct user_namespace *mnt_userns, +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_removexattr, + struct user_namespace *mnt_userns, struct dentry *dentry, + const char *name) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO | LSM_RET_ONE | LSM_RET_GT_ONE, + inode_need_killpriv, struct dentry *dentry) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_killpriv, + struct user_namespace *mnt_userns, struct dentry *dentry) +LSM_HOOK(int, -EOPNOTSUPP, + LSM_RET_NEG | LSM_RET_ZERO | LSM_RET_ONE | LSM_RET_GT_ONE, + inode_getsecurity, struct user_namespace *mnt_userns, struct inode *inode, const char *name, void **buffer, bool alloc) -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, +LSM_HOOK(int, -EOPNOTSUPP, LSM_RET_NEG | LSM_RET_ZERO, inode_setsecurity, + struct inode *inode, const char *name, const void *value, size_t size, + int flags) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO | LSM_RET_ONE | LSM_RET_GT_ONE, + inode_listsecurity, struct inode *inode, char *buffer, size_t buffer_size) -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, const char *name) -LSM_HOOK(int, 0, kernfs_init_security, struct kernfs_node *kn_dir, - struct kernfs_node *kn) -LSM_HOOK(int, 0, file_permission, struct file *file, int mask) -LSM_HOOK(int, 0, file_alloc_security, struct file *file) -LSM_HOOK(void, LSM_RET_VOID, file_free_security, struct file *file) -LSM_HOOK(int, 0, file_ioctl, struct file *file, unsigned int cmd, - unsigned long arg) -LSM_HOOK(int, 0, mmap_addr, unsigned long addr) -LSM_HOOK(int, 0, mmap_file, struct file *file, unsigned long reqprot, - unsigned long prot, unsigned long flags) -LSM_HOOK(int, 0, file_mprotect, struct vm_area_struct *vma, - unsigned long reqprot, unsigned long prot) -LSM_HOOK(int, 0, file_lock, struct file *file, unsigned int cmd) -LSM_HOOK(int, 0, file_fcntl, struct file *file, unsigned int cmd, - unsigned long arg) -LSM_HOOK(void, LSM_RET_VOID, file_set_fowner, struct file *file) -LSM_HOOK(int, 0, file_send_sigiotask, struct task_struct *tsk, - struct fown_struct *fown, int sig) -LSM_HOOK(int, 0, file_receive, struct file *file) -LSM_HOOK(int, 0, file_open, struct file *file) -LSM_HOOK(int, 0, task_alloc, struct task_struct *task, - unsigned long clone_flags) -LSM_HOOK(void, LSM_RET_VOID, task_free, struct task_struct *task) -LSM_HOOK(int, 0, cred_alloc_blank, struct cred *cred, gfp_t gfp) -LSM_HOOK(void, LSM_RET_VOID, cred_free, struct cred *cred) -LSM_HOOK(int, 0, cred_prepare, struct cred *new, const struct cred *old, - gfp_t gfp) -LSM_HOOK(void, LSM_RET_VOID, cred_transfer, struct cred *new, +LSM_HOOK(void, LSM_RET_VOID, 0, inode_getsecid, struct inode *inode, u32 *secid) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_copy_up, struct dentry *src, + struct cred **new) +LSM_HOOK(int, -EOPNOTSUPP, LSM_RET_NEG | LSM_RET_ZERO | LSM_RET_ONE, + inode_copy_up_xattr, const char *name) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, kernfs_init_security, + struct kernfs_node *kn_dir, struct kernfs_node *kn) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, file_permission, struct file *file, + int mask) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, file_alloc_security, + struct file *file) +LSM_HOOK(void, LSM_RET_VOID, 0, file_free_security, struct file *file) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, file_ioctl, struct file *file, + unsigned int cmd, unsigned long arg) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, mmap_addr, unsigned long addr) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, mmap_file, struct file *file, + unsigned long reqprot, unsigned long prot, unsigned long flags) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, file_mprotect, + struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, file_lock, struct file *file, + unsigned int cmd) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, file_fcntl, struct file *file, + unsigned int cmd, unsigned long arg) +LSM_HOOK(void, LSM_RET_VOID, 0, file_set_fowner, struct file *file) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, file_send_sigiotask, + struct task_struct *tsk, struct fown_struct *fown, int sig) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, file_receive, struct file *file) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, file_open, struct file *file) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, task_alloc, + struct task_struct *task, unsigned long clone_flags) +LSM_HOOK(void, LSM_RET_VOID, 0, task_free, struct task_struct *task) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, cred_alloc_blank, + struct cred *cred, gfp_t gfp) +LSM_HOOK(void, LSM_RET_VOID, 0, cred_free, struct cred *cred) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, cred_prepare, struct cred *new, + const struct cred *old, gfp_t gfp) +LSM_HOOK(void, LSM_RET_VOID, 0, cred_transfer, struct cred *new, const struct cred *old) -LSM_HOOK(void, LSM_RET_VOID, cred_getsecid, const struct cred *c, u32 *secid) -LSM_HOOK(int, 0, kernel_act_as, struct cred *new, u32 secid) -LSM_HOOK(int, 0, kernel_create_files_as, struct cred *new, struct inode *inode) -LSM_HOOK(int, 0, kernel_module_request, char *kmod_name) -LSM_HOOK(int, 0, kernel_load_data, enum kernel_load_data_id id, bool contents) -LSM_HOOK(int, 0, kernel_post_load_data, char *buf, loff_t size, - enum kernel_load_data_id id, char *description) -LSM_HOOK(int, 0, kernel_read_file, struct file *file, - enum kernel_read_file_id id, bool contents) -LSM_HOOK(int, 0, kernel_post_read_file, struct file *file, char *buf, - loff_t size, enum kernel_read_file_id id) -LSM_HOOK(int, 0, task_fix_setuid, struct cred *new, const struct cred *old, - int flags) -LSM_HOOK(int, 0, task_fix_setgid, struct cred *new, const struct cred * old, - int flags) -LSM_HOOK(int, 0, task_fix_setgroups, struct cred *new, const struct cred * old) -LSM_HOOK(int, 0, task_setpgid, struct task_struct *p, pid_t pgid) -LSM_HOOK(int, 0, task_getpgid, struct task_struct *p) -LSM_HOOK(int, 0, task_getsid, struct task_struct *p) -LSM_HOOK(void, LSM_RET_VOID, current_getsecid_subj, u32 *secid) -LSM_HOOK(void, LSM_RET_VOID, task_getsecid_obj, +LSM_HOOK(void, LSM_RET_VOID, 0, cred_getsecid, const struct cred *c, u32 *secid) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, kernel_act_as, struct cred *new, + u32 secid) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, kernel_create_files_as, + struct cred *new, struct inode *inode) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, kernel_module_request, + char *kmod_name) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, kernel_load_data, + enum kernel_load_data_id id, bool contents) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, kernel_post_load_data, char *buf, + loff_t size, enum kernel_load_data_id id, char *description) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, kernel_read_file, + struct file *file, enum kernel_read_file_id id, bool contents) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, kernel_post_read_file, + struct file *file, char *buf, loff_t size, enum kernel_read_file_id id) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, task_fix_setuid, struct cred *new, + const struct cred *old, int flags) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, task_fix_setgid, struct cred *new, + const struct cred *old, int flags) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, task_fix_setgroups, + struct cred *new, const struct cred *old) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, task_setpgid, + struct task_struct *p, pid_t pgid) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, task_getpgid, + struct task_struct *p) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, task_getsid, struct task_struct *p) +LSM_HOOK(void, LSM_RET_VOID, 0, current_getsecid_subj, u32 *secid) +LSM_HOOK(void, LSM_RET_VOID, 0, task_getsecid_obj, struct task_struct *p, u32 *secid) -LSM_HOOK(int, 0, task_setnice, struct task_struct *p, int nice) -LSM_HOOK(int, 0, task_setioprio, struct task_struct *p, int ioprio) -LSM_HOOK(int, 0, task_getioprio, struct task_struct *p) -LSM_HOOK(int, 0, task_prlimit, const struct cred *cred, - const struct cred *tcred, unsigned int flags) -LSM_HOOK(int, 0, task_setrlimit, struct task_struct *p, unsigned int resource, - struct rlimit *new_rlim) -LSM_HOOK(int, 0, task_setscheduler, struct task_struct *p) -LSM_HOOK(int, 0, task_getscheduler, struct task_struct *p) -LSM_HOOK(int, 0, task_movememory, struct task_struct *p) -LSM_HOOK(int, 0, task_kill, struct task_struct *p, struct kernel_siginfo *info, - int sig, const struct cred *cred) -LSM_HOOK(int, -ENOSYS, task_prctl, int option, unsigned long arg2, - unsigned long arg3, unsigned long arg4, unsigned long arg5) -LSM_HOOK(void, LSM_RET_VOID, task_to_inode, struct task_struct *p, +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, task_setnice, + struct task_struct *p, int nice) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, task_setioprio, + struct task_struct *p, int ioprio) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, task_getioprio, + struct task_struct *p) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, task_prlimit, + const struct cred *cred, const struct cred *tcred, unsigned int flags) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, task_setrlimit, + struct task_struct *p, unsigned int resource, struct rlimit *new_rlim) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, task_setscheduler, + struct task_struct *p) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, task_getscheduler, + struct task_struct *p) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, task_movememory, + struct task_struct *p) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, task_kill, struct task_struct *p, + struct kernel_siginfo *info, int sig, const struct cred *cred) +LSM_HOOK(int, -ENOSYS, + LSM_RET_NEG | LSM_RET_ZERO | LSM_RET_ONE | LSM_RET_GT_ONE, task_prctl, + int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, + unsigned long arg5) +LSM_HOOK(void, LSM_RET_VOID, 0, task_to_inode, struct task_struct *p, struct inode *inode) -LSM_HOOK(int, 0, userns_create, const struct cred *cred) -LSM_HOOK(int, 0, ipc_permission, struct kern_ipc_perm *ipcp, short flag) -LSM_HOOK(void, LSM_RET_VOID, ipc_getsecid, struct kern_ipc_perm *ipcp, +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, userns_create, + const struct cred *cred) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, ipc_permission, + struct kern_ipc_perm *ipcp, short flag) +LSM_HOOK(void, LSM_RET_VOID, 0, ipc_getsecid, struct kern_ipc_perm *ipcp, u32 *secid) -LSM_HOOK(int, 0, msg_msg_alloc_security, struct msg_msg *msg) -LSM_HOOK(void, LSM_RET_VOID, msg_msg_free_security, struct msg_msg *msg) -LSM_HOOK(int, 0, msg_queue_alloc_security, struct kern_ipc_perm *perm) -LSM_HOOK(void, LSM_RET_VOID, msg_queue_free_security, +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, msg_msg_alloc_security, + struct msg_msg *msg) +LSM_HOOK(void, LSM_RET_VOID, 0, msg_msg_free_security, struct msg_msg *msg) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, msg_queue_alloc_security, + struct kern_ipc_perm *perm) +LSM_HOOK(void, LSM_RET_VOID, 0, msg_queue_free_security, + struct kern_ipc_perm *perm) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, msg_queue_associate, + struct kern_ipc_perm *perm, int msqflg) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, msg_queue_msgctl, + struct kern_ipc_perm *perm, int cmd) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, msg_queue_msgsnd, + struct kern_ipc_perm *perm, struct msg_msg *msg, int msqflg) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, msg_queue_msgrcv, + struct kern_ipc_perm *perm, struct msg_msg *msg, + struct task_struct *target, long type, int mode) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, shm_alloc_security, struct kern_ipc_perm *perm) -LSM_HOOK(int, 0, msg_queue_associate, struct kern_ipc_perm *perm, int msqflg) -LSM_HOOK(int, 0, msg_queue_msgctl, struct kern_ipc_perm *perm, int cmd) -LSM_HOOK(int, 0, msg_queue_msgsnd, struct kern_ipc_perm *perm, - struct msg_msg *msg, int msqflg) -LSM_HOOK(int, 0, msg_queue_msgrcv, struct kern_ipc_perm *perm, - struct msg_msg *msg, struct task_struct *target, long type, int mode) -LSM_HOOK(int, 0, shm_alloc_security, struct kern_ipc_perm *perm) -LSM_HOOK(void, LSM_RET_VOID, shm_free_security, struct kern_ipc_perm *perm) -LSM_HOOK(int, 0, shm_associate, struct kern_ipc_perm *perm, int shmflg) -LSM_HOOK(int, 0, shm_shmctl, struct kern_ipc_perm *perm, int cmd) -LSM_HOOK(int, 0, shm_shmat, struct kern_ipc_perm *perm, char __user *shmaddr, - int shmflg) -LSM_HOOK(int, 0, sem_alloc_security, struct kern_ipc_perm *perm) -LSM_HOOK(void, LSM_RET_VOID, sem_free_security, struct kern_ipc_perm *perm) -LSM_HOOK(int, 0, sem_associate, struct kern_ipc_perm *perm, int semflg) -LSM_HOOK(int, 0, sem_semctl, struct kern_ipc_perm *perm, int cmd) -LSM_HOOK(int, 0, sem_semop, struct kern_ipc_perm *perm, struct sembuf *sops, - unsigned nsops, int alter) -LSM_HOOK(int, 0, netlink_send, struct sock *sk, struct sk_buff *skb) -LSM_HOOK(void, LSM_RET_VOID, d_instantiate, struct dentry *dentry, +LSM_HOOK(void, LSM_RET_VOID, 0, shm_free_security, struct kern_ipc_perm *perm) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, shm_associate, + struct kern_ipc_perm *perm, int shmflg) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, shm_shmctl, + struct kern_ipc_perm *perm, int cmd) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, shm_shmat, + struct kern_ipc_perm *perm, char __user *shmaddr, int shmflg) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sem_alloc_security, + struct kern_ipc_perm *perm) +LSM_HOOK(void, LSM_RET_VOID, 0, sem_free_security, struct kern_ipc_perm *perm) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sem_associate, + struct kern_ipc_perm *perm, int semflg) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sem_semctl, + struct kern_ipc_perm *perm, int cmd) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sem_semop, + struct kern_ipc_perm *perm, struct sembuf *sops, unsigned nsops, + int alter) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, netlink_send, struct sock *sk, + struct sk_buff *skb) +LSM_HOOK(void, LSM_RET_VOID, 0, d_instantiate, struct dentry *dentry, struct inode *inode) -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, 0, ismaclabel, const char *name) -LSM_HOOK(int, -EOPNOTSUPP, secid_to_secctx, u32 secid, char **secdata, - u32 *seclen) -LSM_HOOK(int, 0, secctx_to_secid, const char *secdata, u32 seclen, u32 *secid) -LSM_HOOK(void, LSM_RET_VOID, release_secctx, char *secdata, u32 seclen) -LSM_HOOK(void, LSM_RET_VOID, inode_invalidate_secctx, struct inode *inode) -LSM_HOOK(int, 0, inode_notifysecctx, struct inode *inode, void *ctx, u32 ctxlen) -LSM_HOOK(int, 0, inode_setsecctx, struct dentry *dentry, void *ctx, u32 ctxlen) -LSM_HOOK(int, 0, inode_getsecctx, struct inode *inode, void **ctx, - u32 *ctxlen) +LSM_HOOK(int, -EINVAL, + LSM_RET_NEG | LSM_RET_ZERO | LSM_RET_ONE | LSM_RET_GT_ONE, getprocattr, + struct task_struct *p, const char *name, char **value) +LSM_HOOK(int, -EINVAL, + LSM_RET_NEG | LSM_RET_ZERO | LSM_RET_ONE | LSM_RET_GT_ONE, setprocattr, + const char *name, void *value, size_t size) +LSM_HOOK(int, 0, LSM_RET_ZERO | LSM_RET_ONE, ismaclabel, const char *name) +LSM_HOOK(int, -EOPNOTSUPP, LSM_RET_NEG | LSM_RET_ZERO, secid_to_secctx, + u32 secid, char **secdata, u32 *seclen) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, secctx_to_secid, + const char *secdata, u32 seclen, u32 *secid) +LSM_HOOK(void, LSM_RET_VOID, 0, release_secctx, char *secdata, u32 seclen) +LSM_HOOK(void, LSM_RET_VOID, 0, inode_invalidate_secctx, struct inode *inode) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_notifysecctx, + struct inode *inode, void *ctx, u32 ctxlen) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_setsecctx, + struct dentry *dentry, void *ctx, u32 ctxlen) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inode_getsecctx, + struct inode *inode, void **ctx, u32 *ctxlen) #if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE) -LSM_HOOK(int, 0, post_notification, const struct cred *w_cred, - const struct cred *cred, struct watch_notification *n) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, post_notification, + const struct cred *w_cred, const struct cred *cred, + struct watch_notification *n) #endif /* CONFIG_SECURITY && CONFIG_WATCH_QUEUE */ #if defined(CONFIG_SECURITY) && defined(CONFIG_KEY_NOTIFICATIONS) -LSM_HOOK(int, 0, watch_key, struct key *key) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, watch_key, struct key *key) #endif /* CONFIG_SECURITY && CONFIG_KEY_NOTIFICATIONS */ #ifdef CONFIG_SECURITY_NETWORK -LSM_HOOK(int, 0, unix_stream_connect, struct sock *sock, struct sock *other, - struct sock *newsk) -LSM_HOOK(int, 0, unix_may_send, struct socket *sock, struct socket *other) -LSM_HOOK(int, 0, socket_create, int family, int type, int protocol, int kern) -LSM_HOOK(int, 0, socket_post_create, struct socket *sock, int family, int type, - int protocol, int kern) -LSM_HOOK(int, 0, socket_socketpair, struct socket *socka, struct socket *sockb) -LSM_HOOK(int, 0, socket_bind, struct socket *sock, struct sockaddr *address, - int addrlen) -LSM_HOOK(int, 0, socket_connect, struct socket *sock, struct sockaddr *address, - int addrlen) -LSM_HOOK(int, 0, socket_listen, struct socket *sock, int backlog) -LSM_HOOK(int, 0, socket_accept, struct socket *sock, struct socket *newsock) -LSM_HOOK(int, 0, socket_sendmsg, struct socket *sock, struct msghdr *msg, - int size) -LSM_HOOK(int, 0, socket_recvmsg, struct socket *sock, struct msghdr *msg, - int size, int flags) -LSM_HOOK(int, 0, socket_getsockname, struct socket *sock) -LSM_HOOK(int, 0, socket_getpeername, struct socket *sock) -LSM_HOOK(int, 0, socket_getsockopt, struct socket *sock, int level, int optname) -LSM_HOOK(int, 0, socket_setsockopt, struct socket *sock, int level, int optname) -LSM_HOOK(int, 0, socket_shutdown, struct socket *sock, int how) -LSM_HOOK(int, 0, socket_sock_rcv_skb, struct sock *sk, struct sk_buff *skb) -LSM_HOOK(int, 0, socket_getpeersec_stream, struct socket *sock, - sockptr_t optval, sockptr_t optlen, unsigned int len) -LSM_HOOK(int, 0, socket_getpeersec_dgram, struct socket *sock, - struct sk_buff *skb, u32 *secid) -LSM_HOOK(int, 0, sk_alloc_security, struct sock *sk, int family, gfp_t priority) -LSM_HOOK(void, LSM_RET_VOID, sk_free_security, struct sock *sk) -LSM_HOOK(void, LSM_RET_VOID, sk_clone_security, const struct sock *sk, +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, unix_stream_connect, + struct sock *sock, struct sock *other, struct sock *newsk) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, unix_may_send, struct socket *sock, + struct socket *other) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, socket_create, int family, + int type, int protocol, int kern) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, socket_post_create, + struct socket *sock, int family, int type, int protocol, int kern) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, socket_socketpair, + struct socket *socka, struct socket *sockb) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, socket_bind, struct socket *sock, + struct sockaddr *address, int addrlen) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, socket_connect, + struct socket *sock, struct sockaddr *address, int addrlen) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, socket_listen, struct socket *sock, + int backlog) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, socket_accept, struct socket *sock, + struct socket *newsock) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, socket_sendmsg, + struct socket *sock, struct msghdr *msg, int size) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, socket_recvmsg, + struct socket *sock, struct msghdr *msg, int size, int flags) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, socket_getsockname, + struct socket *sock) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, socket_getpeername, + struct socket *sock) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, socket_getsockopt, + struct socket *sock, int level, int optname) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, socket_setsockopt, + struct socket *sock, int level, int optname) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, socket_shutdown, + struct socket *sock, int how) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, socket_sock_rcv_skb, + struct sock *sk, struct sk_buff *skb) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, socket_getpeersec_stream, + struct socket *sock, sockptr_t optval, sockptr_t optlen, + unsigned int len) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, socket_getpeersec_dgram, + struct socket *sock, struct sk_buff *skb, u32 *secid) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sk_alloc_security, struct sock *sk, + int family, gfp_t priority) +LSM_HOOK(void, LSM_RET_VOID, 0, sk_free_security, struct sock *sk) +LSM_HOOK(void, LSM_RET_VOID, 0, sk_clone_security, const struct sock *sk, struct sock *newsk) -LSM_HOOK(void, LSM_RET_VOID, sk_getsecid, struct sock *sk, u32 *secid) -LSM_HOOK(void, LSM_RET_VOID, sock_graft, struct sock *sk, struct socket *parent) -LSM_HOOK(int, 0, inet_conn_request, const struct sock *sk, struct sk_buff *skb, - struct request_sock *req) -LSM_HOOK(void, LSM_RET_VOID, inet_csk_clone, struct sock *newsk, +LSM_HOOK(void, LSM_RET_VOID, 0, sk_getsecid, struct sock *sk, u32 *secid) +LSM_HOOK(void, LSM_RET_VOID, 0, sock_graft, struct sock *sk, struct socket *parent) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, inet_conn_request, + const struct sock *sk, struct sk_buff *skb, struct request_sock *req) +LSM_HOOK(void, LSM_RET_VOID, 0, inet_csk_clone, struct sock *newsk, const struct request_sock *req) -LSM_HOOK(void, LSM_RET_VOID, inet_conn_established, struct sock *sk, +LSM_HOOK(void, LSM_RET_VOID, 0, inet_conn_established, struct sock *sk, struct sk_buff *skb) -LSM_HOOK(int, 0, secmark_relabel_packet, u32 secid) -LSM_HOOK(void, LSM_RET_VOID, secmark_refcount_inc, void) -LSM_HOOK(void, LSM_RET_VOID, secmark_refcount_dec, void) -LSM_HOOK(void, LSM_RET_VOID, req_classify_flow, const struct request_sock *req, +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, secmark_relabel_packet, u32 secid) +LSM_HOOK(void, LSM_RET_VOID, 0, secmark_refcount_inc, void) +LSM_HOOK(void, LSM_RET_VOID, 0, secmark_refcount_dec, void) +LSM_HOOK(void, LSM_RET_VOID, 0, req_classify_flow, const struct request_sock *req, struct flowi_common *flic) -LSM_HOOK(int, 0, tun_dev_alloc_security, void **security) -LSM_HOOK(void, LSM_RET_VOID, tun_dev_free_security, void *security) -LSM_HOOK(int, 0, tun_dev_create, void) -LSM_HOOK(int, 0, tun_dev_attach_queue, void *security) -LSM_HOOK(int, 0, tun_dev_attach, struct sock *sk, void *security) -LSM_HOOK(int, 0, tun_dev_open, void *security) -LSM_HOOK(int, 0, sctp_assoc_request, struct sctp_association *asoc, - struct sk_buff *skb) -LSM_HOOK(int, 0, sctp_bind_connect, struct sock *sk, int optname, - struct sockaddr *address, int addrlen) -LSM_HOOK(void, LSM_RET_VOID, sctp_sk_clone, struct sctp_association *asoc, +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, tun_dev_alloc_security, + void **security) +LSM_HOOK(void, LSM_RET_VOID, 0, tun_dev_free_security, void *security) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, tun_dev_create, void) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, tun_dev_attach_queue, + void *security) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, tun_dev_attach, struct sock *sk, + void *security) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, tun_dev_open, void *security) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sctp_assoc_request, + struct sctp_association *asoc, struct sk_buff *skb) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sctp_bind_connect, struct sock *sk, + int optname, struct sockaddr *address, int addrlen) +LSM_HOOK(void, LSM_RET_VOID, 0, sctp_sk_clone, struct sctp_association *asoc, struct sock *sk, struct sock *newsk) -LSM_HOOK(int, 0, sctp_assoc_established, struct sctp_association *asoc, - struct sk_buff *skb) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, sctp_assoc_established, + struct sctp_association *asoc, struct sk_buff *skb) #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_INFINIBAND -LSM_HOOK(int, 0, ib_pkey_access, void *sec, u64 subnet_prefix, u16 pkey) -LSM_HOOK(int, 0, ib_endport_manage_subnet, void *sec, const char *dev_name, - u8 port_num) -LSM_HOOK(int, 0, ib_alloc_security, void **sec) -LSM_HOOK(void, LSM_RET_VOID, ib_free_security, void *sec) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, ib_pkey_access, void *sec, + u64 subnet_prefix, u16 pkey) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, ib_endport_manage_subnet, + void *sec, const char *dev_name, u8 port_num) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, ib_alloc_security, void **sec) +LSM_HOOK(void, LSM_RET_VOID, 0, ib_free_security, void *sec) #endif /* CONFIG_SECURITY_INFINIBAND */ #ifdef CONFIG_SECURITY_NETWORK_XFRM -LSM_HOOK(int, 0, xfrm_policy_alloc_security, struct xfrm_sec_ctx **ctxp, - struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp) -LSM_HOOK(int, 0, xfrm_policy_clone_security, struct xfrm_sec_ctx *old_ctx, - struct xfrm_sec_ctx **new_ctx) -LSM_HOOK(void, LSM_RET_VOID, xfrm_policy_free_security, +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, xfrm_policy_alloc_security, + struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx, + gfp_t gfp) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, xfrm_policy_clone_security, + struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx) +LSM_HOOK(void, LSM_RET_VOID, 0, xfrm_policy_free_security, + struct xfrm_sec_ctx *ctx) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, xfrm_policy_delete_security, struct xfrm_sec_ctx *ctx) -LSM_HOOK(int, 0, xfrm_policy_delete_security, struct xfrm_sec_ctx *ctx) -LSM_HOOK(int, 0, xfrm_state_alloc, struct xfrm_state *x, - struct xfrm_user_sec_ctx *sec_ctx) -LSM_HOOK(int, 0, xfrm_state_alloc_acquire, struct xfrm_state *x, - struct xfrm_sec_ctx *polsec, u32 secid) -LSM_HOOK(void, LSM_RET_VOID, xfrm_state_free_security, struct xfrm_state *x) -LSM_HOOK(int, 0, xfrm_state_delete_security, struct xfrm_state *x) -LSM_HOOK(int, 0, xfrm_policy_lookup, struct xfrm_sec_ctx *ctx, u32 fl_secid) -LSM_HOOK(int, 1, xfrm_state_pol_flow_match, struct xfrm_state *x, - struct xfrm_policy *xp, const struct flowi_common *flic) -LSM_HOOK(int, 0, xfrm_decode_session, struct sk_buff *skb, u32 *secid, - int ckall) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, xfrm_state_alloc, + struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, xfrm_state_alloc_acquire, + struct xfrm_state *x, struct xfrm_sec_ctx *polsec, u32 secid) +LSM_HOOK(void, LSM_RET_VOID, 0, xfrm_state_free_security, struct xfrm_state *x) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, xfrm_state_delete_security, + struct xfrm_state *x) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, xfrm_policy_lookup, + struct xfrm_sec_ctx *ctx, u32 fl_secid) +LSM_HOOK(int, 1, LSM_RET_ZERO | LSM_RET_ONE, xfrm_state_pol_flow_match, + struct xfrm_state *x, struct xfrm_policy *xp, + const struct flowi_common *flic) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, xfrm_decode_session, + struct sk_buff *skb, u32 *secid, int ckall) #endif /* CONFIG_SECURITY_NETWORK_XFRM */ /* key management security hooks */ #ifdef CONFIG_KEYS -LSM_HOOK(int, 0, key_alloc, struct key *key, const struct cred *cred, - unsigned long flags) -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, LSM_RET_NEG | LSM_RET_ZERO, key_alloc, struct key *key, + const struct cred *cred, unsigned long flags) +LSM_HOOK(void, LSM_RET_VOID, 0, key_free, struct key *key) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, key_permission, key_ref_t key_ref, + const struct cred *cred, enum key_need_perm need_perm) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO | LSM_RET_ONE | LSM_RET_GT_ONE, + key_getsecurity, struct key *key, char **_buffer) #endif /* CONFIG_KEYS */ #ifdef CONFIG_AUDIT -LSM_HOOK(int, 0, audit_rule_init, u32 field, u32 op, char *rulestr, - void **lsmrule) -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(void, LSM_RET_VOID, audit_rule_free, void *lsmrule) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, audit_rule_init, u32 field, u32 op, + char *rulestr, void **lsmrule) +LSM_HOOK(int, 0, LSM_RET_ZERO | LSM_RET_ONE, audit_rule_known, + struct audit_krule *krule) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO | LSM_RET_ONE, audit_rule_match, + u32 secid, u32 field, u32 op, void *lsmrule) +LSM_HOOK(void, LSM_RET_VOID, 0, audit_rule_free, void *lsmrule) #endif /* CONFIG_AUDIT */ #ifdef CONFIG_BPF_SYSCALL -LSM_HOOK(int, 0, bpf, int cmd, union bpf_attr *attr, unsigned int size) -LSM_HOOK(int, 0, bpf_map, struct bpf_map *map, fmode_t fmode) -LSM_HOOK(int, 0, bpf_prog, struct bpf_prog *prog) -LSM_HOOK(int, 0, bpf_map_alloc_security, struct bpf_map *map) -LSM_HOOK(void, LSM_RET_VOID, bpf_map_free_security, struct bpf_map *map) -LSM_HOOK(int, 0, bpf_prog_alloc_security, struct bpf_prog_aux *aux) -LSM_HOOK(void, LSM_RET_VOID, bpf_prog_free_security, struct bpf_prog_aux *aux) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, bpf, int cmd, union bpf_attr *attr, + unsigned int size) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, bpf_map, struct bpf_map *map, + fmode_t fmode) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, bpf_prog, struct bpf_prog *prog) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, bpf_map_alloc_security, + struct bpf_map *map) +LSM_HOOK(void, LSM_RET_VOID, 0, bpf_map_free_security, struct bpf_map *map) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, bpf_prog_alloc_security, + struct bpf_prog_aux *aux) +LSM_HOOK(void, LSM_RET_VOID, 0, bpf_prog_free_security, struct bpf_prog_aux *aux) #endif /* CONFIG_BPF_SYSCALL */ -LSM_HOOK(int, 0, locked_down, enum lockdown_reason what) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, locked_down, + enum lockdown_reason what) #ifdef CONFIG_PERF_EVENTS -LSM_HOOK(int, 0, perf_event_open, struct perf_event_attr *attr, int type) -LSM_HOOK(int, 0, perf_event_alloc, struct perf_event *event) -LSM_HOOK(void, LSM_RET_VOID, perf_event_free, struct perf_event *event) -LSM_HOOK(int, 0, perf_event_read, struct perf_event *event) -LSM_HOOK(int, 0, perf_event_write, struct perf_event *event) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, perf_event_open, + struct perf_event_attr *attr, int type) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, perf_event_alloc, + struct perf_event *event) +LSM_HOOK(void, LSM_RET_VOID, 0, perf_event_free, struct perf_event *event) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, perf_event_read, + struct perf_event *event) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, perf_event_write, + struct perf_event *event) #endif /* CONFIG_PERF_EVENTS */ #ifdef CONFIG_IO_URING -LSM_HOOK(int, 0, uring_override_creds, const struct cred *new) -LSM_HOOK(int, 0, uring_sqpoll, void) -LSM_HOOK(int, 0, uring_cmd, struct io_uring_cmd *ioucmd) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, uring_override_creds, + const struct cred *new) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, uring_sqpoll, void) +LSM_HOOK(int, 0, LSM_RET_NEG | LSM_RET_ZERO, uring_cmd, + struct io_uring_cmd *ioucmd) #endif /* CONFIG_IO_URING */ diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 883f0f252f06..d1859b8ab9a3 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1591,13 +1591,13 @@ * */ union security_list_options { - #define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__); + #define LSM_HOOK(RET, DEFAULT, RET_FLAGS, NAME, ...) RET (*NAME)(__VA_ARGS__); #include "lsm_hook_defs.h" #undef LSM_HOOK }; struct security_hook_heads { - #define LSM_HOOK(RET, DEFAULT, NAME, ...) struct hlist_head NAME; + #define LSM_HOOK(RET, DEFAULT, RET_FLAGS, NAME, ...) struct hlist_head NAME; #include "lsm_hook_defs.h" #undef LSM_HOOK } __randomize_layout; @@ -1632,6 +1632,11 @@ struct lsm_blob_sizes { */ #define LSM_RET_VOID ((void) 0) +#define LSM_RET_NEG 0x01 +#define LSM_RET_ZERO 0x02 +#define LSM_RET_ONE 0x04 +#define LSM_RET_GT_ONE 0x08 + /* * Initializing a security_hook_list structure takes * up a lot of space in a source file. This macro takes diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c index 9ea42a45da47..98f810f661a6 100644 --- a/kernel/bpf/bpf_lsm.c +++ b/kernel/bpf/bpf_lsm.c @@ -21,7 +21,7 @@ /* For every LSM hook that allows attachment of BPF programs, declare a nop * function where a BPF program can be attached. */ -#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ +#define LSM_HOOK(RET, DEFAULT, RET_FLAGS, NAME, ...) \ noinline RET bpf_lsm_##NAME(__VA_ARGS__) \ { \ return DEFAULT; \ @@ -30,7 +30,8 @@ noinline RET bpf_lsm_##NAME(__VA_ARGS__) \ #include #undef LSM_HOOK -#define LSM_HOOK(RET, DEFAULT, NAME, ...) BTF_ID(func, bpf_lsm_##NAME) +#define LSM_HOOK(RET, DEFAULT, RET_FLAGS, NAME, ...) \ + BTF_ID(func, bpf_lsm_##NAME) BTF_SET_START(bpf_lsm_hooks) #include #undef LSM_HOOK diff --git a/security/bpf/hooks.c b/security/bpf/hooks.c index e5971fa74fd7..a2a3b2be345f 100644 --- a/security/bpf/hooks.c +++ b/security/bpf/hooks.c @@ -7,7 +7,7 @@ #include static struct security_hook_list bpf_lsm_hooks[] __lsm_ro_after_init = { - #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ + #define LSM_HOOK(RET, DEFAULT, RET_FLAGS, NAME, ...) \ LSM_HOOK_INIT(NAME, bpf_lsm_##NAME), #include #undef LSM_HOOK diff --git a/security/security.c b/security/security.c index f27c885ee98d..357cd845d1ed 100644 --- a/security/security.c +++ b/security/security.c @@ -371,7 +371,7 @@ int __init early_security_init(void) { struct lsm_info *lsm; -#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ +#define LSM_HOOK(RET, DEFAULT, RET_FLAGS, NAME, ...) \ INIT_HLIST_HEAD(&security_hook_heads.NAME); #include "linux/lsm_hook_defs.h" #undef LSM_HOOK @@ -710,7 +710,7 @@ static int lsm_superblock_alloc(struct super_block *sb) #define DECLARE_LSM_RET_DEFAULT_void(DEFAULT, NAME) #define DECLARE_LSM_RET_DEFAULT_int(DEFAULT, NAME) \ static const int __maybe_unused LSM_RET_DEFAULT(NAME) = (DEFAULT); -#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ +#define LSM_HOOK(RET, DEFAULT, RET_FLAGS, NAME, ...) \ DECLARE_LSM_RET_DEFAULT_##RET(DEFAULT, NAME) #include From patchwork Wed Dec 7 17:24:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13067437 X-Patchwork-Delegate: paul@paul-moore.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 75E1CC47089 for ; Wed, 7 Dec 2022 17:26:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230019AbiLGR0S (ORCPT ); Wed, 7 Dec 2022 12:26:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33518 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229762AbiLGR0C (ORCPT ); Wed, 7 Dec 2022 12:26:02 -0500 Received: from frasgout11.his.huawei.com (frasgout11.his.huawei.com [14.137.139.23]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 99FA25B5A4; Wed, 7 Dec 2022 09:25:59 -0800 (PST) Received: from mail02.huawei.com (unknown [172.18.147.229]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4NS3sh1xb2z9xGZF; Thu, 8 Dec 2022 01:18:48 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwD34m9YzJBjc9DJAA--.62662S6; Wed, 07 Dec 2022 18:25:35 +0100 (CET) From: Roberto Sassu To: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, song@kernel.org, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com, haoluo@google.com, jolsa@kernel.org, revest@chromium.org, jackmanb@chromium.org, mykolal@fb.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, shuah@kernel.org Cc: bpf@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Roberto Sassu , stable@vger.kernel.org Subject: [RFC][PATCH v2 4/7] bpf-lsm: Enforce return value limitations on security modules Date: Wed, 7 Dec 2022 18:24:31 +0100 Message-Id: <20221207172434.435893-5-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221207172434.435893-1-roberto.sassu@huaweicloud.com> References: <20221207172434.435893-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwD34m9YzJBjc9DJAA--.62662S6 X-Coremail-Antispam: 1UD129KBjvJXoW3GFy5Aw1xWF47tFWDJF1kXwb_yoWxGw1rpr WfAFyYkr4v93y7W3Wqyan5ZrZ5XF10ga1UGF98G34Fvr42vryvqw1UGrnIvry5Cryjgr1x Kr42grWjgw47ZaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPlb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26r4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrV C2j2WlYx0E2Ix0cI8IcVAFwI0_JrI_JrylYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE 7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262 kKe7AKxVW8ZVWrXwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s02 6c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GF v_WrylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVW8JVW5JwCI42IY6xIIjxv20xvE c7CjxVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aV AFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZF pf9x07j7GYLUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgATBF1jj4JqowAAsv X-CFilter-Loop: Reflected Precedence: bulk List-ID: From: Roberto Sassu With the patch for the LSM infrastructure to redefine the LSM_HOOK() macro and to introduce the return value flags, it becomes straightforward for eBPF to leverage this information to enforce return values limitations on eBPF programs implementing security hooks. Update the bpf_lsm_hooks BTF ID set, by including the return value flags. Then, introduce bpf_lsm_is_ret_value_allowed(), which determines in which intervals the R0 register (which contains the return value) falls, and checks if the corresponding return value flag is set for those intervals. In addition, for the interval including zero, ensure that the hook is not inode_init_security, otherwise report that zero is not allowed. By LSM conventions, LSMs should return zero only if they set an xattr, which currently eBPF programs cannot do. Finally, expose the new function and add a call to it in the verifier. Cc: stable@vger.kernel.org # 5.7.x Fixes: 9d3fdea789c8 ("bpf: lsm: Provide attachment points for BPF LSM programs") Signed-off-by: Roberto Sassu --- include/linux/bpf_lsm.h | 9 +++++ kernel/bpf/bpf_lsm.c | 78 ++++++++++++++++++++++++++++++++++++++--- kernel/bpf/verifier.c | 7 ++-- 3 files changed, 87 insertions(+), 7 deletions(-) diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h index 2f5757085dfd..0ce5948f3662 100644 --- a/include/linux/bpf_lsm.h +++ b/include/linux/bpf_lsm.h @@ -29,6 +29,8 @@ int bpf_lsm_verify_prog(struct bpf_verifier_log *vlog, bool bpf_lsm_is_sleepable_hook(u32 btf_id); bool bpf_lsm_is_trusted(const struct bpf_prog *prog); +bool bpf_lsm_is_ret_value_allowed(struct bpf_verifier_log *vlog, + struct bpf_reg_state *reg, u32 btf_id); static inline struct bpf_storage_blob *bpf_inode( const struct inode *inode) @@ -57,6 +59,13 @@ static inline bool bpf_lsm_is_trusted(const struct bpf_prog *prog) return false; } +static inline bool bpf_lsm_is_ret_value_allowed(struct bpf_verifier_log *vlog, + struct bpf_reg_state *reg, + u32 btf_id) +{ + return false; +} + static inline int bpf_lsm_verify_prog(struct bpf_verifier_log *vlog, const struct bpf_prog *prog) { diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c index 98f810f661a6..39ddafc06021 100644 --- a/kernel/bpf/bpf_lsm.c +++ b/kernel/bpf/bpf_lsm.c @@ -31,11 +31,11 @@ noinline RET bpf_lsm_##NAME(__VA_ARGS__) \ #undef LSM_HOOK #define LSM_HOOK(RET, DEFAULT, RET_FLAGS, NAME, ...) \ - BTF_ID(func, bpf_lsm_##NAME) -BTF_SET_START(bpf_lsm_hooks) + BTF_ID_FLAGS(func, bpf_lsm_##NAME, RET_FLAGS) +BTF_SET8_START(bpf_lsm_hooks) #include #undef LSM_HOOK -BTF_SET_END(bpf_lsm_hooks) +BTF_SET8_END(bpf_lsm_hooks) /* List of LSM hooks that should operate on 'current' cgroup regardless * of function signature. @@ -105,7 +105,7 @@ int bpf_lsm_verify_prog(struct bpf_verifier_log *vlog, return -EINVAL; } - if (!btf_id_set_contains(&bpf_lsm_hooks, prog->aux->attach_btf_id)) { + if (!btf_id_set8_contains(&bpf_lsm_hooks, prog->aux->attach_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); return -EINVAL; @@ -367,6 +367,76 @@ bool bpf_lsm_is_trusted(const struct bpf_prog *prog) return !btf_id_set_contains(&untrusted_lsm_hooks, prog->aux->attach_btf_id); } +BTF_SET_START(zero_forbidden_lsm_hooks) +BTF_ID(func, bpf_lsm_inode_init_security) +BTF_SET_END(zero_forbidden_lsm_hooks) + +bool bpf_lsm_is_ret_value_allowed(struct bpf_verifier_log *vlog, + struct bpf_reg_state *reg, u32 btf_id) +{ + u32 *id = btf_id_set8_contains(&bpf_lsm_hooks, btf_id); + s64 smin_value = reg->smin_value; + s64 smax_value = reg->smax_value; + u32 *ret_flags = id + 1; + + /* See no_alu32/test_bpf_cookie.bpf.o for how return -EPERM is compiled: + * + * 11: 18 06 00 00 ff ff ff ff 00 00 00 00 00 00 00 00 r6 = 4294967295 ll + * 13: 67 00 00 00 20 00 00 00 r0 <<= 32 + * 14: 77 00 00 00 20 00 00 00 r0 >>= 32 + * 15: 5d 08 07 00 00 00 00 00 if r8 != r0 goto +7 + * + * This causes predicted values to be: + * smin_value = 0xffffffff, smax_value = 0xffffffff, + * s32_min_value = 0xffffffff, s32_max_value = 0xffffffff, + * + * despite it is an ALU64 operation. So, checking reg->alu32 is not + * enough. Then, if after casting the 64 bit values they are equal to + * the 32 bit ones, use the latter ones (the LSM infrastructure takes + * an int). + */ + if ((reg->s32_min_value == (u32)smin_value && + reg->s32_max_value == (u32)smax_value) || reg->alu32) { + smin_value = reg->s32_min_value; + smax_value = reg->s32_max_value; + } + + /* Interval includes < 0 values. */ + if (smin_value < 0) { + if (!(*ret_flags & LSM_RET_NEG)) { + bpf_log(vlog, "Invalid R0, cannot return < 0\n"); + return false; + } + } + + /* Interval includes 0. */ + if (smin_value <= 0 && smax_value >= 0) { + if (!(*ret_flags & LSM_RET_ZERO) || + btf_id_set_contains(&zero_forbidden_lsm_hooks, btf_id)) { + bpf_log(vlog, "Invalid R0, cannot return 0\n"); + return false; + } + } + + /* Interval includes 1. */ + if (smin_value <= 1 && smax_value >= 1) { + if (!(*ret_flags & LSM_RET_ONE)) { + bpf_log(vlog, "Invalid R0, cannot return 1\n"); + return false; + } + } + + /* Interval includes > 1 values. */ + if (smax_value > 1) { + if (!(*ret_flags & LSM_RET_GT_ONE)) { + bpf_log(vlog, "Invalid R0, cannot return > 1\n"); + return false; + } + } + + return true; +} + const struct bpf_prog_ops lsm_prog_ops = { }; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index edce85c425a2..5d13b7f42238 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -12064,9 +12064,10 @@ static int check_return_code(struct bpf_verifier_env *env) case BPF_PROG_TYPE_LSM: if (env->prog->expected_attach_type != BPF_LSM_CGROUP) { - /* Regular BPF_PROG_TYPE_LSM programs can return - * any value. - */ + if (!bpf_lsm_is_ret_value_allowed(&env->log, reg, + env->prog->aux->attach_btf_id)) + return -EINVAL; + return 0; } if (!env->prog->aux->attach_func_proto->type) { From patchwork Wed Dec 7 17:24:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13067438 X-Patchwork-Delegate: paul@paul-moore.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 786B6C352A1 for ; Wed, 7 Dec 2022 17:26:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229992AbiLGR0r (ORCPT ); Wed, 7 Dec 2022 12:26:47 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34422 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229998AbiLGR0Q (ORCPT ); Wed, 7 Dec 2022 12:26:16 -0500 Received: from frasgout12.his.huawei.com (frasgout12.his.huawei.com [14.137.139.154]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EAE4D61743; Wed, 7 Dec 2022 09:26:09 -0800 (PST) Received: from mail02.huawei.com (unknown [172.18.147.227]) by frasgout12.his.huawei.com (SkyGuard) with ESMTP id 4NS3tP1d7vz9v7Y8; Thu, 8 Dec 2022 01:19:25 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwD34m9YzJBjc9DJAA--.62662S7; Wed, 07 Dec 2022 18:25:45 +0100 (CET) From: Roberto Sassu To: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, song@kernel.org, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com, haoluo@google.com, jolsa@kernel.org, revest@chromium.org, jackmanb@chromium.org, mykolal@fb.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, shuah@kernel.org Cc: bpf@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Roberto Sassu Subject: [RFC][PATCH v2 5/7] selftests/bpf: Check if return values of LSM programs are allowed Date: Wed, 7 Dec 2022 18:24:32 +0100 Message-Id: <20221207172434.435893-6-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221207172434.435893-1-roberto.sassu@huaweicloud.com> References: <20221207172434.435893-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwD34m9YzJBjc9DJAA--.62662S7 X-Coremail-Antispam: 1UD129KBjvJXoWxJF1kAr4UAFyxAr48Cr17ZFb_yoWrZr4Up3 WrZw1jkF40vF4avayrK397uayS9FW3CrWUKwnxZwnrZaykJF4xW3WUtFy5Ar13Gr15Gr9Y qF17Can5u3WUZa7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPlb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26r4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrV C2j2WlYx0E2Ix0cI8IcVAFwI0_JrI_JrylYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE 7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262 kKe7AKxVW8ZVWrXwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s02 6c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GF v_WrylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVW8JVW5JwCI42IY6xIIjxv20xvE c7CjxVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aV AFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZF pf9x07j7GYLUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgATBF1jj4JqowABsu X-CFilter-Loop: Reflected Precedence: bulk List-ID: From: Roberto Sassu Ensure that the eBPF verifier allows to load only LSM programs that return an allowed value depending on the LSM hook they attach to. Signed-off-by: Roberto Sassu --- .../testing/selftests/bpf/verifier/lsm_ret.c | 148 ++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 tools/testing/selftests/bpf/verifier/lsm_ret.c diff --git a/tools/testing/selftests/bpf/verifier/lsm_ret.c b/tools/testing/selftests/bpf/verifier/lsm_ret.c new file mode 100644 index 000000000000..c9c9cee8e406 --- /dev/null +++ b/tools/testing/selftests/bpf/verifier/lsm_ret.c @@ -0,0 +1,148 @@ +{ + "lsm return value: positive not allowed, return -EPERM", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, -EPERM), + BPF_EXIT_INSN(), + }, + .prog_type = BPF_PROG_TYPE_LSM, + .kfunc = "inode_permission", + .expected_attach_type = BPF_LSM_MAC, + .result = ACCEPT, +}, +{ + "lsm return value: positive not allowed, return zero", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, + .prog_type = BPF_PROG_TYPE_LSM, + .kfunc = "inode_permission", + .expected_attach_type = BPF_LSM_MAC, + .result = ACCEPT, +}, +{ + "lsm return value: positive not allowed, return one", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .prog_type = BPF_PROG_TYPE_LSM, + .kfunc = "inode_permission", + .expected_attach_type = BPF_LSM_MAC, + .errstr = "Invalid R0, cannot return 1", + .result = REJECT, +}, +{ + "lsm return value: zero/positive not allowed, return -EPERM", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, -EPERM), + BPF_EXIT_INSN(), + }, + .prog_type = BPF_PROG_TYPE_LSM, + .kfunc = "inode_init_security", + .expected_attach_type = BPF_LSM_MAC, + .result = ACCEPT, +}, +{ + "lsm return value: zero/positive not allowed, return zero", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, + .prog_type = BPF_PROG_TYPE_LSM, + .kfunc = "inode_init_security", + .expected_attach_type = BPF_LSM_MAC, + .errstr = "Invalid R0, cannot return 0", + .result = REJECT, +}, +{ + "lsm return value: zero/positive not allowed, return one", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .prog_type = BPF_PROG_TYPE_LSM, + .kfunc = "inode_init_security", + .expected_attach_type = BPF_LSM_MAC, + .errstr = "Invalid R0, cannot return 1", + .result = REJECT, +}, +{ + "lsm return value: positive allowed, return one", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .prog_type = BPF_PROG_TYPE_LSM, + .kfunc = "getprocattr", + .expected_attach_type = BPF_LSM_MAC, + .result = ACCEPT, +}, +{ + "lsm return value: positive allowed, return two", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 2), + BPF_EXIT_INSN(), + }, + .prog_type = BPF_PROG_TYPE_LSM, + .kfunc = "getprocattr", + .expected_attach_type = BPF_LSM_MAC, + .result = ACCEPT, +}, +{ + "lsm return value: only one allowed, return one", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .prog_type = BPF_PROG_TYPE_LSM, + .kfunc = "audit_rule_match", + .expected_attach_type = BPF_LSM_MAC, + .result = ACCEPT, +}, +{ + "lsm return value: only one allowed, return two", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 2), + BPF_EXIT_INSN(), + }, + .prog_type = BPF_PROG_TYPE_LSM, + .kfunc = "audit_rule_match", + .expected_attach_type = BPF_LSM_MAC, + .errstr = "Invalid R0, cannot return > 1", + .result = REJECT, +}, +{ + "lsm return value: negative not allowed, return -EPERM", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, -EPERM), + BPF_EXIT_INSN(), + }, + .prog_type = BPF_PROG_TYPE_LSM, + .kfunc = "ismaclabel", + .expected_attach_type = BPF_LSM_MAC, + .errstr = "Invalid R0, cannot return < 0", + .result = REJECT, +}, +{ + "lsm return value: negative not allowed, return zero", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, + .prog_type = BPF_PROG_TYPE_LSM, + .kfunc = "ismaclabel", + .expected_attach_type = BPF_LSM_MAC, + .result = ACCEPT, +}, +{ + "lsm return value: negative not allowed, return one", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .prog_type = BPF_PROG_TYPE_LSM, + .kfunc = "ismaclabel", + .expected_attach_type = BPF_LSM_MAC, + .result = ACCEPT, +}, From patchwork Wed Dec 7 17:24:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13067439 X-Patchwork-Delegate: paul@paul-moore.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id ED937C47089 for ; Wed, 7 Dec 2022 17:27:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229899AbiLGR1I (ORCPT ); Wed, 7 Dec 2022 12:27:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33924 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229676AbiLGR0c (ORCPT ); Wed, 7 Dec 2022 12:26:32 -0500 Received: from frasgout11.his.huawei.com (frasgout11.his.huawei.com [14.137.139.23]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2718561529; Wed, 7 Dec 2022 09:26:19 -0800 (PST) Received: from mail02.huawei.com (unknown [172.18.147.227]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4NS3t45s8mz9xqcF; Thu, 8 Dec 2022 01:19:08 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwD34m9YzJBjc9DJAA--.62662S8; Wed, 07 Dec 2022 18:25:56 +0100 (CET) From: Roberto Sassu To: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, song@kernel.org, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com, haoluo@google.com, jolsa@kernel.org, revest@chromium.org, jackmanb@chromium.org, mykolal@fb.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, shuah@kernel.org Cc: bpf@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Roberto Sassu Subject: [RFC][PATCH v2 6/7] selftests/bpf: Prevent positive ret values in test_lsm and verify_pkcs7_sig Date: Wed, 7 Dec 2022 18:24:33 +0100 Message-Id: <20221207172434.435893-7-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221207172434.435893-1-roberto.sassu@huaweicloud.com> References: <20221207172434.435893-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwD34m9YzJBjc9DJAA--.62662S8 X-Coremail-Antispam: 1UD129KBjvJXoW7uFy5Cw1UGrW3ZF13WFykXwb_yoW8ZFyfpF yvg3Z0krWSgF13XF17Cws7XF4fKFs7Xa4FyayxXry3Zwn7JryxXr48KrW5Wrn0krWF9r93 Zay2ga1avr18AaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPlb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26r4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrV C2j2WlYx0E2Ix0cI8IcVAFwI0_JrI_JrylYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE 7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262 kKe7AKxVW8ZVWrXwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s02 6c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GF v_WrylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVW8JVW5JwCI42IY6xIIjxv20xvE c7CjxVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aV AFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZF pf9x07j7GYLUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQATBF1jj4ZorQAAsk X-CFilter-Loop: Reflected Precedence: bulk List-ID: From: Roberto Sassu Modify test_lsm and verify_pkcs7_sig to ensure that they don't return positive values. Signed-off-by: Roberto Sassu --- tools/testing/selftests/bpf/progs/lsm.c | 4 ++++ .../selftests/bpf/progs/test_verify_pkcs7_sig.c | 11 +++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/bpf/progs/lsm.c b/tools/testing/selftests/bpf/progs/lsm.c index d8d8af623bc2..42252750d866 100644 --- a/tools/testing/selftests/bpf/progs/lsm.c +++ b/tools/testing/selftests/bpf/progs/lsm.c @@ -88,6 +88,10 @@ SEC("lsm/file_mprotect") int BPF_PROG(test_int_hook, struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot, int ret) { + /* file_mprotect hook must return zero or negative values. */ + if (ret > 0) + ret = -EINVAL; + if (ret != 0) 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 ce419304ff1f..d3cab4370f29 100644 --- a/tools/testing/selftests/bpf/progs/test_verify_pkcs7_sig.c +++ b/tools/testing/selftests/bpf/progs/test_verify_pkcs7_sig.c @@ -42,14 +42,14 @@ struct { char _license[] SEC("license") = "GPL"; SEC("lsm.s/bpf") -int BPF_PROG(bpf, int cmd, union bpf_attr *attr, unsigned int size) +s64 BPF_PROG(bpf, int cmd, union bpf_attr *attr, unsigned int size) { struct bpf_dynptr data_ptr, sig_ptr; struct data *data_val; struct bpf_key *trusted_keyring; __u32 pid; __u64 value; - int ret, zero = 0; + s64 ret, zero = 0; pid = bpf_get_current_pid_tgid() >> 32; if (pid != monitored_pid) @@ -86,5 +86,12 @@ int BPF_PROG(bpf, int cmd, union bpf_attr *attr, unsigned int size) bpf_key_put(trusted_keyring); + /* + * bpf hook must return zero or negative values, use s64 to propagate + * the bounds to R0. + */ + if (ret > 0) + return -EINVAL; + return ret; } From patchwork Wed Dec 7 17:24:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13067440 X-Patchwork-Delegate: paul@paul-moore.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B0028C47089 for ; Wed, 7 Dec 2022 17:27:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229962AbiLGR1S (ORCPT ); Wed, 7 Dec 2022 12:27:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33492 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229981AbiLGR0q (ORCPT ); Wed, 7 Dec 2022 12:26:46 -0500 Received: from frasgout13.his.huawei.com (frasgout13.his.huawei.com [14.137.139.46]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EC80A6D7C6; Wed, 7 Dec 2022 09:26:29 -0800 (PST) Received: from mail02.huawei.com (unknown [172.18.147.229]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4NS3tK3Vcyz9xHdQ; Thu, 8 Dec 2022 01:19:21 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwD34m9YzJBjc9DJAA--.62662S9; Wed, 07 Dec 2022 18:26:06 +0100 (CET) From: Roberto Sassu To: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, song@kernel.org, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com, haoluo@google.com, jolsa@kernel.org, revest@chromium.org, jackmanb@chromium.org, mykolal@fb.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, shuah@kernel.org Cc: bpf@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Roberto Sassu Subject: [RFC][PATCH v2 7/7] selftests/bpf: Change return value in test_libbpf_get_fd_by_id_opts.c Date: Wed, 7 Dec 2022 18:24:34 +0100 Message-Id: <20221207172434.435893-8-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221207172434.435893-1-roberto.sassu@huaweicloud.com> References: <20221207172434.435893-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwD34m9YzJBjc9DJAA--.62662S9 X-Coremail-Antispam: 1UD129KBjvJXoW7Kw15Ar4xtry3Cr17uFWUCFg_yoW8ArW5pF WrXw1YkFZYgr1xu3W7JFWDGFySkFyxZayUXFW8JryDZr18XF4DJr18KF1Yqr98Gr4vgwsa vr4xKrWYkr18CaUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPlb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26r4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrV C2j2WlYx0E2Ix0cI8IcVAFwI0_JrI_JrylYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE 7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262 kKe7AKxVW8ZVWrXwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s02 6c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GF v_WrylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVW8JVW5JwCI42IY6xIIjxv20xvE c7CjxVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aV AFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZF pf9x07j7GYLUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgATBF1jj4JqpAAAso X-CFilter-Loop: Reflected Precedence: bulk List-ID: From: Roberto Sassu In the no_alu32 version, the eBPF assembly looks like: 0: b7 00 00 00 00 00 00 00 r0 = 0 1: 79 12 00 00 00 00 00 00 r2 = *(u64 *)(r1 + 0) 2: 18 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r3 = 0 ll 4: 5d 32 04 00 00 00 00 00 if r2 != r3 goto +4 5: 79 10 08 00 00 00 00 00 r0 = *(u64 *)(r1 + 8) 6: 67 00 00 00 3e 00 00 00 r0 <<= 62 7: c7 00 00 00 3f 00 00 00 r0 s>>= 63 8: 57 00 00 00 f3 ff ff ff r0 &= -13 Unfortunately, ANDing of negative numbers is not yet supported in the verifier. As a consequence, current bounds are lost in the AND operation, resulting in estimating a positive return value, even if there isn't. For now, return -EPERM instead of -EACCES, to remove the AND operation and let the verifier know that the return value is legitimate (negative or zero). Signed-off-by: Roberto Sassu --- .../selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c b/tools/testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c index f5ac5f3e8919..a143dbbd5573 100644 --- a/tools/testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c +++ b/tools/testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c @@ -29,8 +29,13 @@ int BPF_PROG(check_access, struct bpf_map *map, fmode_t fmode) if (map != (struct bpf_map *)&data_input) return 0; + /* + * Prefer -EPERM to -EACCES to avoid ANDing negative numbers in the + * no_alu32 version, which results in the current register bounds to + * be lost. + */ if (fmode & FMODE_WRITE) - return -EACCES; + return -EPERM; return 0; }