Group :: System/Kernel and hardware
RPM: kernel-image-std-def
Main Changelog Spec Patches Sources Download Gear Bugs and FR Repocop
Patch: xt_audit.patch
Download
Download
include/linux/audit.h | 8 +++
kernel/audit.c | 26 ++++++++++
net/netfilter/xt_AUDIT.c | 124 ++++++++++++++++++++++++++++++++++++-----------
3 files changed, 131 insertions(+), 27 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 82b7c1116a85..eac7cfa222f3 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -183,6 +183,12 @@ extern void audit_log_key(struct audit_buffer *ab,
extern void audit_log_path_denied(int type,
const char *operation);
extern void audit_log_lost(const char *message);
+#ifdef CONFIG_SECURITY
+extern void audit_log_secctx(struct audit_buffer *ab, u32 secid);
+#else
+static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid)
+{ }
+#endif
extern int audit_log_task_context(struct audit_buffer *ab);
extern void audit_log_task_info(struct audit_buffer *ab);
@@ -244,6 +250,8 @@ static inline void audit_log_key(struct audit_buffer *ab, char *key)
{ }
static inline void audit_log_path_denied(int type, const char *operation)
{ }
+static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid)
+{ }
static inline int audit_log_task_context(struct audit_buffer *ab)
{
return 0;
diff --git a/kernel/audit.c b/kernel/audit.c
index 121d37e700a6..6e634921b9b6 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -2421,6 +2421,32 @@ void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
}
}
+#ifdef CONFIG_SECURITY
+/**
+ * audit_log_secctx - Converts and logs SELinux context
+ * @ab: audit_buffer
+ * @secid: security number
+ *
+ * This is a helper function that calls security_secid_to_secctx to convert
+ * secid to secctx and then adds the (converted) SELinux context to the audit
+ * log by calling audit_log_format, thus also preventing leak of internal secid
+ * to userspace. If secid cannot be converted audit_panic is called.
+ */
+void audit_log_secctx(struct audit_buffer *ab, u32 secid)
+{
+ u32 len;
+ char *secctx;
+
+ if (security_secid_to_secctx(secid, &secctx, &len)) {
+ audit_panic("Cannot convert secid to context");
+ } else {
+ audit_log_format(ab, " obj=%s", secctx);
+ security_release_secctx(secctx, len);
+ }
+}
+EXPORT_SYMBOL(audit_log_secctx);
+#endif
+
EXPORT_SYMBOL(audit_log_start);
EXPORT_SYMBOL(audit_log_end);
EXPORT_SYMBOL(audit_log_format);
diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
index b6a015aee0ce..43002af9fec5 100644
--- a/net/netfilter/xt_AUDIT.c
+++ b/net/netfilter/xt_AUDIT.c
@@ -28,76 +28,146 @@ MODULE_ALIAS("ip6t_AUDIT");
MODULE_ALIAS("ebt_AUDIT");
MODULE_ALIAS("arpt_AUDIT");
-static bool audit_ip4(struct audit_buffer *ab, struct sk_buff *skb)
+static void audit_proto(struct audit_buffer *ab, struct sk_buff *skb,
+ unsigned int proto, unsigned int offset)
+{
+ switch (proto) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+ case IPPROTO_UDPLITE: {
+ const __be16 *pptr;
+ __be16 _ports[2];
+
+ pptr = skb_header_pointer(skb, offset, sizeof(_ports), _ports);
+ if (pptr == NULL) {
+ audit_log_format(ab, " truncated=1");
+ return;
+ }
+
+ audit_log_format(ab, " sport=%hu dport=%hu",
+ ntohs(pptr[0]), ntohs(pptr[1]));
+ }
+ break;
+
+ case IPPROTO_ICMP:
+ case IPPROTO_ICMPV6: {
+ const u8 *iptr;
+ u8 _ih[2];
+
+ iptr = skb_header_pointer(skb, offset, sizeof(_ih), &_ih);
+ if (iptr == NULL) {
+ audit_log_format(ab, " truncated=1");
+ return;
+ }
+
+ audit_log_format(ab, " icmptype=%hhu icmpcode=%hhu",
+ iptr[0], iptr[1]);
+
+ }
+ break;
+ }
+}
+
+static void audit_ip4(struct audit_buffer *ab, struct sk_buff *skb)
{
struct iphdr _iph;
const struct iphdr *ih;
ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_iph), &_iph);
- if (!ih)
- return false;
+ if (!ih) {
+ audit_log_format(ab, " truncated=1");
+ return;
+ }
- audit_log_format(ab, " saddr=%pI4 daddr=%pI4 proto=%hhu",
- &ih->saddr, &ih->daddr, ih->protocol);
+ audit_log_format(ab, " saddr=%pI4 daddr=%pI4 ipid=%hu proto=%hhu",
+ &ih->saddr, &ih->daddr, ntohs(ih->id), ih->protocol);
- return true;
+ if (ntohs(ih->frag_off) & IP_OFFSET) {
+ audit_log_format(ab, " frag=1");
+ return;
+ }
+
+ audit_proto(ab, skb, ih->protocol, ih->ihl * 4);
}
-static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
+static void audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
{
struct ipv6hdr _ip6h;
const struct ipv6hdr *ih;
u8 nexthdr;
__be16 frag_off;
+ int offset;
ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_ip6h), &_ip6h);
- if (!ih)
- return false;
+ if (!ih) {
+ audit_log_format(ab, " truncated=1");
+ return;
+ }
nexthdr = ih->nexthdr;
- ipv6_skip_exthdr(skb, skb_network_offset(skb) + sizeof(_ip6h), &nexthdr, &frag_off);
+ offset = ipv6_skip_exthdr(skb, skb_network_offset(skb) + sizeof(_ip6h),
+ &nexthdr, &frag_off);
audit_log_format(ab, " saddr=%pI6c daddr=%pI6c proto=%hhu",
&ih->saddr, &ih->daddr, nexthdr);
- return true;
+ if (offset)
+ audit_proto(ab, skb, nexthdr, offset);
}
static unsigned int
audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
+ const struct xt_audit_info *info = par->targinfo;
struct audit_buffer *ab;
- int fam = -1;
if (audit_enabled == AUDIT_OFF)
goto errout;
+
ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
if (ab == NULL)
goto errout;
- audit_log_format(ab, "mark=%#x", skb->mark);
+ audit_log_format(ab, "action=%hhu hook=%u len=%u inif=%s outif=%s",
+ info->type, xt_hooknum(par), skb->len,
+ xt_in(par) ? xt_inname(par) : "?",
+ xt_out(par) ? xt_outname(par) : "?");
+
+ if (skb->mark)
+ audit_log_format(ab, " mark=%#x", skb->mark);
+
+ if (skb->dev && skb->dev->type == ARPHRD_ETHER) {
+ audit_log_format(ab, " smac=%pM dmac=%pM macproto=0x%04x",
+ eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
+ ntohs(eth_hdr(skb)->h_proto));
+
+ if (xt_family(par) == NFPROTO_BRIDGE) {
+ switch (eth_hdr(skb)->h_proto) {
+ case htons(ETH_P_IP):
+ audit_ip4(ab, skb);
+ break;
+
+ case htons(ETH_P_IPV6):
+ audit_ip6(ab, skb);
+ break;
+ }
+ }
+ }
switch (xt_family(par)) {
- case NFPROTO_BRIDGE:
- switch (eth_hdr(skb)->h_proto) {
- case htons(ETH_P_IP):
- fam = audit_ip4(ab, skb) ? NFPROTO_IPV4 : -1;
- break;
- case htons(ETH_P_IPV6):
- fam = audit_ip6(ab, skb) ? NFPROTO_IPV6 : -1;
- break;
- }
- break;
case NFPROTO_IPV4:
- fam = audit_ip4(ab, skb) ? NFPROTO_IPV4 : -1;
+ audit_ip4(ab, skb);
break;
+
case NFPROTO_IPV6:
- fam = audit_ip6(ab, skb) ? NFPROTO_IPV6 : -1;
+ audit_ip6(ab, skb);
break;
}
- if (fam == -1)
- audit_log_format(ab, " saddr=? daddr=? proto=-1");
+#ifdef CONFIG_NETWORK_SECMARK
+ if (skb->secmark)
+ audit_log_secctx(ab, skb->secmark);
+#endif
audit_log_end(ab);