Skip to content
Permalink
Browse files
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>
  • Loading branch information
rgbriggs authored and intel-lab-lkp committed Mar 18, 2021
1 parent 5504a69 commit 6c3d6ac0f39a29e8474b0ff59609e3c3168339c0
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 83 deletions.
@@ -118,6 +118,35 @@ enum audit_nfcfgop {
AUDIT_NFT_OP_INVALID,
};

static const u8 nft2audit_op[] = { // enum nf_tables_msg_types
/* NFT_MSG_NEWTABLE */ AUDIT_NFT_OP_TABLE_REGISTER,
/* NFT_MSG_GETTABLE */ AUDIT_NFT_OP_INVALID,
/* NFT_MSG_DELTABLE */ AUDIT_NFT_OP_TABLE_UNREGISTER,
/* NFT_MSG_NEWCHAIN */ AUDIT_NFT_OP_CHAIN_REGISTER,
/* NFT_MSG_GETCHAIN */ AUDIT_NFT_OP_INVALID,
/* NFT_MSG_DELCHAIN */ AUDIT_NFT_OP_CHAIN_UNREGISTER,
/* NFT_MSG_NEWRULE */ AUDIT_NFT_OP_RULE_REGISTER,
/* NFT_MSG_GETRULE */ AUDIT_NFT_OP_INVALID,
/* NFT_MSG_DELRULE */ AUDIT_NFT_OP_RULE_UNREGISTER,
/* NFT_MSG_NEWSET */ AUDIT_NFT_OP_SET_REGISTER,
/* NFT_MSG_GETSET */ AUDIT_NFT_OP_INVALID,
/* NFT_MSG_DELSET */ AUDIT_NFT_OP_SET_UNREGISTER,
/* NFT_MSG_NEWSETELEM */ AUDIT_NFT_OP_SETELEM_REGISTER,
/* NFT_MSG_GETSETELEM */ AUDIT_NFT_OP_INVALID,
/* NFT_MSG_DELSETELEM */ AUDIT_NFT_OP_SETELEM_UNREGISTER,
/* NFT_MSG_NEWGEN */ AUDIT_NFT_OP_GEN_REGISTER,
/* NFT_MSG_GETGEN */ AUDIT_NFT_OP_INVALID,
/* NFT_MSG_TRACE */ AUDIT_NFT_OP_INVALID,
/* NFT_MSG_NEWOBJ */ AUDIT_NFT_OP_OBJ_REGISTER,
/* NFT_MSG_GETOBJ */ AUDIT_NFT_OP_INVALID,
/* NFT_MSG_DELOBJ */ AUDIT_NFT_OP_OBJ_UNREGISTER,
/* NFT_MSG_GETOBJ_RESET */ AUDIT_NFT_OP_OBJ_RESET,
/* 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_MAX */ AUDIT_NFT_OP_INVALID,
};

extern int is_audit_feature_set(int which);

