diff --git a/SOURCES/bz1459276-dont-truncate-in-client.patch b/SOURCES/bz1459276-dont-truncate-in-client.patch deleted file mode 100644 index 2959a0c..0000000 --- a/SOURCES/bz1459276-dont-truncate-in-client.patch +++ /dev/null @@ -1,37 +0,0 @@ -diff --git a/lib/unix.c b/lib/unix.c -index 3c8f327..3c46f28 100644 ---- a/lib/unix.c -+++ b/lib/unix.c -@@ -290,7 +290,7 @@ qb_sys_unlink_or_truncate_at(int32_t dirfd, const char *path, - "Unlinking file at dir: %s", path); - if (res != ENOENT && truncate_fallback) { - res = errno = 0; -- if ((fd = openat(dirfd, path, O_WRONLY|O_TRUNC)) == -1) { -+ if ((fd = openat(dirfd, path, O_WRONLY)) == -1) { - res = errno; - qb_util_perror(LOG_DEBUG, - "Truncating file at dir: %s", -diff --git a/tests/Makefile.am b/tests/Makefile.am -index fe54741..f00e6b9 100644 ---- a/tests/Makefile.am -+++ b/tests/Makefile.am -@@ -103,7 +103,7 @@ if HAVE_CHECK - EXTRA_DIST += resources.test - EXTRA_DIST += blackbox-segfault.sh - --TESTS = array.test map.test rb.test log.test blackbox-segfault.sh loop.test ipc.test resources.test -+TESTS = array.test map.test rb.test log.test blackbox-segfault.sh loop.test resources.test - - resources.log: rb.log log.log ipc.log - -diff --git a/tests/resources.test b/tests/resources.test -index b250401..e735ac5 100755 ---- a/tests/resources.test -+++ b/tests/resources.test -@@ -1,5 +1,6 @@ - #!/bin/sh - RETURN=0 -+exit $RETURN - - for d in /dev/shm /var/run; do - leftovers=$(find $d -name qb-test* -size +0c 2>/dev/null | wc -l) diff --git a/SOURCES/bz1473695-dont-crash-on-shm-truncate.patch b/SOURCES/bz1473695-dont-crash-on-shm-truncate.patch new file mode 100644 index 0000000..97cef8e --- /dev/null +++ b/SOURCES/bz1473695-dont-crash-on-shm-truncate.patch @@ -0,0 +1,185 @@ +diff --git a/include/qb/qbipcs.h b/include/qb/qbipcs.h +index 55c0f81..7b4daa7 100644 +--- a/include/qb/qbipcs.h ++++ b/include/qb/qbipcs.h +@@ -142,6 +142,10 @@ typedef void (*qb_ipcs_connection_created_fn) (qb_ipcs_connection_t *c); + * successfully created. + * @note if you return anything but 0 this function will be + * repeativily called (until 0 is returned). ++ * ++ * With SHM connections libqb will briefly trap SIGBUS during the ++ * disconnect process to guard against server crashes if the mapped ++ * file is truncated. The signal will be restored afterwards. + */ + typedef int32_t (*qb_ipcs_connection_closed_fn) (qb_ipcs_connection_t *c); + +diff --git a/lib/ipc_int.h b/lib/ipc_int.h +index 67fc444..9cd06cf 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; ++ pid_t server_pid; + struct qb_ipc_one_way setup; + struct qb_ipc_one_way request; + struct qb_ipc_one_way response; +diff --git a/lib/ipc_setup.c b/lib/ipc_setup.c +index 57d755b..0e16964 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->server_pid = data->ugp.pid; + + destroy_ipc_auth_data(data); + return r->hdr.error; +diff --git a/lib/ipc_shm.c b/lib/ipc_shm.c +index 699f4e4..9f237b6 100644 +--- a/lib/ipc_shm.c ++++ b/lib/ipc_shm.c +@@ -20,6 +20,8 @@ + */ + #include "os_base.h" + #include ++#include ++#include + + #include "ipc_int.h" + #include "util_int.h" +@@ -36,9 +38,12 @@ + static void + qb_ipcc_shm_disconnect(struct qb_ipcc_connection *c) + { +- void (*rb_destructor)(struct qb_ringbuffer_s *) = c->is_connected +- ? qb_rb_close +- : qb_rb_force_close; ++ void (*rb_destructor)(struct qb_ringbuffer_s *); ++ ++ rb_destructor = qb_rb_close; ++ if (!c->is_connected && (!c->server_pid || (kill(c->server_pid, 0) == -1 && errno == ESRCH))) { ++ rb_destructor = qb_rb_force_close; ++ } + + qb_ipcc_us_sock_close(c->setup.u.us.sock); + +@@ -215,18 +220,30 @@ return_error: + * service functions + * -------------------------------------------------------- + */ ++static jmp_buf sigbus_jmpbuf; ++static void catch_sigbus(int signal) ++{ ++ longjmp(sigbus_jmpbuf, 1); ++} + + static void + qb_ipcs_shm_disconnect(struct qb_ipcs_connection *c) + { +- if (c->state == QB_IPCS_CONNECTION_ESTABLISHED || +- c->state == QB_IPCS_CONNECTION_ACTIVE) { +- if (c->setup.u.us.sock > 0) { +- (void)c->service->poll_fns.dispatch_del(c->setup.u.us.sock); +- qb_ipcc_us_sock_close(c->setup.u.us.sock); +- c->setup.u.us.sock = -1; +- } ++ struct sigaction sa; ++ struct sigaction old_sa; ++ ++ /* Don't die if the client has truncated the SHM under us */ ++ memset(&old_sa, 0, sizeof(old_sa)); ++ memset(&sa, 0, sizeof(sa)); ++ sa.sa_handler = catch_sigbus; ++ sigemptyset(&sa.sa_mask); ++ sa.sa_flags = 0; ++ sigaction(SIGBUS, &sa, &old_sa); ++ ++ if (setjmp(sigbus_jmpbuf) == 1) { ++ goto end_disconnect; + } ++ + if (c->state == QB_IPCS_CONNECTION_SHUTTING_DOWN || + c->state == QB_IPCS_CONNECTION_ACTIVE) { + if (c->response.u.shm.rb) { +@@ -239,6 +256,17 @@ qb_ipcs_shm_disconnect(struct qb_ipcs_connection *c) + qb_rb_close(qb_rb_lastref_and_ret(&c->request.u.shm.rb)); + } + } ++ ++ if (c->state == QB_IPCS_CONNECTION_ESTABLISHED || ++ c->state == QB_IPCS_CONNECTION_ACTIVE) { ++ if (c->setup.u.us.sock > 0) { ++ (void)c->service->poll_fns.dispatch_del(c->setup.u.us.sock); ++ qb_ipcc_us_sock_close(c->setup.u.us.sock); ++ c->setup.u.us.sock = -1; ++ } ++ } ++end_disconnect: ++ sigaction(SIGBUS, &old_sa, NULL); + } + + static int32_t +diff --git a/tests/check_ipc.c b/tests/check_ipc.c +index f8af2c5..46c3b40 100644 +--- a/tests/check_ipc.c ++++ b/tests/check_ipc.c +@@ -444,18 +444,30 @@ run_ipc_server(void) + static int32_t + run_function_in_new_process(void (*run_ipc_server_fn)(void)) + { +- pid_t pid = fork (); ++ pid_t pid1 = fork (); ++ pid_t pid2; + +- if (pid == -1) { ++ if (pid1 == -1) { + fprintf (stderr, "Can't fork\n"); + return -1; + } + +- if (pid == 0) { +- run_ipc_server_fn(); +- exit(0); ++ /* Double-fork so the servers can be reaped in a timely manner */ ++ if (pid1 == 0) { ++ pid2 = fork(); ++ if (pid2 == -1) { ++ fprintf (stderr, "Can't fork twice\n"); ++ exit(0); ++ } ++ if (pid2 == 0) { ++ run_ipc_server_fn(); ++ exit(0); ++ } else { ++ waitpid(pid2, NULL, 0); ++ exit(0); ++ } + } +- return pid; ++ return pid1; + } + + static void +--- a/lib/loop_poll.cg 2018-04-20 11:23:05.255007538 +0100 ++++ b/lib/loop_poll.c 2018-04-20 11:23:36.000113203 +0100 +@@ -723,7 +723,7 @@ qb_loop_signal_mod(qb_loop_t * lp, + sig->p = p; + + if (sig->signal != the_sig) { +- signal(sig->signal, SIG_DFL); ++ (void)signal(sig->signal, SIG_DFL); + sig->signal = the_sig; + _adjust_sigactions_(s); + } +@@ -774,7 +774,7 @@ qb_loop_signal_del(qb_loop_t * lp, qb_lo + } + + qb_list_del(&sig->item.list); +- signal(sig->signal, SIG_DFL); ++ (void)signal(sig->signal, SIG_DFL); + free(sig); + _adjust_sigactions_(s); + return 0; diff --git a/SPECS/libqb.spec b/SPECS/libqb.spec index e87a4f7..54eb2c6 100644 --- a/SPECS/libqb.spec +++ b/SPECS/libqb.spec @@ -1,6 +1,6 @@ Name: libqb Version: 1.0.1 -Release: 6%{?dist} +Release: 7%{?dist} Summary: An IPC library for high performance servers Group: System Environment/Libraries @@ -10,9 +10,10 @@ Source0: https://github.com/ClusterLabs/%{name}/releases/download/v%{vers Patch1: bz1422454-ipc-detect-corrupt-shm-in-peek.patch Patch2: bz1446254-ipc-allow-fs-sockets.patch -Patch3: bz1459276-dont-truncate-in-client.patch +#Patch3: bz1459276-dont-truncate-in-client.patch Patch4: bz1422573_1-dont-override-user-signals.patch Patch5: bz1422573_2-dont-override-user-signals.patch +Patch6: bz1473695-dont-crash-on-shm-truncate.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -28,9 +29,10 @@ Initially these are IPC and poll. %setup -q %patch1 -p1 -b .bz1422454-ipc-detect-corrupt-shm-in-peek %patch2 -p1 -b .bz1446254-ipc-allow-fs-sockets -%patch3 -p1 -b .bz1459276-dont-truncate-in-client.patch +#%patch3 -p1 -b .bz1459276-dont-truncate-in-client.patch %patch4 -p1 -b .bz1422573_1-dont-override-user-signals.patch %patch5 -p1 -b .bz1422573_2-dont-override-user-signals.patch +%patch6 -p1 -b .bz1473695-dont-crash-on-shm-truncate.patch # work-around for broken epoll in rawhide/f17 %build @@ -80,6 +82,12 @@ developing applications that use %{name}. %changelog +* Fri Apr 20 2018 Christine Caulfield - 1.0.1-7 + Prevent crashes when client truncates SHM segment + I've reverted the patch for 1459276 which is no longer needed as this + is a proper fix. + Resolves: rhbz#1473695 + * Fri Nov 03 2017 Christine Caulfield - 1.0.1-6 Don't override external signal handlers Resolves: rhbz#1422573