From 6d75ccba6f2ebff3c3485f7e2dfceeda38c62c1b Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 5 Sep 2012 16:27:27 -0700 Subject: [PATCH] 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".) --- lib/ipc_us.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/ipc_us.c b/lib/ipc_us.c index bae1811..3549b9e 100644 --- a/lib/ipc_us.c +++ b/lib/ipc_us.c @@ -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);