1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300 |
- /**
- * 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);
- }
|