diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2022-05-14 04:59:56 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-14 04:59:56 +0900 |
commit | bdaf5c3df6ba2f374ef3be73cd2520d42ea677ac (patch) | |
tree | 90cc6fe9e2c3402b2d843c92e6840f78b9790080 | |
parent | 3881fd406b13746336c6c654fd2f68261161fd8a (diff) | |
parent | a98042e7a3a6d81e0cdb256458695a82f6dcafd3 (diff) | |
download | systemd-bdaf5c3df6ba2f374ef3be73cd2520d42ea677ac.tar.gz |
Merge pull request #23369 from yuwata/error-handling-fixlets
Several fixlets
-rw-r--r-- | src/basic/fileio.c | 4 | ||||
-rw-r--r-- | src/basic/socket-util.c | 5 | ||||
-rw-r--r-- | src/test/test-socket-util.c | 47 | ||||
-rw-r--r-- | src/userdb/userdbctl.c | 2 |
4 files changed, 54 insertions, 4 deletions
diff --git a/src/basic/fileio.c b/src/basic/fileio.c index e7b670ab2e..c2497ff856 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -776,7 +776,7 @@ int read_full_file_full( /* Seeking is not supported on AF_UNIX sockets */ if (offset != UINT64_MAX) - return -ESPIPE; + return -ENXIO; if (dir_fd == AT_FDCWD) r = sockaddr_un_set_path(&sa.un, filename); @@ -809,7 +809,7 @@ int read_full_file_full( return r; if (bind(sk, &bsa.sa, r) < 0) - return r; + return -errno; } if (connect(sk, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 8d0494ece5..0dfe2a7dbc 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -1236,7 +1236,10 @@ int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path) { * addresses!), which the kernel doesn't. We do this to reduce chance of incompatibility with other apps that * do not expect non-NUL terminated file system path. */ if (l+1 > sizeof(ret->sun_path)) - return -EINVAL; + return path[0] == '@' ? -EINVAL : -ENAMETOOLONG; /* return a recognizable error if this is + * too long to fit into a sockaddr_un, but + * is a file system path, and thus might be + * connectible via O_PATH indirection. */ *ret = (struct sockaddr_un) { .sun_family = AF_UNIX, diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c index 3245516f9a..cd1e374ec8 100644 --- a/src/test/test-socket-util.c +++ b/src/test/test-socket-util.c @@ -2,6 +2,7 @@ #include <fcntl.h> #include <grp.h> +#include <net/if_arp.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -11,11 +12,15 @@ #include "escape.h" #include "exit-status.h" #include "fd-util.h" +#include "fs-util.h" #include "in-addr-util.h" #include "io-util.h" #include "log.h" #include "macro.h" +#include "path-util.h" #include "process-util.h" +#include "random-util.h" +#include "rm-rf.h" #include "socket-util.h" #include "string-util.h" #include "tests.h" @@ -478,4 +483,46 @@ TEST(ipv6_enabled) { log_info("IPv6 enabled: %s", yes_no(socket_ipv6_is_enabled())); } +TEST(sockaddr_un_set_path) { + _cleanup_(rm_rf_physical_and_freep) char *t = NULL; + _cleanup_(unlink_and_freep) char *sh = NULL; + _cleanup_free_ char *j = NULL; + union sockaddr_union sa; + _cleanup_close_ int fd1 = -1, fd2 = -1, fd3 = -1; + + assert_se(mkdtemp_malloc("/tmp/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaXXXXXX", &t) >= 0); + assert_se(strlen(t) > SUN_PATH_LEN); + + assert_se(j = path_join(t, "sock")); + assert_se(sockaddr_un_set_path(&sa.un, j) == -ENAMETOOLONG); /* too long for AF_UNIX socket */ + + assert_se(asprintf(&sh, "/tmp/%" PRIx64, random_u64()) >= 0); + assert_se(symlink(t, sh) >= 0); /* create temporary symlink, to access it anyway */ + + free(j); + assert_se(j = path_join(sh, "sock")); + assert_se(sockaddr_un_set_path(&sa.un, j) >= 0); + + fd1 = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); + assert_se(fd1 >= 0); + assert_se(bind(fd1, &sa.sa, SOCKADDR_LEN(sa)) >= 0); + assert_se(listen(fd1, 1) >= 0); + + sh = unlink_and_free(sh); /* remove temporary symlink */ + + fd2 = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); + assert_se(fd2 >= 0); + assert_se(connect(fd2, &sa.sa, SOCKADDR_LEN(sa)) < 0); + assert_se(errno == ENOENT); /* we removed the symlink, must fail */ + + free(j); + assert_se(j = path_join(t, "sock")); + + fd3 = open(j, O_CLOEXEC|O_PATH|O_NOFOLLOW); + assert_se(fd3 > 0); + assert_se(sockaddr_un_set_path(&sa.un, FORMAT_PROC_FD_PATH(fd3)) >= 0); /* connect via O_PATH instead, circumventing 108ch limit */ + + assert_se(connect(fd2, &sa.sa, SOCKADDR_LEN(sa)) >= 0); +} + DEFINE_TEST_MAIN(LOG_DEBUG); diff --git a/src/userdb/userdbctl.c b/src/userdb/userdbctl.c index 9effb3c61e..eddbe765b0 100644 --- a/src/userdb/userdbctl.c +++ b/src/userdb/userdbctl.c @@ -957,7 +957,7 @@ static int display_services(int argc, char *argv[], void *userdata) { fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (fd < 0) - return log_error_errno(r, "Failed to allocate AF_UNIX/SOCK_STREAM socket: %m"); + return log_error_errno(errno, "Failed to allocate AF_UNIX/SOCK_STREAM socket: %m"); if (connect(fd, &sockaddr.sa, sockaddr_len) < 0) { no = strjoin("No (", errno_to_name(errno), ")"); |