summaryrefslogtreecommitdiffstats
path: root/libebtc.c
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2017-10-06 12:48:50 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2017-10-24 17:56:32 +0200
commit6a826591878db3fa9e2a94b87a3d5edd8e0fc442 (patch)
tree2e2202491027f2c52a45022c75722a77aff7f5c1 /libebtc.c
parent73c2371744c08c677540d468a588586effecab2d (diff)
Use flock() for --concurrent option
The previous locking mechanism was not atomic, hence it was possible that a killed ebtables process would leave the lock file in place which in turn made future ebtables processes wait indefinitely for the lock to become free. Fix this by using flock(). This also simplifies code quite a bit because there is no need for a custom signal handler or an __exit routine anymore. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'libebtc.c')
-rw-r--r--libebtc.c49
1 files changed, 5 insertions, 44 deletions
diff --git a/libebtc.c b/libebtc.c
index 74830ec..c0ff8cc 100644
--- a/libebtc.c
+++ b/libebtc.c
@@ -31,6 +31,7 @@
#include "include/ethernetdb.h"
#include <unistd.h>
#include <fcntl.h>
+#include <sys/file.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -137,58 +138,18 @@ void ebt_list_extensions()
#define LOCKDIR "/var/lib/ebtables"
#define LOCKFILE LOCKDIR"/lock"
#endif
-static int lockfd = -1, locked;
int use_lockfd;
/* Returns 0 on success, -1 when the file is locked by another process
* or -2 on any other error. */
static int lock_file()
{
- int try = 0;
- int ret = 0;
- sigset_t sigset;
-
-tryagain:
- /* the SIGINT handler will call unlock_file. To make sure the state
- * of the variable locked is correct, we need to temporarily mask the
- * SIGINT interrupt. */
- sigemptyset(&sigset);
- sigaddset(&sigset, SIGINT);
- sigprocmask(SIG_BLOCK, &sigset, NULL);
- lockfd = open(LOCKFILE, O_CREAT | O_EXCL | O_WRONLY, 00600);
- if (lockfd < 0) {
- if (errno == EEXIST)
- ret = -1;
- else if (try == 1)
- ret = -2;
- else {
- if (mkdir(LOCKDIR, 00700))
- ret = -2;
- else {
- try = 1;
- goto tryagain;
- }
- }
- } else {
- close(lockfd);
- locked = 1;
- }
- sigprocmask(SIG_UNBLOCK, &sigset, NULL);
- return ret;
-}
+ int fd = open(LOCKFILE, O_CREAT, 00600);
-void unlock_file()
-{
- if (locked) {
- remove(LOCKFILE);
- locked = 0;
- }
+ if (fd < 0)
+ return -2;
+ return flock(fd, LOCK_EX);
}
-void __attribute__ ((destructor)) onexit()
-{
- if (use_lockfd)
- unlock_file();
-}
/* Get the table from the kernel or from a binary file
* init: 1 = ask the kernel for the initial contents of a table, i.e. the
* way it looks when the table is insmod'ed