X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fsocket.c;h=624e28744f0226210b7f3f7d0faafe58886b157b;hb=e9fc29f4ecc9509ccc02eb8a014341e26c0d7831;hp=0ccda2fe3cf22a9fd3d01325822c9ed51b2436d1;hpb=151b9b9662a90455262ce575a8a8ae74bf4ff336;p=elogind.git diff --git a/src/core/socket.c b/src/core/socket.c index 0ccda2fe3..624e28744 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -29,9 +29,7 @@ #include #include #include -#ifdef HAVE_XATTR -#include -#endif +#include #include "sd-event.h" #include "log.h" @@ -90,11 +88,8 @@ static void socket_init(Unit *u) { s->ip_ttl = -1; s->mark = -1; - exec_context_init(&s->exec_context); s->exec_context.std_output = u->manager->default_std_output; s->exec_context.std_error = u->manager->default_std_error; - kill_context_init(&s->kill_context); - cgroup_context_init(&s->cgroup_context); s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID; } @@ -119,9 +114,7 @@ void socket_free_ports(Socket *s) { sd_event_source_unref(p->event_source); - if (p->fd >= 0) - close_nointr_nofail(p->fd); - + safe_close(p->fd); free(p->path); free(p); } @@ -134,8 +127,6 @@ static void socket_done(Unit *u) { socket_free_ports(s); - cgroup_context_done(&s->cgroup_context); - exec_context_done(&s->exec_context); s->exec_runtime = exec_runtime_unref(s->exec_runtime); exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX); s->control_command = NULL; @@ -175,7 +166,12 @@ static int socket_arm_timer(Socket *s) { return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT); } - return sd_event_add_monotonic(UNIT(s)->manager->event, &s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_usec, 0, socket_dispatch_timer, s); + return sd_event_add_time( + UNIT(s)->manager->event, + &s->timer_event_source, + CLOCK_MONOTONIC, + now(CLOCK_MONOTONIC) + s->timeout_usec, 0, + socket_dispatch_timer, s); } static int socket_instantiate_service(Socket *s) { @@ -196,16 +192,14 @@ static int socket_instantiate_service(Socket *s) { assert(s->accept); - if (!(prefix = unit_name_to_prefix(UNIT(s)->id))) + prefix = unit_name_to_prefix(UNIT(s)->id); + if (!prefix) return -ENOMEM; - r = asprintf(&name, "%s@%u.service", prefix, s->n_accepted); - - if (r < 0) + if (asprintf(&name, "%s@%u.service", prefix, s->n_accepted) < 0) return -ENOMEM; r = manager_load_unit(UNIT(s)->manager, name, NULL, NULL, &u); - if (r < 0) return r; @@ -338,7 +332,7 @@ static int socket_add_extras(Socket *s) { if (r < 0) return r; - r = unit_exec_context_defaults(u, &s->exec_context); + r = unit_patch_contexts(u); if (r < 0) return r; @@ -347,7 +341,7 @@ static int socket_add_extras(Socket *s) { if (r < 0) return r; - r = unit_add_default_slice(u); + r = unit_add_default_slice(u, &s->cgroup_context); if (r < 0) return r; } @@ -457,7 +451,8 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) { "%sBroadcast: %s\n" "%sPassCredentials: %s\n" "%sPassSecurity: %s\n" - "%sTCPCongestion: %s\n", + "%sTCPCongestion: %s\n" + "%sRemoveOnStop: %s\n", prefix, socket_state_to_string(s->state), prefix, socket_result_to_string(s->result), prefix, socket_address_bind_ipv6_only_to_string(s->bind_ipv6_only), @@ -470,12 +465,13 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) { prefix, yes_no(s->broadcast), prefix, yes_no(s->pass_cred), prefix, yes_no(s->pass_sec), - prefix, strna(s->tcp_congestion)); + prefix, strna(s->tcp_congestion), + prefix, yes_no(s->remove_on_stop)); if (s->control_pid > 0) fprintf(f, - "%sControl PID: %lu\n", - prefix, (unsigned long) s->control_pid); + "%sControl PID: "PID_FMT"\n", + prefix, s->control_pid); if (s->bind_to_device) fprintf(f, @@ -595,13 +591,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) { static int instance_from_socket(int fd, unsigned nr, char **instance) { socklen_t l; char *r; - union { - struct sockaddr sa; - struct sockaddr_un un; - struct sockaddr_in in; - struct sockaddr_in6 in6; - struct sockaddr_storage storage; - } local, remote; + union sockaddr_union local, remote; assert(fd >= 0); assert(instance); @@ -673,16 +663,22 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) { int k; k = getpeercred(fd, &ucred); - if (k < 0) + if (k >= 0) { + if (asprintf(&r, + "%u-"PID_FMT"-"UID_FMT, + nr, ucred.pid, ucred.uid) < 0) + return -ENOMEM; + } else if (k == -ENODATA) { + /* This handles the case where somebody is + * connecting from another pid/uid namespace + * (e.g. from outside of our container). */ + if (asprintf(&r, + "%u-unknown", + nr) < 0) + return -ENOMEM; + } else return k; - if (asprintf(&r, - "%u-%lu-%lu", - nr, - (unsigned long) ucred.pid, - (unsigned long) ucred.uid) < 0) - return -ENOMEM; - break; } @@ -706,17 +702,35 @@ static void socket_close_fds(Socket *s) { if (p->fd < 0) continue; - close_nointr_nofail(p->fd); + p->fd = safe_close(p->fd); - /* One little note: we should never delete any sockets - * in the file system here! After all some other - * process we spawned might still have a reference of - * this fd and wants to continue to use it. Therefore - * we delete sockets in the file system before we - * create a new one, not after we stopped using - * one! */ + /* One little note: we should normally not delete any + * sockets in the file system here! After all some + * other process we spawned might still have a + * reference of this fd and wants to continue to use + * it. Therefore we delete sockets in the file system + * before we create a new one, not after we stopped + * using one! */ - p->fd = -1; + if (s->remove_on_stop) { + switch (p->type) { + + case SOCKET_FIFO: + unlink(p->path); + break; + + case SOCKET_MQUEUE: + mq_unlink(p->path); + break; + + case SOCKET_SOCKET: + socket_address_unlink(&p->address); + break; + + default: + break; + } + } } } @@ -886,9 +900,7 @@ static int fifo_address_create( fail: label_context_clear(); - - if (fd >= 0) - close_nointr_nofail(fd); + safe_close(fd); return r; } @@ -923,8 +935,7 @@ static int special_address_create( return 0; fail: - if (fd >= 0) - close_nointr_nofail(fd); + safe_close(fd); return r; } @@ -983,9 +994,7 @@ static int mq_address_create( return 0; fail: - if (fd >= 0) - close_nointr_nofail(fd); - + safe_close(fd); return r; } @@ -1006,17 +1015,15 @@ static int socket_open_fds(Socket *s) { if (!know_label) { - if ((r = socket_instantiate_service(s)) < 0) + r = socket_instantiate_service(s); + if (r < 0) return r; if (UNIT_ISSET(s->service) && SERVICE(UNIT_DEREF(s->service))->exec_command[SERVICE_EXEC_START]) { r = label_get_create_label_from_exe(SERVICE(UNIT_DEREF(s->service))->exec_command[SERVICE_EXEC_START]->path, &label); - - if (r < 0) { - if (r != -EPERM) - return r; - } + if (r < 0 && r != -EPERM) + return r; } know_label = true; @@ -1134,14 +1141,15 @@ static void socket_set_state(Socket *s, SocketState state) { old_state = s->state; s->state = state; - if (state != SOCKET_START_PRE && - state != SOCKET_START_POST && - state != SOCKET_STOP_PRE && - state != SOCKET_STOP_PRE_SIGTERM && - state != SOCKET_STOP_PRE_SIGKILL && - state != SOCKET_STOP_POST && - state != SOCKET_FINAL_SIGTERM && - state != SOCKET_FINAL_SIGKILL) { + if (!IN_SET(state, + SOCKET_START_PRE, + SOCKET_START_POST, + SOCKET_STOP_PRE, + SOCKET_STOP_PRE_SIGTERM, + SOCKET_STOP_PRE_SIGKILL, + SOCKET_STOP_POST, + SOCKET_FINAL_SIGTERM, + SOCKET_FINAL_SIGKILL)) { s->timer_event_source = sd_event_source_unref(s->timer_event_source); socket_unwatch_control_pid(s); @@ -1152,12 +1160,13 @@ static void socket_set_state(Socket *s, SocketState state) { if (state != SOCKET_LISTENING) socket_unwatch_fds(s); - if (state != SOCKET_START_POST && - state != SOCKET_LISTENING && - state != SOCKET_RUNNING && - state != SOCKET_STOP_PRE && - state != SOCKET_STOP_PRE_SIGTERM && - state != SOCKET_STOP_PRE_SIGKILL) + if (!IN_SET(state, + SOCKET_START_POST, + SOCKET_LISTENING, + SOCKET_RUNNING, + SOCKET_STOP_PRE, + SOCKET_STOP_PRE_SIGTERM, + SOCKET_STOP_PRE_SIGKILL)) socket_close_fds(s); if (state != old_state) @@ -1253,6 +1262,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) { UNIT(s)->manager->confirm_spawn, UNIT(s)->manager->cgroup_supported, UNIT(s)->cgroup_path, + manager_get_runtime_prefix(UNIT(s)->manager), UNIT(s)->id, 0, NULL, @@ -1287,6 +1297,8 @@ static void socket_enter_dead(Socket *s, SocketResult f) { exec_runtime_destroy(s->exec_runtime); s->exec_runtime = exec_runtime_unref(s->exec_runtime); + exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager)); + socket_set_state(s, s->result != SOCKET_SUCCESS ? SOCKET_FAILED : SOCKET_DEAD); } @@ -1475,7 +1487,7 @@ static void socket_enter_running(Socket *s, int cfd) { log_debug_unit(UNIT(s)->id, "Suppressing connection request on %s since unit stop is scheduled.", UNIT(s)->id); if (cfd >= 0) - close_nointr_nofail(cfd); + safe_close(cfd); else { /* Flush all sockets by closing and reopening them */ socket_close_fds(s); @@ -1511,6 +1523,12 @@ static void socket_enter_running(Socket *s, int cfd) { } if (!pending) { + if (!UNIT_ISSET(s->service)) { + log_error_unit(UNIT(s)->id, "%s: service to activate vanished, refusing activation.", UNIT(s)->id); + r = -ENOENT; + goto fail; + } + r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT_DEREF(s->service), JOB_REPLACE, true, &error, NULL); if (r < 0) goto fail; @@ -1523,7 +1541,7 @@ static void socket_enter_running(Socket *s, int cfd) { if (s->n_connections >= s->max_connections) { log_warning_unit(UNIT(s)->id, "%s: Too many incoming connections (%u)", UNIT(s)->id, s->n_connections); - close_nointr_nofail(cfd); + safe_close(cfd); return; } @@ -1538,7 +1556,7 @@ static void socket_enter_running(Socket *s, int cfd) { /* ENOTCONN is legitimate if TCP RST was received. * This connection is over, but the socket unit lives on. */ - close_nointr_nofail(cfd); + safe_close(cfd); return; } @@ -1589,9 +1607,7 @@ fail: bus_error_message(&error, r)); socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); - - if (cfd >= 0) - close_nointr_nofail(cfd); + safe_close(cfd); } static void socket_run_next(Socket *s) { @@ -1720,7 +1736,7 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) { unit_serialize_item_format(u, f, "n-accepted", "%u", s->n_accepted); if (s->control_pid > 0) - unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) s->control_pid); + unit_serialize_item_format(u, f, "control-pid", PID_FMT, s->control_pid); if (s->control_command_id >= 0) unit_serialize_item(u, f, "control-command", socket_exec_command_to_string(s->control_command_id)); @@ -1822,8 +1838,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, break; if (p) { - if (p->fd >= 0) - close_nointr_nofail(p->fd); + safe_close(p->fd); p->fd = fdset_remove(fds, fd); } } @@ -1842,8 +1857,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, break; if (p) { - if (p->fd >= 0) - close_nointr_nofail(p->fd); + safe_close(p->fd); p->fd = fdset_remove(fds, fd); } } @@ -1862,8 +1876,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, break; if (p) { - if (p->fd >= 0) - close_nointr_nofail(p->fd); + safe_close(p->fd); p->fd = fdset_remove(fds, fd); } } @@ -1881,8 +1894,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, break; if (p) { - if (p->fd >= 0) - close_nointr_nofail(p->fd); + safe_close(p->fd); p->fd = fdset_remove(fds, fd); } } @@ -1900,8 +1912,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, break; if (p) { - if (p->fd >= 0) - close_nointr_nofail(p->fd); + safe_close(p->fd); p->fd = fdset_remove(fds, fd); } }