extern int __init audit_register_class(int class, unsigned *list);
@@ -717,17 +717,6 @@ static void nf_tables_table_notify(const struct nft_ctx *ctx, int event)
{
struct sk_buff *skb;
int err;
char *buf = kasprintf(GFP_KERNEL, "%s:%llu;?:0",
ctx->table->name, ctx->table->handle);

audit_log_nfcfg(buf,
ctx->family,
ctx->table->use,
event == NFT_MSG_NEWTABLE ?
AUDIT_NFT_OP_TABLE_REGISTER :
AUDIT_NFT_OP_TABLE_UNREGISTER,
GFP_KERNEL);
kfree(buf);

if (!ctx->report &&
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
@@ -1491,18 +1480,6 @@ static void nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
{
struct sk_buff *skb;
int err;
char *buf = kasprintf(GFP_KERNEL, "%s:%llu;%s:%llu",
ctx->table->name, ctx->table->handle,
ctx->chain->name, ctx->chain->handle);

audit_log_nfcfg(buf,
ctx->family,
ctx->chain->use,
event == NFT_MSG_NEWCHAIN ?
AUDIT_NFT_OP_CHAIN_REGISTER :
AUDIT_NFT_OP_CHAIN_UNREGISTER,
GFP_KERNEL);
kfree(buf);

if (!ctx->report &&
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
@@ -2855,18 +2832,6 @@ static void nf_tables_rule_notify(const struct nft_ctx *ctx,
{
struct sk_buff *skb;
int err;
char *buf = kasprintf(GFP_KERNEL, "%s:%llu;%s:%llu",
ctx->table->name, ctx->table->handle,
ctx->chain->name, ctx->chain->handle);

audit_log_nfcfg(buf,
ctx->family,
rule->handle,
event == NFT_MSG_NEWRULE ?
AUDIT_NFT_OP_RULE_REGISTER :
AUDIT_NFT_OP_RULE_UNREGISTER,
GFP_KERNEL);
kfree(buf);

if (!ctx->report &&
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
@@ -3901,18 +3866,6 @@ static void nf_tables_set_notify(const struct nft_ctx *ctx,
struct sk_buff *skb;
u32 portid = ctx->portid;
int err;
char *buf = kasprintf(gfp_flags, "%s:%llu;%s:%llu",
ctx->table->name, ctx->table->handle,
set->name, set->handle);

audit_log_nfcfg(buf,
ctx->family,
set->field_count,
event == NFT_MSG_NEWSET ?
AUDIT_NFT_OP_SET_REGISTER :
AUDIT_NFT_OP_SET_UNREGISTER,
gfp_flags);
kfree(buf);

if (!ctx->report &&
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
@@ -5097,18 +5050,6 @@ static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
u32 portid = ctx->portid;
struct sk_buff *skb;
int err;
char *buf = kasprintf(GFP_KERNEL, "%s:%llu;%s:%llu",
ctx->table->name, ctx->table->handle,
set->name, set->handle);

audit_log_nfcfg(buf,
ctx->family,
set->handle,
event == NFT_MSG_NEWSETELEM ?
AUDIT_NFT_OP_SETELEM_REGISTER :
AUDIT_NFT_OP_SETELEM_UNREGISTER,
GFP_KERNEL);
kfree(buf);

if (!ctx->report && !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
return;
@@ -6310,12 +6251,11 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
filter->type != NFT_OBJECT_UNSPEC &&
obj->ops->type->type != filter->type)
goto cont;

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

audit_log_nfcfg(buf,
family,
@@ -6436,8 +6376,8 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk,
reset = true;

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

audit_log_nfcfg(buf,
family,
@@ -6525,15 +6465,15 @@ void nft_obj_notify(struct net *net, const struct nft_table *table,
{
struct sk_buff *skb;
int err;
char *buf = kasprintf(gfp, "%s:%llu;?:0",
table->name, table->handle);
char *buf = kasprintf(gfp, "%s:%u",
table->name, net->nft.base_seq);

audit_log_nfcfg(buf,
family,
obj->handle,
event == NFT_MSG_NEWOBJ ?
AUDIT_NFT_OP_OBJ_REGISTER :
AUDIT_NFT_OP_OBJ_UNREGISTER,
AUDIT_NFT_OP_OBJ_REGISTER :
AUDIT_NFT_OP_OBJ_UNREGISTER,
gfp);
kfree(buf);

@@ -7333,18 +7273,6 @@ static void nf_tables_flowtable_notify(struct nft_ctx *ctx,
{
struct sk_buff *skb;
int err;
char *buf = kasprintf(GFP_KERNEL, "%s:%llu;%s:%llu",
flowtable->table->name, flowtable->table->handle,
flowtable->name, flowtable->handle);

audit_log_nfcfg(buf,
ctx->family,
flowtable->hooknum,
event == NFT_MSG_NEWFLOWTABLE ?
AUDIT_NFT_OP_FLOWTABLE_REGISTER :
AUDIT_NFT_OP_FLOWTABLE_UNREGISTER,
GFP_KERNEL);
kfree(buf);

if (!ctx->report &&
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
@@ -7465,9 +7393,6 @@ static void nf_tables_gen_notify(struct net *net, struct sk_buff *skb,
struct sk_buff *skb2;
int err;

audit_log_nfcfg("?:0;?:0", 0, net->nft.base_seq,
AUDIT_NFT_OP_GEN_REGISTER, GFP_KERNEL);

if (!nlmsg_report(nlh) &&
!nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
return;
@@ -8012,6 +7937,14 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
struct nft_trans_elem *te;
struct nft_chain *chain;
struct nft_table *table;
struct audit_log_nftdata {
struct nft_table *table;
int entries;
int op;
struct audit_log_nftdata *next;
} ad = { NULL, 0, 0, NULL }, *adp, *adnext;
#define AUNFTABLENAMELEN (NFT_TABLE_MAXNAMELEN + 22)
char aubuf[AUNFTABLENAMELEN];
int err;

if (list_empty(&net->nft.commit_list)) {
@@ -8206,12 +8139,45 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
}
break;
}
adp = &ad;
if (!adp->table) {
adp->table = trans->ctx.table;
adp->entries = 1;
adp->op = trans->msg_type;
} else {
adnext = &ad;
do {
adp = adnext;
if (adp->table == trans->ctx.table)
goto found;
adnext = adp->next;
} while (adnext);
adp->next = kzalloc(sizeof(*adp->next), GFP_KERNEL);
adp = adp->next;
adp->table = trans->ctx.table;
found:
adp->entries++;
if (!adp->op || adp->op > trans->msg_type)
adp->op = trans->msg_type;
}
}

nft_commit_notify(net, NETLINK_CB(skb).portid);
nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN);
nf_tables_commit_release(net);

adp = &ad;
while (adp && adp->table) {
snprintf(aubuf, AUNFTABLENAMELEN, "%s:%u", adp->table->name,
net->nft.base_seq);
audit_log_nfcfg(aubuf, adp->table->family, adp->entries,
nft2audit_op[adp->op], GFP_KERNEL);
adnext = adp->next;
if (adp != &ad)
kfree(adp);
adp = adnext;
}

return 0;
}

0 comments on commit 6c3d6ac

Please sign in to comment.