Fix CVE-2019-12779

This commit is contained in:
yang_zhuang_zhuang 2021-02-05 16:32:51 +08:00
parent cd08d61b08
commit faf539cd90
5 changed files with 667 additions and 1 deletions

View File

@ -0,0 +1,134 @@
From e322e98dc264bc5911d6fe1d371e55ac9f95a71e Mon Sep 17 00:00:00 2001
From: Christine Caulfield <ccaulfie@redhat.com>
Date: Tue, 12 Mar 2019 10:15:41 +0000
Subject: [PATCH] ipc: use O_EXCL on SHM files, and randomize the names
Signed-off-by: Christine Caulfield <ccaulfie@redhat.com>
---
lib/ipc_setup.c | 14 ++++++++++++--
lib/ipc_socket.c | 2 +-
lib/ipcs.c | 14 ++++++++++++++
lib/log_blackbox.c | 2 +-
lib/ringbuffer.c | 2 +-
5 files changed, 29 insertions(+), 5 deletions(-)
diff --git a/lib/ipc_setup.c b/lib/ipc_setup.c
index 0e169643..36ae2cfb 100644
--- a/lib/ipc_setup.c
+++ b/lib/ipc_setup.c
@@ -43,6 +43,9 @@
#include "util_int.h"
#include "ipc_int.h"
+/* Maximum number of times we generate a random socket name before giving up */
+#define MAX_NAME_RETRY_COUNT 20
+
struct ipc_auth_ugp {
uid_t uid;
gid_t gid;
@@ -619,6 +622,7 @@ handle_new_connection(struct qb_ipcs_service *s,
struct qb_ipc_connection_request *req = msg;
int32_t res = auth_result;
int32_t res2 = 0;
+ uint32_t retry_count = 0;
uint32_t max_buffer_size = QB_MAX(req->max_msg_size, s->max_buffer_size);
struct qb_ipc_connection_response response;
@@ -643,8 +647,6 @@ handle_new_connection(struct qb_ipcs_service *s,
c->auth.gid = c->egid = ugp->gid;
c->auth.mode = 0600;
c->stats.client_pid = ugp->pid;
- snprintf(c->description, CONNECTION_DESCRIPTION,
- "%d-%d-%d", s->pid, ugp->pid, c->setup.u.us.sock);
if (auth_result == 0 && c->service->serv_fns.connection_accept) {
res = c->service->serv_fns.connection_accept(c,
@@ -657,9 +659,17 @@ handle_new_connection(struct qb_ipcs_service *s,
qb_util_log(LOG_DEBUG, "IPC credentials authenticated (%s)",
c->description);
+retry_description:
+ snprintf(c->description, CONNECTION_DESCRIPTION,
+ "%d-%d-%lu", s->pid, ugp->pid, (unsigned long)(random()%65536));
+
memset(&response, 0, sizeof(response));
if (s->funcs.connect) {
res = s->funcs.connect(s, c, &response);
+ if (res == -EEXIST && ++retry_count < MAX_NAME_RETRY_COUNT) {
+ qb_util_log(LOG_DEBUG, "Retrying socket name %s (count=%ld)\n", c->description, retry_count);
+ goto retry_description;
+ }
if (res != 0) {
goto send_response;
}
diff --git a/lib/ipc_socket.c b/lib/ipc_socket.c
index fe2040e2..1f7cde38 100644
--- a/lib/ipc_socket.c
+++ b/lib/ipc_socket.c
@@ -790,7 +790,7 @@ qb_ipcs_us_connect(struct qb_ipcs_service *s,
fd_hdr = qb_sys_mmap_file_open(path, r->request,
SHM_CONTROL_SIZE,
- O_CREAT | O_TRUNC | O_RDWR);
+ O_CREAT | O_TRUNC | O_RDWR | O_EXCL);
if (fd_hdr < 0) {
res = fd_hdr;
errno = -fd_hdr;
diff --git a/lib/ipcs.c b/lib/ipcs.c
index 4a375fca..573b4276 100644
--- a/lib/ipcs.c
+++ b/lib/ipcs.c
@@ -40,6 +40,8 @@ qb_ipcs_create(const char *name,
enum qb_ipc_type type, struct qb_ipcs_service_handlers *handlers)
{
struct qb_ipcs_service *s;
+ int fd;
+ unsigned int seed;
s = calloc(1, sizeof(struct qb_ipcs_service));
if (s == NULL) {
@@ -75,6 +77,18 @@ qb_ipcs_create(const char *name,
qb_list_init(&s->list);
qb_list_add(&s->list, &qb_ipc_services);
+ /* Randomise socket names */
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd == -1) {
+ seed = (time_t)time(NULL);
+ } else {
+ if (read(fd, &seed, sizeof(seed)) != 4) {
+ seed = (time_t)time(NULL);
+ }
+ close(fd);
+ }
+ srand(seed);
+
return s;
}
diff --git a/lib/log_blackbox.c b/lib/log_blackbox.c
index 64c30fe..a451742 100644
--- a/lib/log_blackbox.c
+++ b/lib/log_blackbox.c
@@ -165,7 +165,7 @@ qb_log_blackbox_write_to_file(const char *filename)
{
ssize_t written_size = 0;
struct qb_log_target *t;
- int fd = open(filename, O_CREAT | O_RDWR, 0700);
+ int fd = open(filename, O_CREAT | O_RDWR | O_EXCL, 0700);
if (fd < 0) {
return -errno;
diff --git a/lib/ringbuffer.c b/lib/ringbuffer.c
index 81411cb1..8852ff5b 100644
--- a/lib/ringbuffer.c
+++ b/lib/ringbuffer.c
@@ -155,7 +155,7 @@ qb_rb_open_2(const char *name, size_t size, uint32_t flags,
sizeof(struct qb_ringbuffer_shared_s) + shared_user_data_size;
if (flags & QB_RB_FLAG_CREATE) {
- file_flags |= O_CREAT | O_TRUNC;
+ file_flags |= O_CREAT | O_TRUNC | O_EXCL;
}
rb = calloc(1, sizeof(struct qb_ringbuffer_s));

View File

@ -0,0 +1,106 @@
From 7cd7b06d52ac80c343f362c7e39ef75495439dfc Mon Sep 17 00:00:00 2001
From: Christine Caulfield <ccaulfie@redhat.com>
Date: Tue, 12 Mar 2019 14:08:47 +0000
Subject: [PATCH] ipc: fixes
Use O_EXCL on IPC files
---
lib/ipc_setup.c | 14 ++------------
lib/ipcs.c | 14 --------------
lib/log_blackbox.c | 2 +-
3 files changed, 3 insertions(+), 27 deletions(-)
diff --git a/lib/ipc_setup.c b/lib/ipc_setup.c
index 36ae2cfb..0e169643 100644
--- a/lib/ipc_setup.c
+++ b/lib/ipc_setup.c
@@ -43,9 +43,6 @@
#include "util_int.h"
#include "ipc_int.h"
-/* Maximum number of times we generate a random socket name before giving up */
-#define MAX_NAME_RETRY_COUNT 20
-
struct ipc_auth_ugp {
uid_t uid;
gid_t gid;
@@ -622,7 +619,6 @@ handle_new_connection(struct qb_ipcs_service *s,
struct qb_ipc_connection_request *req = msg;
int32_t res = auth_result;
int32_t res2 = 0;
- uint32_t retry_count = 0;
uint32_t max_buffer_size = QB_MAX(req->max_msg_size, s->max_buffer_size);
struct qb_ipc_connection_response response;
@@ -647,6 +643,8 @@ handle_new_connection(struct qb_ipcs_service *s,
c->auth.gid = c->egid = ugp->gid;
c->auth.mode = 0600;
c->stats.client_pid = ugp->pid;
+ snprintf(c->description, CONNECTION_DESCRIPTION,
+ "%d-%d-%d", s->pid, ugp->pid, c->setup.u.us.sock);
if (auth_result == 0 && c->service->serv_fns.connection_accept) {
res = c->service->serv_fns.connection_accept(c,
@@ -659,17 +657,9 @@ handle_new_connection(struct qb_ipcs_service *s,
qb_util_log(LOG_DEBUG, "IPC credentials authenticated (%s)",
c->description);
-retry_description:
- snprintf(c->description, CONNECTION_DESCRIPTION,
- "%d-%d-%lu", s->pid, ugp->pid, (unsigned long)(random()%65536));
-
memset(&response, 0, sizeof(response));
if (s->funcs.connect) {
res = s->funcs.connect(s, c, &response);
- if (res == -EEXIST && ++retry_count < MAX_NAME_RETRY_COUNT) {
- qb_util_log(LOG_DEBUG, "Retrying socket name %s (count=%ld)\n", c->description, retry_count);
- goto retry_description;
- }
if (res != 0) {
goto send_response;
}
diff --git a/lib/ipcs.c b/lib/ipcs.c
index 573b4276..4a375fca 100644
--- a/lib/ipcs.c
+++ b/lib/ipcs.c
@@ -40,8 +40,6 @@ qb_ipcs_create(const char *name,
enum qb_ipc_type type, struct qb_ipcs_service_handlers *handlers)
{
struct qb_ipcs_service *s;
- int fd;
- unsigned int seed;
s = calloc(1, sizeof(struct qb_ipcs_service));
if (s == NULL) {
@@ -77,18 +75,6 @@ qb_ipcs_create(const char *name,
qb_list_init(&s->list);
qb_list_add(&s->list, &qb_ipc_services);
- /* Randomise socket names */
- fd = open("/dev/urandom", O_RDONLY);
- if (fd == -1) {
- seed = (time_t)time(NULL);
- } else {
- if (read(fd, &seed, sizeof(seed)) != 4) {
- seed = (time_t)time(NULL);
- }
- close(fd);
- }
- srand(seed);
-
return s;
}
diff --git a/lib/log_blackbox.c b/lib/log_blackbox.c
index a451742..9727b4c 100644
--- a/lib/log_blackbox.c
+++ b/lib/log_blackbox.c
@@ -165,7 +165,7 @@ qb_log_blackbox_write_to_file(const char *filename)
{
ssize_t written_size = 0;
struct qb_log_target *t;
- int fd = open(filename, O_CREAT | O_RDWR | O_EXCL, 0700);
+ int fd = open(filename, O_CREAT | O_RDWR, 0700);
if (fd < 0) {
return -errno;

View File

@ -0,0 +1,228 @@
From 6a4067c1d1764d93d255eccecfd8bf9f43cb0b4d Mon Sep 17 00:00:00 2001
From: Christine Caulfield <ccaulfie@redhat.com>
Date: Mon, 8 Apr 2019 16:24:19 +0100
Subject: [PATCH] ipc: Use mkdtemp for more secure IPC files
Use mkdtemp makes sure that IPC files are only visible to the
owning (client) process and do not use predictable names outside
of that.
This is not meant to be the last word on the subject, it's mainly a
simple way of making the current libqb more secure. Importantly, it's
backwards compatible with an old server.
It calls rmdir on the directory created by mkdtemp way too often, but
it seems to be the only way to be sure that things get cleaned up on
the various types of server/client exit. I'm sure we can come up with
something tidier for master but I hope this, or something similar, will
be OK for 1.0.x.
---
lib/ipc_int.h | 4 +++-
lib/ipc_setup.c | 39 +++++++++++++++++++++++++++++++++++++++
lib/ipc_shm.c | 9 ++++++---
lib/ipc_socket.c | 13 ++++++++++---
lib/ipcs.c | 3 ++-
lib/ringbuffer.c | 4 ++--
lib/unix.c | 4 +++-
7 files changed, 65 insertions(+), 11 deletions(-)
diff --git a/lib/ipc_int.h b/lib/ipc_int.h
index 9cd06cfe..c8904487 100644
--- a/lib/ipc_int.h
+++ b/lib/ipc_int.h
@@ -161,7 +161,7 @@ enum qb_ipcs_connection_state {
QB_IPCS_CONNECTION_SHUTTING_DOWN,
};
-#define CONNECTION_DESCRIPTION (34) /* INT_MAX length + 3 */
+#define CONNECTION_DESCRIPTION NAME_MAX
struct qb_ipcs_connection_auth {
uid_t uid;
@@ -208,4 +208,6 @@ int32_t qb_ipc_us_sock_error_is_disconnected(int err);
int use_filesystem_sockets(void);
+void remove_tempdir(const char *name, size_t namelen);
+
#endif /* QB_IPC_INT_H_DEFINED */
diff --git a/lib/ipc_setup.c b/lib/ipc_setup.c
index 0e169643..43dc3e78 100644
--- a/lib/ipc_setup.c
+++ b/lib/ipc_setup.c
@@ -643,8 +643,28 @@ handle_new_connection(struct qb_ipcs_service *s,
c->auth.gid = c->egid = ugp->gid;
c->auth.mode = 0600;
c->stats.client_pid = ugp->pid;
+
+#if defined(QB_LINUX) || defined(QB_CYGWIN)
+ snprintf(c->description, CONNECTION_DESCRIPTION,
+ "/dev/shm/qb-%d-%d-%d-XXXXXX", s->pid, ugp->pid, c->setup.u.us.sock);
+ if (mkdtemp(c->description) == NULL) {
+ res = errno;
+ goto send_response;
+ }
+ res = chown(c->description, c->auth.uid, c->auth.gid);
+ if (res != 0) {
+ res = errno;
+ goto send_response;
+ }
+
+ /* We can't pass just a directory spec to the clients */
+ strncat(c->description,"/qb", CONNECTION_DESCRIPTION);
+#else
snprintf(c->description, CONNECTION_DESCRIPTION,
"%d-%d-%d", s->pid, ugp->pid, c->setup.u.us.sock);
+#endif
+
+
if (auth_result == 0 && c->service->serv_fns.connection_accept) {
res = c->service->serv_fns.connection_accept(c,
@@ -865,3 +885,22 @@ qb_ipcs_us_connection_acceptor(int fd, int revent, void *data)
qb_ipcs_uc_recv_and_auth(new_fd, s);
return 0;
}
+
+void remove_tempdir(const char *name, size_t namelen)
+{
+#if defined(QB_LINUX) || defined(QB_CYGWIN)
+ char dirname[PATH_MAX];
+ char *slash;
+ memcpy(dirname, name, namelen);
+
+ slash = strrchr(dirname, '/');
+ if (slash) {
+ *slash = '\0';
+ /* This gets called more than it needs to be really, so we don't check
+ * the return code. It's more of a desperate attempt to clean up after ourself
+ * in either the server or client.
+ */
+ (void)rmdir(dirname);
+ }
+#endif
+}
diff --git a/lib/ipc_shm.c b/lib/ipc_shm.c
index 9f237b6e..758a2b51 100644
--- a/lib/ipc_shm.c
+++ b/lib/ipc_shm.c
@@ -265,6 +265,9 @@ qb_ipcs_shm_disconnect(struct qb_ipcs_connection *c)
c->setup.u.us.sock = -1;
}
}
+
+ remove_tempdir(c->description, CONNECTION_DESCRIPTION);
+
end_disconnect:
sigaction(SIGBUS, &old_sa, NULL);
}
@@ -313,11 +316,11 @@ qb_ipcs_shm_connect(struct qb_ipcs_service *s,
qb_util_log(LOG_DEBUG, "connecting to client [%d]", c->pid);
snprintf(r->request, NAME_MAX, "%s-request-%s",
- s->name, c->description);
+ c->description, s->name);
snprintf(r->response, NAME_MAX, "%s-response-%s",
- s->name, c->description);
+ c->description, s->name);
snprintf(r->event, NAME_MAX, "%s-event-%s",
- s->name, c->description);
+ c->description, s->name);
res = qb_ipcs_shm_rb_open(c, &c->request,
r->request);
diff --git a/lib/ipc_socket.c b/lib/ipc_socket.c
index 1f7cde38..59492323 100644
--- a/lib/ipc_socket.c
+++ b/lib/ipc_socket.c
@@ -374,6 +374,10 @@ qb_ipcc_us_disconnect(struct qb_ipcc_connection *c)
free(base_name);
}
}
+
+ /* Last-ditch attempt to tidy up after ourself */
+ remove_tempdir(c->request.u.us.shared_file_name, PATH_MAX);
+
qb_ipcc_us_sock_close(c->event.u.us.sock);
qb_ipcc_us_sock_close(c->request.u.us.sock);
qb_ipcc_us_sock_close(c->setup.u.us.sock);
@@ -765,7 +769,10 @@ qb_ipcs_us_disconnect(struct qb_ipcs_connection *c)
c->state == QB_IPCS_CONNECTION_ACTIVE) {
munmap(c->request.u.us.shared_data, SHM_CONTROL_SIZE);
unlink(c->request.u.us.shared_file_name);
+
+
}
+ remove_tempdir(c->description, CONNECTION_DESCRIPTION);
}
static int32_t
@@ -784,9 +791,9 @@ qb_ipcs_us_connect(struct qb_ipcs_service *s,
c->request.u.us.sock = c->setup.u.us.sock;
c->response.u.us.sock = c->setup.u.us.sock;
- snprintf(r->request, NAME_MAX, "qb-%s-control-%s",
- s->name, c->description);
- snprintf(r->response, NAME_MAX, "qb-%s-%s", s->name, c->description);
+ snprintf(r->request, NAME_MAX, "%s-control-%s",
+ c->description, s->name);
+ snprintf(r->response, NAME_MAX, "%s-%s", c->description, s->name);
fd_hdr = qb_sys_mmap_file_open(path, r->request,
SHM_CONTROL_SIZE,
diff --git a/lib/ipcs.c b/lib/ipcs.c
index 4a375fca..29f3431b 100644
--- a/lib/ipcs.c
+++ b/lib/ipcs.c
@@ -642,12 +642,13 @@ qb_ipcs_disconnect(struct qb_ipcs_connection *c)
scheduled_retry = 1;
}
}
-
+ remove_tempdir(c->description, CONNECTION_DESCRIPTION);
if (scheduled_retry == 0) {
/* This removes the initial alloc ref */
qb_ipcs_connection_unref(c);
}
}
+
}
static void
diff --git a/lib/ringbuffer.c b/lib/ringbuffer.c
index 8852ff5b..f85ad979 100644
--- a/lib/ringbuffer.c
+++ b/lib/ringbuffer.c
@@ -166,7 +166,7 @@ qb_rb_open_2(const char *name, size_t size, uint32_t flags,
/*
* Create a shared_hdr memory segment for the header.
*/
- snprintf(filename, PATH_MAX, "qb-%s-header", name);
+ snprintf(filename, PATH_MAX, "%s-header", name);
fd_hdr = qb_sys_mmap_file_open(path, filename,
shared_size, file_flags);
if (fd_hdr < 0) {
@@ -217,7 +217,7 @@ qb_rb_open_2(const char *name, size_t size, uint32_t flags,
* They have to be separate.
*/
if (flags & QB_RB_FLAG_CREATE) {
- snprintf(filename, PATH_MAX, "qb-%s-data", name);
+ snprintf(filename, PATH_MAX, "%s-data", name);
fd_data = qb_sys_mmap_file_open(path,
filename,
real_size, file_flags);
diff --git a/lib/unix.c b/lib/unix.c
index 3c8f327c..49701a33 100644
--- a/lib/unix.c
+++ b/lib/unix.c
@@ -81,7 +81,9 @@ qb_sys_mmap_file_open(char *path, const char *file, size_t bytes,
(void)strlcpy(path, file, PATH_MAX);
} else {
#if defined(QB_LINUX) || defined(QB_CYGWIN)
- snprintf(path, PATH_MAX, "/dev/shm/%s", file);
+ /* This is only now called when talking to an old libqb
+ where we need to add qb- to the name */
+ snprintf(path, PATH_MAX, "/dev/shm/qb-%s", file);
#else
snprintf(path, PATH_MAX, "%s/%s", SOCKETDIR, file);
is_absolute = path;

View File

@ -0,0 +1,189 @@
From 75ab31bdd05a15947dc56edf4d6b7f377355435e Mon Sep 17 00:00:00 2001
From: Chrissie Caulfield <ccaulfie@redhat.com>
Date: Fri, 20 Apr 2018 09:48:04 +0100
Subject: [PATCH] ipc_shm: Don't truncate SHM files of an active server (#307)
* ipc_shm: Don't truncate SHM files of an active server
I've put in an extra check so that clients don't truncate the
SHM file if the server still exists. Sadly on FreeBSD we can't
get the server PID for the client (unless someone has a patch handy!)
so we still do the truncate when disconnected. As a backstop (and also
to cover the BSD issue) I've added a SIGBUS trap to the server shutdown
so that it doesn't cause a server crash.
Signed-off-by: Christine Caulfield <ccaulfie@redhat.com>
Reviewed by: Jan Friesse <jfriesse@redhat.com>
---
include/qb/qbipcs.h | 4 ++++
lib/ipc_int.h | 1 +
lib/ipc_setup.c | 1 +
lib/ipc_shm.c | 48 +++++++++++++++++++++++++++++++++++----------
tests/check_ipc.c | 24 +++++++++++++++++------
5 files changed, 62 insertions(+), 16 deletions(-)
diff --git a/include/qb/qbipcs.h b/include/qb/qbipcs.h
index 55c0f815..7b4daa7d 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
* repeatedly 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 67fc444c..9cd06cfe 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 57d755b4..0e169643 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 699f4e47..9f237b6e 100644
--- a/lib/ipc_shm.c
+++ b/lib/ipc_shm.c
@@ -20,6 +20,8 @@
*/
#include "os_base.h"
#include <poll.h>
+#include <signal.h>
+#include <setjmp.h>
#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 @@ qb_ipcc_shm_connect(struct qb_ipcc_connection * c,
* 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 f8af2c5e..46c3b404 100644
--- a/tests/check_ipc.c
+++ b/tests/check_ipc.c
@@ -444,18 +444,30 @@ run_ipc_server(void)
static pid_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

View File

@ -1,11 +1,17 @@
Name: libqb
Version: 1.0.3
Release: 6
Release: 7
Summary: High performance servers IPC library
Group: System Environment/Libraries
License: LGPLv2+
URL: https://github.com/ClusterLabs/libqb
Source0: https://github.com/ClusterLabs/libqb/releases/download/v%{version}/libqb-%{version}.tar.xz
Patch1: backport-ipc_shm-Don-t-truncate-SHM-files-of-an-active-server.patch
Patch2: backport-0001-CVE-2019-12779-ipc-use-O_EXCL-on-SHM-files-and-randomize-the-names.patch
Patch3: backport-0002-CVE-2019-12779-ipc-fixes.patch
Patch4: backport-0003-CVE-2019-12779-ipc-Use-mkdtemp-for-more-secure-IPC-files.patch
BuildRequires: autoconf automake libtool doxygen procps check-devel gcc
%description
@ -69,5 +75,8 @@ help documents for libqb package
%{_mandir}/man3/qb*3*
%changelog
* Fri Feb 5 2021 yangzhuangzhuang <yangzhuangzhuang1@huawei.com> - 1.0.3-7
- Fix CVE-2019-12779
* Tue Apr 27 2020 wangerfeng <wangerfeng5@huawei.com> - 1.0.3-6
- Package init