trace: use standard POSIX header for basename()
[project/procd.git] / jail / cgroups.c
index fc2bbebcf9c129076c2020e87102f22d71d44bf8..2d3dce4d31acc25b0c4c38643e55928f7743847f 100644 (file)
  * https://github.com/containers/crun/blob/0.14.1/crun.1.md#cgroup-v2
  *
  * ToDo:
- *  - convert cgroup1 devices to eBPF program
  *  - convert cgroup1 net_prio and net_cls to eBPF program
  *  - rdma (anyone?) intelrdt (anyone?)
  */
 
 #define _GNU_SOURCE
 
-#include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <stdlib.h>
@@ -43,6 +41,7 @@
 
 #include "log.h"
 #include "cgroups.h"
+#include "cgroups-bpf.h"
 
 #define CGROUP_ROOT "/sys/fs/cgroup/"
 #define CGROUP_IO_WEIGHT_MAX 10000
@@ -73,7 +72,9 @@ static void cgroups_set(const char *key, const char *val)
        valp = avl_find_element(&cgvals, key, valp, avl);
        if (!valp) {
                valp = malloc(sizeof(struct cgval));
-               assert(valp != NULL);
+               if (!valp)
+                       exit(ENOMEM);
+
                valp->avl.key = strdup(key);
                avl_insert(&cgvals, &valp->avl);
        } else {
@@ -137,7 +138,7 @@ void cgroups_apply(pid_t pid)
                else if (!strncmp("pids.", ent, 5))
                        pids = true;
                else if (!strncmp("rdma.", ent, 5))
-                       pids = true;
+                       rdma = true;
        }
 
        maxlen += strlen(cgroup_path) + 2;
@@ -168,7 +169,8 @@ void cgroups_apply(pid_t pid)
        *ent = '\0';
 
        ent = malloc(maxlen);
-       assert(ent != 0);
+       if (!ent)
+               exit(ENOMEM);
 
        DEBUG("recursively applying cgroup.subtree_control = \"%s\"\n", subtree_control);
        cdir = &cgroup_path[strlen(CGROUP_ROOT) - 2];
@@ -176,9 +178,17 @@ void cgroups_apply(pid_t pid)
                *cdir = '\0';
                snprintf(ent, maxlen, "%s/cgroup.subtree_control", cgroup_path);
                DEBUG(" * %s\n", ent);
-               fd = open(ent, O_WRONLY);
-               assert(fd != -1);
-               write(fd, subtree_control, strlen(subtree_control));
+               if ((fd = open(ent, O_WRONLY)) < 0) {
+                       ERROR("can't open %s: %m\n", ent);
+                       continue;
+               }
+
+               if (write(fd, subtree_control, strlen(subtree_control)) == -1) {
+                       ERROR("can't write to %s: %m\n", ent);
+                       close(fd);
+                       continue;
+               }
+
                close(fd);
                *cdir = '/';
        }
@@ -187,7 +197,7 @@ void cgroups_apply(pid_t pid)
                DEBUG("applying cgroup2 %s=\"%s\"\n", (char *)valp->avl.key, valp->val);
                snprintf(ent, maxlen, "%s/%s", cgroup_path, (char *)valp->avl.key);
                fd = open(ent, O_WRONLY);
-               if (fd == -1) {
+               if (fd < 0) {
                        ERROR("can't open %s: %m\n", ent);
                        continue;
                }
@@ -197,11 +207,22 @@ void cgroups_apply(pid_t pid)
                close(fd);
        }
 
+       int dirfd = open(cgroup_path, O_DIRECTORY);
+       if (dirfd < 0) {
+               ERROR("can't open %s: %m\n", cgroup_path);
+       } else {
+               attach_cgroups_ebpf(dirfd);
+               close(dirfd);
+       }
+
        snprintf(ent, maxlen, "%s/%s", cgroup_path, "cgroup.procs");
        fd = open(ent, O_WRONLY);
-       assert(fd != -1);
-       dprintf(fd, "%d", pid);
-       close(fd);
+       if (fd < 0) {
+               ERROR("can't open %s: %m\n", cgroup_path);
+       } else {
+               dprintf(fd, "%d", pid);
+               close(fd);
+       }
 
        free(ent);
 }
