On 3/19/2024 1:02 AM, Roberto Sassu wrote: > On Mon, 2024-03-18 at 09:52 -0700, Stanislav Fomichev wrote: >> On 03/16, Xu Kuohai wrote: >>> From: Xu Kuohai <xukuohai@huawei.com> >>> >>> A bpf prog returning positive number attached to file_alloc_security hook >>> will make kernel panic. >> >> I'll leave it up to KP. I remember there was a similar patch series in >> the past, but I have no state on why it was not accepted.. > > Yes, this one: > > v1: https://lore.kernel.org/bpf/20221115175652.3836811-1-roberto.sassu@huaweicloud.com/ > v2: https://lore.kernel.org/bpf/20221207172434.435893-1-roberto.sassu@huaweicloud.com/ > Hmm, these two series do address the same problem. Now I'm pretty sure I read your series last year, at least some of the patches, but I didn't think of it when I ran into this panic issue last week. Maybe it's because I does not fully understand it. > The selftests were failing, and I wasn't able to come up with a > solution on the verifier side. I see patch 5 goes in that direction, > and I remember there was related work in this area. > > (just saw Paul's answer, maybe the new KP's patch set also solves this) > > Roberto > >
On 3/19/2024 12:58 AM, Paul Moore wrote: > On Mon, Mar 18, 2024 at 12:52 PM Stanislav Fomichev <sdf@google.com> wrote: >> On 03/16, Xu Kuohai wrote: >>> From: Xu Kuohai <xukuohai@huawei.com> >>> >>> A bpf prog returning positive number attached to file_alloc_security hook >>> will make kernel panic. >> >> I'll leave it up to KP. I remember there was a similar patch series in >> the past, but I have no state on why it was not accepted.. > > I believe this is the patchset you are referring to: > > https://lore.kernel.org/linux-security-module/20240207124918.3498756-1-kpsingh@kernel.org > Thank you for the reply. IIUC, the above patchset is intended to reduce the indirect call overhead of bpf lsm. I have tested it, and the panic issue still exists with this patchset applied. > It wasn't that the patchset was accepted or rejected, it is still in > the review queue as there are higher priority items being kicked > around in the LSM space at the moment. It also wasn't a pure bug-fix > or feature patchset/patch, which muddied things a bit. >
On 3/18/2024 1:08 AM, Roberto Sassu wrote:
> On Sun, 2024-03-17 at 22:17 -0700, Eric Biggers wrote:
>> On Fri, Mar 15, 2024 at 08:35:48PM -0700, Fan Wu wrote:
>>> +config IPE_PROP_FS_VERITY
>>> + bool "Enable property for fs-verity files"
>>> + depends on FS_VERITY && FS_VERITY_BUILTIN_SIGNATURES
>>> + help
>>> + This option enables the usage of properties "fsverity_signature"
>>> + and "fsverity_digest". These properties evaluate to TRUE when
>>> + a file is fsverity enabled and with a signed digest
>>
>> Again: why would anyone care if there is a signature, if that signature is not
>> checked.
>>
>> I think you meant to write something like: "when a file is fsverity enabled and
>> has a valid builtin signature whose signing cert is in the .fs-verity keyring".
>
> I was also thinking the same. I didn't follow the recent development
> closely, but unless IPE locks somehow the .fs-verity keyring, the
> property you suggested would not be immutable. Meaning that someone can
> add/remove a key in that keyring, making the property true or false.
>
> Roberto
Yes, the .fs-verity keyring's mutability could affect the property's
immutability. However, we are not planing to "lock" the keyrings, but we
would like to use policies languages to express what certificate can be
trusted.
For example, we can have a rule like this:
#Certificate declaration
CERTIFICATE=MyCertificate CertThumbprint=DummyThumbprint
op=EXECUTE fsverity_signature=MyCertificate action=ALLOW
This will be our immediate next work after the initial version is accepted.
-Fan
On 3/17/2024 10:17 PM, Eric Biggers wrote:
> On Fri, Mar 15, 2024 at 08:35:48PM -0700, Fan Wu wrote:
>> +config IPE_PROP_FS_VERITY
>> + bool "Enable property for fs-verity files"
>> + depends on FS_VERITY && FS_VERITY_BUILTIN_SIGNATURES
>> + help
>> + This option enables the usage of properties "fsverity_signature"
>> + and "fsverity_digest". These properties evaluate to TRUE when
>> + a file is fsverity enabled and with a signed digest
>
> Again: why would anyone care if there is a signature, if that signature is not
> checked.
>
> I think you meant to write something like: "when a file is fsverity enabled and
> has a valid builtin signature whose signing cert is in the .fs-verity keyring".
>
> - Eric
Thanks for the suggestion. I agree this is a more accurate description.
I'll update the description to include these details.
-Fan
On Mon, 2024-03-18 at 09:52 -0700, Stanislav Fomichev wrote: > On 03/16, Xu Kuohai wrote: > > From: Xu Kuohai <xukuohai@huawei.com> > > > > A bpf prog returning positive number attached to file_alloc_security hook > > will make kernel panic. > > I'll leave it up to KP. I remember there was a similar patch series in > the past, but I have no state on why it was not accepted.. Yes, this one: v1: https://lore.kernel.org/bpf/20221115175652.3836811-1-roberto.sassu@huaweicloud.com/ v2: https://lore.kernel.org/bpf/20221207172434.435893-1-roberto.sassu@huaweicloud.com/ The selftests were failing, and I wasn't able to come up with a solution on the verifier side. I see patch 5 goes in that direction, and I remember there was related work in this area. (just saw Paul's answer, maybe the new KP's patch set also solves this) Roberto
On Mon, Mar 18, 2024 at 12:52 PM Stanislav Fomichev <sdf@google.com> wrote: > On 03/16, Xu Kuohai wrote: > > From: Xu Kuohai <xukuohai@huawei.com> > > > > A bpf prog returning positive number attached to file_alloc_security hook > > will make kernel panic. > > I'll leave it up to KP. I remember there was a similar patch series in > the past, but I have no state on why it was not accepted.. I believe this is the patchset you are referring to: https://lore.kernel.org/linux-security-module/20240207124918.3498756-1-kpsingh@kernel.org It wasn't that the patchset was accepted or rejected, it is still in the review queue as there are higher priority items being kicked around in the LSM space at the moment. It also wasn't a pure bug-fix or feature patchset/patch, which muddied things a bit. -- paul-moore.com
On 03/16, Xu Kuohai wrote:
> From: Xu Kuohai <xukuohai@huawei.com>
>
> A bpf prog returning positive number attached to file_alloc_security hook
> will make kernel panic.
I'll leave it up to KP. I remember there was a similar patch series in
the past, but I have no state on why it was not accepted..
On Tue, Mar 12, 2024 at 05:06:36PM +0000, Matt Bobrowski wrote: > Hey Christian, > > On Mon, Mar 11, 2024 at 01:00:56PM +0100, Christian Brauner wrote: > > On Fri, Mar 08, 2024 at 05:23:30PM -0800, Alexei Starovoitov wrote: > > > On Fri, Mar 8, 2024 at 2:36 AM Christian Brauner <brauner@kernel.org> wrote: > > > > > > > > > > > > These exports are specifically for an out-of-tree BPF LSM program that > > > > is not accessible to the public. The question in the other mail stands. > > > > > > The question was already answered. You just don't like the answer. > > > bpf progs are not equivalent to kernel modules. > > > They have completely different safety and visibility properties. > > > The safety part I already talked about. > > > Sounds like the visibility has to be explained. > > > Kernel modules are opaque binary blobs. > > > bpf programs are fully transparent. The intent is known > > > to the verifier and to anyone with understanding > > > of bpf assembly. > > > Those that cannot read bpf asm can read C source code that is > > > embedded in the bpf program in kernel memory. > > > It's not the same as "llvm-dwarfdump module.ko" on disk. > > > The bpf prog source code is loaded into the kernel > > > at program verification time for debugging and visibility reasons. > > > If there is a verifier bug and bpf manages to crash the kernel > > > vmcore will have relevant lines of program C source code right there. > > > > > > Hence out-of-tree or in-tree bpf makes no practical difference. > > > The program cannot hide its meaning and doesn't hamper debugging. > > > > > > Hence adding EXPORT_SYMBOL == Brace for impact! > > > Expect crashes, api misuse and what not. > > > > > > While adding bpf_kfunc is a nop for kernel development. > > > If kfunc is in the way of code refactoring it can be removed > > > (as we demonstrated several times). > > > A kfunc won't cause headaches for the kernel code it is > > > calling (assuming no verifier bugs). > > > If there is a bug it's on us to fix it as we demonstrated in the past. > > > For example: bpf_probe_read_kernel(). > > > It's a wrapper of copy_from_kernel_nofault() and over the years > > > bpf users hit various bugs in copy_from_kernel_nofault(), > > > reported them, and _bpf developers_ fixed them. > > > Though copy_from_kernel_nofault() is as generic as it can get > > > and the same bugs could have been reproduced without bpf > > > we took care of fixing these parts of the kernel. > > > > > > Look at path_put(). > > > It's EXPORT_SYMBOL and any kernel module can easily screw up > > > reference counting, so that sooner or later distro folks > > > will experience debug pains due to out-of-tree drivers. > > > > > > kfunc that calls path_put() won't have such consequences. > > > The verifier will prevent path_put() on a pointer that wasn't > > > acquired by the same bpf program. No support pains. > > > It's a nop for vfs folks. > > > > > > > > First of all, there is no such thing as get_task_fs_pwd/root > > > > > in the kernel. > > > > > > > > Yeah, we'd need specific helpers for a never seen before out-of-tree BPF > > > > LSM. I don't see how that's different from an out-of-tree kernel module. > > > > > > Sorry, but you don't seem to understand what bpf can and cannot do, > > > hence they look similar. > > > > Maybe. On the other hand you seem to ignore what I'm saying. You > > currently don't have a clear set of rules for when it's ok for someone > > to send patches and request access to bpf kfuncs to implement a new BPF > > program. This patchset very much illustrates this point. The safety > > properties of bpf don't matter for this. And again, your safety > > properties very much didn't protect you from your bpf_d_path() mess. > > > > We're not even clearly told where and how these helper are supposed to be > > used. That's not ok and will never be ok. As long as there are no clear > > criteria to operate under this is highly problematic. This may be fine > > from a bpf perspective and one can even understand why because that's > > apparently your model or promise to your users. But there's no reason to > > expect the same level of laxness from any of the subsystems you're > > requesting kfuncs from. > > You raise a completely fair point, and I truly do apologies for the > lack of context and in depth explanations around the specific > situations that the proposed BPF kfuncs are intended to be used > from. Admittedly, that's a failure on my part, and I can completely > understand why from a maintainers point of view there would be > reservations around acknowledging requests for adding such invisible > dependencies. Thanks for providing more background. > Now, I'm in a little bit of a tough situation as I'm unable to point > you to an open-source BPF LSM implementation that intends to make use > of such newly proposed BPF kfuncs. That's just an unfortunate > constraint and circumstance that I'm having to deal with, so I'm just > going to have to provide heavily redacted and incomplete example to > illustrate how these BPF kfuncs intend to be used from BPF LSM > programs that I personally work on here at Google. Notably though, the > contexts that I do share here may obviously be a nonholistic view on > how these newly introduced BPF kfuncs end up getting used in practice > by some other completely arbitrary open-source BPF LSM programs. I have to say that this to me is wild. Essentially we're supposed to allow access to our internal APIs based on internal use-cases that aren't public and likely never will be. If that's acceptable then I want bpf to document this in their kernel Documentation and submit this for review to the wider community.
On Wed, Mar 13, 2024 at 02:05:13PM -0700, Alexei Starovoitov wrote: > On Mon, Mar 11, 2024 at 5:01 AM Christian Brauner <brauner@kernel.org> wrote: > > > > > > > One can argue that get_mm_exe_file() is not exported, > > > > > but it's nothing but rcu_lock-wrap plus get_file_rcu() > > > > > which is EXPORT_SYMBOL. > > > > > > > > Oh, good spot. That's an accident. get_file_rcu() definitely shouldn't > > > > be exported. So that'll be removed asap. > > > > > > So, just to make a point that > > > "Included in that set are functions that aren't currently even > > > exported to modules" > > > you want to un-export get_file_rcu() ? > > > > No. The reason it was exported was because of the drm subsystem and we > > already quite disliked that. But it turned out that's not needed so in > > commit 61d4fb0b349e ("file, i915: fix file reference for > > mmap_singleton()") they were moved away from this helper. > > Arguably that commit 61d4fb0b349e should have had > Fixes: 0ede61d8589c ("file: convert to SLAB_TYPESAFE_BY_RCU") > i915 was buggy before you touched it > and safe_by_rcu exposed the bug. > I can see why you guys looked at it, saw issues, > and decided to look away. > Though your guess in commit 61d4fb0b349e > " > Now, there might be delays until > file->f_op->release::singleton_release() is called and > i915->gem.mmap_singleton is set to NULL. > " > feels unlikely. > I suspect release() delay cannot be that long to cause rcu stall. > In the log prior to the splat there are just two mmap related calls > from selftests in i915_gem_mman_live_selftests(): > i915: Running i915_gem_mman_live_selftests/igt_mmap_offset_exhaustion > i915: Running i915_gem_mman_live_selftests/igt_mmap > 1st mmap test passed, but 2nd failed. > So it looks like it's not a race, but an issue with cleanup in that driver. > And instead of getting to the bottom of the issue > you've decided to paper over with get_file_active(). > I agree with that trade-off. > But the bug in i915 is still there and it's probably an UAF. > get_file_active() is probably operating on a broken 'struct file' > that got to zero, but somehow it still around > or it's just a garbage memory and file->f_count > just happened to be zero. > > My point is that it's not ok to have such double standards. > On one side you're arguing that we shouldn't introduce kfunc: > +__bpf_kfunc struct file *bpf_get_task_exe_file(struct task_struct *task) > +{ > + return get_task_exe_file(task); > +} > that cleanly takes ref cnt on task->mm->exe_file and _not_ using lower > level get_file/get_file_rcu/get_file_active api-s directly which > are certainly problematic to expose anywhere, since safe_by_rcu > protocol is delicate. > > But on the other side there is buggy i915 that does > questionable dance with get_file_active(). > It's EXPORT_SYMBOL_GPL as well and out of tree driver can > ruin safe_by_rcu file properties with hard to debug consequences. You're lending strong support for my earlier point. Because this is a clear an example where a subsystem got access to a helper that it shouldn't have had access to. So we fixed the issue. But this whole polemic just illustrates that you simply didn't bother to understand how the code works. The way you talk about UAF together with SLAB_TYPESAFE_BY_RCU is telling. Please read the code instead of guessing. So the same way we don't have to take responsibility for bpf misunderstanding the expectations of d_path() we don't have to take responsibility for misusing an internal helper by another subsystem. So your argument here is moot at best and polemical and opportunistic at worst. It certainly doesn't illustrate what you think it does. And the above is fundamentally a suspiciously long sideshow. So let's get back to the core topic: Unless you document your rules when it's ok for a bpf program to come along and request access to internal apis patchsets such as this are not acceptable. > > > There is absolutely no way that any userspace will > > get access to such low-level helpers. They have zero business to be > > involved in the lifetimes of objects on this level just as no module has. > > correct, and kfuncs do not give bpf prog to do direct get_file*() access > because we saw how tricky safe_by_rcu is. > Hence kfuncs acquire file via get_task_exe_file or get_mm_exe_file > and release via fput. > That's the same pattern that security/tomoyo/util.c is doing: > exe_file = get_mm_exe_file(mm); > if (!exe_file) > return NULL; > > cp = tomoyo_realpath_from_path(&exe_file->f_path); > fput(exe_file); > > in bpf_lsm case it will be: > > exe_file = bpf_get_mm_exe_file(mm); > if (!exe_file) > // the verifier will enforce that bpf prog has this NULL check here > // because we annotate kfunc as: > BTF_ID_FLAGS(func, bpf_get_mm_exe_file, KF_ACQUIRE | KF_TRUSTED_ARGS | > KF_RET_NULL) > > bpf_path_d_path(&exe_file->f_path, ...); > bpf_put_file(exe_file); > // and the verifier will enforce that bpf_put_file() is called too. > // and there is no path out of this bpf program that can take file refcnt > // without releasing. > > So really these kfuncs are a nop from vfs pov. > If there is a bug in the verifier we will debug it and we will fix it. > > You keep saying that bpf_d_path() is a mess. > Right. It is a mess now and we're fixing it. > When it was introduced 4 years ago it was safe at that time. Uhm, no it was always sketchy. > The unrelated verifier "smartness" made it possible to use it in UAF. > We found the issue now and we're fixing it. > Over these years we didn't ask vfs folks to help fix such bugs, > and not asking for help now. > You're being cc-ed on the patches to be aware on how we plan to fix > this bpf_d_path() mess. If you have a viable alternative please suggest. The fix is to export a variant with trusted args. > As it stands the new kfuncs are clean and safe way to solve this mess. I will remind you of what you have been told in [1]: "No. It's not up to maintainers to suggest alternatives. Sometimes it's simply enough to explain *why* something isn't acceptable. A plain "no" without explanation isn't sufficient. NAKs need a good reason. But they don't need more than that. The onus of coming up with an acceptable solution is on the person who needs something new." You've been provided: a) good reasons why the patchset in it's current form isn't acceptable repeated multiple times b) support for exporting a variant of bpf_d_path() that is safe to use c) a request that all kfunc exports for the vfs will have to be located under fs/, not in kernel/bpf/ d) a path on how to move forward with additional kfunc requests: Clear and documented rules when it's ok for someone to come along and request access to bpf kfuncs when it's to be rejected and when it's ok to be supported. You repeatedly threatening to go over the heads of people will not make them more amenable to happily integrate with your subsystem. [1]: https://lore.kernel.org/all/CAHk-=whD2HMe4ja5nR6WWofUh3nLmhjoSPDvZm2-XMGjeie5Tg@mail.gmail.com
On Mon, 2024-03-18 at 04:38 -0500, Dr. Greg wrote: > Good morning Paul/Roberto, I hope this note finds your respective > weeks starting well, greetings to the wider security list as well. > > We ran into an issue, that seems to be secondary to the LSM/IMA > integration, in our TSEM port to the 6.8 kernel that would seem to be > relevant to other or future LSM's. > > It appears that the IMA/LSM work added the following code to the > security/security.c:security_inode_init_security() function: > > if (!blob_sizes.lbs_xattr_count) > return 0; > > Which denies access to the hook by an LSM that has registered a > handler for an event but that has not registered the use of extended > attributes through the LSM blob mechanism. This pre-supposes the > notion that all LSM's that may want to be notified of an inode > instantiation event will be using extended attributes. > > For example, in TSEM we use this hook to propagate task identity > ownership and inode instance information from the > security_inode_create hook into the TSEM inode security state > information. > > We 'fixed' the problem by requesting a single extended attribute > allocation for TSEM, but that seems inelegant in the larger picture, > given that a handler that wishes to use the hook in the absence of > extended attributes can use the hook and return EOPNOTSUPP with no ill > effects. Hi Greg I agree, it should not be needed. > We haven't had time to track down the involved code but a cursory > examination would seem to suggest that this also effectively denies > the ability to create an operational BPF hook for this handler. Given > that BPF is proposed as a mechanism to implement just any arbitrary > security policy, this would seem problematic, if it doesn't already > break current BPF LSM implementations that may have placed a handler > on this event. > > We could certainly roll a patch for consideration on how to address > this issue if that would be of assistance. At the very least the > documentation for the function no longer matches its operational > characteristics. I think the check above was just an optimization, but I agree you might do other tasks, other than just filling the xattrs slot. For me, it would not be really a problem to modify the code to invoke the inode_init_security hooks with xattrs set to NULL. I haven't found any counterargument, but will think some more. > Have a good week. You too! Roberto
[-- Attachment #1: Type: text/plain, Size: 3577 bytes --] Hi Mickaël, Günther, Sorry for the delay! On Thu, Mar 07, 2024 at 11:21:57AM +0100, Mickaël Salaün wrote: > CCing Alejandro > > On Tue, Feb 27, 2024 at 05:32:20PM +0100, Günther Noack wrote: > > On Tue, Feb 27, 2024 at 12:05:49PM +0100, Mickaël Salaün wrote: > > > Extend the kernel support section with one subsection for build time > > > configuration and another for boot time configuration. > > > > > > Extend the boot time subsection with a concrete example. > > > > > > Update the journalctl command to include the boot option. > > > > > > Cc: Günther Noack <gnoack@google.com> > > > Cc: Kees Cook <keescook@chromium.org> > > > Signed-off-by: Mickaël Salaün <mic@digikod.net> > > > --- > > > > > > Changes since v1: > > > * New patch, suggested by Kees Cook. > > > --- > > > Documentation/userspace-api/landlock.rst | 57 +++++++++++++++++++++--- > > > 1 file changed, 51 insertions(+), 6 deletions(-) [...] > > > + > > > + lsm=landlock,lockdown,yama,integrity,apparmor > > > + > > > +After a reboot, we can check that Landlock is up and running by looking at > > > +kernel logs: > > > + > > > +.. code-block:: console > > > + > > > + # dmesg | grep landlock || journalctl -kb -g landlock > > > + [ 0.000000] Command line: [...] lsm=landlock,lockdown,yama,integrity,apparmor > > > + [ 0.000000] Kernel command line: [...] lsm=landlock,lockdown,yama,integrity,apparmor > > > + [ 0.000000] LSM: initializing lsm=lockdown,capability,landlock,yama,integrity,apparmor > > > + [ 0.000000] landlock: Up and running. > > > + > > > +Note that according to the built time kernel configuration, > > > > s/built time/build time/ > > ^ > > OK Here, this should actually be "build-time" since it works as an adjective. > > > > > It feels like the phrase "according to" could be slightly more specific here. > > > > To paraphrase Alejandro Colomar, "Note that" is usually redundant. > > https://lore.kernel.org/all/0aafcdd6-4ac7-8501-c607-9a24a98597d7@gmail.com/ > > > > I'd suggest: > > > > The kernel may be configured at build time to always load the ``lockdown`` and > > ``capability`` LSMs. In that case, these LSMs will appear at the beginning of > > the ``LSM: initializing`` log line as well, even if they are not configured in > > the boot loader. LGTM > > OK, I integrated your suggestion. I guess `capability` is not really > considered an LSM but it would be too confusing and out of scope for an > user documentation to explain that. > > > > > > +``lockdown,capability,`` may always stay at the beginning of the ``LSM: > > > +initializing lsm=`` list even if they are not configured with the bootloader, > > > > Nit: The man pages spell this in two words as "boot loader". > > OK, I'll use "boot loader" too. > > > > > > > > +which is OK. > > > + > > > +Network support > > > +--------------- > > > + > > > To be able to explicitly allow TCP operations (e.g., adding a network rule with > > > ``LANDLOCK_ACCESS_NET_BIND_TCP``), the kernel must support TCP > > > (``CONFIG_INET=y``). Otherwise, sys_landlock_add_rule() returns an > > > > > > base-commit: b4007fd27206c478a4b76e299bddf4a71787f520 > > > -- > > > 2.44.0 > > > > > > > Reviewed-by: Günther Noack <gnoack@google.com> > > Thanks! Reviewed-by: Alejandro Colomar <alx@kernel.org> Have a lovely day! Alex -- <https://www.alejandro-colomar.es/> Looking for a remote C programming job at the moment. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --]
Good morning Paul/Roberto, I hope this note finds your respective weeks starting well, greetings to the wider security list as well. We ran into an issue, that seems to be secondary to the LSM/IMA integration, in our TSEM port to the 6.8 kernel that would seem to be relevant to other or future LSM's. It appears that the IMA/LSM work added the following code to the security/security.c:security_inode_init_security() function: if (!blob_sizes.lbs_xattr_count) return 0; Which denies access to the hook by an LSM that has registered a handler for an event but that has not registered the use of extended attributes through the LSM blob mechanism. This pre-supposes the notion that all LSM's that may want to be notified of an inode instantiation event will be using extended attributes. For example, in TSEM we use this hook to propagate task identity ownership and inode instance information from the security_inode_create hook into the TSEM inode security state information. We 'fixed' the problem by requesting a single extended attribute allocation for TSEM, but that seems inelegant in the larger picture, given that a handler that wishes to use the hook in the absence of extended attributes can use the hook and return EOPNOTSUPP with no ill effects. We haven't had time to track down the involved code but a cursory examination would seem to suggest that this also effectively denies the ability to create an operational BPF hook for this handler. Given that BPF is proposed as a mechanism to implement just any arbitrary security policy, this would seem problematic, if it doesn't already break current BPF LSM implementations that may have placed a handler on this event. We could certainly roll a patch for consideration on how to address this issue if that would be of assistance. At the very least the documentation for the function no longer matches its operational characteristics. Have a good week. As always, Dr. Greg The Quixote Project - Flailing at the Travails of Cybersecurity https://github.com/Quixote-Project
On Sun, 2024-03-17 at 22:17 -0700, Eric Biggers wrote:
> On Fri, Mar 15, 2024 at 08:35:48PM -0700, Fan Wu wrote:
> > +config IPE_PROP_FS_VERITY
> > + bool "Enable property for fs-verity files"
> > + depends on FS_VERITY && FS_VERITY_BUILTIN_SIGNATURES
> > + help
> > + This option enables the usage of properties "fsverity_signature"
> > + and "fsverity_digest". These properties evaluate to TRUE when
> > + a file is fsverity enabled and with a signed digest
>
> Again: why would anyone care if there is a signature, if that signature is not
> checked.
>
> I think you meant to write something like: "when a file is fsverity enabled and
> has a valid builtin signature whose signing cert is in the .fs-verity keyring".
I was also thinking the same. I didn't follow the recent development
closely, but unless IPE locks somehow the .fs-verity keyring, the
property you suggested would not be immutable. Meaning that someone can
add/remove a key in that keyring, making the property true or false.
Roberto
On Fri, Mar 15, 2024 at 08:35:47PM -0700, Fan Wu wrote: > fsverity represents a mechanism to support both integrity and > authenticity protection of a file, supporting both signed and unsigned > digests. > > An LSM which controls access to a resource based on authenticity and > integrity of said resource, can then use this data to make an informed > decision on the authorization (provided by the LSM's policy) of said > claim. > > This effectively allows the extension of a policy enforcement layer in > LSM for fsverity, allowing for more granular control of how a > particular authenticity claim can be used. For example, "all (built-in) > signed fsverity files should be allowed to execute, but only these > hashes are allowed to be loaded as kernel modules". > > This enforcement must be done in kernel space, as a userspace only > solution would fail a simple litmus test: Download a self-contained > malicious binary that never touches the userspace stack. This > binary would still be able to execute. > > This patch introduces a new security_inode_setintegrity() hook call in > fsverity to store the verified fsverity signature in the inode's LSM blobs. > The hook call is executed after fsverity_verify_signature(), ensuring that > the signature is verified against fsverity's keyring. > > The last commit in this patch set will add a link to the IPE documentation in > fsverity.rst. There are multiple types of fsverity signatures. Please make it clear which one you're talking about ("fsverity builtin signatures"). > diff --git a/Documentation/filesystems/fsverity.rst b/Documentation/filesystems/fsverity.rst > index 13e4b18e5dbb..708c79631f32 100644 > --- a/Documentation/filesystems/fsverity.rst > +++ b/Documentation/filesystems/fsverity.rst > @@ -461,7 +461,10 @@ Enabling this option adds the following: > > 3. A new sysctl "fs.verity.require_signatures" is made available. > When set to 1, the kernel requires that all verity files have a > - correctly signed digest as described in (2). > + correctly signed digest as described in (2). Note that verification > + happens as long as the file's signature exists regardless of the state of > + "fs.verity.require_signatures", and the IPE LSM relies on this behavior > + to save verified signature into LSM blobs. This probably should go in item (2) instead, as that already mentions the behavior when opening a file. > The data that the signature as described in (2) must be a signature of > is the fs-verity file digest in the following format:: > @@ -481,7 +484,7 @@ be carefully considered before using them: > > - Builtin signature verification does *not* make the kernel enforce > that any files actually have fs-verity enabled. Thus, it is not a > - complete authentication policy. Currently, if it is used, the only > + complete authentication policy. Currently, if it is used, one > way to complete the authentication policy is for trusted userspace > code to explicitly check whether files have fs-verity enabled with a > signature before they are accessed. (With > @@ -489,6 +492,11 @@ be carefully considered before using them: > enabled suffices.) But, in this case the trusted userspace code > could just store the signature alongside the file and verify it > itself using a cryptographic library, instead of using this feature. > + Another approach is to utilize built-in signature verification in > + conjunction with the IPE LSM, which supports defining > + a kernel-enforced, system-wide authentication policy that allows only > + files with an fs-verity signature enabled to perform certain operations, > + such as execution. Note that IPE doesn't require fs.verity.require_signatures=1. Make this a new paragraph. Also, the acronym "IPE" should be spelled out somewhere. IPE should be mentioned in the list in the "Use cases" section next to IMA, and it can be spelled out there. > +#ifdef CONFIG_FS_VERITY_BUILTIN_SIGNATURES > +static int fsverity_inode_setintegrity(struct inode *inode, > + const struct fsverity_descriptor *desc) > +{ > + return security_inode_setintegrity(inode, LSM_INTGR_FSV_SIG, > + desc->signature, > + le32_to_cpu(desc->sig_size)); > +} > +#else > +static inline int fsverity_inode_setintegrity(struct inode *inode, > + const struct fsverity_descriptor *desc) > +{ > + return 0; > +} > +#endif /* CONFIG_FS_VERITY_BUILTIN_SIGNATURES */ > + > /* > * Create a new fsverity_info from the given fsverity_descriptor (with optional > * appended builtin signature), and check the signature if present. The > * fsverity_descriptor must have already undergone basic validation. > */ > -struct fsverity_info *fsverity_create_info(const struct inode *inode, > +struct fsverity_info *fsverity_create_info(struct inode *inode, > struct fsverity_descriptor *desc) > { > struct fsverity_info *vi; > @@ -241,6 +258,11 @@ struct fsverity_info *fsverity_create_info(const struct inode *inode, > } > } > > + err = fsverity_inode_setintegrity(inode, desc); > + > + if (err) > + goto fail; Delete the blank line before 'if (err)' > diff --git a/fs/verity/signature.c b/fs/verity/signature.c > index 90c07573dd77..d4ed03a114e9 100644 > --- a/fs/verity/signature.c > +++ b/fs/verity/signature.c > @@ -41,7 +41,10 @@ static struct key *fsverity_keyring; > * @sig_size: size of signature in bytes, or 0 if no signature > * > * If the file includes a signature of its fs-verity file digest, verify it > - * against the certificates in the fs-verity keyring. > + * against the certificates in the fs-verity keyring. Note that verification > + * happens as long as the file's signature exists regardless of the state of > + * fsverity_require_signatures, and the IPE LSM relies on this behavior > + * to save the verified file signature of the file into security blobs. "save the verified file signature of the file into security blobs" isn't what IPE actually does, though. And even if it was, it would not explain why IPE expects the signature to be verified. > diff --git a/include/linux/security.h b/include/linux/security.h > index 0885866b261e..edd12c0a673a 100644 > --- a/include/linux/security.h > +++ b/include/linux/security.h > @@ -86,6 +86,7 @@ enum lsm_event { > enum lsm_intgr_type { > LSM_INTGR_DMV_SIG, > LSM_INTGR_DMV_ROOTHASH, > + LSM_INTGR_FSV_SIG, > __LSM_INTGR_MAX > }; These are hard to understand because they are abbreviated too much. And again, there are multiple type of fsverity signatures. How about: enum lsm_integrity_type { LSM_INTEGRITY_DM_VERITY_SIG, LSM_INTEGRITY_DM_VERITY_ROOT_HASH, LSM_INTEGRITY_FS_VERITY_BUILTIN_SIG, __LSM_INTEGRITY_MAX }; - Eric
On Fri, Mar 15, 2024 at 08:35:48PM -0700, Fan Wu wrote:
> +config IPE_PROP_FS_VERITY
> + bool "Enable property for fs-verity files"
> + depends on FS_VERITY && FS_VERITY_BUILTIN_SIGNATURES
> + help
> + This option enables the usage of properties "fsverity_signature"
> + and "fsverity_digest". These properties evaluate to TRUE when
> + a file is fsverity enabled and with a signed digest
Again: why would anyone care if there is a signature, if that signature is not
checked.
I think you meant to write something like: "when a file is fsverity enabled and
has a valid builtin signature whose signing cert is in the .fs-verity keyring".
- Eric
On Sun, Mar 17, 2024 at 8:29 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
> On 3/15/2024 8:35 PM, Fan Wu wrote:
> > This patch introduces a new hook to notify security system that the
> > content of initramfs has been unpacked into the rootfs.
> >
> > Upon receiving this notification, the security system can activate
> > a policy to allow only files that originated from the initramfs to
> > execute or load into kernel during the early stages of booting.
> >
> > This approach is crucial for minimizing the attack surface by
> > ensuring that only trusted files from the initramfs are operational
> > in the critical boot phase.
> >
> > Signed-off-by: Fan Wu <wufan@linux.microsoft.com>
> >
> > ---
> > v1-v11:
> > + Not present
> >
> > v12:
> > + Introduced
> >
> > v13:
> > + Rename the hook name to initramfs_populated()
> >
> > v14:
> > + No changes
> >
> > v15:
> > + No changes
> > ---
> > include/linux/lsm_hook_defs.h | 2 ++
> > include/linux/security.h | 8 ++++++++
> > init/initramfs.c | 3 +++
> > security/security.c | 10 ++++++++++
> > 4 files changed, 23 insertions(+)
> >
> > diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
> > index 334e00efbde4..7db99ae75651 100644
> > --- a/include/linux/lsm_hook_defs.h
> > +++ b/include/linux/lsm_hook_defs.h
> > @@ -450,3 +450,5 @@ 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)
> > #endif /* CONFIG_IO_URING */
> > +
> > +LSM_HOOK(void, LSM_RET_VOID, initramfs_populated, void)
>
> This is an awfully expensive way to set a flag. Adding a LSM hook list
> isn't free. Isn't there a way to capture this state change through one of
> the mount hooks?
Unfortunately no, the initramfs isn't mounted like a traditional
filesystem, it is "populated" by unpacking the cpio into the initramfs
at early boot. This LSM hook should be called exactly once during
boot, and the performance impact should be minimal; I should also be
wildly more performant than earlier revisions of this patchset that
required grabbing a single spinlock on every file access.
Of course if you have an idea on how this could be done
differently/better I think we're all open to new ideas ...
--
paul-moore.com
On 3/15/2024 8:35 PM, Fan Wu wrote: > This patch introduces a new hook to notify security system that the > content of initramfs has been unpacked into the rootfs. > > Upon receiving this notification, the security system can activate > a policy to allow only files that originated from the initramfs to > execute or load into kernel during the early stages of booting. > > This approach is crucial for minimizing the attack surface by > ensuring that only trusted files from the initramfs are operational > in the critical boot phase. > > Signed-off-by: Fan Wu <wufan@linux.microsoft.com> > > --- > v1-v11: > + Not present > > v12: > + Introduced > > v13: > + Rename the hook name to initramfs_populated() > > v14: > + No changes > > v15: > + No changes > --- > include/linux/lsm_hook_defs.h | 2 ++ > include/linux/security.h | 8 ++++++++ > init/initramfs.c | 3 +++ > security/security.c | 10 ++++++++++ > 4 files changed, 23 insertions(+) > > diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h > index 334e00efbde4..7db99ae75651 100644 > --- a/include/linux/lsm_hook_defs.h > +++ b/include/linux/lsm_hook_defs.h > @@ -450,3 +450,5 @@ 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) > #endif /* CONFIG_IO_URING */ > + > +LSM_HOOK(void, LSM_RET_VOID, initramfs_populated, void) This is an awfully expensive way to set a flag. Adding a LSM hook list isn't free. Isn't there a way to capture this state change through one of the mount hooks? > diff --git a/include/linux/security.h b/include/linux/security.h > index 41a8f667bdfa..14fff542f2e3 100644 > --- a/include/linux/security.h > +++ b/include/linux/security.h > @@ -2255,4 +2255,12 @@ static inline int security_uring_cmd(struct io_uring_cmd *ioucmd) > #endif /* CONFIG_SECURITY */ > #endif /* CONFIG_IO_URING */ > > +#ifdef CONFIG_SECURITY > +extern void security_initramfs_populated(void); > +#else > +static inline void security_initramfs_populated(void) > +{ > +} > +#endif /* CONFIG_SECURITY */ > + > #endif /* ! __LINUX_SECURITY_H */ > diff --git a/init/initramfs.c b/init/initramfs.c > index da79760b8be3..cc9115117896 100644 > --- a/init/initramfs.c > +++ b/init/initramfs.c > @@ -17,6 +17,7 @@ > #include <linux/namei.h> > #include <linux/init_syscalls.h> > #include <linux/umh.h> > +#include <linux/security.h> > > #include "do_mounts.h" > > @@ -719,6 +720,8 @@ static void __init do_populate_rootfs(void *unused, async_cookie_t cookie) > #endif > } > > + security_initramfs_populated(); > + > done: > /* > * If the initrd region is overlapped with crashkernel reserved region, > diff --git a/security/security.c b/security/security.c > index 287bfac6b471..b10230c51c0b 100644 > --- a/security/security.c > +++ b/security/security.c > @@ -5675,3 +5675,13 @@ int security_uring_cmd(struct io_uring_cmd *ioucmd) > return call_int_hook(uring_cmd, ioucmd); > } > #endif /* CONFIG_IO_URING */ > + > +/** > + * security_initramfs_populated() - Notify LSMs that initramfs has been loaded > + * > + * Tells the LSMs the initramfs has been unpacked into the rootfs. > + */ > +void security_initramfs_populated(void) > +{ > + call_void_hook(initramfs_populated); > +}
On Sat, Mar 16, 2024 at 6:47 AM Dr. Greg <greg@enjellic.com> wrote:
>
> Good morning Paul, I hope your weekend is going well or your week is
> starting well, whenever this e-mail finds you.
>
> We've been waiting for the release of 6.8 for the V3 release of TSEM.
> TSEM seems to be co-habitating with it reasonably well, modulo some
> atomic structure magazine refill issues we are sorting out that appear
> to be caused by workqueue scheduling latency differences between this
> kernel and older kernels, so we are getting ready to push the V3
> release.
>
> Casey has previously raised an issue with the fact that we used a
> single include file, tsem.h, for all of the entities that are global
> to the various compilation units. We placed that file first in the
> patch series so that it could be referenced for review as the
> individual compilation units were added ...
Considering that there are still a number of concerns around the
design of TSEM I wouldn't worry too much about the smaller, easier to
change implementation details, like header file organization at this
point in time. If you've got something that is functional, that
should be sufficient. We still need to sort out if the basic design
and TSEM concepts are acceptable upstream.
--
paul-moore.com
On 3/15/24 3:16 PM, Andrii Nakryiko wrote: > On Fri, Mar 15, 2024 at 11:41?AM Jens Axboe <axboe@kernel.dk> wrote: >> >> On 3/15/24 10:45 AM, Andrii Nakryiko wrote: >>>> +/** >>>> + * ns_capable_any - Determine if the current task has one of two superior capabilities in effect >>>> + * @ns: The usernamespace we want the capability in >>>> + * @cap1: The capabilities to be tested for first >>>> + * @cap2: The capabilities to be tested for secondly >>>> + * >>>> + * Return true if the current task has at least one of the two given superior >>>> + * capabilities currently available for use, false if not. >>>> + * >>>> + * In contrast to or'ing capable() this call will create exactly one audit >>>> + * message, either for @cap1, if it is granted or both are not permitted, >>>> + * or @cap2, if it is granted while the other one is not. >>>> + * >>>> + * The capabilities should be ordered from least to most invasive, i.e. CAP_SYS_ADMIN last. >>>> + * >>>> + * This sets PF_SUPERPRIV on the task if the capability is available on the >>>> + * assumption that it's about to be used. >>>> + */ >>>> +bool ns_capable_any(struct user_namespace *ns, int cap1, int cap2) >>>> +{ >>>> + if (cap1 == cap2) >>>> + return ns_capable(ns, cap1); >>>> + >>>> + if (ns_capable_noauditondeny(ns, cap1)) >>>> + return true; >>>> + >>>> + if (ns_capable_noauditondeny(ns, cap2)) >>>> + return true; >>>> + >>>> + return ns_capable(ns, cap1); >>> >>> this will incur an extra capable() check (with all the LSMs involved, >>> etc), and so for some cases where capability is expected to not be >>> present, this will be a regression. Is there some way to not redo the >>> check, but just audit the failure? At this point we do know that cap1 >>> failed before, so might as well just log that. >> >> Not sure why that's important - if it's a failure case, and any audit >> failure should be, then why would we care if that's now doing a bit of >> extra work? > > Lack of capability doesn't necessarily mean "failure". E.g., in FUSE > there are at least few places where the code checks > capable(CAP_SYS_ADMIN), and based on that decides on some limit values > or extra checks. So if !capable(CAP_SYS_ADMIN), operation doesn't > necessarily fail outright, it just has some more restricted resources > or something. > > Luckily in FUSE's case it's singular capable() check, so capable_any() > won't incur extra overhead. But I was just wondering if it would be > possible to avoid this with capable_any() as well, so that no one has > to do these trade-offs. That's certainly a special and odd case, as most other cases really would be of the: if (capable(SOMETHING)) return -EFAUL; Might make more sense to special case the FUSE thing then, or provide a cheap way for it to do what it needs to do. I really don't think that kind of: if (capable(SOMETHING)) do something since I can else bummer, do something else then is a common occurrence. > We also had cases in production of some BPF applications tracing > cap_capable() calls, so each extra triggering of it would be a bit of > added overhead, as a general rule. > > Having said the above, I do like capable_any() changes (which is why I > acked BPF side of things). Yes, the BPF tracking capable in production is a pain in the butt, as it slows down any valid fast path capable checking by a substantial amount. We've had to work around that on the block side, unfortunately. These are obviously cases where you expect success, and any failure is permanent as far as that operation goes. -- Jens Axboe
From: Xu Kuohai <xukuohai@huawei.com> A bpf prog returning positive number attached to file_alloc_security hook will make kernel panic. The reason is that the positive number returned by bpf prog is not a valid errno, and could not be filtered out with IS_ERR which is used by the file system to check errors. As a result, the file system uses this positive number as file pointer, causing panic. Considering that hook file_alloc_security never returned positive number before bpf lsm was introduced, and other bpf lsm hooks may have the same problem, this patch adds lsm return value check in bpf verifier to ensure no unpredicted values will be returned by lsm bpf prog. Fixes: 520b7aa00d8c ("bpf: lsm: Initialize the BPF LSM hooks") Reported-by: Xin Liu <liuxin350@huawei.com> Signed-off-by: Xu Kuohai <xukuohai@huawei.com> --- include/linux/bpf.h | 1 + kernel/bpf/btf.c | 5 +++- kernel/bpf/verifier.c | 57 +++++++++++++++++++++++++++++++++++++------ 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 4f20f62f9d63..aac92857a5a5 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -917,6 +917,7 @@ struct bpf_insn_access_aux { }; }; struct bpf_verifier_log *log; /* for verbose logs */ + bool is_retval; /* is accessing function return value ? */ }; static inline void diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 90c4a32d89ff..d593684d80c6 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -6227,8 +6227,11 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type, if (arg == nr_args) { switch (prog->expected_attach_type) { - case BPF_LSM_CGROUP: case BPF_LSM_MAC: + /* mark we are accessing the return value */ + info->is_retval = true; + fallthrough; + case BPF_LSM_CGROUP: case BPF_TRACE_FEXIT: /* When LSM programs are attached to void LSM hooks * they use FEXIT trampolines and when attached to diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 63749ad5ac6b..c3387357bc0d 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -2325,6 +2325,25 @@ static void mark_reg_unknown(struct bpf_verifier_env *env, __mark_reg_unknown(env, regs + regno); } +static int __mark_reg_s32_range(struct bpf_verifier_env *env, + struct bpf_reg_state *regs, + u32 regno, + s32 s32_min, + s32 s32_max) +{ + struct bpf_reg_state *reg = regs + regno; + + reg->s32_min_value = max_t(s32, reg->s32_min_value, s32_min); + reg->s32_max_value = min_t(s32, reg->s32_max_value, s32_max); + + reg->smin_value = max_t(s64, reg->smin_value, s32_min); + reg->smax_value = min_t(s64, reg->smax_value, s32_max); + + reg_bounds_sync(reg); + + return reg_bounds_sanity_check(env, reg, "s32_range"); +} + static void __mark_reg_not_init(const struct bpf_verifier_env *env, struct bpf_reg_state *reg) { @@ -5557,11 +5576,12 @@ static int check_packet_access(struct bpf_verifier_env *env, u32 regno, int off, /* check access to 'struct bpf_context' fields. Supports fixed offsets only */ static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off, int size, enum bpf_access_type t, enum bpf_reg_type *reg_type, - struct btf **btf, u32 *btf_id) + struct btf **btf, u32 *btf_id, bool *is_retval) { struct bpf_insn_access_aux info = { .reg_type = *reg_type, .log = &env->log, + .is_retval = false, }; if (env->ops->is_valid_access && @@ -5574,6 +5594,7 @@ static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off, * type of narrower access. */ *reg_type = info.reg_type; + *is_retval = info.is_retval; if (base_type(*reg_type) == PTR_TO_BTF_ID) { *btf = info.btf; @@ -6715,6 +6736,17 @@ static int check_stack_access_within_bounds( return grow_stack_state(env, state, -min_off /* size */); } +static bool get_func_retval_range(struct bpf_prog *prog, + struct bpf_retval_range *range) +{ + if (prog->type == BPF_PROG_TYPE_LSM && + prog->expected_attach_type == BPF_LSM_MAC && + !bpf_lsm_get_retval_range(prog, range)) { + return true; + } + return false; +} + /* check whether memory at (regno + off) is accessible for t = (read | write) * if t==write, value_regno is a register which value is stored into memory * if t==read, value_regno is a register which will receive the value from memory @@ -6819,6 +6851,8 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn if (!err && value_regno >= 0 && (t == BPF_READ || rdonly_mem)) mark_reg_unknown(env, regs, value_regno); } else if (reg->type == PTR_TO_CTX) { + bool is_retval = false; + struct bpf_retval_range range; enum bpf_reg_type reg_type = SCALAR_VALUE; struct btf *btf = NULL; u32 btf_id = 0; @@ -6834,7 +6868,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn return err; err = check_ctx_access(env, insn_idx, off, size, t, ®_type, &btf, - &btf_id); + &btf_id, &is_retval); if (err) verbose_linfo(env, insn_idx, "; "); if (!err && t == BPF_READ && value_regno >= 0) { @@ -6843,7 +6877,14 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn * case, we know the offset is zero. */ if (reg_type == SCALAR_VALUE) { - mark_reg_unknown(env, regs, value_regno); + if (is_retval && get_func_retval_range(env->prog, &range)) { + err = __mark_reg_s32_range(env, regs, value_regno, + range.minval, range.maxval); + if (err) + return err; + } else { + mark_reg_unknown(env, regs, value_regno); + } } else { mark_reg_known_zero(env, regs, value_regno); @@ -15466,10 +15507,12 @@ static int check_return_code(struct bpf_verifier_env *env, int regno, const char case BPF_PROG_TYPE_LSM: if (env->prog->expected_attach_type != BPF_LSM_CGROUP) { - /* Regular BPF_PROG_TYPE_LSM programs can return - * any value. - */ - return 0; + /* no range found, any return value is allowed */ + if (!get_func_retval_range(env->prog, &range)) + return 0; + /* no restricted range, any return value is allowed */ + if (range.minval == S32_MIN && range.maxval == S32_MAX) + return 0; } if (!env->prog->aux->attach_func_proto->type) { /* Make sure programs that attach to void -- 2.30.2
From: Xu Kuohai <xukuohai@huawei.com> Add function to read lsm hook return value range. The following patch will use this information to check lsm hook return values in bpf verifier. Signed-off-by: Xu Kuohai <xukuohai@huawei.com> --- include/linux/bpf_lsm.h | 8 ++++++ kernel/bpf/bpf_lsm.c | 56 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h index 1de7ece5d36d..e51c042abf43 100644 --- a/include/linux/bpf_lsm.h +++ b/include/linux/bpf_lsm.h @@ -9,6 +9,7 @@ #include <linux/sched.h> #include <linux/bpf.h> +#include <linux/bpf_verifier.h> #include <linux/lsm_hooks.h> #ifdef CONFIG_BPF_LSM @@ -45,6 +46,8 @@ void bpf_inode_storage_free(struct inode *inode); void bpf_lsm_find_cgroup_shim(const struct bpf_prog *prog, bpf_func_t *bpf_func); +int bpf_lsm_get_retval_range(const struct bpf_prog *prog, + struct bpf_retval_range *range); #else /* !CONFIG_BPF_LSM */ static inline bool bpf_lsm_is_sleepable_hook(u32 btf_id) @@ -78,6 +81,11 @@ static inline void bpf_lsm_find_cgroup_shim(const struct bpf_prog *prog, { } +static inline int bpf_lsm_get_retval_range(const struct bpf_prog *prog, + struct bpf_retval_range *range) +{ + return -EOPNOTSUPP; +} #endif /* CONFIG_BPF_LSM */ #endif /* _LINUX_BPF_LSM_H */ diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c index ee9d1a795334..7b4611fd3a37 100644 --- a/kernel/bpf/bpf_lsm.c +++ b/kernel/bpf/bpf_lsm.c @@ -11,7 +11,6 @@ #include <linux/lsm_hooks.h> #include <linux/bpf_lsm.h> #include <linux/kallsyms.h> -#include <linux/bpf_verifier.h> #include <net/bpf_sk_storage.h> #include <linux/bpf_local_storage.h> #include <linux/btf_ids.h> @@ -40,6 +39,31 @@ noinline RET bpf_lsm_##NAME(__VA_ARGS__) \ #undef LSM_RET_INT #undef LSM_RET_VOID +struct lsm_retval_desc { + unsigned long func_addr; + int minval; + int maxval; +}; + +#define LSM_RET_INT_ERRNO -MAX_ERRNO, 0 +#define LSM_RET_INT_ANY INT_MIN, INT_MAX +#define LSM_RET_INT(defval, range_desc) LSM_RET_INT_##range_desc + +#define LSM_HOOK_RETVAL_int(NAME, ...) \ +{ (unsigned long)&bpf_lsm_##NAME, __VA_ARGS__ }, + +#define LSM_HOOK_RETVAL_void(NAME, ...) + +#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ +LSM_HOOK_RETVAL_##RET(NAME, DEFAULT) + +static struct lsm_retval_desc lsm_retvalues[] = { +#include <linux/lsm_hook_defs.h> +}; +#undef LSM_HOOK +#undef LSM_RET_INT +#undef LSM_RET_VOID + #define LSM_HOOK(RET, DEFAULT, NAME, ...) BTF_ID(func, bpf_lsm_##NAME) BTF_SET_START(bpf_lsm_hooks) #include <linux/lsm_hook_defs.h> @@ -399,3 +423,33 @@ const struct bpf_verifier_ops lsm_verifier_ops = { .get_func_proto = bpf_lsm_func_proto, .is_valid_access = btf_ctx_access, }; + +static struct lsm_retval_desc *find_retval_desc(const char *func_name) +{ + unsigned long addr; + struct lsm_retval_desc *desc; + + addr = kallsyms_lookup_name(func_name); + for (unsigned int i = 0U; i < ARRAY_SIZE(lsm_retvalues); i++) { + desc = &lsm_retvalues[i]; + if (addr == desc->func_addr) + return desc; + } + + return NULL; +} + +int bpf_lsm_get_retval_range(const struct bpf_prog *prog, + struct bpf_retval_range *retval_range) +{ + struct lsm_retval_desc *desc; + + desc = find_retval_desc(prog->aux->attach_func_name); + if (desc == NULL) + return -ENODEV; + + retval_range->minval = desc->minval; + retval_range->maxval = desc->maxval; + + return 0; +} -- 2.30.2
From: Xu Kuohai <xukuohai@huawei.com> After checking lsm hook return range in verifier, the test case "test_progs -t test_lsm" failed, and the failure log says: libbpf: prog 'test_int_hook': BPF program load failed: Invalid argument libbpf: prog 'test_int_hook': -- BEGIN PROG LOAD LOG -- 0: R1=ctx() R10=fp0 ; int BPF_PROG(test_int_hook, struct vm_area_struct *vma, @ lsm.c:89 0: (79) r0 = *(u64 *)(r1 +24) ; R0_w=scalar(smin=smin32=-4095,smax=smax32=0) R1=ctx() [...] 24: (b4) w0 = -1 ; R0_w=0xffffffff ; int BPF_PROG(test_int_hook, struct vm_area_struct *vma, @ lsm.c:89 25: (95) exit At program exit the register R0 has smin=4294967295 smax=4294967295 should have been in [-4095, 0] It can be seen that instruction "w0 = -1" zero extended -1 to 64-bit register r0, setting both smin and smax values of r0 to 4294967295. This resulted in a false reject when r0 was checked with range [-4095, 0]. Given bpf_retval_range is a 32-bit range, this patch fixes it by changing the compare between r0 and return range from 64-bit operation to 32-bit operation. Fixes: 8fa4ecd49b81 ("bpf: enforce exact retval range on subprog/callback exit") Signed-off-by: Xu Kuohai <xukuohai@huawei.com> --- kernel/bpf/verifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index c3387357bc0d..36cd13982926 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -9864,7 +9864,7 @@ static bool in_rbtree_lock_required_cb(struct bpf_verifier_env *env) static bool retval_range_within(struct bpf_retval_range range, const struct bpf_reg_state *reg) { - return range.minval <= reg->smin_value && reg->smax_value <= range.maxval; + return range.minval <= reg->s32_min_value && reg->s32_max_value <= range.maxval; } static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx) -- 2.30.2
From: Xu Kuohai <xukuohai@huawei.com> Add return value descriptions for lsm hook. Two integer ranges are added: 1. ERRNO: Integer between -MAX_ERRNO and 0, including -MAX_ERRNO and 0. 2. ANY: Any integer Signed-off-by: Xu Kuohai <xukuohai@huawei.com> --- include/linux/lsm_hook_defs.h | 431 +++++++++++++++++----------------- kernel/bpf/bpf_lsm.c | 2 +- security/security.c | 2 +- 3 files changed, 218 insertions(+), 217 deletions(-) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 22b64b15faa8..f6a744910aa4 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -18,419 +18,420 @@ * The macro LSM_HOOK is used to define the data structures required by * the LSM framework using the pattern: * - * LSM_HOOK(<return_type>, <default_value>, <hook_name>, args...) + * LSM_HOOK(<return_type>, <return_description>, <hook_name>, args...) * * struct security_hook_heads { - * #define LSM_HOOK(RET, DEFAULT, NAME, ...) struct hlist_head NAME; + * #define LSM_HOOK(RET, RETVAL_DESC, NAME, ...) struct hlist_head NAME; * #include <linux/lsm_hook_defs.h> * #undef LSM_HOOK * }; */ -LSM_HOOK(int, LSM_RET_INT(0), binder_set_context_mgr, const struct cred *mgr) -LSM_HOOK(int, LSM_RET_INT(0), binder_transaction, const struct cred *from, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), binder_set_context_mgr, const struct cred *mgr) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), binder_transaction, const struct cred *from, const struct cred *to) -LSM_HOOK(int, LSM_RET_INT(0), binder_transfer_binder, const struct cred *from, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), binder_transfer_binder, const struct cred *from, const struct cred *to) -LSM_HOOK(int, LSM_RET_INT(0), binder_transfer_file, const struct cred *from, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), binder_transfer_file, const struct cred *from, const struct cred *to, const struct file *file) -LSM_HOOK(int, LSM_RET_INT(0), ptrace_access_check, struct task_struct *child, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), ptrace_access_check, struct task_struct *child, unsigned int mode) -LSM_HOOK(int, LSM_RET_INT(0), ptrace_traceme, struct task_struct *parent) -LSM_HOOK(int, LSM_RET_INT(0), capget, const struct task_struct *target, kernel_cap_t *effective, - kernel_cap_t *inheritable, kernel_cap_t *permitted) -LSM_HOOK(int, LSM_RET_INT(0), capset, struct cred *new, const struct cred *old, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), ptrace_traceme, struct task_struct *parent) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), capget, const struct task_struct *target, + kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, LSM_RET_INT(0), capable, const struct cred *cred, struct user_namespace *ns, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), capable, const struct cred *cred, struct user_namespace *ns, int cap, unsigned int opts) -LSM_HOOK(int, LSM_RET_INT(0), quotactl, int cmds, int type, int id, const struct super_block *sb) -LSM_HOOK(int, LSM_RET_INT(0), quota_on, struct dentry *dentry) -LSM_HOOK(int, LSM_RET_INT(0), syslog, int type) -LSM_HOOK(int, LSM_RET_INT(0), settime, const struct timespec64 *ts, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), quotactl, int cmds, int type, int id, + const struct super_block *sb) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), quota_on, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), syslog, int type) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), settime, const struct timespec64 *ts, const struct timezone *tz) -LSM_HOOK(int, LSM_RET_INT(1), vm_enough_memory, struct mm_struct *mm, long pages) -LSM_HOOK(int, LSM_RET_INT(0), bprm_creds_for_exec, struct linux_binprm *bprm) -LSM_HOOK(int, LSM_RET_INT(0), bprm_creds_from_file, struct linux_binprm *bprm, +LSM_HOOK(int, LSM_RET_INT(1, ANY), vm_enough_memory, struct mm_struct *mm, long pages) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), bprm_creds_for_exec, struct linux_binprm *bprm) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), bprm_creds_from_file, struct linux_binprm *bprm, const struct file *file) -LSM_HOOK(int, LSM_RET_INT(0), bprm_check_security, struct linux_binprm *bprm) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), bprm_check_security, struct linux_binprm *bprm) LSM_HOOK(void, LSM_RET_VOID, bprm_committing_creds, const struct linux_binprm *bprm) LSM_HOOK(void, LSM_RET_VOID, bprm_committed_creds, const struct linux_binprm *bprm) -LSM_HOOK(int, LSM_RET_INT(0), fs_context_submount, struct fs_context *fc, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), fs_context_submount, struct fs_context *fc, struct super_block *reference) -LSM_HOOK(int, LSM_RET_INT(0), fs_context_dup, struct fs_context *fc, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), fs_context_dup, struct fs_context *fc, struct fs_context *src_sc) -LSM_HOOK(int, LSM_RET_INT(-ENOPARAM), fs_context_parse_param, struct fs_context *fc, +LSM_HOOK(int, LSM_RET_INT(-ENOPARAM, ERRNO), fs_context_parse_param, struct fs_context *fc, struct fs_parameter *param) -LSM_HOOK(int, LSM_RET_INT(0), sb_alloc_security, struct super_block *sb) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, LSM_RET_INT(0), sb_eat_lsm_opts, char *orig, void **mnt_opts) -LSM_HOOK(int, LSM_RET_INT(0), sb_mnt_opts_compat, struct super_block *sb, void *mnt_opts) -LSM_HOOK(int, LSM_RET_INT(0), sb_remount, struct super_block *sb, void *mnt_opts) -LSM_HOOK(int, LSM_RET_INT(0), sb_kern_mount, const struct super_block *sb) -LSM_HOOK(int, LSM_RET_INT(0), sb_show_options, struct seq_file *m, struct super_block *sb) -LSM_HOOK(int, LSM_RET_INT(0), sb_statfs, struct dentry *dentry) -LSM_HOOK(int, LSM_RET_INT(0), sb_mount, const char *dev_name, const struct path *path, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), sb_eat_lsm_opts, char *orig, void **mnt_opts) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), sb_mnt_opts_compat, struct super_block *sb, void *mnt_opts) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), sb_remount, struct super_block *sb, void *mnt_opts) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), sb_kern_mount, const struct super_block *sb) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), sb_show_options, struct seq_file *m, struct super_block *sb) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), sb_statfs, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), sb_mount, const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data) -LSM_HOOK(int, LSM_RET_INT(0), sb_umount, struct vfsmount *mnt, int flags) -LSM_HOOK(int, LSM_RET_INT(0), sb_pivotroot, const struct path *old_path, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), sb_umount, struct vfsmount *mnt, int flags) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), sb_pivotroot, const struct path *old_path, const struct path *new_path) -LSM_HOOK(int, LSM_RET_INT(0), sb_set_mnt_opts, struct super_block *sb, void *mnt_opts, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), sb_set_mnt_opts, struct super_block *sb, void *mnt_opts, unsigned long kern_flags, unsigned long *set_kern_flags) -LSM_HOOK(int, LSM_RET_INT(0), sb_clone_mnt_opts, const struct super_block *oldsb, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, LSM_RET_INT(0), move_mount, const struct path *from_path, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), move_mount, const struct path *from_path, const struct path *to_path) -LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP), dentry_init_security, struct dentry *dentry, +LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP, ERRNO), dentry_init_security, struct dentry *dentry, int mode, const struct qstr *name, const char **xattr_name, void **ctx, u32 *ctxlen) -LSM_HOOK(int, LSM_RET_INT(0), dentry_create_files_as, struct dentry *dentry, int mode, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, LSM_RET_INT(0), path_unlink, const struct path *dir, struct dentry *dentry) -LSM_HOOK(int, LSM_RET_INT(0), path_mkdir, const struct path *dir, struct dentry *dentry, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), path_unlink, const struct path *dir, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), path_mkdir, const struct path *dir, struct dentry *dentry, umode_t mode) -LSM_HOOK(int, LSM_RET_INT(0), path_rmdir, const struct path *dir, struct dentry *dentry) -LSM_HOOK(int, LSM_RET_INT(0), path_mknod, const struct path *dir, struct dentry *dentry, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), path_rmdir, const struct path *dir, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), path_mknod, const struct path *dir, struct dentry *dentry, umode_t mode, unsigned int dev) -LSM_HOOK(int, LSM_RET_INT(0), path_truncate, const struct path *path) -LSM_HOOK(int, LSM_RET_INT(0), path_symlink, const struct path *dir, struct dentry *dentry, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), path_truncate, const struct path *path) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), path_symlink, const struct path *dir, struct dentry *dentry, const char *old_name) -LSM_HOOK(int, LSM_RET_INT(0), path_link, struct dentry *old_dentry, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), path_link, struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry) -LSM_HOOK(int, LSM_RET_INT(0), path_rename, const struct path *old_dir, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, LSM_RET_INT(0), path_chmod, const struct path *path, umode_t mode) -LSM_HOOK(int, LSM_RET_INT(0), path_chown, const struct path *path, kuid_t uid, kgid_t gid) -LSM_HOOK(int, LSM_RET_INT(0), path_chroot, const struct path *path) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), path_chmod, const struct path *path, umode_t mode) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), path_chown, const struct path *path, kuid_t uid, kgid_t gid) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), path_chroot, const struct path *path) #endif /* CONFIG_SECURITY_PATH */ /* Needed for inode based security check */ -LSM_HOOK(int, LSM_RET_INT(0), path_notify, const struct path *path, u64 mask, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), path_notify, const struct path *path, u64 mask, unsigned int obj_type) -LSM_HOOK(int, LSM_RET_INT(0), inode_alloc_security, struct inode *inode) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_alloc_security, struct inode *inode) LSM_HOOK(void, LSM_RET_VOID, inode_free_security, struct inode *inode) -LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP), inode_init_security, struct inode *inode, +LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP, ERRNO), inode_init_security, struct inode *inode, struct inode *dir, const struct qstr *qstr, struct xattr *xattrs, int *xattr_count) -LSM_HOOK(int, LSM_RET_INT(0), inode_init_security_anon, struct inode *inode, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_init_security_anon, struct inode *inode, const struct qstr *name, const struct inode *context_inode) -LSM_HOOK(int, LSM_RET_INT(0), inode_create, struct inode *dir, struct dentry *dentry, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_create, struct inode *dir, struct dentry *dentry, umode_t mode) -LSM_HOOK(int, LSM_RET_INT(0), inode_link, struct dentry *old_dentry, struct inode *dir, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_link, struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) -LSM_HOOK(int, LSM_RET_INT(0), inode_unlink, struct inode *dir, struct dentry *dentry) -LSM_HOOK(int, LSM_RET_INT(0), inode_symlink, struct inode *dir, struct dentry *dentry, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_unlink, struct inode *dir, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_symlink, struct inode *dir, struct dentry *dentry, const char *old_name) -LSM_HOOK(int, LSM_RET_INT(0), inode_mkdir, struct inode *dir, struct dentry *dentry, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_mkdir, struct inode *dir, struct dentry *dentry, umode_t mode) -LSM_HOOK(int, LSM_RET_INT(0), inode_rmdir, struct inode *dir, struct dentry *dentry) -LSM_HOOK(int, LSM_RET_INT(0), inode_mknod, struct inode *dir, struct dentry *dentry, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_rmdir, struct inode *dir, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_mknod, struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) -LSM_HOOK(int, LSM_RET_INT(0), inode_rename, struct inode *old_dir, struct dentry *old_dentry, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_rename, struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) -LSM_HOOK(int, LSM_RET_INT(0), inode_readlink, struct dentry *dentry) -LSM_HOOK(int, LSM_RET_INT(0), inode_follow_link, struct dentry *dentry, struct inode *inode, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_readlink, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_follow_link, struct dentry *dentry, struct inode *inode, bool rcu) -LSM_HOOK(int, LSM_RET_INT(0), inode_permission, struct inode *inode, int mask) -LSM_HOOK(int, LSM_RET_INT(0), inode_setattr, struct dentry *dentry, struct iattr *attr) -LSM_HOOK(int, LSM_RET_INT(0), inode_getattr, const struct path *path) -LSM_HOOK(int, LSM_RET_INT(0), inode_setxattr, struct mnt_idmap *idmap, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_permission, struct inode *inode, int mask) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_setattr, struct dentry *dentry, struct iattr *attr) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_getattr, const struct path *path) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_setxattr, struct mnt_idmap *idmap, 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, const char *name, const void *value, size_t size, int flags) -LSM_HOOK(int, LSM_RET_INT(0), inode_getxattr, struct dentry *dentry, const char *name) -LSM_HOOK(int, LSM_RET_INT(0), inode_listxattr, struct dentry *dentry) -LSM_HOOK(int, LSM_RET_INT(0), inode_removexattr, struct mnt_idmap *idmap, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_getxattr, struct dentry *dentry, const char *name) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_listxattr, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_removexattr, struct mnt_idmap *idmap, struct dentry *dentry, const char *name) -LSM_HOOK(int, LSM_RET_INT(0), inode_set_acl, struct mnt_idmap *idmap, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_set_acl, struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name, struct posix_acl *kacl) -LSM_HOOK(int, LSM_RET_INT(0), inode_get_acl, struct mnt_idmap *idmap, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_get_acl, struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name) -LSM_HOOK(int, LSM_RET_INT(0), inode_remove_acl, struct mnt_idmap *idmap, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_remove_acl, struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name) -LSM_HOOK(int, LSM_RET_INT(0), inode_need_killpriv, struct dentry *dentry) -LSM_HOOK(int, LSM_RET_INT(0), inode_killpriv, struct mnt_idmap *idmap, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_need_killpriv, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_killpriv, struct mnt_idmap *idmap, struct dentry *dentry) -LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP), inode_getsecurity, struct mnt_idmap *idmap, +LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP, ERRNO), inode_getsecurity, struct mnt_idmap *idmap, struct inode *inode, const char *name, void **buffer, bool alloc) -LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP), inode_setsecurity, struct inode *inode, +LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP, ERRNO), inode_setsecurity, struct inode *inode, const char *name, const void *value, size_t size, int flags) -LSM_HOOK(int, LSM_RET_INT(0), inode_listsecurity, struct inode *inode, char *buffer, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, LSM_RET_INT(0), inode_copy_up, struct dentry *src, struct cred **new) -LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP), inode_copy_up_xattr, const char *name) -LSM_HOOK(int, LSM_RET_INT(0), kernfs_init_security, struct kernfs_node *kn_dir, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_copy_up, struct dentry *src, struct cred **new) +LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP, ERRNO), inode_copy_up_xattr, const char *name) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), kernfs_init_security, struct kernfs_node *kn_dir, struct kernfs_node *kn) -LSM_HOOK(int, LSM_RET_INT(0), file_permission, struct file *file, int mask) -LSM_HOOK(int, LSM_RET_INT(0), file_alloc_security, struct file *file) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), file_permission, struct file *file, int mask) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), file_alloc_security, struct file *file) LSM_HOOK(void, LSM_RET_VOID, file_free_security, struct file *file) -LSM_HOOK(int, LSM_RET_INT(0), file_ioctl, struct file *file, unsigned int cmd, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), file_ioctl, struct file *file, unsigned int cmd, unsigned long arg) -LSM_HOOK(int, LSM_RET_INT(0), file_ioctl_compat, struct file *file, unsigned int cmd, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), file_ioctl_compat, struct file *file, unsigned int cmd, unsigned long arg) -LSM_HOOK(int, LSM_RET_INT(0), mmap_addr, unsigned long addr) -LSM_HOOK(int, LSM_RET_INT(0), mmap_file, struct file *file, unsigned long reqprot, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), mmap_addr, unsigned long addr) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), mmap_file, struct file *file, unsigned long reqprot, unsigned long prot, unsigned long flags) -LSM_HOOK(int, LSM_RET_INT(0), file_mprotect, struct vm_area_struct *vma, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), file_mprotect, struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot) -LSM_HOOK(int, LSM_RET_INT(0), file_lock, struct file *file, unsigned int cmd) -LSM_HOOK(int, LSM_RET_INT(0), file_fcntl, struct file *file, unsigned int cmd, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), file_lock, struct file *file, unsigned int cmd) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, LSM_RET_INT(0), file_send_sigiotask, struct task_struct *tsk, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), file_send_sigiotask, struct task_struct *tsk, struct fown_struct *fown, int sig) -LSM_HOOK(int, LSM_RET_INT(0), file_receive, struct file *file) -LSM_HOOK(int, LSM_RET_INT(0), file_open, struct file *file) -LSM_HOOK(int, LSM_RET_INT(0), file_truncate, struct file *file) -LSM_HOOK(int, LSM_RET_INT(0), task_alloc, struct task_struct *task, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), file_receive, struct file *file) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), file_open, struct file *file) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), file_truncate, struct file *file) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, LSM_RET_INT(0), cred_alloc_blank, struct cred *cred, gfp_t gfp) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), cred_alloc_blank, struct cred *cred, gfp_t gfp) LSM_HOOK(void, LSM_RET_VOID, cred_free, struct cred *cred) -LSM_HOOK(int, LSM_RET_INT(0), cred_prepare, struct cred *new, const struct cred *old, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), cred_prepare, struct cred *new, const struct cred *old, gfp_t gfp) LSM_HOOK(void, LSM_RET_VOID, 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, LSM_RET_INT(0), kernel_act_as, struct cred *new, u32 secid) -LSM_HOOK(int, LSM_RET_INT(0), kernel_create_files_as, struct cred *new, struct inode *inode) -LSM_HOOK(int, LSM_RET_INT(0), kernel_module_request, char *kmod_name) -LSM_HOOK(int, LSM_RET_INT(0), kernel_load_data, enum kernel_load_data_id id, bool contents) -LSM_HOOK(int, LSM_RET_INT(0), kernel_post_load_data, char *buf, loff_t size, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), kernel_act_as, struct cred *new, u32 secid) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), kernel_create_files_as, struct cred *new, struct inode *inode) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), kernel_module_request, char *kmod_name) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), kernel_load_data, enum kernel_load_data_id id, bool contents) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), kernel_post_load_data, char *buf, loff_t size, enum kernel_load_data_id id, char *description) -LSM_HOOK(int, LSM_RET_INT(0), kernel_read_file, struct file *file, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), kernel_read_file, struct file *file, enum kernel_read_file_id id, bool contents) -LSM_HOOK(int, LSM_RET_INT(0), kernel_post_read_file, struct file *file, char *buf, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), kernel_post_read_file, struct file *file, char *buf, loff_t size, enum kernel_read_file_id id) -LSM_HOOK(int, LSM_RET_INT(0), task_fix_setuid, struct cred *new, const struct cred *old, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), task_fix_setuid, struct cred *new, const struct cred *old, int flags) -LSM_HOOK(int, LSM_RET_INT(0), task_fix_setgid, struct cred *new, const struct cred *old, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), task_fix_setgid, struct cred *new, const struct cred *old, int flags) -LSM_HOOK(int, LSM_RET_INT(0), task_fix_setgroups, struct cred *new, const struct cred *old) -LSM_HOOK(int, LSM_RET_INT(0), task_setpgid, struct task_struct *p, pid_t pgid) -LSM_HOOK(int, LSM_RET_INT(0), task_getpgid, struct task_struct *p) -LSM_HOOK(int, LSM_RET_INT(0), task_getsid, struct task_struct *p) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), task_fix_setgroups, struct cred *new, const struct cred *old) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), task_setpgid, struct task_struct *p, pid_t pgid) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), task_getpgid, struct task_struct *p) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, struct task_struct *p, u32 *secid) -LSM_HOOK(int, LSM_RET_INT(0), task_setnice, struct task_struct *p, int nice) -LSM_HOOK(int, LSM_RET_INT(0), task_setioprio, struct task_struct *p, int ioprio) -LSM_HOOK(int, LSM_RET_INT(0), task_getioprio, struct task_struct *p) -LSM_HOOK(int, LSM_RET_INT(0), task_prlimit, const struct cred *cred, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), task_setnice, struct task_struct *p, int nice) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), task_setioprio, struct task_struct *p, int ioprio) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), task_getioprio, struct task_struct *p) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), task_prlimit, const struct cred *cred, const struct cred *tcred, unsigned int flags) -LSM_HOOK(int, LSM_RET_INT(0), task_setrlimit, struct task_struct *p, unsigned int resource, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), task_setrlimit, struct task_struct *p, unsigned int resource, struct rlimit *new_rlim) -LSM_HOOK(int, LSM_RET_INT(0), task_setscheduler, struct task_struct *p) -LSM_HOOK(int, LSM_RET_INT(0), task_getscheduler, struct task_struct *p) -LSM_HOOK(int, LSM_RET_INT(0), task_movememory, struct task_struct *p) -LSM_HOOK(int, LSM_RET_INT(0), task_kill, struct task_struct *p, struct kernel_siginfo *info, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), task_setscheduler, struct task_struct *p) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), task_getscheduler, struct task_struct *p) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), task_movememory, struct task_struct *p) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), task_kill, struct task_struct *p, struct kernel_siginfo *info, int sig, const struct cred *cred) -LSM_HOOK(int, LSM_RET_INT(-ENOSYS), task_prctl, int option, unsigned long arg2, +LSM_HOOK(int, LSM_RET_INT(-ENOSYS, ERRNO), task_prctl, int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) LSM_HOOK(void, LSM_RET_VOID, task_to_inode, struct task_struct *p, struct inode *inode) -LSM_HOOK(int, LSM_RET_INT(0), userns_create, const struct cred *cred) -LSM_HOOK(int, LSM_RET_INT(0), ipc_permission, struct kern_ipc_perm *ipcp, short flag) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), userns_create, const struct cred *cred) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), ipc_permission, struct kern_ipc_perm *ipcp, short flag) LSM_HOOK(void, LSM_RET_VOID, ipc_getsecid, struct kern_ipc_perm *ipcp, u32 *secid) -LSM_HOOK(int, LSM_RET_INT(0), msg_msg_alloc_security, struct msg_msg *msg) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, LSM_RET_INT(0), msg_queue_alloc_security, struct kern_ipc_perm *perm) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), msg_queue_alloc_security, struct kern_ipc_perm *perm) LSM_HOOK(void, LSM_RET_VOID, msg_queue_free_security, struct kern_ipc_perm *perm) -LSM_HOOK(int, LSM_RET_INT(0), msg_queue_associate, struct kern_ipc_perm *perm, int msqflg) -LSM_HOOK(int, LSM_RET_INT(0), msg_queue_msgctl, struct kern_ipc_perm *perm, int cmd) -LSM_HOOK(int, LSM_RET_INT(0), msg_queue_msgsnd, struct kern_ipc_perm *perm, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), msg_queue_associate, struct kern_ipc_perm *perm, int msqflg) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), msg_queue_msgctl, struct kern_ipc_perm *perm, int cmd) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), msg_queue_msgsnd, struct kern_ipc_perm *perm, struct msg_msg *msg, int msqflg) -LSM_HOOK(int, LSM_RET_INT(0), msg_queue_msgrcv, struct kern_ipc_perm *perm, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), msg_queue_msgrcv, struct kern_ipc_perm *perm, struct msg_msg *msg, struct task_struct *target, long type, int mode) -LSM_HOOK(int, LSM_RET_INT(0), shm_alloc_security, struct kern_ipc_perm *perm) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, LSM_RET_INT(0), shm_associate, struct kern_ipc_perm *perm, int shmflg) -LSM_HOOK(int, LSM_RET_INT(0), shm_shmctl, struct kern_ipc_perm *perm, int cmd) -LSM_HOOK(int, LSM_RET_INT(0), shm_shmat, struct kern_ipc_perm *perm, char __user *shmaddr, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), shm_associate, struct kern_ipc_perm *perm, int shmflg) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), shm_shmctl, struct kern_ipc_perm *perm, int cmd) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), shm_shmat, struct kern_ipc_perm *perm, char __user *shmaddr, int shmflg) -LSM_HOOK(int, LSM_RET_INT(0), sem_alloc_security, struct kern_ipc_perm *perm) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, LSM_RET_INT(0), sem_associate, struct kern_ipc_perm *perm, int semflg) -LSM_HOOK(int, LSM_RET_INT(0), sem_semctl, struct kern_ipc_perm *perm, int cmd) -LSM_HOOK(int, LSM_RET_INT(0), sem_semop, struct kern_ipc_perm *perm, struct sembuf *sops, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), sem_associate, struct kern_ipc_perm *perm, int semflg) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), sem_semctl, struct kern_ipc_perm *perm, int cmd) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), sem_semop, struct kern_ipc_perm *perm, struct sembuf *sops, unsigned nsops, int alter) -LSM_HOOK(int, LSM_RET_INT(0), netlink_send, struct sock *sk, struct sk_buff *skb) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), netlink_send, struct sock *sk, struct sk_buff *skb) LSM_HOOK(void, LSM_RET_VOID, d_instantiate, struct dentry *dentry, struct inode *inode) -LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP), getselfattr, unsigned int attr, +LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP, ERRNO), getselfattr, unsigned int attr, struct lsm_ctx __user *ctx, size_t *size, u32 flags) -LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP), setselfattr, unsigned int attr, +LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP, ERRNO), setselfattr, unsigned int attr, struct lsm_ctx *ctx, size_t size, u32 flags) -LSM_HOOK(int, LSM_RET_INT(-EINVAL), getprocattr, struct task_struct *p, const char *name, +LSM_HOOK(int, LSM_RET_INT(-EINVAL, ERRNO), getprocattr, struct task_struct *p, const char *name, char **value) -LSM_HOOK(int, LSM_RET_INT(-EINVAL), setprocattr, const char *name, void *value, size_t size) -LSM_HOOK(int, LSM_RET_INT(0), ismaclabel, const char *name) -LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP), secid_to_secctx, u32 secid, char **secdata, +LSM_HOOK(int, LSM_RET_INT(-EINVAL, ERRNO), setprocattr, const char *name, void *value, size_t size) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), ismaclabel, const char *name) +LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP, ERRNO), secid_to_secctx, u32 secid, char **secdata, u32 *seclen) -LSM_HOOK(int, LSM_RET_INT(0), secctx_to_secid, const char *secdata, u32 seclen, u32 *secid) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, LSM_RET_INT(0), inode_notifysecctx, struct inode *inode, void *ctx, u32 ctxlen) -LSM_HOOK(int, LSM_RET_INT(0), inode_setsecctx, struct dentry *dentry, void *ctx, u32 ctxlen) -LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP), inode_getsecctx, struct inode *inode, void **ctx, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_notifysecctx, struct inode *inode, void *ctx, u32 ctxlen) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), inode_setsecctx, struct dentry *dentry, void *ctx, u32 ctxlen) +LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP, ERRNO), inode_getsecctx, struct inode *inode, void **ctx, u32 *ctxlen) #if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE) -LSM_HOOK(int, LSM_RET_INT(0), post_notification, const struct cred *w_cred, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, LSM_RET_INT(0), watch_key, struct key *key) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), watch_key, struct key *key) #endif /* CONFIG_SECURITY && CONFIG_KEY_NOTIFICATIONS */ #ifdef CONFIG_SECURITY_NETWORK -LSM_HOOK(int, LSM_RET_INT(0), unix_stream_connect, struct sock *sock, struct sock *other, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), unix_stream_connect, struct sock *sock, struct sock *other, struct sock *newsk) -LSM_HOOK(int, LSM_RET_INT(0), unix_may_send, struct socket *sock, struct socket *other) -LSM_HOOK(int, LSM_RET_INT(0), socket_create, int family, int type, int protocol, int kern) -LSM_HOOK(int, LSM_RET_INT(0), socket_post_create, struct socket *sock, int family, int type, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), unix_may_send, struct socket *sock, struct socket *other) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), socket_create, int family, int type, int protocol, int kern) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), socket_post_create, struct socket *sock, int family, int type, int protocol, int kern) -LSM_HOOK(int, LSM_RET_INT(0), socket_socketpair, struct socket *socka, struct socket *sockb) -LSM_HOOK(int, LSM_RET_INT(0), socket_bind, struct socket *sock, struct sockaddr *address, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), socket_socketpair, struct socket *socka, struct socket *sockb) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), socket_bind, struct socket *sock, struct sockaddr *address, int addrlen) -LSM_HOOK(int, LSM_RET_INT(0), socket_connect, struct socket *sock, struct sockaddr *address, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), socket_connect, struct socket *sock, struct sockaddr *address, int addrlen) -LSM_HOOK(int, LSM_RET_INT(0), socket_listen, struct socket *sock, int backlog) -LSM_HOOK(int, LSM_RET_INT(0), socket_accept, struct socket *sock, struct socket *newsock) -LSM_HOOK(int, LSM_RET_INT(0), socket_sendmsg, struct socket *sock, struct msghdr *msg, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), socket_listen, struct socket *sock, int backlog) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), socket_accept, struct socket *sock, struct socket *newsock) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), socket_sendmsg, struct socket *sock, struct msghdr *msg, int size) -LSM_HOOK(int, LSM_RET_INT(0), socket_recvmsg, struct socket *sock, struct msghdr *msg, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), socket_recvmsg, struct socket *sock, struct msghdr *msg, int size, int flags) -LSM_HOOK(int, LSM_RET_INT(0), socket_getsockname, struct socket *sock) -LSM_HOOK(int, LSM_RET_INT(0), socket_getpeername, struct socket *sock) -LSM_HOOK(int, LSM_RET_INT(0), socket_getsockopt, struct socket *sock, int level, int optname) -LSM_HOOK(int, LSM_RET_INT(0), socket_setsockopt, struct socket *sock, int level, int optname) -LSM_HOOK(int, LSM_RET_INT(0), socket_shutdown, struct socket *sock, int how) -LSM_HOOK(int, LSM_RET_INT(0), socket_sock_rcv_skb, struct sock *sk, struct sk_buff *skb) -LSM_HOOK(int, LSM_RET_INT(-ENOPROTOOPT), socket_getpeersec_stream, struct socket *sock, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), socket_getsockname, struct socket *sock) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), socket_getpeername, struct socket *sock) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), socket_getsockopt, struct socket *sock, int level, int optname) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), socket_setsockopt, struct socket *sock, int level, int optname) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), socket_shutdown, struct socket *sock, int how) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), socket_sock_rcv_skb, struct sock *sk, struct sk_buff *skb) +LSM_HOOK(int, LSM_RET_INT(-ENOPROTOOPT, ERRNO), socket_getpeersec_stream, struct socket *sock, sockptr_t optval, sockptr_t optlen, unsigned int len) -LSM_HOOK(int, LSM_RET_INT(-ENOPROTOOPT), socket_getpeersec_dgram, struct socket *sock, +LSM_HOOK(int, LSM_RET_INT(-ENOPROTOOPT, ERRNO), socket_getpeersec_dgram, struct socket *sock, struct sk_buff *skb, u32 *secid) -LSM_HOOK(int, LSM_RET_INT(0), sk_alloc_security, struct sock *sk, int family, gfp_t priority) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, struct sock *newsk) LSM_HOOK(void, LSM_RET_VOID, sk_getsecid, const struct sock *sk, u32 *secid) LSM_HOOK(void, LSM_RET_VOID, sock_graft, struct sock *sk, struct socket *parent) -LSM_HOOK(int, LSM_RET_INT(0), inet_conn_request, const struct sock *sk, struct sk_buff *skb, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, const struct request_sock *req) LSM_HOOK(void, LSM_RET_VOID, inet_conn_established, struct sock *sk, struct sk_buff *skb) -LSM_HOOK(int, LSM_RET_INT(0), secmark_relabel_packet, u32 secid) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, struct flowi_common *flic) -LSM_HOOK(int, LSM_RET_INT(0), tun_dev_alloc_security, void **security) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), tun_dev_alloc_security, void **security) LSM_HOOK(void, LSM_RET_VOID, tun_dev_free_security, void *security) -LSM_HOOK(int, LSM_RET_INT(0), tun_dev_create, void) -LSM_HOOK(int, LSM_RET_INT(0), tun_dev_attach_queue, void *security) -LSM_HOOK(int, LSM_RET_INT(0), tun_dev_attach, struct sock *sk, void *security) -LSM_HOOK(int, LSM_RET_INT(0), tun_dev_open, void *security) -LSM_HOOK(int, LSM_RET_INT(0), sctp_assoc_request, struct sctp_association *asoc, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), tun_dev_create, void) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), tun_dev_attach_queue, void *security) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), tun_dev_attach, struct sock *sk, void *security) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), tun_dev_open, void *security) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), sctp_assoc_request, struct sctp_association *asoc, struct sk_buff *skb) -LSM_HOOK(int, LSM_RET_INT(0), sctp_bind_connect, struct sock *sk, int optname, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, struct sock *sk, struct sock *newsk) -LSM_HOOK(int, LSM_RET_INT(0), sctp_assoc_established, struct sctp_association *asoc, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), sctp_assoc_established, struct sctp_association *asoc, struct sk_buff *skb) -LSM_HOOK(int, LSM_RET_INT(0), mptcp_add_subflow, struct sock *sk, struct sock *ssk) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), mptcp_add_subflow, struct sock *sk, struct sock *ssk) #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_INFINIBAND -LSM_HOOK(int, LSM_RET_INT(0), ib_pkey_access, void *sec, u64 subnet_prefix, u16 pkey) -LSM_HOOK(int, LSM_RET_INT(0), ib_endport_manage_subnet, void *sec, const char *dev_name, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), ib_pkey_access, void *sec, u64 subnet_prefix, u16 pkey) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), ib_endport_manage_subnet, void *sec, const char *dev_name, u8 port_num) -LSM_HOOK(int, LSM_RET_INT(0), ib_alloc_security, void **sec) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), ib_alloc_security, void **sec) LSM_HOOK(void, LSM_RET_VOID, ib_free_security, void *sec) #endif /* CONFIG_SECURITY_INFINIBAND */ #ifdef CONFIG_SECURITY_NETWORK_XFRM -LSM_HOOK(int, LSM_RET_INT(0), xfrm_policy_alloc_security, struct xfrm_sec_ctx **ctxp, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), xfrm_policy_alloc_security, struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp) -LSM_HOOK(int, LSM_RET_INT(0), xfrm_policy_clone_security, struct xfrm_sec_ctx *old_ctx, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, struct xfrm_sec_ctx *ctx) -LSM_HOOK(int, LSM_RET_INT(0), xfrm_policy_delete_security, struct xfrm_sec_ctx *ctx) -LSM_HOOK(int, LSM_RET_INT(0), xfrm_state_alloc, struct xfrm_state *x, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), xfrm_policy_delete_security, struct xfrm_sec_ctx *ctx) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), xfrm_state_alloc, struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) -LSM_HOOK(int, LSM_RET_INT(0), xfrm_state_alloc_acquire, struct xfrm_state *x, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, LSM_RET_INT(0), xfrm_state_delete_security, struct xfrm_state *x) -LSM_HOOK(int, LSM_RET_INT(0), xfrm_policy_lookup, struct xfrm_sec_ctx *ctx, u32 fl_secid) -LSM_HOOK(int, LSM_RET_INT(1), xfrm_state_pol_flow_match, struct xfrm_state *x, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), xfrm_state_delete_security, struct xfrm_state *x) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), xfrm_policy_lookup, struct xfrm_sec_ctx *ctx, u32 fl_secid) +LSM_HOOK(int, LSM_RET_INT(1, ANY), xfrm_state_pol_flow_match, struct xfrm_state *x, struct xfrm_policy *xp, const struct flowi_common *flic) -LSM_HOOK(int, LSM_RET_INT(0), xfrm_decode_session, struct sk_buff *skb, u32 *secid, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, LSM_RET_INT(0), key_alloc, struct key *key, const struct cred *cred, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), 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, LSM_RET_INT(0), key_permission, key_ref_t key_ref, const struct cred *cred, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), key_permission, key_ref_t key_ref, const struct cred *cred, enum key_need_perm need_perm) -LSM_HOOK(int, LSM_RET_INT(0), key_getsecurity, struct key *key, char **buffer) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), key_getsecurity, struct key *key, char **buffer) #endif /* CONFIG_KEYS */ #ifdef CONFIG_AUDIT -LSM_HOOK(int, LSM_RET_INT(0), audit_rule_init, u32 field, u32 op, char *rulestr, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), audit_rule_init, u32 field, u32 op, char *rulestr, void **lsmrule) -LSM_HOOK(int, LSM_RET_INT(0), audit_rule_known, struct audit_krule *krule) -LSM_HOOK(int, LSM_RET_INT(0), audit_rule_match, u32 secid, u32 field, u32 op, void *lsmrule) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), audit_rule_known, struct audit_krule *krule) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), audit_rule_match, u32 secid, u32 field, u32 op, void *lsmrule) LSM_HOOK(void, LSM_RET_VOID, audit_rule_free, void *lsmrule) #endif /* CONFIG_AUDIT */ #ifdef CONFIG_BPF_SYSCALL -LSM_HOOK(int, LSM_RET_INT(0), bpf, int cmd, union bpf_attr *attr, unsigned int size) -LSM_HOOK(int, LSM_RET_INT(0), bpf_map, struct bpf_map *map, fmode_t fmode) -LSM_HOOK(int, LSM_RET_INT(0), bpf_prog, struct bpf_prog *prog) -LSM_HOOK(int, LSM_RET_INT(0), bpf_map_create, struct bpf_map *map, union bpf_attr *attr, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), bpf, int cmd, union bpf_attr *attr, unsigned int size) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), bpf_map, struct bpf_map *map, fmode_t fmode) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), bpf_prog, struct bpf_prog *prog) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), bpf_map_create, struct bpf_map *map, union bpf_attr *attr, struct bpf_token *token) LSM_HOOK(void, LSM_RET_VOID, bpf_map_free, struct bpf_map *map) -LSM_HOOK(int, LSM_RET_INT(0), bpf_prog_load, struct bpf_prog *prog, union bpf_attr *attr, +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), bpf_prog_load, struct bpf_prog *prog, union bpf_attr *attr, struct bpf_token *token) LSM_HOOK(void, LSM_RET_VOID, bpf_prog_free, struct bpf_prog *prog) -LSM_HOOK(int, LSM_RET_INT(0), bpf_token_create, struct bpf_token *token, union bpf_attr *attr, - struct path *path) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), bpf_token_create, struct bpf_token *token, + union bpf_attr *attr, struct path *path) LSM_HOOK(void, LSM_RET_VOID, bpf_token_free, struct bpf_token *token) -LSM_HOOK(int, LSM_RET_INT(0), bpf_token_cmd, const struct bpf_token *token, enum bpf_cmd cmd) -LSM_HOOK(int, LSM_RET_INT(0), bpf_token_capable, const struct bpf_token *token, int cap) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), bpf_token_cmd, const struct bpf_token *token, enum bpf_cmd cmd) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), bpf_token_capable, const struct bpf_token *token, int cap) #endif /* CONFIG_BPF_SYSCALL */ -LSM_HOOK(int, LSM_RET_INT(0), locked_down, enum lockdown_reason what) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), locked_down, enum lockdown_reason what) #ifdef CONFIG_PERF_EVENTS -LSM_HOOK(int, LSM_RET_INT(0), perf_event_open, struct perf_event_attr *attr, int type) -LSM_HOOK(int, LSM_RET_INT(0), perf_event_alloc, struct perf_event *event) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), perf_event_open, struct perf_event_attr *attr, int type) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), perf_event_alloc, struct perf_event *event) LSM_HOOK(void, LSM_RET_VOID, perf_event_free, struct perf_event *event) -LSM_HOOK(int, LSM_RET_INT(0), perf_event_read, struct perf_event *event) -LSM_HOOK(int, LSM_RET_INT(0), perf_event_write, struct perf_event *event) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), perf_event_read, struct perf_event *event) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), perf_event_write, struct perf_event *event) #endif /* CONFIG_PERF_EVENTS */ #ifdef CONFIG_IO_URING -LSM_HOOK(int, LSM_RET_INT(0), uring_override_creds, const struct cred *new) -LSM_HOOK(int, LSM_RET_INT(0), uring_sqpoll, void) -LSM_HOOK(int, LSM_RET_INT(0), uring_cmd, struct io_uring_cmd *ioucmd) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), uring_override_creds, const struct cred *new) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), uring_sqpoll, void) +LSM_HOOK(int, LSM_RET_INT(0, ERRNO), uring_cmd, struct io_uring_cmd *ioucmd) #endif /* CONFIG_IO_URING */ diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c index 2185dc4c0aed..ee9d1a795334 100644 --- a/kernel/bpf/bpf_lsm.c +++ b/kernel/bpf/bpf_lsm.c @@ -24,7 +24,7 @@ */ #define LSM_RET_VOID ((void) 0) -#define LSM_RET_INT(defval) defval +#define LSM_RET_INT(defval, ...) defval /* For every LSM hook that allows attachment of BPF programs, declare a nop * function where a BPF program can be attached. diff --git a/security/security.c b/security/security.c index 72408a9f0822..0cce7c9c9007 100644 --- a/security/security.c +++ b/security/security.c @@ -828,7 +828,7 @@ int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, size_t *uctx_len, * The macros below define static constants for the default value of each * LSM hook. */ -#define LSM_RET_INT(defval) defval +#define LSM_RET_INT(defval, ...) defval #define LSM_RET_DEFAULT(NAME) (NAME##_default) #define DECLARE_LSM_RET_DEFAULT_void(DEFAULT, NAME) #define DECLARE_LSM_RET_DEFAULT_int(DEFAULT, NAME) \ -- 2.30.2
From: Xu Kuohai <xukuohai@huawei.com> Add macro LSM_RET_INT to annotate lsm hook return integer type and the default return value. The follow-up patch will use this macro to add return value range descriptions. Signed-off-by: Xu Kuohai <xukuohai@huawei.com> --- include/linux/lsm_hook_defs.h | 424 +++++++++++++++++----------------- include/linux/lsm_hooks.h | 6 - kernel/bpf/bpf_lsm.c | 10 + security/security.c | 1 + 4 files changed, 224 insertions(+), 217 deletions(-) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 642272576582..22b64b15faa8 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -26,409 +26,411 @@ * #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, +LSM_HOOK(int, LSM_RET_INT(0), binder_set_context_mgr, const struct cred *mgr) +LSM_HOOK(int, LSM_RET_INT(0), binder_transaction, const struct cred *from, const struct cred *to) -LSM_HOOK(int, 0, binder_transfer_binder, const struct cred *from, +LSM_HOOK(int, LSM_RET_INT(0), binder_transfer_binder, const struct cred *from, const struct cred *to) -LSM_HOOK(int, 0, binder_transfer_file, const struct cred *from, +LSM_HOOK(int, LSM_RET_INT(0), binder_transfer_file, const struct cred *from, const struct cred *to, const struct file *file) -LSM_HOOK(int, 0, ptrace_access_check, struct task_struct *child, +LSM_HOOK(int, LSM_RET_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, const struct task_struct *target, kernel_cap_t *effective, +LSM_HOOK(int, LSM_RET_INT(0), ptrace_traceme, struct task_struct *parent) +LSM_HOOK(int, LSM_RET_INT(0), capget, const 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, +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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, const 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, +LSM_HOOK(int, LSM_RET_INT(0), quotactl, int cmds, int type, int id, const struct super_block *sb) +LSM_HOOK(int, LSM_RET_INT(0), quota_on, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_INT(0), syslog, int type) +LSM_HOOK(int, LSM_RET_INT(0), settime, const struct timespec64 *ts, const struct timezone *tz) -LSM_HOOK(int, 1, vm_enough_memory, struct mm_struct *mm, long pages) -LSM_HOOK(int, 0, bprm_creds_for_exec, struct linux_binprm *bprm) -LSM_HOOK(int, 0, bprm_creds_from_file, struct linux_binprm *bprm, const struct file *file) -LSM_HOOK(int, 0, bprm_check_security, struct linux_binprm *bprm) +LSM_HOOK(int, LSM_RET_INT(1), vm_enough_memory, struct mm_struct *mm, long pages) +LSM_HOOK(int, LSM_RET_INT(0), bprm_creds_for_exec, struct linux_binprm *bprm) +LSM_HOOK(int, LSM_RET_INT(0), bprm_creds_from_file, struct linux_binprm *bprm, + const struct file *file) +LSM_HOOK(int, LSM_RET_INT(0), bprm_check_security, struct linux_binprm *bprm) LSM_HOOK(void, LSM_RET_VOID, bprm_committing_creds, const struct linux_binprm *bprm) LSM_HOOK(void, LSM_RET_VOID, bprm_committed_creds, const struct linux_binprm *bprm) -LSM_HOOK(int, 0, fs_context_submount, struct fs_context *fc, struct super_block *reference) -LSM_HOOK(int, 0, fs_context_dup, struct fs_context *fc, +LSM_HOOK(int, LSM_RET_INT(0), fs_context_submount, struct fs_context *fc, + struct super_block *reference) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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(int, LSM_RET_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, const 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, +LSM_HOOK(int, LSM_RET_INT(0), sb_eat_lsm_opts, char *orig, void **mnt_opts) +LSM_HOOK(int, LSM_RET_INT(0), sb_mnt_opts_compat, struct super_block *sb, void *mnt_opts) +LSM_HOOK(int, LSM_RET_INT(0), sb_remount, struct super_block *sb, void *mnt_opts) +LSM_HOOK(int, LSM_RET_INT(0), sb_kern_mount, const struct super_block *sb) +LSM_HOOK(int, LSM_RET_INT(0), sb_show_options, struct seq_file *m, struct super_block *sb) +LSM_HOOK(int, LSM_RET_INT(0), sb_statfs, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(0), sb_umount, struct vfsmount *mnt, int flags) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(0), 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, move_mount, const struct path *from_path, +LSM_HOOK(int, LSM_RET_INT(0), move_mount, const struct path *from_path, const struct path *to_path) -LSM_HOOK(int, -EOPNOTSUPP, dentry_init_security, struct dentry *dentry, +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(0), 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, +LSM_HOOK(int, LSM_RET_INT(0), path_unlink, const struct path *dir, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(0), path_rmdir, const struct path *dir, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(0), path_truncate, const struct path *path) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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, LSM_RET_INT(0), 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, 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) +LSM_HOOK(int, LSM_RET_INT(0), path_chmod, const struct path *path, umode_t mode) +LSM_HOOK(int, LSM_RET_INT(0), path_chown, const struct path *path, kuid_t uid, kgid_t gid) +LSM_HOOK(int, LSM_RET_INT(0), 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, +LSM_HOOK(int, LSM_RET_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(int, LSM_RET_INT(0), inode_alloc_security, struct inode *inode) LSM_HOOK(void, LSM_RET_VOID, inode_free_security, struct inode *inode) -LSM_HOOK(int, -EOPNOTSUPP, inode_init_security, struct inode *inode, +LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP), inode_init_security, struct inode *inode, struct inode *dir, const struct qstr *qstr, struct xattr *xattrs, int *xattr_count) -LSM_HOOK(int, 0, inode_init_security_anon, struct inode *inode, +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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, LSM_RET_INT(0), 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, +LSM_HOOK(int, LSM_RET_INT(0), inode_unlink, struct inode *dir, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(0), inode_rmdir, struct inode *dir, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_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, LSM_RET_INT(0), 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, +LSM_HOOK(int, LSM_RET_INT(0), inode_readlink, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_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 mnt_idmap *idmap, +LSM_HOOK(int, LSM_RET_INT(0), inode_permission, struct inode *inode, int mask) +LSM_HOOK(int, LSM_RET_INT(0), inode_setattr, struct dentry *dentry, struct iattr *attr) +LSM_HOOK(int, LSM_RET_INT(0), inode_getattr, const struct path *path) +LSM_HOOK(int, LSM_RET_INT(0), inode_setxattr, struct mnt_idmap *idmap, 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, 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 mnt_idmap *idmap, +LSM_HOOK(int, LSM_RET_INT(0), inode_getxattr, struct dentry *dentry, const char *name) +LSM_HOOK(int, LSM_RET_INT(0), inode_listxattr, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_INT(0), inode_removexattr, struct mnt_idmap *idmap, struct dentry *dentry, const char *name) -LSM_HOOK(int, 0, inode_set_acl, struct mnt_idmap *idmap, +LSM_HOOK(int, LSM_RET_INT(0), inode_set_acl, struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name, struct posix_acl *kacl) -LSM_HOOK(int, 0, inode_get_acl, struct mnt_idmap *idmap, +LSM_HOOK(int, LSM_RET_INT(0), inode_get_acl, struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name) -LSM_HOOK(int, 0, inode_remove_acl, struct mnt_idmap *idmap, +LSM_HOOK(int, LSM_RET_INT(0), inode_remove_acl, struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name) -LSM_HOOK(int, 0, inode_need_killpriv, struct dentry *dentry) -LSM_HOOK(int, 0, inode_killpriv, struct mnt_idmap *idmap, +LSM_HOOK(int, LSM_RET_INT(0), inode_need_killpriv, struct dentry *dentry) +LSM_HOOK(int, LSM_RET_INT(0), inode_killpriv, struct mnt_idmap *idmap, struct dentry *dentry) -LSM_HOOK(int, -EOPNOTSUPP, inode_getsecurity, struct mnt_idmap *idmap, +LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP), inode_getsecurity, struct mnt_idmap *idmap, struct inode *inode, const char *name, void **buffer, bool alloc) -LSM_HOOK(int, -EOPNOTSUPP, inode_setsecurity, struct inode *inode, +LSM_HOOK(int, LSM_RET_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, LSM_RET_INT(0), 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, +LSM_HOOK(int, LSM_RET_INT(0), inode_copy_up, struct dentry *src, struct cred **new) +LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP), inode_copy_up_xattr, const char *name) +LSM_HOOK(int, LSM_RET_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(int, LSM_RET_INT(0), file_permission, struct file *file, int mask) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(0), file_ioctl, struct file *file, unsigned int cmd, unsigned long arg) -LSM_HOOK(int, 0, file_ioctl_compat, struct file *file, unsigned int cmd, +LSM_HOOK(int, LSM_RET_INT(0), file_ioctl_compat, 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, +LSM_HOOK(int, LSM_RET_INT(0), mmap_addr, unsigned long addr) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(0), file_lock, struct file *file, unsigned int cmd) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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, file_truncate, struct file *file) -LSM_HOOK(int, 0, task_alloc, struct task_struct *task, +LSM_HOOK(int, LSM_RET_INT(0), file_receive, struct file *file) +LSM_HOOK(int, LSM_RET_INT(0), file_open, struct file *file) +LSM_HOOK(int, LSM_RET_INT(0), file_truncate, struct file *file) +LSM_HOOK(int, LSM_RET_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(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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, 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, +LSM_HOOK(int, LSM_RET_INT(0), kernel_act_as, struct cred *new, u32 secid) +LSM_HOOK(int, LSM_RET_INT(0), kernel_create_files_as, struct cred *new, struct inode *inode) +LSM_HOOK(int, LSM_RET_INT(0), kernel_module_request, char *kmod_name) +LSM_HOOK(int, LSM_RET_INT(0), kernel_load_data, enum kernel_load_data_id id, bool contents) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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(int, LSM_RET_INT(0), task_fix_setgroups, struct cred *new, const struct cred *old) +LSM_HOOK(int, LSM_RET_INT(0), task_setpgid, struct task_struct *p, pid_t pgid) +LSM_HOOK(int, LSM_RET_INT(0), task_getpgid, struct task_struct *p) +LSM_HOOK(int, LSM_RET_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, 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, +LSM_HOOK(int, LSM_RET_INT(0), task_setnice, struct task_struct *p, int nice) +LSM_HOOK(int, LSM_RET_INT(0), task_setioprio, struct task_struct *p, int ioprio) +LSM_HOOK(int, LSM_RET_INT(0), task_getioprio, struct task_struct *p) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(0), task_setscheduler, struct task_struct *p) +LSM_HOOK(int, LSM_RET_INT(0), task_getscheduler, struct task_struct *p) +LSM_HOOK(int, LSM_RET_INT(0), task_movememory, struct task_struct *p) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(-ENOSYS), task_prctl, int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) LSM_HOOK(void, LSM_RET_VOID, task_to_inode, struct task_struct *p, struct inode *inode) -LSM_HOOK(int, 0, userns_create, const struct cred *cred) -LSM_HOOK(int, 0, ipc_permission, struct kern_ipc_perm *ipcp, short flag) +LSM_HOOK(int, LSM_RET_INT(0), userns_create, const struct cred *cred) +LSM_HOOK(int, LSM_RET_INT(0), ipc_permission, struct kern_ipc_perm *ipcp, short flag) LSM_HOOK(void, LSM_RET_VOID, ipc_getsecid, struct kern_ipc_perm *ipcp, u32 *secid) -LSM_HOOK(int, 0, msg_msg_alloc_security, struct msg_msg *msg) +LSM_HOOK(int, LSM_RET_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(int, LSM_RET_INT(0), msg_queue_alloc_security, struct kern_ipc_perm *perm) LSM_HOOK(void, LSM_RET_VOID, msg_queue_free_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, +LSM_HOOK(int, LSM_RET_INT(0), msg_queue_associate, struct kern_ipc_perm *perm, int msqflg) +LSM_HOOK(int, LSM_RET_INT(0), msg_queue_msgctl, struct kern_ipc_perm *perm, int cmd) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(0), shm_associate, struct kern_ipc_perm *perm, int shmflg) +LSM_HOOK(int, LSM_RET_INT(0), shm_shmctl, struct kern_ipc_perm *perm, int cmd) +LSM_HOOK(int, LSM_RET_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(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(0), sem_associate, struct kern_ipc_perm *perm, int semflg) +LSM_HOOK(int, LSM_RET_INT(0), sem_semctl, struct kern_ipc_perm *perm, int cmd) +LSM_HOOK(int, LSM_RET_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(int, LSM_RET_INT(0), netlink_send, struct sock *sk, struct sk_buff *skb) LSM_HOOK(void, LSM_RET_VOID, d_instantiate, struct dentry *dentry, struct inode *inode) -LSM_HOOK(int, -EOPNOTSUPP, getselfattr, unsigned int attr, +LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP), getselfattr, unsigned int attr, struct lsm_ctx __user *ctx, size_t *size, u32 flags) -LSM_HOOK(int, -EOPNOTSUPP, setselfattr, unsigned int attr, +LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP), setselfattr, unsigned int attr, struct lsm_ctx *ctx, size_t size, u32 flags) -LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name, +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(-EINVAL), setprocattr, const char *name, void *value, size_t size) +LSM_HOOK(int, LSM_RET_INT(0), ismaclabel, const char *name) +LSM_HOOK(int, LSM_RET_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(int, LSM_RET_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, -EOPNOTSUPP, inode_getsecctx, struct inode *inode, void **ctx, +LSM_HOOK(int, LSM_RET_INT(0), inode_notifysecctx, struct inode *inode, void *ctx, u32 ctxlen) +LSM_HOOK(int, LSM_RET_INT(0), inode_setsecctx, struct dentry *dentry, void *ctx, u32 ctxlen) +LSM_HOOK(int, LSM_RET_INT(-EOPNOTSUPP), 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, +LSM_HOOK(int, LSM_RET_INT(0), 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, LSM_RET_INT(0), 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, +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(0), unix_may_send, struct socket *sock, struct socket *other) +LSM_HOOK(int, LSM_RET_INT(0), socket_create, int family, int type, int protocol, int kern) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(0), socket_socketpair, struct socket *socka, struct socket *sockb) +LSM_HOOK(int, LSM_RET_INT(0), socket_bind, struct socket *sock, struct sockaddr *address, int addrlen) -LSM_HOOK(int, 0, socket_connect, struct socket *sock, struct sockaddr *address, +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(0), socket_listen, struct socket *sock, int backlog) +LSM_HOOK(int, LSM_RET_INT(0), socket_accept, struct socket *sock, struct socket *newsock) +LSM_HOOK(int, LSM_RET_INT(0), socket_sendmsg, struct socket *sock, struct msghdr *msg, int size) -LSM_HOOK(int, 0, socket_recvmsg, struct socket *sock, struct msghdr *msg, +LSM_HOOK(int, LSM_RET_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, -ENOPROTOOPT, socket_getpeersec_stream, struct socket *sock, +LSM_HOOK(int, LSM_RET_INT(0), socket_getsockname, struct socket *sock) +LSM_HOOK(int, LSM_RET_INT(0), socket_getpeername, struct socket *sock) +LSM_HOOK(int, LSM_RET_INT(0), socket_getsockopt, struct socket *sock, int level, int optname) +LSM_HOOK(int, LSM_RET_INT(0), socket_setsockopt, struct socket *sock, int level, int optname) +LSM_HOOK(int, LSM_RET_INT(0), socket_shutdown, struct socket *sock, int how) +LSM_HOOK(int, LSM_RET_INT(0), socket_sock_rcv_skb, struct sock *sk, struct sk_buff *skb) +LSM_HOOK(int, LSM_RET_INT(-ENOPROTOOPT), socket_getpeersec_stream, struct socket *sock, sockptr_t optval, sockptr_t optlen, unsigned int len) -LSM_HOOK(int, -ENOPROTOOPT, socket_getpeersec_dgram, struct socket *sock, +LSM_HOOK(int, LSM_RET_INT(-ENOPROTOOPT), 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(int, LSM_RET_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, struct sock *newsk) LSM_HOOK(void, LSM_RET_VOID, sk_getsecid, const 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, +LSM_HOOK(int, LSM_RET_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, const struct request_sock *req) LSM_HOOK(void, LSM_RET_VOID, inet_conn_established, struct sock *sk, struct sk_buff *skb) -LSM_HOOK(int, 0, secmark_relabel_packet, u32 secid) +LSM_HOOK(int, LSM_RET_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, struct flowi_common *flic) -LSM_HOOK(int, 0, tun_dev_alloc_security, void **security) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(0), tun_dev_create, void) +LSM_HOOK(int, LSM_RET_INT(0), tun_dev_attach_queue, void *security) +LSM_HOOK(int, LSM_RET_INT(0), tun_dev_attach, struct sock *sk, void *security) +LSM_HOOK(int, LSM_RET_INT(0), tun_dev_open, void *security) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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, struct sock *sk, struct sock *newsk) -LSM_HOOK(int, 0, sctp_assoc_established, struct sctp_association *asoc, +LSM_HOOK(int, LSM_RET_INT(0), sctp_assoc_established, struct sctp_association *asoc, struct sk_buff *skb) -LSM_HOOK(int, 0, mptcp_add_subflow, struct sock *sk, struct sock *ssk) +LSM_HOOK(int, LSM_RET_INT(0), mptcp_add_subflow, struct sock *sk, struct sock *ssk) #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, +LSM_HOOK(int, LSM_RET_INT(0), ib_pkey_access, void *sec, u64 subnet_prefix, u16 pkey) +LSM_HOOK(int, LSM_RET_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(int, LSM_RET_INT(0), ib_alloc_security, void **sec) LSM_HOOK(void, LSM_RET_VOID, 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, +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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, 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, +LSM_HOOK(int, LSM_RET_INT(0), xfrm_policy_delete_security, struct xfrm_sec_ctx *ctx) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(0), xfrm_state_delete_security, struct xfrm_state *x) +LSM_HOOK(int, LSM_RET_INT(0), xfrm_policy_lookup, struct xfrm_sec_ctx *ctx, u32 fl_secid) +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_INT(0), 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, +LSM_HOOK(int, LSM_RET_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, +LSM_HOOK(int, LSM_RET_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, LSM_RET_INT(0), 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, +LSM_HOOK(int, LSM_RET_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(int, LSM_RET_INT(0), audit_rule_known, struct audit_krule *krule) +LSM_HOOK(int, LSM_RET_INT(0), audit_rule_match, u32 secid, u32 field, u32 op, void *lsmrule) LSM_HOOK(void, LSM_RET_VOID, 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_create, struct bpf_map *map, union bpf_attr *attr, +LSM_HOOK(int, LSM_RET_INT(0), bpf, int cmd, union bpf_attr *attr, unsigned int size) +LSM_HOOK(int, LSM_RET_INT(0), bpf_map, struct bpf_map *map, fmode_t fmode) +LSM_HOOK(int, LSM_RET_INT(0), bpf_prog, struct bpf_prog *prog) +LSM_HOOK(int, LSM_RET_INT(0), bpf_map_create, struct bpf_map *map, union bpf_attr *attr, struct bpf_token *token) LSM_HOOK(void, LSM_RET_VOID, bpf_map_free, struct bpf_map *map) -LSM_HOOK(int, 0, bpf_prog_load, struct bpf_prog *prog, union bpf_attr *attr, +LSM_HOOK(int, LSM_RET_INT(0), bpf_prog_load, struct bpf_prog *prog, union bpf_attr *attr, struct bpf_token *token) LSM_HOOK(void, LSM_RET_VOID, bpf_prog_free, struct bpf_prog *prog) -LSM_HOOK(int, 0, bpf_token_create, struct bpf_token *token, union bpf_attr *attr, +LSM_HOOK(int, LSM_RET_INT(0), bpf_token_create, struct bpf_token *token, union bpf_attr *attr, struct path *path) LSM_HOOK(void, LSM_RET_VOID, bpf_token_free, struct bpf_token *token) -LSM_HOOK(int, 0, bpf_token_cmd, const struct bpf_token *token, enum bpf_cmd cmd) -LSM_HOOK(int, 0, bpf_token_capable, const struct bpf_token *token, int cap) +LSM_HOOK(int, LSM_RET_INT(0), bpf_token_cmd, const struct bpf_token *token, enum bpf_cmd cmd) +LSM_HOOK(int, LSM_RET_INT(0), bpf_token_capable, const struct bpf_token *token, int cap) #endif /* CONFIG_BPF_SYSCALL */ -LSM_HOOK(int, 0, locked_down, enum lockdown_reason what) +LSM_HOOK(int, LSM_RET_INT(0), 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(int, LSM_RET_INT(0), perf_event_open, struct perf_event_attr *attr, int type) +LSM_HOOK(int, LSM_RET_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, LSM_RET_INT(0), perf_event_read, struct perf_event *event) +LSM_HOOK(int, LSM_RET_INT(0), 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, LSM_RET_INT(0), uring_override_creds, const struct cred *new) +LSM_HOOK(int, LSM_RET_INT(0), uring_sqpoll, void) +LSM_HOOK(int, LSM_RET_INT(0), 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 a2ade0ffe9e7..14690cad4fb9 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -98,12 +98,6 @@ static inline struct xattr *lsm_get_xattr_slot(struct xattr *xattrs, return &xattrs[(*xattr_count)++]; } -/* - * LSM_RET_VOID is used as the default value in LSM_HOOK definitions for void - * LSM hooks (in include/linux/lsm_hook_defs.h). - */ -#define LSM_RET_VOID ((void) 0) - /* * 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 68240c3c6e7d..2185dc4c0aed 100644 --- a/kernel/bpf/bpf_lsm.c +++ b/kernel/bpf/bpf_lsm.c @@ -18,6 +18,14 @@ #include <linux/ima.h> #include <linux/bpf-cgroup.h> +/* + * LSM_RET_VOID is used as the default value in LSM_HOOK definitions for void + * LSM hooks (in include/linux/lsm_hook_defs.h). + */ +#define LSM_RET_VOID ((void) 0) + +#define LSM_RET_INT(defval) defval + /* For every LSM hook that allows attachment of BPF programs, declare a nop * function where a BPF program can be attached. */ @@ -29,6 +37,8 @@ noinline RET bpf_lsm_##NAME(__VA_ARGS__) \ #include <linux/lsm_hook_defs.h> #undef LSM_HOOK +#undef LSM_RET_INT +#undef LSM_RET_VOID #define LSM_HOOK(RET, DEFAULT, NAME, ...) BTF_ID(func, bpf_lsm_##NAME) BTF_SET_START(bpf_lsm_hooks) diff --git a/security/security.c b/security/security.c index aef69632d0a9..72408a9f0822 100644 --- a/security/security.c +++ b/security/security.c @@ -828,6 +828,7 @@ int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, size_t *uctx_len, * The macros below define static constants for the default value of each * LSM hook. */ +#define LSM_RET_INT(defval) defval #define LSM_RET_DEFAULT(NAME) (NAME##_default) #define DECLARE_LSM_RET_DEFAULT_void(DEFAULT, NAME) #define DECLARE_LSM_RET_DEFAULT_int(DEFAULT, NAME) \ -- 2.30.2
From: Xu Kuohai <xukuohai@huawei.com> A bpf prog returning positive number attached to file_alloc_security hook will make kernel panic. Here is a panic log: [ 441.235774] BUG: kernel NULL pointer dereference, address: 00000000000009 [ 441.236748] #PF: supervisor write access in kernel mode [ 441.237429] #PF: error_code(0x0002) - not-present page [ 441.238119] PGD 800000000b02f067 P4D 800000000b02f067 PUD b031067 PMD 0 [ 441.238990] Oops: 0002 [#1] PREEMPT SMP PTI [ 441.239546] CPU: 0 PID: 347 Comm: loader Not tainted 6.8.0-rc6-gafe0cbf23373 #22 [ 441.240496] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.15.0-0-g2dd4b4 [ 441.241933] RIP: 0010:alloc_file+0x4b/0x190 [ 441.242485] Code: 8b 04 25 c0 3c 1f 00 48 8b b0 30 0c 00 00 e8 9c fe ff ff 48 3d 00 f0 ff fb [ 441.244820] RSP: 0018:ffffc90000c67c40 EFLAGS: 00010203 [ 441.245484] RAX: ffff888006a891a0 RBX: ffffffff8223bd00 RCX: 0000000035b08000 [ 441.246391] RDX: ffff88800b95f7b0 RSI: 00000000001fc110 RDI: f089cd0b8088ffff [ 441.247294] RBP: ffffc90000c67c58 R08: 0000000000000001 R09: 0000000000000001 [ 441.248209] R10: 0000000000000001 R11: 0000000000000001 R12: 0000000000000001 [ 441.249108] R13: ffffc90000c67c78 R14: ffffffff8223bd00 R15: fffffffffffffff4 [ 441.250007] FS: 00000000005f3300(0000) GS:ffff88803ec00000(0000) knlGS:0000000000000000 [ 441.251053] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 441.251788] CR2: 00000000000001a9 CR3: 000000000bdc4003 CR4: 0000000000170ef0 [ 441.252688] Call Trace: [ 441.253011] <TASK> [ 441.253296] ? __die+0x24/0x70 [ 441.253702] ? page_fault_oops+0x15b/0x480 [ 441.254236] ? fixup_exception+0x26/0x330 [ 441.254750] ? exc_page_fault+0x6d/0x1c0 [ 441.255257] ? asm_exc_page_fault+0x26/0x30 [ 441.255792] ? alloc_file+0x4b/0x190 [ 441.256257] alloc_file_pseudo+0x9f/0xf0 [ 441.256760] __anon_inode_getfile+0x87/0x190 [ 441.257311] ? lock_release+0x14e/0x3f0 [ 441.257808] bpf_link_prime+0xe8/0x1d0 [ 441.258315] bpf_tracing_prog_attach+0x311/0x570 [ 441.258916] ? __pfx_bpf_lsm_file_alloc_security+0x10/0x10 [ 441.259605] __sys_bpf+0x1bb7/0x2dc0 [ 441.260070] __x64_sys_bpf+0x20/0x30 [ 441.260533] do_syscall_64+0x72/0x140 [ 441.261004] entry_SYSCALL_64_after_hwframe+0x6e/0x76 [ 441.261643] RIP: 0033:0x4b0349 [ 441.262045] Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 88 [ 441.264355] RSP: 002b:00007fff74daee38 EFLAGS: 00000246 ORIG_RAX: 0000000000000141 [ 441.265293] RAX: ffffffffffffffda RBX: 00007fff74daef30 RCX: 00000000004b0349 [ 441.266187] RDX: 0000000000000040 RSI: 00007fff74daee50 RDI: 000000000000001c [ 441.267114] RBP: 000000000000001b R08: 00000000005ef820 R09: 0000000000000000 [ 441.268018] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000004 [ 441.268907] R13: 0000000000000004 R14: 00000000005ef018 R15: 00000000004004e8 The reason is that the positive number returned by bpf prog is not a valid errno, and could not be filtered out with IS_ERR which is used by the file system to check errors. As a result, the file system uses this positive number as file pointer, causing panic. To fix this issue, there are two schemes: 1. Modify the calling sites of file_alloc_security to take positive return values as zero. 2. Make the bpf verifier to ensure no unpredicted value is returned by lsm bpf prog. Considering that hook file_alloc_security never returned positive number before bpf lsm was introduced, and other bpf lsm hooks may have the same problem, scheme 2 is more reasonable. So this patch set adds lsm return value check in verifier to fix it. Xu Kuohai (5): bpf, lsm: Annotate lsm hook return integer with new macro LSM_RET_INT bpf, lsm: Add return value range description for lsm hook bpf, lsm: Add function to read lsm hook return value range bpf, lsm: Check bpf lsm hook return values in verifier bpf: Fix compare error in function retval_range_within include/linux/bpf.h | 1 + include/linux/bpf_lsm.h | 8 + include/linux/lsm_hook_defs.h | 433 +++++++++++++++++----------------- include/linux/lsm_hooks.h | 6 - kernel/bpf/bpf_lsm.c | 66 +++++- kernel/bpf/btf.c | 5 +- kernel/bpf/verifier.c | 59 ++++- security/security.c | 1 + 8 files changed, 348 insertions(+), 231 deletions(-) -- 2.30.2