|
@@ -1,1300 +0,0 @@
|
|
|
-/**
|
|
|
- * 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 "task-controller.h"
|
|
|
-
|
|
|
-//struct to store the user details
|
|
|
-struct passwd *user_detail = NULL;
|
|
|
-
|
|
|
-//LOGFILE
|
|
|
-FILE *LOGFILE;
|
|
|
-
|
|
|
-//placeholder for global cleanup operations
|
|
|
-void cleanup() {
|
|
|
- free_configurations();
|
|
|
-}
|
|
|
-
|
|
|
-//change the user to passed user for executing/killing tasks
|
|
|
-int change_user(const char * user) {
|
|
|
- if (get_user_details(user) < 0) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- if(initgroups(user_detail->pw_name, user_detail->pw_gid) != 0) {
|
|
|
- fprintf(LOGFILE, "unable to initgroups : %s\n", strerror(errno));
|
|
|
- cleanup();
|
|
|
- return SETUID_OPER_FAILED;
|
|
|
- }
|
|
|
-
|
|
|
- errno = 0;
|
|
|
-
|
|
|
- setgid(user_detail->pw_gid);
|
|
|
- if (errno != 0) {
|
|
|
- fprintf(LOGFILE, "unable to setgid : %s\n", strerror(errno));
|
|
|
- cleanup();
|
|
|
- return SETUID_OPER_FAILED;
|
|
|
- }
|
|
|
-
|
|
|
- setegid(user_detail->pw_gid);
|
|
|
- if (errno != 0) {
|
|
|
- fprintf(LOGFILE, "unable to setegid : %s\n", strerror(errno));
|
|
|
- cleanup();
|
|
|
- return SETUID_OPER_FAILED;
|
|
|
- }
|
|
|
-
|
|
|
- setuid(user_detail->pw_uid);
|
|
|
- if (errno != 0) {
|
|
|
- fprintf(LOGFILE, "unable to setuid : %s\n", strerror(errno));
|
|
|
- cleanup();
|
|
|
- return SETUID_OPER_FAILED;
|
|
|
- }
|
|
|
-
|
|
|
- seteuid(user_detail->pw_uid);
|
|
|
- if (errno != 0) {
|
|
|
- fprintf(LOGFILE, "unable to seteuid : %s\n", strerror(errno));
|
|
|
- cleanup();
|
|
|
- return SETUID_OPER_FAILED;
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Checks the passed value for the variable config_key against the values in
|
|
|
- * the configuration.
|
|
|
- * Returns 0 if the passed value is found in the configuration,
|
|
|
- * -1 otherwise
|
|
|
- */
|
|
|
-int check_variable_against_config(const char *config_key,
|
|
|
- const char *passed_value) {
|
|
|
-
|
|
|
- if (config_key == NULL || passed_value == NULL) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- int found = -1;
|
|
|
-
|
|
|
- const char **config_value = get_values(config_key);
|
|
|
-
|
|
|
- if (config_value == NULL) {
|
|
|
- fprintf(LOGFILE, "%s is not configured.\n", config_key);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- char *full_config_value = (char *)get_value(config_key);
|
|
|
-
|
|
|
- char **config_val_ptr = (char **) config_value;
|
|
|
- while (*config_val_ptr != NULL) {
|
|
|
- if (strcmp(*config_val_ptr, passed_value) == 0) {
|
|
|
- found = 0;
|
|
|
- break;
|
|
|
- }
|
|
|
- config_val_ptr++;
|
|
|
- }
|
|
|
-
|
|
|
- if (found != 0) {
|
|
|
- fprintf(
|
|
|
- LOGFILE,
|
|
|
- "Invalid value passed: \
|
|
|
- Configured value of %s is %s. \
|
|
|
- Passed value is %s.\n",
|
|
|
- config_key, full_config_value, passed_value);
|
|
|
- }
|
|
|
- free(full_config_value);
|
|
|
- free(config_value);
|
|
|
- return found;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Utility function to concatenate argB to argA using the concat_pattern
|
|
|
- */
|
|
|
-char *concatenate(char *concat_pattern, char *return_path_name, int numArgs,
|
|
|
- ...) {
|
|
|
- va_list ap;
|
|
|
- va_start(ap, numArgs);
|
|
|
- int strlen_args = 0;
|
|
|
- char *arg = NULL;
|
|
|
- int j;
|
|
|
- for (j = 0; j < numArgs; j++) {
|
|
|
- arg = va_arg(ap, char*);
|
|
|
- if (arg == NULL) {
|
|
|
- fprintf(LOGFILE, "One of the arguments passed for %s in null.\n",
|
|
|
- return_path_name);
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- strlen_args += strlen(arg);
|
|
|
- }
|
|
|
- va_end(ap);
|
|
|
-
|
|
|
- char *return_path = NULL;
|
|
|
- int str_len = strlen(concat_pattern) + strlen_args;
|
|
|
-
|
|
|
- return_path = (char *) malloc(sizeof(char) * (str_len + 1));
|
|
|
- if (return_path == NULL) {
|
|
|
- fprintf(LOGFILE, "Unable to allocate memory for %s.\n", return_path_name);
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- memset(return_path, '\0', str_len + 1);
|
|
|
- va_start(ap, numArgs);
|
|
|
- vsnprintf(return_path, str_len, concat_pattern, ap);
|
|
|
- va_end(ap);
|
|
|
- return return_path;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Get the job-directory path from tt_root, user name and job-id
|
|
|
- */
|
|
|
-char *get_job_directory(const char * tt_root, const char *user,
|
|
|
- const char *jobid) {
|
|
|
- return concatenate(TT_JOB_DIR_PATTERN, "job_dir_path", 3, tt_root, user,
|
|
|
- jobid);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Get the user directory of a particular user
|
|
|
- */
|
|
|
-char *get_user_directory(const char *tt_root, const char *user) {
|
|
|
- return concatenate(USER_DIR_PATTERN, "user_dir_path", 2, tt_root, user);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Get the distributed cache directory for a particular user
|
|
|
- */
|
|
|
-char *get_distributed_cache_directory(const char *tt_root, const char *user,
|
|
|
- const char* unique_string) {
|
|
|
- return concatenate(USER_DISTRIBUTED_CACHE_DIR_PATTERN,
|
|
|
- "dist_cache_unique_path", 3, tt_root, user, unique_string);
|
|
|
-}
|
|
|
-
|
|
|
-char *get_job_work_directory(const char *job_dir) {
|
|
|
- return concatenate(JOB_DIR_TO_JOB_WORK_PATTERN, "job_work_dir_path", 2,
|
|
|
- job_dir, "");
|
|
|
-}
|
|
|
-/**
|
|
|
- * Get the attempt directory for the given attempt_id
|
|
|
- */
|
|
|
-char *get_attempt_directory(const char *job_dir, const char *attempt_id) {
|
|
|
- return concatenate(JOB_DIR_TO_ATTEMPT_DIR_PATTERN, "attempt_dir_path", 2,
|
|
|
- job_dir, attempt_id);
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Get the path to the task launcher file which is created by the TT
|
|
|
- */
|
|
|
-char *get_task_launcher_file(const char *job_dir, const char *attempt_dir) {
|
|
|
- return concatenate(TASK_SCRIPT_PATTERN, "task_script_path", 2, job_dir,
|
|
|
- attempt_dir);
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Builds the full path of the dir(localTaskDir or localWorkDir)
|
|
|
- * tt_root : is the base path(i.e. mapred-local-dir) sent to task-controller
|
|
|
- * dir_to_be_deleted : is either taskDir($taskId) OR taskWorkDir($taskId/work)
|
|
|
- */
|
|
|
-char *get_task_dir_path(const char *tt_root, const char *user,
|
|
|
- const char *jobid, const char *dir_to_be_deleted) {
|
|
|
- return concatenate(TT_LOCAL_TASK_DIR_PATTERN, "task_dir_full_path", 4,
|
|
|
- tt_root, user, jobid, dir_to_be_deleted);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Get the log directory for the given attempt.
|
|
|
- */
|
|
|
-char *get_task_log_dir(const char *log_dir, const char *job_id,
|
|
|
- const char *attempt_id) {
|
|
|
- return concatenate(ATTEMPT_LOG_DIR_PATTERN, "task_log_dir", 3, log_dir,
|
|
|
- job_id, attempt_id);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Get the log directory for the given job.
|
|
|
- */
|
|
|
-char *get_job_log_dir(const char *log_dir, const char *job_id) {
|
|
|
- return concatenate(JOB_LOG_DIR_PATTERN, "job_log_dir", 2, log_dir, job_id);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Get the job ACLs file for the given job log dir.
|
|
|
- */
|
|
|
-char *get_job_acls_file(const char *log_dir) {
|
|
|
- return concatenate(JOB_LOG_DIR_TO_JOB_ACLS_FILE_PATTERN, "job_acls_file",
|
|
|
- 1, log_dir);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Function to check if the passed tt_root is present in mapreduce.cluster.local.dir
|
|
|
- * the task-controller is configured with.
|
|
|
- */
|
|
|
-int check_tt_root(const char *tt_root) {
|
|
|
- return check_variable_against_config(TT_SYS_DIR_KEY, tt_root);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Function to check if the constructed path and absolute path of the task
|
|
|
- * launcher file resolve to one and same. This is done so as to avoid
|
|
|
- * security pitfalls because of relative path components in the file name.
|
|
|
- */
|
|
|
-int check_path_for_relative_components(char *path) {
|
|
|
- char * resolved_path = (char *) canonicalize_file_name(path);
|
|
|
- if (resolved_path == NULL) {
|
|
|
- fprintf(LOGFILE,
|
|
|
- "Error resolving the path: %s. Passed path: %s\n",
|
|
|
- strerror(errno), path);
|
|
|
- return ERROR_RESOLVING_FILE_PATH;
|
|
|
- }
|
|
|
- if (strcmp(resolved_path, path) != 0) {
|
|
|
- fprintf(LOGFILE,
|
|
|
- "Relative path components in the path: %s. Resolved path: %s\n",
|
|
|
- path, resolved_path);
|
|
|
- free(resolved_path);
|
|
|
- return RELATIVE_PATH_COMPONENTS_IN_FILE_PATH;
|
|
|
- }
|
|
|
- free(resolved_path);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Function to change the owner/group of a given path.
|
|
|
- */
|
|
|
-static int change_owner(const char *path, uid_t uid, gid_t gid) {
|
|
|
- int exit_code = chown(path, uid, gid);
|
|
|
- if (exit_code != 0) {
|
|
|
- fprintf(LOGFILE, "chown %d:%d for path %s failed: %s.\n", uid, gid, path,
|
|
|
- strerror(errno));
|
|
|
- }
|
|
|
- return exit_code;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Function to change the mode of a given path.
|
|
|
- */
|
|
|
-static int change_mode(const char *path, mode_t mode) {
|
|
|
- int exit_code = chmod(path, mode);
|
|
|
- if (exit_code != 0) {
|
|
|
- fprintf(LOGFILE, "chmod %d of path %s failed: %s.\n", mode, path,
|
|
|
- strerror(errno));
|
|
|
- }
|
|
|
- return exit_code;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Function to change permissions of the given path. It does the following
|
|
|
- * recursively:
|
|
|
- * 1) changes the owner/group of the paths to the passed owner/group
|
|
|
- * 2) changes the file permission to the passed file_mode and directory
|
|
|
- * permission to the passed dir_mode
|
|
|
- *
|
|
|
- * should_check_ownership : boolean to enable checking of ownership of each path
|
|
|
- */
|
|
|
-static int secure_path(const char *path, uid_t uid, gid_t gid,
|
|
|
- mode_t file_mode, mode_t dir_mode, int should_check_ownership) {
|
|
|
- FTS *tree = NULL; // the file hierarchy
|
|
|
- FTSENT *entry = NULL; // a file in the hierarchy
|
|
|
- char *paths[] = { (char *) path, NULL };//array needs to be NULL-terminated
|
|
|
- int process_path = 0;
|
|
|
- int dir = 0;
|
|
|
- int error_code = 0;
|
|
|
- int done = 0;
|
|
|
-
|
|
|
- // Get physical locations and don't resolve the symlinks.
|
|
|
- // Don't change directory while walking the directory.
|
|
|
- int ftsoptions = FTS_PHYSICAL | FTS_NOCHDIR;
|
|
|
-
|
|
|
- tree = fts_open(paths, ftsoptions, NULL);
|
|
|
- if (tree == NULL) {
|
|
|
- fprintf(LOGFILE,
|
|
|
- "Cannot open file traversal structure for the path %s:%s.\n", path,
|
|
|
- strerror(errno));
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- while (((entry = fts_read(tree)) != NULL) && !done) {
|
|
|
- dir = 0;
|
|
|
- switch (entry->fts_info) {
|
|
|
- case FTS_D:
|
|
|
- // A directory being visited in pre-order.
|
|
|
- // We change ownership of directories in post-order.
|
|
|
- // so ignore the pre-order visit.
|
|
|
- process_path = 0;
|
|
|
- break;
|
|
|
- case FTS_DC:
|
|
|
- // A directory that causes a cycle in the tree
|
|
|
- // We don't expect cycles, ignore.
|
|
|
- process_path = 0;
|
|
|
- break;
|
|
|
- case FTS_DNR:
|
|
|
- // A directory which cannot be read
|
|
|
- // Ignore and set error code.
|
|
|
- process_path = 0;
|
|
|
- error_code = -1;
|
|
|
- break;
|
|
|
- case FTS_DOT:
|
|
|
- // "." or ".."
|
|
|
- process_path = 0;
|
|
|
- break;
|
|
|
- case FTS_F:
|
|
|
- // A regular file
|
|
|
- process_path = 1;
|
|
|
- break;
|
|
|
- case FTS_DP:
|
|
|
- // A directory being visited in post-order
|
|
|
- if (entry->fts_level == 0) {
|
|
|
- // root directory. Done with traversing.
|
|
|
- done = 1;
|
|
|
- }
|
|
|
- process_path = 1;
|
|
|
- dir = 1;
|
|
|
- break;
|
|
|
- case FTS_SL:
|
|
|
- // A symbolic link
|
|
|
- // We don't want to change-ownership(and set-permissions) for the file/dir
|
|
|
- // pointed to by any symlink.
|
|
|
- process_path = 0;
|
|
|
- break;
|
|
|
- case FTS_SLNONE:
|
|
|
- // A symbolic link with a nonexistent target
|
|
|
- process_path = 0;
|
|
|
- break;
|
|
|
- case FTS_NS:
|
|
|
- // A file for which no stat(2) information was available
|
|
|
- // Ignore and set error code
|
|
|
- process_path = 0;
|
|
|
- error_code = -1;
|
|
|
- break;
|
|
|
- case FTS_ERR:
|
|
|
- // An error return. Ignore and set error code.
|
|
|
- process_path = 0;
|
|
|
- error_code = -1;
|
|
|
- break;
|
|
|
- case FTS_DEFAULT:
|
|
|
- // File that doesn't belong to any of the above type. Ignore.
|
|
|
- process_path = 0;
|
|
|
- break;
|
|
|
- default:
|
|
|
- // None of the above. Ignore and set error code
|
|
|
- process_path = 0;
|
|
|
- error_code = -1;
|
|
|
- }
|
|
|
-
|
|
|
- if (error_code != 0) {
|
|
|
- break;
|
|
|
- }
|
|
|
- if (!process_path) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- error_code = secure_single_path(entry->fts_path, uid, gid,
|
|
|
- (dir ? dir_mode : file_mode), should_check_ownership);
|
|
|
-
|
|
|
- }
|
|
|
- if (fts_close(tree) != 0) {
|
|
|
- fprintf(LOGFILE, "couldn't close file traversal structure:%s.\n",
|
|
|
- strerror(errno));
|
|
|
- }
|
|
|
- return error_code;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Function to change ownership and permissions of the given path.
|
|
|
- * This call sets ownership and permissions just for the path, not recursive.
|
|
|
- */
|
|
|
-int secure_single_path(char *path, uid_t uid, gid_t gid,
|
|
|
- mode_t perm, int should_check_ownership) {
|
|
|
- int error_code = 0;
|
|
|
- if (should_check_ownership &&
|
|
|
- (check_ownership(path, uid, gid) != 0)) {
|
|
|
- fprintf(LOGFILE,
|
|
|
- "Invalid file path. %s not user/group owned by the tasktracker.\n", path);
|
|
|
- error_code = -1;
|
|
|
- } else if (change_owner(path, uid, gid) != 0) {
|
|
|
- fprintf(LOGFILE, "couldn't change the ownership of %s\n", path);
|
|
|
- error_code = -3;
|
|
|
- } else if (change_mode(path, perm) != 0) {
|
|
|
- fprintf(LOGFILE, "couldn't change the permissions of %s\n", path);
|
|
|
- error_code = -3;
|
|
|
- }
|
|
|
- return error_code;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Function to prepare the attempt directories for the task JVM.
|
|
|
- * This is done by changing the ownership of the attempt directory recursively
|
|
|
- * to the job owner. We do the following:
|
|
|
- * * sudo chown user:mapred -R taskTracker/$user/jobcache/$jobid/$attemptid/
|
|
|
- * * sudo chmod 2770 -R taskTracker/$user/jobcache/$jobid/$attemptid/
|
|
|
- */
|
|
|
-int prepare_attempt_directories(const char *job_id, const char *attempt_id,
|
|
|
- const char *user) {
|
|
|
- if (job_id == NULL || attempt_id == NULL || user == NULL) {
|
|
|
- fprintf(LOGFILE, "Either attempt_id is null or the user passed is null.\n");
|
|
|
- return INVALID_ARGUMENT_NUMBER;
|
|
|
- }
|
|
|
-
|
|
|
- gid_t tasktracker_gid = getegid(); // the group permissions of the binary.
|
|
|
-
|
|
|
- if (get_user_details(user) < 0) {
|
|
|
- fprintf(LOGFILE, "Couldn't get the user details of %s.\n", user);
|
|
|
- return INVALID_USER_NAME;
|
|
|
- }
|
|
|
-
|
|
|
- char **local_dir = (char **) get_values(TT_SYS_DIR_KEY);
|
|
|
-
|
|
|
- if (local_dir == NULL) {
|
|
|
- fprintf(LOGFILE, "%s is not configured.\n", TT_SYS_DIR_KEY);
|
|
|
- cleanup();
|
|
|
- return PREPARE_ATTEMPT_DIRECTORIES_FAILED;
|
|
|
- }
|
|
|
-
|
|
|
- char *full_local_dir_str = (char *) get_value(TT_SYS_DIR_KEY);
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE, "Value from config for %s is %s.\n", TT_SYS_DIR_KEY,
|
|
|
- full_local_dir_str);
|
|
|
-#endif
|
|
|
-
|
|
|
- char *job_dir;
|
|
|
- char *attempt_dir;
|
|
|
- char **local_dir_ptr = local_dir;
|
|
|
- int failed = 0;
|
|
|
- while (*local_dir_ptr != NULL) {
|
|
|
- job_dir = get_job_directory(*local_dir_ptr, user, job_id);
|
|
|
- if (job_dir == NULL) {
|
|
|
- fprintf(LOGFILE, "Couldn't get job directory for %s.\n", job_id);
|
|
|
- failed = 1;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- // prepare attempt-dir in each of the mapreduce.cluster.local.dir
|
|
|
- attempt_dir = get_attempt_directory(job_dir, attempt_id);
|
|
|
- if (attempt_dir == NULL) {
|
|
|
- fprintf(LOGFILE, "Couldn't get attempt directory for %s.\n", attempt_id);
|
|
|
- failed = 1;
|
|
|
- free(job_dir);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- struct stat filestat;
|
|
|
- if (stat(attempt_dir, &filestat) != 0) {
|
|
|
- if (errno == ENOENT) {
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE,
|
|
|
- "attempt_dir %s doesn't exist. Not doing anything.\n", attempt_dir);
|
|
|
-#endif
|
|
|
- } else {
|
|
|
- // stat failed because of something else!
|
|
|
- fprintf(LOGFILE, "Failed to stat the attempt_dir %s\n", attempt_dir);
|
|
|
- failed = 1;
|
|
|
- free(attempt_dir);
|
|
|
- free(job_dir);
|
|
|
- break;
|
|
|
- }
|
|
|
- } else if (secure_path(attempt_dir, user_detail->pw_uid,
|
|
|
- tasktracker_gid, S_IRWXU | S_IRWXG, S_ISGID | S_IRWXU | S_IRWXG,
|
|
|
- 1) != 0) {
|
|
|
- // No setgid on files and setgid on dirs, 770
|
|
|
- fprintf(LOGFILE, "Failed to secure the attempt_dir %s\n", attempt_dir);
|
|
|
- failed = 1;
|
|
|
- free(attempt_dir);
|
|
|
- free(job_dir);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- local_dir_ptr++;
|
|
|
- free(attempt_dir);
|
|
|
- free(job_dir);
|
|
|
- }
|
|
|
- free(local_dir);
|
|
|
- free(full_local_dir_str);
|
|
|
-
|
|
|
- cleanup();
|
|
|
- if (failed) {
|
|
|
- return PREPARE_ATTEMPT_DIRECTORIES_FAILED;
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Function to prepare the job log dir(and job acls file in it) for the child.
|
|
|
- * It gives the user ownership of the job's log-dir to the user and
|
|
|
- * group ownership to the user running tasktracker(i.e. tt_user).
|
|
|
- *
|
|
|
- * * sudo chown user:mapred log-dir/userlogs/$jobid
|
|
|
- * * if user is not $tt_user,
|
|
|
- * * sudo chmod 2570 log-dir/userlogs/$jobid
|
|
|
- * * else
|
|
|
- * * sudo chmod 2770 log-dir/userlogs/$jobid
|
|
|
- * * sudo chown user:mapred log-dir/userlogs/$jobid/job-acls.xml
|
|
|
- * * if user is not $tt_user,
|
|
|
- * * sudo chmod 2570 log-dir/userlogs/$jobid/job-acls.xml
|
|
|
- * * else
|
|
|
- * * sudo chmod 2770 log-dir/userlogs/$jobid/job-acls.xml
|
|
|
- */
|
|
|
-int prepare_job_logs(const char *log_dir, const char *job_id,
|
|
|
- mode_t permissions) {
|
|
|
-
|
|
|
- char *job_log_dir = get_job_log_dir(log_dir, job_id);
|
|
|
- if (job_log_dir == NULL) {
|
|
|
- fprintf(LOGFILE, "Couldn't get job log directory %s.\n", job_log_dir);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- struct stat filestat;
|
|
|
- if (stat(job_log_dir, &filestat) != 0) {
|
|
|
- if (errno == ENOENT) {
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE, "job_log_dir %s doesn't exist. Not doing anything.\n",
|
|
|
- job_log_dir);
|
|
|
-#endif
|
|
|
- free(job_log_dir);
|
|
|
- return 0;
|
|
|
- } else {
|
|
|
- // stat failed because of something else!
|
|
|
- fprintf(LOGFILE, "Failed to stat the job log dir %s\n", job_log_dir);
|
|
|
- free(job_log_dir);
|
|
|
- return -1;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- gid_t tasktracker_gid = getegid(); // the group permissions of the binary.
|
|
|
- // job log directory should not be set permissions recursively
|
|
|
- // because, on tt restart/reinit, it would contain directories of earlier run
|
|
|
- if (secure_single_path(job_log_dir, user_detail->pw_uid, tasktracker_gid,
|
|
|
- S_ISGID | permissions, 1) != 0) {
|
|
|
- fprintf(LOGFILE, "Failed to secure the log_dir %s\n", job_log_dir);
|
|
|
- free(job_log_dir);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- //set ownership and permissions for job_log_dir/job-acls.xml, if exists.
|
|
|
- char *job_acls_file = get_job_acls_file(job_log_dir);
|
|
|
- if (job_acls_file == NULL) {
|
|
|
- fprintf(LOGFILE, "Couldn't get job acls file %s.\n", job_acls_file);
|
|
|
- free(job_log_dir);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- struct stat filestat1;
|
|
|
- if (stat(job_acls_file, &filestat1) != 0) {
|
|
|
- if (errno == ENOENT) {
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE, "job_acls_file %s doesn't exist. Not doing anything.\n",
|
|
|
- job_acls_file);
|
|
|
-#endif
|
|
|
- free(job_acls_file);
|
|
|
- free(job_log_dir);
|
|
|
- return 0;
|
|
|
- } else {
|
|
|
- // stat failed because of something else!
|
|
|
- fprintf(LOGFILE, "Failed to stat the job_acls_file %s\n", job_acls_file);
|
|
|
- free(job_acls_file);
|
|
|
- free(job_log_dir);
|
|
|
- return -1;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (secure_single_path(job_acls_file, user_detail->pw_uid, tasktracker_gid,
|
|
|
- permissions, 1) != 0) {
|
|
|
- fprintf(LOGFILE, "Failed to secure the job acls file %s\n", job_acls_file);
|
|
|
- free(job_acls_file);
|
|
|
- free(job_log_dir);
|
|
|
- return -1;
|
|
|
- }
|
|
|
- free(job_acls_file);
|
|
|
- free(job_log_dir);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Function to prepare the task logs for the child. It gives the user
|
|
|
- * ownership of the attempt's log-dir to the user and group ownership to the
|
|
|
- * user running tasktracker.
|
|
|
- * * sudo chown user:mapred log-dir/userlogs/$jobid/$attemptid
|
|
|
- * * sudo chmod -R 2770 log-dir/userlogs/$jobid/$attemptid
|
|
|
- */
|
|
|
-int prepare_task_logs(const char *log_dir, const char *job_id,
|
|
|
- const char *task_id) {
|
|
|
-
|
|
|
- char *task_log_dir = get_task_log_dir(log_dir, job_id, task_id);
|
|
|
- if (task_log_dir == NULL) {
|
|
|
- fprintf(LOGFILE, "Couldn't get task_log directory %s.\n", task_log_dir);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- struct stat filestat;
|
|
|
- if (stat(task_log_dir, &filestat) != 0) {
|
|
|
- if (errno == ENOENT) {
|
|
|
- // See TaskRunner.java to see that an absent log-dir doesn't fail the task.
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE, "task_log_dir %s doesn't exist. Not doing anything.\n",
|
|
|
- task_log_dir);
|
|
|
-#endif
|
|
|
- free(task_log_dir);
|
|
|
- return 0;
|
|
|
- } else {
|
|
|
- // stat failed because of something else!
|
|
|
- fprintf(LOGFILE, "Failed to stat the task_log_dir %s\n", task_log_dir);
|
|
|
- free(task_log_dir);
|
|
|
- return -1;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- gid_t tasktracker_gid = getegid(); // the group permissions of the binary.
|
|
|
- if (secure_path(task_log_dir, user_detail->pw_uid, tasktracker_gid,
|
|
|
- S_IRWXU | S_IRWXG, S_ISGID | S_IRWXU | S_IRWXG, 1) != 0) {
|
|
|
- // setgid on dirs but not files, 770. As of now, there are no files though
|
|
|
- fprintf(LOGFILE, "Failed to secure the log_dir %s\n", task_log_dir);
|
|
|
- free(task_log_dir);
|
|
|
- return -1;
|
|
|
- }
|
|
|
- free(task_log_dir);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-//function used to populate and user_details structure.
|
|
|
-int get_user_details(const char *user) {
|
|
|
- if (user_detail == NULL) {
|
|
|
- user_detail = getpwnam(user);
|
|
|
- if (user_detail == NULL) {
|
|
|
- fprintf(LOGFILE, "Invalid user\n");
|
|
|
- return -1;
|
|
|
- }
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Function to check if the TaskTracker actually owns the file.
|
|
|
- * Or it has right ownership already.
|
|
|
- */
|
|
|
-int check_ownership(char *path, uid_t uid, gid_t gid) {
|
|
|
- struct stat filestat;
|
|
|
- if (stat(path, &filestat) != 0) {
|
|
|
- return UNABLE_TO_STAT_FILE;
|
|
|
- }
|
|
|
- // check user/group. User should be TaskTracker user, group can either be
|
|
|
- // TaskTracker's primary group or the special group to which binary's
|
|
|
- // permissions are set.
|
|
|
- // Or it can be the user/group owned by uid and gid passed.
|
|
|
- if ((getuid() != filestat.st_uid || (getgid() != filestat.st_gid && getegid()
|
|
|
- != filestat.st_gid)) &&
|
|
|
- ((uid != filestat.st_uid) || (gid != filestat.st_gid))) {
|
|
|
- return FILE_NOT_OWNED_BY_TASKTRACKER;
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Function to initialize the user directories of a user.
|
|
|
- * It does the following:
|
|
|
- * * sudo chown user:mapred -R taskTracker/$user
|
|
|
- * * if user is not $tt_user,
|
|
|
- * * sudo chmod 2570 -R taskTracker/$user
|
|
|
- * * else // user is tt_user
|
|
|
- * * sudo chmod 2770 -R taskTracker/$user
|
|
|
- * This is done once per every user on the TaskTracker.
|
|
|
- */
|
|
|
-int initialize_user(const char *user) {
|
|
|
-
|
|
|
- if (user == NULL) {
|
|
|
- fprintf(LOGFILE, "user passed is null.\n");
|
|
|
- return INVALID_ARGUMENT_NUMBER;
|
|
|
- }
|
|
|
-
|
|
|
- if (get_user_details(user) < 0) {
|
|
|
- fprintf(LOGFILE, "Couldn't get the user details of %s", user);
|
|
|
- return INVALID_USER_NAME;
|
|
|
- }
|
|
|
-
|
|
|
- gid_t tasktracker_gid = getegid(); // the group permissions of the binary.
|
|
|
-
|
|
|
- char **local_dir = (char **) get_values(TT_SYS_DIR_KEY);
|
|
|
- if (local_dir == NULL) {
|
|
|
- fprintf(LOGFILE, "%s is not configured.\n", TT_SYS_DIR_KEY);
|
|
|
- cleanup();
|
|
|
- return INVALID_TT_ROOT;
|
|
|
- }
|
|
|
-
|
|
|
- char *full_local_dir_str = (char *) get_value(TT_SYS_DIR_KEY);
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE, "Value from config for %s is %s.\n", TT_SYS_DIR_KEY,
|
|
|
- full_local_dir_str);
|
|
|
-#endif
|
|
|
-
|
|
|
- int is_tt_user = (user_detail->pw_uid == getuid());
|
|
|
-
|
|
|
- // for tt_user, set 770 permissions; otherwise set 570
|
|
|
- mode_t permissions = is_tt_user ? (S_IRWXU | S_IRWXG)
|
|
|
- : (S_IRUSR | S_IXUSR | S_IRWXG);
|
|
|
- char *user_dir;
|
|
|
- char **local_dir_ptr = local_dir;
|
|
|
- int failed = 0;
|
|
|
- while (*local_dir_ptr != NULL) {
|
|
|
- user_dir = get_user_directory(*local_dir_ptr, user);
|
|
|
- if (user_dir == NULL) {
|
|
|
- fprintf(LOGFILE, "Couldn't get userdir directory for %s.\n", user);
|
|
|
- failed = 1;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- struct stat filestat;
|
|
|
- if (stat(user_dir, &filestat) != 0) {
|
|
|
- if (errno == ENOENT) {
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE, "user_dir %s doesn't exist. Not doing anything.\n",
|
|
|
- user_dir);
|
|
|
-#endif
|
|
|
- } else {
|
|
|
- // stat failed because of something else!
|
|
|
- fprintf(LOGFILE, "Failed to stat the user_dir %s\n",
|
|
|
- user_dir);
|
|
|
- failed = 1;
|
|
|
- free(user_dir);
|
|
|
- break;
|
|
|
- }
|
|
|
- } else if (secure_path(user_dir, user_detail->pw_uid,
|
|
|
- tasktracker_gid, permissions, S_ISGID | permissions, 1) != 0) {
|
|
|
- // No setgid on files and setgid on dirs,
|
|
|
- // 770 for tt_user and 570 for any other user
|
|
|
- fprintf(LOGFILE, "Failed to secure the user_dir %s\n",
|
|
|
- user_dir);
|
|
|
- failed = 1;
|
|
|
- free(user_dir);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- local_dir_ptr++;
|
|
|
- free(user_dir);
|
|
|
- }
|
|
|
- free(local_dir);
|
|
|
- free(full_local_dir_str);
|
|
|
- cleanup();
|
|
|
- if (failed) {
|
|
|
- return INITIALIZE_USER_FAILED;
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Function to prepare the job directories for the task JVM.
|
|
|
- * We do the following:
|
|
|
- * * sudo chown user:mapred -R taskTracker/$user/jobcache/$jobid
|
|
|
- * * sudo chown user:mapred -R logs/userlogs/$jobid
|
|
|
- * * if user is not $tt_user,
|
|
|
- * * sudo chmod 2570 -R taskTracker/$user/jobcache/$jobid
|
|
|
- * * sudo chmod 2570 -R logs/userlogs/$jobid
|
|
|
- * * else // user is tt_user
|
|
|
- * * sudo chmod 2770 -R taskTracker/$user/jobcache/$jobid
|
|
|
- * * sudo chmod 2770 -R logs/userlogs/$jobid
|
|
|
- * *
|
|
|
- * * For any user, sudo chmod 2770 taskTracker/$user/jobcache/$jobid/work
|
|
|
- */
|
|
|
-int initialize_job(const char *jobid, const char *user) {
|
|
|
- if (jobid == NULL || user == NULL) {
|
|
|
- fprintf(LOGFILE, "Either jobid is null or the user passed is null.\n");
|
|
|
- return INVALID_ARGUMENT_NUMBER;
|
|
|
- }
|
|
|
-
|
|
|
- if (get_user_details(user) < 0) {
|
|
|
- fprintf(LOGFILE, "Couldn't get the user details of %s", user);
|
|
|
- return INVALID_USER_NAME;
|
|
|
- }
|
|
|
-
|
|
|
- gid_t tasktracker_gid = getegid(); // the group permissions of the binary.
|
|
|
-
|
|
|
- char **local_dir = (char **) get_values(TT_SYS_DIR_KEY);
|
|
|
- if (local_dir == NULL) {
|
|
|
- fprintf(LOGFILE, "%s is not configured.\n", TT_SYS_DIR_KEY);
|
|
|
- cleanup();
|
|
|
- return INVALID_TT_ROOT;
|
|
|
- }
|
|
|
-
|
|
|
- char *full_local_dir_str = (char *) get_value(TT_SYS_DIR_KEY);
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE, "Value from config for %s is %s.\n", TT_SYS_DIR_KEY,
|
|
|
- full_local_dir_str);
|
|
|
-#endif
|
|
|
-
|
|
|
- int is_tt_user = (user_detail->pw_uid == getuid());
|
|
|
-
|
|
|
- // for tt_user, set 770 permissions; for any other user, set 570 for job-dir
|
|
|
- mode_t permissions = is_tt_user ? (S_IRWXU | S_IRWXG)
|
|
|
- : (S_IRUSR | S_IXUSR | S_IRWXG);
|
|
|
- char *job_dir, *job_work_dir;
|
|
|
- char **local_dir_ptr = local_dir;
|
|
|
- int failed = 0;
|
|
|
- while (*local_dir_ptr != NULL) {
|
|
|
- job_dir = get_job_directory(*local_dir_ptr, user, jobid);
|
|
|
- if (job_dir == NULL) {
|
|
|
- fprintf(LOGFILE, "Couldn't get job directory for %s.\n", jobid);
|
|
|
- failed = 1;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- struct stat filestat;
|
|
|
- if (stat(job_dir, &filestat) != 0) {
|
|
|
- if (errno == ENOENT) {
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE, "job_dir %s doesn't exist. Not doing anything.\n",
|
|
|
- job_dir);
|
|
|
-#endif
|
|
|
- } else {
|
|
|
- // stat failed because of something else!
|
|
|
- fprintf(LOGFILE, "Failed to stat the job_dir %s\n", job_dir);
|
|
|
- failed = 1;
|
|
|
- free(job_dir);
|
|
|
- break;
|
|
|
- }
|
|
|
- } else if (secure_path(job_dir, user_detail->pw_uid, tasktracker_gid,
|
|
|
- permissions, S_ISGID | permissions, 1) != 0) {
|
|
|
- // No setgid on files and setgid on dirs,
|
|
|
- // 770 for tt_user and 570 for any other user
|
|
|
- fprintf(LOGFILE, "Failed to secure the job_dir %s\n", job_dir);
|
|
|
- failed = 1;
|
|
|
- free(job_dir);
|
|
|
- break;
|
|
|
- } else if (!is_tt_user) {
|
|
|
- // For tt_user, we don't need this as we already set 2770 for
|
|
|
- // job-work-dir because of "chmod -R" done above
|
|
|
- job_work_dir = get_job_work_directory(job_dir);
|
|
|
- if (job_work_dir == NULL) {
|
|
|
- fprintf(LOGFILE, "Couldn't get job-work directory for %s.\n", jobid);
|
|
|
- failed = 1;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- // Set 2770 on the job-work directory
|
|
|
- if (stat(job_work_dir, &filestat) != 0) {
|
|
|
- if (errno == ENOENT) {
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE,
|
|
|
- "job_work_dir %s doesn't exist. Not doing anything.\n",
|
|
|
- job_work_dir);
|
|
|
-#endif
|
|
|
- free(job_work_dir);
|
|
|
- } else {
|
|
|
- // stat failed because of something else!
|
|
|
- fprintf(LOGFILE, "Failed to stat the job_work_dir %s\n",
|
|
|
- job_work_dir);
|
|
|
- failed = 1;
|
|
|
- free(job_work_dir);
|
|
|
- free(job_dir);
|
|
|
- break;
|
|
|
- }
|
|
|
- } else if (change_mode(job_work_dir, S_ISGID | S_IRWXU | S_IRWXG) != 0) {
|
|
|
- fprintf(LOGFILE,
|
|
|
- "couldn't change the permissions of job_work_dir %s\n",
|
|
|
- job_work_dir);
|
|
|
- failed = 1;
|
|
|
- free(job_work_dir);
|
|
|
- free(job_dir);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- local_dir_ptr++;
|
|
|
- free(job_dir);
|
|
|
- }
|
|
|
- free(local_dir);
|
|
|
- free(full_local_dir_str);
|
|
|
- int exit_code = 0;
|
|
|
- if (failed) {
|
|
|
- exit_code = INITIALIZE_JOB_FAILED;
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
-
|
|
|
- char *log_dir = (char *) get_value(TT_LOG_DIR_KEY);
|
|
|
- if (log_dir == NULL) {
|
|
|
- fprintf(LOGFILE, "Log directory is not configured.\n");
|
|
|
- exit_code = INVALID_TT_LOG_DIR;
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
-
|
|
|
- if (prepare_job_logs(log_dir, jobid, permissions) != 0) {
|
|
|
- fprintf(LOGFILE, "Couldn't prepare job logs directory %s for %s.\n",
|
|
|
- log_dir, jobid);
|
|
|
- exit_code = PREPARE_JOB_LOGS_FAILED;
|
|
|
- }
|
|
|
-
|
|
|
- cleanup:
|
|
|
- // free configurations
|
|
|
- cleanup();
|
|
|
- if (log_dir != NULL) {
|
|
|
- free(log_dir);
|
|
|
- }
|
|
|
- return exit_code;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Function to initialize the distributed cache file for a user.
|
|
|
- * It does the following:
|
|
|
- * * sudo chown user:mapred -R taskTracker/$user/distcache/<randomdir>
|
|
|
- * * if user is not $tt_user,
|
|
|
- * * sudo chmod 2570 -R taskTracker/$user/distcache/<randomdir>
|
|
|
- * * else // user is tt_user
|
|
|
- * * sudo chmod 2770 -R taskTracker/$user/distcache/<randomdir>
|
|
|
- * This is done once per localization. Tasks reusing JVMs just create
|
|
|
- * symbolic links themselves and so there isn't anything specific to do in
|
|
|
- * that case.
|
|
|
- */
|
|
|
-int initialize_distributed_cache_file(const char *tt_root,
|
|
|
- const char *unique_string, const char *user) {
|
|
|
- if (tt_root == NULL) {
|
|
|
- fprintf(LOGFILE, "tt_root passed is null.\n");
|
|
|
- return INVALID_ARGUMENT_NUMBER;
|
|
|
- }
|
|
|
- if (unique_string == NULL) {
|
|
|
- fprintf(LOGFILE, "unique_string passed is null.\n");
|
|
|
- return INVALID_ARGUMENT_NUMBER;
|
|
|
- }
|
|
|
-
|
|
|
- if (user == NULL) {
|
|
|
- fprintf(LOGFILE, "user passed is null.\n");
|
|
|
- return INVALID_ARGUMENT_NUMBER;
|
|
|
- }
|
|
|
-
|
|
|
- if (get_user_details(user) < 0) {
|
|
|
- fprintf(LOGFILE, "Couldn't get the user details of %s", user);
|
|
|
- return INVALID_USER_NAME;
|
|
|
- }
|
|
|
- //Check tt_root
|
|
|
- if (check_tt_root(tt_root) < 0) {
|
|
|
- fprintf(LOGFILE, "invalid tt root passed %s\n", tt_root);
|
|
|
- cleanup();
|
|
|
- return INVALID_TT_ROOT;
|
|
|
- }
|
|
|
-
|
|
|
- // set permission on the unique directory
|
|
|
- char *localized_unique_dir = get_distributed_cache_directory(tt_root, user,
|
|
|
- unique_string);
|
|
|
- if (localized_unique_dir == NULL) {
|
|
|
- fprintf(LOGFILE, "Couldn't get unique distcache directory for %s.\n", user);
|
|
|
- cleanup();
|
|
|
- return INITIALIZE_DISTCACHEFILE_FAILED;
|
|
|
- }
|
|
|
-
|
|
|
- gid_t binary_gid = getegid(); // the group permissions of the binary.
|
|
|
-
|
|
|
- int is_tt_user = (user_detail->pw_uid == getuid());
|
|
|
-
|
|
|
- // for tt_user, set 770 permissions; for any other user, set 570
|
|
|
- mode_t permissions = is_tt_user ? (S_IRWXU | S_IRWXG)
|
|
|
- : (S_IRUSR | S_IXUSR | S_IRWXG);
|
|
|
- int failed = 0;
|
|
|
- struct stat filestat;
|
|
|
- if (stat(localized_unique_dir, &filestat) != 0) {
|
|
|
- // stat on distcache failed because of something
|
|
|
- fprintf(LOGFILE, "Failed to stat the localized_unique_dir %s\n",
|
|
|
- localized_unique_dir);
|
|
|
- failed = INITIALIZE_DISTCACHEFILE_FAILED;
|
|
|
- } else if (secure_path(localized_unique_dir, user_detail->pw_uid,
|
|
|
- binary_gid, permissions, S_ISGID | permissions, 1) != 0) {
|
|
|
- // No setgid on files and setgid on dirs,
|
|
|
- // 770 for tt_user and 570 for any other user
|
|
|
- fprintf(LOGFILE, "Failed to secure the localized_unique_dir %s\n",
|
|
|
- localized_unique_dir);
|
|
|
- failed = INITIALIZE_DISTCACHEFILE_FAILED;
|
|
|
- }
|
|
|
- free(localized_unique_dir);
|
|
|
- cleanup();
|
|
|
- return failed;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Function used to initialize task. Prepares attempt_dir, jars_dir and
|
|
|
- * log_dir to be accessible by the child
|
|
|
- */
|
|
|
-int initialize_task(const char *jobid, const char *taskid, const char *user) {
|
|
|
- int exit_code = 0;
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE, "job-id passed to initialize_task : %s.\n", jobid);
|
|
|
- fprintf(LOGFILE, "task-d passed to initialize_task : %s.\n", taskid);
|
|
|
-#endif
|
|
|
-
|
|
|
- if (prepare_attempt_directories(jobid, taskid, user) != 0) {
|
|
|
- fprintf(LOGFILE,
|
|
|
- "Couldn't prepare the attempt directories for %s of user %s.\n",
|
|
|
- taskid, user);
|
|
|
- exit_code = PREPARE_ATTEMPT_DIRECTORIES_FAILED;
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
-
|
|
|
- char *log_dir = (char *) get_value(TT_LOG_DIR_KEY);
|
|
|
- if (log_dir == NULL) {
|
|
|
- fprintf(LOGFILE, "Log directory is not configured.\n");
|
|
|
- exit_code = INVALID_TT_LOG_DIR;
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
-
|
|
|
- if (prepare_task_logs(log_dir, jobid, taskid) != 0) {
|
|
|
- fprintf(LOGFILE, "Couldn't prepare task logs directory %s for %s.\n",
|
|
|
- log_dir, taskid);
|
|
|
- exit_code = PREPARE_TASK_LOGS_FAILED;
|
|
|
- }
|
|
|
-
|
|
|
- cleanup:
|
|
|
- // free configurations
|
|
|
- cleanup();
|
|
|
- if (log_dir != NULL) {
|
|
|
- free(log_dir);
|
|
|
- }
|
|
|
- return exit_code;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Function used to launch a task as the provided user.
|
|
|
- */
|
|
|
-int run_task_as_user(const char * user, const char *jobid, const char *taskid,
|
|
|
- const char *tt_root) {
|
|
|
- return run_process_as_user(user, jobid, taskid, tt_root, LAUNCH_TASK_JVM);
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Function that is used as a helper to launch task JVMs and debug scripts.
|
|
|
- * Not meant for launching any other process. It does the following :
|
|
|
- * 1) Checks if the tt_root passed is found in mapreduce.cluster.local.dir
|
|
|
- * 2) Prepares attempt_dir and log_dir to be accessible by the task JVMs
|
|
|
- * 3) Uses get_task_launcher_file to fetch the task script file path
|
|
|
- * 4) Does an execlp on the same in order to replace the current image with
|
|
|
- * task image.
|
|
|
- */
|
|
|
-int run_process_as_user(const char * user, const char * jobid,
|
|
|
-const char *taskid, const char *tt_root, int command) {
|
|
|
- if (command != LAUNCH_TASK_JVM && command != RUN_DEBUG_SCRIPT) {
|
|
|
- return INVALID_COMMAND_PROVIDED;
|
|
|
- }
|
|
|
- if (jobid == NULL || taskid == NULL || tt_root == NULL) {
|
|
|
- return INVALID_ARGUMENT_NUMBER;
|
|
|
- }
|
|
|
-
|
|
|
- if (command == LAUNCH_TASK_JVM) {
|
|
|
- fprintf(LOGFILE, "run_process_as_user launching a JVM for task :%s.\n", taskid);
|
|
|
- } else if (command == RUN_DEBUG_SCRIPT) {
|
|
|
- fprintf(LOGFILE, "run_process_as_user launching a debug script for task :%s.\n", taskid);
|
|
|
- }
|
|
|
-
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE, "Job-id passed to run_process_as_user : %s.\n", jobid);
|
|
|
- fprintf(LOGFILE, "task-d passed to run_process_as_user : %s.\n", taskid);
|
|
|
- fprintf(LOGFILE, "tt_root passed to run_process_as_user : %s.\n", tt_root);
|
|
|
-#endif
|
|
|
-
|
|
|
- //Check tt_root before switching the user, as reading configuration
|
|
|
- //file requires privileged access.
|
|
|
- if (check_tt_root(tt_root) < 0) {
|
|
|
- fprintf(LOGFILE, "invalid tt root passed %s\n", tt_root);
|
|
|
- cleanup();
|
|
|
- return INVALID_TT_ROOT;
|
|
|
- }
|
|
|
-
|
|
|
- int exit_code = 0;
|
|
|
- char *job_dir = NULL, *task_script_path = NULL;
|
|
|
-
|
|
|
- if (command == LAUNCH_TASK_JVM &&
|
|
|
- (exit_code = initialize_task(jobid, taskid, user)) != 0) {
|
|
|
- fprintf(LOGFILE, "Couldn't initialise the task %s of user %s.\n", taskid,
|
|
|
- user);
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
-
|
|
|
- job_dir = get_job_directory(tt_root, user, jobid);
|
|
|
- if (job_dir == NULL) {
|
|
|
- fprintf(LOGFILE, "Couldn't obtain job_dir for %s in %s.\n", jobid, tt_root);
|
|
|
- exit_code = OUT_OF_MEMORY;
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
-
|
|
|
- task_script_path = get_task_launcher_file(job_dir, taskid);
|
|
|
- if (task_script_path == NULL) {
|
|
|
- fprintf(LOGFILE, "Couldn't obtain task_script_path in %s.\n", job_dir);
|
|
|
- exit_code = OUT_OF_MEMORY;
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
-
|
|
|
- errno = 0;
|
|
|
- exit_code = check_path_for_relative_components(task_script_path);
|
|
|
- if(exit_code != 0) {
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
-
|
|
|
- //change the user
|
|
|
- fcloseall();
|
|
|
- free(job_dir);
|
|
|
- umask(0007);
|
|
|
- if (change_user(user) != 0) {
|
|
|
- exit_code = SETUID_OPER_FAILED;
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
-
|
|
|
- errno = 0;
|
|
|
- cleanup();
|
|
|
- execlp(task_script_path, task_script_path, NULL);
|
|
|
- if (errno != 0) {
|
|
|
- free(task_script_path);
|
|
|
- if (command == LAUNCH_TASK_JVM) {
|
|
|
- fprintf(LOGFILE, "Couldn't execute the task jvm file: %s", strerror(errno));
|
|
|
- exit_code = UNABLE_TO_EXECUTE_TASK_SCRIPT;
|
|
|
- } else if (command == RUN_DEBUG_SCRIPT) {
|
|
|
- fprintf(LOGFILE, "Couldn't execute the task debug script file: %s", strerror(errno));
|
|
|
- exit_code = UNABLE_TO_EXECUTE_DEBUG_SCRIPT;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return exit_code;
|
|
|
-
|
|
|
-cleanup:
|
|
|
- if (job_dir != NULL) {
|
|
|
- free(job_dir);
|
|
|
- }
|
|
|
- if (task_script_path != NULL) {
|
|
|
- free(task_script_path);
|
|
|
- }
|
|
|
- // free configurations
|
|
|
- cleanup();
|
|
|
- return exit_code;
|
|
|
-}
|
|
|
-/*
|
|
|
- * Function used to launch a debug script as the provided user.
|
|
|
- */
|
|
|
-int run_debug_script_as_user(const char * user, const char *jobid, const char *taskid,
|
|
|
- const char *tt_root) {
|
|
|
- return run_process_as_user(user, jobid, taskid, tt_root, RUN_DEBUG_SCRIPT);
|
|
|
-}
|
|
|
-/**
|
|
|
- * Function used to terminate/kill a task launched by the user,
|
|
|
- * or dump the process' stack (by sending SIGQUIT).
|
|
|
- * The function sends appropriate signal to the process group
|
|
|
- * specified by the task_pid.
|
|
|
- */
|
|
|
-int kill_user_task(const char *user, const char *task_pid, int sig) {
|
|
|
- int pid = 0;
|
|
|
-
|
|
|
- if(task_pid == NULL) {
|
|
|
- return INVALID_ARGUMENT_NUMBER;
|
|
|
- }
|
|
|
-
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE, "user passed to kill_user_task : %s.\n", user);
|
|
|
- fprintf(LOGFILE, "task-pid passed to kill_user_task : %s.\n", task_pid);
|
|
|
- fprintf(LOGFILE, "signal passed to kill_user_task : %d.\n", sig);
|
|
|
-#endif
|
|
|
-
|
|
|
- pid = atoi(task_pid);
|
|
|
-
|
|
|
- if(pid <= 0) {
|
|
|
- return INVALID_TASK_PID;
|
|
|
- }
|
|
|
-
|
|
|
- fcloseall();
|
|
|
- if (change_user(user) != 0) {
|
|
|
- cleanup();
|
|
|
- return SETUID_OPER_FAILED;
|
|
|
- }
|
|
|
-
|
|
|
- //Don't continue if the process-group is not alive anymore.
|
|
|
- if(kill(-pid,0) < 0) {
|
|
|
- errno = 0;
|
|
|
- cleanup();
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- if (kill(-pid, sig) < 0) {
|
|
|
- if(errno != ESRCH) {
|
|
|
- fprintf(LOGFILE, "Error is %s\n", strerror(errno));
|
|
|
- cleanup();
|
|
|
- return UNABLE_TO_KILL_TASK;
|
|
|
- }
|
|
|
- errno = 0;
|
|
|
- }
|
|
|
- cleanup();
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Enables the path for deletion by changing the owner, group and permissions
|
|
|
- * of the specified path and all the files/directories in the path recursively.
|
|
|
- * * sudo chown user:mapred -R full_path
|
|
|
- * * sudo chmod 2770 -R full_path
|
|
|
- * Before changing permissions, makes sure that the given path doesn't contain
|
|
|
- * any relative components.
|
|
|
- * tt_root : is the base path(i.e. mapred-local-dir) sent to task-controller
|
|
|
- * full_path : is either jobLocalDir, taskDir OR taskWorkDir that is to be
|
|
|
- * deleted
|
|
|
- */
|
|
|
-static int enable_path_for_cleanup(const char *tt_root, const char *user,
|
|
|
- char *full_path) {
|
|
|
- int exit_code = 0;
|
|
|
- gid_t tasktracker_gid = getegid(); // the group permissions of the binary.
|
|
|
-
|
|
|
- if (check_tt_root(tt_root) < 0) {
|
|
|
- fprintf(LOGFILE, "invalid tt root passed %s\n", tt_root);
|
|
|
- cleanup();
|
|
|
- return INVALID_TT_ROOT;
|
|
|
- }
|
|
|
-
|
|
|
- if (full_path == NULL) {
|
|
|
- fprintf(LOGFILE,
|
|
|
- "Could not build the full path. Not deleting the dir %s\n",
|
|
|
- full_path);
|
|
|
- exit_code = UNABLE_TO_BUILD_PATH; // may be malloc failed
|
|
|
- }
|
|
|
- // Make sure that the path given is not having any relative components
|
|
|
- else if ((exit_code = check_path_for_relative_components(full_path)) != 0) {
|
|
|
- fprintf(LOGFILE,
|
|
|
- "Not changing permissions. Path may contain relative components.\n",
|
|
|
- full_path);
|
|
|
- }
|
|
|
- else if (get_user_details(user) < 0) {
|
|
|
- fprintf(LOGFILE, "Couldn't get the user details of %s.\n", user);
|
|
|
- exit_code = INVALID_USER_NAME;
|
|
|
- }
|
|
|
- else if (exit_code = secure_path(full_path, user_detail->pw_uid,
|
|
|
- tasktracker_gid,
|
|
|
- S_IRWXU | S_IRWXG, S_ISGID | S_IRWXU | S_IRWXG, 0) != 0) {
|
|
|
- // No setgid on files and setgid on dirs, 770.
|
|
|
- // set 770 permissions for user, TTgroup for all files/directories in
|
|
|
- // 'full_path' recursively sothat deletion of path by TaskTracker succeeds.
|
|
|
-
|
|
|
- fprintf(LOGFILE, "Failed to set permissions for %s\n", full_path);
|
|
|
- }
|
|
|
-
|
|
|
- if (full_path != NULL) {
|
|
|
- free(full_path);
|
|
|
- }
|
|
|
- // free configurations
|
|
|
- cleanup();
|
|
|
- return exit_code;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Enables the task work-dir/local-dir path for deletion.
|
|
|
- * tt_root : is the base path(i.e. mapred-local-dir) sent to task-controller
|
|
|
- * dir_to_be_deleted : is either taskDir OR taskWorkDir that is to be deleted
|
|
|
- */
|
|
|
-int enable_task_for_cleanup(const char *tt_root, const char *user,
|
|
|
- const char *jobid, const char *dir_to_be_deleted) {
|
|
|
- char *full_path = get_task_dir_path(tt_root, user, jobid, dir_to_be_deleted);
|
|
|
- return enable_path_for_cleanup(tt_root, user, full_path);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Enables the jobLocalDir for deletion.
|
|
|
- * tt_root : is the base path(i.e. mapred-local-dir) sent to task-controller
|
|
|
- * user : owner of the job
|
|
|
- * jobid : id of the job for which the cleanup is needed.
|
|
|
- */
|
|
|
-int enable_job_for_cleanup(const char *tt_root, const char *user,
|
|
|
- const char *jobid) {
|
|
|
- char *full_path = get_job_directory(tt_root, user, jobid);
|
|
|
- return enable_path_for_cleanup(tt_root, user, full_path);
|
|
|
-}
|