diff mbox series

[16/18] bpf-preload: Do kernel mount to ensure that pinned objects don't disappear

Message ID 20220328175033.2437312-17-roberto.sassu@huawei.com (mailing list archive)
State Changes Requested
Delegated to: BPF
Headers show
Series bpf: Secure and authenticated preloading of eBPF programs | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR fail PR summary
netdev/tree_selection success Guessing tree name failed - patch did not apply, async

Commit Message

Roberto Sassu March 28, 2022, 5:50 p.m. UTC
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>
---
 fs/namespace.c      | 1 +
 include/linux/bpf.h | 5 +++++
 init/main.c         | 2 ++
 kernel/bpf/inode.c  | 9 +++++++++
 4 files changed, 17 insertions(+)

Comments

kernel test robot March 29, 2022, 2:15 a.m. UTC | #1
Hi Roberto,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on bpf-next/master]
[also build test ERROR on linus/master next-20220328]
[cannot apply to bpf/master v5.17]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/intel-lab-lkp/linux/commits/Roberto-Sassu/bpf-Secure-and-authenticated-preloading-of-eBPF-programs/20220329-015829
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
config: riscv-randconfig-c004-20220327 (https://download.01.org/0day-ci/archive/20220329/202203291034.vCkMuZo5-lkp@intel.com/config)
compiler: riscv64-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/eddbb1ec1e92ba00c4acc9f123769265e17e8e40
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Roberto-Sassu/bpf-Secure-and-authenticated-preloading-of-eBPF-programs/20220329-015829
        git checkout eddbb1ec1e92ba00c4acc9f123769265e17e8e40
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=riscv SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   kernel/bpf/inode.c:25:37: error: 'CONFIG_BPF_PRELOAD_LIST' undeclared here (not in a function)
      25 | static char *bpf_preload_list_str = CONFIG_BPF_PRELOAD_LIST;
         |                                     ^~~~~~~~~~~~~~~~~~~~~~~
>> kernel/bpf/inode.c:1026:13: error: redefinition of 'mount_bpffs'
    1026 | void __init mount_bpffs(void)
         |             ^~~~~~~~~~~
   In file included from include/linux/filter.h:9,
                    from kernel/bpf/inode.c:20:
   include/linux/bpf.h:1146:27: note: previous definition of 'mount_bpffs' with type 'void(void)'
    1146 | static inline void __init mount_bpffs(void)
         |                           ^~~~~~~~~~~


vim +/mount_bpffs +1026 kernel/bpf/inode.c

  1025	
> 1026	void __init mount_bpffs(void)
kernel test robot March 29, 2022, 4:08 a.m. UTC | #2
Hi Roberto,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on bpf-next/master]
[also build test ERROR on linus/master next-20220328]
[cannot apply to bpf/master v5.17]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/intel-lab-lkp/linux/commits/Roberto-Sassu/bpf-Secure-and-authenticated-preloading-of-eBPF-programs/20220329-015829
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
config: hexagon-randconfig-r041-20220328 (https://download.01.org/0day-ci/archive/20220329/202203291256.TUOyKEtD-lkp@intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 0f6d9501cf49ce02937099350d08f20c4af86f3d)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/eddbb1ec1e92ba00c4acc9f123769265e17e8e40
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Roberto-Sassu/bpf-Secure-and-authenticated-preloading-of-eBPF-programs/20220329-015829
        git checkout eddbb1ec1e92ba00c4acc9f123769265e17e8e40
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   kernel/bpf/inode.c:25:37: error: use of undeclared identifier 'CONFIG_BPF_PRELOAD_LIST'
   static char *bpf_preload_list_str = CONFIG_BPF_PRELOAD_LIST;
                                       ^
>> kernel/bpf/inode.c:1026:13: error: redefinition of 'mount_bpffs'
   void __init mount_bpffs(void)
               ^
   include/linux/bpf.h:1146:27: note: previous definition is here
   static inline void __init mount_bpffs(void)
                             ^
   2 errors generated.


vim +/mount_bpffs +1026 kernel/bpf/inode.c

  1025	
> 1026	void __init mount_bpffs(void)
diff mbox series

Patch

diff --git a/fs/namespace.c b/fs/namespace.c
index 6e9844b8c6fb..3b69f96dc641 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -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"
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index bdb5298735ce..5f624310fda2 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -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 {
@@ -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 {
diff --git a/init/main.c b/init/main.c
index 0c064c2c79fd..30dcd0dd9faa 100644
--- a/init/main.c
+++ b/init/main.c
@@ -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>
@@ -1638,4 +1639,5 @@  static noinline void __init kernel_init_freeable(void)
 	 */
 
 	integrity_load_keys();
+	mount_bpffs();
 }
diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
index c1941c65ce95..e8361d7679d0 100644
--- a/kernel/bpf/inode.c
+++ b/kernel/bpf/inode.c
@@ -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");
+}