Blame SOURCES/ebtables-2.0.10-flock.patch

8c7451
From 03df255180677b86eb058866be668063fcc6f598 Mon Sep 17 00:00:00 2001
8c7451
From: Phil Sutter <phil@nwl.cc>
8c7451
Date: Fri, 6 Oct 2017 12:48:50 +0200
8c7451
Subject: [PATCH] Use flock() for --concurrent option
8c7451
8c7451
The previous locking mechanism was not atomic, hence it was possible
8c7451
that a killed ebtables process would leave the lock file in place which
8c7451
in turn made future ebtables processes wait indefinitely for the lock to
8c7451
become free.
8c7451
8c7451
Fix this by using flock(). This also simplifies code quite a bit because
8c7451
there is no need for a custom signal handler or an __exit routine
8c7451
anymore.
8c7451
8c7451
Signed-off-by: Phil Sutter <phil@nwl.cc>
8c7451
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
8c7451
Signed-off-by: Phil Sutter <psutter@redhat.com>
8c7451
---
8c7451
 ebtables.c |  8 --------
8c7451
 libebtc.c  | 49 +++++--------------------------------------------
8c7451
 2 files changed, 5 insertions(+), 52 deletions(-)
8c7451
8c7451
diff --git a/ebtables.c b/ebtables.c
8c7451
index 62f1ba80063d8..f7dfccf4b2f31 100644
8c7451
--- a/ebtables.c
8c7451
+++ b/ebtables.c
8c7451
@@ -528,12 +528,6 @@ void ebt_early_init_once()
8c7451
 	ebt_iterate_targets(merge_target);
8c7451
 }
8c7451
 
8c7451
-/* signal handler, installed when the option --concurrent is specified. */
8c7451
-static void sighandler(int signum)
8c7451
-{
8c7451
-	exit(-1);
8c7451
-}
8c7451
-
8c7451
 /* We use exec_style instead of #ifdef's because ebtables.so is a shared object. */
8c7451
 int do_command(int argc, char *argv[], int exec_style,
8c7451
                struct ebt_u_replace *replace_)
8c7451
@@ -1047,8 +1041,6 @@ big_iface_length:
8c7451
 			strcpy(replace->filename, optarg);
8c7451
 			break;
8c7451
 		case 13 : /* concurrent */
8c7451
-			signal(SIGINT, sighandler);
8c7451
-			signal(SIGTERM, sighandler);
8c7451
 			use_lockfd = 1;
8c7451
 			break;
8c7451
 		case 1 :
8c7451
diff --git a/libebtc.c b/libebtc.c
8c7451
index b0814213b6b06..ab3429577a1f1 100644
8c7451
--- a/libebtc.c
8c7451
+++ b/libebtc.c
8c7451
@@ -31,6 +31,7 @@
8c7451
 #include "include/ethernetdb.h"
8c7451
 #include <unistd.h>
8c7451
 #include <fcntl.h>
8c7451
+#include <sys/file.h>
8c7451
 #include <sys/wait.h>
8c7451
 #include <sys/stat.h>
8c7451
 #include <sys/types.h>
8c7451
@@ -137,58 +138,18 @@ void ebt_list_extensions()
8c7451
 #define LOCKDIR "/run"
8c7451
 #define LOCKFILE LOCKDIR"/ebtables.lock"
8c7451
 #endif
8c7451
-static int lockfd = -1, locked;
8c7451
 int use_lockfd;
8c7451
 /* Returns 0 on success, -1 when the file is locked by another process
8c7451
  * or -2 on any other error. */
8c7451
 static int lock_file()
8c7451
 {
8c7451
-	int try = 0;
8c7451
-	int ret = 0;
8c7451
-	sigset_t sigset;
8c7451
-
8c7451
-tryagain:
8c7451
-	/* the SIGINT handler will call unlock_file. To make sure the state
8c7451
-	 * of the variable locked is correct, we need to temporarily mask the
8c7451
-	 * SIGINT interrupt. */
8c7451
-	sigemptyset(&sigset);
8c7451
-	sigaddset(&sigset, SIGINT);
8c7451
-	sigprocmask(SIG_BLOCK, &sigset, NULL);
8c7451
-	lockfd = open(LOCKFILE, O_CREAT | O_EXCL | O_WRONLY, 00600);
8c7451
-	if (lockfd < 0) {
8c7451
-		if (errno == EEXIST)
8c7451
-			ret = -1;
8c7451
-		else if (try == 1)
8c7451
-			ret = -2;
8c7451
-		else {
8c7451
-			if (mkdir(LOCKDIR, 00700))
8c7451
-				ret = -2;
8c7451
-			else {
8c7451
-				try = 1;
8c7451
-				goto tryagain;
8c7451
-			}
8c7451
-		}
8c7451
-	} else {
8c7451
-		close(lockfd);
8c7451
-		locked = 1;
8c7451
-	}
8c7451
-	sigprocmask(SIG_UNBLOCK, &sigset, NULL);
8c7451
-	return ret;
8c7451
-}
8c7451
+	int fd = open(LOCKFILE, O_CREAT, 00600);
8c7451
 
8c7451
-void unlock_file()
8c7451
-{
8c7451
-	if (locked) {
8c7451
-		remove(LOCKFILE);
8c7451
-		locked = 0;
8c7451
-	}
8c7451
+	if (fd < 0)
8c7451
+		return -2;
8c7451
+	return flock(fd, LOCK_EX);
8c7451
 }
8c7451
 
8c7451
-void __attribute__ ((destructor)) onexit()
8c7451
-{
8c7451
-	if (use_lockfd)
8c7451
-		unlock_file();
8c7451
-}
8c7451
 /* Get the table from the kernel or from a binary file
8c7451
  * init: 1 = ask the kernel for the initial contents of a table, i.e. the
8c7451
  *           way it looks when the table is insmod'ed
8c7451
-- 
8c7451
2.13.1
8c7451