summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2020-09-09 00:11:14 +0900
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-09-20 11:42:25 +0200
commite81f9924e838ea355387a32875e213d7bc758f23 (patch)
treea9fe4df726232aa5d31252a70bb54d8963e2c055
parentb500049b961e185fcb2ab0bb5f92a058c5b578e3 (diff)
downloadsystemd-e81f9924e838ea355387a32875e213d7bc758f23.tar.gz
util: try to set with SO_{RCV,SND}BUFFORCE when requested size is larger than the kernel limit
The commit 10ce2e0681ac16e7bb3619b7bb1a72a6f98a2f2c 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 #14417. (cherry picked from commit b92f350789e33942be0cf85af22a580c1fd483d6) (cherry picked from commit 4dcae666889ae9469e4406c0bcaffadbc01c4f66)
-rw-r--r--src/basic/socket-util.c40
1 files changed, 28 insertions, 12 deletions
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index 4c12888381..f54b8b4275 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -627,13 +627,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;
}
@@ -649,13 +657,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;
}