]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
netfilter: nf_tables: Introduce NFT_TABLE_F_PERSIST
authorPhil Sutter <phil@nwl.cc>
Thu, 21 Dec 2023 13:31:58 +0000 (14:31 +0100)
committerFlorian Westphal <fw@strlen.de>
Mon, 29 Jan 2024 14:43:20 +0000 (15:43 +0100)
This companion flag to NFT_TABLE_F_OWNER requests the kernel to keep the
table around after the process has exited. It marks such table as
orphaned (by dropping OWNER flag but keeping PERSIST flag in place),
which opens it for other processes to manipulate. For the sake of
simplicity, PERSIST flag may not be altered though.

Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
include/uapi/linux/netfilter/nf_tables.h
net/netfilter/nf_tables_api.c

index fbce238abdc16d03db0b20107e58818817487de4..3fee994721cd64ceb36d468f0bd3e261f1bc1ce0 100644 (file)
@@ -180,13 +180,16 @@ enum nft_hook_attributes {
  *
  * @NFT_TABLE_F_DORMANT: this table is not active
  * @NFT_TABLE_F_OWNER:   this table is owned by a process
+ * @NFT_TABLE_F_PERSIST: this table shall outlive its owner
  */
 enum nft_table_flags {
        NFT_TABLE_F_DORMANT     = 0x1,
        NFT_TABLE_F_OWNER       = 0x2,
+       NFT_TABLE_F_PERSIST     = 0x4,
 };
 #define NFT_TABLE_F_MASK       (NFT_TABLE_F_DORMANT | \
-                                NFT_TABLE_F_OWNER)
+                                NFT_TABLE_F_OWNER | \
+                                NFT_TABLE_F_PERSIST)
 
 /**
  * enum nft_table_attributes - nf_tables table netlink attributes
index c537104411e7d1b1c1b449b55c7a3c43fb7e2ac3..6a96f0003faa96cc231595cf2f91297eb75453b9 100644 (file)
@@ -1219,6 +1219,9 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
             flags & NFT_TABLE_F_OWNER))
                return -EOPNOTSUPP;
 
+       if ((flags ^ ctx->table->flags) & NFT_TABLE_F_PERSIST)
+               return -EOPNOTSUPP;
+
        /* No dormant off/on/off/on games in single transaction */
        if (ctx->table->flags & __NFT_TABLE_F_UPDATE)
                return -EINVAL;
@@ -11345,6 +11348,10 @@ again:
        list_for_each_entry(table, &nft_net->tables, list) {
                if (nft_table_has_owner(table) &&
                    n->portid == table->nlpid) {
+                       if (table->flags & NFT_TABLE_F_PERSIST) {
+                               table->flags &= ~NFT_TABLE_F_OWNER;
+                               continue;
+                       }
                        __nft_release_hook(net, table);
                        list_del_rcu(&table->list);
                        to_delete[deleted++] = table;