ipc_us: on Linux, set SO_PASSCRED on the sending socket too

Linux doesn't pass credential information by default, only when it has
been specifically requested with SO_PASSCRED.  This means there's a
race between when the ipc server side has set up and is listening on the
socket, and when the client may connect; if the client connects and sends
its first message before the server has set SO_PASSCRED on the socket,
then there will be no ucred information associated with the message.

The fix is to set SO_PASSCRED on the client socket as well, so that
the message will always have a ucred associated with it when the server
reads it.

Without this change, around 1% of cpg_model_initialize() calls fail
with CS_ERR_ACCESS.

(This Linux behaviour was introduced just on a year ago in
16e5726269611b71c930054ffe9b858c1cea88eb "af_unix: dont send
SCM_CREDENTIALS by default".)
This commit is contained in:
Jeremy Fitzhardinge 2012-09-05 16:27:27 -07:00
parent b79f8ceb1e
commit 6d75ccba6f

View File

@ -407,12 +407,20 @@ qb_ipcc_us_setup_connect(struct qb_ipcc_connection *c,
{
int32_t res;
struct qb_ipc_connection_request request;
#ifdef QB_LINUX
int off = 0;
int on = 1;
#endif
res = qb_ipcc_us_sock_connect(c->name, &c->setup.u.us.sock);
if (res != 0) {
return res;
}
#ifdef QB_LINUX
setsockopt(c->setup.u.us.sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
#endif
memset(&request, 0, sizeof(request));
request.hdr.id = QB_IPC_MSG_AUTHENTICATE;
request.hdr.size = sizeof(request);
@ -423,6 +431,10 @@ qb_ipcc_us_setup_connect(struct qb_ipcc_connection *c,
return res;
}
#ifdef QB_LINUX
setsockopt(c->setup.u.us.sock, SOL_SOCKET, SO_PASSCRED, &off, sizeof(off));
#endif
res =
qb_ipc_us_recv(&c->setup, r,
sizeof(struct qb_ipc_connection_response), -1);