X-Git-Url: https://git.saurik.com/apple/launchd.git/blobdiff_plain/5b0a4722f2ef1eac59c9650b37b29ac8b34a160e..f70834ee277faaa833845b86850fa6a18afa634f:/launchd/src/launchd_unix_ipc.c?ds=sidebyside diff --git a/launchd/src/launchd_unix_ipc.c b/launchd/src/launchd_unix_ipc.c index c939c1f..0dcd9f9 100644 --- a/launchd/src/launchd_unix_ipc.c +++ b/launchd/src/launchd_unix_ipc.c @@ -18,11 +18,12 @@ * @APPLE_APACHE_LICENSE_HEADER_END@ */ -static const char *const __rcs_file_version__ = "$Revision: 23274 $"; +static const char *const __rcs_file_version__ = "$Revision: 24557 $"; #include "config.h" #include "launchd_unix_ipc.h" +#include #include #include #include @@ -47,8 +48,8 @@ static const char *const __rcs_file_version__ = "$Revision: 23274 $"; #include #include -#include "liblaunch_public.h" -#include "liblaunch_private.h" +#include "launch.h" +#include "launch_priv.h" #include "launchd.h" #include "launchd_runtime.h" #include "launchd_core_logic.h" @@ -60,6 +61,7 @@ static LIST_HEAD(, conncb) connections; static launch_data_t adjust_rlimits(launch_data_t in); static void ipc_readmsg2(launch_data_t data, const char *cmd, void *context); +static void ipc_readmsg(launch_data_t msg, void *context); static void ipc_listen_callback(void *obj __attribute__((unused)), struct kevent *kev); @@ -72,7 +74,7 @@ static char *sockdir = NULL; static bool ipc_inited = false; -void +static void ipc_clean_up(void) { if (ipc_self != getpid()) { @@ -80,9 +82,9 @@ ipc_clean_up(void) } if (-1 == unlink(sockpath)) { - runtime_syslog(LOG_WARNING, "unlink(\"%s\"): %m", sockpath); + runtime_syslog(LOG_WARNING, "unlink(\"%s\"): %s", sockpath, strerror(errno)); } else if (-1 == rmdir(sockdir)) { - runtime_syslog(LOG_WARNING, "rmdir(\"%s\"): %m", sockdir); + runtime_syslog(LOG_WARNING, "rmdir(\"%s\"): %s", sockdir, strerror(errno)); } } @@ -101,7 +103,7 @@ ipc_server_init(void) memset(&sun, 0, sizeof(sun)); sun.sun_family = AF_UNIX; - if (getpid() == 1) { + if (pid1_magic) { strcpy(ourdir, LAUNCHD_SOCK_PREFIX); strncpy(sun.sun_path, LAUNCHD_SOCK_PREFIX "/sock", sizeof(sun.sun_path)); @@ -114,17 +116,18 @@ ipc_server_init(void) stat(ourdir, &sb); if (!S_ISDIR(sb.st_mode)) { errno = EEXIST; - runtime_syslog(LOG_ERR, "mkdir(\"%s\"): %m", LAUNCHD_SOCK_PREFIX); + runtime_syslog(LOG_ERR, "mkdir(\"%s\"): %s", LAUNCHD_SOCK_PREFIX, strerror(errno)); goto out_bad; } } else { - runtime_syslog(LOG_ERR, "mkdir(\"%s\"): %m", ourdir); + runtime_syslog(LOG_ERR, "mkdir(\"%s\"): %s", ourdir, strerror(errno)); goto out_bad; } } } else { - snprintf(ourdir, sizeof(ourdir), "/tmp/launchd-%u.XXXXXX", getpid()); - if (!launchd_assumes(mkdtemp(ourdir) != NULL)) { + snprintf(ourdir, sizeof(ourdir), _PATH_TMP "launchd-%u.XXXXXX", getpid()); + if (mkdtemp(ourdir) == NULL) { + runtime_syslog(LOG_ERR, "Could not create critical directory \"%s\": %s", ourdir, strerror(errno)); goto out_bad; } snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/sock", ourdir); @@ -132,7 +135,7 @@ ipc_server_init(void) if (unlink(sun.sun_path) == -1 && errno != ENOENT) { if (errno != EROFS) { - runtime_syslog(LOG_ERR, "unlink(\"thesocket\"): %m"); + runtime_syslog(LOG_ERR, "unlink(\"thesocket\"): %s", strerror(errno)); } goto out_bad; } @@ -147,18 +150,18 @@ ipc_server_init(void) if (r == -1) { if (errno != EROFS) { - runtime_syslog(LOG_ERR, "bind(\"thesocket\"): %m"); + runtime_syslog(LOG_ERR, "bind(\"thesocket\"): %s", strerror(errno)); } goto out_bad; } if (listen(fd, SOMAXCONN) == -1) { - runtime_syslog(LOG_ERR, "listen(\"thesocket\"): %m"); + runtime_syslog(LOG_ERR, "listen(\"thesocket\"): %s", strerror(errno)); goto out_bad; } if (kevent_mod(fd, EVFILT_READ, EV_ADD, 0, 0, &kqipc_listen_callback) == -1) { - runtime_syslog(LOG_ERR, "kevent_mod(\"thesocket\", EVFILT_READ): %m"); + runtime_syslog(LOG_ERR, "kevent_mod(\"thesocket\", EVFILT_READ): %s", strerror(errno)); goto out_bad; } @@ -171,7 +174,7 @@ ipc_server_init(void) out_bad: if (!ipc_inited && fd != -1) { - launchd_assumes(runtime_close(fd) == 0); + (void)launchd_assumes(runtime_close(fd) == 0); } } @@ -183,7 +186,12 @@ ipc_open(int fd, job_t j) fcntl(fd, F_SETFL, O_NONBLOCK); c->kqconn_callback = ipc_callback; - c->conn = launchd_fdopen(fd); + if (j) { + c->conn = launchd_fdopen(-1, fd); + } else { + c->conn = launchd_fdopen(fd, -1); + } + c->j = j; LIST_INSERT_HEAD(&connections, c, sle); kevent_mod(fd, EVFILT_READ, EV_ADD, 0, 0, &c->kqconn_callback); @@ -212,7 +220,7 @@ ipc_callback(void *obj, struct kevent *kev) if (kev->filter == EVFILT_READ) { if (launchd_msg_recv(c->conn, ipc_readmsg, c) == -1 && errno != EAGAIN) { if (errno != ECONNRESET) { - runtime_syslog(LOG_DEBUG, "%s(): recv: %m", __func__); + runtime_syslog(LOG_DEBUG, "%s(): recv: %s", __func__, strerror(errno)); } ipc_close(c); } @@ -220,7 +228,7 @@ ipc_callback(void *obj, struct kevent *kev) r = launchd_msg_send(c->conn, NULL); if (r == -1) { if (errno != EAGAIN) { - runtime_syslog(LOG_DEBUG, "%s(): send: %m", __func__); + runtime_syslog(LOG_DEBUG, "%s(): send: %s", __func__, strerror(errno)); ipc_close(c); } } else if (r == 0) { @@ -232,9 +240,15 @@ ipc_callback(void *obj, struct kevent *kev) } } -static void set_user_env(launch_data_t obj, const char *key, void *context __attribute__((unused))) +static void +set_user_env(launch_data_t obj, const char *key, void *context __attribute__((unused))) { - setenv(key, launch_data_get_string(obj), 1); + const char *v = launch_data_get_string(obj); + if (v) { + setenv(key, v, 1); + } else { + runtime_syslog(LOG_WARNING, "Attempt to set NULL environment variable: %s (type = %d)", key, launch_data_get_type(obj)); + } } void @@ -264,7 +278,7 @@ ipc_close_fds(launch_data_t o) break; case LAUNCH_DATA_FD: if (launch_data_get_fd(o) != -1) { - launchd_assumes(runtime_close(launch_data_get_fd(o)) == 0); + (void)launchd_assumes(runtime_close(launch_data_get_fd(o)) == 0); } break; default: @@ -321,14 +335,13 @@ ipc_readmsg(launch_data_t msg, void *context) if (errno == EAGAIN) { kevent_mod(launchd_getfd(rmc.c->conn), EVFILT_WRITE, EV_ADD, 0, 0, &rmc.c->kqconn_callback); } else { - runtime_syslog(LOG_DEBUG, "launchd_msg_send() == -1: %m"); + runtime_syslog(LOG_DEBUG, "launchd_msg_send() == -1: %s", strerror(errno)); ipc_close(rmc.c); } } launch_data_free(rmc.resp); } - void ipc_readmsg2(launch_data_t data, const char *cmd, void *context) { @@ -340,88 +353,113 @@ ipc_readmsg2(launch_data_t data, const char *cmd, void *context) return; } - //job_log(rmc->c->j, LOG_DEBUG, "Unix IPC request: %s", cmd); - - if (data == NULL) { - if (!strcmp(cmd, LAUNCH_KEY_CHECKIN)) { - if (rmc->c->j) { - resp = job_export(rmc->c->j); - job_checkin(rmc->c->j); - } else { - resp = launch_data_new_errno(EACCES); +// job_log(rmc->c->j, LOG_NOTICE, "Socket IPC request: %s.", cmd); + + /* Do not allow commands other than check-in to come over the trusted socket + * on the Desktop. On Embedded, allow all commands over the trusted socket if + * the job has the God Mode key set. + */ +#if TARGET_OS_EMBEDDED + bool allow_privileged_ops = ( !rmc->c->j || job_is_god(rmc->c->j) ); +#else + bool allow_privileged_ops = !rmc->c->j; +#endif + + if (rmc->c->j && strcmp(cmd, LAUNCH_KEY_CHECKIN) == 0) { + resp = job_export(rmc->c->j); + job_checkin(rmc->c->j); + } else if (allow_privileged_ops) { + #if TARGET_OS_EMBEDDED + g_embedded_privileged_action = rmc->c->j && job_is_god(rmc->c->j); + #endif + if (data == NULL) { + if (!strcmp(cmd, LAUNCH_KEY_SHUTDOWN)) { + launchd_shutdown(); + resp = launch_data_new_errno(0); + } else if (!strcmp(cmd, LAUNCH_KEY_SINGLEUSER)) { + launchd_single_user(); + resp = launch_data_new_errno(0); + } else if (!strcmp(cmd, LAUNCH_KEY_GETJOBS)) { + resp = job_export_all(); + ipc_revoke_fds(resp); + } else if (!strcmp(cmd, LAUNCH_KEY_GETRESOURCELIMITS)) { + resp = adjust_rlimits(NULL); + } else if (!strcmp(cmd, LAUNCH_KEY_GETRUSAGESELF)) { + struct rusage rusage; + getrusage(RUSAGE_SELF, &rusage); + resp = launch_data_new_opaque(&rusage, sizeof(rusage)); + } else if (!strcmp(cmd, LAUNCH_KEY_GETRUSAGECHILDREN)) { + struct rusage rusage; + getrusage(RUSAGE_CHILDREN, &rusage); + resp = launch_data_new_opaque(&rusage, sizeof(rusage)); } - } else if (!strcmp(cmd, LAUNCH_KEY_SHUTDOWN)) { - launchd_shutdown(); - resp = launch_data_new_errno(0); - } else if (!strcmp(cmd, LAUNCH_KEY_SINGLEUSER)) { - launchd_single_user(); - resp = launch_data_new_errno(0); - } else if (!strcmp(cmd, LAUNCH_KEY_GETJOBS)) { - resp = job_export_all(); - ipc_revoke_fds(resp); - } else if (!strcmp(cmd, LAUNCH_KEY_GETRESOURCELIMITS)) { - resp = adjust_rlimits(NULL); - } else if (!strcmp(cmd, LAUNCH_KEY_GETRUSAGESELF)) { - struct rusage rusage; - getrusage(RUSAGE_SELF, &rusage); - resp = launch_data_new_opaque(&rusage, sizeof(rusage)); - } else if (!strcmp(cmd, LAUNCH_KEY_GETRUSAGECHILDREN)) { - struct rusage rusage; - getrusage(RUSAGE_CHILDREN, &rusage); - resp = launch_data_new_opaque(&rusage, sizeof(rusage)); - } - } else if (!strcmp(cmd, LAUNCH_KEY_STARTJOB)) { - if ((j = job_find(launch_data_get_string(data))) != NULL) { - job_dispatch(j, true); - errno = 0; - } - resp = launch_data_new_errno(errno); - } else if (!strcmp(cmd, LAUNCH_KEY_STOPJOB)) { - if ((j = job_find(launch_data_get_string(data))) != NULL) { - job_stop(j); - errno = 0; - } - resp = launch_data_new_errno(errno); - } else if (!strcmp(cmd, LAUNCH_KEY_REMOVEJOB)) { - if ((j = job_find(launch_data_get_string(data))) != NULL) { - job_remove(j); - errno = 0; - } - resp = launch_data_new_errno(errno); - } else if (!strcmp(cmd, LAUNCH_KEY_SUBMITJOB)) { - if (launch_data_get_type(data) == LAUNCH_DATA_ARRAY) { - resp = job_import_bulk(data); } else { - if (job_import(data)) { - errno = 0; + if (!strcmp(cmd, LAUNCH_KEY_STARTJOB)) { + if ((j = job_find(NULL, launch_data_get_string(data))) != NULL) { + errno = job_dispatch(j, true) ? 0 : errno; + } + resp = launch_data_new_errno(errno); + } else if (!strcmp(cmd, LAUNCH_KEY_STOPJOB)) { + if ((j = job_find(NULL, launch_data_get_string(data))) != NULL) { + errno = 0; + job_stop(j); + } + resp = launch_data_new_errno(errno); + } else if (!strcmp(cmd, LAUNCH_KEY_REMOVEJOB)) { + if ((j = job_find(NULL, launch_data_get_string(data))) != NULL) { + errno = 0; + job_remove(j); + } + resp = launch_data_new_errno(errno); + } else if (!strcmp(cmd, LAUNCH_KEY_SUBMITJOB)) { + if (launch_data_get_type(data) == LAUNCH_DATA_ARRAY) { + resp = job_import_bulk(data); + } else { + if (job_import(data)) { + errno = 0; + } + resp = launch_data_new_errno(errno); + } + } else if (!strcmp(cmd, LAUNCH_KEY_UNSETUSERENVIRONMENT)) { + unsetenv(launch_data_get_string(data)); + resp = launch_data_new_errno(0); + } else if (!strcmp(cmd, LAUNCH_KEY_SETUSERENVIRONMENT)) { + launch_data_dict_iterate(data, set_user_env, NULL); + resp = launch_data_new_errno(0); + } else if (!strcmp(cmd, LAUNCH_KEY_SETRESOURCELIMITS)) { + resp = adjust_rlimits(data); + } else if (!strcmp(cmd, LAUNCH_KEY_GETJOB)) { + if ((j = job_find(NULL, launch_data_get_string(data))) == NULL) { + resp = launch_data_new_errno(errno); + } else { + resp = job_export(j); + ipc_revoke_fds(resp); + } + } else if (!strcmp(cmd, LAUNCH_KEY_SETPRIORITYLIST)) { + resp = launch_data_new_errno(launchd_set_jetsam_priorities(data)); } - resp = launch_data_new_errno(errno); - } - } else if (!strcmp(cmd, LAUNCH_KEY_UNSETUSERENVIRONMENT)) { - unsetenv(launch_data_get_string(data)); - resp = launch_data_new_errno(0); - } else if (!strcmp(cmd, LAUNCH_KEY_SETUSERENVIRONMENT)) { - launch_data_dict_iterate(data, set_user_env, NULL); - resp = launch_data_new_errno(0); - } else if (!strcmp(cmd, LAUNCH_KEY_SETRESOURCELIMITS)) { - resp = adjust_rlimits(data); - } else if (!strcmp(cmd, LAUNCH_KEY_GETJOB)) { - if ((j = job_find(launch_data_get_string(data))) == NULL) { - resp = launch_data_new_errno(errno); - } else { - resp = job_export(j); - ipc_revoke_fds(resp); } + #if TARGET_OS_EMBEDDED + g_embedded_privileged_action = false; + #endif + } else { + resp = launch_data_new_errno(EACCES); } rmc->resp = resp; } +static int +close_abi_fixup(int fd) +{ + return runtime_close(fd); +} + void ipc_close(struct conncb *c) { LIST_REMOVE(c, sle); - launchd_close(c->conn, runtime_close); + launchd_close(c->conn, close_abi_fixup); free(c); } @@ -433,7 +471,7 @@ adjust_rlimits(launch_data_t in) size_t i,ltmpsz; for (i = 0; i < RLIM_NLIMITS; i++) { - launchd_assumes(getrlimit(i, l + i) != -1); + (void)launchd_assumes(getrlimit(i, l + i) != -1); } if (in) { @@ -450,7 +488,7 @@ adjust_rlimits(launch_data_t in) continue; } - if (/* XXX readcfg_pid && */ getpid() == 1 && (i == RLIMIT_NOFILE || i == RLIMIT_NPROC)) { + if (/* XXX readcfg_pid && */ pid1_magic && (i == RLIMIT_NOFILE || i == RLIMIT_NPROC)) { int gmib[] = { CTL_KERN, KERN_MAXPROC }; int pmib[] = { CTL_KERN, KERN_MAXPROCPERUID }; const char *gstr = "kern.maxproc"; @@ -464,30 +502,24 @@ adjust_rlimits(launch_data_t in) gstr = "kern.maxfiles"; pstr = "kern.maxfilesperproc"; break; - case RLIMIT_NPROC: - /* kernel will not clamp to this value, we must */ - if (gval > (2048 + 20)) { - gval = 2048 + 20; - } - break; default: break; } if (gval > 0) { - launchd_assumes(sysctl(gmib, 2, NULL, NULL, &gval, sizeof(gval)) != -1); + (void)launchd_assumes(sysctl(gmib, 2, NULL, NULL, &gval, sizeof(gval)) != -1); } else { runtime_syslog(LOG_WARNING, "sysctl(\"%s\"): can't be zero", gstr); } if (pval > 0) { - launchd_assumes(sysctl(pmib, 2, NULL, NULL, &pval, sizeof(pval)) != -1); + (void)launchd_assumes(sysctl(pmib, 2, NULL, NULL, &pval, sizeof(pval)) != -1); } else { runtime_syslog(LOG_WARNING, "sysctl(\"%s\"): can't be zero", pstr); } } - launchd_assumes(setrlimit(i, ltmp + i) != -1); + (void)launchd_assumes(setrlimit(i, ltmp + i) != -1); /* the kernel may have clamped the values we gave it */ - launchd_assumes(getrlimit(i, l + i) != -1); + (void)launchd_assumes(getrlimit(i, l + i) != -1); } }