aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2017-06-02 13:05:24 -0700
committerAndi Kleen <ak@linux.intel.com>2017-06-02 13:05:24 -0700
commitdef5f22ab7f2134a7bdd82f70ff0c1ef16fe3731 (patch)
treeb712b530934281f4d7e0bcd662f8ff2d983762e9
parentf8f1490cb2c6754aa108779e04fa2f099e394895 (diff)
downloadmcelog-def5f22ab7f2134a7bdd82f70ff0c1ef16fe3731.tar.gz
Set SO_PASSCRED on listen socketsv152
Report from Oleksiy Kovyrin in https://github.com/andikleen/mcelog/issues/53 There is an issue on systems with linux systems running kernel XXX or higher (any kernels where https://android.googlesource.com/kernel/common.git/+/16e5726269611b71c930054ffe9b858c1cea88eb has been applied). Mcelog client randomly fails with a "permission denied" error. Here is how it happens: mcelog daemon creates a unix streaming socket with listen() mcelog client connects to it mcelog daemon calls accept() mcelog daemon calls setsockopt(SO_PASSCRED) and asks the kernel to pass uid/gid of the client mcelog client sends its commands mcelog daemon receives commands, checks uid to be 0, responds, all good It is all good when it works, but there is a race between steps 4 and 5. If the client is too fast, the message arrives without credentials and kernel just sets uid=nobody. Mcelog daemon checks that and denies the request. After the initial commit to linux, there has been a fix in 90c6bd34f884cd9cee21f1d152baf6c18bcac949 (described here: https://lists.ubuntu.com/archives/kernel-team/2013-October/033188.html), that, if mcelog code is changed to set SO_PASSCRED on the listen socket, would fix the race. --- Fix by also setting SO_PASSCRED on the listen socket, but not check for errors here. Signed-off-by: Andi Kleen <ak@linux.intel.com>
-rw-r--r--server.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/server.c b/server.c
index 5b56d29..86029c5 100644
--- a/server.c
+++ b/server.c
@@ -322,6 +322,7 @@ void server_setup(void)
{
int fd;
struct sockaddr_un adr;
+ int on;
server_config();
@@ -360,6 +361,11 @@ void server_setup(void)
listen(fd, 10);
+ /* Set SO_PASSCRED to avoid race with client connecting too fast */
+ /* Ignore error for old kernels */
+ on = 1;
+ setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
+
register_pollcb(fd, POLLIN, client_accept, NULL);
return;