Skip to content

Commit 238cf79

Browse files
ebiedermdtcccc
authored andcommitted
cgroup-v1: Require capabilities to set release_agent
ANBZ: torvalds#432 commit 12e1ce08da69be233d6827856c0f282da1023bb5 amazonlinux. The cgroup release_agent is called with call_usermodehelper. The function call_usermodehelper starts the release_agent with a full set fo capabilities. Therefore require capabilities when setting the release_agaent. Reported-by: Tabitha Sable <[email protected]> Tested-by: Tabitha Sable <[email protected]> Fixes: 81a6a5c ("Task Control Groups: automatic userspace notification of idle cgroups") Cc: [email protected] # v2.6.24+ Signed-off-by: "Eric W. Biederman" <[email protected]> Signed-off-by: Tejun Heo <[email protected]> [fllinden: modified for 4.14 for the mount options path, by looking up the right user namespace (like the fs context code) and passing it to parse_cgroupfs_options for a check] Signed-off-by: Frank van der Linden <[email protected]> Signed-off-by: Tianchen Ding <[email protected]> Acked-by: Michael Wang <[email protected]>
1 parent 406145c commit 238cf79

File tree

1 file changed

+29
-3
lines changed

1 file changed

+29
-3
lines changed

kernel/cgroup/cgroup-v1.c

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,15 @@ static ssize_t cgroup_release_agent_write(struct kernfs_open_file *of,
579579

580580
BUILD_BUG_ON(sizeof(cgrp->root->release_agent_path) < PATH_MAX);
581581

582+
/*
583+
* Release agent gets called with all capabilities,
584+
* require capabilities to set release agent.
585+
*/
586+
587+
if ((of->file->f_cred->user_ns != &init_user_ns) ||
588+
!capable(CAP_SYS_ADMIN))
589+
return -EPERM;
590+
582591
cgrp = cgroup_kn_lock_live(of->kn, false);
583592
if (!cgrp)
584593
return -ENODEV;
@@ -1032,7 +1041,8 @@ static int cgroup1_show_options(struct seq_file *seq, struct kernfs_root *kf_roo
10321041
return 0;
10331042
}
10341043

1035-
static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
1044+
static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts,
1045+
struct user_namespace *user_ns)
10361046
{
10371047
char *token, *o = data;
10381048
bool all_ss = false, one_ss = false;
@@ -1084,6 +1094,13 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
10841094
/* Specifying two release agents is forbidden */
10851095
if (opts->release_agent)
10861096
return -EINVAL;
1097+
1098+
/*
1099+
* Release agent gets called with all capabilities,
1100+
* require capabilities to set release agent.
1101+
*/
1102+
if ((user_ns != &init_user_ns) || !capable(CAP_SYS_ADMIN))
1103+
return -EPERM;
10871104
opts->release_agent =
10881105
kstrndup(token + 14, PATH_MAX - 1, GFP_KERNEL);
10891106
if (!opts->release_agent)
@@ -1174,11 +1191,17 @@ static int cgroup1_remount(struct kernfs_root *kf_root, int *flags, char *data)
11741191
struct cgroup_root *root = cgroup_root_from_kf(kf_root);
11751192
struct cgroup_sb_opts opts;
11761193
u16 added_mask, removed_mask;
1194+
struct user_namespace *user_ns;
1195+
struct super_block *sb;
11771196

11781197
cgroup_lock_and_drain_offline(&cgrp_dfl_root.cgrp);
11791198

1199+
sb = kernfs_pin_sb(kf_root, NULL);
1200+
user_ns = get_user_ns(sb->s_user_ns);
11801201
/* See what subsystems are wanted */
1181-
ret = parse_cgroupfs_options(data, &opts);
1202+
ret = parse_cgroupfs_options(data, &opts, user_ns);
1203+
put_user_ns(user_ns);
1204+
deactivate_super(sb);
11821205
if (ret)
11831206
goto out_unlock;
11841207

@@ -1245,11 +1268,14 @@ struct dentry *cgroup1_mount(struct file_system_type *fs_type, int flags,
12451268
struct dentry *dentry;
12461269
int i, ret;
12471270
bool new_root = false;
1271+
struct user_namespace *user_ns;
12481272

12491273
cgroup_lock_and_drain_offline(&cgrp_dfl_root.cgrp);
12501274

1275+
user_ns = get_user_ns(get_current_cred()->user_ns);
12511276
/* First find the desired set of subsystems */
1252-
ret = parse_cgroupfs_options(data, &opts);
1277+
ret = parse_cgroupfs_options(data, &opts, user_ns);
1278+
put_user_ns(user_ns);
12531279
if (ret)
12541280
goto out_unlock;
12551281

0 commit comments

Comments
 (0)