632cf8
diff -urp libqb-1.0.3.orig/lib/ipc_shm.c libqb-1.0.3/lib/ipc_shm.c
632cf8
--- libqb-1.0.3.orig/lib/ipc_shm.c	2020-05-20 09:00:31.826899188 +0100
632cf8
+++ libqb-1.0.3/lib/ipc_shm.c	2020-05-20 09:11:56.607788472 +0100
632cf8
@@ -282,6 +282,8 @@ qb_ipcs_shm_connect(struct qb_ipcs_servi
632cf8
 		    struct qb_ipc_connection_response *r)
632cf8
 {
632cf8
 	int32_t res;
632cf8
+	char dirname[PATH_MAX];
632cf8
+	char *slash;
632cf8
 
632cf8
 	qb_util_log(LOG_DEBUG, "connecting to client [%d]", c->pid);
632cf8
 
632cf8
@@ -292,6 +294,14 @@ qb_ipcs_shm_connect(struct qb_ipcs_servi
632cf8
 	snprintf(r->event, NAME_MAX, "%s-event-%s",
632cf8
 		 c->description, s->name);
632cf8
 
632cf8
+	/* Set correct ownership if qb_ipcs_connection_auth_set() has been used */
632cf8
+	strlcpy(dirname, c->description, sizeof(dirname));
632cf8
+	slash = strrchr(dirname, '/');
632cf8
+	if (slash) {
632cf8
+		*slash = '\0';
632cf8
+		(void)chown(dirname, c->auth.uid, c->auth.gid);
632cf8
+	}
632cf8
+
632cf8
 	res = qb_ipcs_shm_rb_open(c, &c->request,
632cf8
 				  r->request);
632cf8
 	if (res != 0) {
632cf8
diff -urp libqb-1.0.3.orig/tests/check_ipc.c libqb-1.0.3/tests/check_ipc.c
632cf8
--- libqb-1.0.3.orig/tests/check_ipc.c	2017-12-21 09:02:11.000000000 +0000
632cf8
+++ libqb-1.0.3/tests/check_ipc.c	2020-05-20 09:07:55.607104804 +0100
632cf8
@@ -98,6 +98,8 @@ enum my_msg_ids {
632cf8
  * 7) service availability
632cf8
  *
632cf8
  * 8) multiple services
632cf8
+ *
632cf8
+ * 9) setting perms on the sockets
632cf8
  */
632cf8
 static qb_loop_t *my_loop;
632cf8
 static qb_ipcs_service_t* s1;
632cf8
@@ -109,6 +111,7 @@ static int32_t num_bulk_events = 10;
632cf8
 static int32_t num_stress_events = 30000;
632cf8
 static int32_t reference_count_test = QB_FALSE;
632cf8
 static int32_t multiple_connections = QB_FALSE;
632cf8
+static int32_t set_perms_on_socket = QB_FALSE;
632cf8
 
632cf8
 
632cf8
 static int32_t
632cf8
@@ -360,6 +363,16 @@ s1_connection_destroyed(qb_ipcs_connecti
632cf8
 	qb_leave();
632cf8
 }
632cf8
 
632cf8
+static int32_t
632cf8
+s1_connection_accept(qb_ipcs_connection_t *c, uid_t uid, gid_t gid)
632cf8
+{
632cf8
+	if (set_perms_on_socket) {
632cf8
+		qb_ipcs_connection_auth_set(c, 555, 741, S_IRWXU|S_IRWXG|S_IROTH|S_IWOTH);
632cf8
+	}
632cf8
+	return 0;
632cf8
+}
632cf8
+
632cf8
+
632cf8
 static void
632cf8
 s1_connection_created(qb_ipcs_connection_t *c)
632cf8
 {
632cf8
@@ -402,7 +415,7 @@ run_ipc_server(void)
632cf8
 	qb_loop_signal_handle handle;
632cf8
 
632cf8
 	struct qb_ipcs_service_handlers sh = {
632cf8
-		.connection_accept = NULL,
632cf8
+		.connection_accept = s1_connection_accept,
632cf8
 		.connection_created = s1_connection_created,
632cf8
 		.msg_process = s1_msg_process_fn,
632cf8
 		.connection_destroyed = s1_connection_destroyed,
632cf8
@@ -517,7 +530,7 @@ verify_graceful_stop(pid_t pid)
632cf8
 	} else {
632cf8
 		fail_if(rc == 0);
632cf8
 	}
632cf8
-	
632cf8
+
632cf8
 	return 0;
632cf8
 }
632cf8
 
632cf8
@@ -1018,7 +1031,7 @@ test_ipc_stress_connections(void)
632cf8
 			}
