Skip to content

Commit

Permalink
bpf-preload: Do kernel mount to ensure that pinned objects don't disa…
Browse files Browse the repository at this point in the history
…ppear

One of the differences between traditional LSMs in the security subsystem
and LSMs implemented as eBPF programs is that for the latter category it
cannot be guaranteed that they cannot be stopped.

If a pinned program is unpinned, its execution will be stopped and will not
enforce anymore its policy. For traditional LSMs this problem does not
arise as, once they are invoked by the kernel, only the LSMs themselves
decide whether or not they could be stopped.

Solve this problem by mounting the bpf filesystem from the kernel, so that
an object cannot be unpinned (a kernel mount is not accessible to user
space). This will ensure that the LSM will run until the very end of the
kernel lifecycle.

Delay the kernel mount until the security subsystem (e.g. IMA) is fully
initialized (e.g. keys loaded), so that the security subsystem can evaluate
kernel modules loaded by populate_bpffs().

Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
  • Loading branch information
robertosassu authored and intel-lab-lkp committed Mar 28, 2022
1 parent bdcbabb commit eddbb1e
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 0 deletions.
1 change: 1 addition & 0 deletions fs/namespace.c
Expand Up @@ -31,6 +31,7 @@
#include <uapi/linux/mount.h>
#include <linux/fs_context.h>
#include <linux/shmem_fs.h>
#include <linux/bpf.h>
#include <linux/mnt_idmapping.h>

#include "pnode.h"
Expand Down
5 changes: 5 additions & 0 deletions include/linux/bpf.h
Expand Up @@ -1103,6 +1103,8 @@ static inline void bpf_module_put(const void *data, struct module *owner)
module_put(owner);
}

void __init mount_bpffs(void);

#ifdef CONFIG_NET
/* Define it here to avoid the use of forward declaration */
struct bpf_dummy_ops_state {
Expand Down Expand Up @@ -1141,6 +1143,9 @@ static inline int bpf_struct_ops_map_sys_lookup_elem(struct bpf_map *map,
{
return -EINVAL;
}
static inline void __init mount_bpffs(void)
{
}
#endif

struct bpf_array {
Expand Down
2 changes: 2 additions & 0 deletions init/main.c
Expand Up @@ -99,6 +99,7 @@
#include <linux/kcsan.h>
#include <linux/init_syscalls.h>
#include <linux/stackdepot.h>
#include <linux/bpf.h>
#include <net/net_namespace.h>

#include <asm/io.h>
Expand Down Expand Up @@ -1638,4 +1639,5 @@ static noinline void __init kernel_init_freeable(void)
*/

integrity_load_keys();
mount_bpffs();
}
9 changes: 9 additions & 0 deletions kernel/bpf/inode.c
Expand Up @@ -1020,3 +1020,12 @@ static int __init bpf_init(void)
return ret;
}
fs_initcall(bpf_init);

static struct vfsmount *bpffs_mount __read_mostly;

void __init mount_bpffs(void)
{
bpffs_mount = kern_mount(&bpf_fs_type);
if (IS_ERR(bpffs_mount))
pr_err("bpffs: could not mount!\n");
}

0 comments on commit eddbb1e

Please sign in to comment.