tree-wide: use getsockopt_int() where appropriate

Replace open-coded getsockopt() calls for int-typed socket options
(SO_TYPE, SO_PROTOCOL, SO_DOMAIN, SO_ACCEPTCONN, SO_ERROR, SO_SNDBUF,
SO_RCVBUF) with getsockopt_int(), which also validates the returned
size.

This also fixes an operator precedence issue in fd_set_sndbuf() and
fd_set_rcvbuf(): "r >= 0 && l == sizeof(value) && increase ? a : b"
parses as "(r >= 0 && l == sizeof(value) && increase) ? a : b", hence
with increase=false the possibly uninitialized value was compared even
if getsockopt() failed.
This commit is contained in:
Lennart Poettering authored and Lennart Poettering committed 2026-11-05 21:59:57 +01:00
1 parent efc430cae2
commit 67ffd130ea
7 files changed
+46 -66

No files matched your search

+17 -29
View File
@@ -331,7 +331,6 @@ bool socket_ipv6_is_enabled(void) {
bool socket_address_matches_fd(const SocketAddress *a, int fd) {
SocketAddress b;
socklen_t solen;
assert(a);
assert(fd >= 0);
@@ -343,16 +342,14 @@ bool socket_address_matches_fd(const SocketAddress *a, int fd) {
if (b.sockaddr.sa.sa_family != a->sockaddr.sa.sa_family)
return false;
solen = sizeof(b.type);
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &b.type, &solen) < 0)
if (getsockopt_int(fd, SOL_SOCKET, SO_TYPE, &b.type) < 0)
return false;
if (b.type != a->type)
return false;
if (a->protocol != 0) {
solen = sizeof(b.protocol);
if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &b.protocol, &solen) < 0)
if (getsockopt_int(fd, SOL_SOCKET, SO_PROTOCOL, &b.protocol) < 0)
return false;
if (b.protocol != a->protocol)
@@ -699,13 +696,12 @@ bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b
int fd_set_sndbuf(int fd, size_t n, bool increase) {
int r, value;
socklen_t l = sizeof(value);
if (n > INT_MAX)
return -ERANGE;
r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
if (getsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, &value) >= 0 &&
(increase ? (size_t) value >= n*2 : (size_t) value == n*2))
return 0;
/* First, try to set the buffer size with SO_SNDBUF. */
@@ -715,9 +711,8 @@ int fd_set_sndbuf(int fd, size_t n, bool increase) {
/* SO_SNDBUF above may set to the kernel limit, instead of the requested size.
* So, we need to check the actual buffer size here. */
l = sizeof(value);
r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
if (getsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, &value) >= 0 &&
(increase ? (size_t) value >= n*2 : (size_t) value == n*2))
return 1;
/* If we have the privileges we will ignore the kernel limit. */
@@ -730,13 +725,12 @@ int fd_set_sndbuf(int fd, size_t n, bool increase) {
int fd_set_rcvbuf(int fd, size_t n, bool increase) {
int r, value;
socklen_t l = sizeof(value);
if (n > INT_MAX)
return -ERANGE;
r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
if (getsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, &value) >= 0 &&
(increase ? (size_t) value >= n*2 : (size_t) value == n*2))
return 0;
/* First, try to set the buffer size with SO_RCVBUF. */
@@ -746,9 +740,8 @@ int fd_set_rcvbuf(int fd, size_t n, bool increase) {
/* SO_RCVBUF above may set to the kernel limit, instead of the requested size.
* So, we need to check the actual buffer size here. */
l = sizeof(value);
r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
if (getsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, &value) >= 0 &&
(increase ? (size_t) value >= n*2 : (size_t) value == n*2))
return 1;
/* If we have the privileges we will ignore the kernel limit. */
@@ -1141,15 +1134,13 @@ fallback:
int flush_accept(int fd) {
int r, b;
socklen_t l = sizeof(b);
/* Similar to flush_fd() but flushes all incoming connections by accepting and immediately closing
* them. */
if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &b, &l) < 0)
return -errno;
assert(l == sizeof(b));
r = getsockopt_int(fd, SOL_SOCKET, SO_ACCEPTCONN, &b);
if (r < 0)
return r;
if (!b) /* Let's check if this socket accepts connections before calling accept(). accept4() can
* return EOPNOTSUPP if the fd is not a listening socket, which we should treat as a fatal
* error, or in case the incoming TCP connection triggered a network issue, which we want to
@@ -1493,14 +1484,11 @@ ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags) {
}
int socket_get_family(int fd) {
int af;
socklen_t sl = sizeof(af);
int af, r;
if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &af, &sl) < 0)
return -errno;
if (sl != sizeof(af))
return -EINVAL;
r = getsockopt_int(fd, SOL_SOCKET, SO_DOMAIN, &af);
if (r < 0)
return r;
return af;
}
+3 -3
View File
@@ -26,6 +26,7 @@
#include "path-util.h"
#include "process-util.h"
#include "random-util.h"
#include "socket-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "time-util.h"
@@ -1476,7 +1477,6 @@ int bus_socket_read_message(sd_bus *bus) {
int bus_socket_process_opening(sd_bus *b) {
int error = 0, events, r;
socklen_t slen = sizeof(error);
assert(b->state == BUS_OPENING);
@@ -1488,9 +1488,9 @@ int bus_socket_process_opening(sd_bus *b) {
if (!(events & (POLLOUT|POLLERR|POLLHUP)))
return 0;
r = getsockopt(b->output_fd, SOL_SOCKET, SO_ERROR, &error, &slen);
r = getsockopt_int(b->output_fd, SOL_SOCKET, SO_ERROR, &error);
if (r < 0)
b->last_connect_error = errno;
b->last_connect_error = -r;
else if (error != 0)
b->last_connect_error = error;
else if (events & (POLLERR|POLLHUP))
+9 -14
View File
@@ -210,6 +210,7 @@ _public_ int sd_is_special(int fd, const char *path) {
static int is_socket_internal(int fd, int type, int listening) {
struct stat st_fd;
int r;
assert_return(fd >= 0, -EBADF);
assert_return(type >= 0, -EINVAL);
@@ -221,28 +222,22 @@ static int is_socket_internal(int fd, int type, int listening) {
return 0;
if (type != 0) {
int other_type = 0;
socklen_t l = sizeof(other_type);
int other_type;
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
return -errno;
if (l != sizeof(other_type))
return -EINVAL;
r = getsockopt_int(fd, SOL_SOCKET, SO_TYPE, &other_type);
if (r < 0)
return r;
if (other_type != type)
return 0;
}
if (listening >= 0) {
int accepting = 0;
socklen_t l = sizeof(accepting);
int accepting;
if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
return -errno;
if (l != sizeof(accepting))
return -EINVAL;
r = getsockopt_int(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting);
if (r < 0)
return r;
if (!accepting != !listening)
return 0;
+2 -2
View File
@@ -10,6 +10,7 @@
#include "event-util.h"
#include "fd-util.h"
#include "pidref.h"
#include "socket-util.h"
#include "time-util.h"
int event_source_inherit_fiber_priority(sd_event_source *s) {
@@ -68,9 +69,8 @@ static int io_handler(sd_event_source *s, int fd, uint32_t revents, void *userda
* directly without re-querying. */
if (FLAGS_SET(revents, EPOLLERR)) {
int error = 0;
socklen_t len = sizeof(error);
int r = RET_NERRNO(getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len));
int r = getsockopt_int(fd, SOL_SOCKET, SO_ERROR, &error);
if (r == -ENOTSOCK)
return sd_future_resolve(f, (int) revents);
if (r >= 0 && error != 0)
+6 -10
View File
@@ -3852,17 +3852,15 @@ _public_ int sd_varlink_server_listen_name(sd_varlink_server *s, const char *nam
for (int i = 0; i < m; i++) {
int b, fd;
socklen_t l = sizeof(b);
if (!streq(names[i], name))
continue;
fd = SD_LISTEN_FDS_START + i;
if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &b, &l) < 0)
return -errno;
assert(l == sizeof(b));
r = getsockopt_int(fd, SOL_SOCKET, SO_ACCEPTCONN, &b);
if (r < 0)
return r;
if (b) /* Listening socket? */
r = sd_varlink_server_listen_fd(s, fd);
@@ -4323,7 +4321,6 @@ _public_ int sd_varlink_server_set_description(sd_varlink_server *s, const char
_public_ int sd_varlink_invocation(sd_varlink_invocation_flags_t flags) {
_cleanup_strv_free_ char **names = NULL;
int r, b;
socklen_t l = sizeof(b);
/* Returns true if this is a "pure" varlink server invocation, i.e. with one fd passed. */
@@ -4348,10 +4345,9 @@ _public_ int sd_varlink_invocation(sd_varlink_invocation_flags_t flags) {
if ((flags & (SD_VARLINK_ALLOW_LISTEN|SD_VARLINK_ALLOW_ACCEPT)) == 0) /* Neither is set, then fail */
return -EISCONN;
if (getsockopt(SD_LISTEN_FDS_START, SOL_SOCKET, SO_ACCEPTCONN, &b, &l) < 0)
return -errno;
assert(l == sizeof(b));
r = getsockopt_int(SD_LISTEN_FDS_START, SOL_SOCKET, SO_ACCEPTCONN, &b);
if (r < 0)
return r;
if (!FLAGS_SET(flags, b ? SD_VARLINK_ALLOW_LISTEN : SD_VARLINK_ALLOW_ACCEPT))
return -EISCONN;
+5 -3
View File
@@ -16,6 +16,7 @@
#include "resolved-dns-stream.h"
#include "resolved-manager.h"
#include "set.h"
#include "socket-util.h"
#include "time-util.h"
#define DNS_STREAMS_MAX 128
@@ -333,9 +334,10 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use
}
if (revents & EPOLLERR) {
socklen_t errlen = sizeof(r);
if (getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &r, &errlen) == 0)
return dns_stream_complete(s, r);
int error;
if (getsockopt_int(s->fd, SOL_SOCKET, SO_ERROR, &error) >= 0)
return dns_stream_complete(s, error);
}
if ((revents & EPOLLOUT) &&
+4 -5
View File
@@ -270,15 +270,14 @@ static int connection_complete(Connection *c) {
static int connect_cb(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
Connection *c = ASSERT_PTR(userdata);
socklen_t solen;
int error;
int error, r;
assert(s);
assert(fd >= 0);
solen = sizeof(error);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &solen) < 0) {
log_error_errno(errno, "Failed to issue SO_ERROR: %m");
r = getsockopt_int(fd, SOL_SOCKET, SO_ERROR, &error);
if (r < 0) {
log_error_errno(r, "Failed to issue SO_ERROR: %m");
goto fail;
}