]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/socket.c
tree-wide: introduce PIPE_EBADF macro
[thirdparty/systemd.git] / src / core / socket.c
index 81178e3de267e9d8f608247af89b772a3943ef15..409d415d8d99295a25164aa645110ebec6d29df8 100644 (file)
 #include "bus-error.h"
 #include "bus-util.h"
 #include "chase-symlinks.h"
+#include "constants.h"
 #include "copy.h"
 #include "dbus-socket.h"
 #include "dbus-unit.h"
-#include "def.h"
 #include "errno-list.h"
 #include "exit-status.h"
 #include "fd-util.h"
@@ -28,7 +28,7 @@
 #include "ip-protocol-list.h"
 #include "label.h"
 #include "log.h"
-#include "mkdir.h"
+#include "mkdir-label.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
@@ -109,8 +109,7 @@ static void socket_unwatch_control_pid(Socket *s) {
         if (s->control_pid <= 0)
                 return;
 
-        unit_unwatch_pid(UNIT(s), s->control_pid);
-        s->control_pid = 0;
+        unit_unwatch_pid(UNIT(s), TAKE_PID(s->control_pid));
 }
 
 static void socket_cleanup_fd_list(SocketPort *p) {
@@ -209,8 +208,6 @@ static int socket_arm_timer(Socket *s, usec_t usec) {
 }
 
 static bool have_non_accept_socket(Socket *s) {
-        SocketPort *p;
-
         assert(s);
 
         if (!s->accept)
@@ -229,7 +226,6 @@ static bool have_non_accept_socket(Socket *s) {
 }
 
 static int socket_add_mount_dependencies(Socket *s) {
-        SocketPort *p;
         int r;
 
         assert(s);
@@ -369,7 +365,6 @@ static int socket_add_extras(Socket *s) {
 
 static const char *socket_find_symlink_target(Socket *s) {
         const char *found = NULL;
-        SocketPort *p;
 
         LIST_FOREACH(port, p, s->ports) {
                 const char *f = NULL;
@@ -444,7 +439,7 @@ static int peer_address_compare_func(const SocketPeer *x, const SocketPeer *y) {
         if (r != 0)
                 return r;
 
-        switch(x->peer.sa.sa_family) {
+        switch (x->peer.sa.sa_family) {
         case AF_INET:
                 return memcmp(&x->peer.in.sin_addr, &y->peer.in.sin_addr, sizeof(x->peer.in.sin_addr));
         case AF_INET6:
@@ -464,10 +459,6 @@ static int socket_load(Unit *u) {
         assert(u);
         assert(u->load_state == UNIT_STUB);
 
-        r = set_ensure_allocated(&s->peers_by_address, &peer_address_hash_ops);
-        if (r < 0)
-                return r;
-
         r = unit_load_fragment_and_dropin(u, true);
         if (r < 0)
                 return r;
@@ -486,12 +477,13 @@ static int socket_load(Unit *u) {
 static SocketPeer *socket_peer_new(void) {
         SocketPeer *p;
 
-        p = new0(SocketPeer, 1);
+        p = new(SocketPeer, 1);
         if (!p)
                 return NULL;
 
-        p->n_ref = 1;
-
+        *p = (SocketPeer) {
+                .n_ref = 1,
+        };
         return p;
 }
 
@@ -508,14 +500,15 @@ DEFINE_TRIVIAL_REF_UNREF_FUNC(SocketPeer, socket_peer, socket_peer_free);
 
 int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) {
         _cleanup_(socket_peer_unrefp) SocketPeer *remote = NULL;
-        SocketPeer sa = {}, *i;
-        socklen_t salen = sizeof(sa.peer);
+        SocketPeer sa = {
+                .peer_salen = sizeof(union sockaddr_union),
+        }, *i;
         int r;
 
         assert(fd >= 0);
         assert(s);
 
-        if (getpeername(fd, &sa.peer.sa, &salen) < 0)
+        if (getpeername(fd, &sa.peer.sa, &sa.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)) {
@@ -523,6 +516,10 @@ int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) {
                 return 0;
         }
 
+        r = set_ensure_allocated(&s->peers_by_address, &peer_address_hash_ops);
+        if (r < 0)
+                return r;
+
         i = set_get(s->peers_by_address, &sa);
         if (i) {
                 *p = socket_peer_ref(i);
@@ -534,7 +531,7 @@ int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) {
                 return log_oom();
 
         remote->peer = sa.peer;
-        remote->peer_salen = salen;
+        remote->peer_salen = sa.peer_salen;
 
         r = set_put(s->peers_by_address, remote);
         if (r < 0)
@@ -543,7 +540,6 @@ int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) {
         remote->socket = s;
 
         *p = TAKE_PTR(remote);
-
         return 1;
 }
 
@@ -565,7 +561,6 @@ _const_ static const char* listen_lookup(int family, int type) {
 
 static void socket_dump(Unit *u, FILE *f, const char *prefix) {
         Socket *s = SOCKET(u);
-        SocketPort *p;
         const char *prefix2, *str;
 
         assert(s);
@@ -744,16 +739,14 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
                 switch (p->type) {
                 case SOCKET_SOCKET: {
                         _cleanup_free_ char *k = NULL;
-                        const char *t;
                         int r;
 
                         r = socket_address_print(&p->address, &k);
-                        if (r < 0)
-                                t = strerror_safe(r);
-                        else
-                                t = k;
-
-                        fprintf(f, "%s%s: %s\n", prefix, listen_lookup(socket_address_family(&p->address), p->address.type), t);
+                        if (r < 0) {
+                                errno = -r;
+                                fprintf(f, "%s%s: %m\n", prefix, listen_lookup(socket_address_family(&p->address), p->address.type));
+                        } else
+                                fprintf(f, "%s%s: %s\n", prefix, listen_lookup(socket_address_family(&p->address), p->address.type), k);
                         break;
                 }
                 case SOCKET_SPECIAL:
@@ -781,8 +774,6 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
                 fprintf(f, "%sSocketProtocol: %s\n", prefix, str);
 
         if (!strv_isempty(s->symlinks)) {
-                char **q;
-
                 fprintf(f, "%sSymlinks:", prefix);
                 STRV_FOREACH(q, s->symlinks)
                         fprintf(f, " %s", *q);
@@ -865,14 +856,12 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) {
                                      be16toh(remote.in6.sin6_port)) < 0)
                                 return -ENOMEM;
                 } else {
-                        char a[INET6_ADDRSTRLEN], b[INET6_ADDRSTRLEN];
-
                         if (asprintf(&r,
                                      "%u-%s:%u-%s:%u",
                                      nr,
-                                     inet_ntop(AF_INET6, &local.in6.sin6_addr, a, sizeof(a)),
+                                     IN6_ADDR_TO_STRING(&local.in6.sin6_addr),
                                      be16toh(local.in6.sin6_port),
-                                     inet_ntop(AF_INET6, &remote.in6.sin6_addr, b, sizeof(b)),
+                                     IN6_ADDR_TO_STRING(&remote.in6.sin6_addr),
                                      be16toh(remote.in6.sin6_port)) < 0)
                                 return -ENOMEM;
                 }
@@ -923,9 +912,6 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) {
 }
 
 static void socket_close_fds(Socket *s) {
-        SocketPort *p;
-        char **i;
-
         assert(s);
 
         LIST_FOREACH(port, p, s->ports) {
@@ -1130,7 +1116,7 @@ static int fifo_address_create(
                 mode_t directory_mode,
                 mode_t socket_mode) {
 
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
         mode_t old_mask;
         struct stat st;
         int r;
@@ -1186,7 +1172,7 @@ fail:
 }
 
 static int special_address_create(const char *path, bool writable) {
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
         struct stat st;
 
         assert(path);
@@ -1206,7 +1192,7 @@ static int special_address_create(const char *path, bool writable) {
 }
 
 static int usbffs_address_create(const char *path) {
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
         struct stat st;
 
         assert(path);
@@ -1231,7 +1217,7 @@ static int mq_address_create(
                 long maxmsg,
                 long msgsize) {
 
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
         struct stat st;
         mode_t old_mask;
         struct mq_attr _attr, *attr = NULL;
@@ -1271,7 +1257,6 @@ static int mq_address_create(
 
 static int socket_symlink(Socket *s) {
         const char *p;
-        char **i;
         int r;
 
         assert(s);
@@ -1295,7 +1280,8 @@ static int socket_symlink(Socket *s) {
                 }
 
                 if (r < 0)
-                        log_unit_warning_errno(UNIT(s), r, "Failed to create symlink %s → %s, ignoring: %m", p, *i);
+                        log_unit_warning_errno(UNIT(s), r, "Failed to create symlink %s %s %s, ignoring: %m",
+                                               p, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), *i);
         }
 
         return 0;
@@ -1421,39 +1407,40 @@ static int socket_determine_selinux_label(Socket *s, char **ret) {
         assert(s);
         assert(ret);
 
-        if (s->selinux_context_from_net) {
-                /* If this is requested, get the label from the network label */
+        Unit *service;
+        ExecCommand *c;
+        const char *exec_context;
+        _cleanup_free_ char *path = NULL;
 
-                r = mac_selinux_get_our_label(ret);
-                if (r == -EOPNOTSUPP)
-                        goto no_label;
+        r = socket_load_service_unit(s, -1, &service);
+        if (r == -ENODATA)
+                goto no_label;
+        if (r < 0)
+                return r;
 
-        } else {
-                /* Otherwise, get it from the executable we are about to start. */
+        exec_context = SERVICE(service)->exec_context.selinux_context;
+        if (exec_context) {
+                char *con;
 
-                Unit *service;
-                ExecCommand *c;
-                _cleanup_free_ char *path = NULL;
-
-                r = socket_load_service_unit(s, -1, &service);
-                if (r == -ENODATA)
-                        goto no_label;
-                if (r < 0)
-                        return r;
+                con = strdup(exec_context);
+                if (!con)
+                        return -ENOMEM;
 
-                c = SERVICE(service)->exec_command[SERVICE_EXEC_START];
-                if (!c)
-                        goto no_label;
+                *ret = TAKE_PTR(con);
+                return 0;
+        }
 
-                r = chase_symlinks(c->path, SERVICE(service)->exec_context.root_directory, CHASE_PREFIX_ROOT, &path, NULL);
-                if (r < 0)
-                        goto no_label;
+        c = SERVICE(service)->exec_command[SERVICE_EXEC_START];
+        if (!c)
+                goto no_label;
 
-                r = mac_selinux_get_create_label_from_exe(path, ret);
-                if (IN_SET(r, -EPERM, -EOPNOTSUPP))
-                        goto no_label;
-        }
+        r = chase_symlinks(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:
@@ -1515,7 +1502,7 @@ static int socket_address_listen_in_cgroup(
                 const SocketAddress *address,
                 const char *label) {
 
-        _cleanup_close_pair_ int pair[2] = { -1, -1 };
+        _cleanup_close_pair_ int pair[2] = PIPE_EBADF;
         int fd, r;
         pid_t pid;
 
@@ -1624,7 +1611,6 @@ static int socket_open_fds(Socket *orig_s) {
         _cleanup_(socket_close_fdsp) Socket *s = orig_s;
         _cleanup_(mac_selinux_freep) char *label = NULL;
         bool know_label = false;
-        SocketPort *p;
         int r;
 
         assert(s);
@@ -1734,7 +1720,6 @@ static int socket_open_fds(Socket *orig_s) {
 }
 
 static void socket_unwatch_fds(Socket *s) {
-        SocketPort *p;
         int r;
 
         assert(s);
@@ -1753,7 +1738,6 @@ static void socket_unwatch_fds(Socket *s) {
 }
 
 static int socket_watch_fds(Socket *s) {
-        SocketPort *p;
         int r;
 
         assert(s);
@@ -1791,7 +1775,6 @@ enum {
 
 static int socket_check_open(Socket *s) {
         bool have_open = false, have_closed = false;
-        SocketPort *p;
 
         assert(s);
 
@@ -1935,10 +1918,10 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
 
         _cleanup_(exec_params_clear) ExecParameters exec_params = {
                 .flags     = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN,
-                .stdin_fd  = -1,
-                .stdout_fd = -1,
-                .stderr_fd = -1,
-                .exec_fd   = -1,
+                .stdin_fd  = -EBADF,
+                .stdout_fd = -EBADF,
+                .stderr_fd = -EBADF,
+                .exec_fd   = -EBADF,
         };
         pid_t pid;
         int r;
@@ -1995,7 +1978,6 @@ static int socket_chown(Socket *s, pid_t *_pid) {
         if (r == 0) {
                 uid_t uid = UID_INVALID;
                 gid_t gid = GID_INVALID;
-                SocketPort *p;
 
                 /* Child */
 
@@ -2294,7 +2276,7 @@ fail:
 }
 
 static void flush_ports(Socket *s) {
-        SocketPort *p;
+        assert(s);
 
         /* Flush all incoming traffic, regardless if actual bytes or new connections, so that this socket isn't busy
          * anymore */
@@ -2401,7 +2383,7 @@ static void socket_enter_running(Socket *s, int cfd_in) {
 
                 s->n_accepted++;
 
-                r = service_set_socket_fd(SERVICE(service), cfd, s, s->selinux_context_from_net);
+                r = service_set_socket_fd(SERVICE(service), cfd, s, p, s->selinux_context_from_net);
                 if (ERRNO_IS_DISCONNECT(r))
                         return;
                 if (r < 0)
@@ -2410,8 +2392,6 @@ static void socket_enter_running(Socket *s, int cfd_in) {
                 TAKE_FD(cfd); /* We passed ownership of the fd to the service now. Forget it here. */
                 s->n_connections++;
 
-                SERVICE(service)->peer = TAKE_PTR(p); /* Pass ownership of the peer reference */
-
                 r = manager_add_job(UNIT(s)->manager, JOB_START, service, JOB_REPLACE, NULL, &error, NULL);
                 if (r < 0) {
                         /* We failed to activate the new service, but it still exists. Let's make sure the
@@ -2565,7 +2545,6 @@ static int socket_stop(Unit *u) {
 
 static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
         Socket *s = SOCKET(u);
-        SocketPort *p;
         int r;
 
         assert(u);
@@ -2676,7 +2655,6 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
                 }
         } else if (streq(key, "fifo")) {
                 int fd, skip = 0;
-                SocketPort *p;
 
                 if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
                         log_unit_debug(u, "Failed to parse fifo value: %s", value);
@@ -2697,7 +2675,6 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
 
         } else if (streq(key, "special")) {
                 int fd, skip = 0;
-                SocketPort *p;
 
                 if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
                         log_unit_debug(u, "Failed to parse special value: %s", value);
@@ -2718,7 +2695,6 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
 
         } else if (streq(key, "mqueue")) {
                 int fd, skip = 0;
-                SocketPort *p;
 
                 if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
                         log_unit_debug(u, "Failed to parse mqueue value: %s", value);
@@ -2739,7 +2715,6 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
 
         } else if (streq(key, "socket")) {
                 int fd, type, skip = 0;
-                SocketPort *p;
 
                 if (sscanf(value, "%i %i %n", &fd, &type, &skip) < 2 || fd < 0 || type < 0 || !fdset_contains(fds, fd))
                         log_unit_debug(u, "Failed to parse socket value: %s", value);
@@ -2760,7 +2735,6 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
 
         } else if (streq(key, "netlink")) {
                 int fd, skip = 0;
-                SocketPort *p;
 
                 if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
                         log_unit_debug(u, "Failed to parse socket value: %s", value);
@@ -2780,7 +2754,6 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
 
         } else if (streq(key, "ffs")) {
                 int fd, skip = 0;
-                SocketPort *p;
 
                 if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
                         log_unit_debug(u, "Failed to parse ffs value: %s", value);
@@ -2807,7 +2780,6 @@ 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);
-        SocketPort *p;
 
         assert(u);
 
@@ -2927,7 +2899,7 @@ static int socket_accept_do(Socket *s, int fd) {
 }
 
 static int socket_accept_in_cgroup(Socket *s, SocketPort *p, int fd) {
-        _cleanup_close_pair_ int pair[2] = { -1, -1 };
+        _cleanup_close_pair_ int pair[2] = PIPE_EBADF;
         int cfd, r;
         pid_t pid;
 
@@ -3005,10 +2977,9 @@ shortcut:
 }
 
 static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
-        SocketPort *p = userdata;
-        int cfd = -1;
+        SocketPort *p = ASSERT_PTR(userdata);
+        int cfd = -EBADF;
 
-        assert(p);
         assert(fd >= 0);
 
         if (p->socket->state != SOCKET_LISTENING)
@@ -3229,7 +3200,6 @@ static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *use
 
 int socket_collect_fds(Socket *s, int **fds) {
         size_t k = 0, n = 0;
-        SocketPort *p;
         int *rfds;
 
         assert(s);
@@ -3419,7 +3389,7 @@ static int socket_can_clean(Unit *u, ExecCleanMask *ret) {
         return exec_context_get_clean_mask(&s->exec_context, ret);
 }
 
-static int socket_test_start_limit(Unit *u) {
+static int socket_can_start(Unit *u) {
         Socket *s = SOCKET(u);
         int r;
 
@@ -3431,7 +3401,7 @@ static int socket_test_start_limit(Unit *u) {
                 return r;
         }
 
-        return 0;
+        return 1;
 }
 
 static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
@@ -3561,5 +3531,5 @@ const UnitVTable socket_vtable = {
                 },
         },
 
-        .test_start_limit = socket_test_start_limit,
+        .can_start = socket_can_start,
 };