Accepting request 306309 from home:pluskalm:branches:network:utilities
- Fix CVE-2015-0847 * nbd_signaling_CVE-2015-0847.patch OBS-URL: https://build.opensuse.org/request/show/306309 OBS-URL: https://build.opensuse.org/package/show/network:utilities/nbd?expand=0&rev=31
This commit is contained in:
parent
bd9f213808
commit
6e1eb1c315
@ -1,3 +1,9 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Mon May 11 08:13:48 UTC 2015 - mpluskal@suse.com
|
||||||
|
|
||||||
|
- Fix CVE-2015-0847
|
||||||
|
* nbd_signaling_CVE-2015-0847.patch
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Fri Apr 17 13:27:19 UTC 2015 - mpluskal@suse.com
|
Fri Apr 17 13:27:19 UTC 2015 - mpluskal@suse.com
|
||||||
|
|
||||||
|
3
nbd.spec
3
nbd.spec
@ -32,6 +32,8 @@ Patch2: nbd-2.9.25-close.diff
|
|||||||
Patch3: nbd-2.9.25-doxyfile.diff
|
Patch3: nbd-2.9.25-doxyfile.diff
|
||||||
# fix return value
|
# fix return value
|
||||||
Patch4: no-return-nonvoid.patch
|
Patch4: no-return-nonvoid.patch
|
||||||
|
# fix for CVE-2015-0847 (incorrect signal handling DoD)
|
||||||
|
Patch5: nbd_signaling_CVE-2015-0847.patch
|
||||||
BuildRequires: doxygen
|
BuildRequires: doxygen
|
||||||
BuildRequires: glib2-devel >= 2.26.0
|
BuildRequires: glib2-devel >= 2.26.0
|
||||||
BuildRequires: xz
|
BuildRequires: xz
|
||||||
@ -89,6 +91,7 @@ the connection closes.
|
|||||||
%patch2 -p1
|
%patch2 -p1
|
||||||
%patch3 -p1
|
%patch3 -p1
|
||||||
%patch4 -p1
|
%patch4 -p1
|
||||||
|
%patch5 -p1
|
||||||
|
|
||||||
%build
|
%build
|
||||||
export CFLAGS="%{optflags} -fstack-protector -fno-strict-aliasing"
|
export CFLAGS="%{optflags} -fstack-protector -fno-strict-aliasing"
|
||||||
|
181
nbd_signaling_CVE-2015-0847.patch
Normal file
181
nbd_signaling_CVE-2015-0847.patch
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
Index: nbd-3.10/nbd-server.c
|
||||||
|
===================================================================
|
||||||
|
--- nbd-3.10.orig/nbd-server.c
|
||||||
|
+++ nbd-3.10/nbd-server.c
|
||||||
|
@@ -168,6 +168,16 @@ char default_authname[] = SYSCONFDIR "/n
|
||||||
|
|
||||||
|
#include <nbdsrv.h>
|
||||||
|
|
||||||
|
+static volatile sig_atomic_t is_sigchld_caught; /**< Flag set by
|
||||||
|
+ SIGCHLD handler
|
||||||
|
+ to mark a child
|
||||||
|
+ exit */
|
||||||
|
+
|
||||||
|
+static volatile sig_atomic_t is_sigterm_caught; /**< Flag set by
|
||||||
|
+ SIGTERM handler
|
||||||
|
+ to mark a exit
|
||||||
|
+ request */
|
||||||
|
+
|
||||||
|
static volatile sig_atomic_t is_sighup_caught; /**< Flag set by SIGHUP
|
||||||
|
handler to mark a
|
||||||
|
reconfiguration
|
||||||
|
@@ -930,27 +940,16 @@ GArray* parse_cfile(gchar* f, struct gen
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
- * Signal handler for SIGCHLD
|
||||||
|
+ * Handle SIGCHLD by setting atomically a flag which will be evaluated in the
|
||||||
|
+ * main loop of the root server process. This allows us to separate the signal
|
||||||
|
+ * catching from th actual task triggered by SIGCHLD and hence processing in the
|
||||||
|
+ * interrupt context is kept as minimial as possible.
|
||||||
|
+ *
|
||||||
|
* @param s the signal we're handling (must be SIGCHLD, or something
|
||||||
|
* is severely wrong)
|
||||||
|
**/
|
||||||
|
-void sigchld_handler(int s) {
|
||||||
|
- int status;
|
||||||
|
- int* i;
|
||||||
|
- pid_t pid;
|
||||||
|
-
|
||||||
|
- while((pid=waitpid(-1, &status, WNOHANG)) > 0) {
|
||||||
|
- if(WIFEXITED(status)) {
|
||||||
|
- msg(LOG_INFO, "Child exited with %d", WEXITSTATUS(status));
|
||||||
|
- }
|
||||||
|
- i=g_hash_table_lookup(children, &pid);
|
||||||
|
- if(!i) {
|
||||||
|
- msg(LOG_INFO, "SIGCHLD received for an unknown child with PID %ld", (long)pid);
|
||||||
|
- } else {
|
||||||
|
- DEBUG("Removing %d from the list of children", pid);
|
||||||
|
- g_hash_table_remove(children, &pid);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+static void sigchld_handler(const int s G_GNUC_UNUSED) {
|
||||||
|
+ is_sigchld_caught = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -968,15 +967,16 @@ void killchild(gpointer key, gpointer va
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
- * Handle SIGTERM and dispatch it to our children
|
||||||
|
+ * Handle SIGTERM by setting atomically a flag which will be evaluated in the
|
||||||
|
+ * main loop of the root server process. This allows us to separate the signal
|
||||||
|
+ * catching from th actual task triggered by SIGTERM and hence processing in the
|
||||||
|
+ * interrupt context is kept as minimial as possible.
|
||||||
|
+ *
|
||||||
|
* @param s the signal we're handling (must be SIGTERM, or something
|
||||||
|
* is severely wrong).
|
||||||
|
**/
|
||||||
|
-void sigterm_handler(int s) {
|
||||||
|
- g_hash_table_foreach(children, killchild, NULL);
|
||||||
|
- unlink(pidfname);
|
||||||
|
-
|
||||||
|
- exit(EXIT_SUCCESS);
|
||||||
|
+static void sigterm_handler(const int s G_GNUC_UNUSED) {
|
||||||
|
+ is_sigterm_caught = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -2066,9 +2066,12 @@ spawn_child()
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/* Child */
|
||||||
|
+
|
||||||
|
+ /* Child's signal disposition is reset to default. */
|
||||||
|
signal(SIGCHLD, SIG_DFL);
|
||||||
|
signal(SIGTERM, SIG_DFL);
|
||||||
|
signal(SIGHUP, SIG_DFL);
|
||||||
|
+ sigemptyset(&oldset);
|
||||||
|
out:
|
||||||
|
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||||
|
return pid;
|
||||||
|
@@ -2262,9 +2265,12 @@ handle_oldstyle_connection(GArray *const
|
||||||
|
goto handle_connection_out;
|
||||||
|
}
|
||||||
|
/* child */
|
||||||
|
+
|
||||||
|
+ /* Child's signal disposition is reset to default. */
|
||||||
|
signal(SIGCHLD, SIG_DFL);
|
||||||
|
signal(SIGTERM, SIG_DFL);
|
||||||
|
signal(SIGHUP, SIG_DFL);
|
||||||
|
+ sigemptyset(&oldset);
|
||||||
|
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||||
|
|
||||||
|
g_hash_table_destroy(children);
|
||||||
|
@@ -2368,6 +2374,8 @@ void serveloop(GArray* servers) {
|
||||||
|
int max;
|
||||||
|
fd_set mset;
|
||||||
|
fd_set rset;
|
||||||
|
+ sigset_t blocking_mask;
|
||||||
|
+ sigset_t original_mask;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up the master fd_set. The set of descriptors we need
|
||||||
|
@@ -2390,7 +2398,56 @@ void serveloop(GArray* servers) {
|
||||||
|
FD_SET(sock, &mset);
|
||||||
|
max=sock>max?sock:max;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ /* Construct a signal mask which is used to make signal testing and
|
||||||
|
+ * receiving an atomic operation to ensure no signal is received between
|
||||||
|
+ * tests and blocking pselect(). */
|
||||||
|
+ if (sigemptyset(&blocking_mask) == -1)
|
||||||
|
+ err("failed to initialize blocking_mask: %m");
|
||||||
|
+
|
||||||
|
+ if (sigaddset(&blocking_mask, SIGCHLD) == -1)
|
||||||
|
+ err("failed to add SIGCHLD to blocking_mask: %m");
|
||||||
|
+
|
||||||
|
+ if (sigaddset(&blocking_mask, SIGHUP) == -1)
|
||||||
|
+ err("failed to add SIGHUP to blocking_mask: %m");
|
||||||
|
+
|
||||||
|
+ if (sigaddset(&blocking_mask, SIGTERM) == -1)
|
||||||
|
+ err("failed to add SIGTERM to blocking_mask: %m");
|
||||||
|
+
|
||||||
|
+ if (sigprocmask(SIG_BLOCK, &blocking_mask, &original_mask) == -1)
|
||||||
|
+ err("failed to block signals: %m");
|
||||||
|
+
|
||||||
|
for(;;) {
|
||||||
|
+ if (is_sigterm_caught) {
|
||||||
|
+ is_sigterm_caught = 0;
|
||||||
|
+
|
||||||
|
+ g_hash_table_foreach(children, killchild, NULL);
|
||||||
|
+ unlink(pidfname);
|
||||||
|
+
|
||||||
|
+ exit(EXIT_SUCCESS);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (is_sigchld_caught) {
|
||||||
|
+ int status;
|
||||||
|
+ int* i;
|
||||||
|
+ pid_t pid;
|
||||||
|
+
|
||||||
|
+ is_sigchld_caught = 0;
|
||||||
|
+
|
||||||
|
+ while ((pid=waitpid(-1, &status, WNOHANG)) > 0) {
|
||||||
|
+ if (WIFEXITED(status)) {
|
||||||
|
+ msg(LOG_INFO, "Child exited with %d", WEXITSTATUS(status));
|
||||||
|
+ }
|
||||||
|
+ i = g_hash_table_lookup(children, &pid);
|
||||||
|
+ if (!i) {
|
||||||
|
+ msg(LOG_INFO, "SIGCHLD received for an unknown child with PID %ld", (long)pid);
|
||||||
|
+ } else {
|
||||||
|
+ DEBUG("Removing %d from the list of children", pid);
|
||||||
|
+ g_hash_table_remove(children, &pid);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* SIGHUP causes the root server process to reconfigure
|
||||||
|
* itself and add new export servers for each newly
|
||||||
|
* found export configuration group, i.e. spawn new
|
||||||
|
@@ -2425,8 +2482,7 @@ void serveloop(GArray* servers) {
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&rset, &mset, sizeof(fd_set));
|
||||||
|
- if(select(max+1, &rset, NULL, NULL, NULL)>0) {
|
||||||
|
-
|
||||||
|
+ if (pselect(max + 1, &rset, NULL, NULL, NULL, &original_mask) > 0) {
|
||||||
|
DEBUG("accept, ");
|
||||||
|
for(i=0; i < modernsocks->len; i++) {
|
||||||
|
int sock = g_array_index(modernsocks, int, i);
|
Loading…
x
Reference in New Issue
Block a user