Skip to content

Commit c520292

Browse files
rgbriggsummakynes
authored andcommitted
audit: log nftables configuration change events once per table
Reduce logging of nftables events to a level similar to iptables. Restore the table field to list the table, adding the generation. Indicate the op as the most significant operation in the event. A couple of sample events: type=PROCTITLE msg=audit(2021-03-18 09:30:49.801:143) : proctitle=/usr/bin/python3 -s /usr/sbin/firewalld --nofork --nopid type=SYSCALL msg=audit(2021-03-18 09:30:49.801:143) : arch=x86_64 syscall=sendmsg success=yes exit=172 a0=0x6 a1=0x7ffdcfcbe650 a2=0x0 a3=0x7ffdcfcbd52c items=0 ppid=1 pid=367 auid=unset uid=root gid=root euid=root suid=root fsuid=root egid=roo t sgid=root fsgid=root tty=(none) ses=unset comm=firewalld exe=/usr/bin/python3.9 subj=system_u:system_r:firewalld_t:s0 key=(null) type=NETFILTER_CFG msg=audit(2021-03-18 09:30:49.801:143) : table=firewalld:2 family=ipv6 entries=1 op=nft_register_table pid=367 subj=system_u:system_r:firewalld_t:s0 comm=firewalld type=NETFILTER_CFG msg=audit(2021-03-18 09:30:49.801:143) : table=firewalld:2 family=ipv4 entries=1 op=nft_register_table pid=367 subj=system_u:system_r:firewalld_t:s0 comm=firewalld type=NETFILTER_CFG msg=audit(2021-03-18 09:30:49.801:143) : table=firewalld:2 family=inet entries=1 op=nft_register_table pid=367 subj=system_u:system_r:firewalld_t:s0 comm=firewalld type=PROCTITLE msg=audit(2021-03-18 09:30:49.839:144) : proctitle=/usr/bin/python3 -s /usr/sbin/firewalld --nofork --nopid type=SYSCALL msg=audit(2021-03-18 09:30:49.839:144) : arch=x86_64 syscall=sendmsg success=yes exit=22792 a0=0x6 a1=0x7ffdcfcbe650 a2=0x0 a3=0x7ffdcfcbd52c items=0 ppid=1 pid=367 auid=unset uid=root gid=root euid=root suid=root fsuid=root egid=r oot sgid=root fsgid=root tty=(none) ses=unset comm=firewalld exe=/usr/bin/python3.9 subj=system_u:system_r:firewalld_t:s0 key=(null) type=NETFILTER_CFG msg=audit(2021-03-18 09:30:49.839:144) : table=firewalld:3 family=ipv6 entries=30 op=nft_register_chain pid=367 subj=system_u:system_r:firewalld_t:s0 comm=firewalld type=NETFILTER_CFG msg=audit(2021-03-18 09:30:49.839:144) : table=firewalld:3 family=ipv4 entries=30 op=nft_register_chain pid=367 subj=system_u:system_r:firewalld_t:s0 comm=firewalld type=NETFILTER_CFG msg=audit(2021-03-18 09:30:49.839:144) : table=firewalld:3 family=inet entries=165 op=nft_register_chain pid=367 subj=system_u:system_r:firewalld_t:s0 comm=firewalld The issue was originally documented in linux-audit/audit-kernel#124 Signed-off-by: Richard Guy Briggs <rgb@redhat.com> Acked-by: Paul Moore <paul@paul-moore.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent cefa31a commit c520292

File tree

1 file changed

+103
-83
lines changed

1 file changed

+103
-83
lines changed

net/netfilter/nf_tables_api.c

Lines changed: 103 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,41 @@ static const struct rhashtable_params nft_objname_ht_params = {
6666
.automatic_shrinking = true,
6767
};
6868

