aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_input.c3
-rw-r--r--net/xfrm/xfrm_output.c2
-rw-r--r--net/xfrm/xfrm_policy.c14
-rw-r--r--net/xfrm/xfrm_state.c153
4 files changed, 147 insertions, 25 deletions
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 493243fc5fe5..1b250f33ad5b 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -147,6 +147,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
147 x = xfrm_state_lookup(daddr, spi, nexthdr, family); 147 x = xfrm_state_lookup(daddr, spi, nexthdr, family);
148 if (x == NULL) { 148 if (x == NULL) {
149 XFRM_INC_STATS(LINUX_MIB_XFRMINNOSTATES); 149 XFRM_INC_STATS(LINUX_MIB_XFRMINNOSTATES);
150 xfrm_audit_state_notfound(skb, family, spi, seq);
150 goto drop; 151 goto drop;
151 } 152 }
152 153
@@ -163,7 +164,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
163 goto drop_unlock; 164 goto drop_unlock;
164 } 165 }
165 166
166 if (x->props.replay_window && xfrm_replay_check(x, seq)) { 167 if (x->props.replay_window && xfrm_replay_check(x, skb, seq)) {
167 XFRM_INC_STATS(LINUX_MIB_XFRMINSEQOUTOFWINDOW); 168 XFRM_INC_STATS(LINUX_MIB_XFRMINSEQOUTOFWINDOW);
168 goto drop_unlock; 169 goto drop_unlock;
169 } 170 }
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 867484a046af..09514449fe8a 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -57,6 +57,8 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
57 57
58 if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { 58 if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
59 XFRM_SKB_CB(skb)->seq = ++x->replay.oseq; 59 XFRM_SKB_CB(skb)->seq = ++x->replay.oseq;
60 if (unlikely(x->replay.oseq == 0))
61 xfrm_audit_state_replay_overflow(x, skb);
60 if (xfrm_aevent_is_on()) 62 if (xfrm_aevent_is_on())
61 xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); 63 xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
62 } 64 }
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index abc3e39b115b..280f8ded975c 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2407,12 +2407,11 @@ void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
2407{ 2407{
2408 struct audit_buffer *audit_buf; 2408 struct audit_buffer *audit_buf;
2409 2409
2410 if (audit_enabled == 0) 2410 audit_buf = xfrm_audit_start("SPD-add");
2411 return;
2412 audit_buf = xfrm_audit_start(auid, secid);
2413 if (audit_buf == NULL) 2411 if (audit_buf == NULL)
2414 return; 2412 return;
2415 audit_log_format(audit_buf, " op=SPD-add res=%u", result); 2413 xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
2414 audit_log_format(audit_buf, " res=%u", result);
2416 xfrm_audit_common_policyinfo(xp, audit_buf); 2415 xfrm_audit_common_policyinfo(xp, audit_buf);
2417 audit_log_end(audit_buf); 2416 audit_log_end(audit_buf);
2418} 2417}
@@ -2423,12 +2422,11 @@ void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
2423{ 2422{
2424 struct audit_buffer *audit_buf; 2423 struct audit_buffer *audit_buf;
2425 2424
2426 if (audit_enabled == 0) 2425 audit_buf = xfrm_audit_start("SPD-delete");
2427 return;
2428 audit_buf = xfrm_audit_start(auid, secid);
2429 if (audit_buf == NULL) 2426 if (audit_buf == NULL)
2430 return; 2427 return;
2431 audit_log_format(audit_buf, " op=SPD-delete res=%u", result); 2428 xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
2429 audit_log_format(audit_buf, " res=%u", result);
2432 xfrm_audit_common_policyinfo(xp, audit_buf); 2430 xfrm_audit_common_policyinfo(xp, audit_buf);
2433 audit_log_end(audit_buf); 2431 audit_log_end(audit_buf);
2434} 2432}
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 9e57378c51df..6bf876c866df 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -61,6 +61,13 @@ static unsigned int xfrm_state_genid;
61static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); 61static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
62static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); 62static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
63 63
64#ifdef CONFIG_AUDITSYSCALL
65static void xfrm_audit_state_replay(struct xfrm_state *x,
66 struct sk_buff *skb, __be32 net_seq);
67#else
68#define xfrm_audit_state_replay(x, s, sq) do { ; } while (0)
69#endif /* CONFIG_AUDITSYSCALL */
70
64static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, 71static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr,
65 xfrm_address_t *saddr, 72 xfrm_address_t *saddr,
66 u32 reqid, 73 u32 reqid,
@@ -1609,13 +1616,14 @@ static void xfrm_replay_timer_handler(unsigned long data)
1609 spin_unlock(&x->lock); 1616 spin_unlock(&x->lock);
1610} 1617}
1611 1618
1612int xfrm_replay_check(struct xfrm_state *x, __be32 net_seq) 1619int xfrm_replay_check(struct xfrm_state *x,
1620 struct sk_buff *skb, __be32 net_seq)
1613{ 1621{
1614 u32 diff; 1622 u32 diff;
1615 u32 seq = ntohl(net_seq); 1623 u32 seq = ntohl(net_seq);
1616 1624
1617 if (unlikely(seq == 0)) 1625 if (unlikely(seq == 0))
1618 return -EINVAL; 1626 goto err;
1619 1627
1620 if (likely(seq > x->replay.seq)) 1628 if (likely(seq > x->replay.seq))
1621 return 0; 1629 return 0;
@@ -1624,14 +1632,18 @@ int xfrm_replay_check(struct xfrm_state *x, __be32 net_seq)
1624 if (diff >= min_t(unsigned int, x->props.replay_window, 1632 if (diff >= min_t(unsigned int, x->props.replay_window,
1625 sizeof(x->replay.bitmap) * 8)) { 1633 sizeof(x->replay.bitmap) * 8)) {
1626 x->stats.replay_window++; 1634 x->stats.replay_window++;
1627 return -EINVAL; 1635 goto err;
1628 } 1636 }
1629 1637
1630 if (x->replay.bitmap & (1U << diff)) { 1638 if (x->replay.bitmap & (1U << diff)) {
1631 x->stats.replay++; 1639 x->stats.replay++;
1632 return -EINVAL; 1640 goto err;
1633 } 1641 }
1634 return 0; 1642 return 0;
1643
1644err:
1645 xfrm_audit_state_replay(x, skb, net_seq);
1646 return -EINVAL;
1635} 1647}
1636EXPORT_SYMBOL(xfrm_replay_check); 1648EXPORT_SYMBOL(xfrm_replay_check);
1637 1649
@@ -1996,8 +2008,8 @@ void __init xfrm_state_init(void)
1996} 2008}
1997 2009
1998#ifdef CONFIG_AUDITSYSCALL 2010#ifdef CONFIG_AUDITSYSCALL
1999static inline void xfrm_audit_common_stateinfo(struct xfrm_state *x, 2011static inline void xfrm_audit_helper_sainfo(struct xfrm_state *x,
2000 struct audit_buffer *audit_buf) 2012 struct audit_buffer *audit_buf)
2001{ 2013{
2002 struct xfrm_sec_ctx *ctx = x->security; 2014 struct xfrm_sec_ctx *ctx = x->security;
2003 u32 spi = ntohl(x->id.spi); 2015 u32 spi = ntohl(x->id.spi);
@@ -2024,18 +2036,45 @@ static inline void xfrm_audit_common_stateinfo(struct xfrm_state *x,
2024 audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi); 2036 audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi);
2025} 2037}
2026 2038
2039static inline void xfrm_audit_helper_pktinfo(struct sk_buff *skb, u16 family,
2040 struct audit_buffer *audit_buf)
2041{
2042 struct iphdr *iph4;
2043 struct ipv6hdr *iph6;
2044
2045 switch (family) {
2046 case AF_INET:
2047 iph4 = ip_hdr(skb);
2048 audit_log_format(audit_buf,
2049 " src=" NIPQUAD_FMT " dst=" NIPQUAD_FMT,
2050 NIPQUAD(iph4->saddr),
2051 NIPQUAD(iph4->daddr));
2052 break;
2053 case AF_INET6:
2054 iph6 = ipv6_hdr(skb);
2055 audit_log_format(audit_buf,
2056 " src=" NIP6_FMT " dst=" NIP6_FMT
2057 " flowlbl=0x%x%x%x",
2058 NIP6(iph6->saddr),
2059 NIP6(iph6->daddr),
2060 iph6->flow_lbl[0] & 0x0f,
2061 iph6->flow_lbl[1],
2062 iph6->flow_lbl[2]);
2063 break;
2064 }
2065}
2066
2027void xfrm_audit_state_add(struct xfrm_state *x, int result, 2067void xfrm_audit_state_add(struct xfrm_state *x, int result,
2028 u32 auid, u32 secid) 2068 u32 auid, u32 secid)
2029{ 2069{
2030 struct audit_buffer *audit_buf; 2070 struct audit_buffer *audit_buf;
2031 2071
2032 if (audit_enabled == 0) 2072 audit_buf = xfrm_audit_start("SAD-add");
2033 return;
2034 audit_buf = xfrm_audit_start(auid, secid);
2035 if (audit_buf == NULL) 2073 if (audit_buf == NULL)
2036 return; 2074 return;
2037 audit_log_format(audit_buf, " op=SAD-add res=%u", result); 2075 xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
2038 xfrm_audit_common_stateinfo(x, audit_buf); 2076 xfrm_audit_helper_sainfo(x, audit_buf);
2077 audit_log_format(audit_buf, " res=%u", result);
2039 audit_log_end(audit_buf); 2078 audit_log_end(audit_buf);
2040} 2079}
2041EXPORT_SYMBOL_GPL(xfrm_audit_state_add); 2080EXPORT_SYMBOL_GPL(xfrm_audit_state_add);
@@ -2045,14 +2084,96 @@ void xfrm_audit_state_delete(struct xfrm_state *x, int result,
2045{ 2084{
2046 struct audit_buffer *audit_buf; 2085 struct audit_buffer *audit_buf;
2047 2086
2048 if (audit_enabled == 0) 2087 audit_buf = xfrm_audit_start("SAD-delete");
2049 return;
2050 audit_buf = xfrm_audit_start(auid, secid);
2051 if (audit_buf == NULL) 2088 if (audit_buf == NULL)
2052 return; 2089 return;
2053 audit_log_format(audit_buf, " op=SAD-delete res=%u", result); 2090 xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
2054 xfrm_audit_common_stateinfo(x, audit_buf); 2091 xfrm_audit_helper_sainfo(x, audit_buf);
2092 audit_log_format(audit_buf, " res=%u", result);
2055 audit_log_end(audit_buf); 2093 audit_log_end(audit_buf);
2056} 2094}
2057EXPORT_SYMBOL_GPL(xfrm_audit_state_delete); 2095EXPORT_SYMBOL_GPL(xfrm_audit_state_delete);
2096
2097void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
2098 struct sk_buff *skb)
2099{
2100 struct audit_buffer *audit_buf;
2101 u32 spi;
2102
2103 audit_buf = xfrm_audit_start("SA-replay-overflow");
2104 if (audit_buf == NULL)
2105 return;
2106 xfrm_audit_helper_pktinfo(skb, x->props.family, audit_buf);
2107 /* don't record the sequence number because it's inherent in this kind
2108 * of audit message */
2109 spi = ntohl(x->id.spi);
2110 audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi);
2111 audit_log_end(audit_buf);
2112}
2113EXPORT_SYMBOL_GPL(xfrm_audit_state_replay_overflow);
2114
2115static void xfrm_audit_state_replay(struct xfrm_state *x,
2116 struct sk_buff *skb, __be32 net_seq)
2117{
2118 struct audit_buffer *audit_buf;
2119 u32 spi;
2120
2121 audit_buf = xfrm_audit_start("SA-replayed-pkt");
2122 if (audit_buf == NULL)
2123 return;
2124 xfrm_audit_helper_pktinfo(skb, x->props.family, audit_buf);
2125 spi = ntohl(x->id.spi);
2126 audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
2127 spi, spi, ntohl(net_seq));
2128 audit_log_end(audit_buf);
2129}
2130
2131void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family)
2132{
2133 struct audit_buffer *audit_buf;
2134
2135 audit_buf = xfrm_audit_start("SA-notfound");
2136 if (audit_buf == NULL)
2137 return;
2138 xfrm_audit_helper_pktinfo(skb, family, audit_buf);
2139 audit_log_end(audit_buf);
2140}
2141EXPORT_SYMBOL_GPL(xfrm_audit_state_notfound_simple);
2142
2143void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
2144 __be32 net_spi, __be32 net_seq)
2145{
2146 struct audit_buffer *audit_buf;
2147 u32 spi;
2148
2149 audit_buf = xfrm_audit_start("SA-notfound");
2150 if (audit_buf == NULL)
2151 return;
2152 xfrm_audit_helper_pktinfo(skb, family, audit_buf);
2153 spi = ntohl(net_spi);
2154 audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
2155 spi, spi, ntohl(net_seq));
2156 audit_log_end(audit_buf);
2157}
2158EXPORT_SYMBOL_GPL(xfrm_audit_state_notfound);
2159
2160void xfrm_audit_state_icvfail(struct xfrm_state *x,
2161 struct sk_buff *skb, u8 proto)
2162{
2163 struct audit_buffer *audit_buf;
2164 __be32 net_spi;
2165 __be32 net_seq;
2166
2167 audit_buf = xfrm_audit_start("SA-icv-failure");
2168 if (audit_buf == NULL)
2169 return;
2170 xfrm_audit_helper_pktinfo(skb, x->props.family, audit_buf);
2171 if (xfrm_parse_spi(skb, proto, &net_spi, &net_seq) == 0) {
2172 u32 spi = ntohl(net_spi);
2173 audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
2174 spi, spi, ntohl(net_seq));
2175 }
2176 audit_log_end(audit_buf);
2177}
2178EXPORT_SYMBOL_GPL(xfrm_audit_state_icvfail);
2058#endif /* CONFIG_AUDITSYSCALL */ 2179#endif /* CONFIG_AUDITSYSCALL */