diff options
author | Andi Kleen <ak@linux.intel.com> | 2017-06-02 13:05:24 -0700 |
---|---|---|
committer | Andi Kleen <ak@linux.intel.com> | 2017-06-02 13:05:24 -0700 |
commit | def5f22ab7f2134a7bdd82f70ff0c1ef16fe3731 (patch) | |
tree | b712b530934281f4d7e0bcd662f8ff2d983762e9 | |
parent | f8f1490cb2c6754aa108779e04fa2f099e394895 (diff) | |
download | mcelog-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.c | 6 |
1 files changed, 6 insertions, 0 deletions
@@ -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; |