diff options
Diffstat (limited to 'src/core/socket.c')
-rw-r--r-- | src/core/socket.c | 382 |
1 files changed, 192 insertions, 190 deletions
diff --git a/src/core/socket.c b/src/core/socket.c index 9adae16..41147d4 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -53,29 +53,44 @@ struct SocketPeer { Socket *socket; union sockaddr_union peer; socklen_t peer_salen; + struct ucred peer_cred; }; static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = { - [SOCKET_DEAD] = UNIT_INACTIVE, - [SOCKET_START_PRE] = UNIT_ACTIVATING, - [SOCKET_START_CHOWN] = UNIT_ACTIVATING, - [SOCKET_START_POST] = UNIT_ACTIVATING, - [SOCKET_LISTENING] = UNIT_ACTIVE, - [SOCKET_RUNNING] = UNIT_ACTIVE, - [SOCKET_STOP_PRE] = UNIT_DEACTIVATING, + [SOCKET_DEAD] = UNIT_INACTIVE, + [SOCKET_START_PRE] = UNIT_ACTIVATING, + [SOCKET_START_CHOWN] = UNIT_ACTIVATING, + [SOCKET_START_POST] = UNIT_ACTIVATING, + [SOCKET_LISTENING] = UNIT_ACTIVE, + [SOCKET_RUNNING] = UNIT_ACTIVE, + [SOCKET_STOP_PRE] = UNIT_DEACTIVATING, [SOCKET_STOP_PRE_SIGTERM] = UNIT_DEACTIVATING, [SOCKET_STOP_PRE_SIGKILL] = UNIT_DEACTIVATING, - [SOCKET_STOP_POST] = UNIT_DEACTIVATING, - [SOCKET_FINAL_SIGTERM] = UNIT_DEACTIVATING, - [SOCKET_FINAL_SIGKILL] = UNIT_DEACTIVATING, - [SOCKET_FAILED] = UNIT_FAILED, - [SOCKET_CLEANING] = UNIT_MAINTENANCE, + [SOCKET_STOP_POST] = UNIT_DEACTIVATING, + [SOCKET_FINAL_SIGTERM] = UNIT_DEACTIVATING, + [SOCKET_FINAL_SIGKILL] = UNIT_DEACTIVATING, + [SOCKET_FAILED] = UNIT_FAILED, + [SOCKET_CLEANING] = UNIT_MAINTENANCE, }; static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); static void flush_ports(Socket *s); +static bool SOCKET_STATE_WITH_PROCESS(SocketState state) { + return IN_SET(state, + SOCKET_START_PRE, + SOCKET_START_CHOWN, + SOCKET_START_POST, + SOCKET_STOP_PRE, + SOCKET_STOP_PRE_SIGTERM, + SOCKET_STOP_PRE_SIGKILL, + SOCKET_STOP_POST, + SOCKET_FINAL_SIGTERM, + SOCKET_FINAL_SIGKILL, + SOCKET_CLEANING); +} + static void socket_init(Unit *u) { Socket *s = SOCKET(u); @@ -108,12 +123,7 @@ static void socket_init(Unit *u) { static void socket_unwatch_control_pid(Socket *s) { assert(s); - - if (!pidref_is_set(&s->control_pid)) - return; - - unit_unwatch_pidref(UNIT(s), &s->control_pid); - pidref_done(&s->control_pid); + unit_unwatch_pidref_done(UNIT(s), &s->control_pid); } static void socket_cleanup_fd_list(SocketPort *p) { @@ -144,11 +154,9 @@ void socket_free_ports(Socket *s) { } static void socket_done(Unit *u) { - Socket *s = SOCKET(u); + Socket *s = ASSERT_PTR(SOCKET(u)); SocketPeer *p; - assert(s); - socket_free_ports(s); while ((p = set_steal_first(s->peers_by_address))) @@ -157,6 +165,7 @@ static void socket_done(Unit *u) { s->peers_by_address = set_free(s->peers_by_address); s->exec_runtime = exec_runtime_free(s->exec_runtime); + exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX); s->control_command = NULL; @@ -221,7 +230,7 @@ static int socket_add_mount_dependencies(Socket *s) { if (!path) continue; - r = unit_require_mounts_for(UNIT(s), path, UNIT_DEPENDENCY_FILE); + r = unit_add_mounts_for(UNIT(s), path, UNIT_DEPENDENCY_FILE, UNIT_MOUNT_REQUIRES); if (r < 0) return r; } @@ -243,6 +252,7 @@ static int socket_add_device_dependencies(Socket *s) { static int socket_add_default_dependencies(Socket *s) { int r; + assert(s); if (!UNIT(s)->default_dependencies) @@ -263,6 +273,7 @@ static int socket_add_default_dependencies(Socket *s) { static bool socket_has_exec(Socket *s) { unsigned i; + assert(s); for (i = 0; i < _SOCKET_EXEC_COMMAND_MAX; i++) @@ -273,11 +284,9 @@ static bool socket_has_exec(Socket *s) { } static int socket_add_extras(Socket *s) { - Unit *u = UNIT(s); + Unit *u = UNIT(ASSERT_PTR(s)); int r; - assert(s); - /* Pick defaults for the trigger limit, if nothing was explicitly configured. We pick a relatively high limit * in Accept=yes mode, and a lower limit for Accept=no. Reason: in Accept=yes mode we are invoking accept() * ourselves before the trigger limit can hit, thus incoming connections are taken off the socket queue quickly @@ -406,11 +415,13 @@ static void peer_address_hash_func(const SocketPeer *s, struct siphash *state) { assert(s); if (s->peer.sa.sa_family == AF_INET) - siphash24_compress(&s->peer.in.sin_addr, sizeof(s->peer.in.sin_addr), state); + siphash24_compress_typesafe(s->peer.in.sin_addr, state); else if (s->peer.sa.sa_family == AF_INET6) - siphash24_compress(&s->peer.in6.sin6_addr, sizeof(s->peer.in6.sin6_addr), state); + siphash24_compress_typesafe(s->peer.in6.sin6_addr, state); else if (s->peer.sa.sa_family == AF_VSOCK) - siphash24_compress(&s->peer.vm.svm_cid, sizeof(s->peer.vm.svm_cid), state); + siphash24_compress_typesafe(s->peer.vm.svm_cid, state); + else if (s->peer.sa.sa_family == AF_UNIX) + siphash24_compress_typesafe(s->peer_cred.uid, state); else assert_not_reached(); } @@ -429,6 +440,8 @@ static int peer_address_compare_func(const SocketPeer *x, const SocketPeer *y) { return memcmp(&x->peer.in6.sin6_addr, &y->peer.in6.sin6_addr, sizeof(x->peer.in6.sin6_addr)); case AF_VSOCK: return CMP(x->peer.vm.svm_cid, y->peer.vm.svm_cid); + case AF_UNIX: + return CMP(x->peer_cred.uid, y->peer_cred.uid); } assert_not_reached(); } @@ -436,10 +449,9 @@ static int peer_address_compare_func(const SocketPeer *x, const SocketPeer *y) { DEFINE_PRIVATE_HASH_OPS(peer_address_hash_ops, SocketPeer, peer_address_hash_func, peer_address_compare_func); static int socket_load(Unit *u) { - Socket *s = SOCKET(u); + Socket *s = ASSERT_PTR(SOCKET(u)); int r; - assert(u); assert(u->load_state == UNIT_STUB); r = unit_load_fragment_and_dropin(u, true); @@ -457,16 +469,22 @@ static int socket_load(Unit *u) { return socket_verify(s); } -static SocketPeer *socket_peer_new(void) { +static SocketPeer *socket_peer_dup(const SocketPeer *q) { SocketPeer *p; + assert(q); + p = new(SocketPeer, 1); if (!p) return NULL; *p = (SocketPeer) { .n_ref = 1, + .peer = q->peer, + .peer_salen = q->peer_salen, + .peer_cred = q->peer_cred, }; + return p; } @@ -483,36 +501,46 @@ DEFINE_TRIVIAL_REF_UNREF_FUNC(SocketPeer, socket_peer, socket_peer_free); int socket_acquire_peer(Socket *s, int fd, SocketPeer **ret) { _cleanup_(socket_peer_unrefp) SocketPeer *remote = NULL; - SocketPeer sa = { + SocketPeer key = { .peer_salen = sizeof(union sockaddr_union), + .peer_cred = UCRED_INVALID, }, *i; int r; - assert(fd >= 0); assert(s); + assert(fd >= 0); assert(ret); - if (getpeername(fd, &sa.peer.sa, &sa.peer_salen) < 0) + if (getpeername(fd, &key.peer.sa, &key.peer_salen) < 0) return log_unit_error_errno(UNIT(s), errno, "getpeername() failed: %m"); - if (!IN_SET(sa.peer.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)) { + switch (key.peer.sa.sa_family) { + case AF_INET: + case AF_INET6: + case AF_VSOCK: + break; + + case AF_UNIX: + r = getpeercred(fd, &key.peer_cred); + if (r < 0) + return log_unit_error_errno(UNIT(s), r, "Failed to get peer credentials of socket: %m"); + break; + + default: *ret = NULL; return 0; } - i = set_get(s->peers_by_address, &sa); + i = set_get(s->peers_by_address, &key); if (i) { *ret = socket_peer_ref(i); return 1; } - remote = socket_peer_new(); + remote = socket_peer_dup(&key); if (!remote) return log_oom(); - remote->peer = sa.peer; - remote->peer_salen = sa.peer_salen; - r = set_ensure_put(&s->peers_by_address, &peer_address_hash_ops, remote); if (r < 0) return log_unit_error_errno(UNIT(s), r, "Failed to insert peer info into hash table: %m"); @@ -540,10 +568,9 @@ static const char* listen_lookup(int family, int type) { } static void socket_dump(Unit *u, FILE *f, const char *prefix) { - Socket *s = SOCKET(u); + Socket *s = ASSERT_PTR(SOCKET(u)); const char *prefix2, *str; - assert(s); assert(f); prefix = strempty(prefix); @@ -563,6 +590,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) { "%sTransparent: %s\n" "%sBroadcast: %s\n" "%sPassCredentials: %s\n" + "%sPassFileDescriptorsToExec: %s\n" "%sPassSecurity: %s\n" "%sPassPacketInfo: %s\n" "%sTCPCongestion: %s\n" @@ -583,6 +611,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) { prefix, yes_no(s->transparent), prefix, yes_no(s->broadcast), prefix, yes_no(s->pass_cred), + prefix, yes_no(s->pass_fds_to_exec), prefix, yes_no(s->pass_sec), prefix, yes_no(s->pass_pktinfo), prefix, strna(s->tcp_congestion), @@ -776,8 +805,8 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) { if (!s->exec_command[c]) continue; - fprintf(f, "%s-> %s:\n", - prefix, socket_exec_command_to_string(c)); + fprintf(f, "%s%s %s:\n", + prefix, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), socket_exec_command_to_string(c)); exec_command_dump_list(s->exec_command[c], f, prefix2); } @@ -1274,6 +1303,9 @@ static int socket_symlink(Socket *s) { static int usbffs_write_descs(int fd, Service *s) { int r; + assert(fd >= 0); + assert(s); + if (!s->usb_function_descriptors || !s->usb_function_strings) return -EINVAL; @@ -1339,12 +1371,17 @@ clear: } int socket_load_service_unit(Socket *s, int cfd, Unit **ret) { + int r; + /* Figure out what the unit that will be used to handle the connections on the socket looks like. * * If cfd < 0, then we don't have a connection yet. In case of Accept=yes sockets, use a fake * instance name. */ + assert(s); + assert(ret); + if (UNIT_ISSET(s->service)) { *ret = UNIT_DEREF(s->service); return 0; @@ -1355,7 +1392,6 @@ int socket_load_service_unit(Socket *s, int cfd, Unit **ret) { /* Build the instance name and load the unit */ _cleanup_free_ char *prefix = NULL, *instance = NULL, *name = NULL; - int r; r = unit_name_to_prefix(UNIT(s)->id, &prefix); if (r < 0) @@ -1385,50 +1421,26 @@ int socket_load_service_unit(Socket *s, int cfd, Unit **ret) { } static int socket_determine_selinux_label(Socket *s, char **ret) { + Unit *service; int r; assert(s); assert(ret); - Unit *service; - ExecCommand *c; - const char *exec_context; - _cleanup_free_ char *path = NULL; - - r = socket_load_service_unit(s, -1, &service); - if (r == -ENODATA) - goto no_label; + r = socket_load_service_unit(s, /* cfd= */ -EBADF, &service); + if (r == -ENODATA) { + *ret = NULL; + return 0; + } if (r < 0) return r; - exec_context = SERVICE(service)->exec_context.selinux_context; - if (exec_context) { - char *con; - - con = strdup(exec_context); - if (!con) - return -ENOMEM; - - *ret = TAKE_PTR(con); + r = service_determine_exec_selinux_label(SERVICE(service), ret); + if (r == -ENODATA) { + *ret = NULL; return 0; } - - c = SERVICE(service)->exec_command[SERVICE_EXEC_START]; - if (!c) - goto no_label; - - r = chase(c->path, SERVICE(service)->exec_context.root_directory, CHASE_PREFIX_ROOT, &path, NULL); - if (r < 0) - goto no_label; - - r = mac_selinux_get_create_label_from_exe(path, ret); - if (IN_SET(r, -EPERM, -EOPNOTSUPP)) - goto no_label; return r; - -no_label: - *ret = NULL; - return 0; } static int socket_address_listen_do( @@ -1794,6 +1806,7 @@ static int socket_check_open(Socket *s) { static void socket_set_state(Socket *s, SocketState state) { SocketState old_state; + assert(s); if (s->state != state) @@ -1802,18 +1815,7 @@ static void socket_set_state(Socket *s, SocketState state) { old_state = s->state; s->state = state; - if (!IN_SET(state, - SOCKET_START_PRE, - SOCKET_START_CHOWN, - SOCKET_START_POST, - SOCKET_STOP_PRE, - SOCKET_STOP_PRE_SIGTERM, - SOCKET_STOP_PRE_SIGKILL, - SOCKET_STOP_POST, - SOCKET_FINAL_SIGTERM, - SOCKET_FINAL_SIGKILL, - SOCKET_CLEANING)) { - + if (!SOCKET_STATE_WITH_PROCESS(state)) { s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source); socket_unwatch_control_pid(s); s->control_command = NULL; @@ -1841,10 +1843,9 @@ static void socket_set_state(Socket *s, SocketState state) { } static int socket_coldplug(Unit *u) { - Socket *s = SOCKET(u); + Socket *s = ASSERT_PTR(SOCKET(u)); int r; - assert(s); assert(s->state == SOCKET_DEAD); if (s->deserialized_state == s->state) @@ -1852,17 +1853,7 @@ static int socket_coldplug(Unit *u) { if (pidref_is_set(&s->control_pid) && pidref_is_unwaited(&s->control_pid) > 0 && - IN_SET(s->deserialized_state, - SOCKET_START_PRE, - SOCKET_START_CHOWN, - SOCKET_START_POST, - SOCKET_STOP_PRE, - SOCKET_STOP_PRE_SIGTERM, - SOCKET_STOP_PRE_SIGKILL, - SOCKET_STOP_POST, - SOCKET_FINAL_SIGTERM, - SOCKET_FINAL_SIGKILL, - SOCKET_CLEANING)) { + SOCKET_STATE_WITH_PROCESS(s->deserialized_state)) { r = unit_watch_pidref(UNIT(s), &s->control_pid, /* exclusive= */ false); if (r < 0) @@ -1911,11 +1902,9 @@ static int socket_coldplug(Unit *u) { } static int socket_spawn(Socket *s, ExecCommand *c, PidRef *ret_pid) { - _cleanup_(exec_params_shallow_clear) ExecParameters exec_params = EXEC_PARAMETERS_INIT( EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN); _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; - pid_t pid; int r; assert(s); @@ -1934,17 +1923,33 @@ static int socket_spawn(Socket *s, ExecCommand *c, PidRef *ret_pid) { if (r < 0) return r; + /* Note that ExecStartPre= command doesn't inherit any FDs. It runs before we open listen FDs. */ + if (s->pass_fds_to_exec) { + _cleanup_strv_free_ char **fd_names = NULL; + _cleanup_free_ int *fds = NULL; + int n_fds; + + n_fds = socket_collect_fds(s, &fds); + if (n_fds < 0) + return n_fds; + + r = strv_extend_n(&fd_names, socket_fdname(s), n_fds); + if (r < 0) + return r; + + exec_params.flags |= EXEC_PASS_FDS; + exec_params.fds = TAKE_PTR(fds); + exec_params.fd_names = TAKE_PTR(fd_names); + exec_params.n_socket_fds = n_fds; + } + r = exec_spawn(UNIT(s), c, &s->exec_context, &exec_params, s->exec_runtime, &s->cgroup_context, - &pid); - if (r < 0) - return r; - - r = pidref_set_pid(&pidref, pid); + &pidref); if (r < 0) return r; @@ -2052,6 +2057,7 @@ static void socket_enter_signal(Socket *s, SocketState state, SocketResult f); static void socket_enter_stop_post(Socket *s, SocketResult f) { int r; + assert(s); if (s->result == SOCKET_SUCCESS) @@ -2094,13 +2100,7 @@ static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) { if (s->result == SOCKET_SUCCESS) s->result = f; - r = unit_kill_context( - UNIT(s), - &s->kill_context, - state_to_kill_operation(s, state), - /* main_pid= */ NULL, - &s->control_pid, - /* main_pid_alien= */ false); + r = unit_kill_context(UNIT(s), state_to_kill_operation(s, state)); if (r < 0) { log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m"); goto fail; @@ -2134,6 +2134,7 @@ fail: static void socket_enter_stop_pre(Socket *s, SocketResult f) { int r; + assert(s); if (s->result == SOCKET_SUCCESS) @@ -2160,6 +2161,7 @@ static void socket_enter_stop_pre(Socket *s, SocketResult f) { static void socket_enter_listening(Socket *s) { int r; + assert(s); if (!s->accept && s->flush_pending) { @@ -2179,6 +2181,7 @@ static void socket_enter_listening(Socket *s) { static void socket_enter_start_post(Socket *s) { int r; + assert(s); socket_unwatch_control_pid(s); @@ -2235,6 +2238,7 @@ fail: static void socket_enter_start_pre(Socket *s) { int r; + assert(s); socket_unwatch_control_pid(s); @@ -2278,7 +2282,6 @@ static void socket_enter_running(Socket *s, int cfd_in) { /* Note that this call takes possession of the connection fd passed. It either has to assign it * somewhere or close it. */ _cleanup_close_ int cfd = cfd_in; - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; @@ -2315,8 +2318,8 @@ static void socket_enter_running(Socket *s, int cfd_in) { if (!pending) { if (!UNIT_ISSET(s->service)) { - r = log_unit_warning_errno(UNIT(s), SYNTHETIC_ERRNO(ENOENT), - "Service to activate vanished, refusing activation."); + log_unit_warning(UNIT(s), + "Service to activate vanished, refusing activation."); goto fail; } @@ -2347,7 +2350,10 @@ static void socket_enter_running(Socket *s, int cfd_in) { if (r > 0 && p->n_ref > s->max_connections_per_source) { _cleanup_free_ char *t = NULL; - (void) sockaddr_pretty(&p->peer.sa, p->peer_salen, true, false, &t); + if (p->peer.sa.sa_family == AF_UNIX) + (void) asprintf(&t, "UID " UID_FMT, p->peer_cred.uid); + else + (void) sockaddr_pretty(&p->peer.sa, p->peer_salen, /* translate_ipv6= */ true, /* include_port= */ false, &t); log_unit_warning(UNIT(s), "Too many incoming connections (%u) from source %s, dropping connection.", @@ -2357,18 +2363,15 @@ static void socket_enter_running(Socket *s, int cfd_in) { } r = socket_load_service_unit(s, cfd, &service); - if (r < 0) { - if (ERRNO_IS_DISCONNECT(r)) - return; - - log_unit_warning_errno(UNIT(s), r, "Failed to load connection service unit: %m"); + if (ERRNO_IS_NEG_DISCONNECT(r)) + return; + if (r < 0 || UNIT_IS_LOAD_ERROR(service->load_state)) { + log_unit_warning_errno(UNIT(s), r < 0 ? r : service->load_error, + "Failed to load connection service unit: %m"); goto fail; } - - r = unit_add_two_dependencies(UNIT(s), UNIT_BEFORE, UNIT_TRIGGERS, service, - false, UNIT_DEPENDENCY_IMPLICIT); - if (r < 0) { - log_unit_warning_errno(UNIT(s), r, "Failed to add Before=/Triggers= dependencies on connection unit: %m"); + if (service->load_state == UNIT_MASKED) { + log_unit_warning(UNIT(s), "Connection service unit is masked, refusing."); goto fail; } @@ -2383,7 +2386,10 @@ static void socket_enter_running(Socket *s, int cfd_in) { goto fail; } - TAKE_FD(cfd); /* We passed ownership of the fd to the service now. Forget it here. */ + /* We passed ownership of the fd and socket peer to the service now. */ + TAKE_FD(cfd); + TAKE_PTR(p); + s->n_connections++; r = manager_add_job(UNIT(s)->manager, JOB_START, service, JOB_REPLACE, NULL, &error, NULL); @@ -2405,13 +2411,9 @@ refuse: return; queue_error: - if (ERRNO_IS_RESOURCE(r)) - log_unit_warning(UNIT(s), "Failed to queue service startup job: %s", - bus_error_message(&error, r)); - else - log_unit_warning(UNIT(s), "Failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s", - cfd >= 0 ? "template" : "non-template", - bus_error_message(&error, r)); + log_unit_warning_errno(UNIT(s), r, "Failed to queue service startup job%s: %s", + cfd >= 0 && !ERRNO_IS_RESOURCE(r) ? " (Maybe the service is missing or is a template unit?)" : "", + bus_error_message(&error, r)); fail: socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); @@ -2444,11 +2446,9 @@ static void socket_run_next(Socket *s) { } static int socket_start(Unit *u) { - Socket *s = SOCKET(u); + Socket *s = ASSERT_PTR(SOCKET(u)); int r; - assert(s); - /* We cannot fulfill this request right now, try again later * please! */ if (IN_SET(s->state, @@ -2496,16 +2496,15 @@ static int socket_start(Unit *u) { s->result = SOCKET_SUCCESS; exec_command_reset_status_list_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX); - u->reset_accounting = true; + if (s->cgroup_runtime) + s->cgroup_runtime->reset_accounting = true; socket_enter_start_pre(s); return 1; } static int socket_stop(Unit *u) { - Socket *s = SOCKET(u); - - assert(s); + Socket *s = ASSERT_PTR(SOCKET(u)); /* Already on it */ if (IN_SET(s->state, @@ -2540,10 +2539,9 @@ static int socket_stop(Unit *u) { } static int socket_serialize(Unit *u, FILE *f, FDSet *fds) { - Socket *s = SOCKET(u); + Socket *s = ASSERT_PTR(SOCKET(u)); int r; - assert(u); assert(f); assert(fds); @@ -2595,10 +2593,9 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) { } static int socket_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { - Socket *s = SOCKET(u); + Socket *s = ASSERT_PTR(SOCKET(u)); int r; - assert(u); assert(key); assert(value); @@ -2836,9 +2833,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, } static void socket_distribute_fds(Unit *u, FDSet *fds) { - Socket *s = SOCKET(u); - - assert(u); + Socket *s = ASSERT_PTR(SOCKET(u)); LIST_FOREACH(port, p, s->ports) { int fd; @@ -2860,15 +2855,15 @@ static void socket_distribute_fds(Unit *u, FDSet *fds) { } static UnitActiveState socket_active_state(Unit *u) { - assert(u); + Socket *s = ASSERT_PTR(SOCKET(u)); - return state_translation_table[SOCKET(u)->state]; + return state_translation_table[s->state]; } static const char *socket_sub_state_to_string(Unit *u) { - assert(u); + Socket *s = ASSERT_PTR(SOCKET(u)); - return socket_state_to_string(SOCKET(u)->state); + return socket_state_to_string(s->state); } int socket_port_to_address(const SocketPort *p, char **ret) { @@ -2906,7 +2901,6 @@ int socket_port_to_address(const SocketPort *p, char **ret) { } const char* socket_port_type_to_string(SocketPort *p) { - assert(p); switch (p->type) { @@ -2968,9 +2962,7 @@ SocketType socket_port_type_from_string(const char *s) { } static bool socket_may_gc(Unit *u) { - Socket *s = SOCKET(u); - - assert(u); + Socket *s = ASSERT_PTR(SOCKET(u)); return s->n_connections == 0; } @@ -3108,10 +3100,9 @@ fail: } static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) { - Socket *s = SOCKET(u); + Socket *s = ASSERT_PTR(SOCKET(u)); SocketResult f; - assert(s); assert(pid >= 0); if (pid != s->control_pid.pid) @@ -3215,9 +3206,8 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) { } static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) { - Socket *s = SOCKET(userdata); + Socket *s = ASSERT_PTR(SOCKET(userdata)); - assert(s); assert(s->timer_event_source == source); switch (s->state) { @@ -3289,12 +3279,11 @@ static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *use return 0; } -int socket_collect_fds(Socket *s, int **fds) { - size_t k = 0, n = 0; - int *rfds; +int socket_collect_fds(Socket *s, int **ret) { + size_t n = 0, k = 0; assert(s); - assert(fds); + assert(ret); /* Called from the service code for requesting our fds */ @@ -3304,25 +3293,25 @@ int socket_collect_fds(Socket *s, int **fds) { n += p->n_auxiliary_fds; } - if (n <= 0) { - *fds = NULL; + if (n == 0) { + *ret = NULL; return 0; } - rfds = new(int, n); - if (!rfds) + int *fds = new(int, n); + if (!fds) return -ENOMEM; LIST_FOREACH(port, p, s->ports) { if (p->fd >= 0) - rfds[k++] = p->fd; - for (size_t i = 0; i < p->n_auxiliary_fds; ++i) - rfds[k++] = p->auxiliary_fds[i]; + fds[k++] = p->fd; + FOREACH_ARRAY(i, p->auxiliary_fds, p->n_auxiliary_fds) + fds[k++] = *i; } assert(k == n); - *fds = rfds; + *ret = fds; return (int) n; } @@ -3353,9 +3342,8 @@ void socket_connection_unref(Socket *s) { } static void socket_trigger_notify(Unit *u, Unit *other) { - Socket *s = SOCKET(u); + Socket *s = ASSERT_PTR(SOCKET(u)); - assert(u); assert(other); /* Filter out invocations with bogus state */ @@ -3390,8 +3378,24 @@ static void socket_trigger_notify(Unit *u, Unit *other) { socket_set_state(s, SOCKET_RUNNING); } +static void socket_handoff_timestamp( + Unit *u, + const struct ucred *ucred, + const dual_timestamp *ts) { + + Socket *s = ASSERT_PTR(SOCKET(u)); + + assert(ucred); + assert(ts); + + if (s->control_pid.pid == ucred->pid && s->control_command) { + exec_status_handoff(&s->control_command->exec_status, ucred, ts); + unit_add_to_dbus_queue(u); + } +} + static int socket_get_timeout(Unit *u, usec_t *timeout) { - Socket *s = SOCKET(u); + Socket *s = ASSERT_PTR(SOCKET(u)); usec_t t; int r; @@ -3423,11 +3427,10 @@ static PidRef *socket_control_pid(Unit *u) { } static int socket_clean(Unit *u, ExecCleanMask mask) { + Socket *s = ASSERT_PTR(SOCKET(u)); _cleanup_strv_free_ char **l = NULL; - Socket *s = SOCKET(u); int r; - assert(s); assert(mask != 0); if (s->state != SOCKET_DEAD) @@ -3467,19 +3470,15 @@ fail: } static int socket_can_clean(Unit *u, ExecCleanMask *ret) { - Socket *s = SOCKET(u); - - assert(s); + Socket *s = ASSERT_PTR(SOCKET(u)); return exec_context_get_clean_mask(&s->exec_context, ret); } static int socket_can_start(Unit *u) { - Socket *s = SOCKET(u); + Socket *s = ASSERT_PTR(SOCKET(u)); int r; - assert(s); - r = unit_test_start_limit(u); if (r < 0) { socket_enter_dead(s, SOCKET_FAILURE_START_LIMIT_HIT); @@ -3494,7 +3493,7 @@ static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = { [SOCKET_EXEC_START_CHOWN] = "ExecStartChown", [SOCKET_EXEC_START_POST] = "ExecStartPost", [SOCKET_EXEC_STOP_PRE] = "ExecStopPre", - [SOCKET_EXEC_STOP_POST] = "ExecStopPost" + [SOCKET_EXEC_STOP_POST] = "ExecStopPost", }; DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand); @@ -3508,7 +3507,7 @@ static const char* const socket_result_table[_SOCKET_RESULT_MAX] = { [SOCKET_FAILURE_CORE_DUMP] = "core-dump", [SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit", [SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit", - [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit" + [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit", }; DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult); @@ -3552,6 +3551,7 @@ const UnitVTable socket_vtable = { .cgroup_context_offset = offsetof(Socket, cgroup_context), .kill_context_offset = offsetof(Socket, kill_context), .exec_runtime_offset = offsetof(Socket, exec_runtime), + .cgroup_runtime_offset = offsetof(Socket, cgroup_runtime), .sections = "Unit\0" @@ -3596,6 +3596,8 @@ const UnitVTable socket_vtable = { .reset_failed = socket_reset_failed, + .notify_handoff_timestamp = socket_handoff_timestamp, + .control_pid = socket_control_pid, .bus_set_property = bus_socket_set_property, |