632cf8
 		} while (conn == NULL && c < 5);
632cf8
 		fail_if(conn == NULL);
632cf8
-		
632cf8
+
632cf8
 		if (((connections+1) % 1000) == 0) {
632cf8
 			qb_log(LOG_INFO, "%d ipc connections made", connections+1);
632cf8
 		}
632cf8
@@ -1448,6 +1461,63 @@ START_TEST(test_ipcc_truncate_when_unlin
632cf8
 END_TEST
632cf8
 #endif
632cf8
 
632cf8
+// Check perms uses illegal access to libqb internals
632cf8
+// DO NOT try this at home.
632cf8
+#include "../lib/ipc_int.h"
632cf8
+#include "../lib/ringbuffer_int.h"
632cf8
+START_TEST(test_ipc_server_perms)
632cf8
+{
632cf8
+	pid_t pid;
632cf8
+	struct stat st;
632cf8
+	int j;
632cf8
+	uint32_t max_size;
632cf8
+	int res;
632cf8
+	int c = 0;
632cf8
+
632cf8
+	// Can only test this if we are root
632cf8
+	if (getuid() != 0) {
632cf8
+		return;
632cf8
+	}
632cf8
+
632cf8
+	ipc_type = QB_IPC_SHM;
632cf8
+	set_perms_on_socket = QB_TRUE;
632cf8
+	max_size = MAX_MSG_SIZE;
632cf8
+
632cf8
+	pid = run_function_in_new_process(run_ipc_server);
632cf8
+	fail_if(pid == -1);
632cf8
+
632cf8
+	do {
632cf8
+		conn = qb_ipcc_connect(ipc_name, max_size);
632cf8
+		if (conn == NULL) {
632cf8
+			j = waitpid(pid, NULL, WNOHANG);
632cf8
+			ck_assert_int_eq(j, 0);
632cf8
+			poll(NULL, 0, 400);
632cf8
+			c++;
632cf8
+		}
632cf8
+	} while (conn == NULL && c < 5);
632cf8
+	fail_if(conn == NULL);
632cf8
+
632cf8
+	// Check perms - uses illegal access to libqb internals
632cf8
+	char sockdir[PATH_MAX];
632cf8
+	strcpy(sockdir, conn->request.u.shm.rb->shared_hdr->hdr_path);
632cf8
+	*strrchr(sockdir, '/') = 0;
632cf8
+	res = stat(sockdir, &st);
632cf8
+
632cf8
+	ck_assert_int_eq(res, 0);
632cf8
+	ck_assert(st.st_mode & S_IRWXG);
632cf8
+	ck_assert_int_eq(st.st_uid, 555);
632cf8
+	ck_assert_int_eq(st.st_gid, 741);
632cf8
+
632cf8
+	res = stat(conn->request.u.shm.rb->shared_hdr->hdr_path, &st);
632cf8
+	ck_assert_int_eq(res, 0);
632cf8
+	ck_assert_int_eq(st.st_uid, 555);
632cf8
+	ck_assert_int_eq(st.st_gid, 741);
632cf8
+
632cf8
+	qb_ipcc_disconnect(conn);
632cf8
+	verify_graceful_stop(pid);
632cf8
+}
632cf8
+END_TEST
632cf8
+
632cf8
 static void
632cf8
 test_ipc_service_ref_count(void)
632cf8
 {
632cf8
@@ -1502,7 +1572,7 @@ END_TEST
632cf8
 #if 0
632cf8
 static void test_max_dgram_size(void)
632cf8
 {
632cf8
-	/* most implementations will not let you set a dgram buffer 
632cf8
+	/* most implementations will not let you set a dgram buffer
632cf8
 	 * of 1 million bytes. This test verifies that the we can detect
632cf8
 	 * the max dgram buffersize regardless, and that the value we detect
632cf8
 	 * is consistent. */
632cf8
@@ -1562,6 +1632,7 @@ make_shm_suite(void)
632cf8
 	add_tcase(s, tc, test_ipc_exit_shm, 8);
632cf8
 	add_tcase(s, tc, test_ipc_event_on_created_shm, 10);
632cf8
 	add_tcase(s, tc, test_ipc_service_ref_count_shm, 10);
632cf8
+	add_tcase(s, tc, test_ipc_server_perms, 7);
632cf8
 	add_tcase(s, tc, test_ipc_stress_connections_shm, 3600);
632cf8
 
632cf8
 #ifdef HAVE_FAILURE_INJECTION