@@ -297,7 +318,9 @@ static struct iomax_line *get_iomax_line(struct avl_tree *iomax, uint64_t major,
        l = avl_find_element(iomax, &d, l, avl);
        if (!l) {
                l = malloc(sizeof(struct iomax_line));
-               assert(l != NULL);
+               if (!l)
+                       exit(ENOMEM);
+
                l->dev.major = d.major;
                l->dev.minor = d.minor;
                l->avl.key = &l->dev;
@@ -345,11 +368,14 @@ static int parseOCIlinuxcgroups_legacy_blockio(struct blob_attr *msg)
                ++numweightstrs;
 
        weightstrs = calloc(numweightstrs + 1, sizeof(char *));
-       assert(weightstrs != 0);
+       if (!weightstrs)
+               exit(ENOMEM);
+
        numweightstrs = 0;
 
        if (weight > -1)
-               asprintf(&weightstrs[numweightstrs++], "default %d", weight);
+               if (asprintf(&weightstrs[numweightstrs++], "default %d", weight) < 0)
+                       return ENOMEM;
 
        blobmsg_for_each_attr(cur, tb[OCI_LINUX_CGROUPS_BLOCKIO_WEIGHTDEVICE], rem) {
                uint64_t major, minor;
@@ -382,7 +408,8 @@ static int parseOCIlinuxcgroups_legacy_blockio(struct blob_attr *msg)
                major = blobmsg_cast_u64(tbwd[OCI_LINUX_CGROUPS_BLOCKIO_WEIGHTDEVICE_MAJOR]);
                minor = blobmsg_cast_u64(tbwd[OCI_LINUX_CGROUPS_BLOCKIO_WEIGHTDEVICE_MINOR]);
 
-               asprintf(&weightstrs[numweightstrs++], "%" PRIu64 ":%" PRIu64 " %u", major, minor, devweight);
+               if (asprintf(&weightstrs[numweightstrs++], "%" PRIu64 ":%" PRIu64 " %u", major, minor, devweight) < 0)
+                       return ENOMEM;
        }
 
        if (numweightstrs) {
@@ -391,7 +418,8 @@ static int parseOCIlinuxcgroups_legacy_blockio(struct blob_attr *msg)
                        strtotlen += strlen(*(curstr++)) + 1;
 
                weightstr = calloc(strtotlen, sizeof(char));
-               assert(weightstr != 0);
+               if (!weightstr)
+                       exit(ENOMEM);
 
                curstr = weightstrs;
                while (*curstr) {
@@ -483,7 +511,9 @@ static int parseOCIlinuxcgroups_legacy_blockio(struct blob_attr *msg)
                return 0;
 
        iomaxstrs = calloc(numiomaxstrs + 1, sizeof(char *));
-       assert(iomaxstrs != 0);
+       if (!iomaxstrs)
+               exit(ENOMEM);
+
        numiomaxstrs = 0;
 
        avl_for_each_element(&iomax, curiomax, avl) {
@@ -524,7 +554,9 @@ static int parseOCIlinuxcgroups_legacy_blockio(struct blob_attr *msg)
                        strtotlen += strlen(*(curstr++)) + 1; /* +1 accounts for \n at end of line */
 
                iomaxstr = calloc(strtotlen, sizeof(char));
-               assert(iomaxstr != 0);
+               if (!iomaxstr)
+                       exit(ENOMEM);
+
                curstr = iomaxstrs;
 
                while (*curstr) {
@@ -644,7 +676,7 @@ static int parseOCIlinuxcgroups_legacy_memory(struct blob_attr *msg)
 {
        struct blob_attr *tb[__OCI_LINUX_CGROUPS_MEMORY_MAX];
        char tmp[32] = { 0 };
-       int64_t limit, swap, reservation;
+       int64_t limit = -1, swap, reservation;
 
        blobmsg_parse(oci_linux_cgroups_memory_policy, __OCI_LINUX_CGROUPS_MEMORY_MAX, tb, blobmsg_data(msg), blobmsg_len(msg));
 
@@ -785,8 +817,7 @@ int parseOCIlinuxcgroups(struct blob_attr *msg)
 
        blobmsg_parse(oci_linux_cgroups_policy, __OCI_LINUX_CGROUPS_MAX, tb, blobmsg_data(msg), blobmsg_len(msg));
 
-       if (tb[OCI_LINUX_CGROUPS_DEVICES] ||
-           tb[OCI_LINUX_CGROUPS_HUGEPAGELIMITS] ||
+       if (tb[OCI_LINUX_CGROUPS_HUGEPAGELIMITS] ||
            tb[OCI_LINUX_CGROUPS_INTELRDT] ||
            tb[OCI_LINUX_CGROUPS_NETWORK] ||
            tb[OCI_LINUX_CGROUPS_RDMA])
@@ -804,6 +835,12 @@ int parseOCIlinuxcgroups(struct blob_attr *msg)
                        return ret;
        }
 
+       if (tb[OCI_LINUX_CGROUPS_DEVICES]) {
+               ret = parseOCIlinuxcgroups_devices(tb[OCI_LINUX_CGROUPS_DEVICES]);
+               if (ret)
+                       return ret;
+       }
+
        if (tb[OCI_LINUX_CGROUPS_MEMORY]) {
                ret = parseOCIlinuxcgroups_legacy_memory(tb[OCI_LINUX_CGROUPS_MEMORY]);
                if (ret)