main.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. #include "task-controller.h"
  19. void open_log_file(const char *log_file) {
  20. if (log_file == NULL) {
  21. LOGFILE = stdout;
  22. } else {
  23. LOGFILE = fopen(log_file, "a");
  24. if (LOGFILE == NULL) {
  25. fprintf(stdout, "Unable to open LOGFILE : %s \n", log_file);
  26. LOGFILE = stdout;
  27. }
  28. if (LOGFILE != stdout) {
  29. if (chmod(log_file, S_IREAD | S_IEXEC | S_IWRITE | S_IROTH | S_IWOTH
  30. | S_IRGRP | S_IWGRP) < 0) {
  31. fprintf(stdout, "Unable to change permission of the log file %s \n",
  32. log_file);
  33. fclose(LOGFILE);
  34. fprintf(stdout, "changing log file to stdout");
  35. LOGFILE = stdout;
  36. }
  37. }
  38. }
  39. }
  40. void display_usage(FILE *stream) {
  41. fprintf(stream,
  42. "Usage: task-controller [-l logfile] user command command-args\n");
  43. }
  44. /**
  45. * Check the permissions on taskcontroller to make sure that security is
  46. * promisable. For this, we need task-controller binary to
  47. * * be user-owned by root
  48. * * be group-owned by a configured special group.
  49. * * others do not have write or execute permissions
  50. * * be setuid
  51. */
  52. int check_taskcontroller_permissions(char *executable_file) {
  53. errno = 0;
  54. char * resolved_path = (char *) canonicalize_file_name(executable_file);
  55. if (resolved_path == NULL) {
  56. fprintf(LOGFILE,
  57. "Error resolving the canonical name for the executable : %s!",
  58. strerror(errno));
  59. return -1;
  60. }
  61. struct stat filestat;
  62. errno = 0;
  63. if (stat(resolved_path, &filestat) != 0) {
  64. fprintf(LOGFILE, "Could not stat the executable : %s!.\n", strerror(errno));
  65. return -1;
  66. }
  67. uid_t binary_euid = filestat.st_uid; // Binary's user owner
  68. gid_t binary_egid = filestat.st_gid; // Binary's group owner
  69. // Effective uid should be root
  70. if (binary_euid != 0) {
  71. fprintf(LOGFILE,
  72. "The task-controller binary should be user-owned by root.\n");
  73. return -1;
  74. }
  75. // Get the group entry for the special_group
  76. errno = 0;
  77. struct group *special_group_entry = getgrgid(binary_egid);
  78. if (special_group_entry == NULL) {
  79. fprintf(LOGFILE,
  80. "Unable to get information for effective group of the binary : %s\n",
  81. strerror(errno));
  82. return -1;
  83. }
  84. char * binary_group = special_group_entry->gr_name;
  85. // verify that the group name of the special group
  86. // is same as the one in configuration
  87. if (check_variable_against_config(TT_GROUP_KEY, binary_group) != 0) {
  88. fprintf(LOGFILE,
  89. "Group of the binary does not match with that in configuration\n");
  90. return -1;
  91. }
  92. // check others do not have write/execute permissions
  93. if ((filestat.st_mode & S_IWOTH) == S_IWOTH ||
  94. (filestat.st_mode & S_IXOTH) == S_IXOTH) {
  95. fprintf(LOGFILE,
  96. "The task-controller binary should not have write or execute for others.\n");
  97. return -1;
  98. }
  99. // Binary should be setuid executable
  100. if ((filestat.st_mode & S_ISUID) != S_ISUID) {
  101. fprintf(LOGFILE,
  102. "The task-controller binary should be set setuid.\n");
  103. return -1;
  104. }
  105. return 0;
  106. }
  107. int main(int argc, char **argv) {
  108. int command;
  109. int next_option = 0;
  110. const char * job_id = NULL;
  111. const char * task_id = NULL;
  112. const char * tt_root = NULL;
  113. const char *log_dir = NULL;
  114. const char * unique_string = NULL;
  115. int exit_code = 0;
  116. const char * task_pid = NULL;
  117. const char* const short_options = "l:";
  118. const struct option long_options[] = { { "log", 1, NULL, 'l' }, { NULL, 0,
  119. NULL, 0 } };
  120. const char* log_file = NULL;
  121. char * dir_to_be_deleted = NULL;
  122. int conf_dir_len = 0;
  123. char *executable_file = argv[0];
  124. #ifndef HADOOP_CONF_DIR
  125. conf_dir_len = (strlen(executable_file) - strlen(EXEC_PATTERN)) + 1;
  126. if (conf_dir_len < 1) {
  127. // We didn't get an absolute path to our executable_file; bail.
  128. printf("Cannot find configuration directory.\n");
  129. printf("This program must be run with its full absolute path.\n");
  130. return INVALID_CONF_DIR;
  131. } else {
  132. hadoop_conf_dir = (char *) malloc (sizeof(char) * conf_dir_len);
  133. strncpy(hadoop_conf_dir, executable_file,
  134. (strlen(executable_file) - strlen(EXEC_PATTERN)));
  135. hadoop_conf_dir[(strlen(executable_file) - strlen(EXEC_PATTERN))] = '\0';
  136. }
  137. #endif
  138. do {
  139. next_option = getopt_long(argc, argv, short_options, long_options, NULL);
  140. switch (next_option) {
  141. case 'l':
  142. log_file = optarg;
  143. default:
  144. break;
  145. }
  146. } while (next_option != -1);
  147. open_log_file(log_file);
  148. if (check_taskcontroller_permissions(executable_file) != 0) {
  149. fprintf(LOGFILE, "Invalid permissions on task-controller binary.\n");
  150. return INVALID_TASKCONTROLLER_PERMISSIONS;
  151. }
  152. //Minimum number of arguments required to run the task-controller
  153. //command-name user command tt-root
  154. if (argc < 3) {
  155. display_usage(stdout);
  156. return INVALID_ARGUMENT_NUMBER;
  157. }
  158. //checks done for user name
  159. //checks done if the user is root or not.
  160. if (argv[optind] == NULL) {
  161. fprintf(LOGFILE, "Invalid user name \n");
  162. return INVALID_USER_NAME;
  163. }
  164. if (get_user_details(argv[optind]) != 0) {
  165. return INVALID_USER_NAME;
  166. }
  167. //implicit conversion to int instead of __gid_t and __uid_t
  168. if (user_detail->pw_gid == 0 || user_detail->pw_uid == 0) {
  169. fprintf(LOGFILE, "Cannot run tasks as super user\n");
  170. return SUPER_USER_NOT_ALLOWED_TO_RUN_TASKS;
  171. }
  172. optind = optind + 1;
  173. command = atoi(argv[optind++]);
  174. fprintf(LOGFILE, "main : command provided %d\n",command);
  175. fprintf(LOGFILE, "main : user is %s\n", user_detail->pw_name);
  176. switch (command) {
  177. case INITIALIZE_USER:
  178. exit_code = initialize_user(user_detail->pw_name);
  179. break;
  180. case INITIALIZE_JOB:
  181. job_id = argv[optind++];
  182. exit_code = initialize_job(job_id, user_detail->pw_name);
  183. break;
  184. case INITIALIZE_DISTRIBUTEDCACHE_FILE:
  185. tt_root = argv[optind++];
  186. unique_string = argv[optind++];
  187. exit_code = initialize_distributed_cache_file(tt_root, unique_string,
  188. user_detail->pw_name);
  189. break;
  190. case LAUNCH_TASK_JVM:
  191. tt_root = argv[optind++];
  192. job_id = argv[optind++];
  193. task_id = argv[optind++];
  194. exit_code
  195. = run_task_as_user(user_detail->pw_name, job_id, task_id, tt_root);
  196. break;
  197. case INITIALIZE_TASK:
  198. job_id = argv[optind++];
  199. task_id = argv[optind++];
  200. exit_code = initialize_task(job_id, task_id, user_detail->pw_name);
  201. break;
  202. case TERMINATE_TASK_JVM:
  203. task_pid = argv[optind++];
  204. exit_code = kill_user_task(user_detail->pw_name, task_pid, SIGTERM);
  205. break;
  206. case KILL_TASK_JVM:
  207. task_pid = argv[optind++];
  208. exit_code = kill_user_task(user_detail->pw_name, task_pid, SIGKILL);
  209. break;
  210. case RUN_DEBUG_SCRIPT:
  211. tt_root = argv[optind++];
  212. job_id = argv[optind++];
  213. task_id = argv[optind++];
  214. exit_code
  215. = run_debug_script_as_user(user_detail->pw_name, job_id, task_id, tt_root);
  216. break;
  217. case SIGQUIT_TASK_JVM:
  218. task_pid = argv[optind++];
  219. exit_code = kill_user_task(user_detail->pw_name, task_pid, SIGQUIT);
  220. break;
  221. case ENABLE_TASK_FOR_CLEANUP:
  222. tt_root = argv[optind++];
  223. job_id = argv[optind++];
  224. dir_to_be_deleted = argv[optind++];
  225. exit_code = enable_task_for_cleanup(tt_root, user_detail->pw_name, job_id,
  226. dir_to_be_deleted);
  227. break;
  228. case ENABLE_JOB_FOR_CLEANUP:
  229. tt_root = argv[optind++];
  230. job_id = argv[optind++];
  231. exit_code = enable_job_for_cleanup(tt_root, user_detail->pw_name, job_id);
  232. break;
  233. default:
  234. exit_code = INVALID_COMMAND_PROVIDED;
  235. }
  236. fflush(LOGFILE);
  237. fclose(LOGFILE);
  238. return exit_code;
  239. }