From f43526f340c8a7fcfb14413fe675db53a266b801 Mon Sep 17 00:00:00 2001 From: Christine Caulfield Date: Thu, 24 Sep 2020 09:31:22 +0100 Subject: [PATCH 1/2] ipc: addd qb_ipcc_auth_get() API call We can't use SO_PEERCRED on the client fd when using socket IPC becayse it's a DGRAM socket (pacemaker tries this). So provide an API to get the server credentials that libqb has already squirreled away for its own purposes. Also, fix some unused-variable compiler warnings in unix.c when building on systems withpout posix_fallocate(). --- include/qb/qbipcc.h | 11 ++++++++ lib/ipc_int.h | 1 + lib/ipc_setup.c | 1 + lib/ipcc.c | 12 +++++++++ lib/unix.c | 4 ++- tests/check_ipc.c | 66 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 94 insertions(+), 1 deletion(-) diff --git a/include/qb/qbipcc.h b/include/qb/qbipcc.h index 5bf14cf83..de96c7289 100644 --- a/include/qb/qbipcc.h +++ b/include/qb/qbipcc.h @@ -109,6 +109,17 @@ void qb_ipcc_disconnect(qb_ipcc_connection_t* c); */ int32_t qb_ipcc_fd_get(qb_ipcc_connection_t* c, int32_t * fd); +/** + * Get the credentials of the server process + * + * + * @param c connection instance + * @param pid PID of the server we are connected to + * @param uid UID of the server we are connected to + * @param gid GID of the server we are connected to + */ +int32_t qb_ipcc_auth_get(qb_ipcc_connection_t* c, pid_t *pid, uid_t *uid, gid_t *gid); + /** * Set the maximum allowable flowcontrol value. * diff --git a/lib/ipc_int.h b/lib/ipc_int.h index 70f7d17a1..5772b78df 100644 --- a/lib/ipc_int.h +++ b/lib/ipc_int.h @@ -92,6 +92,7 @@ struct qb_ipcc_connection { char name[NAME_MAX]; int32_t needs_sock_for_poll; gid_t egid; + uid_t euid; pid_t server_pid; struct qb_ipc_one_way setup; struct qb_ipc_one_way request; diff --git a/lib/ipc_setup.c b/lib/ipc_setup.c index 23eeabb21..f5dec9faa 100644 --- a/lib/ipc_setup.c +++ b/lib/ipc_setup.c @@ -494,6 +494,7 @@ qb_ipcc_us_setup_connect(struct qb_ipcc_connection *c, qb_ipc_auth_creds(data); c->egid = data->ugp.gid; + c->euid = data->ugp.uid; c->server_pid = data->ugp.pid; destroy_ipc_auth_data(data); diff --git a/lib/ipcc.c b/lib/ipcc.c index e29209559..32463c3bd 100644 --- a/lib/ipcc.c +++ b/lib/ipcc.c @@ -366,6 +366,18 @@ qb_ipcc_fd_get(struct qb_ipcc_connection * c, int32_t * fd) return 0; } +int32_t +qb_ipcc_auth_get(struct qb_ipcc_connection * c, pid_t *pid, uid_t *uid, gid_t *gid) +{ + if (c == NULL || pid == NULL || uid == NULL || gid == NULL) { + return -EINVAL; + } + *pid = c->server_pid; + *uid = c->euid; + *gid = c->egid; + return 0; +} + ssize_t qb_ipcc_event_recv(struct qb_ipcc_connection * c, void *msg_pt, size_t msg_len, int32_t ms_timeout) diff --git a/lib/unix.c b/lib/unix.c index 327ccdf8a..5f84cdfca 100644 --- a/lib/unix.c +++ b/lib/unix.c @@ -74,10 +74,12 @@ qb_sys_mmap_file_open(char *path, const char *file, size_t bytes, uint32_t file_flags) { int32_t fd; - int32_t i; int32_t res = 0; +#ifndef HAVE_POSIX_FALLOCATE ssize_t written; char *buffer = NULL; + int32_t i; +#endif char *is_absolute = strchr(file, '/'); if (is_absolute) { diff --git a/tests/check_ipc.c b/tests/check_ipc.c index 345c2afde..e8f81f3ac 100644 --- a/tests/check_ipc.c +++ b/tests/check_ipc.c @@ -1105,6 +1105,49 @@ test_ipc_txrx(void) } } +static void +test_ipc_getauth(void) +{ + int32_t j; + int32_t c = 0; + pid_t pid; + pid_t spid; + uid_t suid; + gid_t sgid; + int res; + uint32_t max_size = MAX_MSG_SIZE; + + pid = run_function_in_new_process("server", run_ipc_server, NULL); + ck_assert(pid != -1); + + do { + conn = qb_ipcc_connect(ipc_name, max_size); + if (conn == NULL) { + j = waitpid(pid, NULL, WNOHANG); + ck_assert_int_eq(j, 0); + poll(NULL, 0, 400); + c++; + } + } while (conn == NULL && c < 5); + ck_assert(conn != NULL); + + res = qb_ipcc_auth_get(NULL, NULL, NULL, NULL); + ck_assert(res == -EINVAL); + + res = qb_ipcc_auth_get(conn, &spid, &suid, &sgid); + ck_assert(res == 0); +#ifndef HAVE_GETPEEREID + /* GETPEEREID doesn't return a PID */ + ck_assert(spid != 0); +#endif + ck_assert(suid == getuid()); + ck_assert(sgid == getgid()); + + request_server_exit(); + qb_ipcc_disconnect(conn); + verify_graceful_stop(pid); +} + static void test_ipc_exit(void) { @@ -1193,6 +1236,27 @@ START_TEST(test_ipc_txrx_us_timeout) } END_TEST + +START_TEST(test_ipc_txrx_shm_getauth) +{ + qb_enter(); + ipc_type = QB_IPC_SHM; + set_ipc_name(__func__); + test_ipc_getauth(); + qb_leave(); +} +END_TEST + +START_TEST(test_ipc_txrx_us_getauth) +{ + qb_enter(); + ipc_type = QB_IPC_SOCKET; + set_ipc_name(__func__); + test_ipc_getauth(); + qb_leave(); +} +END_TEST + START_TEST(test_ipc_txrx_shm_tmo) { qb_enter(); @@ -2213,6 +2277,7 @@ make_shm_suite(void) TCase *tc; Suite *s = suite_create("shm"); + add_tcase(s, tc, test_ipc_txrx_shm_getauth, 7); add_tcase(s, tc, test_ipc_txrx_shm_timeout, 28); add_tcase(s, tc, test_ipc_server_fail_shm, 7); add_tcase(s, tc, test_ipc_txrx_shm_block, 7); @@ -2243,6 +2308,7 @@ make_soc_suite(void) Suite *s = suite_create("socket"); TCase *tc; + add_tcase(s, tc, test_ipc_txrx_us_getauth, 7); add_tcase(s, tc, test_ipc_txrx_us_timeout, 28); /* Commented out for the moment as space in /dev/shm on the CI machines causes random failures */ From 2c9b9d4b028def5bb58358ef0cf2080ace87358d Mon Sep 17 00:00:00 2001 From: Christine Caulfield Date: Fri, 25 Sep 2020 10:19:13 +0100 Subject: [PATCH 2/2] ipcc: Some ufixes as recommended by Ken --- lib/ipc_int.h | 2 +- lib/ipcc.c | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/ipc_int.h b/lib/ipc_int.h index 5772b78df..03c5dabbb 100644 --- a/lib/ipc_int.h +++ b/lib/ipc_int.h @@ -92,7 +92,6 @@ struct qb_ipcc_connection { char name[NAME_MAX]; int32_t needs_sock_for_poll; gid_t egid; - uid_t euid; pid_t server_pid; struct qb_ipc_one_way setup; struct qb_ipc_one_way request; @@ -103,6 +102,7 @@ struct qb_ipcc_connection { uint32_t fc_enable_max; int32_t is_connected; void * context; + uid_t euid; }; int32_t qb_ipcc_us_setup_connect(struct qb_ipcc_connection *c, diff --git a/lib/ipcc.c b/lib/ipcc.c index 32463c3bd..a6cf409b6 100644 --- a/lib/ipcc.c +++ b/lib/ipcc.c @@ -369,12 +369,18 @@ qb_ipcc_fd_get(struct qb_ipcc_connection * c, int32_t * fd) int32_t qb_ipcc_auth_get(struct qb_ipcc_connection * c, pid_t *pid, uid_t *uid, gid_t *gid) { - if (c == NULL || pid == NULL || uid == NULL || gid == NULL) { + if (c == NULL) { return -EINVAL; } - *pid = c->server_pid; - *uid = c->euid; - *gid = c->egid; + if (pid) { + *pid = c->server_pid; + } + if (uid) { + *uid = c->euid; + } + if (gid) { + *gid = c->egid; + } return 0; }