@@ -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
@@ -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 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
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;