On Thu, May 28, 2020 at 9:44 PM Richard Guy Briggs <rgb(a)redhat.com> wrote:
iptables, ip6tables, arptables and ebtables table registration,
replacement and unregistration configuration events are logged for the
native (legacy) iptables setsockopt api, but not for the
nftables netlink api which is used by the nft-variant of iptables in
addition to nftables itself.
Add calls to log the configuration actions in the nftables netlink api.
This uses the same NETFILTER_CFG record format but overloads the table
field.
type=NETFILTER_CFG msg=audit(2020-05-28 17:46:41.878:162) : table=?:0;?:0
family=unspecified entries=2 op=nft_register_gen pid=396
subj=system_u:system_r:firewalld_t:s0 comm=firewalld
...
type=NETFILTER_CFG msg=audit(2020-05-28 17:46:41.878:162) : table=firewalld:1;?:0
family=inet entries=0 op=nft_register_table pid=396 subj=system_u:system_r:firewalld_t:s0
comm=firewalld
...
type=NETFILTER_CFG msg=audit(2020-05-28 17:46:41.911:163) :
table=firewalld:1;filter_FORWARD:85 family=inet entries=8 op=nft_register_chain pid=396
subj=system_u:system_r:firewalld_t:s0 comm=firewalld
...
type=NETFILTER_CFG msg=audit(2020-05-28 17:46:41.911:163) :
table=firewalld:1;filter_FORWARD:85 family=inet entries=101 op=nft_register_rule pid=396
subj=system_u:system_r:firewalld_t:s0 comm=firewalld
...
type=NETFILTER_CFG msg=audit(2020-05-28 17:46:41.911:163) : table=firewalld:1;__set0:87
family=inet entries=87 op=nft_register_setelem pid=396
subj=system_u:system_r:firewalld_t:s0 comm=firewalld
...
type=NETFILTER_CFG msg=audit(2020-05-28 17:46:41.911:163) : table=firewalld:1;__set0:87
family=inet entries=0 op=nft_register_set pid=396 subj=system_u:system_r:firewalld_t:s0
comm=firewalld
For further information please see issue
https://github.com/linux-audit/audit-kernel/issues/124
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
Changelog:
v2:
- differentiate between xtables and nftables
- add set, setelem, obj, flowtable, gen
- use nentries field as appropriate per type
- overload the "tables" field with table handle and chain/set/flowtable
include/linux/audit.h | 52 +++++++++++++++++++++++++
kernel/auditsc.c | 24 ++++++++++--
net/netfilter/nf_tables_api.c | 89 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 162 insertions(+), 3 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 3fcd9ee49734..d79866a38505 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -12,6 +12,7 @@
#include <linux/sched.h>
#include <linux/ptrace.h>
#include <uapi/linux/audit.h>
+#include <uapi/linux/netfilter/nf_tables.h>
#define AUDIT_INO_UNSET ((unsigned long)-1)
#define AUDIT_DEV_UNSET ((dev_t)-1)
@@ -98,6 +99,57 @@ enum audit_nfcfgop {
AUDIT_XT_OP_REGISTER,
AUDIT_XT_OP_REPLACE,
AUDIT_XT_OP_UNREGISTER,
+ AUDIT_NFT_OP_TABLE_REGISTER,
+ AUDIT_NFT_OP_TABLE_UNREGISTER,
+ AUDIT_NFT_OP_CHAIN_REGISTER,
+ AUDIT_NFT_OP_CHAIN_UNREGISTER,
+ AUDIT_NFT_OP_RULE_REGISTER,
+ AUDIT_NFT_OP_RULE_UNREGISTER,
+ AUDIT_NFT_OP_SET_REGISTER,
+ AUDIT_NFT_OP_SET_UNREGISTER,
+ AUDIT_NFT_OP_SETELEM_REGISTER,
+ AUDIT_NFT_OP_SETELEM_UNREGISTER,
+ AUDIT_NFT_OP_GEN_REGISTER,
+ AUDIT_NFT_OP_OBJ_REGISTER,
+ AUDIT_NFT_OP_OBJ_UNREGISTER,
+ AUDIT_NFT_OP_OBJ_RESET,
+ AUDIT_NFT_OP_FLOWTABLE_REGISTER,
+ AUDIT_NFT_OP_FLOWTABLE_UNREGISTER,
+ AUDIT_NFT_OP_INVALID,
+};
+
+struct audit_nftcfgop_tab {
+ enum nf_tables_msg_types nftop;
+ enum audit_nfcfgop op;
+};
+
+static const struct audit_nftcfgop_tab audit_nftcfgs[] = {
+ { 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 },
};
I didn't check every "op" defined above to match with the changes in
nf_tables_api.c, but is there a reason why we can't simply hardcode
the AUDIT_NFT_OP_* values in the audit_log_nfcfg() calls in
nf_tables_api.c? If we can, let's do that.
If we can't do that, we need to add some build-time protection to
catch if NFT_MSG_MAX increases without this table being updated.
static int audit_match_perm(struct audit_context *ctx, int mask)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 4471393da6d8..7a386eca6e04 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -12,6 +12,7 @@
#include <linux/netlink.h>
#include <linux/vmalloc.h>
#include <linux/rhashtable.h>
+#include <linux/audit.h>
#include <linux/netfilter.h>
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nf_tables.h>
@@ -693,6 +694,14 @@ 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,
+ audit_nftcfgs[event].op);
As an example, the below would work, yes?
audit_log_nfcfg(...,
(event == NFT_MSG_NEWTABLE ?
AUDIT_NFT_OP_TABLE_REGISTER :
AUDIT_NFT_OP_TABLE_UNREGISTER)
+ kfree(buf);
if (!ctx->report &&
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))