Merge branch 'for-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
[platform/kernel/linux-rpi.git] / kernel / cgroup / cgroup.c
index 33ff9ec..06b5ea9 100644 (file)
@@ -1813,12 +1813,14 @@ int cgroup_show_path(struct seq_file *sf, struct kernfs_node *kf_node,
 enum cgroup2_param {
        Opt_nsdelegate,
        Opt_memory_localevents,
+       Opt_memory_recursiveprot,
        nr__cgroup2_params
 };
 
 static const struct fs_parameter_spec cgroup2_fs_parameters[] = {
        fsparam_flag("nsdelegate",              Opt_nsdelegate),
        fsparam_flag("memory_localevents",      Opt_memory_localevents),
+       fsparam_flag("memory_recursiveprot",    Opt_memory_recursiveprot),
        {}
 };
 
@@ -1839,6 +1841,9 @@ static int cgroup2_parse_param(struct fs_context *fc, struct fs_parameter *param
        case Opt_memory_localevents:
                ctx->flags |= CGRP_ROOT_MEMORY_LOCAL_EVENTS;
                return 0;
+       case Opt_memory_recursiveprot:
+               ctx->flags |= CGRP_ROOT_MEMORY_RECURSIVE_PROT;
+               return 0;
        }
        return -EINVAL;
 }
@@ -1855,6 +1860,11 @@ static void apply_cgroup_root_flags(unsigned int root_flags)
                        cgrp_dfl_root.flags |= CGRP_ROOT_MEMORY_LOCAL_EVENTS;
                else
                        cgrp_dfl_root.flags &= ~CGRP_ROOT_MEMORY_LOCAL_EVENTS;
+
+               if (root_flags & CGRP_ROOT_MEMORY_RECURSIVE_PROT)
+                       cgrp_dfl_root.flags |= CGRP_ROOT_MEMORY_RECURSIVE_PROT;
+               else
+                       cgrp_dfl_root.flags &= ~CGRP_ROOT_MEMORY_RECURSIVE_PROT;
        }
 }
 
@@ -1864,6 +1874,8 @@ static int cgroup_show_options(struct seq_file *seq, struct kernfs_root *kf_root
                seq_puts(seq, ",nsdelegate");
        if (cgrp_dfl_root.flags & CGRP_ROOT_MEMORY_LOCAL_EVENTS)
                seq_puts(seq, ",memory_localevents");
+       if (cgrp_dfl_root.flags & CGRP_ROOT_MEMORY_RECURSIVE_PROT)
+               seq_puts(seq, ",memory_recursiveprot");
        return 0;
 }
 
@@ -6450,6 +6462,10 @@ void cgroup_sk_alloc(struct sock_cgroup_data *skcd)
                return;
        }
 
+       /* Don't associate the sock with unrelated interrupted task's cgroup. */
+       if (in_interrupt())
+               return;
+
        rcu_read_lock();
 
        while (true) {
@@ -6478,27 +6494,58 @@ void cgroup_sk_free(struct sock_cgroup_data *skcd)
 #endif /* CONFIG_SOCK_CGROUP_DATA */
 
 #ifdef CONFIG_CGROUP_BPF
-int cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
-                     struct bpf_prog *replace_prog, enum bpf_attach_type type,
+int cgroup_bpf_attach(struct cgroup *cgrp,
+                     struct bpf_prog *prog, struct bpf_prog *replace_prog,
+                     struct bpf_cgroup_link *link,
+                     enum bpf_attach_type type,
                      u32 flags)
 {
        int ret;
 
        mutex_lock(&cgroup_mutex);
-       ret = __cgroup_bpf_attach(cgrp, prog, replace_prog, type, flags);
+       ret = __cgroup_bpf_attach(cgrp, prog, replace_prog, link, type, flags);
+       mutex_unlock(&cgroup_mutex);
+       return ret;
+}
+
+int cgroup_bpf_replace(struct bpf_link *link, struct bpf_prog *old_prog,
+                      struct bpf_prog *new_prog)
+{
+       struct bpf_cgroup_link *cg_link;
+       int ret;
+
+       if (link->ops != &bpf_cgroup_link_lops)
+               return -EINVAL;
+
+       cg_link = container_of(link, struct bpf_cgroup_link, link);
+
+       mutex_lock(&cgroup_mutex);
+       /* link might have been auto-released by dying cgroup, so fail */
+       if (!cg_link->cgroup) {
+               ret = -EINVAL;
+               goto out_unlock;
+       }
+       if (old_prog && link->prog != old_prog) {
+               ret = -EPERM;
+               goto out_unlock;
+       }
+       ret = __cgroup_bpf_replace(cg_link->cgroup, cg_link, new_prog);
+out_unlock:
        mutex_unlock(&cgroup_mutex);
        return ret;
 }
+
 int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
-                     enum bpf_attach_type type, u32 flags)
+                     enum bpf_attach_type type)
 {
        int ret;
 
        mutex_lock(&cgroup_mutex);
-       ret = __cgroup_bpf_detach(cgrp, prog, type);
+       ret = __cgroup_bpf_detach(cgrp, prog, NULL, type);
        mutex_unlock(&cgroup_mutex);
        return ret;
 }
+
 int cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
                     union bpf_attr __user *uattr)
 {
@@ -6556,7 +6603,10 @@ static struct kobj_attribute cgroup_delegate_attr = __ATTR_RO(delegate);
 static ssize_t features_show(struct kobject *kobj, struct kobj_attribute *attr,
                             char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "nsdelegate\nmemory_localevents\n");
+       return snprintf(buf, PAGE_SIZE,
+                       "nsdelegate\n"
+                       "memory_localevents\n"
+                       "memory_recursiveprot\n");
 }
 static struct kobj_attribute cgroup_features_attr = __ATTR_RO(features);