69+
struct nft_audit_data {
70+
struct nft_table *table;
71+
int entries;
72+
int op;
73+
struct list_head list;
74+
};
75+
76+
static const u8 nft2audit_op[NFT_MSG_MAX] = { // enum nf_tables_msg_types
77+
[NFT_MSG_NEWTABLE] = AUDIT_NFT_OP_TABLE_REGISTER,
78+
[NFT_MSG_GETTABLE] = AUDIT_NFT_OP_INVALID,
79+
[NFT_MSG_DELTABLE] = AUDIT_NFT_OP_TABLE_UNREGISTER,
80+
[NFT_MSG_NEWCHAIN] = AUDIT_NFT_OP_CHAIN_REGISTER,
81+
[NFT_MSG_GETCHAIN] = AUDIT_NFT_OP_INVALID,
82+
[NFT_MSG_DELCHAIN] = AUDIT_NFT_OP_CHAIN_UNREGISTER,
83+
[NFT_MSG_NEWRULE] = AUDIT_NFT_OP_RULE_REGISTER,
84+
[NFT_MSG_GETRULE] = AUDIT_NFT_OP_INVALID,
85+
[NFT_MSG_DELRULE] = AUDIT_NFT_OP_RULE_UNREGISTER,
86+
[NFT_MSG_NEWSET] = AUDIT_NFT_OP_SET_REGISTER,
87+
[NFT_MSG_GETSET] = AUDIT_NFT_OP_INVALID,
88+
[NFT_MSG_DELSET] = AUDIT_NFT_OP_SET_UNREGISTER,
89+
[NFT_MSG_NEWSETELEM] = AUDIT_NFT_OP_SETELEM_REGISTER,
90+
[NFT_MSG_GETSETELEM] = AUDIT_NFT_OP_INVALID,
91+
[NFT_MSG_DELSETELEM] = AUDIT_NFT_OP_SETELEM_UNREGISTER,
92+
[NFT_MSG_NEWGEN] = AUDIT_NFT_OP_GEN_REGISTER,
93+
[NFT_MSG_GETGEN] = AUDIT_NFT_OP_INVALID,
94+
[NFT_MSG_TRACE] = AUDIT_NFT_OP_INVALID,
95+
[NFT_MSG_NEWOBJ] = AUDIT_NFT_OP_OBJ_REGISTER,
96+
[NFT_MSG_GETOBJ] = AUDIT_NFT_OP_INVALID,
97+
[NFT_MSG_DELOBJ] = AUDIT_NFT_OP_OBJ_UNREGISTER,
98+
[NFT_MSG_GETOBJ_RESET] = AUDIT_NFT_OP_OBJ_RESET,
99+
[NFT_MSG_NEWFLOWTABLE] = AUDIT_NFT_OP_FLOWTABLE_REGISTER,
100+
[NFT_MSG_GETFLOWTABLE] = AUDIT_NFT_OP_INVALID,
101+
[NFT_MSG_DELFLOWTABLE] = AUDIT_NFT_OP_FLOWTABLE_UNREGISTER,
102+
};
103+
69104
static void nft_validate_state_update(struct net *net, u8 new_validate_state)
70105
{
71106
switch (net->nft.validate_state) {
@@ -718,17 +753,6 @@ static void nf_tables_table_notify(const struct nft_ctx *ctx, int event)
718753
{
719754
struct sk_buff *skb;
720755
int err;
721-
char *buf = kasprintf(GFP_KERNEL, "%s:%llu;?:0",
722-
ctx->table->name, ctx->table->handle);
723-
724-
audit_log_nfcfg(buf,
725-
ctx->family,
726-
ctx->table->use,
727-
event == NFT_MSG_NEWTABLE ?
728-
AUDIT_NFT_OP_TABLE_REGISTER :
729-
AUDIT_NFT_OP_TABLE_UNREGISTER,
730-
GFP_KERNEL);
731-
kfree(buf);
732756

733757
if (!ctx->report &&
734758
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
@@ -1502,18 +1526,6 @@ static void nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
15021526
{
15031527
struct sk_buff *skb;
15041528
int err;
1505-
char *buf = kasprintf(GFP_KERNEL, "%s:%llu;%s:%llu",
1506-
ctx->table->name, ctx->table->handle,
1507-
ctx->chain->name, ctx->chain->handle);
1508-
1509-
audit_log_nfcfg(buf,
1510-
ctx->family,
1511-
ctx->chain->use,
1512-
event == NFT_MSG_NEWCHAIN ?
1513-
AUDIT_NFT_OP_CHAIN_REGISTER :
1514-
AUDIT_NFT_OP_CHAIN_UNREGISTER,
1515-
GFP_KERNEL);
1516-
kfree(buf);
15171529

15181530
if (!ctx->report &&
15191531
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
@@ -2866,18 +2878,6 @@ static void nf_tables_rule_notify(const struct nft_ctx *ctx,
28662878
{
28672879
struct sk_buff *skb;
28682880
int err;
2869-
char *buf = kasprintf(GFP_KERNEL, "%s:%llu;%s:%llu",
2870-
ctx->table->name, ctx->table->handle,
2871-
ctx->chain->name, ctx->chain->handle);
2872-
2873-
audit_log_nfcfg(buf,
2874-
ctx->family,
2875-
rule->handle,
2876-
event == NFT_MSG_NEWRULE ?
2877-
AUDIT_NFT_OP_RULE_REGISTER :
2878-
AUDIT_NFT_OP_RULE_UNREGISTER,
2879-
GFP_KERNEL);
2880-
kfree(buf);
28812881

28822882
if (!ctx->report &&
28832883
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
@@ -3912,18 +3912,6 @@ static void nf_tables_set_notify(const struct nft_ctx *ctx,
39123912
struct sk_buff *skb;
39133913
u32 portid = ctx->portid;
39143914
int err;
3915-
char *buf = kasprintf(gfp_flags, "%s:%llu;%s:%llu",
3916-
ctx->table->name, ctx->table->handle,
3917-
set->name, set->handle);
3918-
3919-
audit_log_nfcfg(buf,
3920-
ctx->family,
3921-
set->field_count,
3922-
event == NFT_MSG_NEWSET ?
3923-
AUDIT_NFT_OP_SET_REGISTER :
3924-
AUDIT_NFT_OP_SET_UNREGISTER,
3925-
gfp_flags);
3926-
kfree(buf);
39273915

39283916
if (!ctx->report &&
39293917
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
@@ -5108,18 +5096,6 @@ static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
51085096
u32 portid = ctx->portid;
51095097
struct sk_buff *skb;
51105098
int err;
5111-
char *buf = kasprintf(GFP_KERNEL, "%s:%llu;%s:%llu",
5112-
ctx->table->name, ctx->table->handle,
5113-
set->name, set->handle);
5114-
5115-
audit_log_nfcfg(buf,
5116-
ctx->family,
5117-
set->handle,
5118-
event == NFT_MSG_NEWSETELEM ?
5119-
AUDIT_NFT_OP_SETELEM_REGISTER :
5120-
AUDIT_NFT_OP_SETELEM_UNREGISTER,
5121-
GFP_KERNEL);
5122-
kfree(buf);
51235099

51245100
if (!ctx->report && !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
51255101
return;
@@ -6321,12 +6297,11 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
63216297
filter->type != NFT_OBJECT_UNSPEC &&
63226298
obj->ops->type->type != filter->type)
63236299
goto cont;
6324-
63256300
if (reset) {
63266301
char *buf = kasprintf(GFP_ATOMIC,
6327-
"%s:%llu;?:0",
6302+
"%s:%u",
63286303
table->name,
6329-
table->handle);
6304+
net->nft.base_seq);
63306305

63316306
audit_log_nfcfg(buf,
63326307
family,
@@ -6447,8 +6422,8 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk,
64476422
reset = true;
64486423

64496424
if (reset) {
6450-
char *buf = kasprintf(GFP_ATOMIC, "%s:%llu;?:0",
6451-
table->name, table->handle);
6425+
char *buf = kasprintf(GFP_ATOMIC, "%s:%u",
6426+
table->name, net->nft.base_seq);
64526427

64536428
audit_log_nfcfg(buf,
64546429
family,
@@ -6536,15 +6511,15 @@ void nft_obj_notify(struct net *net, const struct nft_table *table,
65366511
{
65376512
struct sk_buff *skb;
65386513
int err;
6539-
char *buf = kasprintf(gfp, "%s:%llu;?:0",
6540-
table->name, table->handle);
6514+
char *buf = kasprintf(gfp, "%s:%u",
6515+
table->name, net->nft.base_seq);
65416516

65426517
audit_log_nfcfg(buf,
65436518
family,
65446519
obj->handle,
65456520
event == NFT_MSG_NEWOBJ ?
6546-
AUDIT_NFT_OP_OBJ_REGISTER :
6547-
AUDIT_NFT_OP_OBJ_UNREGISTER,
6521+
AUDIT_NFT_OP_OBJ_REGISTER :
6522+
AUDIT_NFT_OP_OBJ_UNREGISTER,
65486523
gfp);
65496524
kfree(buf);
65506525

@@ -7362,18 +7337,6 @@ static void nf_tables_flowtable_notify(struct nft_ctx *ctx,
73627337
{
73637338
struct sk_buff *skb;
73647339
int err;
7365-
char *buf = kasprintf(GFP_KERNEL, "%s:%llu;%s:%llu",
7366-
flowtable->table->name, flowtable->table->handle,
7367-
flowtable->name, flowtable->handle);
7368-
7369-
audit_log_nfcfg(buf,
7370-
ctx->family,
7371-
flowtable->hooknum,
7372-
event == NFT_MSG_NEWFLOWTABLE ?
7373-
AUDIT_NFT_OP_FLOWTABLE_REGISTER :
7374-
AUDIT_NFT_OP_FLOWTABLE_UNREGISTER,
7375-
GFP_KERNEL);
7376-
kfree(buf);
73777340

73787341
if (!ctx->report &&
73797342
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
@@ -7494,9 +7457,6 @@ static void nf_tables_gen_notify(struct net *net, struct sk_buff *skb,
74947457
struct sk_buff *skb2;
74957458
int err;
74967459

7497-
audit_log_nfcfg("?:0;?:0", 0, net->nft.base_seq,
7498-
AUDIT_NFT_OP_GEN_REGISTER, GFP_KERNEL);
7499-
75007460
if (!nlmsg_report(nlh) &&
75017461
!nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
75027462
return;
@@ -8035,12 +7995,64 @@ static void nft_commit_notify(struct net *net, u32 portid)
80357995
WARN_ON_ONCE(!list_empty(&net->nft.notify_list));
80367996
}
80377997

7998+
static int nf_tables_commit_audit_alloc(struct list_head *adl,
7999+
struct nft_table *table)
8000+
{
8001+
struct nft_audit_data *adp;
8002+
8003+
list_for_each_entry(adp, adl, list) {
8004+
if (adp->table == table)
8005+
return 0;
8006+
}
8007+
adp = kzalloc(sizeof(*adp), GFP_KERNEL);
8008+
if (!adp)
8009+
return -ENOMEM;
8010+
adp->table = table;
8011+
list_add(&adp->list, adl);
8012+
return 0;
8013+
}
8014+
8015+
static void nf_tables_commit_audit_collect(struct list_head *adl,
8016+
struct nft_table *table, u32 op)
8017+
{
8018+
struct nft_audit_data *adp;
8019+
8020+
list_for_each_entry(adp, adl, list) {
8021+
if (adp->table == table)
8022+
goto found;
8023+
}
8024+
WARN_ONCE("table=%s not expected in commit list", table->name);
8025+
return;
8026+
found:
8027+
adp->entries++;
8028+
if (!adp->op || adp->op > op)
8029+
adp->op = op;
8030+
}
8031+
8032+
#define AUNFTABLENAMELEN (NFT_TABLE_MAXNAMELEN + 22)
8033+
8034+
static void nf_tables_commit_audit_log(struct list_head *adl, u32 generation)
8035+
{
8036+
struct nft_audit_data *adp, *adn;
8037+
char aubuf[AUNFTABLENAMELEN];
8038+
8039+
list_for_each_entry_safe(adp, adn, adl, list) {
8040+
snprintf(aubuf, AUNFTABLENAMELEN, "%s:%u", adp->table->name,
8041+
generation);
8042+
audit_log_nfcfg(aubuf, adp->table->family, adp->entries,
8043+
nft2audit_op[adp->op], GFP_KERNEL);
8044+
list_del(&adp->list);
8045+
kfree(adp);
8046+
}
8047+
}
8048+
80388049
static int nf_tables_commit(struct net *net, struct sk_buff *skb)
80398050
{
80408051
struct nft_trans *trans, *next;
80418052
struct nft_trans_elem *te;
80428053
struct nft_chain *chain;
80438054
struct nft_table *table;
8055+
LIST_HEAD(adl);
80448056
int err;
80458057

80468058
if (list_empty(&net->nft.commit_list)) {
@@ -8060,6 +8072,11 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
80608072
list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
80618073
int ret;
80628074

8075+
ret = nf_tables_commit_audit_alloc(&adl, trans->ctx.table);
8076+
if (ret) {
8077+
nf_tables_commit_chain_prepare_cancel(net);
8078+
return ret;
8079+
}
80638080
if (trans->msg_type == NFT_MSG_NEWRULE ||
80648081
trans->msg_type == NFT_MSG_DELRULE) {
80658082
chain = trans->ctx.chain;
@@ -8088,6 +8105,8 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
80888105
net->nft.gencursor = nft_gencursor_next(net);
80898106

80908107
list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
8108+
nf_tables_commit_audit_collect(&adl, trans->ctx.table,
8109+
trans->msg_type);
80918110
switch (trans->msg_type) {
80928111
case NFT_MSG_NEWTABLE:
80938112
if (nft_trans_table_update(trans)) {
@@ -8240,6 +8259,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
82408259

82418260
nft_commit_notify(net, NETLINK_CB(skb).portid);
82428261
nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN);
8262+
nf_tables_commit_audit_log(&adl, net->nft.base_seq);
82438263
nf_tables_commit_release(net);
82448264

82458265
return 0;

0 commit comments

Comments
 (0)