mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
audit: log nftables configuration change events
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@redhat.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
This commit is contained in:
parent
bbccc11bc8
commit
8e6cf365e1
@ -12,6 +12,7 @@
|
|||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
#include <uapi/linux/audit.h>
|
#include <uapi/linux/audit.h>
|
||||||
|
#include <uapi/linux/netfilter/nf_tables.h>
|
||||||
|
|
||||||
#define AUDIT_INO_UNSET ((unsigned long)-1)
|
#define AUDIT_INO_UNSET ((unsigned long)-1)
|
||||||
#define AUDIT_DEV_UNSET ((dev_t)-1)
|
#define AUDIT_DEV_UNSET ((dev_t)-1)
|
||||||
@ -98,6 +99,23 @@ enum audit_nfcfgop {
|
|||||||
AUDIT_XT_OP_REGISTER,
|
AUDIT_XT_OP_REGISTER,
|
||||||
AUDIT_XT_OP_REPLACE,
|
AUDIT_XT_OP_REPLACE,
|
||||||
AUDIT_XT_OP_UNREGISTER,
|
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,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int is_audit_feature_set(int which);
|
extern int is_audit_feature_set(int which);
|
||||||
|
@ -75,6 +75,7 @@
|
|||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/fsnotify_backend.h>
|
#include <linux/fsnotify_backend.h>
|
||||||
#include <uapi/linux/limits.h>
|
#include <uapi/linux/limits.h>
|
||||||
|
#include <uapi/linux/netfilter/nf_tables.h>
|
||||||
|
|
||||||
#include "audit.h"
|
#include "audit.h"
|
||||||
|
|
||||||
@ -136,9 +137,26 @@ struct audit_nfcfgop_tab {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct audit_nfcfgop_tab audit_nfcfgs[] = {
|
static const struct audit_nfcfgop_tab audit_nfcfgs[] = {
|
||||||
{ AUDIT_XT_OP_REGISTER, "register" },
|
{ AUDIT_XT_OP_REGISTER, "xt_register" },
|
||||||
{ AUDIT_XT_OP_REPLACE, "replace" },
|
{ AUDIT_XT_OP_REPLACE, "xt_replace" },
|
||||||
{ AUDIT_XT_OP_UNREGISTER, "unregister" },
|
{ AUDIT_XT_OP_UNREGISTER, "xt_unregister" },
|
||||||
|
{ AUDIT_NFT_OP_TABLE_REGISTER, "nft_register_table" },
|
||||||
|
{ AUDIT_NFT_OP_TABLE_UNREGISTER, "nft_unregister_table" },
|
||||||
|
{ AUDIT_NFT_OP_CHAIN_REGISTER, "nft_register_chain" },
|
||||||
|
{ AUDIT_NFT_OP_CHAIN_UNREGISTER, "nft_unregister_chain" },
|
||||||
|
{ AUDIT_NFT_OP_RULE_REGISTER, "nft_register_rule" },
|
||||||
|
{ AUDIT_NFT_OP_RULE_UNREGISTER, "nft_unregister_rule" },
|
||||||
|
{ AUDIT_NFT_OP_SET_REGISTER, "nft_register_set" },
|
||||||
|
{ AUDIT_NFT_OP_SET_UNREGISTER, "nft_unregister_set" },
|
||||||
|
{ AUDIT_NFT_OP_SETELEM_REGISTER, "nft_register_setelem" },
|
||||||
|
{ AUDIT_NFT_OP_SETELEM_UNREGISTER, "nft_unregister_setelem" },
|
||||||
|
{ AUDIT_NFT_OP_GEN_REGISTER, "nft_register_gen" },
|
||||||
|
{ AUDIT_NFT_OP_OBJ_REGISTER, "nft_register_obj" },
|
||||||
|
{ AUDIT_NFT_OP_OBJ_UNREGISTER, "nft_unregister_obj" },
|
||||||
|
{ 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_INVALID, "nft_invalid" },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int audit_match_perm(struct audit_context *ctx, int mask)
|
static int audit_match_perm(struct audit_context *ctx, int mask)
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
#include <linux/rhashtable.h>
|
#include <linux/rhashtable.h>
|
||||||
|
#include <linux/audit.h>
|
||||||
#include <linux/netfilter.h>
|
#include <linux/netfilter.h>
|
||||||
#include <linux/netfilter/nfnetlink.h>
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
#include <linux/netfilter/nf_tables.h>
|
#include <linux/netfilter/nf_tables.h>
|
||||||
@ -693,6 +694,16 @@ static void nf_tables_table_notify(const struct nft_ctx *ctx, int event)
|
|||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int err;
|
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);
|
||||||
|
kfree(buf);
|
||||||
|
|
||||||
if (!ctx->report &&
|
if (!ctx->report &&
|
||||||
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
|
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
|
||||||
@ -1428,6 +1439,17 @@ static void nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
|
|||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int err;
|
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);
|
||||||
|
kfree(buf);
|
||||||
|
|
||||||
if (!ctx->report &&
|
if (!ctx->report &&
|
||||||
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
|
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
|
||||||
@ -2693,6 +2715,17 @@ static void nf_tables_rule_notify(const struct nft_ctx *ctx,
|
|||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int err;
|
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);
|
||||||
|
kfree(buf);
|
||||||
|
|
||||||
if (!ctx->report &&
|
if (!ctx->report &&
|
||||||
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
|
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
|
||||||
@ -3695,6 +3728,17 @@ static void nf_tables_set_notify(const struct nft_ctx *ctx,
|
|||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
u32 portid = ctx->portid;
|
u32 portid = ctx->portid;
|
||||||
int err;
|
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);
|
||||||
|
kfree(buf);
|
||||||
|
|
||||||
if (!ctx->report &&
|
if (!ctx->report &&
|
||||||
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
|
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
|
||||||
@ -4811,6 +4855,17 @@ static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
|
|||||||
u32 portid = ctx->portid;
|
u32 portid = ctx->portid;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int err;
|
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);
|
||||||
|
kfree(buf);
|
||||||
|
|
||||||
if (!ctx->report && !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
|
if (!ctx->report && !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
|
||||||
return;
|
return;
|
||||||
@ -5892,6 +5947,19 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
|
|||||||
obj->ops->type->type != filter->type)
|
obj->ops->type->type != filter->type)
|
||||||
goto cont;
|
goto cont;
|
||||||
|
|
||||||
|
if (reset) {
|
||||||
|
char *buf = kasprintf(GFP_KERNEL,
|
||||||
|
"%s:%llu;?:0",
|
||||||
|
table->name,
|
||||||
|
table->handle);
|
||||||
|
|
||||||
|
audit_log_nfcfg(buf,
|
||||||
|
family,
|
||||||
|
obj->handle,
|
||||||
|
AUDIT_NFT_OP_OBJ_RESET);
|
||||||
|
kfree(buf);
|
||||||
|
}
|
||||||
|
|
||||||
if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid,
|
if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid,
|
||||||
cb->nlh->nlmsg_seq,
|
cb->nlh->nlmsg_seq,
|
||||||
NFT_MSG_NEWOBJ,
|
NFT_MSG_NEWOBJ,
|
||||||
@ -6002,6 +6070,17 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk,
|
|||||||
if (NFNL_MSG_TYPE(nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
|
if (NFNL_MSG_TYPE(nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
|
||||||
reset = true;
|
reset = true;
|
||||||
|
|
||||||
|
if (reset) {
|
||||||
|
char *buf = kasprintf(GFP_KERNEL, "%s:%llu;?:0",
|
||||||
|
table->name, table->handle);
|
||||||
|
|
||||||
|
audit_log_nfcfg(buf,
|
||||||
|
family,
|
||||||
|
obj->handle,
|
||||||
|
AUDIT_NFT_OP_OBJ_RESET);
|
||||||
|
kfree(buf);
|
||||||
|
}
|
||||||
|
|
||||||
err = nf_tables_fill_obj_info(skb2, net, NETLINK_CB(skb).portid,
|
err = nf_tables_fill_obj_info(skb2, net, NETLINK_CB(skb).portid,
|
||||||
nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0,
|
nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0,
|
||||||
family, table, obj, reset);
|
family, table, obj, reset);
|
||||||
@ -6077,6 +6156,16 @@ void nft_obj_notify(struct net *net, const struct nft_table *table,
|
|||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int err;
|
int err;
|
||||||
|
char *buf = kasprintf(GFP_KERNEL, "%s:%llu;?:0",
|
||||||
|
table->name, table->handle);
|
||||||
|
|
||||||
|
audit_log_nfcfg(buf,
|
||||||
|
family,
|
||||||
|
obj->handle,
|
||||||
|
event == NFT_MSG_NEWOBJ ?
|
||||||
|
AUDIT_NFT_OP_OBJ_REGISTER :
|
||||||
|
AUDIT_NFT_OP_OBJ_UNREGISTER);
|
||||||
|
kfree(buf);
|
||||||
|
|
||||||
if (!report &&
|
if (!report &&
|
||||||
!nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
|
!nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
|
||||||
@ -6856,6 +6945,17 @@ static void nf_tables_flowtable_notify(struct nft_ctx *ctx,
|
|||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int err;
|
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);
|
||||||
|
kfree(buf);
|
||||||
|
|
||||||
if (ctx->report &&
|
if (ctx->report &&
|
||||||
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
|
!nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
|
||||||
@ -6977,6 +7077,9 @@ static void nf_tables_gen_notify(struct net *net, struct sk_buff *skb,
|
|||||||
struct sk_buff *skb2;
|
struct sk_buff *skb2;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
audit_log_nfcfg("?:0;?:0", 0, net->nft.base_seq,
|
||||||
|
AUDIT_NFT_OP_GEN_REGISTER);
|
||||||
|
|
||||||
if (nlmsg_report(nlh) &&
|
if (nlmsg_report(nlh) &&
|
||||||
!nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
|
!nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user