Thread (29 messages) 29 messages, 5 authors, 2023-10-12

Re: [PATCH v6 bpf-next 04/13] bpf: add BPF token support to BPF_MAP_CREATE command

From: Andrii Nakryiko <hidden>
Date: 2023-10-12 00:31:10
Also in: bpf, linux-fsdevel, netdev

On Tue, Oct 10, 2023 at 1:35 AM Jiri Olsa [off-list ref] wrote:
On Wed, Sep 27, 2023 at 03:58:00PM -0700, Andrii Nakryiko wrote:

SNIP
quoted
-#define BPF_MAP_CREATE_LAST_FIELD map_extra
+#define BPF_MAP_CREATE_LAST_FIELD map_token_fd
 /* called via syscall */
 static int map_create(union bpf_attr *attr)
 {
      const struct bpf_map_ops *ops;
+     struct bpf_token *token = NULL;
      int numa_node = bpf_map_attr_numa_node(attr);
      u32 map_type = attr->map_type;
      struct bpf_map *map;
@@ -1157,14 +1158,32 @@ static int map_create(union bpf_attr *attr)
      if (!ops->map_mem_usage)
              return -EINVAL;

+     if (attr->map_token_fd) {
+             token = bpf_token_get_from_fd(attr->map_token_fd);
+             if (IS_ERR(token))
+                     return PTR_ERR(token);
+
+             /* if current token doesn't grant map creation permissions,
+              * then we can't use this token, so ignore it and rely on
+              * system-wide capabilities checks
+              */
+             if (!bpf_token_allow_cmd(token, BPF_MAP_CREATE) ||
+                 !bpf_token_allow_map_type(token, attr->map_type)) {
+                     bpf_token_put(token);
+                     token = NULL;
+             }
+     }
+
+     err = -EPERM;
+
      /* Intent here is for unprivileged_bpf_disabled to block BPF map
       * creation for unprivileged users; other actions depend
       * on fd availability and access to bpffs, so are dependent on
       * object creation success. Even with unprivileged BPF disabled,
       * capability checks are still carried out.
       */
-     if (sysctl_unprivileged_bpf_disabled && !bpf_capable())
-             return -EPERM;
+     if (sysctl_unprivileged_bpf_disabled && !bpf_token_capable(token, CAP_BPF))
+             goto put_token;

      /* check privileged map type permissions */
      switch (map_type) {
@@ -1197,25 +1216,27 @@ static int map_create(union bpf_attr *attr)
      case BPF_MAP_TYPE_LRU_PERCPU_HASH:
      case BPF_MAP_TYPE_STRUCT_OPS:
      case BPF_MAP_TYPE_CPUMAP:
-             if (!bpf_capable())
-                     return -EPERM;
+             if (!bpf_token_capable(token, CAP_BPF))
+                     goto put_token;
              break;
      case BPF_MAP_TYPE_SOCKMAP:
      case BPF_MAP_TYPE_SOCKHASH:
      case BPF_MAP_TYPE_DEVMAP:
      case BPF_MAP_TYPE_DEVMAP_HASH:
      case BPF_MAP_TYPE_XSKMAP:
-             if (!bpf_net_capable())
-                     return -EPERM;
+             if (!bpf_token_capable(token, CAP_NET_ADMIN))
+                     goto put_token;
              break;
      default:
              WARN(1, "unsupported map type %d", map_type);
-             return -EPERM;
+             goto put_token;
      }

      map = ops->map_alloc(attr);
-     if (IS_ERR(map))
-             return PTR_ERR(map);
+     if (IS_ERR(map)) {
+             err = PTR_ERR(map);
+             goto put_token;
+     }
      map->ops = ops;
      map->map_type = map_type;
@@ -1252,7 +1273,7 @@ static int map_create(union bpf_attr *attr)
              map->btf = btf;

              if (attr->btf_value_type_id) {
-                     err = map_check_btf(map, btf, attr->btf_key_type_id,
+                     err = map_check_btf(map, token, btf, attr->btf_key_type_id,
                                          attr->btf_value_type_id);
                      if (err)
                              goto free_map;
I might be missing something, but should we call bpf_token_put(token)
on non-error path as well? probably after bpf_map_save_memcg call
Not missing anything. I used to keep token reference inside struct
bpf_map on success, but I ripped that out, so yes, token has to be put
properly even on success. Thanks for catching this!

And yes, right after bpf_map_save_memcg() seems like the best spot.

jirka
quoted
@@ -1293,6 +1314,8 @@ static int map_create(union bpf_attr *attr)
 free_map:
      btf_put(map->btf);
      map->ops->map_free(map);
+put_token:
+     bpf_token_put(token);
      return err;
 }
SNIP
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help