mirror of
https://github.com/systemd/systemd.git
synced 2026-11-06 05:17:24 +00:00
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:
1 parent
efc430cae2
commit
67ffd130ea
7 files changed
+46
-66
No files matched your search
+17
-29
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) &&
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user