Skip to content

Commit 1a893b4

Browse files
Phil Sutterummakynes
authored andcommitted
netfilter: nf_tables: Add audit support to log statement
This extends log statement to support the behaviour achieved with AUDIT target in iptables. Audit logging is enabled via a pseudo log level 8. In this case any other settings like log prefix are ignored since audit log format is fixed. Signed-off-by: Phil Sutter <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 554ced0 commit 1a893b4

File tree

2 files changed

+96
-1
lines changed

2 files changed

+96
-1
lines changed

include/uapi/linux/netfilter/nf_tables.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,11 @@ enum nft_log_attributes {
10801080
};
10811081
#define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1)
10821082

1083+
/**
1084+
* LOGLEVEL_AUDIT - a pseudo log level enabling audit logging
1085+
*/
1086+
#define LOGLEVEL_AUDIT 8
1087+
10831088
/**
10841089
* enum nft_queue_attributes - nf_tables queue expression netlink attributes
10851090
*

net/netfilter/nft_log.c

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@
99
* Development of this code funded by Astaro AG (http://www.astaro.com/)
1010
*/
1111

12+
#include <linux/audit.h>
1213
#include <linux/kernel.h>
1314
#include <linux/init.h>
1415
#include <linux/module.h>
1516
#include <linux/netlink.h>
1617
#include <linux/netfilter.h>
1718
#include <linux/netfilter/nf_tables.h>
19+
#include <net/ipv6.h>
20+
#include <net/ip.h>
1821
#include <net/netfilter/nf_tables.h>
1922
#include <net/netfilter/nf_log.h>
2023
#include <linux/netdevice.h>
@@ -26,12 +29,93 @@ struct nft_log {
2629
char *prefix;
2730
};
2831

32+
static bool audit_ip4(struct audit_buffer *ab, struct sk_buff *skb)
33+
{
34+
struct iphdr _iph;
35+
const struct iphdr *ih;
36+
37+
ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_iph), &_iph);
38+
if (!ih)
39+
return false;
40+
41+
audit_log_format(ab, " saddr=%pI4 daddr=%pI4 proto=%hhu",
42+
&ih->saddr, &ih->daddr, ih->protocol);
43+
44+
return true;
45+
}
46+
47+
static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
48+
{
49+
struct ipv6hdr _ip6h;
50+
const struct ipv6hdr *ih;
51+
u8 nexthdr;
52+
__be16 frag_off;
53+
54+
ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_ip6h), &_ip6h);
55+
if (!ih)
56+
return false;
57+
58+
nexthdr = ih->nexthdr;
59+
ipv6_skip_exthdr(skb, skb_network_offset(skb) + sizeof(_ip6h), &nexthdr, &frag_off);
60+
61+
audit_log_format(ab, " saddr=%pI6c daddr=%pI6c proto=%hhu",
62+
&ih->saddr, &ih->daddr, nexthdr);
63+
64+
return true;
65+
}
66+
67+
static void nft_log_eval_audit(const struct nft_pktinfo *pkt)
68+
{
69+
struct sk_buff *skb = pkt->skb;
70+
struct audit_buffer *ab;
71+
int fam = -1;
72+
73+
if (!audit_enabled)
74+
return;
75+
76+
ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
77+
if (!ab)
78+
return;
79+
80+
audit_log_format(ab, "mark=%#x", skb->mark);
81+
82+
switch (nft_pf(pkt)) {
83+
case NFPROTO_BRIDGE:
84+
switch (eth_hdr(skb)->h_proto) {
85+
case htons(ETH_P_IP):
86+
fam = audit_ip4(ab, skb) ? NFPROTO_IPV4 : -1;
87+
break;
88+
case htons(ETH_P_IPV6):
89+
fam = audit_ip6(ab, skb) ? NFPROTO_IPV6 : -1;
90+
break;
91+
}
92+
break;
93+
case NFPROTO_IPV4:
94+
fam = audit_ip4(ab, skb) ? NFPROTO_IPV4 : -1;
95+
break;
96+
case NFPROTO_IPV6:
97+
fam = audit_ip6(ab, skb) ? NFPROTO_IPV6 : -1;
98+
break;
99+
}
100+
101+
if (fam == -1)
102+
audit_log_format(ab, " saddr=? daddr=? proto=-1");
103+
104+
audit_log_end(ab);
105+
}
106+
29107
static void nft_log_eval(const struct nft_expr *expr,
30108
struct nft_regs *regs,
31109
const struct nft_pktinfo *pkt)
32110
{
33111
const struct nft_log *priv = nft_expr_priv(expr);
34112

113+
if (priv->loginfo.type == NF_LOG_TYPE_LOG &&
114+
priv->loginfo.u.log.level == LOGLEVEL_AUDIT) {
115+
nft_log_eval_audit(pkt);
116+
return;
117+
}
118+
35119
nf_log_packet(nft_net(pkt), nft_pf(pkt), nft_hook(pkt), pkt->skb,
36120
nft_in(pkt), nft_out(pkt), &priv->loginfo, "%s",
37121
priv->prefix);
@@ -84,7 +168,7 @@ static int nft_log_init(const struct nft_ctx *ctx,
84168
} else {
85169
li->u.log.level = LOGLEVEL_WARNING;
86170
}
87-
if (li->u.log.level > LOGLEVEL_DEBUG) {
171+
if (li->u.log.level > LOGLEVEL_AUDIT) {
88172
err = -EINVAL;
89173
goto err1;
90174
}
@@ -112,6 +196,9 @@ static int nft_log_init(const struct nft_ctx *ctx,
112196
break;
113197
}
114198

199+
if (li->u.log.level == LOGLEVEL_AUDIT)
200+
return 0;
201+
115202
err = nf_logger_find_get(ctx->family, li->type);
116203
if (err < 0)
117204
goto err1;
@@ -133,6 +220,9 @@ static void nft_log_destroy(const struct nft_ctx *ctx,
133220
if (priv->prefix != nft_log_null_prefix)
134221
kfree(priv->prefix);
135222

223+
if (li->u.log.level == LOGLEVEL_AUDIT)
224+
return;
225+
136226
nf_logger_put(ctx->family, li->type);
137227
}
138228

0 commit comments

Comments
 (0)