This is an automated email from the ASF dual-hosted git repository.
eyang pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/hadoop.git
The following commit(s) were added to refs/heads/trunk by this push:
new 72b1bed YARN-9884. Make container-executor mount logic modular
Contributed by Eric Badger
72b1bed is described below
commit 72b1bed9982a3b775fa60ec2ea818d1fbed683a2
Author: Eric Yang <[email protected]>
AuthorDate: Fri Oct 18 19:09:20 2019 -0400
YARN-9884. Make container-executor mount logic modular
Contributed by Eric Badger
---
.../src/CMakeLists.txt | 1 +
.../container-executor/impl/container-executor.c | 4 +-
.../src/main/native/container-executor/impl/main.c | 5 +
.../src/main/native/container-executor/impl/util.c | 137 +++++
.../src/main/native/container-executor/impl/util.h | 46 +-
.../container-executor/impl/utils/docker-util.c | 663 +++++++++------------
.../container-executor/impl/utils/docker-util.h | 31 -
.../container-executor/impl/utils/mount-utils.c | 356 +++++++++++
.../container-executor/impl/utils/mount-utils.h | 40 ++
.../test/utils/test_docker_util.cc | 101 ++--
10 files changed, 929 insertions(+), 455 deletions(-)
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/CMakeLists.txt
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/CMakeLists.txt
index bb7fd06..7e8b19f 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/CMakeLists.txt
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/CMakeLists.txt
@@ -137,6 +137,7 @@ add_library(container
main/native/container-executor/impl/modules/fpga/fpga-module.c
main/native/container-executor/impl/modules/devices/devices-module.c
main/native/container-executor/impl/utils/docker-util.c
+ main/native/container-executor/impl/utils/mount-utils.c
)
add_executable(container-executor
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c
index 318356d..72e0cf1 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c
@@ -1367,7 +1367,7 @@ char **construct_docker_command(const char *command_file)
{
ret = get_docker_command(command_file, &CFG, &buffer);
if (ret != 0) {
fprintf(ERRORFILE, "Error constructing docker command, docker error
code=%d, error message='%s'\n", ret,
- get_docker_error_message(ret));
+ get_error_message(ret));
exit(DOCKER_RUN_FAILED);
}
@@ -1414,7 +1414,7 @@ int exec_container(const char *command_file) {
if (ret != 0) {
free_configuration(&command_config);
free(docker_binary);
- return INVALID_COMMAND_FILE;
+ return INVALID_DOCKER_COMMAND_FILE;
}
char *value = get_configuration_value("docker-command",
DOCKER_COMMAND_FILE_SECTION, &command_config);
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c
index f890bd7..ce3e21e 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/main.c
@@ -788,6 +788,11 @@ int main(int argc, char **argv) {
break;
}
+ if (exit_code) {
+ fprintf(ERRORFILE, "Nonzero exit code=%d, error message='%s'\n", exit_code,
+ get_error_message(exit_code));
+ }
+
flush_and_close_log_files();
return exit_code;
}
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/util.c
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/util.c
index 1165428..c0b73d3 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/util.c
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/util.c
@@ -195,3 +195,140 @@ void quote_and_append_arg(char **str, size_t *size, const
char* param, const cha
sprintf(cur_ptr, append_format, param, tmp);
free(tmp);
}
+
+
+const char *get_error_message(const int error_code) {
+ switch (error_code) {
+ case INVALID_ARGUMENT_NUMBER:
+ return "Invalid argument number";
+ case INVALID_COMMAND_PROVIDED:
+ return "Invalid command provided";
+ case INVALID_NM_ROOT_DIRS:
+ return "Invalid NM root dirs";
+ case SETUID_OPER_FAILED:
+ return "setuid operation failed";
+ case UNABLE_TO_EXECUTE_CONTAINER_SCRIPT:
+ return "Unable to execute container script";
+ case UNABLE_TO_SIGNAL_CONTAINER:
+ return "Unable to signal container";
+ case INVALID_CONTAINER_PID:
+ return "Invalid container PID";
+ case OUT_OF_MEMORY:
+ return "Out of memory";
+ case INITIALIZE_USER_FAILED:
+ return "Initialize user failed";
+ case PATH_TO_DELETE_IS_NULL:
+ return "Path to delete is null";
+ case INVALID_CONTAINER_EXEC_PERMISSIONS:
+ return "Invalid container-executor permissions";
+ case INVALID_CONFIG_FILE:
+ return "Invalid config file";
+ case SETSID_OPER_FAILED:
+ return "setsid operation failed";
+ case WRITE_PIDFILE_FAILED:
+ return "Write to pidfile failed";
+ case WRITE_CGROUP_FAILED:
+ return "Write to cgroup failed";
+ case TRAFFIC_CONTROL_EXECUTION_FAILED:
+ return "Traffic control execution failed";
+ case DOCKER_RUN_FAILED:
+ return "Docker run failed";
+ case ERROR_OPENING_DOCKER_FILE:
+ return "Error opening Docker file";
+ case ERROR_READING_DOCKER_FILE:
+ return "Error reading Docker file";
+ case FEATURE_DISABLED:
+ return "Feature disabled";
+ case COULD_NOT_CREATE_SCRIPT_COPY:
+ return "Could not create script copy";
+ case COULD_NOT_CREATE_CREDENTIALS_COPY:
+ return "Could not create credentials copy";
+ case COULD_NOT_CREATE_WORK_DIRECTORIES:
+ return "Could not create work dirs";
+ case COULD_NOT_CREATE_APP_LOG_DIRECTORIES:
+ return "Could not create app log dirs";
+ case COULD_NOT_CREATE_TMP_DIRECTORIES:
+ return "Could not create tmp dirs";
+ case ERROR_CREATE_CONTAINER_DIRECTORIES_ARGUMENTS:
+ return "Error in create container directories arguments";
+ case ERROR_SANITIZING_DOCKER_COMMAND:
+ return "Error sanitizing Docker command";
+ case DOCKER_IMAGE_INVALID:
+ return "Docker image invalid";
+ case ERROR_COMPILING_REGEX:
+ return "Error compiling regex";
+ case INVALID_CONTAINER_ID:
+ return "Invalid container id";
+ case DOCKER_EXEC_FAILED:
+ return "Docker exec failed";
+ case COULD_NOT_CREATE_KEYSTORE_COPY:
+ return "Could not create keystore copy";
+ case COULD_NOT_CREATE_TRUSTSTORE_COPY:
+ return "Could not create truststore copy";
+ case ERROR_CALLING_SETVBUF:
+ return "Error calling setvbuf";
+ case BUFFER_TOO_SMALL:
+ return "Buffer too small";
+ case INVALID_MOUNT:
+ return "Invalid mount";
+ case INVALID_RO_MOUNT:
+ return "Invalid read-only mount";
+ case INVALID_RW_MOUNT:
+ return "Invalid read-write mount";
+ case MOUNT_ACCESS_ERROR:
+ return "Mount access error";
+ case INVALID_DOCKER_COMMAND_FILE:
+ return "Invalid docker command file passed";
+ case INCORRECT_DOCKER_COMMAND:
+ return "Incorrect command";
+ case INVALID_DOCKER_CONTAINER_NAME:
+ return "Invalid docker container name";
+ case INVALID_DOCKER_IMAGE_NAME:
+ return "Invalid docker image name";
+ case INVALID_DOCKER_USER_NAME:
+ return "Invalid docker user name";
+ case INVALID_DOCKER_INSPECT_FORMAT:
+ return "Invalid docker inspect format";
+ case UNKNOWN_DOCKER_COMMAND:
+ return "Unknown docker command";
+ case INVALID_DOCKER_NETWORK:
+ return "Invalid docker network";
+ case INVALID_DOCKER_PORTS_MAPPING:
+ return "Invalid docker ports mapping";
+ case INVALID_DOCKER_CAPABILITY:
+ return "Invalid docker capability";
+ case PRIVILEGED_DOCKER_CONTAINERS_DISABLED:
+ return "Privileged docker containers are disabled";
+ case INVALID_DOCKER_DEVICE:
+ return "Invalid docker device";
+ case INVALID_DOCKER_STOP_COMMAND:
+ return "Invalid docker stop command";
+ case INVALID_DOCKER_KILL_COMMAND:
+ return "Invalid docker kill command";
+ case INVALID_DOCKER_VOLUME_DRIVER:
+ return "Invalid docker volume-driver";
+ case INVALID_DOCKER_VOLUME_NAME:
+ return "Invalid docker volume name";
+ case INVALID_DOCKER_VOLUME_COMMAND:
+ return "Invalid docker volume command";
+ case DOCKER_PID_HOST_DISABLED:
+ return "Docker host pid namespace is disabled";
+ case INVALID_DOCKER_PID_NAMESPACE:
+ return "Invalid docker pid namespace";
+ case INVALID_DOCKER_IMAGE_TRUST:
+ return "Docker image is not trusted";
+ case INVALID_DOCKER_TMPFS_MOUNT:
+ return "Invalid docker tmpfs mount";
+ case INVALID_DOCKER_RUNTIME:
+ return "Invalid docker runtime";
+ case DOCKER_SERVICE_MODE_DISABLED:
+ return "Docker service mode disabled";
+ default:
+ return "Unknown error code";
+ }
+}
+
+int is_regex(const char *str) {
+ // regex should begin with prefix "regex:"
+ return (strncmp(str, "regex:", 6) == 0);
+}
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/util.h
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/util.h
index caa1c5f..dcc00a9 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/util.h
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/util.h
@@ -31,10 +31,10 @@ enum errorcodes {
INVALID_COMMAND_PROVIDED = 3,
// SUPER_USER_NOT_ALLOWED_TO_RUN_TASKS (NOT USED) 4
INVALID_NM_ROOT_DIRS = 5,
- SETUID_OPER_FAILED, //6
- UNABLE_TO_EXECUTE_CONTAINER_SCRIPT, //7
- UNABLE_TO_SIGNAL_CONTAINER, //8
- INVALID_CONTAINER_PID, //9
+ SETUID_OPER_FAILED = 6,
+ UNABLE_TO_EXECUTE_CONTAINER_SCRIPT = 7,
+ UNABLE_TO_SIGNAL_CONTAINER = 8,
+ INVALID_CONTAINER_PID = 9,
// ERROR_RESOLVING_FILE_PATH (NOT_USED) 10
// RELATIVE_PATH_COMPONENTS_IN_FILE_PATH (NOT USED) 11
// UNABLE_TO_STAT_FILE (NOT USED) 12
@@ -46,8 +46,8 @@ enum errorcodes {
OUT_OF_MEMORY = 18,
// INITIALIZE_DISTCACHEFILE_FAILED (NOT USED) 19
INITIALIZE_USER_FAILED = 20,
- PATH_TO_DELETE_IS_NULL, //21
- INVALID_CONTAINER_EXEC_PERMISSIONS, //22
+ PATH_TO_DELETE_IS_NULL = 21,
+ INVALID_CONTAINER_EXEC_PERMISSIONS = 22,
// PREPARE_JOB_LOGS_FAILED (NOT USED) 23
INVALID_CONFIG_FILE = 24,
SETSID_OPER_FAILED = 25,
@@ -72,7 +72,35 @@ enum errorcodes {
DOCKER_EXEC_FAILED = 44,
COULD_NOT_CREATE_KEYSTORE_COPY = 45,
COULD_NOT_CREATE_TRUSTSTORE_COPY = 46,
- ERROR_CALLING_SETVBUF = 47
+ ERROR_CALLING_SETVBUF = 47,
+ BUFFER_TOO_SMALL = 48,
+ INVALID_MOUNT = 49,
+ INVALID_RO_MOUNT = 50,
+ INVALID_RW_MOUNT = 51,
+ MOUNT_ACCESS_ERROR = 52,
+ INVALID_DOCKER_COMMAND_FILE = 53,
+ INCORRECT_DOCKER_COMMAND = 54,
+ INVALID_DOCKER_CONTAINER_NAME = 55,
+ INVALID_DOCKER_IMAGE_NAME = 56,
+ INVALID_DOCKER_USER_NAME = 57,
+ INVALID_DOCKER_INSPECT_FORMAT = 58,
+ UNKNOWN_DOCKER_COMMAND = 59,
+ INVALID_DOCKER_NETWORK = 60,
+ INVALID_DOCKER_PORTS_MAPPING = 61,
+ INVALID_DOCKER_CAPABILITY = 62,
+ PRIVILEGED_DOCKER_CONTAINERS_DISABLED = 63,
+ INVALID_DOCKER_DEVICE = 64,
+ INVALID_DOCKER_STOP_COMMAND = 65,
+ INVALID_DOCKER_KILL_COMMAND = 66,
+ INVALID_DOCKER_VOLUME_DRIVER = 67,
+ INVALID_DOCKER_VOLUME_NAME = 68,
+ INVALID_DOCKER_VOLUME_COMMAND = 69,
+ DOCKER_PID_HOST_DISABLED = 70,
+ INVALID_DOCKER_PID_NAMESPACE = 71,
+ INVALID_DOCKER_IMAGE_TRUST = 72,
+ INVALID_DOCKER_TMPFS_MOUNT = 73,
+ INVALID_DOCKER_RUNTIME = 74,
+ DOCKER_SERVICE_MODE_DISABLED = 75
};
/* Macros for min/max. */
@@ -169,4 +197,8 @@ inline void* alloc_and_clear_memory(size_t num, size_t
size) {
return ret;
}
+const char *get_error_message(const int error_code);
+
+int is_regex(const char *str);
+
#endif
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.c
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.c
index 3ef571f..f35fd88 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.c
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.c
@@ -32,6 +32,7 @@
#include <grp.h>
#include <pwd.h>
#include <errno.h>
+#include "mount-utils.h"
int entry_point = 0;
@@ -40,11 +41,11 @@ static int read_and_verify_command_file(const char
*command_file, const char *do
int ret = 0;
ret = read_config(command_file, command_config);
if (ret != 0) {
- return INVALID_COMMAND_FILE;
+ return INVALID_DOCKER_COMMAND_FILE;
}
char *command = get_configuration_value("docker-command",
DOCKER_COMMAND_FILE_SECTION, command_config);
if (command == NULL || (strcmp(command, docker_command) != 0)) {
- ret = INCORRECT_COMMAND;
+ ret = INCORRECT_DOCKER_COMMAND;
}
free(command);
return ret;
@@ -173,23 +174,12 @@ free_and_exit:
return ret;
}
-static int is_regex(const char *str) {
- // regex should begin with prefix "regex:"
- return (strncmp(str, "regex:", 6) == 0);
-}
-
static int is_valid_tmpfs_mount(const char *mount) {
const char *regex_str = "^/[^:]+$";
// execute_regex_match return 0 is matched success
return execute_regex_match(regex_str, mount) == 0;
}
-static int is_volume_name(const char *volume_name) {
- const char *regex_str = "^[a-zA-Z0-9]([a-zA-Z0-9_.-]*)$";
- // execute_regex_match return 0 is matched success
- return execute_regex_match(regex_str, volume_name) == 0;
-}
-
static int is_valid_ports_mapping(const char *ports_mapping) {
const char *regex_str =
"^:[0-9]+|^[0-9]+:[0-9]+|^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.)"
"{3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]):[0-9]+:[0-9]+$";
@@ -197,11 +187,6 @@ static int is_valid_ports_mapping(const char
*ports_mapping) {
return execute_regex_match(regex_str, ports_mapping) == 0;
}
-static int is_volume_name_matched_by_regex(const char* requested, const char*
pattern) {
- // execute_regex_match return 0 is matched success
- return is_volume_name(requested) && (execute_regex_match(pattern +
sizeof("regex:"), requested) == 0);
-}
-
static int add_param_to_command_if_allowed(const struct configuration
*command_config,
const struct configuration
*executor_cfg,
const char *key, const char
*allowed_key, const char *param,
@@ -322,66 +307,6 @@ static int validate_container_name(const char
*container_name) {
return INVALID_DOCKER_CONTAINER_NAME;
}
-const char *get_docker_error_message(const int error_code) {
-
- switch (error_code) {
- case INVALID_COMMAND_FILE:
- return "Invalid command file passed";
- case INCORRECT_COMMAND:
- return "Incorrect command";
- case BUFFER_TOO_SMALL:
- return "Command buffer too small";
- case INVALID_DOCKER_CONTAINER_NAME:
- return "Invalid docker container name";
- case INVALID_DOCKER_IMAGE_NAME:
- return "Invalid docker image name";
- case INVALID_DOCKER_USER_NAME:
- return "Invalid docker user name";
- case INVALID_DOCKER_INSPECT_FORMAT:
- return "Invalid docker inspect format";
- case UNKNOWN_DOCKER_COMMAND:
- return "Unknown docker command";
- case INVALID_DOCKER_NETWORK:
- return "Invalid docker network";
- case INVALID_DOCKER_PORTS_MAPPING:
- return "Invalid docker ports mapping";
- case INVALID_DOCKER_CAPABILITY:
- return "Invalid docker capability";
- case PRIVILEGED_CONTAINERS_DISABLED:
- return "Privileged containers are disabled";
- case INVALID_DOCKER_MOUNT:
- return "Invalid docker mount";
- case INVALID_DOCKER_RO_MOUNT:
- return "Invalid docker read-only mount";
- case INVALID_DOCKER_RW_MOUNT:
- return "Invalid docker read-write mount";
- case MOUNT_ACCESS_ERROR:
- return "Mount access error";
- case INVALID_DOCKER_DEVICE:
- return "Invalid docker device";
- case INVALID_DOCKER_VOLUME_DRIVER:
- return "Invalid docker volume-driver";
- case INVALID_DOCKER_VOLUME_NAME:
- return "Invalid docker volume name";
- case INVALID_DOCKER_VOLUME_COMMAND:
- return "Invalid docker volume command";
- case PID_HOST_DISABLED:
- return "Host pid namespace is disabled";
- case INVALID_PID_NAMESPACE:
- return "Invalid pid namespace";
- case INVALID_DOCKER_IMAGE_TRUST:
- return "Docker image is not trusted";
- case INVALID_DOCKER_TMPFS_MOUNT:
- return "Invalid docker tmpfs mount";
- case INVALID_DOCKER_RUNTIME:
- return "Invalid docker runtime";
- case SERVICE_MODE_DISABLED:
- return "Service mode disabled";
- default:
- return "Unknown error";
- }
-}
-
int get_max_retries(const struct configuration *conf) {
int retries = 10;
char *max_retries = get_configuration_value(DOCKER_INSPECT_MAX_RETRIES_KEY,
@@ -424,7 +349,7 @@ int get_docker_command(const char *command_file, const
struct configuration *con
ret = read_config(command_file, &command_config);
if (ret != 0) {
free_configuration(&command_config);
- return INVALID_COMMAND_FILE;
+ return INVALID_DOCKER_COMMAND_FILE;
}
char *docker = get_docker_binary(conf);
@@ -905,7 +830,7 @@ int get_docker_exec_command(const char *command_file, const
struct configuration
}
}
} else {
- ret = INVALID_COMMAND_FILE;
+ ret = INVALID_DOCKER_COMMAND_FILE;
}
free_and_exit:
free(container_name);
@@ -999,7 +924,7 @@ int is_service_mode_enabled(const struct configuration
*command_config,
if (is_feature_enabled(DOCKER_SERVICE_MODE_ENABLED_KEY, ret, section)) {
ret = 1;
} else {
- ret = SERVICE_MODE_DISABLED;
+ ret = DOCKER_SERVICE_MODE_DISABLED;
}
}
free(value);
@@ -1083,17 +1008,17 @@ static int set_pid_namespace(const struct configuration
*command_config,
}
} else {
fprintf(ERRORFILE, "Host pid namespace is disabled\n");
- ret = PID_HOST_DISABLED;
+ ret = DOCKER_PID_HOST_DISABLED;
goto free_and_exit;
}
} else {
fprintf(ERRORFILE, "Host pid namespace is disabled\n");
- ret = PID_HOST_DISABLED;
+ ret = DOCKER_PID_HOST_DISABLED;
goto free_and_exit;
}
} else {
fprintf(ERRORFILE, "Invalid pid namespace\n");
- ret = INVALID_PID_NAMESPACE;
+ ret = INVALID_DOCKER_PID_NAMESPACE;
}
}
@@ -1161,164 +1086,6 @@ static int set_env(const struct configuration
*command_config, struct args *args
return ret;
}
-/**
- * Helper function to help normalize mounts for checking if mounts are
- * permitted. The function does the following -
- * 1. Find the canonical path for mount using realpath
- * 2. If the path is a directory, add a '/' at the end (if not present)
- * 3. Return a copy of the canonicalised path(to be freed by the caller)
- * @param mount path to be canonicalised
- * @param isRegexAllowed whether regex matching is allowed for normalize mount
- * @return pointer to canonicalised path, NULL on error
- */
-static char* normalize_mount(const char* mount, int isRegexAllowed) {
- int ret = 0;
- struct stat buff;
- char *ret_ptr = NULL, *real_mount = NULL;
- if (mount == NULL) {
- return NULL;
- }
- real_mount = realpath(mount, NULL);
- if (real_mount == NULL) {
- // If mount is a valid named volume, just return it and let docker decide
- if (is_volume_name(mount)) {
- return strdup(mount);
- }
- // we only allow permitted mount to be REGEX, for permitted mount, we check
- // if it's a valid REGEX return; for user mount, we need to strictly check
- if (isRegexAllowed) {
- if (is_regex(mount)) {
- return strdup(mount);
- }
- }
- fprintf(ERRORFILE, "Could not determine real path of mount '%s'\n", mount);
- return NULL;
- }
- ret = stat(real_mount, &buff);
- if (ret == 0) {
- if (S_ISDIR(buff.st_mode)) {
- size_t len = strlen(real_mount);
- if (len <= 0) {
- free(real_mount);
- return NULL;
- }
- if (real_mount[len - 1] != '/') {
- ret_ptr = (char *) alloc_and_clear_memory(len + 2, sizeof(char));
- strncpy(ret_ptr, real_mount, len);
- ret_ptr[len] = '/';
- ret_ptr[len + 1] = '\0';
- } else {
- ret_ptr = strdup(real_mount);
- }
- } else {
- ret_ptr = strdup(real_mount);
- }
- } else {
- fprintf(ERRORFILE, "Could not stat path '%s'\n", real_mount);
- ret_ptr = NULL;
- }
- free(real_mount);
- return ret_ptr;
-}
-
-static int normalize_mounts(char **mounts, int isRegexAllowed) {
- int i = 0;
- char *tmp = NULL;
- if (mounts == NULL) {
- return 0;
- }
- for (i = 0; mounts[i] != NULL; ++i) {
- tmp = normalize_mount(mounts[i], isRegexAllowed);
- if (tmp == NULL) {
- return -1;
- }
- free(mounts[i]);
- mounts[i] = tmp;
- }
- return 0;
-}
-
-static int check_mount_permitted(const char **permitted_mounts, const char
*requested) {
- int i = 0, ret = 0;
- size_t permitted_mount_len = 0;
- if (permitted_mounts == NULL) {
- return 0;
- }
- char *normalized_path = normalize_mount(requested, 0);
- if (normalized_path == NULL) {
- return -1;
- }
- for (i = 0; permitted_mounts[i] != NULL; ++i) {
- if (strcmp(normalized_path, permitted_mounts[i]) == 0) {
- ret = 1;
- break;
- }
- // if (permitted_mounts[i] is a REGEX): use REGEX to compare; return
- if (is_regex(permitted_mounts[i]) &&
- is_volume_name_matched_by_regex(normalized_path, permitted_mounts[i])) {
- ret = 1;
- break;
- }
-
- // directory check
- permitted_mount_len = strlen(permitted_mounts[i]);
- struct stat path_stat;
- stat(permitted_mounts[i], &path_stat);
- if(S_ISDIR(path_stat.st_mode)) {
- if (strncmp(normalized_path, permitted_mounts[i], permitted_mount_len)
== 0) {
- ret = 1;
- break;
- }
- }
- }
- free(normalized_path);
- return ret;
-}
-
-static char* get_mount_source(const char *mount) {
- const char *tmp = strchr(mount, ':');
- if (tmp == NULL) {
- fprintf(ERRORFILE, "Invalid docker mount '%s'\n", mount);
- return NULL;
- }
- size_t len = tmp - mount;
- return strndup(mount, len);
-}
-
-static char* get_mount_type(const char *mount) {
- const char *tmp = strrchr(mount, ':');
- if (tmp == NULL) {
- fprintf(ERRORFILE, "Invalid docker mount '%s'\n", mount);
- return NULL;
- }
- if (strlen(tmp) < 2) {
- fprintf(ERRORFILE, "Invalid docker mount '%s'\n", mount);
- return NULL;
- }
- char *mount_type = strdup(&tmp[1]);
- if (strncmp("ro", mount_type, 2) != 0 &&
- strncmp("rw", mount_type, 2) != 0) {
- fprintf(ERRORFILE, "Invalid docker mount type '%s'\n", mount_type);
- free(mount_type);
- return NULL;
- }
- if (strlen(mount_type) > 2) {
- if (strlen(mount_type) < 8 ||
- (strcmp("shared", mount_type + 3) != 0 &&
- strcmp("rshared", mount_type + 3) != 0 &&
- strcmp("slave", mount_type + 3) != 0 &&
- strcmp("rslave", mount_type + 3) != 0 &&
- strcmp("private", mount_type + 3) != 0 &&
- strcmp("rprivate", mount_type + 3) != 0)) {
- fprintf(ERRORFILE, "Invalid docker mount type '%s'\n", mount_type);
- free(mount_type);
- return NULL;
- }
- mount_type[2] = ',';
- }
- return mount_type;
-}
-
static int add_tmpfs_mounts(const struct configuration *command_config, args
*args) {
char **values = get_configuration_values_delimiter("tmpfs",
DOCKER_COMMAND_FILE_SECTION, command_config, ",");
int i = 0, ret = 0;
@@ -1348,122 +1115,7 @@ free_and_exit:
return ret;
}
-static int add_mounts(const struct configuration *command_config, const struct
configuration *conf, args *args) {
- const char *tmp_path_buffer[2] = {NULL, NULL};
- char *mount_src = NULL;
- char *mount_type = NULL;
- char **permitted_ro_mounts =
get_configuration_values_delimiter("docker.allowed.ro-mounts",
-
CONTAINER_EXECUTOR_CFG_DOCKER_SECTION, conf, ",");
- char **permitted_rw_mounts =
get_configuration_values_delimiter("docker.allowed.rw-mounts",
-
CONTAINER_EXECUTOR_CFG_DOCKER_SECTION, conf, ",");
- char **values = get_configuration_values_delimiter("mounts",
DOCKER_COMMAND_FILE_SECTION, command_config, ",");
- char *config_path = get_config_path("");
- const char *container_executor_cfg_path = normalize_mount(config_path, 0);
- free(config_path);
- int i = 0, permitted_rw = 0, permitted_ro = 0, ret = 0;
- if (values == NULL) {
- goto free_and_exit;
- }
- // Disable mount volumes if image is not trusted.
- if (check_trusted_image(command_config, conf) != 0) {
- fprintf(ERRORFILE, "Disable mount volume for untrusted image\n");
- // YARN will implicitly bind node manager local directory to
- // docker image. This can create file system security holes,
- // if docker container has binary to escalate privileges.
- // For untrusted image, we drop mounting without reporting
- // INVALID_DOCKER_MOUNT messages to allow running untrusted
- // image in a sandbox.
- ret = 0;
- goto free_and_exit;
- }
- ret = normalize_mounts(permitted_ro_mounts, 1);
- ret |= normalize_mounts(permitted_rw_mounts, 1);
- if (ret != 0) {
- fprintf(ERRORFILE, "Unable to find permitted docker mounts on disk\n");
- ret = MOUNT_ACCESS_ERROR;
- goto free_and_exit;
- }
- for (i = 0; values[i] != NULL; i++) {
- mount_src = get_mount_source(values[i]);
- if (mount_src == NULL) {
- fprintf(ERRORFILE, "Invalid docker mount '%s'\n", values[i]);
- ret = INVALID_DOCKER_MOUNT;
- goto free_and_exit;
- }
- mount_type = get_mount_type(values[i]);
- if (mount_type == NULL) {
- fprintf(ERRORFILE, "Invalid docker mount '%s'\n", values[i]);
- ret = INVALID_DOCKER_MOUNT;
- goto free_and_exit;
- }
- permitted_rw = check_mount_permitted((const char **) permitted_rw_mounts,
mount_src);
- permitted_ro = check_mount_permitted((const char **) permitted_ro_mounts,
mount_src);
- if (permitted_ro == -1 || permitted_rw == -1) {
- fprintf(ERRORFILE, "Invalid docker mount '%s', realpath=%s\n",
values[i], mount_src);
- ret = INVALID_DOCKER_MOUNT;
- goto free_and_exit;
- }
- if (strncmp("rw", mount_type, 2) == 0) {
- // rw mount
- if (permitted_rw == 0) {
- fprintf(ERRORFILE, "Configuration does not allow docker mount '%s',
realpath=%s\n", values[i], mount_src);
- ret = INVALID_DOCKER_RW_MOUNT;
- goto free_and_exit;
- } else {
- // determine if the user can modify the container-executor.cfg file
- tmp_path_buffer[0] = normalize_mount(mount_src, 0);
- // just re-use the function, flip the args to check if the
container-executor path is in the requested
- // mount point
- ret = check_mount_permitted(tmp_path_buffer,
container_executor_cfg_path);
- free((void *) tmp_path_buffer[0]);
- if (ret == 1) {
- fprintf(ERRORFILE, "Attempting to mount a parent directory '%s' of
container-executor.cfg as read-write\n",
- values[i]);
- ret = INVALID_DOCKER_RW_MOUNT;
- goto free_and_exit;
- }
- }
- } else {
- // ro mount
- if (permitted_ro == 0 && permitted_rw == 0) {
- fprintf(ERRORFILE, "Configuration does not allow docker mount '%s',
realpath=%s\n", values[i], mount_src);
- ret = INVALID_DOCKER_RO_MOUNT;
- goto free_and_exit;
- }
- }
-
- if (strlen(mount_type) > 2) {
- // overwrite separator between read mode and propagation option with ','
- int mount_type_index = strlen(values[i]) - strlen(mount_type);
- values[i][mount_type_index + 2] = ',';
- }
- ret = add_to_args(args, "-v");
- if (ret != 0) {
- ret = BUFFER_TOO_SMALL;
- goto free_and_exit;
- }
-
- ret = add_to_args(args, values[i]);
- if (ret != 0) {
- ret = BUFFER_TOO_SMALL;
- goto free_and_exit;
- }
- free(mount_src);
- free(mount_type);
- mount_src = NULL;
- mount_type = NULL;
- }
-
-free_and_exit:
- free(mount_src);
- free(mount_type);
- free_values(permitted_ro_mounts);
- free_values(permitted_rw_mounts);
- free_values(values);
- free((void *) container_executor_cfg_path);
- return ret;
-}
static int check_privileges(const char *user) {
int ngroups = 0;
@@ -1567,13 +1219,13 @@ static int set_privileged(const struct configuration
*command_config, const stru
// Disable set privileged if entry point mode is disabled
if (get_use_entry_point_flag() != 1) {
fprintf(ERRORFILE, "Privileged containers are disabled for
non-entry-point mode\n");
- ret = PRIVILEGED_CONTAINERS_DISABLED;
+ ret = PRIVILEGED_DOCKER_CONTAINERS_DISABLED;
goto free_and_exit;
}
// Disable set privileged if image is not trusted.
if (check_trusted_image(command_config, conf) != 0) {
fprintf(ERRORFILE, "Privileged containers are disabled from
untrusted source\n");
- ret = PRIVILEGED_CONTAINERS_DISABLED;
+ ret = PRIVILEGED_DOCKER_CONTAINERS_DISABLED;
goto free_and_exit;
}
allowed = check_privileges(user);
@@ -1584,17 +1236,17 @@ static int set_privileged(const struct configuration
*command_config, const stru
}
} else {
fprintf(ERRORFILE, "Privileged containers are disabled for user:
%s\n", user);
- ret = PRIVILEGED_CONTAINERS_DISABLED;
+ ret = PRIVILEGED_DOCKER_CONTAINERS_DISABLED;
goto free_and_exit;
}
} else {
fprintf(ERRORFILE, "Privileged containers are disabled\n");
- ret = PRIVILEGED_CONTAINERS_DISABLED;
+ ret = PRIVILEGED_DOCKER_CONTAINERS_DISABLED;
goto free_and_exit;
}
} else {
fprintf(ERRORFILE, "Privileged containers are disabled\n");
- ret = PRIVILEGED_CONTAINERS_DISABLED;
+ ret = PRIVILEGED_DOCKER_CONTAINERS_DISABLED;
goto free_and_exit;
}
}
@@ -1606,6 +1258,287 @@ free_and_exit:
return ret;
}
+
+
+static char* get_docker_mount_source(const char *mount) {
+ const char *tmp = strchr(mount, ':');
+ if (tmp == NULL) {
+ fprintf(ERRORFILE, "Invalid docker mount '%s'\n", mount);
+ return NULL;
+ }
+ size_t len = tmp - mount;
+ return strndup(mount, len);
+}
+
+static char* get_docker_mount_dest(const char *mount) {
+ size_t len;
+ const char *start = strchr(mount, ':') + 1;
+ if (start == NULL) {
+ fprintf(ERRORFILE, "Invalid docker mount '%s'\n", mount);
+ return NULL;
+ }
+
+ const char *end = strchr(start, ':');
+ if (end == NULL) {
+ len = strlen(mount) - (start - mount);
+ } else {
+ len = end - start;
+ }
+ return strndup(start, len);
+}
+
+static mount_options* get_docker_mount_options(const char *mount_string) {
+ char **opts = NULL;
+ mount_options *options = NULL;
+ unsigned int num_opts = 0;
+ char *option = NULL;
+ int len = 0;
+
+ //+1 because we don't care about the ':'
+ const char *option_string = strrchr(mount_string, ':') + 1;
+ if (option_string == NULL) {
+ fprintf(ERRORFILE, "Invalid docker mount '%s'\n", mount_string);
+ return NULL;
+ }
+
+ options = (mount_options *) calloc(1, sizeof(*options));
+ if (options == NULL) {
+ fprintf(ERRORFILE, "Unable to allocate %ld bytes\n", sizeof(*options));
+ return NULL;
+ }
+
+ len = strlen(option_string);
+
+ if (len == 2) {
+ opts = (char **) calloc(1, sizeof(*opts));
+ if (opts == NULL) {
+ fprintf(ERRORFILE, "Unable to allocate %ld bytes\n",
sizeof(*opts));
+ free(options);
+ return NULL;
+ }
+ num_opts = 1;
+ } else if (len < 8) {
+ fprintf(ERRORFILE, "Invalid docker mount. Too many options. '%s'\n",
mount_string);
+ free(options);
+ return NULL;
+ } else {
+ opts = (char **) calloc(2, sizeof(*opts));
+ if (opts == NULL) {
+ fprintf(ERRORFILE, "Unable to allocate %ld bytes\n", 2 *
sizeof(*opts));
+ free(options);
+ return NULL;
+ }
+ num_opts = 2;
+ }
+
+ options->opts = opts;
+ options->num_opts = num_opts;
+
+ char *option_string_token = strdup(option_string);
+ option = strtok(option_string_token, "+");
+ for (unsigned int i = 0; i < options->num_opts; i++) {
+ if (option == NULL) {
+ fprintf(ERRORFILE, "Invalid docker mount options '%s'\n",
mount_string);
+ free(option_string_token);
+ free_mount_options(options);
+ return NULL;
+ }
+
+ if (strcmp("rw", option) == 0) {
+ options->rw = 1;
+ } else if (strcmp("ro", option) == 0) {
+ options->rw = 0;
+ } else if (strcmp("shared", option) != 0 &&
+ (strcmp("rshared", option) != 0) &&
+ (strcmp("slave", option) != 0) &&
+ (strcmp("rslave", option) != 0) &&
+ (strcmp("private", option) != 0) &&
+ (strcmp("rprivate", option) != 0)) {
+ fprintf(ERRORFILE, "Invalid docker mount options '%s'\n",
mount_string);
+ free(option_string_token);
+ free_mount_options(options);
+ return NULL;
+ }
+ options->opts[i] = strdup(option);
+ option = strtok(NULL, "+");
+ }
+
+ free(option_string_token);
+ return options;
+}
+
+static char* get_docker_mount_options_string(mount_options *options) {
+ char *options_string = NULL;
+ int len = 0;
+ int idx = 0;
+ unsigned int i;
+
+ for (i = 0; i < options->num_opts; i++) {
+ len += strlen(options->opts[i]);
+ }
+ len += i; // i-1 commas plus 1 for NUL termination
+
+ options_string = (char *) calloc(len, sizeof(*options_string));
+ if (options_string == NULL) {
+ fputs("Unable to allocate memory\n", ERRORFILE);
+ return NULL;
+ }
+
+ idx += sprintf(options_string, "%s", options->opts[0]);
+ for (i = 1; i < options->num_opts; i++) {
+ idx += sprintf(options_string + idx, ",%s", options->opts[i]);
+ }
+
+ return options_string;
+}
+
+static int add_mounts_to_docker_args(mount *mounts, unsigned int num_mounts,
args *args) {
+ int ret = 0, len;
+ unsigned int i;
+ char *mount_string = NULL;
+ char *options_string = NULL;
+
+ if (mounts == NULL) {
+ return ret;
+ }
+
+ for (i = 0; i < num_mounts; i++) {
+ ret = add_to_args(args, "-v");
+ if (ret != 0) {
+ ret = BUFFER_TOO_SMALL;
+ return ret;
+ }
+ options_string = get_docker_mount_options_string(mounts[i].options);
+
+ //magic number '+3': +1 for both ':', and +1 for NULL termination
+ len = strlen(mounts[i].src) + strlen(mounts[i].dest) +
strlen(options_string) + 3;
+ mount_string = (char *) calloc(len, sizeof(*mount_string));
+
+ snprintf(mount_string, len, "%s:%s:%s", mounts[i].src, mounts[i].dest,
options_string);
+
+ ret = add_to_args(args, mount_string);
+ if (ret != 0) {
+ ret = BUFFER_TOO_SMALL;
+ goto free_and_exit;
+ }
+ free(mount_string);
+ free(options_string);
+ }
+ return ret;
+
+free_and_exit:
+ free(mount_string);
+ free(options_string);
+ return ret;
+}
+
+static int get_docker_mounts(mount *mounts, char **mounts_string, unsigned int
num_mounts) {
+ unsigned int i;
+ int ret = 0;
+ char *src, *dest;
+ mount_options *options = NULL;
+
+ if (mounts_string == NULL) {
+ fprintf(ERRORFILE, "Unable to normalize container-executor.cfg
path\n");
+ ret = MOUNT_ACCESS_ERROR;
+ goto free_and_exit;
+ }
+
+ for (i = 0; i < num_mounts; i++) {
+ src = get_docker_mount_source(mounts_string[i]);
+ if (src == NULL) {
+ fprintf(ERRORFILE, "Invalid mount '%s'\n", mounts_string[i]);
+ ret = INVALID_MOUNT;
+ goto free_and_exit;
+ }
+ mounts[i].src = src;
+
+ dest = get_docker_mount_dest(mounts_string[i]);
+ if (dest == NULL) {
+ fprintf(ERRORFILE, "Invalid mount '%s'\n", mounts_string[i]);
+ ret = INVALID_MOUNT;
+ goto free_and_exit;
+ }
+ mounts[i].dest = dest;
+
+ options = get_docker_mount_options(mounts_string[i]);
+ if (options == NULL) {
+ fprintf(ERRORFILE, "Invalid mount '%s'\n", mounts_string[i]);
+ ret = INVALID_MOUNT;
+ goto free_and_exit;
+ }
+ mounts[i].options = options;
+ }
+
+free_and_exit:
+ return ret;
+}
+
+static int add_docker_mounts(const struct configuration *command_config, const
struct configuration *conf, args *args) {
+ mount *mounts = NULL;
+ unsigned int num_mounts = 0;
+ int ret;
+ char **permitted_ro_mounts = NULL;
+ char **permitted_rw_mounts = NULL;
+ char **mounts_string = NULL;
+ permitted_ro_mounts =
get_configuration_values_delimiter("docker.allowed.ro-mounts",
+
CONTAINER_EXECUTOR_CFG_DOCKER_SECTION, conf, ",");
+ permitted_rw_mounts =
get_configuration_values_delimiter("docker.allowed.rw-mounts",
+
CONTAINER_EXECUTOR_CFG_DOCKER_SECTION, conf, ",");
+ mounts_string = get_configuration_values_delimiter("mounts",
DOCKER_COMMAND_FILE_SECTION, command_config, ",");
+
+ if (mounts_string == NULL) {
+ ret = 0;
+ goto free_and_exit;
+ }
+
+ while (mounts_string[num_mounts] != NULL) {
+ num_mounts++;
+ }
+
+ // Disable mount volumes if image is not trusted.
+ if (check_trusted_image(command_config, conf) != 0) {
+ fprintf(ERRORFILE, "Disable mount volume for untrusted image\n");
+ // YARN will implicitly bind node manager local directory to
+ // docker image. This can create file system security holes,
+ // if docker container has binary to escalate privileges.
+ // For untrusted image, we drop mounting without reporting
+ // INVALID_MOUNT messages to allow running untrusted
+ // image in a sandbox.
+ ret = 0;
+ goto free_and_exit;
+ }
+
+ mounts = (mount *) calloc(num_mounts, sizeof(*mounts));
+ if (mounts == NULL) {
+ fprintf(ERRORFILE, "Unable to allocate %ld bytes\n", num_mounts *
sizeof(*mounts));
+ ret = OUT_OF_MEMORY;
+ goto free_and_exit;
+ }
+
+ ret = get_docker_mounts(mounts, mounts_string, num_mounts);
+ if (ret != 0) {
+ goto free_and_exit;
+ }
+
+ ret = validate_mounts(permitted_ro_mounts, permitted_rw_mounts, mounts,
num_mounts);
+ if (ret != 0) {
+ goto free_and_exit;
+ }
+
+ ret = add_mounts_to_docker_args(mounts, num_mounts, args);
+ if (ret != 0) {
+ goto free_and_exit;
+ }
+
+free_and_exit:
+ free_values(permitted_ro_mounts);
+ free_values(permitted_rw_mounts);
+ free_values(mounts_string);
+ free_mounts(mounts, num_mounts);
+ return ret;
+}
+
int get_docker_run_command(const char *command_file, const struct
configuration *conf, args *args) {
int ret = 0, i = 0;
char *container_name = NULL, *user = NULL, *image = NULL;
@@ -1622,8 +1555,8 @@ int get_docker_run_command(const char *command_file,
const struct configuration
}
service_mode_enabled = is_service_mode_enabled(&command_config, conf, args);
- if (service_mode_enabled == SERVICE_MODE_DISABLED) {
- ret = SERVICE_MODE_DISABLED;
+ if (service_mode_enabled == DOCKER_SERVICE_MODE_DISABLED) {
+ ret = DOCKER_SERVICE_MODE_DISABLED;
goto free_and_exit;
}
@@ -1721,7 +1654,7 @@ int get_docker_run_command(const char *command_file,
const struct configuration
goto free_and_exit;
}
- ret = add_mounts(&command_config, conf, args);
+ ret = add_docker_mounts(&command_config, conf, args);
if (ret != 0) {
goto free_and_exit;
}
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.h
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.h
index d9d34a0..99731b4 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.h
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.h
@@ -45,37 +45,6 @@ typedef struct args {
char *data[DOCKER_ARG_MAX];
} args;
-enum docker_error_codes {
- INVALID_COMMAND_FILE = 1,
- INCORRECT_COMMAND,
- BUFFER_TOO_SMALL,
- INVALID_DOCKER_CONTAINER_NAME,
- INVALID_DOCKER_IMAGE_NAME,
- INVALID_DOCKER_USER_NAME,
- INVALID_DOCKER_INSPECT_FORMAT,
- UNKNOWN_DOCKER_COMMAND,
- INVALID_DOCKER_NETWORK,
- INVALID_DOCKER_PORTS_MAPPING,
- INVALID_DOCKER_CAPABILITY,
- PRIVILEGED_CONTAINERS_DISABLED,
- INVALID_DOCKER_MOUNT,
- INVALID_DOCKER_RO_MOUNT,
- INVALID_DOCKER_RW_MOUNT,
- MOUNT_ACCESS_ERROR,
- INVALID_DOCKER_DEVICE,
- INVALID_DOCKER_STOP_COMMAND,
- INVALID_DOCKER_KILL_COMMAND,
- INVALID_DOCKER_VOLUME_DRIVER,
- INVALID_DOCKER_VOLUME_NAME,
- INVALID_DOCKER_VOLUME_COMMAND,
- PID_HOST_DISABLED,
- INVALID_PID_NAMESPACE,
- INVALID_DOCKER_IMAGE_TRUST,
- INVALID_DOCKER_TMPFS_MOUNT,
- INVALID_DOCKER_RUNTIME,
- SERVICE_MODE_DISABLED
-};
-
/**
* Get the full path for the docker binary.
* @param conf Configuration for the container-executor
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/mount-utils.c
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/mount-utils.c
new file mode 100644
index 0000000..5d936e0
--- /dev/null
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/mount-utils.c
@@ -0,0 +1,356 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "util.h"
+#include "mount-utils.h"
+#include "configuration.h"
+
+/**
+ * Function to free an options struct.
+ * @param options - options struct to be freed.
+ * @return void.
+ */
+void free_mount_options(mount_options *options) {
+ if (options == NULL) {
+ return;
+ }
+
+ if (options->opts != NULL) {
+ for (unsigned int i = 0; i < options->num_opts; i++) {
+ free(options->opts[i]);
+ }
+ free(options->opts);
+ }
+
+ free(options);
+}
+
+/**
+ * Function to free an array of mounts.
+ * @param mounts - Array of mounts to be freed.
+ * @param num_mounts - Number of mounts to be freed.
+ * @return void.
+ */
+void free_mounts(mount *mounts, const unsigned int num_mounts) {
+ if (mounts == NULL) {
+ return;
+ }
+
+ for (unsigned int i = 0; i < num_mounts; i++) {
+ free(mounts[i].src);
+ free(mounts[i].dest);
+ free_mount_options(mounts[i].options);
+ }
+ free(mounts);
+}
+
+/**
+ * Function to determine whether a string is a volume name.
+ * @param volume_name - string to check.
+ * @return 1 on match, 0 on no match.
+ */
+static int is_volume_name(const char *volume_name) {
+ const char *regex_str = "^[a-zA-Z0-9]([a-zA-Z0-9_.-]*)$";
+ // execute_regex_match return 0 is matched success
+ return execute_regex_match(regex_str, volume_name) == 0;
+}
+
+/**
+ * Function to determine whether a string is a valid volume name and if
+ * it matches a passed in regex.
+ * @param requested - string to check.
+ * @param pattern - regular expression to check against.
+ * @return 1 on match, 0 on no match.
+ */
+static int is_volume_name_matched_by_regex(const char* requested, const char*
pattern) {
+ // execute_regex_match return 0 is matched success
+ return is_volume_name(requested) && (execute_regex_match(pattern +
sizeof("regex:"), requested) == 0);
+}
+
+/**
+ * Helper function to help normalize mounts for checking if mounts are
+ * permitted. The function does the following -
+ * 1. Find the canonical path for mount using realpath
+ * 2. If the path is a directory, add a '/' at the end (if not present)
+ * 3. Return a copy of the canonicalised path(to be freed by the caller)
+ * @param mount path to be canonicalised.
+ * @param isRegexAllowed whether regex matching is allowed for normalize mount.
+ * @return pointer to canonicalised path, NULL on error.
+ */
+static char* normalize_mount(const char* mount, const int isRegexAllowed) {
+ int ret = 0;
+ struct stat buff;
+ char *ret_ptr = NULL, *real_mount = NULL;
+ if (mount == NULL) {
+ return NULL;
+ }
+ real_mount = realpath(mount, NULL);
+ if (real_mount == NULL) {
+ // If mount is a valid named volume, just return it and let the
container runtime decide
+ if (is_volume_name(mount)) {
+ ret_ptr = strdup(mount);
+ goto free_and_exit;
+ }
+ // we only allow permitted mount to be REGEX, for permitted mount, we
check
+ // if it's a valid REGEX return; for user mount, we need to strictly
check
+ if (isRegexAllowed) {
+ if (is_regex(mount)) {
+ ret_ptr = strdup(mount);
+ goto free_and_exit;
+ }
+ }
+ fprintf(ERRORFILE, "Could not determine real path of mount '%s'\n",
mount);
+ ret_ptr = NULL;
+ goto free_and_exit;
+ }
+ ret = stat(real_mount, &buff);
+ if (ret == 0) {
+ if (S_ISDIR(buff.st_mode)) {
+ size_t len = strlen(real_mount);
+ if (len <= 0) {
+ ret_ptr = NULL;
+ goto free_and_exit;
+ }
+ if (real_mount[len - 1] != '/') {
+ ret_ptr = (char *) alloc_and_clear_memory(len + 2,
sizeof(char));
+ strncpy(ret_ptr, real_mount, len);
+ ret_ptr[len] = '/';
+ ret_ptr[len + 1] = '\0';
+ } else {
+ ret_ptr = strdup(real_mount);
+ }
+ } else {
+ ret_ptr = strdup(real_mount);
+ }
+ } else {
+ fprintf(ERRORFILE, "Could not stat path '%s'\n", real_mount);
+ ret_ptr = NULL;
+ }
+
+free_and_exit:
+ free(real_mount);
+ return ret_ptr;
+}
+
+/**
+ * Function to normalize an array of strings. Each string in the array will
+ * be normalized to its real path in the file system.
+ * @param mounts - An array of strings to normalize. The contents of this
+ * string array will be modified and replaced with their normalized
equivalents.
+ * If a string is replaced, the original string will be freed. The caller is
responsible
+ * for freeing the mounts string array.
+ * @param isRegexAllowed - Integer to determine whether or not regex is
allowed.
+ * for any of the strings. 1 for allowed, 0 for not allowed.
+ * @return 0 on success, -1 on failure.
+ */
+static int normalize_mounts(char **mounts, const int isRegexAllowed) {
+ unsigned int i = 0;
+ char *tmp = NULL;
+ if (mounts == NULL) {
+ return 0;
+ }
+ for (i = 0; mounts[i] != NULL; ++i) {
+ tmp = normalize_mount(mounts[i], isRegexAllowed);
+ if (tmp == NULL) {
+ return -1;
+ }
+ free(mounts[i]);
+ mounts[i] = tmp;
+ }
+ return 0;
+}
+
+/**
+ * Function to get the normalized path of the container-executor config file.
+ * @param container_executor_cfg_path - A pointer to a string. This pointer
will
+ * point to an allocated string containing the normalized path to the
container-executor
+ * config file. The caller is responsible for freeing this memory.
+ * @return 0 on success, MOUNT_ACCESS_ERROR on failure.
+ */
+static int get_normalized_config_path(const char
**container_executor_cfg_path) {
+ char *config_path = NULL;
+ int ret = 0;
+
+ config_path = get_config_path("");
+ *container_executor_cfg_path = normalize_mount(config_path, 0);
+ if (*container_executor_cfg_path == NULL) {
+ ret = MOUNT_ACCESS_ERROR;
+ goto free_and_exit;
+ }
+
+free_and_exit:
+ free(config_path);
+ return ret;
+}
+
+/**
+ * Function to determine whether or not a requested string path is allowed as
a mount.
+ * The requested string will be normalized and checked against the normalized
paths in the
+ * permitted_mounts string array. Volumes that match a regex in the
permitted_mounts list
+ * will also be allowed.
+ * @param permitted_mounts - An array of strings that define the permitted
list of paths
+ * for the requested string.
+ * @param requested - A string that is requested to be mounted.
+ * @return 0 on not permitted, 1 on permitted, -1 on error.
+ */
+static int check_mount_permitted(const char **permitted_mounts, const char
*requested) {
+ int ret = 0;
+ unsigned int i;
+ size_t permitted_mount_len = 0;
+ if (permitted_mounts == NULL) {
+ return 0;
+ }
+ char *normalized_path = normalize_mount(requested, 0);
+ if (normalized_path == NULL) {
+ return -1;
+ }
+ for (i = 0; permitted_mounts[i] != NULL; ++i) {
+ if (strcmp(normalized_path, permitted_mounts[i]) == 0) {
+ ret = 1;
+ break;
+ }
+ // if (permitted_mounts[i] is a REGEX): use REGEX to compare; return
+ if (is_regex(permitted_mounts[i]) &&
+ is_volume_name_matched_by_regex(normalized_path,
permitted_mounts[i])) {
+ ret = 1;
+ break;
+ }
+
+ // directory check
+ permitted_mount_len = strlen(permitted_mounts[i]);
+ struct stat path_stat;
+ stat(permitted_mounts[i], &path_stat);
+ if (S_ISDIR(path_stat.st_mode)) {
+ if (strncmp(normalized_path, permitted_mounts[i],
permitted_mount_len) == 0) {
+ ret = 1;
+ break;
+ }
+ }
+ }
+ free(normalized_path);
+ return ret;
+}
+
+/**
+ * Function to validate whether a requested mount path is permitted or not.
The normalized mount path
+ * must be in the correct permitted list based on the type of mount (ro or rw)
and must not be a
+ * parent of the container-executor config file.
+ * @param permitted_ro_mounts - Array of permitted read-only mounts.
+ * @param permitted_rw_mounts - Array of permitted read-write mounts.
+ * @param requested - Mount path to be validated
+ * @return 0 on valid mount, INVALID_MOUNT, INVALID_RW_MOUNT, INVALID_RO_MOUNT,
+ * or MOUNT_ACCESS_ERROR on error.
+ */
+static int validate_mount(const char **permitted_ro_mounts, const char
**permitted_rw_mounts, const mount *requested) {
+ const char *container_executor_cfg_path = NULL;
+ const char *tmp_path_buffer[2] = {NULL, NULL};
+ int permitted_rw, permitted_ro;
+ int ret = 0;
+
+ if (requested == NULL) {
+ goto free_and_exit;
+ }
+
+ ret = get_normalized_config_path(&container_executor_cfg_path);
+ if (ret != 0) {
+ goto free_and_exit;
+ }
+
+ permitted_rw = check_mount_permitted(permitted_rw_mounts, requested->src);
+ permitted_ro = check_mount_permitted(permitted_ro_mounts, requested->src);
+
+ if (permitted_ro == -1 || permitted_rw == -1) {
+ fprintf(ERRORFILE, "Invalid mount src='%s', dest='%s'\n",
+ requested->src, requested->dest);
+ ret = INVALID_MOUNT;
+ goto free_and_exit;
+ }
+
+ if (requested->options != NULL && requested->options->rw == 1) {
+ // rw mount
+ if (permitted_rw == 0) {
+ fprintf(ERRORFILE, "Configuration does not allow mount src='%s',
dest='%s'\n",
+ requested->src, requested->dest);
+ ret = INVALID_RW_MOUNT;
+ goto free_and_exit;
+ } else {
+ // determine if the user can modify the container-executor.cfg file
+ tmp_path_buffer[0] = normalize_mount(requested->src, 0);
+ // just re-use the function, flip the args to check if the
container-executor path is in the requested
+ // mount point
+ ret = check_mount_permitted(tmp_path_buffer,
container_executor_cfg_path);
+ free((void *) tmp_path_buffer[0]);
+ if (ret == 1) {
+ fprintf(ERRORFILE, "Attempting to mount a parent directory of
container-executor.cfg as read-write. src='%s', dest='%s'\n",
+ requested->src, requested->dest);
+ ret = INVALID_RW_MOUNT;
+ goto free_and_exit;
+ }
+ }
+ } else {
+ // ro mount
+ if (permitted_ro == 0 && permitted_rw == 0) {
+ fprintf(ERRORFILE, "Configuration does not allow mount src='%s',
dest='%s'\n",
+ requested->src, requested->dest);
+ ret = INVALID_RO_MOUNT;
+ goto free_and_exit;
+ }
+ }
+
+free_and_exit:
+ free((void *) container_executor_cfg_path);
+ return ret;
+}
+
+/**
+ * Function to validate an array of mounts.
+ * @param permitted_ro_mounts - Array of permitted read-only mounts.
+ * @param permitted_rw_mounts - Array of permitted read-write mounts.
+ * @param mounts - Array of mounts to be validated.
+ * @param num_mounts - Number of mounts to be valildated.
+ * @return 0 on valid mounts, INVALID_MOUNT, INVALID_RW_MOUNT,
INVALID_RO_MOUNT,
+ * or MOUNT_ACCESS_ERROR on error.
+ */
+int validate_mounts(char **permitted_ro_mounts, char **permitted_rw_mounts,
mount *mounts, const unsigned int num_mounts) {
+ int ret = 0;
+ unsigned int i;
+
+ ret = normalize_mounts(permitted_ro_mounts, 1);
+ ret |= normalize_mounts(permitted_rw_mounts, 1);
+ if (ret != 0) {
+ fprintf(ERRORFILE, "Unable to find permitted mounts on disk\n");
+ ret = MOUNT_ACCESS_ERROR;
+ goto free_and_exit;
+ }
+
+ for (i = 0; i < num_mounts; i++) {
+ ret = validate_mount((const char **) permitted_ro_mounts, (const char
**) permitted_rw_mounts, &mounts[i]);
+ if (ret != 0) {
+ goto free_and_exit;
+ }
+ }
+
+free_and_exit:
+ return ret;
+}
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/mount-utils.h
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/mount-utils.h
new file mode 100644
index 0000000..524cf68
--- /dev/null
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/mount-utils.h
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __YARN_POSIX_CONTAINER_EXECUTOR_MOUNT_UTIL_H__
+#define __YARN_POSIX_CONTAINER_EXECUTOR_MOUNT_UTIL_H__
+
+typedef struct mount_options_struct {
+ char **opts;
+ unsigned int num_opts;
+ unsigned int rw; // 0 for read, 1 for write
+} mount_options;
+
+typedef struct mount_struct {
+ char *src;
+ char *dest;
+ mount_options *options;
+} mount;
+
+void free_mount_options(mount_options *options);
+
+void free_mounts(mount *mounts, const unsigned int num_mounts);
+
+int validate_mounts(char **permitted_ro_mounts, char **permitted_rw_mounts,
mount *mounts, unsigned int num_mounts);
+
+#endif
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/utils/test_docker_util.cc
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/utils/test_docker_util.cc
index f57413e..8e354d1 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/utils/test_docker_util.cc
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/utils/test_docker_util.cc
@@ -22,6 +22,7 @@
extern "C" {
#include "utils/docker-util.c"
+#include "utils/mount-utils.c"
}
namespace ContainerExecutor {
@@ -121,7 +122,7 @@ namespace ContainerExecutor {
for (itr = file_cmd_vec.begin(); itr != file_cmd_vec.end(); ++itr) {
write_command_file(itr->first);
int ret = (*docker_func)(docker_command_file.c_str(),
&container_executor_cfg, &tmp);
- ASSERT_EQ(0, ret) << "error message: " <<
get_docker_error_message(ret) << " for input " << itr->first;
+ ASSERT_EQ(0, ret) << "error message: " << get_error_message(ret) << "
for input " << itr->first;
char *actual = flatten(&tmp);
ASSERT_STREQ(itr->second.c_str(), actual);
reset_args(&tmp);
@@ -136,7 +137,7 @@ namespace ContainerExecutor {
reset_args(&tmp);
}
int ret = (*docker_func)("unknown-file", &container_executor_cfg, &tmp);
- ASSERT_EQ(static_cast<int>(INVALID_COMMAND_FILE), ret);
+ ASSERT_EQ(static_cast<int>(INVALID_DOCKER_COMMAND_FILE), ret);
reset_args(&tmp);
}
@@ -181,10 +182,10 @@ namespace ContainerExecutor {
std::vector<std::pair<std::string, int> > bad_file_cmd_vec;
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=run\n
format='{{.State.Status}}'",
- static_cast<int>(INCORRECT_COMMAND)));
+ static_cast<int>(INCORRECT_DOCKER_COMMAND)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"docker-command=inspect\n format='{{.State.Status}}'",
- static_cast<int>(INCORRECT_COMMAND)));
+ static_cast<int>(INCORRECT_DOCKER_COMMAND)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=inspect\n
format={{.State.Status}}\n name=",
static_cast<int>(INVALID_DOCKER_CONTAINER_NAME)));
@@ -218,9 +219,9 @@ namespace ContainerExecutor {
std::vector<std::pair<std::string, int> > bad_file_cmd_vec;
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
- "[docker-command-execution]\n docker-command=run\n image=image-id",
static_cast<int>(INCORRECT_COMMAND)));
+ "[docker-command-execution]\n docker-command=run\n image=image-id",
static_cast<int>(INCORRECT_DOCKER_COMMAND)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
- "docker-command=load\n image=image-id",
static_cast<int>(INCORRECT_COMMAND)));
+ "docker-command=load\n image=image-id",
static_cast<int>(INCORRECT_DOCKER_COMMAND)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=load\n image=",
static_cast<int>(INVALID_DOCKER_IMAGE_NAME)));
bad_file_cmd_vec.push_back(std::make_pair<std::string,
int>("[docker-command-execution]\n docker-command=load",
@@ -288,9 +289,9 @@ namespace ContainerExecutor {
std::vector<std::pair<std::string, int> > bad_file_cmd_vec;
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
- "[docker-command-execution]\n docker-command=run\n image=image-id",
static_cast<int>(INCORRECT_COMMAND)));
+ "[docker-command-execution]\n docker-command=run\n image=image-id",
static_cast<int>(INCORRECT_DOCKER_COMMAND)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
- "docker-command=pull\n image=image-id",
static_cast<int>(INCORRECT_COMMAND)));
+ "docker-command=pull\n image=image-id",
static_cast<int>(INCORRECT_DOCKER_COMMAND)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=pull\n image=",
static_cast<int>(INVALID_DOCKER_IMAGE_NAME)));
bad_file_cmd_vec.push_back(std::make_pair<std::string,
int>("[docker-command-execution]\n docker-command=pull",
@@ -309,9 +310,9 @@ namespace ContainerExecutor {
std::vector<std::pair<std::string, int> > bad_file_cmd_vec;
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=run\n
name=container_e1_12312_11111_02_000001",
- static_cast<int>(INCORRECT_COMMAND)));
+ static_cast<int>(INCORRECT_DOCKER_COMMAND)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
- "docker-command=rm\n name=ctr-id",
static_cast<int>(INCORRECT_COMMAND)));
+ "docker-command=rm\n name=ctr-id",
static_cast<int>(INCORRECT_DOCKER_COMMAND)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=rm\n name=",
static_cast<int>(INVALID_DOCKER_CONTAINER_NAME)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
@@ -332,9 +333,9 @@ namespace ContainerExecutor {
std::vector<std::pair<std::string, int> > bad_file_cmd_vec;
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=run\n
name=container_e1_12312_11111_02_000001",
- static_cast<int>(INCORRECT_COMMAND)));
+ static_cast<int>(INCORRECT_DOCKER_COMMAND)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
- "docker-command=stop\n name=ctr-id",
static_cast<int>(INCORRECT_COMMAND)));
+ "docker-command=stop\n name=ctr-id",
static_cast<int>(INCORRECT_DOCKER_COMMAND)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=stop\n name=",
static_cast<int>(INVALID_DOCKER_CONTAINER_NAME)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
@@ -359,9 +360,9 @@ namespace ContainerExecutor {
std::vector<std::pair<std::string, int> > bad_file_cmd_vec;
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=run\n
name=container_e1_12312_11111_02_000001",
- static_cast<int>(INCORRECT_COMMAND)));
+ static_cast<int>(INCORRECT_DOCKER_COMMAND)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
- "docker-command=kill\n name=ctr-id",
static_cast<int>(INCORRECT_COMMAND)));
+ "docker-command=kill\n name=ctr-id",
static_cast<int>(INCORRECT_DOCKER_COMMAND)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=kill\n name=",
static_cast<int>(INVALID_DOCKER_CONTAINER_NAME)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
@@ -382,9 +383,9 @@ namespace ContainerExecutor {
std::vector<std::pair<std::string, int> > bad_file_cmd_vec;
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=run\n
name=container_e1_12312_11111_02_000001",
- static_cast<int>(INCORRECT_COMMAND)));
+ static_cast<int>(INCORRECT_DOCKER_COMMAND)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
- "docker-command=start\n name=ctr-id",
static_cast<int>(INCORRECT_COMMAND)));
+ "docker-command=start\n name=ctr-id",
static_cast<int>(INCORRECT_DOCKER_COMMAND)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=start\n name=",
static_cast<int>(INVALID_DOCKER_CONTAINER_NAME)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
@@ -474,7 +475,7 @@ namespace ContainerExecutor {
}
ret = set_runtime(&cmd_cfg, &container_cfg, &buff);
char *actual = flatten(&buff);
- ASSERT_EQ(0, ret) << "error message: " << get_docker_error_message(ret)
<< " for input " << itr->first;
+ ASSERT_EQ(0, ret) << "error message: " << get_error_message(ret) << "
for input " << itr->first;
ASSERT_STREQ(itr->second.c_str(), actual);
reset_args(&buff);
free(actual);
@@ -599,7 +600,7 @@ namespace ContainerExecutor {
}
ret = add_ports_mapping_to_command(&cmd_cfg, &buff);
char *actual = flatten(&buff);
- ASSERT_EQ(0, ret) << "error message: " << get_docker_error_message(ret)
<< " for input " << itr->first;
+ ASSERT_EQ(0, ret) << "error message: " << get_error_message(ret) << "
for input " << itr->first;
ASSERT_STREQ(itr->second.c_str(), actual);
reset_args(&buff);
free(actual);
@@ -655,7 +656,7 @@ namespace ContainerExecutor {
"[docker-command-execution]\n docker-command=run", ""));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=run\n pid=other",
- static_cast<int>(INVALID_PID_NAMESPACE)));
+ static_cast<int>(INVALID_DOCKER_PID_NAMESPACE)));
for (int i = 1; i < 3; ++i) {
write_container_executor_cfg(container_executor_cfg_contents[0]);
@@ -719,10 +720,10 @@ namespace ContainerExecutor {
bad_file_cmd_vec.clear();
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=run\n pid=other",
- static_cast<int>(INVALID_PID_NAMESPACE)));
+ static_cast<int>(INVALID_DOCKER_PID_NAMESPACE)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=run\n pid=host",
- static_cast<int>(PID_HOST_DISABLED)));
+ static_cast<int>(DOCKER_PID_HOST_DISABLED)));
for (itr2 = bad_file_cmd_vec.begin(); itr2 != bad_file_cmd_vec.end();
++itr2) {
write_command_file(itr2->first);
ret = read_config(docker_command_file.c_str(), &cmd_cfg);
@@ -816,7 +817,7 @@ namespace ContainerExecutor {
FAIL();
}
ret = set_privileged(&cmd_cfg, &container_cfg, &buff);
- ASSERT_EQ(6, ret);
+ ASSERT_EQ(INVALID_DOCKER_USER_NAME, ret);
ASSERT_EQ(0, buff.length);
reset_args(&buff);
free_configuration(&cmd_cfg);
@@ -827,7 +828,7 @@ namespace ContainerExecutor {
FAIL();
}
ret = set_privileged(&cmd_cfg, &container_cfg, &buff);
- ASSERT_EQ(PRIVILEGED_CONTAINERS_DISABLED, ret);
+ ASSERT_EQ(PRIVILEGED_DOCKER_CONTAINERS_DISABLED, ret);
ASSERT_EQ(0, buff.length);
reset_args(&buff);
free_configuration(&cmd_cfg);
@@ -864,7 +865,7 @@ namespace ContainerExecutor {
FAIL();
}
ret = set_privileged(&cmd_cfg, &container_cfg, &buff);
- ASSERT_EQ(PRIVILEGED_CONTAINERS_DISABLED, ret);
+ ASSERT_EQ(PRIVILEGED_DOCKER_CONTAINERS_DISABLED, ret);
ASSERT_EQ(0, buff.length);
reset_args(&buff);
free_configuration(&cmd_cfg);
@@ -1069,7 +1070,7 @@ namespace ContainerExecutor {
}
- TEST_F(TestDockerUtil, test_add_mounts) {
+ TEST_F(TestDockerUtil, test_add_docker_mounts) {
struct configuration container_cfg, cmd_cfg;
struct args buff = ARGS_INITIAL_VALUE;
int ret = 0;
@@ -1125,7 +1126,7 @@ namespace ContainerExecutor {
if (ret != 0) {
FAIL();
}
- ret = add_mounts(&cmd_cfg, &container_cfg, &buff);
+ ret = add_docker_mounts(&cmd_cfg, &container_cfg, &buff);
char *actual = flatten(&buff);
ASSERT_EQ(0, ret);
ASSERT_STREQ(itr->second.c_str(), actual);
@@ -1137,22 +1138,22 @@ namespace ContainerExecutor {
std::vector<std::pair<std::string, int> > bad_file_cmds_vec;
bad_file_cmds_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=run\n
image=hadoop/image\n mounts=/lib:/lib:rw",
- static_cast<int>(INVALID_DOCKER_RW_MOUNT)));
+ static_cast<int>(INVALID_RW_MOUNT)));
bad_file_cmds_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=run\n
image=hadoop/image\n mounts=/usr/bin/:/usr/bin:rw",
- static_cast<int>(INVALID_DOCKER_RW_MOUNT)));
+ static_cast<int>(INVALID_RW_MOUNT)));
bad_file_cmds_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=run\n
image=hadoop/image\n mounts=/blah:/blah:rw",
- static_cast<int>(INVALID_DOCKER_MOUNT)));
+ static_cast<int>(INVALID_MOUNT)));
bad_file_cmds_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=run\n
image=hadoop/image\n mounts=/tmp:/tmp:shared",
- static_cast<int>(INVALID_DOCKER_MOUNT)));
+ static_cast<int>(INVALID_MOUNT)));
bad_file_cmds_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=run\n
image=hadoop/image\n mounts=/lib:/lib",
- static_cast<int>(INVALID_DOCKER_MOUNT)));
+ static_cast<int>(INVALID_MOUNT)));
bad_file_cmds_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=run\n
image=hadoop/image\n mounts=/lib:/lib:other",
- static_cast<int>(INVALID_DOCKER_MOUNT)));
+ static_cast<int>(INVALID_MOUNT)));
std::vector<std::pair<std::string, int> >::const_iterator itr2;
@@ -1162,7 +1163,7 @@ namespace ContainerExecutor {
if (ret != 0) {
FAIL();
}
- ret = add_mounts(&cmd_cfg, &container_cfg, &buff);
+ ret = add_docker_mounts(&cmd_cfg, &container_cfg, &buff);
char *actual = flatten(&buff);
ASSERT_EQ(itr2->second, ret);
ASSERT_STREQ("", actual);
@@ -1181,8 +1182,8 @@ namespace ContainerExecutor {
if (ret != 0) {
FAIL();
}
- ret = add_mounts(&cmd_cfg, &container_cfg, &buff);
- ASSERT_EQ(INVALID_DOCKER_RW_MOUNT, ret) << " for input " <<
cmd_file_contents;
+ ret = add_docker_mounts(&cmd_cfg, &container_cfg, &buff);
+ ASSERT_EQ(INVALID_RW_MOUNT, ret) << " for input " << cmd_file_contents;
char *actual = flatten(&buff);
ASSERT_STREQ("", actual);
reset_args(&buff);
@@ -1196,7 +1197,7 @@ namespace ContainerExecutor {
free(ce_path);
free_configuration(&container_cfg);
- // For untrusted image, container add_mounts will pass through
+ // For untrusted image, container add_docker_mounts will pass through
// without mounting or report error code.
container_executor_cfg_contents = "[docker]\n";
write_container_executor_cfg(container_executor_cfg_contents);
@@ -1204,7 +1205,7 @@ namespace ContainerExecutor {
if (ret != 0) {
FAIL();
}
- ret = add_mounts(&cmd_cfg, &container_cfg, &buff);
+ ret = add_docker_mounts(&cmd_cfg, &container_cfg, &buff);
char *actual = flatten(&buff);
ASSERT_EQ(0, ret);
ASSERT_STREQ("", actual);
@@ -1266,7 +1267,7 @@ namespace ContainerExecutor {
if (ret != 0) {
FAIL();
}
- ret = add_mounts(&cmd_cfg, &container_cfg, &buff);
+ ret = add_docker_mounts(&cmd_cfg, &container_cfg, &buff);
char *actual = flatten(&buff);
ASSERT_EQ(0, ret);
ASSERT_STREQ(itr->second.c_str(), actual);
@@ -1278,10 +1279,10 @@ namespace ContainerExecutor {
std::vector<std::pair<std::string, int> > bad_file_cmds_vec;
bad_file_cmds_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=run\n
image=hadoop/image\n mounts=/etc:/etc:ro",
- static_cast<int>(INVALID_DOCKER_RO_MOUNT)));
+ static_cast<int>(INVALID_RO_MOUNT)));
bad_file_cmds_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=run\n
image=hadoop/image\n mounts=/blah:/blah:ro",
- static_cast<int>(INVALID_DOCKER_MOUNT)));
+ static_cast<int>(INVALID_MOUNT)));
std::vector<std::pair<std::string, int> >::const_iterator itr2;
@@ -1291,7 +1292,7 @@ namespace ContainerExecutor {
if (ret != 0) {
FAIL();
}
- ret = add_mounts(&cmd_cfg, &container_cfg, &buff);
+ ret = add_docker_mounts(&cmd_cfg, &container_cfg, &buff);
char *actual = flatten(&buff);
ASSERT_EQ(itr2->second, ret);
ASSERT_STREQ("", actual);
@@ -1312,8 +1313,8 @@ namespace ContainerExecutor {
if (ret != 0) {
FAIL();
}
- ret = add_mounts(&cmd_cfg, &container_cfg, &buff);
- ASSERT_EQ(INVALID_DOCKER_RO_MOUNT, ret);
+ ret = add_docker_mounts(&cmd_cfg, &container_cfg, &buff);
+ ASSERT_EQ(INVALID_RO_MOUNT, ret);
ASSERT_EQ(0, buff.length);
reset_args(&buff);
free_configuration(&cmd_cfg);
@@ -1508,7 +1509,7 @@ namespace ContainerExecutor {
" network=bridge\n privileged=true\n"
" cap-add=CHOWN,SETUID\n cgroup-parent=ctr-cgroup\n
detach=true\n rm=true\n group-add=1000,1001\n"
" launch-command=bash,test_script.sh,arg1,arg2",
- PRIVILEGED_CONTAINERS_DISABLED));
+ PRIVILEGED_DOCKER_CONTAINERS_DISABLED));
// invalid rw mount
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
@@ -1518,7 +1519,7 @@ namespace ContainerExecutor {
" network=bridge\n devices=/dev/test:/dev/test\n"
" cap-add=CHOWN,SETUID\n cgroup-parent=ctr-cgroup\n
detach=true\n rm=true\n"
" launch-command=bash,test_script.sh,arg1,arg2",
- static_cast<int>(INVALID_DOCKER_RW_MOUNT)));
+ static_cast<int>(INVALID_RW_MOUNT)));
// invalid ro mount
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
@@ -1528,7 +1529,7 @@ namespace ContainerExecutor {
" network=bridge\n devices=/dev/test:/dev/test\n"
" cap-add=CHOWN,SETUID\n cgroup-parent=ctr-cgroup\n
detach=true\n rm=true\n"
" launch-command=bash,test_script.sh,arg1,arg2",
- static_cast<int>(INVALID_DOCKER_RO_MOUNT)));
+ static_cast<int>(INVALID_RO_MOUNT)));
// invalid capability
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
@@ -1548,7 +1549,7 @@ namespace ContainerExecutor {
" network=bridge\n devices=/dev/dev1:/dev/dev1\n
privileged=true\n"
" cap-add=CHOWN,SETUID\n cgroup-parent=ctr-cgroup\n
detach=true\n rm=true\n"
" launch-command=bash,test_script.sh,arg1,arg2",
- static_cast<int>(PRIVILEGED_CONTAINERS_DISABLED)));
+ static_cast<int>(PRIVILEGED_DOCKER_CONTAINERS_DISABLED)));
// invalid network
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
@@ -1690,7 +1691,7 @@ namespace ContainerExecutor {
" network=bridge\n devices=/dev/test:/dev/test\n
privileged=true\n"
" cap-add=CHOWN,SETUID\n cgroup-parent=ctr-cgroup\n
detach=true\n rm=true\n"
" launch-command=bash,test_script.sh,arg1,arg2",
- static_cast<int>(PRIVILEGED_CONTAINERS_DISABLED)));
+ static_cast<int>(PRIVILEGED_DOCKER_CONTAINERS_DISABLED)));
run_docker_command_test(file_cmd_vec, bad_file_cmd_vec,
get_docker_run_command);
free_configuration(&container_executor_cfg);
@@ -1978,10 +1979,10 @@ namespace ContainerExecutor {
std::vector<std::pair<std::string, int> > bad_file_cmd_vec;
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"[docker-command-execution]\n docker-command=run\n image=image-id",
- static_cast<int>(INCORRECT_COMMAND)));
+ static_cast<int>(INCORRECT_DOCKER_COMMAND)));
bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
"docker-command=images\n image=image-id",
- static_cast<int>(INCORRECT_COMMAND)));
+ static_cast<int>(INCORRECT_DOCKER_COMMAND)));
run_docker_command_test(file_cmd_vec, bad_file_cmd_vec,
get_docker_images_command);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]