|
@@ -23,9 +23,6 @@ struct passwd *user_detail = NULL;
|
|
|
//LOGFILE
|
|
|
FILE *LOGFILE;
|
|
|
|
|
|
-//hadoop temp dir root which is configured in secure configuration
|
|
|
-const char *mapred_local_dir;
|
|
|
-
|
|
|
//placeholder for global cleanup operations
|
|
|
void cleanup() {
|
|
|
free_configurations();
|
|
@@ -38,94 +35,67 @@ int change_user(const char * user) {
|
|
|
}
|
|
|
|
|
|
if(initgroups(user_detail->pw_name, user_detail->pw_gid) != 0) {
|
|
|
- cleanup();
|
|
|
- return SETUID_OPER_FAILED;
|
|
|
+ cleanup();
|
|
|
+ return SETUID_OPER_FAILED;
|
|
|
}
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE,"change_user : setting user as %s ", user_detail->pw_name);
|
|
|
-#endif
|
|
|
+
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
-//Function to set the hadoop.temp.dir key from configuration.
|
|
|
-//would return -1 if the configuration is not proper.
|
|
|
-
|
|
|
-int get_mapred_local_dir() {
|
|
|
-
|
|
|
- if (mapred_local_dir == NULL) {
|
|
|
- mapred_local_dir = get_value(TT_SYS_DIR_KEY);
|
|
|
- }
|
|
|
-
|
|
|
- //after the call it should not be null
|
|
|
- if (mapred_local_dir == NULL) {
|
|
|
- return -1;
|
|
|
- } else {
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
// function to check if the passed tt_root is present in hadoop.tmp.dir
|
|
|
int check_tt_root(const char *tt_root) {
|
|
|
- char *token;
|
|
|
+ char ** mapred_local_dir;
|
|
|
int found = -1;
|
|
|
|
|
|
if (tt_root == NULL) {
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- if (mapred_local_dir == NULL) {
|
|
|
- if (get_mapred_local_dir() < 0) {
|
|
|
- fprintf(LOGFILE, "invalid hadoop config\n");
|
|
|
- return -1;
|
|
|
- }
|
|
|
- }
|
|
|
+ mapred_local_dir = (char **)get_values(TT_SYS_DIR_KEY);
|
|
|
|
|
|
- token = strtok((char *) mapred_local_dir, ",");
|
|
|
- if (token == NULL && mapred_local_dir != NULL) {
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE,"Single hadoop.tmp.dir configured");
|
|
|
-#endif
|
|
|
- token = (char *)mapred_local_dir;
|
|
|
+ if (mapred_local_dir == NULL) {
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
- while (1) {
|
|
|
- if (strcmp(tt_root, token) == 0) {
|
|
|
+ while(*mapred_local_dir != NULL) {
|
|
|
+ if(strcmp(*mapred_local_dir,tt_root) == 0) {
|
|
|
found = 0;
|
|
|
break;
|
|
|
}
|
|
|
- token = strtok(NULL, ",");
|
|
|
- if (token == NULL) {
|
|
|
- break;
|
|
|
- }
|
|
|
}
|
|
|
-
|
|
|
+ free(mapred_local_dir);
|
|
|
return found;
|
|
|
-
|
|
|
}
|
|
|
+
|
|
|
/**
|
|
|
* Function to check if the constructed path and absolute
|
|
|
* path resolve to one and same.
|
|
@@ -157,39 +127,6 @@ int check_owner(uid_t uid, char *path) {
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
-/*
|
|
|
- *Function which would return .pid file path which is used while running
|
|
|
- * and killing of the tasks by the user.
|
|
|
- *
|
|
|
- * check TT_SYS_DIR for pattern
|
|
|
- */
|
|
|
-void get_pid_path(const char * jobid, const char * taskid, const char *tt_root,
|
|
|
- char ** pid_path) {
|
|
|
-
|
|
|
- int str_len = strlen(TT_SYS_DIR) + strlen(jobid) + strlen(taskid) + strlen(
|
|
|
- tt_root);
|
|
|
- *pid_path = NULL;
|
|
|
-
|
|
|
- if (mapred_local_dir == NULL) {
|
|
|
- if (get_mapred_local_dir() < 0) {
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- *pid_path = (char *) malloc(sizeof(char) * (str_len + 1));
|
|
|
-
|
|
|
- if (*pid_path == NULL) {
|
|
|
- fprintf(LOGFILE, "unable to allocate memory for pid path\n");
|
|
|
- return;
|
|
|
- }
|
|
|
- memset(*pid_path,'\0',str_len+1);
|
|
|
- snprintf(*pid_path, str_len, TT_SYS_DIR, tt_root, jobid, taskid);
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE, "get_pid_path : pid path = %s\n", *pid_path);
|
|
|
- fflush(LOGFILE);
|
|
|
-#endif
|
|
|
-
|
|
|
-}
|
|
|
|
|
|
/*
|
|
|
* function to provide path to the task file which is created by the tt
|
|
@@ -198,19 +135,19 @@ void get_pid_path(const char * jobid, const char * taskid, const char *tt_root,
|
|
|
*/
|
|
|
void get_task_file_path(const char * jobid, const char * taskid,
|
|
|
const char * tt_root, char **task_script_path) {
|
|
|
+ const char ** mapred_local_dir = get_values(TT_SYS_DIR_KEY);
|
|
|
*task_script_path = NULL;
|
|
|
int str_len = strlen(TT_LOCAL_TASK_SCRIPT_PATTERN) + strlen(jobid) + (strlen(
|
|
|
taskid)) + strlen(tt_root);
|
|
|
|
|
|
if (mapred_local_dir == NULL) {
|
|
|
- if (get_mapred_local_dir() < 0) {
|
|
|
- return;
|
|
|
- }
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
*task_script_path = (char *) malloc(sizeof(char) * (str_len + 1));
|
|
|
if (*task_script_path == NULL) {
|
|
|
fprintf(LOGFILE, "Unable to allocate memory for task_script_path \n");
|
|
|
+ free(mapred_local_dir);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -221,7 +158,7 @@ void get_task_file_path(const char * jobid, const char * taskid,
|
|
|
fprintf(LOGFILE, "get_task_file_path : task script path = %s\n", *task_script_path);
|
|
|
fflush(LOGFILE);
|
|
|
#endif
|
|
|
-
|
|
|
+ free(mapred_local_dir);
|
|
|
}
|
|
|
|
|
|
//end of private functions
|
|
@@ -247,142 +184,55 @@ int get_user_details(const char *user) {
|
|
|
*Function used to launch a task as the provided user.
|
|
|
* First the function checks if the tt_root passed is found in
|
|
|
* hadoop.temp.dir
|
|
|
- *
|
|
|
- *Then gets the path to which the task has to write its pid from
|
|
|
- *get_pid_path.
|
|
|
- *
|
|
|
- * THen writes its pid into the file.
|
|
|
- *
|
|
|
- * Then changes the permission of the pid file into 600
|
|
|
- *
|
|
|
- * Then uses get_task_file_path to fetch the task script file path.
|
|
|
- *
|
|
|
+ * Uses get_task_file_path to fetch the task script file path.
|
|
|
* Does an execlp on the same in order to replace the current image with
|
|
|
* task image.
|
|
|
- *
|
|
|
*/
|
|
|
|
|
|
int run_task_as_user(const char * user, const char *jobid, const char *taskid,
|
|
|
const char *tt_root) {
|
|
|
char *task_script_path = NULL;
|
|
|
- char *pid_path = NULL;
|
|
|
- char *task_script = NULL;
|
|
|
- FILE *file_handle = NULL;
|
|
|
int exit_code = 0;
|
|
|
uid_t uid = getuid();
|
|
|
|
|
|
+ if(jobid == NULL || taskid == NULL) {
|
|
|
+ return INVALID_ARGUMENT_NUMBER;
|
|
|
+ }
|
|
|
+
|
|
|
#ifdef DEBUG
|
|
|
fprintf(LOGFILE,"run_task_as_user : Job id : %s \n", jobid);
|
|
|
fprintf(LOGFILE,"run_task_as_user : task id : %s \n", taskid);
|
|
|
fprintf(LOGFILE,"run_task_as_user : tt_root : %s \n", tt_root);
|
|
|
fflush(LOGFILE);
|
|
|
#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;
|
|
|
}
|
|
|
|
|
|
- get_pid_path(jobid, taskid, tt_root, &pid_path);
|
|
|
- if (pid_path == NULL) {
|
|
|
- fprintf(LOGFILE, "Invalid task-pid path provided");
|
|
|
- cleanup();
|
|
|
- return INVALID_PID_PATH;
|
|
|
- }
|
|
|
- errno = 0;
|
|
|
- file_handle = fopen(pid_path, "w");
|
|
|
-
|
|
|
- if (file_handle == NULL) {
|
|
|
- fprintf(LOGFILE, "Error opening task-pid file %s :%s\n", pid_path,
|
|
|
- strerror(errno));
|
|
|
- exit_code = UNABLE_TO_OPEN_PID_FILE_WRITE_MODE;
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
-
|
|
|
- errno = 0;
|
|
|
- if (fprintf(file_handle, "%d\n", getpid()) < 0) {
|
|
|
- fprintf(LOGFILE, "Error writing to task-pid file :%s\n", strerror(errno));
|
|
|
- exit_code = UNABLE_TO_WRITE_TO_PID_FILE;
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
-
|
|
|
- fflush(file_handle);
|
|
|
- fclose(file_handle);
|
|
|
- file_handle = NULL;
|
|
|
- //change the permissions of the file
|
|
|
- errno = 0;
|
|
|
- //setting permission to 600
|
|
|
- if (chmod(pid_path, S_IREAD | S_IWRITE) < 0) {
|
|
|
- fprintf(LOGFILE, "Error changing permission of %s task-pid file : %s",
|
|
|
- pid_path, strerror(errno));
|
|
|
- errno = 0;
|
|
|
- if (remove(pid_path) < 0) {
|
|
|
- fprintf(LOGFILE, "Error deleting %s task-pid file : %s", pid_path,
|
|
|
- strerror(errno));
|
|
|
- exit_code = UNABLE_TO_CHANGE_PERMISSION_AND_DELETE_PID_FILE;
|
|
|
- } else {
|
|
|
- exit_code = UNABLE_TO_CHANGE_PERMISSION_OF_PID_FILE;
|
|
|
- }
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
-
|
|
|
- if(chown(pid_path, uid, getgid()) < 0) {
|
|
|
- fprintf(LOGFILE, "Error changing ownershipt of %s task-pid file : %s\n",
|
|
|
- pid_path, strerror(errno));
|
|
|
- errno = 0;
|
|
|
- if (remove(pid_path) < 0) {
|
|
|
- fprintf(LOGFILE, "Error deleting %s task-pid file : %s", pid_path,
|
|
|
- strerror(errno));
|
|
|
- exit_code = UNABLE_TO_CHANGE_OWNERSHIP_AND_DELETE_PID_FILE;
|
|
|
- } else {
|
|
|
- exit_code = UNABLE_TO_CHANGE_OWNERSHIP_OF_PID_FILE;
|
|
|
- }
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
- //while checking path make sure the target of the path exists otherwise
|
|
|
- //check_paths would fail always. So write out .pid file then check if
|
|
|
- //it correctly resolves. If not delete the pid file and bail out.
|
|
|
- errno = 0;
|
|
|
- exit_code = check_path(pid_path);
|
|
|
- if(exit_code != 0) {
|
|
|
- remove(pid_path);
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
-
|
|
|
- //free pid_t path which is allocated
|
|
|
- free(pid_path);
|
|
|
- pid_path = NULL;
|
|
|
-
|
|
|
//change the user
|
|
|
- fcloseall();
|
|
|
fclose(LOGFILE);
|
|
|
+ fcloseall();
|
|
|
umask(0);
|
|
|
if (change_user(user) != 0) {
|
|
|
- exit_code = SETUID_OPER_FAILED;
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
-
|
|
|
- //change set the launching process as the session leader.
|
|
|
- if(setsid() < 0) {
|
|
|
- exit_code = SETSID_FAILED;
|
|
|
- goto cleanup;
|
|
|
+ cleanup();
|
|
|
+ return SETUID_OPER_FAILED;
|
|
|
}
|
|
|
|
|
|
get_task_file_path(jobid, taskid, tt_root, &task_script_path);
|
|
|
-
|
|
|
if (task_script_path == NULL) {
|
|
|
- exit_code = INVALID_TASK_SCRIPT_PATH;
|
|
|
- goto cleanup;
|
|
|
+ cleanup();
|
|
|
+ return INVALID_TASK_SCRIPT_PATH;
|
|
|
}
|
|
|
- //resolve paths.
|
|
|
errno = 0;
|
|
|
exit_code = check_path(task_script_path);
|
|
|
- if(exit_code !=0) {
|
|
|
+ if(exit_code != 0) {
|
|
|
goto cleanup;
|
|
|
}
|
|
|
errno = 0;
|
|
|
- //get stat of the task file.
|
|
|
exit_code = check_owner(uid, task_script_path);
|
|
|
if(exit_code != 0) {
|
|
|
goto cleanup;
|
|
@@ -398,127 +248,53 @@ int run_task_as_user(const char * user, const char *jobid, const char *taskid,
|
|
|
return exit_code;
|
|
|
|
|
|
cleanup:
|
|
|
- if (pid_path != NULL) {
|
|
|
- free(pid_path);
|
|
|
- }
|
|
|
if (task_script_path != NULL) {
|
|
|
free(task_script_path);
|
|
|
}
|
|
|
- if (file_handle != NULL) {
|
|
|
- fclose(file_handle);
|
|
|
- }
|
|
|
// free configurations
|
|
|
cleanup();
|
|
|
return exit_code;
|
|
|
}
|
|
|
+
|
|
|
/**
|
|
|
- * Function used to terminate a task launched by the user.
|
|
|
- *
|
|
|
- * The function first checks if the passed tt-root is found in
|
|
|
- * configured hadoop.temp.dir (which is a list of tt_roots).
|
|
|
- *
|
|
|
- * Then gets the task-pid path using function get_pid_path.
|
|
|
- *
|
|
|
- * reads the task-pid from the file which is mentioned by get_pid_path
|
|
|
- *
|
|
|
- * kills the task by sending SIGTERM to that particular process.
|
|
|
- *
|
|
|
+ * Function used to terminate/kill a task launched by the user.
|
|
|
+ * The function sends appropriate signal to the process group
|
|
|
+ * specified by the task_pid.
|
|
|
*/
|
|
|
|
|
|
-int kill_user_task(const char *user, const char *jobid, const char *taskid,
|
|
|
- const char *tt_root) {
|
|
|
+int kill_user_task(const char *user, const char *task_pid, int sig) {
|
|
|
int pid = 0;
|
|
|
- int i = 0;
|
|
|
- char *pid_path = NULL;
|
|
|
- FILE *file_handle = NULL;
|
|
|
- const char *sleep_interval_char;
|
|
|
- int sleep_interval = 0;
|
|
|
- uid_t uid = getuid();
|
|
|
- int exit_code = 0;
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE,"kill_user_task : Job id : %s \n", jobid);
|
|
|
- fprintf(LOGFILE,"kill_user_task : task id : %s \n", taskid);
|
|
|
- fprintf(LOGFILE,"kill_user_task : tt_root : %s \n", tt_root);
|
|
|
- fflush(LOGFILE);
|
|
|
-#endif
|
|
|
- if (check_tt_root(tt_root) < 0) {
|
|
|
- fprintf(LOGFILE, "invalid tt root specified");
|
|
|
- cleanup();
|
|
|
- return INVALID_TT_ROOT;
|
|
|
- }
|
|
|
- get_pid_path(jobid, taskid, tt_root, &pid_path);
|
|
|
- if (pid_path == NULL) {
|
|
|
- cleanup();
|
|
|
- return INVALID_PID_PATH;
|
|
|
- }
|
|
|
- errno = 0;
|
|
|
- exit_code = check_path(pid_path);
|
|
|
- if(exit_code != 0) {
|
|
|
- free(pid_path);
|
|
|
- cleanup();
|
|
|
- return exit_code;
|
|
|
- }
|
|
|
- errno = 0;
|
|
|
- exit_code = check_owner(uid, pid_path);
|
|
|
|
|
|
- if(exit_code != 0) {
|
|
|
- free(pid_path);
|
|
|
- cleanup();
|
|
|
- return exit_code;
|
|
|
+ if(task_pid == NULL) {
|
|
|
+ return INVALID_ARGUMENT_NUMBER;
|
|
|
}
|
|
|
+ pid = atoi(task_pid);
|
|
|
|
|
|
-#ifdef DEBUG
|
|
|
- fprintf(LOGFILE,"kill_user_task : task-pid path :%s \n",pid_path);
|
|
|
- fflush(LOGFILE);
|
|
|
-#endif
|
|
|
- errno = 0;
|
|
|
- file_handle = fopen(pid_path, "r");
|
|
|
- if (file_handle == NULL) {
|
|
|
- fprintf(LOGFILE, "unable to open task-pid file :%s \n", pid_path);
|
|
|
- free(pid_path);
|
|
|
- cleanup();
|
|
|
- return UNABLE_TO_OPEN_PID_FILE_READ_MODE;
|
|
|
+ if(pid <= 0) {
|
|
|
+ return INVALID_TASK_PID;
|
|
|
}
|
|
|
- fscanf(file_handle, "%d", &pid);
|
|
|
- fclose(file_handle);
|
|
|
fclose(LOGFILE);
|
|
|
- free(pid_path);
|
|
|
- if (pid == 0) {
|
|
|
- cleanup();
|
|
|
- return UNABLE_TO_READ_PID;
|
|
|
- }
|
|
|
+ fcloseall();
|
|
|
if (change_user(user) != 0) {
|
|
|
cleanup();
|
|
|
return SETUID_OPER_FAILED;
|
|
|
}
|
|
|
- //kill the entire session.
|
|
|
- if (kill(-pid, SIGTERM) < 0) {
|
|
|
- fprintf(LOGFILE, "%s\n", strerror(errno));
|
|
|
- cleanup();
|
|
|
- return UNABLE_TO_KILL_TASK;
|
|
|
- }
|
|
|
- //get configured interval time.
|
|
|
- sleep_interval_char = get_value("mapred.tasktracker.tasks.sleeptime-before-sigkill");
|
|
|
- if(sleep_interval_char != NULL) {
|
|
|
- sleep_interval = atoi(sleep_interval_char);
|
|
|
- }
|
|
|
- if(sleep_interval == 0) {
|
|
|
- sleep_interval = 5;
|
|
|
+
|
|
|
+ //Don't continue if the process-group is not alive anymore.
|
|
|
+ if(kill(-pid,0) < 0) {
|
|
|
+ errno = 0;
|
|
|
+ return 0;
|
|
|
}
|
|
|
- //sleep for configured interval.
|
|
|
- sleep(sleep_interval);
|
|
|
- //check pid exists
|
|
|
- if(kill(-pid,0) == 0) {
|
|
|
- //if pid present then sigkill it
|
|
|
- if(kill(-pid, SIGKILL) <0) {
|
|
|
- //ignore no such pid present.
|
|
|
- if(errno != ESRCH) {
|
|
|
- //log error ,exit unclean
|
|
|
- cleanup();
|
|
|
- return UNABLE_TO_KILL_TASK;
|
|
|
- }
|
|
|
+
|
|
|
+ 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;
|
|
|
}
|
|
|
+
|