aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2017-01-23 17:04:19 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-01-23 17:04:19 +0000
commit850b49ca1f9c6913a9e8abf17f0b063ef438dc45 (patch)
tree2867e9a1db9cdefc87350cc09015c00579312118
parent199fce01185992c5ec923505836647ee2ca63019 (diff)
parent7ce69df55d5a599246b39b28188a6f70e4d25f31 (diff)
downloadiptables-850b49ca1f9c6913a9e8abf17f0b063ef438dc45.tar.gz
Merge "iptables: Change locking semantics."
am: 7ce69df55d Change-Id: I6d6398e84499f12408d83aad715ae7d14c53f13e
-rw-r--r--iptables/ip6tables-restore.c22
-rw-r--r--iptables/ip6tables.c2
-rw-r--r--iptables/iptables-restore.c22
-rw-r--r--iptables/iptables.c2
-rw-r--r--iptables/xshared.c16
-rw-r--r--iptables/xshared.h24
6 files changed, 67 insertions, 21 deletions
diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c
index e17ad9d2..8d097984 100644
--- a/iptables/ip6tables-restore.c
+++ b/iptables/ip6tables-restore.c
@@ -185,7 +185,7 @@ int ip6tables_restore_main(int argc, char *argv[])
{
struct xtc_handle *handle = NULL;
char buffer[10240];
- int c;
+ int c, lock;
char curtable[XT_TABLE_MAXNAMELEN + 1];
FILE *in;
int in_table = 0, testing = 0;
@@ -193,6 +193,7 @@ int ip6tables_restore_main(int argc, char *argv[])
const struct xtc_ops *ops = &ip6tc_ops;
line = 0;
+ lock = XT_LOCK_NOT_ACQUIRED;
ip6tables_globals.program_name = "ip6tables-restore";
c = xtables_init_all(&ip6tables_globals, NFPROTO_IPV6);
@@ -254,12 +255,6 @@ int ip6tables_restore_main(int argc, char *argv[])
}
else in = stdin;
- if (!xtables_lock(wait)) {
- fprintf(stderr, "Another app is currently holding the xtables lock. "
- "Perhaps you want to use the -w option?\n");
- exit(RESOURCE_PROBLEM);
- }
-
/* Grab standard input. */
while (fgets(buffer, sizeof(buffer), in)) {
int ret = 0;
@@ -283,8 +278,21 @@ int ip6tables_restore_main(int argc, char *argv[])
DEBUGP("Not calling commit, testing\n");
ret = 1;
}
+
+ /* Release the lock since we're done with the current table. */
+ if (lock >= 0) {
+ xtables_unlock(lock);
+ }
in_table = 0;
} else if ((buffer[0] == '*') && (!in_table)) {
+ /* Acquire a lock before we create a new table handle */
+ lock = xtables_lock(wait);
+ if (lock == XT_LOCK_BUSY) {
+ fprintf(stderr, "Another app is currently holding the xtables lock. "
+ "Perhaps you want to use the -w option?\n");
+ exit(RESOURCE_PROBLEM);
+ }
+
/* New table */
char *table;
diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c
index 1fb33f6d..8eefb826 100644
--- a/iptables/ip6tables.c
+++ b/iptables/ip6tables.c
@@ -1738,7 +1738,7 @@ int do_command6(int argc, char *argv[], char **table,
chain, XT_EXTENSION_MAXNAMELEN);
/* Attempt to acquire the xtables lock */
- if (!restore && !xtables_lock(wait)) {
+ if (!restore && (xtables_lock(wait) == XT_LOCK_BUSY)) {
fprintf(stderr, "Another app is currently holding the xtables lock. "
"Perhaps you want to use the -w option?\n");
xtables_free_opts(1);
diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c
index 4d49b3c9..a41a46d3 100644
--- a/iptables/iptables-restore.c
+++ b/iptables/iptables-restore.c
@@ -185,7 +185,7 @@ iptables_restore_main(int argc, char *argv[])
{
struct xtc_handle *handle = NULL;
char buffer[10240];
- int c;
+ int c, lock;
char curtable[XT_TABLE_MAXNAMELEN + 1];
FILE *in;
int in_table = 0, testing = 0;
@@ -193,6 +193,7 @@ iptables_restore_main(int argc, char *argv[])
const struct xtc_ops *ops = &iptc_ops;
line = 0;
+ lock = XT_LOCK_NOT_ACQUIRED;
iptables_globals.program_name = "iptables-restore";
c = xtables_init_all(&iptables_globals, NFPROTO_IPV4);
@@ -254,12 +255,6 @@ iptables_restore_main(int argc, char *argv[])
}
else in = stdin;
- if (!xtables_lock(wait)) {
- fprintf(stderr, "Another app is currently holding the xtables lock. "
- "Perhaps you want to use the -w option?\n");
- exit(RESOURCE_PROBLEM);
- }
-
/* Grab standard input. */
while (fgets(buffer, sizeof(buffer), in)) {
int ret = 0;
@@ -283,8 +278,21 @@ iptables_restore_main(int argc, char *argv[])
DEBUGP("Not calling commit, testing\n");
ret = 1;
}
+
+ /* Release the lock since we're done with the current table. */
+ if (lock >= 0) {
+ xtables_unlock(lock);
+ }
in_table = 0;
} else if ((buffer[0] == '*') && (!in_table)) {
+ /* Acquire a lock before we create a new table handle */
+ lock = xtables_lock(wait);
+ if (lock == XT_LOCK_BUSY) {
+ fprintf(stderr, "Another app is currently holding the xtables lock. "
+ "Perhaps you want to use the -w option?\n");
+ exit(RESOURCE_PROBLEM);
+ }
+
/* New table */
char *table;
diff --git a/iptables/iptables.c b/iptables/iptables.c
index fe18e1cc..1ace4cc3 100644
--- a/iptables/iptables.c
+++ b/iptables/iptables.c
@@ -1735,7 +1735,7 @@ int do_command4(int argc, char *argv[], char **table,
chain, XT_EXTENSION_MAXNAMELEN);
/* Attempt to acquire the xtables lock */
- if (!restore && !xtables_lock(wait)) {
+ if (!restore && (xtables_lock(wait) == XT_LOCK_BUSY)) {
fprintf(stderr, "Another app is currently holding the xtables lock. "
"Perhaps you want to use the -w option?\n");
xtables_free_opts(1);
diff --git a/iptables/xshared.c b/iptables/xshared.c
index 6c9992ed..c144b485 100644
--- a/iptables/xshared.c
+++ b/iptables/xshared.c
@@ -243,7 +243,7 @@ void xs_init_match(struct xtables_match *match)
match->init(match->m);
}
-bool xtables_lock(bool wait)
+int xtables_lock(bool wait)
{
int i = 0, ret, xt_socket;
struct sockaddr_un xt_addr;
@@ -254,18 +254,26 @@ bool xtables_lock(bool wait)
xt_socket = socket(AF_UNIX, SOCK_STREAM, 0);
/* If we can't even create a socket, fall back to prior (lockless) behavior */
if (xt_socket < 0)
- return true;
+ return XT_LOCK_UNSUPPORTED;
while (1) {
ret = bind(xt_socket, (struct sockaddr*)&xt_addr,
offsetof(struct sockaddr_un, sun_path)+XT_SOCKET_LEN);
if (ret == 0)
- return true;
+ return xt_socket;
else if (wait == false)
- return false;
+ return XT_LOCK_BUSY;
if (++i % 2 == 0)
fprintf(stderr, "Another app is currently holding the xtables lock; "
"waiting for it to exit...\n");
sleep(1);
}
}
+
+void xtables_unlock(int lock) {
+ if (lock < 0) {
+ return;
+ }
+
+ close(lock);
+}
diff --git a/iptables/xshared.h b/iptables/xshared.h
index 1e2b9b8e..9f9e8031 100644
--- a/iptables/xshared.h
+++ b/iptables/xshared.h
@@ -84,7 +84,29 @@ extern struct xtables_match *load_proto(struct iptables_command_state *);
extern int subcmd_main(int, char **, const struct subcommand *);
extern void xs_init_target(struct xtables_target *);
extern void xs_init_match(struct xtables_match *);
-extern bool xtables_lock(bool wait);
+
+/**
+ * Values for the iptables lock.
+ *
+ * A value >= 0 indicates the lock filedescriptor. Other values are:
+ *
+ * XT_LOCK_UNSUPPORTED : The system does not support locking, execution will
+ * proceed lockless.
+ *
+ * XT_LOCK_BUSY : The lock was held by another process. xtables_lock only
+ * returns this value when |wait| == false. If |wait| == true, xtables_lock
+ * will not return unless the lock has been acquired.
+ *
+ * XT_LOCK_NOT_ACQUIRED : We have not yet attempted to acquire the lock.
+ */
+enum {
+ XT_LOCK_BUSY = -1,
+ XT_LOCK_UNSUPPORTED = -2,
+ XT_LOCK_NOT_ACQUIRED = -3,
+};
+extern int xtables_lock(bool wait);
+
+extern void xtables_unlock(int lock);
extern const struct xtables_afinfo *afinfo;