#6 Backport unnamed BPF changes (#22214, ##22279)
Merged 3 years ago by daandemeyer. Opened 3 years ago by daandemeyer.
centos-sig-hyperscale/ daandemeyer/systemd backport-name-unnamed-bpf  into  fb-v250.3

bpf: name unnamed bpf programs
Julia Kartseva • 3 years ago  
file modified
+2 -2
@@ -192,7 +192,7 @@ 

          if (policy == CGROUP_DEVICE_POLICY_AUTO && !allow_list)

                  return 0;

  

-         r = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE, &prog);

+         r = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE, "sd_devices", &prog);

          if (r < 0)

                  return log_error_errno(r, "Loading device control BPF program failed: %m");

  
@@ -306,7 +306,7 @@ 

                  return supported = 0;

          }

  

-         r = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE, &program);

+         r = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE, "sd_devices", &program);

          if (r < 0) {

                  log_debug_errno(r, "Can't allocate CGROUP DEVICE BPF program, BPF device control is not supported: %m");

                  return supported = 0;

file modified
+19 -7
@@ -145,6 +145,7 @@ 

  

  static int bpf_firewall_compile_bpf(

                  Unit *u,

+                 const char *prog_name,

                  bool is_ingress,

                  BPFProgram **ret,

                  bool ip_allow_any,
@@ -216,7 +217,7 @@ 

                  return 0;

          }

  

-         r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, &p);

+         r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, prog_name, &p);

          if (r < 0)

                  return r;

  
@@ -526,9 +527,10 @@ 

  }

  

  int bpf_firewall_compile(Unit *u) {

+         const char *ingress_name = NULL, *egress_name = NULL;

+         bool ip_allow_any = false, ip_deny_any = false;

          CGroupContext *cc;

          int r, supported;

-         bool ip_allow_any = false, ip_deny_any = false;

  

          assert(u);

  
@@ -551,6 +553,13 @@ 

                  return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP),

                                              "BPF_F_ALLOW_MULTI is not supported on this manager, not doing BPF firewall on slice units.");

  

+         /* If BPF_F_ALLOW_MULTI flag is supported program name is also supported (both were added to v4.15

+          * kernel). */

+         if (supported == BPF_FIREWALL_SUPPORTED_WITH_MULTI) {

+                 ingress_name = "sd_fw_ingress";

+                 egress_name = "sd_fw_egress";

+         }

+ 

          /* Note that when we compile a new firewall we first flush out the access maps and the BPF programs themselves,

           * but we reuse the accounting maps. That way the firewall in effect always maps to the actual

           * configuration, but we don't flush out the accounting unnecessarily */
@@ -584,11 +593,11 @@ 

          if (r < 0)

                  return log_unit_error_errno(u, r, "Preparation of eBPF accounting maps failed: %m");

  

-         r = bpf_firewall_compile_bpf(u, true, &u->ip_bpf_ingress, ip_allow_any, ip_deny_any);

+         r = bpf_firewall_compile_bpf(u, ingress_name, true, &u->ip_bpf_ingress, ip_allow_any, ip_deny_any);

          if (r < 0)

                  return log_unit_error_errno(u, r, "Compilation for ingress BPF program failed: %m");

  

-         r = bpf_firewall_compile_bpf(u, false, &u->ip_bpf_egress, ip_allow_any, ip_deny_any);

+         r = bpf_firewall_compile_bpf(u, egress_name, false, &u->ip_bpf_egress, ip_allow_any, ip_deny_any);

          if (r < 0)

                  return log_unit_error_errno(u, r, "Compilation for egress BPF program failed: %m");

  
@@ -604,7 +613,7 @@ 

                  _cleanup_(bpf_program_freep) BPFProgram *prog = NULL;

                  int r;

  

-                 r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, &prog);

+                 r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, NULL, &prog);

                  if (r < 0)

                          return log_unit_error_errno(u, r, "Can't allocate CGROUP SKB BPF program: %m");

  
@@ -825,7 +834,8 @@ 

                  return supported = BPF_FIREWALL_UNSUPPORTED;

          }

  

-         r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, &program);

+         /* prog_name is NULL since it is supported only starting from v4.15 kernel. */

