Skip to content

Commit

Permalink
util: try to set with SO_{RCV,SND}BUFFORCE when requested size is lar…
Browse files Browse the repository at this point in the history
…ger than the kernel limit

The commit 10ce2e0 inverts the order of
SO_{RCV,SND}BUFFORCE and SO_{RCV,SND}BUF. However, setting buffer size with
SO_{RCV,SND}BUF does not fail even if the requested size is larger than
the kernel limit. Hence, SO_{RCV,SND}BUFFORCE will not use anymore and
the buffer size is always limited by the kernel limit even if we have
the priviledge to ignore the limit.

This makes the buffer size is checked after configuring it with
SO_{RCV,SND}BUF, and if it is still not sufficient, then try to set it
with FORCE command. With this commit, if we have enough priviledge, the
requested buffer size is correctly set.

Hopefully fixes systemd#14417.
  • Loading branch information
yuwata authored and ssahani committed Oct 5, 2020
1 parent 74296cc commit 699c97e
Showing 1 changed file with 28 additions and 12 deletions.
40 changes: 28 additions & 12 deletions src/basic/socket-util.c
Expand Up @@ -628,13 +628,21 @@ int fd_inc_sndbuf(int fd, size_t n) {
if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
return 0;

/* If we have the privileges we will ignore the kernel limit. */
/* First, try to set the buffer size with SO_SNDBUF. */
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n);
if (r < 0)
return r;

if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n) < 0) {
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n);
if (r < 0)
return r;
}
/* SO_SNDBUF above may set to the kernel limit, instead of the requested size.
* So, we need to check the actual buffer size here. */
r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
return 1;

/* If we have the privileges we will ignore the kernel limit. */
r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n);
if (r < 0)
return r;

return 1;
}
Expand All @@ -650,13 +658,21 @@ int fd_inc_rcvbuf(int fd, size_t n) {
if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
return 0;

/* If we have the privileges we will ignore the kernel limit. */
/* First, try to set the buffer size with SO_RCVBUF. */
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n);
if (r < 0)
return r;

if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n) < 0) {
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n);
if (r < 0)
return r;
}
/* SO_RCVBUF above may set to the kernel limit, instead of the requested size.
* So, we need to check the actual buffer size here. */
r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
return 1;

/* If we have the privileges we will ignore the kernel limit. */
r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n);
if (r < 0)
return r;

return 1;
}
Expand Down

0 comments on commit 699c97e

Please sign in to comment.