Changeset 23446
- Timestamp:
- 10/23/07 13:37:23 (14 months ago)
- Location:
- trunk/launchd/src
- Files:
-
- 3 modified
-
launchctl.c (modified) (14 diffs)
-
launchd_core_logic.c (modified) (20 diffs)
-
launchd_runtime.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/launchd/src/launchctl.c
r23400 r23446 75 75 #include <sysexits.h> 76 76 #include <util.h> 77 #include <spawn.h> 78 79 extern char **environ; 77 80 78 81 … … 133 136 static void loopback_setup_ipv4(void); 134 137 static void loopback_setup_ipv6(void); 135 static pid_t fwexec(const char *const *argv, bool _wait);138 static pid_t fwexec(const char *const *argv, int *wstatus); 136 139 static void do_potential_fsck(void); 137 140 static bool path_check(const char *path); … … 1405 1408 if (path_check("/etc/rc.server")) { 1406 1409 const char *rcserver_tool[] = { _PATH_BSHELL, "/etc/rc.server", NULL }; 1407 assumes(fwexec(rcserver_tool, true) != -1);1410 assumes(fwexec(rcserver_tool, NULL) != -1); 1408 1411 } 1409 1412 … … 1412 1415 if (path_check("/etc/rc.cdrom")) { 1413 1416 const char *rccdrom_tool[] = { _PATH_BSHELL, "/etc/rc.cdrom", "multiuser", NULL }; 1414 assumes(fwexec(rccdrom_tool, true) != -1);1417 assumes(fwexec(rccdrom_tool, NULL) != -1); 1415 1418 assumes(reboot(RB_HALT) != -1); 1416 1419 _exit(EXIT_FAILURE); 1417 1420 } else if (is_netboot()) { 1418 1421 const char *rcnetboot_tool[] = { _PATH_BSHELL, "/etc/rc.netboot", "init", NULL }; 1419 if (!assumes(fwexec(rcnetboot_tool, true) != -1)) {1422 if (!assumes(fwexec(rcnetboot_tool, NULL) != -1)) { 1420 1423 assumes(reboot(RB_HALT) != -1); 1421 1424 _exit(EXIT_FAILURE); … … 1433 1436 if (path_check("/etc/fstab")) { 1434 1437 const char *mount_tool[] = { "mount", "-vat", "nonfs", NULL }; 1435 assumes(fwexec(mount_tool, true) != -1);1438 assumes(fwexec(mount_tool, NULL) != -1); 1436 1439 } 1437 1440 1438 1441 if (path_check("/etc/rc.installer_cleanup")) { 1439 1442 const char *rccleanup_tool[] = { _PATH_BSHELL, "/etc/rc.installer_cleanup", "multiuser", NULL }; 1440 assumes(fwexec(rccleanup_tool, true) != -1);1443 assumes(fwexec(rccleanup_tool, NULL) != -1); 1441 1444 } 1442 1445 … … 1447 1450 if (path_check("/usr/libexec/dirhelper")) { 1448 1451 const char *dirhelper_tool[] = { "/usr/libexec/dirhelper", "-machineBoot", NULL }; 1449 assumes(fwexec(dirhelper_tool, true) != -1);1452 assumes(fwexec(dirhelper_tool, NULL) != -1); 1450 1453 } 1451 1454 … … 1455 1458 if (path_check("/etc/security/rc.audit")) { 1456 1459 const char *audit_tool[] = { _PATH_BSHELL, "/etc/security/rc.audit", NULL }; 1457 assumes(fwexec(audit_tool, true) != -1);1460 assumes(fwexec(audit_tool, NULL) != -1); 1458 1461 } 1459 1462 … … 1554 1557 } 1555 1558 1556 fwexec(bcc_tool, true);1559 fwexec(bcc_tool, NULL); 1557 1560 } 1558 1561 … … 2557 2560 setuid(getuid()); 2558 2561 2559 if (fwexec((const char *const *)argv + 2, true) == -1) {2562 if (fwexec((const char *const *)argv + 2, NULL) == -1) { 2560 2563 fprintf(stderr, "%s bsexec failed: %s\n", getprogname(), strerror(errno)); 2561 2564 return 1; … … 2704 2707 2705 2708 pid_t 2706 fwexec(const char *const *argv, bool _wait)2707 { 2708 int wstatus ;2709 fwexec(const char *const *argv, int *wstatus) 2710 { 2711 int wstatus2; 2709 2712 pid_t p; 2710 2713 2711 switch ((p = fork())) { 2712 case -1: 2713 break; 2714 case 0: 2715 if (!_wait) { 2716 setsid(); 2717 } 2718 execvp(argv[0], (char *const *)argv); 2719 _exit(EXIT_FAILURE); 2720 break; 2721 default: 2722 if (!_wait) 2723 return p; 2724 if (p == waitpid(p, &wstatus, 0)) { 2725 if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == EXIT_SUCCESS) 2726 return p; 2727 } 2728 break; 2714 errno = posix_spawnp(&p, argv[0], NULL, NULL, (char **)argv, environ); 2715 2716 if (errno) { 2717 return -1; 2718 } 2719 2720 if (waitpid(p, wstatus ? wstatus : &wstatus2, 0) == -1) { 2721 return -1; 2722 } 2723 2724 if (wstatus) { 2725 return p; 2726 } else if (WIFEXITED(wstatus2) && WEXITSTATUS(wstatus2) == EXIT_SUCCESS) { 2727 return p; 2729 2728 } 2730 2729 … … 2756 2755 #endif 2757 2756 2758 if (fwexec(fsck_tool, true) != -1) {2757 if (fwexec(fsck_tool, NULL) != -1) { 2759 2758 goto out; 2760 2759 } 2761 2760 } 2762 2761 2763 if (fwexec(safe_fsck_tool, true) != -1) {2762 if (fwexec(safe_fsck_tool, NULL) != -1) { 2764 2763 goto out; 2765 2764 } … … 2779 2778 */ 2780 2779 2781 assumes(fwexec(remount_tool, true) != -1);2780 assumes(fwexec(remount_tool, NULL) != -1); 2782 2781 } 2783 2782 … … 2931 2930 } 2932 2931 sysctl_tool[2] = val; 2933 assumes(fwexec(sysctl_tool, true) != -1);2932 assumes(fwexec(sysctl_tool, NULL) != -1); 2934 2933 skip_sysctl_tool: 2935 2934 free(tmpstr); … … 3098 3097 CFRelease(bootrootProp); 3099 3098 3100 if (!assumes((p = fwexec(kextcache_tool, false)) != -1)) { 3101 return; 3102 } 3103 3104 if (!assumes(waitpid(p, &wstatus, 0) != -1)) { 3099 if (!assumes((p = fwexec(kextcache_tool, &wstatus)) != -1)) { 3105 3100 return; 3106 3101 } -
trunk/launchd/src/launchd_core_logic.c
r23445 r23446 133 133 LIST_ENTRY(machservice) port_hash_sle; 134 134 job_t job; 135 uint64_t bad_perf_cnt;136 135 unsigned int gen_num; 137 136 mach_port_name_t port; … … 359 358 importing_global_env:1, importing_hard_limits:1, setmask:1, legacy_mach_job:1, start_pending:1; 360 359 mode_t mask; 361 unsigned int globargv:1, wait4debugger:1, unload_at_exit:1, stall_before_exec:1, only_once:1,360 unsigned int globargv:1, wait4debugger:1, internal_exc_handler:1, stall_before_exec:1, only_once:1, 362 361 currently_ignored:1, forced_peers_to_demand_mode:1, setnice:1, hopefully_exits_last:1, removal_pending:1, 363 wait4pipe_eof:1, sent_sigkill:1, debug_before_kill:1, weird_bootstrap:1, start_on_mount:1,362 legacy_LS_job:1, sent_sigkill:1, debug_before_kill:1, weird_bootstrap:1, start_on_mount:1, 364 363 per_user:1, hopefully_exits_first:1, deny_unknown_mslookups:1, unload_at_mig_return:1, abandon_pg:1, 365 poll_for_vfs_changes:1 , internal_exc_handler:1;364 poll_for_vfs_changes:1; 366 365 const char label[0]; 367 366 }; … … 397 396 static void job_setup_fd(job_t j, int target_fd, const char *path, int flags); 398 397 static void job_postfork_become_user(job_t j); 399 static void job_ find_and_blame_pids_with_weird_uids(job_t j);398 static void job_log_pids_with_weird_uids(job_t j); 400 399 static void job_force_sampletool(job_t j); 401 400 static void job_setup_exception_port(job_t j, task_t target_task); … … 406 405 static void job_callback_read(job_t j, int ident); 407 406 static void job_log_stray_pg(job_t j); 407 static void job_log_chidren_without_exec(job_t j); 408 408 static job_t job_new_anonymous(jobmgr_t jm, pid_t anonpid); 409 409 static job_t job_new(jobmgr_t jm, const char *label, const char *prog, const char *const *argv); … … 1035 1035 struct kinfo_proc kp; 1036 1036 size_t len = sizeof(kp); 1037 const char *zombie = NULL;1038 1037 bool shutdown_state; 1039 1038 job_t jp = NULL, jr = NULL; 1039 uid_t kp_euid, kp_uid, kp_svuid; 1040 gid_t kp_egid, kp_gid, kp_svgid; 1040 1041 1041 1042 if (!jobmgr_assumes(jm, anonpid != 0)) { … … 1062 1063 1063 1064 if (kp.kp_proc.p_stat == SZOMB) { 1064 jobmgr_log(jm, LOG_DEBUG, "Tried to create an anonymous job for zombie PID: %u", anonpid); 1065 zombie = "zombie"; 1065 jobmgr_log(jm, LOG_DEBUG, "Tried to create an anonymous job for zombie PID %u: %s", anonpid, kp.kp_proc.p_comm); 1066 } 1067 1068 if (kp.kp_proc.p_flag & P_SUGID) { 1069 jobmgr_log(jm, LOG_APPLEONLY, "Inconsistency: P_SUGID is set on PID %u: %s", anonpid, kp.kp_proc.p_comm); 1070 } 1071 1072 kp_euid = kp.kp_eproc.e_ucred.cr_uid; 1073 kp_uid = kp.kp_eproc.e_pcred.p_ruid; 1074 kp_svuid = kp.kp_eproc.e_pcred.p_svuid; 1075 kp_egid = kp.kp_eproc.e_ucred.cr_gid; 1076 kp_gid = kp.kp_eproc.e_pcred.p_rgid; 1077 kp_svgid = kp.kp_eproc.e_pcred.p_svgid; 1078 1079 if (kp_euid != kp_uid || kp_euid != kp_svuid || kp_uid != kp_svuid || kp_egid != kp_gid || kp_egid != kp_svgid || kp_gid != kp_svgid) { 1080 jobmgr_log(jm, LOG_APPLEONLY, "Inconsistency: Mixed credentials (e/r/s UID %u/%u/%u GID %u/%u/%u) detected on PID %u: %s", 1081 kp_euid, kp_uid, kp_svuid, kp_egid, kp_gid, kp_svgid, anonpid, kp.kp_proc.p_comm); 1066 1082 } 1067 1083 … … 1082 1098 } 1083 1099 1100 if (jp && !jp->anonymous && !(kp.kp_proc.p_flag & P_EXEC)) { 1101 job_log(jp, LOG_APPLEONLY, "Performance and sanity: fork() without exec*(). Please switch to posix_spawn()"); 1102 } 1103 1104 1084 1105 /* A total hack: Normally, job_new() returns an error during shutdown, but anonymous jobs are special. */ 1085 1106 if ((shutdown_state = jm->shutting_down)) { … … 1087 1108 } 1088 1109 1089 if (jobmgr_assumes(jm, (jr = job_new(jm, AUTO_PICK_LEGACY_LABEL, zombie ? zombie :kp.kp_proc.p_comm, NULL)) != NULL)) {1090 u_int proc_fflags = NOTE_EXEC|NOTE_ EXIT /* |NOTE_REAP */;1110 if (jobmgr_assumes(jm, (jr = job_new(jm, AUTO_PICK_LEGACY_LABEL, kp.kp_proc.p_comm, NULL)) != NULL)) { 1111 u_int proc_fflags = NOTE_EXEC|NOTE_FORK|NOTE_EXIT /* |NOTE_REAP */; 1091 1112 1092 1113 total_anon_children++; … … 1108 1129 1109 1130 if (shutdown_state && jm->hopefully_first_cnt == 0) { 1110 job_log(jr, LOG_APPLEONLY, "This process showed up to the party while all the guests were leaving. Odds are that it will have a miserable time ");1131 job_log(jr, LOG_APPLEONLY, "This process showed up to the party while all the guests were leaving. Odds are that it will have a miserable time."); 1111 1132 } 1112 1133 … … 2045 2066 } 2046 2067 2047 if (j->log_redirect_fd && !j-> wait4pipe_eof) {2068 if (j->log_redirect_fd && !j->legacy_LS_job) { 2048 2069 job_assumes(j, runtime_close(j->log_redirect_fd) != -1); 2049 2070 j->log_redirect_fd = 0; … … 2293 2314 2294 2315 void 2316 job_log_chidren_without_exec(job_t j) 2317 { 2318 int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; 2319 size_t i, kp_cnt, len = 10*1024*1024; 2320 struct kinfo_proc *kp; 2321 2322 if (j->anonymous || j->per_user) { 2323 return; 2324 } 2325 2326 if (!job_assumes(j, (kp = malloc(len)) != NULL)) { 2327 return; 2328 } 2329 if (!job_assumes(j, sysctl(mib, 3, kp, &len, NULL, 0) != -1)) { 2330 goto out; 2331 } 2332 2333 kp_cnt = len / sizeof(struct kinfo_proc); 2334 2335 for (i = 0; i < kp_cnt; i++) { 2336 if (kp[i].kp_eproc.e_ppid != j->p) { 2337 continue; 2338 } else if (kp[i].kp_proc.p_flag & P_EXEC) { 2339 continue; 2340 } 2341 2342 job_log(j, LOG_APPLEONLY, "Performance and sanity: fork() without exec*(). Please switch to posix_spawn()"); 2343 } 2344 2345 out: 2346 free(kp); 2347 } 2348 2349 void 2295 2350 job_callback_proc(job_t j, int flags, int fflags) 2296 2351 { 2297 if ((fflags & NOTE_EXEC) && j->anonymous) { 2298 int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, j->p }; 2299 struct kinfo_proc kp; 2300 size_t len = sizeof(kp); 2301 2302 if (job_assumes(j, sysctl(mib, 4, &kp, &len, NULL, 0) != -1)) { 2303 char newlabel[1000]; 2304 2305 snprintf(newlabel, sizeof(newlabel), "%p.%s", j, kp.kp_proc.p_comm); 2306 2307 job_log(j, LOG_DEBUG, "Program changed. Updating the label to: %s", newlabel); 2308 2309 LIST_REMOVE(j, label_hash_sle); 2310 strcpy((char *)j->label, newlabel); 2311 LIST_INSERT_HEAD(&label_hash[hash_label(j->label)], j, label_hash_sle); 2352 bool program_changed = false; 2353 2354 if (fflags & NOTE_EXEC) { 2355 program_changed = true; 2356 2357 if (j->anonymous) { 2358 int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, j->p }; 2359 struct kinfo_proc kp; 2360 size_t len = sizeof(kp); 2361 2362 if (job_assumes(j, sysctl(mib, 4, &kp, &len, NULL, 0) != -1) && job_assumes(j, len == sizeof(kp))) { 2363 char newlabel[1000]; 2364 2365 snprintf(newlabel, sizeof(newlabel), "%p.%s", j, kp.kp_proc.p_comm); 2366 2367 job_log(j, LOG_INFO, "Program changed. Updating the label to: %s", newlabel); 2368 j->lastlookup = NULL; 2369 j->lastlookup_gennum = 0; 2370 2371 LIST_REMOVE(j, label_hash_sle); 2372 strcpy((char *)j->label, newlabel); 2373 LIST_INSERT_HEAD(&label_hash[hash_label(j->label)], j, label_hash_sle); 2374 } 2375 } else { 2376 job_log(j, LOG_DEBUG, "Program changed"); 2312 2377 } 2313 2378 } 2314 2379 2315 2380 if (fflags & NOTE_FORK) { 2316 job_log(j, LOG_DEBUG, "Called fork()"); 2381 job_log(j, LOG_DEBUG, "fork()ed%s", program_changed ? ". For this message only: We don't know whether this event happened before or after execve()." : ""); 2382 job_log_chidren_without_exec(j); 2317 2383 } 2318 2384 … … 2468 2534 pid_t c; 2469 2535 bool sipc = false; 2470 u_int proc_fflags = /* NOTE_EXEC|NOTE_FORK| */ NOTE_EXIT /* |NOTE_REAP */;2536 u_int proc_fflags = NOTE_EXIT|NOTE_FORK|NOTE_EXEC /* NOTE_REAP */; 2471 2537 2472 2538 if (!job_assumes(j, j->mgr != NULL)) { … … 2763 2829 2764 2830 void 2765 job_ find_and_blame_pids_with_weird_uids(job_t j)2831 job_log_pids_with_weird_uids(job_t j) 2766 2832 { 2767 2833 int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; … … 2835 2901 if ((pwe = getpwuid(j->mach_uid)) == NULL) { 2836 2902 job_log(j, LOG_ERR, "getpwuid(\"%u\") failed", j->mach_uid); 2837 job_ find_and_blame_pids_with_weird_uids(j);2903 job_log_pids_with_weird_uids(j); 2838 2904 _exit(EXIT_FAILURE); 2839 2905 } … … 3751 3817 job_useless(job_t j) 3752 3818 { 3753 /* Yes, j->unload_at_exit and j->only_once seem the same, but they'll differ someday... */ 3754 3755 if ((j->unload_at_exit || j->only_once) && j->start_time != 0) { 3756 if (j->unload_at_exit && j->j_port) { 3819 if ((j->legacy_LS_job || j->only_once) && j->start_time != 0) { 3820 if (j->legacy_LS_job && j->j_port) { 3757 3821 return false; 3758 3822 } … … 3917 3981 3918 3982 if (j->log_redirect_fd) { 3919 if (job_assumes(j, j-> wait4pipe_eof)) {3983 if (job_assumes(j, j->legacy_LS_job)) { 3920 3984 return "Standard out/error is still valid"; 3921 3985 } else { … … 3975 4039 strcpy((char *)ms->name, name); 3976 4040 ms->job = j; 4041 ms->gen_num = 1; 3977 4042 ms->per_pid = pid_local; 3978 4043 … … 5726 5791 runtime_get_caller_creds(&ldc); 5727 5792 5728 #if 0 5729 job_log(j, LOG_APPLEONLY, "bootstrap_register() is deprecated. Service: %s", servicename);5730 #endif 5793 if (!(flags & BOOTSTRAP_PER_PID_SERVICE) && !j->legacy_LS_job) { 5794 job_log(j, LOG_APPLEONLY, "Performance: bootstrap_register() is deprecated. Service: %s", servicename); 5795 } 5731 5796 5732 5797 job_log(j, LOG_DEBUG, "%sMach service registration attempt: %s", flags & BOOTSTRAP_PER_PID_SERVICE ? "Per PID " : "", servicename); … … 5807 5872 launchd_assumes(machservice_port(ms) != MACH_PORT_NULL); 5808 5873 job_log(j, LOG_DEBUG, "%sMach service lookup: %s", flags & BOOTSTRAP_PER_PID_SERVICE ? "Per PID " : "", servicename); 5809 #if 0 5810 /* After Leopard ships, we should enable this */ 5874 5811 5875 if (j->lastlookup == ms && j->lastlookup_gennum == ms->gen_num && !j->per_user) { 5812 ms->bad_perf_cnt++; 5813 job_log(j, LOG_APPLEONLY, "Performance opportunity: Number of bootstrap_lookup(... \"%s\" ...) calls that should have been cached: %llu", 5814 servicename, ms->bad_perf_cnt); 5815 } 5876 job_log(ms->job, LOG_APPLEONLY, "Performance: Please fix the framework to cache the Mach port for service: %s", servicename); 5877 } 5878 5816 5879 j->lastlookup = ms; 5817 5880 j->lastlookup_gennum = ms->gen_num; 5818 #endif 5881 5819 5882 *serviceportp = machservice_port(ms); 5883 5820 5884 kr = BOOTSTRAP_SUCCESS; 5821 5885 } else if (!(flags & BOOTSTRAP_PER_PID_SERVICE) && (inherited_bootstrap_port != MACH_PORT_NULL)) { … … 6470 6534 } 6471 6535 6472 jr->unload_at_exit = true; 6473 jr->wait4pipe_eof = true; 6536 jr->legacy_LS_job = true; 6474 6537 jr->abandon_pg = true; 6475 6538 jr->stall_before_exec = jr->wait4debugger; -
trunk/launchd/src/launchd_runtime.c
r23445 r23446 1174 1174 size_t i, j; 1175 1175 1176 if (apple_internal_logging == 1) { 1177 apple_internal_logging = stat("/AppleInternal", &sb); 1178 } 1179 1180 if (attr->priority == LOG_APPLEONLY) { 1181 if (apple_internal_logging == 0) { 1182 attr->priority = LOG_NOTICE; 1183 } else { 1184 return; 1185 } 1186 } 1187 1176 1188 if (!(LOG_MASK(attr->priority) & internal_mask_pri)) { 1177 1189 goto out; 1178 1190 } 1179 1191 1180 if (apple_internal_logging == 1) {1181 apple_internal_logging = stat("/AppleInternal", &sb);1182 }1183 1184 1185 1192 if (!(debug_shutdown_hangs && getpid() == 1)) { 1186 if (attr->priority == LOG_APPLEONLY) {1187 if (apple_internal_logging == -1) {1188 goto out;1189 }1190 attr->priority = LOG_NOTICE;1191 }1192 1193 vsnprintf(newmsg, sizeof(newmsg), message, args); 1193 1194 logmsg_add(attr, saved_errno, newmsg);

