Blame SOURCES/0012-Use-flock-for-concurrent-option.patch

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