diff options
| -rw-r--r-- | src/basic/socket-util.c | 184 | ||||
| -rw-r--r-- | src/basic/socket-util.h | 12 | ||||
| -rw-r--r-- | src/basic/terminal-util.c | 1 | ||||
| -rw-r--r-- | src/basic/util.c | 181 | ||||
| -rw-r--r-- | src/basic/util.h | 12 | ||||
| -rw-r--r-- | src/core/namespace.c | 1 | ||||
| -rw-r--r-- | src/libsystemd/sd-login/sd-login.c | 1 | ||||
| -rw-r--r-- | src/libsystemd/sd-netlink/sd-netlink.c | 1 | ||||
| -rw-r--r-- | src/nspawn/nspawn-expose-ports.c | 1 | ||||
| -rw-r--r-- | src/nspawn/nspawn.c | 1 | 
10 files changed, 201 insertions, 194 deletions
| diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 312512ba1d..684ac765f5 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -23,20 +23,22 @@  #include <errno.h>  #include <net/if.h>  #include <netdb.h> +#include <netinet/ip.h>  #include <stddef.h>  #include <stdio.h>  #include <string.h>  #include <sys/types.h>  #include <unistd.h> +#include "fd-util.h"  #include "fileio.h"  #include "formats-util.h"  #include "macro.h"  #include "missing.h"  #include "path-util.h" +#include "socket-util.h"  #include "string-util.h"  #include "util.h" -#include "socket-util.h"  int socket_address_parse(SocketAddress *a, const char *s) {          char *e, *n; @@ -749,3 +751,183 @@ bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b          return false;  } + +int fd_inc_sndbuf(int fd, size_t n) { +        int r, value; +        socklen_t l = sizeof(value); + +        r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l); +        if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) +                return 0; + +        /* If we have the privileges we will ignore the kernel limit. */ + +        value = (int) n; +        if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0) +                if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0) +                        return -errno; + +        return 1; +} + +int fd_inc_rcvbuf(int fd, size_t n) { +        int r, value; +        socklen_t l = sizeof(value); + +        r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l); +        if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) +                return 0; + +        /* If we have the privileges we will ignore the kernel limit. */ + +        value = (int) n; +        if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0) +                if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0) +                        return -errno; +        return 1; +} + +static const char* const ip_tos_table[] = { +        [IPTOS_LOWDELAY] = "low-delay", +        [IPTOS_THROUGHPUT] = "throughput", +        [IPTOS_RELIABILITY] = "reliability", +        [IPTOS_LOWCOST] = "low-cost", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff); + +int getpeercred(int fd, struct ucred *ucred) { +        socklen_t n = sizeof(struct ucred); +        struct ucred u; +        int r; + +        assert(fd >= 0); +        assert(ucred); + +        r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n); +        if (r < 0) +                return -errno; + +        if (n != sizeof(struct ucred)) +                return -EIO; + +        /* Check if the data is actually useful and not suppressed due +         * to namespacing issues */ +        if (u.pid <= 0) +                return -ENODATA; +        if (u.uid == UID_INVALID) +                return -ENODATA; +        if (u.gid == GID_INVALID) +                return -ENODATA; + +        *ucred = u; +        return 0; +} + +int getpeersec(int fd, char **ret) { +        socklen_t n = 64; +        char *s; +        int r; + +        assert(fd >= 0); +        assert(ret); + +        s = new0(char, n); +        if (!s) +                return -ENOMEM; + +        r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n); +        if (r < 0) { +                free(s); + +                if (errno != ERANGE) +                        return -errno; + +                s = new0(char, n); +                if (!s) +                        return -ENOMEM; + +                r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n); +                if (r < 0) { +                        free(s); +                        return -errno; +                } +        } + +        if (isempty(s)) { +                free(s); +                return -EOPNOTSUPP; +        } + +        *ret = s; +        return 0; +} + +int send_one_fd(int transport_fd, int fd, int flags) { +        union { +                struct cmsghdr cmsghdr; +                uint8_t buf[CMSG_SPACE(sizeof(int))]; +        } control = {}; +        struct msghdr mh = { +                .msg_control = &control, +                .msg_controllen = sizeof(control), +        }; +        struct cmsghdr *cmsg; + +        assert(transport_fd >= 0); +        assert(fd >= 0); + +        cmsg = CMSG_FIRSTHDR(&mh); +        cmsg->cmsg_level = SOL_SOCKET; +        cmsg->cmsg_type = SCM_RIGHTS; +        cmsg->cmsg_len = CMSG_LEN(sizeof(int)); +        memcpy(CMSG_DATA(cmsg), &fd, sizeof(int)); + +        mh.msg_controllen = CMSG_SPACE(sizeof(int)); +        if (sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags) < 0) +                return -errno; + +        return 0; +} + +int receive_one_fd(int transport_fd, int flags) { +        union { +                struct cmsghdr cmsghdr; +                uint8_t buf[CMSG_SPACE(sizeof(int))]; +        } control = {}; +        struct msghdr mh = { +                .msg_control = &control, +                .msg_controllen = sizeof(control), +        }; +        struct cmsghdr *cmsg, *found = NULL; + +        assert(transport_fd >= 0); + +        /* +         * Receive a single FD via @transport_fd. We don't care for +         * the transport-type. We retrieve a single FD at most, so for +         * packet-based transports, the caller must ensure to send +         * only a single FD per packet.  This is best used in +         * combination with send_one_fd(). +         */ + +        if (recvmsg(transport_fd, &mh, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC | flags) < 0) +                return -errno; + +        CMSG_FOREACH(cmsg, &mh) { +                if (cmsg->cmsg_level == SOL_SOCKET && +                    cmsg->cmsg_type == SCM_RIGHTS && +                    cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { +                        assert(!found); +                        found = cmsg; +                        break; +                } +        } + +        if (!found) { +                cmsg_close_all(&mh); +                return -EIO; +        } + +        return *(int*) CMSG_DATA(found); +} diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index da1273e745..8b5410b391 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -115,3 +115,15 @@ int netlink_family_to_string_alloc(int b, char **s);  int netlink_family_from_string(const char *s) _pure_;  bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b); + +int fd_inc_sndbuf(int fd, size_t n); +int fd_inc_rcvbuf(int fd, size_t n); + +int ip_tos_to_string_alloc(int i, char **s); +int ip_tos_from_string(const char *s); + +int getpeercred(int fd, struct ucred *ucred); +int getpeersec(int fd, char **ret); + +int send_one_fd(int transport_fd, int fd, int flags); +int receive_one_fd(int transport_fd, int flags); diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 3b3ca775d0..7dfab0af62 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -36,6 +36,7 @@  #include "io-util.h"  #include "path-util.h"  #include "process-util.h" +#include "socket-util.h"  #include "string-util.h"  #include "terminal-util.h"  #include "time-util.h" diff --git a/src/basic/util.c b/src/basic/util.c index 010261b37d..2129d46aef 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -32,7 +32,6 @@  #include <linux/oom.h>  #include <linux/sched.h>  #include <locale.h> -#include <netinet/ip.h>  #include <poll.h>  #include <pwd.h>  #include <sched.h> @@ -2271,15 +2270,6 @@ static const char* const rlimit_table[_RLIMIT_MAX] = {  DEFINE_STRING_TABLE_LOOKUP(rlimit, int); -static const char* const ip_tos_table[] = { -        [IPTOS_LOWDELAY] = "low-delay", -        [IPTOS_THROUGHPUT] = "throughput", -        [IPTOS_RELIABILITY] = "reliability", -        [IPTOS_LOWCOST] = "low-cost", -}; - -DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff); -  bool kexec_loaded(void) {         bool loaded = false;         char *s; @@ -2362,41 +2352,6 @@ void* memdup(const void *p, size_t l) {          return r;  } -int fd_inc_sndbuf(int fd, size_t n) { -        int r, value; -        socklen_t l = sizeof(value); - -        r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l); -        if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) -                return 0; - -        /* If we have the privileges we will ignore the kernel limit. */ - -        value = (int) n; -        if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0) -                if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0) -                        return -errno; - -        return 1; -} - -int fd_inc_rcvbuf(int fd, size_t n) { -        int r, value; -        socklen_t l = sizeof(value); - -        r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l); -        if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) -                return 0; - -        /* If we have the privileges we will ignore the kernel limit. */ - -        value = (int) n; -        if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0) -                if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0) -                        return -errno; -        return 1; -} -  int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {          bool stdout_is_tty, stderr_is_tty;          pid_t parent_pid, agent_pid; @@ -3264,73 +3219,6 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int          return reset_uid_gid();  } -int getpeercred(int fd, struct ucred *ucred) { -        socklen_t n = sizeof(struct ucred); -        struct ucred u; -        int r; - -        assert(fd >= 0); -        assert(ucred); - -        r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n); -        if (r < 0) -                return -errno; - -        if (n != sizeof(struct ucred)) -                return -EIO; - -        /* Check if the data is actually useful and not suppressed due -         * to namespacing issues */ -        if (u.pid <= 0) -                return -ENODATA; -        if (u.uid == UID_INVALID) -                return -ENODATA; -        if (u.gid == GID_INVALID) -                return -ENODATA; - -        *ucred = u; -        return 0; -} - -int getpeersec(int fd, char **ret) { -        socklen_t n = 64; -        char *s; -        int r; - -        assert(fd >= 0); -        assert(ret); - -        s = new0(char, n); -        if (!s) -                return -ENOMEM; - -        r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n); -        if (r < 0) { -                free(s); - -                if (errno != ERANGE) -                        return -errno; - -                s = new0(char, n); -                if (!s) -                        return -ENOMEM; - -                r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n); -                if (r < 0) { -                        free(s); -                        return -errno; -                } -        } - -        if (isempty(s)) { -                free(s); -                return -EOPNOTSUPP; -        } - -        *ret = s; -        return 0; -} -  /* This is much like like mkostemp() but is subject to umask(). */  int mkostemp_safe(char *pattern, int flags) {          _cleanup_umask_ mode_t u; @@ -4342,75 +4230,6 @@ int fgetxattr_malloc(int fd, const char *name, char **value) {          }  } -int send_one_fd(int transport_fd, int fd, int flags) { -        union { -                struct cmsghdr cmsghdr; -                uint8_t buf[CMSG_SPACE(sizeof(int))]; -        } control = {}; -        struct msghdr mh = { -                .msg_control = &control, -                .msg_controllen = sizeof(control), -        }; -        struct cmsghdr *cmsg; - -        assert(transport_fd >= 0); -        assert(fd >= 0); - -        cmsg = CMSG_FIRSTHDR(&mh); -        cmsg->cmsg_level = SOL_SOCKET; -        cmsg->cmsg_type = SCM_RIGHTS; -        cmsg->cmsg_len = CMSG_LEN(sizeof(int)); -        memcpy(CMSG_DATA(cmsg), &fd, sizeof(int)); - -        mh.msg_controllen = CMSG_SPACE(sizeof(int)); -        if (sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags) < 0) -                return -errno; - -        return 0; -} - -int receive_one_fd(int transport_fd, int flags) { -        union { -                struct cmsghdr cmsghdr; -                uint8_t buf[CMSG_SPACE(sizeof(int))]; -        } control = {}; -        struct msghdr mh = { -                .msg_control = &control, -                .msg_controllen = sizeof(control), -        }; -        struct cmsghdr *cmsg, *found = NULL; - -        assert(transport_fd >= 0); - -        /* -         * Receive a single FD via @transport_fd. We don't care for -         * the transport-type. We retrieve a single FD at most, so for -         * packet-based transports, the caller must ensure to send -         * only a single FD per packet.  This is best used in -         * combination with send_one_fd(). -         */ - -        if (recvmsg(transport_fd, &mh, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC | flags) < 0) -                return -errno; - -        CMSG_FOREACH(cmsg, &mh) { -                if (cmsg->cmsg_level == SOL_SOCKET && -                    cmsg->cmsg_type == SCM_RIGHTS && -                    cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { -                        assert(!found); -                        found = cmsg; -                        break; -                } -        } - -        if (!found) { -                cmsg_close_all(&mh); -                return -EIO; -        } - -        return *(int*) CMSG_DATA(found); -} -  void nop_signal_handler(int sig) {          /* nothing here */  } diff --git a/src/basic/util.h b/src/basic/util.h index 7d6412523c..55b428fa63 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -330,9 +330,6 @@ int sched_policy_from_string(const char *s);  const char *rlimit_to_string(int i) _const_;  int rlimit_from_string(const char *s) _pure_; -int ip_tos_to_string_alloc(int i, char **s); -int ip_tos_from_string(const char *s); -  extern int saved_argc;  extern char **saved_argv; @@ -344,9 +341,6 @@ char *format_bytes(char *buf, size_t l, uint64_t t);  void* memdup(const void *p, size_t l) _alloc_(2); -int fd_inc_sndbuf(int fd, size_t n); -int fd_inc_rcvbuf(int fd, size_t n); -  int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...);  int setrlimit_closest(int resource, const struct rlimit *rlim); @@ -611,9 +605,6 @@ int container_get_leader(const char *machine, pid_t *pid);  int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd);  int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd); -int getpeercred(int fd, struct ucred *ucred); -int getpeersec(int fd, char **ret); -  int mkostemp_safe(char *pattern, int flags);  int open_tmpfile(const char *path, int flags); @@ -700,9 +691,6 @@ int mount_move_root(const char *path);  int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink);  int fgetxattr_malloc(int fd, const char *name, char **value); -int send_one_fd(int transport_fd, int fd, int flags); -int receive_one_fd(int transport_fd, int flags); -  void nop_signal_handler(int sig);  int version(void); diff --git a/src/core/namespace.c b/src/core/namespace.c index 470f384056..4d11d54bfe 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -36,6 +36,7 @@  #include "namespace.h"  #include "path-util.h"  #include "selinux-util.h" +#include "socket-util.h"  #include "string-util.h"  #include "strv.h"  #include "util.h" diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c index 6012004a0b..f564d43e06 100644 --- a/src/libsystemd/sd-login/sd-login.c +++ b/src/libsystemd/sd-login/sd-login.c @@ -36,6 +36,7 @@  #include "io-util.h"  #include "login-util.h"  #include "macro.h" +#include "socket-util.h"  #include "string-util.h"  #include "strv.h"  #include "user-util.h" diff --git a/src/libsystemd/sd-netlink/sd-netlink.c b/src/libsystemd/sd-netlink/sd-netlink.c index 57c5db1231..ba1f2a5a42 100644 --- a/src/libsystemd/sd-netlink/sd-netlink.c +++ b/src/libsystemd/sd-netlink/sd-netlink.c @@ -30,6 +30,7 @@  #include "missing.h"  #include "netlink-internal.h"  #include "netlink-util.h" +#include "socket-util.h"  #include "util.h"  static int sd_netlink_new(sd_netlink **ret) { diff --git a/src/nspawn/nspawn-expose-ports.c b/src/nspawn/nspawn-expose-ports.c index df9fbe185b..98e4a7682f 100644 --- a/src/nspawn/nspawn-expose-ports.c +++ b/src/nspawn/nspawn-expose-ports.c @@ -27,6 +27,7 @@  #include "local-addresses.h"  #include "netlink-util.h"  #include "nspawn-expose-ports.h" +#include "socket-util.h"  #include "string-util.h"  #include "util.h" diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index f01a376af8..6502fe1943 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -86,6 +86,7 @@  #include "seccomp-util.h"  #endif  #include "signal-util.h" +#include "socket-util.h"  #include "string-util.h"  #include "strv.h"  #include "terminal-util.h" | 
