Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 46c2947f authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso Committed by Greg Kroah-Hartman
Browse files

netfilter: nftables: update table flags from the commit phase



commit 0ce7cf4127f14078ca598ba9700d813178a59409 upstream.

Do not update table flags from the preparation phase. Store the flags
update into the transaction, then update the flags from the commit
phase.

Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent b09e6ccf
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -1392,13 +1392,16 @@ struct nft_trans_chain {

struct nft_trans_table {
	bool				update;
	bool				enable;
	u8				state;
	u32				flags;
};

#define nft_trans_table_update(trans)	\
	(((struct nft_trans_table *)trans->data)->update)
#define nft_trans_table_enable(trans)	\
	(((struct nft_trans_table *)trans->data)->enable)
#define nft_trans_table_state(trans)	\
	(((struct nft_trans_table *)trans->data)->state)
#define nft_trans_table_flags(trans)	\
	(((struct nft_trans_table *)trans->data)->flags)

struct nft_trans_elem {
	struct nft_set			*set;
+16 −15
Original line number Diff line number Diff line
@@ -893,6 +893,12 @@ static void nf_tables_table_disable(struct net *net, struct nft_table *table)
	nft_table_disable(net, table, 0);
}

enum {
	NFT_TABLE_STATE_UNCHANGED	= 0,
	NFT_TABLE_STATE_DORMANT,
	NFT_TABLE_STATE_WAKEUP
};

static int nf_tables_updtable(struct nft_ctx *ctx)
{
	struct nft_trans *trans;
@@ -916,19 +922,17 @@ static int nf_tables_updtable(struct nft_ctx *ctx)

	if ((flags & NFT_TABLE_F_DORMANT) &&
	    !(ctx->table->flags & NFT_TABLE_F_DORMANT)) {
		nft_trans_table_enable(trans) = false;
		nft_trans_table_state(trans) = NFT_TABLE_STATE_DORMANT;
	} else if (!(flags & NFT_TABLE_F_DORMANT) &&
		   ctx->table->flags & NFT_TABLE_F_DORMANT) {
		ctx->table->flags &= ~NFT_TABLE_F_DORMANT;
		ret = nf_tables_table_enable(ctx->net, ctx->table);
		if (ret >= 0)
			nft_trans_table_enable(trans) = true;
		else
			ctx->table->flags |= NFT_TABLE_F_DORMANT;
			nft_trans_table_state(trans) = NFT_TABLE_STATE_WAKEUP;
	}
	if (ret < 0)
		goto err;

	nft_trans_table_flags(trans) = flags;
	nft_trans_table_update(trans) = true;
	nft_trans_commit_list_add_tail(ctx->net, trans);
	return 0;
@@ -7298,11 +7302,10 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
		switch (trans->msg_type) {
		case NFT_MSG_NEWTABLE:
			if (nft_trans_table_update(trans)) {
				if (!nft_trans_table_enable(trans)) {
					nf_tables_table_disable(net,
								trans->ctx.table);
					trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
				}
				if (nft_trans_table_state(trans) == NFT_TABLE_STATE_DORMANT)
					nf_tables_table_disable(net, trans->ctx.table);

				trans->ctx.table->flags = nft_trans_table_flags(trans);
			} else {
				nft_clear(net, trans->ctx.table);
			}
@@ -7497,11 +7500,9 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
		switch (trans->msg_type) {
		case NFT_MSG_NEWTABLE:
			if (nft_trans_table_update(trans)) {
				if (nft_trans_table_enable(trans)) {
					nf_tables_table_disable(net,
								trans->ctx.table);
					trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
				}
				if (nft_trans_table_state(trans) == NFT_TABLE_STATE_WAKEUP)
					nf_tables_table_disable(net, trans->ctx.table);

				nft_trans_destroy(trans);
			} else {
				list_del_rcu(&trans->ctx.table->list);