Commit 7e9be112 authored by Phil Sutter's avatar Phil Sutter Committed by Pablo Neira Ayuso
Browse files

netfilter: nf_tables: Audit log setelem reset



Since set element reset is not integrated into nf_tables' transaction
logic, an explicit log call is needed, similar to NFT_MSG_GETOBJ_RESET
handling.

For the sake of simplicity, catchall element reset will always generate
a dedicated log entry. This relieves nf_tables_dump_set() from having to
adjust the logged element count depending on whether a catchall element
was found or not.

Fixes: 079cd633 ("netfilter: nf_tables: Introduce NFT_MSG_GETSETELEM_RESET")
Signed-off-by: default avatarPhil Sutter <phil@nwl.cc>
Reviewed-by: default avatarRichard Guy Briggs <rgb@redhat.com>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 69c5d284
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -117,6 +117,7 @@ enum audit_nfcfgop {
	AUDIT_NFT_OP_OBJ_RESET,
	AUDIT_NFT_OP_FLOWTABLE_REGISTER,
	AUDIT_NFT_OP_FLOWTABLE_UNREGISTER,
	AUDIT_NFT_OP_SETELEM_RESET,
	AUDIT_NFT_OP_INVALID,
};

+1 −0
Original line number Diff line number Diff line
@@ -143,6 +143,7 @@ static const struct audit_nfcfgop_tab audit_nfcfgs[] = {
	{ AUDIT_NFT_OP_OBJ_RESET,		"nft_reset_obj"		   },
	{ AUDIT_NFT_OP_FLOWTABLE_REGISTER,	"nft_register_flowtable"   },
	{ AUDIT_NFT_OP_FLOWTABLE_UNREGISTER,	"nft_unregister_flowtable" },
	{ AUDIT_NFT_OP_SETELEM_RESET,		"nft_reset_setelem"        },
	{ AUDIT_NFT_OP_INVALID,			"nft_invalid"		   },
};

+28 −3
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ static const u8 nft2audit_op[NFT_MSG_MAX] = { // enum nf_tables_msg_types
	[NFT_MSG_NEWFLOWTABLE]	= AUDIT_NFT_OP_FLOWTABLE_REGISTER,
	[NFT_MSG_GETFLOWTABLE]	= AUDIT_NFT_OP_INVALID,
	[NFT_MSG_DELFLOWTABLE]	= AUDIT_NFT_OP_FLOWTABLE_UNREGISTER,
	[NFT_MSG_GETSETELEM_RESET] = AUDIT_NFT_OP_SETELEM_RESET,
};

static void nft_validate_state_update(struct nft_table *table, u8 new_validate_state)
@@ -5624,13 +5625,25 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
	return nf_tables_fill_setelem(args->skb, set, elem, args->reset);
}

static void audit_log_nft_set_reset(const struct nft_table *table,
				    unsigned int base_seq,
				    unsigned int nentries)
{
	char *buf = kasprintf(GFP_ATOMIC, "%s:%u", table->name, base_seq);

	audit_log_nfcfg(buf, table->family, nentries,
			AUDIT_NFT_OP_SETELEM_RESET, GFP_ATOMIC);
	kfree(buf);
}

struct nft_set_dump_ctx {
	const struct nft_set	*set;
	struct nft_ctx		ctx;
};

static int nft_set_catchall_dump(struct net *net, struct sk_buff *skb,
				 const struct nft_set *set, bool reset)
				 const struct nft_set *set, bool reset,
				 unsigned int base_seq)
{
	struct nft_set_elem_catchall *catchall;
	u8 genmask = nft_genmask_cur(net);
@@ -5646,6 +5659,8 @@ static int nft_set_catchall_dump(struct net *net, struct sk_buff *skb,

		elem.priv = catchall->elem;
		ret = nf_tables_fill_setelem(skb, set, &elem, reset);
		if (reset && !ret)
			audit_log_nft_set_reset(set->table, base_seq, 1);
		break;
	}

@@ -5725,12 +5740,17 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
	set->ops->walk(&dump_ctx->ctx, set, &args.iter);

	if (!args.iter.err && args.iter.count == cb->args[0])
		args.iter.err = nft_set_catchall_dump(net, skb, set, reset);
		args.iter.err = nft_set_catchall_dump(net, skb, set,
						      reset, cb->seq);
	rcu_read_unlock();

	nla_nest_end(skb, nest);
	nlmsg_end(skb, nlh);

	if (reset && args.iter.count > args.iter.skip)
		audit_log_nft_set_reset(table, cb->seq,
					args.iter.count - args.iter.skip);

	if (args.iter.err && args.iter.err != -EMSGSIZE)
		return args.iter.err;
	if (args.iter.count == cb->args[0])
@@ -5955,13 +5975,13 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
	struct netlink_ext_ack *extack = info->extack;
	u8 genmask = nft_genmask_cur(info->net);
	u8 family = info->nfmsg->nfgen_family;
	int rem, err = 0, nelems = 0;
	struct net *net = info->net;
	struct nft_table *table;
	struct nft_set *set;
	struct nlattr *attr;
	struct nft_ctx ctx;
	bool reset = false;
	int rem, err = 0;

	table = nft_table_lookup(net, nla[NFTA_SET_ELEM_LIST_TABLE], family,
				 genmask, 0);
@@ -6004,8 +6024,13 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
			NL_SET_BAD_ATTR(extack, attr);
			break;
		}
		nelems++;
	}

	if (reset)
		audit_log_nft_set_reset(table, nft_pernet(net)->base_seq,
					nelems);

	return err;
}