This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
The following commit(s) were added to refs/heads/master by this push:
new 2b0a4a20f iptables: add file lock to prevent concurrent overwrite
2b0a4a20f is described below
commit 2b0a4a20f55278461248031f5d7078520c492f50
Author: zhanghongyu <[email protected]>
AuthorDate: Wed Aug 20 20:05:59 2025 +0800
iptables: add file lock to prevent concurrent overwrite
the kernel can only prevent the concurrency of s/getsockopt, but
iptables will call these interfaces multiple times at a time. We
need to wait for one iptables to complete before executing the second
one, otherwise the data will be overwritten.
iptables flow:
get current iptables entries [1] -> add new entry 2 [1,2] -> set to kernel
[1,2]
get current iptables entries [1] -> add new entry 3 [1,3] -> set to kernel
[1,3]
entry 2 is lost
Signed-off-by: zhanghongyu <[email protected]>
---
system/iptables/Kconfig | 5 ++++
system/iptables/iptables.c | 58 +++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 62 insertions(+), 1 deletion(-)
diff --git a/system/iptables/Kconfig b/system/iptables/Kconfig
index 171b52ed0..a98f00771 100644
--- a/system/iptables/Kconfig
+++ b/system/iptables/Kconfig
@@ -29,4 +29,9 @@ config SYSTEM_IPTABLES_STACKSIZE
int "iptables & ip6tables stack size"
default DEFAULT_TASK_STACKSIZE
+config SYSTEM_IPTABLES_LOCK_FILE_PATH
+ string "File lock path to prevent concurrent overwrite"
+ default "/tmp/iptables.lock"
+ depends on FS_LOCK_BUCKET_SIZE > 0
+
endif
diff --git a/system/iptables/iptables.c b/system/iptables/iptables.c
index 673559634..367519a34 100644
--- a/system/iptables/iptables.c
+++ b/system/iptables/iptables.c
@@ -26,6 +26,7 @@
#include <nuttx/config.h>
+#include <fcntl.h>
#include <arpa/inet.h>
#include <nuttx/net/netfilter/ip_tables.h>
@@ -33,17 +34,62 @@
#include "iptables.h"
#include "netutils/netlib.h"
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#if CONFIG_FS_LOCK_BUCKET_SIZE == 0
+# define iptables_lock() 0
+# define iptables_unlock(fd) (void)(fd)
+#endif
+
/****************************************************************************
* Private Types
****************************************************************************/
typedef CODE int
- (*iptables_command_func_t)(FAR const struct iptables_args_s *args);
+(*iptables_command_func_t)(FAR const struct iptables_args_s *args);
/****************************************************************************
* Private Functions
****************************************************************************/
+/****************************************************************************
+ * Name: iptables_lock / iptables_unlock
+ *
+ * Description:
+ * Lock and unlock iptables to prevent concurrent overwrite.
+ *
+ ****************************************************************************/
+
+#if CONFIG_FS_LOCK_BUCKET_SIZE > 0
+static int iptables_lock(void)
+{
+ struct flock lock;
+ int lockfd;
+
+ lockfd = open(CONFIG_SYSTEM_IPTABLES_LOCK_FILE_PATH, O_CREAT | O_RDWR,
+ 0666);
+ if (lockfd < 0)
+ {
+ return lockfd;
+ }
+
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ fcntl(lockfd, F_SETLKW, &lock);
+
+ return lockfd;
+}
+
+static int iptables_unlock(int lockfd)
+{
+ return close(lockfd);
+}
+#endif
+
/****************************************************************************
* Name: iptables_addr2str
*
@@ -485,6 +531,7 @@ static int iptables_apply(FAR const struct iptables_args_s
*args,
int main(int argc, FAR char *argv[])
{
struct iptables_args_s args;
+ int lock;
int ret = iptables_parse(&args, argc, argv);
if (ret < 0 || args.cmd == COMMAND_INVALID)
@@ -493,6 +540,13 @@ int main(int argc, FAR char *argv[])
return ret;
}
+ lock = iptables_lock();
+ if (lock < 0)
+ {
+ printf("Failed to lock iptables!\n");
+ return lock;
+ }
+
#ifdef CONFIG_NET_IPFILTER
if (args.table == NULL || strcmp(args.table, XT_TABLE_NAME_FILTER) == 0)
{
@@ -520,5 +574,7 @@ int main(int argc, FAR char *argv[])
printf("Unknown table: %s\n", args.table);
}
+ iptables_unlock(lock);
+
return ret;
}