From 86ff28dea09037795f9a76d1712d741d04e33bfe Mon Sep 17 00:00:00 2001 From: Xuan Date: Fri, 31 Oct 2014 14:36:25 -0700 Subject: [PATCH] YARN-2701. Addendum patch. Potential race condition in startLocalizer when using LinuxContainerExecutor. Contributed by Xuan Gong --- .../impl/container-executor.c | 95 ++++++++++++++----- .../impl/container-executor.h | 6 ++ 2 files changed, 78 insertions(+), 23 deletions(-) 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 7624bef873..9af916147b 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 @@ -451,36 +451,85 @@ char *get_tmp_directory(const char *work_dir) { * with the desired permissions. */ int mkdirs(const char* path, mode_t perm) { - char *buffer = strdup(path); - char *token; - int cwd = open("/", O_RDONLY); - if (cwd == -1) { - fprintf(LOGFILE, "Can't open / in %s - %s\n", path, strerror(errno)); - free(buffer); + struct stat sb; + char * npath; + char * p; + if (stat(path, &sb) == 0) { + return check_dir(path, sb.st_mode, perm, 1); + } + npath = strdup(path); + if (npath == NULL) { + fprintf(LOGFILE, "Not enough memory to copy path string"); return -1; } - for(token = strtok(buffer, "/"); token != NULL; token = strtok(NULL, "/")) { - if (mkdirat(cwd, token, perm) != 0) { - if (errno != EEXIST) { - fprintf(LOGFILE, "Can't create directory %s in %s - %s\n", - token, path, strerror(errno)); - close(cwd); - free(buffer); - return -1; + /* Skip leading slashes. */ + p = npath; + while (*p == '/') { + p++; + } + + while (NULL != (p = strchr(p, '/'))) { + *p = '\0'; + if (create_validate_dir(npath, perm, path, 0) == -1) { + free(npath); + return -1; + } + *p++ = '/'; /* restore slash */ + while (*p == '/') + p++; + } + + /* Create the final directory component. */ + if (create_validate_dir(npath, perm, path, 1) == -1) { + free(npath); + return -1; + } + free(npath); + return 0; +} + +/* +* Create the parent directory if they do not exist. Or check the permission if +* the race condition happens. +* Give 0 or 1 to represent whether this is the final component. If it is, we +* need to check the permission. +*/ +int create_validate_dir(char* npath, mode_t perm, char* path, int finalComponent) { + struct stat sb; + if (stat(npath, &sb) != 0) { + if (mkdir(npath, perm) != 0) { + if (errno != EEXIST || stat(npath, &sb) != 0) { + fprintf(LOGFILE, "Can't create directory %s - %s\n", npath, + strerror(errno)); + return -1; + } + // The directory npath should exist. + if (check_dir(npath, sb.st_mode, perm, finalComponent) == -1) { + return -1; } } - int new_dir = openat(cwd, token, O_RDONLY); - close(cwd); - cwd = new_dir; - if (cwd == -1) { - fprintf(LOGFILE, "Can't open %s in %s - %s\n", token, path, - strerror(errno)); - free(buffer); + } else { + if (check_dir(npath, sb.st_mode, perm, finalComponent) == -1) { + return -1; + } + } + return 0; +} + +// check whether the given path is a directory +// also check the access permissions whether it is the same as desired permissions +int check_dir(char* npath, mode_t st_mode, mode_t desired, int finalComponent) { + if (!S_ISDIR(st_mode)) { + fprintf(LOGFILE, "Path %s is file not dir\n", npath); + return -1; + } else if (finalComponent == 1) { + int filePermInt = st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); + int desiredInt = desired & (S_IRWXU | S_IRWXG | S_IRWXO); + if (filePermInt != desiredInt) { + fprintf(LOGFILE, "Path %s does not have desired permission.\n", npath); return -1; } } - free(buffer); - close(cwd); return 0; } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h index 581ba04921..b1efd6aa65 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h @@ -203,3 +203,9 @@ int create_directory_for_user(const char* path); int change_user(uid_t user, gid_t group); int mount_cgroup(const char *pair, const char *hierarchy); + +int check_dir(char* npath, mode_t st_mode, mode_t desired, + int finalComponent); + +int create_validate_dir(char* npath, mode_t perm, char* path, + int finalComponent);