]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
cgroup: add foreign program to cgroup context
authorJulia Kartseva <hex@fb.com>
Tue, 2 Mar 2021 00:56:04 +0000 (16:56 -0800)
committerJulia Kartseva <hex@fb.com>
Sat, 10 Apr 2021 03:28:47 +0000 (20:28 -0700)
- Store foreign bpf programs in cgroup context. A program is considered
foreign if it was loaded to a kernel by an entity external to systemd,
so systemd is responsible only for attach and detach paths.
- Support the case of pinned bpf programs: pinning to bpffs so a program
is kept loaded to the kernel even when program fd is closed by a user
application is a common way to extend program's lifetime.
- Aadd linked list node struct with attach type and bpffs path
fields.

src/core/cgroup.c
src/core/cgroup.h

index 96073b108b2e7674e88bd4b4936cf64bb0967a3a..85e90260d1fcb72828a9b1b7bb9cd7224a031db8 100644 (file)
@@ -190,6 +190,15 @@ void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockI
         free(b);
 }
 
+void cgroup_context_remove_bpf_foreign_program(CGroupContext *c, CGroupBPFForeignProgram *p) {
+        assert(c);
+        assert(p);
+
+        LIST_REMOVE(programs, c->bpf_foreign_programs, p);
+        free(p->bpffs_path);
+        free(p);
+}
+
 void cgroup_context_done(CGroupContext *c) {
         assert(c);
 
@@ -217,6 +226,9 @@ void cgroup_context_done(CGroupContext *c) {
         c->ip_filters_ingress = strv_free(c->ip_filters_ingress);
         c->ip_filters_egress = strv_free(c->ip_filters_egress);
 
+        while (c->bpf_foreign_programs)
+                cgroup_context_remove_bpf_foreign_program(c, c->bpf_foreign_programs);
+
         cpu_set_reset(&c->cpuset_cpus);
         cpu_set_reset(&c->cpuset_mems);
 }
@@ -360,6 +372,7 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
         CGroupIODeviceLatency *l;
         CGroupBlockIODeviceBandwidth *b;
         CGroupBlockIODeviceWeight *w;
+        CGroupBPFForeignProgram *p;
         CGroupDeviceAllow *a;
         CGroupContext *c;
         IPAddressAccessItem *iaai;
@@ -544,6 +557,10 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
 
         STRV_FOREACH(path, c->ip_filters_egress)
                 fprintf(f, "%sIPEgressFilterPath: %s\n", prefix, *path);
+
+        LIST_FOREACH(programs, p, c->bpf_foreign_programs)
+                fprintf(f, "%sBPFProgram: %s:%s",
+                        prefix, bpf_cgroup_attach_type_to_string(p->attach_type), p->bpffs_path);
 }
 
 int cgroup_add_device_allow(CGroupContext *c, const char *dev, const char *mode) {
@@ -575,6 +592,34 @@ int cgroup_add_device_allow(CGroupContext *c, const char *dev, const char *mode)
         return 0;
 }
 
+int cgroup_add_bpf_foreign_program(CGroupContext *c, uint32_t attach_type, const char *bpffs_path) {
+        CGroupBPFForeignProgram *p;
+        _cleanup_free_ char *d = NULL;
+
+        assert(c);
+        assert(bpffs_path);
+
+        if (!path_is_normalized(bpffs_path) || !path_is_absolute(bpffs_path))
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Path is not normalized: %m");
+
+        d = strdup(bpffs_path);
+        if (!d)
+                return log_oom();
+
+        p = new(CGroupBPFForeignProgram, 1);
+        if (!p)
+                return log_oom();
+
+        *p = (CGroupBPFForeignProgram) {
+                .attach_type = attach_type,
+                .bpffs_path = TAKE_PTR(d),
+        };
+
+        LIST_PREPEND(programs, c->bpf_foreign_programs, TAKE_PTR(p));
+
+        return 0;
+}
+
 #define UNIT_DEFINE_ANCESTOR_MEMORY_LOOKUP(entry)                       \
         uint64_t unit_get_ancestor_##entry(Unit *u) {                   \
                 CGroupContext *c;                                       \
index fa79ba15239e80407e3158343ce112f0c2bd039e..be3060eba7c06bf52949634bde21c1930ceebbd3 100644 (file)
@@ -31,6 +31,7 @@ typedef struct CGroupIODeviceLimit CGroupIODeviceLimit;
 typedef struct CGroupIODeviceLatency CGroupIODeviceLatency;
 typedef struct CGroupBlockIODeviceWeight CGroupBlockIODeviceWeight;
 typedef struct CGroupBlockIODeviceBandwidth CGroupBlockIODeviceBandwidth;
+typedef struct CGroupBPFForeignProgram CGroupBPFForeignProgram;
 
 typedef enum CGroupDevicePolicy {
         /* When devices listed, will allow those, plus built-in ones, if none are listed will allow
@@ -94,6 +95,12 @@ struct CGroupBlockIODeviceBandwidth {
         uint64_t wbps;
 };
 
+struct CGroupBPFForeignProgram {
+        LIST_FIELDS(CGroupBPFForeignProgram, programs);
+        uint32_t attach_type;
+        char *bpffs_path;
+};
+
 struct CGroupContext {
         bool cpu_accounting;
         bool io_accounting;
@@ -142,6 +149,7 @@ struct CGroupContext {
 
         char **ip_filters_ingress;
         char **ip_filters_egress;
+        LIST_HEAD(CGroupBPFForeignProgram, bpf_foreign_programs);
 
         /* For legacy hierarchies */
         uint64_t cpu_shares;
@@ -202,8 +210,10 @@ void cgroup_context_free_io_device_limit(CGroupContext *c, CGroupIODeviceLimit *
 void cgroup_context_free_io_device_latency(CGroupContext *c, CGroupIODeviceLatency *l);
 void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w);
 void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b);
+void cgroup_context_remove_bpf_foreign_program(CGroupContext *c, CGroupBPFForeignProgram *p);
 
 int cgroup_add_device_allow(CGroupContext *c, const char *dev, const char *mode);
+int cgroup_add_bpf_foreign_program(CGroupContext *c, uint32_t attach_type, const char *path);
 
 void cgroup_oomd_xattr_apply(Unit *u, const char *cgroup_path);