summaryrefslogtreecommitdiffstats
path: root/libcutils/uevent.cpp
diff options
context:
space:
mode:
authorDaniel Mentz <danielmentz@google.com>2018-11-27 11:00:29 -0800
committerDaniel Mentz <danielmentz@google.com>2018-12-03 18:39:24 +0000
commit41aa2c3703ece8c7e8f869dbb74aaf68aeca2310 (patch)
treed462f0a1d7b9110b6e83768328c79b04bac2def1 /libcutils/uevent.cpp
parent67fe6f09d571401f5aff8c4ad4f814cb95089366 (diff)
downloadsystem_core-41aa2c3703ece8c7e8f869dbb74aaf68aeca2310.tar.gz
system_core-41aa2c3703ece8c7e8f869dbb74aaf68aeca2310.tar.bz2
system_core-41aa2c3703ece8c7e8f869dbb74aaf68aeca2310.zip
Increase netlink uevent rcvbuf size to 16M
Increase size of the NETLINK_KOBJECT_UEVENT socket receive buffer to 16M. Also, use SO_RCVBUFFORCE to override any limits set by /proc/sys/net/core/rmem_max. We had a couple of instances, where we lost critical uevent messages due to receive buffer overflows. Bug: 119933843 Change-Id: I6aab183aa0194e173f9175b47c6beb0835cf6675
Diffstat (limited to 'libcutils/uevent.cpp')
-rw-r--r--libcutils/uevent.cpp16
1 files changed, 14 insertions, 2 deletions
diff --git a/libcutils/uevent.cpp b/libcutils/uevent.cpp
index 2dfceede5..721de7c47 100644
--- a/libcutils/uevent.cpp
+++ b/libcutils/uevent.cpp
@@ -95,6 +95,8 @@ out:
int uevent_open_socket(int buf_sz, bool passcred) {
struct sockaddr_nl addr;
int on = passcred;
+ int buf_sz_readback = 0;
+ socklen_t optlen = sizeof(buf_sz_readback);
int s;
memset(&addr, 0, sizeof(addr));
@@ -105,11 +107,21 @@ int uevent_open_socket(int buf_sz, bool passcred) {
s = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
if (s < 0) return -1;
- /* buf_sz should be less than net.core.rmem_max for this to succeed */
- if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buf_sz, sizeof(buf_sz)) < 0) {
+ if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buf_sz, sizeof(buf_sz)) < 0 ||
+ getsockopt(s, SOL_SOCKET, SO_RCVBUF, &buf_sz_readback, &optlen) < 0) {
close(s);
return -1;
}
+ /* Only if SO_RCVBUF was not effective, try SO_RCVBUFFORCE. Generally, we
+ * want to avoid SO_RCVBUFFORCE, because it generates SELinux denials in
+ * case we don't have CAP_NET_ADMIN. This is the case, for example, for
+ * healthd. */
+ if (buf_sz_readback < 2 * buf_sz) {
+ if (setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &buf_sz, sizeof(buf_sz)) < 0) {
+ close(s);
+ return -1;
+ }
+ }
setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));