Re: BPF LSM and fexit [was: [PATCH bpf-next v3 04/10] bpf: lsm: Add mutable hooks list for the BPF LSM]
From: Daniel Borkmann <daniel@iogearbox.net>
Date: 2020-02-12 00:09:17
Also in:
bpf, lkml
On 2/12/20 12:26 AM, Alexei Starovoitov wrote:
On Tue, Feb 11, 2020 at 1:38 PM Alexei Starovoitov [off-list ref] wrote:quoted
On Tue, Feb 11, 2020 at 09:33:49PM +0100, Jann Horn wrote:quoted
quoted
Got it. Then let's whitelist them ? All error injection points are marked with ALLOW_ERROR_INJECTION(). We can do something similar here, but let's do it via BTF and avoid abusing yet another elf section for this mark. I think BTF_TYPE_EMIT() should work. Just need to pick explicit enough name and extensive comment about what is going on.Sounds reasonable to me. :)awesome :)Looks like the kernel already provides this whitelisting. $ bpftool btf dump file /sys/kernel/btf/vmlinux |grep FUNC|grep '\<security_' gives the list of all LSM hooks that lsm-bpf will be able to attach to. There are two exceptions there security_add_hooks() and security_init(). Both are '__init'. Too late for lsm-bpf to touch. So filtering BTF funcs by 'security_' prefix will be enough. It should be documented though. The number of attachable funcs depends on kconfig which is a nice property and further strengthen the point that lsm-bpf is very much kernel specific. We probably should blacklist security_bpf*() hooks though.
One thing that is not quite clear to me wrt the fexit approach; assuming
we'd whitelist something like security_inode_link():
int security_inode_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *new_dentry)
{
if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
return 0;
return call_int_hook(inode_link, 0, old_dentry, dir, new_dentry);
}
Would this then mean the BPF prog needs to reimplement above check by
probing old_dentry->d_inode to later ensure its verdict stays 0 there
too, or that such extra code is to be moved to call-sites instead? If
former, what about more complex logic?
Another approach could be to have a special nop inside call_int_hook()
macro which would then get patched to avoid these situations. Somewhat
similar like static keys where it could be defined anywhere in text but
with updating of call_int_hook()'s RC for the verdict.
Thanks,
Daniel