+         r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, NULL, &program);

          if (r < 0) {

                  bpf_firewall_unsupported_reason =

                          log_debug_errno(r, "Can't allocate CGROUP SKB BPF program, BPF firewalling is not supported: %m");
@@ -882,7 +892,9 @@ 

          /* So now we know that the BPF program is generally available, let's see if BPF_F_ALLOW_MULTI is also supported

           * (which was added in kernel 4.15). We use a similar logic as before, but this time we use the BPF_PROG_ATTACH

           * bpf() call and the BPF_F_ALLOW_MULTI flags value. Since the flags are checked early in the system call we'll

-          * get EINVAL if it's not supported, and EBADF as before if it is available. */

+          * get EINVAL if it's not supported, and EBADF as before if it is available.

+          * Use probe result as the indicator that program name is also supported since they both were

+          * added in kernel 4.15. */

  

          zero(attr);

          attr.attach_type = BPF_CGROUP_INET_EGRESS;

file modified
+15 -1
@@ -55,6 +55,7 @@ 

          (void) bpf_program_cgroup_detach(p);

  

          safe_close(p->kernel_fd);

+         free(p->prog_name);

          free(p->instructions);

          free(p->attached_path);

  
@@ -78,8 +79,18 @@ 

          return RET_NERRNO(bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr)));

  }

  

- int bpf_program_new(uint32_t prog_type, BPFProgram **ret) {

+ int bpf_program_new(uint32_t prog_type, const char *prog_name, BPFProgram **ret) {

          _cleanup_(bpf_program_freep) BPFProgram *p = NULL;

+         _cleanup_free_ char *name = NULL;

+ 

+         if (prog_name) {

+                 if (strlen(prog_name) >= BPF_OBJ_NAME_LEN)

+                         return -ENAMETOOLONG;

+ 

+                 name = strdup(prog_name);

+                 if (!name)

+                         return -ENOMEM;

+         }

  

          p = new(BPFProgram, 1);

          if (!p)
@@ -88,6 +99,7 @@ 

          *p = (BPFProgram) {

                  .prog_type = prog_type,

                  .kernel_fd = -1,

+                 .prog_name = TAKE_PTR(name),

          };

  

          *ret = TAKE_PTR(p);
@@ -165,6 +177,8 @@ 

          attr.log_buf = PTR_TO_UINT64(log_buf);

          attr.log_level = !!log_buf;

          attr.log_size = log_size;

+         if (p->prog_name)

+                 strncpy(attr.prog_name, p->prog_name, BPF_OBJ_NAME_LEN - 1);

  

          p->kernel_fd = bpf(BPF_PROG_LOAD, &attr, sizeof(attr));

          if (p->kernel_fd < 0)

file modified
+2 -1
@@ -20,6 +20,7 @@ 

          /* The loaded BPF program, if loaded */

          int kernel_fd;

          uint32_t prog_type;

+         char *prog_name;

  

          /* The code of it BPF program, if known */

          size_t n_instructions;
@@ -32,7 +33,7 @@ 

          uint32_t attached_flags;

  };

  

- int bpf_program_new(uint32_t prog_type, BPFProgram **ret);

+ int bpf_program_new(uint32_t prog_type, const char *prog_name, BPFProgram **ret);

  int bpf_program_new_from_bpffs_path(const char *path, BPFProgram **ret);

  BPFProgram *bpf_program_free(BPFProgram *p);

  

file modified
+1 -1
@@ -55,7 +55,7 @@ 

          assert_se(set_unit_path(unit_dir) >= 0);

          assert_se(runtime_dir = setup_fake_runtime_dir());

  

-         r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, &p);

+         r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, "sd_trivial", &p);

          assert_se(r == 0);

  

          r = bpf_program_add_instructions(p, exit_insn, ELEMENTSOF(exit_insn));

@@ -162,7 +162,7 @@ 

                  if (r < 0)

                          return log_error_errno(r, "Failed to convert program to string");

  

-                 r = bpf_program_new(test_suite[i].prog_type, &prog);

+                 r = bpf_program_new(test_suite[i].prog_type, "sd_trivial", &prog);

                  if (r < 0)

                          return log_error_errno(r, "Failed to create program '%s'", str);

  

Both commits applied cleanly so no conflicts had to be resolved. Didn't test these changes yet as I don't know how.

rebased onto f88cbaa

3 years ago

Pull-Request has been merged by daandemeyer

3 years ago