Skip to content

Commit 351cf87

Browse files
committed
Disable mounting cgroups by default ([email protected] via rkanter)
1 parent d5eca1a commit 351cf87

File tree

4 files changed

+55
-24
lines changed

4 files changed

+55
-24
lines changed

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ static const char* DEFAULT_BANNED_USERS[] = {"yarn", "mapred", "hdfs", "bin", 0}
7373

7474
static const int DEFAULT_DOCKER_SUPPORT_ENABLED = 0;
7575
static const int DEFAULT_TC_SUPPORT_ENABLED = 0;
76+
static const int DEFAULT_MOUNT_CGROUP_SUPPORT_ENABLED = 0;
7677

7778
static const char* PROC_PATH = "/proc";
7879

@@ -482,6 +483,12 @@ int is_tc_support_enabled() {
482483
DEFAULT_TC_SUPPORT_ENABLED, &executor_cfg);
483484
}
484485

486+
int is_mount_cgroups_support_enabled() {
487+
return is_feature_enabled(MOUNT_CGROUP_SUPPORT_ENABLED_KEY,
488+
DEFAULT_MOUNT_CGROUP_SUPPORT_ENABLED,
489+
&executor_cfg);
490+
}
491+
485492
/**
486493
* Utility function to concatenate argB to argA using the concat_pattern.
487494
*/
@@ -2346,20 +2353,25 @@ void chown_dir_contents(const char *dir_path, uid_t uid, gid_t gid) {
23462353
DIR *dp;
23472354
struct dirent *ep;
23482355

2349-
char *path_tmp = malloc(strlen(dir_path) + NAME_MAX + 2);
2356+
size_t len = strlen(dir_path) + NAME_MAX + 2;
2357+
char *path_tmp = malloc(len);
23502358
if (path_tmp == NULL) {
23512359
return;
23522360
}
23532361

2354-
char *buf = stpncpy(path_tmp, dir_path, strlen(dir_path));
2355-
*buf++ = '/';
2356-
23572362
dp = opendir(dir_path);
23582363
if (dp != NULL) {
23592364
while ((ep = readdir(dp)) != NULL) {
2360-
stpncpy(buf, ep->d_name, strlen(ep->d_name));
2361-
buf[strlen(ep->d_name)] = '\0';
2362-
change_owner(path_tmp, uid, gid);
2365+
if (strcmp(ep->d_name, ".") != 0 &&
2366+
strcmp(ep->d_name, "..") != 0 &&
2367+
strstr(ep->d_name, "..") == NULL) {
2368+
int result = snprintf(path_tmp, len, "%s/%s", dir_path, ep->d_name);
2369+
if (result > 0 && result < len) {
2370+
change_owner(path_tmp, uid, gid);
2371+
} else {
2372+
fprintf(LOGFILE, "Ignored %s/%s due to length", dir_path, ep->d_name);
2373+
}
2374+
}
23632375
}
23642376
closedir(dp);
23652377
}
@@ -2383,25 +2395,27 @@ int mount_cgroup(const char *pair, const char *hierarchy) {
23832395
char *mount_path = malloc(len);
23842396
char hier_path[EXECUTOR_PATH_MAX];
23852397
int result = 0;
2386-
struct stat sb;
23872398

23882399
if (controller == NULL || mount_path == NULL) {
23892400
fprintf(LOGFILE, "Failed to mount cgroup controller; not enough memory\n");
23902401
result = OUT_OF_MEMORY;
2402+
goto cleanup;
2403+
}
2404+
if (hierarchy == NULL || strstr(hierarchy, "..") != NULL) {
2405+
fprintf(LOGFILE, "Unsupported cgroup hierarhy path detected.\n");
2406+
result = INVALID_COMMAND_PROVIDED;
2407+
goto cleanup;
23912408
}
23922409
if (get_kv_key(pair, controller, len) < 0 ||
23932410
get_kv_value(pair, mount_path, len) < 0) {
23942411
fprintf(LOGFILE, "Failed to mount cgroup controller; invalid option: %s\n",
23952412
pair);
23962413
result = -1;
23972414
} else {
2398-
if (stat(mount_path, &sb) != 0) {
2399-
// Create mount point, if it does not exist
2400-
const mode_t mount_perms = S_IRWXU | S_IRGRP | S_IXGRP;
2401-
if (mkdirs(mount_path, mount_perms) == 0) {
2402-
fprintf(LOGFILE, "Failed to create cgroup mount point %s at %s\n",
2403-
controller, mount_path);
2404-
}
2415+
if (strstr(mount_path, "..") != NULL) {
2416+
fprintf(LOGFILE, "Unsupported cgroup mount path detected.\n");
2417+
result = INVALID_COMMAND_PROVIDED;
2418+
goto cleanup;
24052419
}
24062420
if (mount("none", mount_path, "cgroup", 0, controller) == 0) {
24072421
char *buf = stpncpy(hier_path, mount_path, strlen(mount_path));
@@ -2410,20 +2424,28 @@ int mount_cgroup(const char *pair, const char *hierarchy) {
24102424

24112425
// create hierarchy as 0750 and chown to Hadoop NM user
24122426
const mode_t perms = S_IRWXU | S_IRGRP | S_IXGRP;
2427+
struct stat sb;
2428+
if (stat(hier_path, &sb) == 0 &&
2429+
(sb.st_uid != nm_uid || sb.st_gid != nm_gid)) {
2430+
fprintf(LOGFILE, "cgroup hierarchy %s already owned by another user %d\n", hier_path, sb.st_uid);
2431+
result = INVALID_COMMAND_PROVIDED;
2432+
goto cleanup;
2433+
}
24132434
if (mkdirs(hier_path, perms) == 0) {
24142435
change_owner(hier_path, nm_uid, nm_gid);
24152436
chown_dir_contents(hier_path, nm_uid, nm_gid);
24162437
}
24172438
} else {
24182439
fprintf(LOGFILE, "Failed to mount cgroup controller %s at %s - %s\n",
2419-
controller, mount_path, strerror(errno));
2440+
controller, mount_path, strerror(errno));
24202441
// if controller is already mounted, don't stop trying to mount others
24212442
if (errno != EBUSY) {
24222443
result = -1;
24232444
}
24242445
}
24252446
}
24262447

2448+
cleanup:
24272449
free(controller);
24282450
free(mount_path);
24292451

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ enum operations {
6464
#define ALLOWED_SYSTEM_USERS_KEY "allowed.system.users"
6565
#define DOCKER_SUPPORT_ENABLED_KEY "feature.docker.enabled"
6666
#define TC_SUPPORT_ENABLED_KEY "feature.tc.enabled"
67+
#define MOUNT_CGROUP_SUPPORT_ENABLED_KEY "feature.mount-cgroup.enabled"
6768
#define TMP_DIR "tmp"
6869

6970
extern struct passwd *user_detail;
@@ -238,6 +239,9 @@ int is_feature_enabled(const char* feature_key, int default_value,
238239
/** Check if tc (traffic control) support is enabled in configuration. */
239240
int is_tc_support_enabled();
240241

242+
/** Check if cgroup mount support is enabled in configuration. */
243+
int is_mount_cgroups_support_enabled();
244+
241245
/**
242246
* Run a batch of tc commands that modify interface configuration
243247
*/

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -262,14 +262,19 @@ static int validate_arguments(int argc, char **argv , int *operation) {
262262
}
263263

264264
if (strcmp("--mount-cgroups", argv[1]) == 0) {
265-
if (argc < 4) {
266-
display_usage(stdout);
267-
return INVALID_ARGUMENT_NUMBER;
265+
if (is_mount_cgroups_support_enabled()) {
266+
if (argc < 4) {
267+
display_usage(stdout);
268+
return INVALID_ARGUMENT_NUMBER;
269+
}
270+
optind++;
271+
cmd_input.cgroups_hierarchy = argv[optind++];
272+
*operation = MOUNT_CGROUPS;
273+
return 0;
274+
} else {
275+
display_feature_disabled_message("mount cgroup");
276+
return FEATURE_DISABLED;
268277
}
269-
optind++;
270-
cmd_input.cgroups_hierarchy = argv[optind++];
271-
*operation = MOUNT_CGROUPS;
272-
return 0;
273278
}
274279

275280
if (strcmp("--tc-modify-state", argv[1]) == 0) {

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/NodeManagerCgroups.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ YARN uses CGroups through a directory structure mounted into the file system by
5050
| Option | Description |
5151
|:---- |:---- |
5252
| Discover CGroups mounted already | This should be used on newer systems like RHEL7 or Ubuntu16 or if the administrator mounts CGroups before YARN starts. Set `yarn.nodemanager.linux-container-executor.cgroups.mount` to false and leave other settings set to their defaults. YARN will locate the mount points in `/proc/mounts`. Common locations include `/sys/fs/cgroup` and `/cgroup`. The default location can vary depending on the Linux distribution in use.|
53-
| CGroups mounted by YARN | If the system does not have CGroups mounted or it is mounted to an inaccessible location then point `yarn.nodemanager.linux-container-executor.cgroups.mount-path` to an empty directory. Set `yarn.nodemanager.linux-container-executor.cgroups.mount` to true. A point to note here is that the container-executor binary will try to create and mount each subsystem as a subdirectory under this path. If `cpu` is already mounted somewhere with `cpuacct`, then the directory `cpu,cpuacct` will be created for the hierarchy.|
53+
| CGroups mounted by YARN | IMPORTANT: This option is deprecated due to security reasons with the `container-executor.cfg` option `feature.mount-cgroup.enabled=0` by default. Please mount cgroups before launching YARN.|
5454
| CGroups mounted already or linked but not in `/proc/mounts` | If cgroups is accessible through lxcfs or simulated by another filesystem, then point `yarn.nodemanager.linux-container-executor.cgroups.mount-path` to your CGroups root directory. Set `yarn.nodemanager.linux-container-executor.cgroups.mount` to false. YARN tries to use this path first, before any CGroup mount point discovery. The path should have a subdirectory for each CGroup hierarchy named by the comma separated CGroup subsystems supported like `<path>/cpu,cpuacct`. Valid subsystem names are `cpu, cpuacct, cpuset, memory, net_cls, blkio, freezer, devices`.|
5555

5656
CGroups and security

0 commit comments

Comments
 (0)