Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 78625
b: refs/heads/master
c: afeb14b
h: refs/heads/master
i:
  78623: 21a6a50
v: v3
  • Loading branch information
Paul Moore authored and David S. Miller committed Jan 28, 2008
1 parent ce6bd6a commit 1d828df
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 35 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: dfd4f0ae2e111e2b93c295938c0e64ebbb69ae6e
refs/heads/master: afeb14b49098ba7a51c96e083a4105a0301f94c4
33 changes: 26 additions & 7 deletions trunk/include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -565,26 +565,33 @@ struct xfrm_audit
};

#ifdef CONFIG_AUDITSYSCALL
static inline struct audit_buffer *xfrm_audit_start(u32 auid, u32 secid)
static inline struct audit_buffer *xfrm_audit_start(const char *op)
{
struct audit_buffer *audit_buf = NULL;
char *secctx;
u32 secctx_len;

if (audit_enabled == 0)
return NULL;
audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC,
AUDIT_MAC_IPSEC_EVENT);
AUDIT_MAC_IPSEC_EVENT);
if (audit_buf == NULL)
return NULL;
audit_log_format(audit_buf, "op=%s", op);
return audit_buf;
}

audit_log_format(audit_buf, "auid=%u", auid);
static inline void xfrm_audit_helper_usrinfo(u32 auid, u32 secid,
struct audit_buffer *audit_buf)
{
char *secctx;
u32 secctx_len;

audit_log_format(audit_buf, " auid=%u", auid);
if (secid != 0 &&
security_secid_to_secctx(secid, &secctx, &secctx_len) == 0) {
audit_log_format(audit_buf, " subj=%s", secctx);
security_release_secctx(secctx, secctx_len);
} else
audit_log_task_context(audit_buf);
return audit_buf;
}

extern void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
Expand All @@ -595,11 +602,22 @@ extern void xfrm_audit_state_add(struct xfrm_state *x, int result,
u32 auid, u32 secid);
extern void xfrm_audit_state_delete(struct xfrm_state *x, int result,
u32 auid, u32 secid);
extern void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
struct sk_buff *skb);
extern void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family);
extern void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
__be32 net_spi, __be32 net_seq);
extern void xfrm_audit_state_icvfail(struct xfrm_state *x,
struct sk_buff *skb, u8 proto);
#else
#define xfrm_audit_policy_add(x, r, a, s) do { ; } while (0)
#define xfrm_audit_policy_delete(x, r, a, s) do { ; } while (0)
#define xfrm_audit_state_add(x, r, a, s) do { ; } while (0)
#define xfrm_audit_state_delete(x, r, a, s) do { ; } while (0)
#define xfrm_audit_state_replay_overflow(x, s) do { ; } while (0)
#define xfrm_audit_state_notfound_simple(s, f) do { ; } while (0)
#define xfrm_audit_state_notfound(s, f, sp, sq) do { ; } while (0)
#define xfrm_audit_state_icvfail(x, s, p) do { ; } while (0)
#endif /* CONFIG_AUDITSYSCALL */

static inline void xfrm_pol_hold(struct xfrm_policy *policy)
Expand Down Expand Up @@ -1214,7 +1232,8 @@ extern int xfrm_state_delete(struct xfrm_state *x);
extern int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info);
extern void xfrm_sad_getinfo(struct xfrmk_sadinfo *si);
extern void xfrm_spd_getinfo(struct xfrmk_spdinfo *si);
extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq);
extern int xfrm_replay_check(struct xfrm_state *x,
struct sk_buff *skb, __be32 seq);
extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq);
extern void xfrm_replay_notify(struct xfrm_state *x, int event);
extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
Expand Down
4 changes: 3 additions & 1 deletion trunk/net/ipv4/ah4.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,10 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
err = ah_mac_digest(ahp, skb, ah->auth_data);
if (err)
goto unlock;
if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len))
if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len)) {
xfrm_audit_state_icvfail(x, skb, IPPROTO_AH);
err = -EBADMSG;
}
}
unlock:
spin_unlock(&x->lock);
Expand Down
1 change: 1 addition & 0 deletions trunk/net/ipv4/esp4.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
BUG();

if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) {
xfrm_audit_state_icvfail(x, skb, IPPROTO_ESP);
err = -EBADMSG;
goto unlock;
}
Expand Down
2 changes: 1 addition & 1 deletion trunk/net/ipv6/ah6.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
if (err)
goto unlock;
if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len)) {
LIMIT_NETDEBUG(KERN_WARNING "ipsec ah authentication error\n");
xfrm_audit_state_icvfail(x, skb, IPPROTO_AH);
err = -EBADMSG;
}
}
Expand Down
1 change: 1 addition & 0 deletions trunk/net/ipv6/esp6.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
BUG();

if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) {
xfrm_audit_state_icvfail(x, skb, IPPROTO_ESP);
ret = -EBADMSG;
goto unlock;
}
Expand Down
1 change: 1 addition & 0 deletions trunk/net/ipv6/xfrm6_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,

if (!x) {
XFRM_INC_STATS(LINUX_MIB_XFRMINNOSTATES);
xfrm_audit_state_notfound_simple(skb, AF_INET6);
goto drop;
}

Expand Down
3 changes: 2 additions & 1 deletion trunk/net/xfrm/xfrm_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
x = xfrm_state_lookup(daddr, spi, nexthdr, family);
if (x == NULL) {
XFRM_INC_STATS(LINUX_MIB_XFRMINNOSTATES);
xfrm_audit_state_notfound(skb, family, spi, seq);
goto drop;
}

Expand All @@ -163,7 +164,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
goto drop_unlock;
}

if (x->props.replay_window && xfrm_replay_check(x, seq)) {
if (x->props.replay_window && xfrm_replay_check(x, skb, seq)) {
XFRM_INC_STATS(LINUX_MIB_XFRMINSEQOUTOFWINDOW);
goto drop_unlock;
}
Expand Down
2 changes: 2 additions & 0 deletions trunk/net/xfrm/xfrm_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ static int xfrm_output_one(struct sk_buff *skb, int err)

if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
XFRM_SKB_CB(skb)->seq = ++x->replay.oseq;
if (unlikely(x->replay.oseq == 0))
xfrm_audit_state_replay_overflow(x, skb);
if (xfrm_aevent_is_on())
xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
}
Expand Down
14 changes: 6 additions & 8 deletions trunk/net/xfrm/xfrm_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -2407,12 +2407,11 @@ void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
{
struct audit_buffer *audit_buf;

if (audit_enabled == 0)
return;
audit_buf = xfrm_audit_start(auid, secid);
audit_buf = xfrm_audit_start("SPD-add");
if (audit_buf == NULL)
return;
audit_log_format(audit_buf, " op=SPD-add res=%u", result);
xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
audit_log_format(audit_buf, " res=%u", result);
xfrm_audit_common_policyinfo(xp, audit_buf);
audit_log_end(audit_buf);
}
Expand All @@ -2423,12 +2422,11 @@ void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
{
struct audit_buffer *audit_buf;

if (audit_enabled == 0)
return;
audit_buf = xfrm_audit_start(auid, secid);
audit_buf = xfrm_audit_start("SPD-delete");
if (audit_buf == NULL)
return;
audit_log_format(audit_buf, " op=SPD-delete res=%u", result);
xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
audit_log_format(audit_buf, " res=%u", result);
xfrm_audit_common_policyinfo(xp, audit_buf);
audit_log_end(audit_buf);
}
Expand Down
153 changes: 137 additions & 16 deletions trunk/net/xfrm/xfrm_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ static unsigned int xfrm_state_genid;
static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);

#ifdef CONFIG_AUDITSYSCALL
static void xfrm_audit_state_replay(struct xfrm_state *x,
struct sk_buff *skb, __be32 net_seq);
#else
#define xfrm_audit_state_replay(x, s, sq) do { ; } while (0)
#endif /* CONFIG_AUDITSYSCALL */

static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr,
xfrm_address_t *saddr,
u32 reqid,
Expand Down Expand Up @@ -1609,13 +1616,14 @@ static void xfrm_replay_timer_handler(unsigned long data)
spin_unlock(&x->lock);
}

int xfrm_replay_check(struct xfrm_state *x, __be32 net_seq)
int xfrm_replay_check(struct xfrm_state *x,
struct sk_buff *skb, __be32 net_seq)
{
u32 diff;
u32 seq = ntohl(net_seq);

if (unlikely(seq == 0))
return -EINVAL;
goto err;

if (likely(seq > x->replay.seq))
return 0;
Expand All @@ -1624,14 +1632,18 @@ int xfrm_replay_check(struct xfrm_state *x, __be32 net_seq)
if (diff >= min_t(unsigned int, x->props.replay_window,
sizeof(x->replay.bitmap) * 8)) {
x->stats.replay_window++;
return -EINVAL;
goto err;
}

if (x->replay.bitmap & (1U << diff)) {
x->stats.replay++;
return -EINVAL;
goto err;
}
return 0;

err:
xfrm_audit_state_replay(x, skb, net_seq);
return -EINVAL;
}
EXPORT_SYMBOL(xfrm_replay_check);

Expand Down Expand Up @@ -1996,8 +2008,8 @@ void __init xfrm_state_init(void)
}

#ifdef CONFIG_AUDITSYSCALL
static inline void xfrm_audit_common_stateinfo(struct xfrm_state *x,
struct audit_buffer *audit_buf)
static inline void xfrm_audit_helper_sainfo(struct xfrm_state *x,
struct audit_buffer *audit_buf)
{
struct xfrm_sec_ctx *ctx = x->security;
u32 spi = ntohl(x->id.spi);
Expand All @@ -2024,18 +2036,45 @@ static inline void xfrm_audit_common_stateinfo(struct xfrm_state *x,
audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi);
}

static inline void xfrm_audit_helper_pktinfo(struct sk_buff *skb, u16 family,
struct audit_buffer *audit_buf)
{
struct iphdr *iph4;
struct ipv6hdr *iph6;

switch (family) {
case AF_INET:
iph4 = ip_hdr(skb);
audit_log_format(audit_buf,
" src=" NIPQUAD_FMT " dst=" NIPQUAD_FMT,
NIPQUAD(iph4->saddr),
NIPQUAD(iph4->daddr));
break;
case AF_INET6:
iph6 = ipv6_hdr(skb);
audit_log_format(audit_buf,
" src=" NIP6_FMT " dst=" NIP6_FMT
" flowlbl=0x%x%x%x",
NIP6(iph6->saddr),
NIP6(iph6->daddr),
iph6->flow_lbl[0] & 0x0f,
iph6->flow_lbl[1],
iph6->flow_lbl[2]);
break;
}
}

void xfrm_audit_state_add(struct xfrm_state *x, int result,
u32 auid, u32 secid)
{
struct audit_buffer *audit_buf;

if (audit_enabled == 0)
return;
audit_buf = xfrm_audit_start(auid, secid);
audit_buf = xfrm_audit_start("SAD-add");
if (audit_buf == NULL)
return;
audit_log_format(audit_buf, " op=SAD-add res=%u", result);
xfrm_audit_common_stateinfo(x, audit_buf);
xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
xfrm_audit_helper_sainfo(x, audit_buf);
audit_log_format(audit_buf, " res=%u", result);
audit_log_end(audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_add);
Expand All @@ -2045,14 +2084,96 @@ void xfrm_audit_state_delete(struct xfrm_state *x, int result,
{
struct audit_buffer *audit_buf;

if (audit_enabled == 0)
return;
audit_buf = xfrm_audit_start(auid, secid);
audit_buf = xfrm_audit_start("SAD-delete");
if (audit_buf == NULL)
return;
audit_log_format(audit_buf, " op=SAD-delete res=%u", result);
xfrm_audit_common_stateinfo(x, audit_buf);
xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
xfrm_audit_helper_sainfo(x, audit_buf);
audit_log_format(audit_buf, " res=%u", result);
audit_log_end(audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_delete);

void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
struct sk_buff *skb)
{
struct audit_buffer *audit_buf;
u32 spi;

audit_buf = xfrm_audit_start("SA-replay-overflow");
if (audit_buf == NULL)
return;
xfrm_audit_helper_pktinfo(skb, x->props.family, audit_buf);
/* don't record the sequence number because it's inherent in this kind
* of audit message */
spi = ntohl(x->id.spi);
audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi);
audit_log_end(audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_replay_overflow);

static void xfrm_audit_state_replay(struct xfrm_state *x,
struct sk_buff *skb, __be32 net_seq)
{
struct audit_buffer *audit_buf;
u32 spi;

audit_buf = xfrm_audit_start("SA-replayed-pkt");
if (audit_buf == NULL)
return;
xfrm_audit_helper_pktinfo(skb, x->props.family, audit_buf);
spi = ntohl(x->id.spi);
audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
spi, spi, ntohl(net_seq));
audit_log_end(audit_buf);
}

void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family)
{
struct audit_buffer *audit_buf;

audit_buf = xfrm_audit_start("SA-notfound");
if (audit_buf == NULL)
return;
xfrm_audit_helper_pktinfo(skb, family, audit_buf);
audit_log_end(audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_notfound_simple);

void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
__be32 net_spi, __be32 net_seq)
{
struct audit_buffer *audit_buf;
u32 spi;

audit_buf = xfrm_audit_start("SA-notfound");
if (audit_buf == NULL)
return;
xfrm_audit_helper_pktinfo(skb, family, audit_buf);
spi = ntohl(net_spi);
audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
spi, spi, ntohl(net_seq));
audit_log_end(audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_notfound);

void xfrm_audit_state_icvfail(struct xfrm_state *x,
struct sk_buff *skb, u8 proto)
{
struct audit_buffer *audit_buf;
__be32 net_spi;
__be32 net_seq;

audit_buf = xfrm_audit_start("SA-icv-failure");
if (audit_buf == NULL)
return;
xfrm_audit_helper_pktinfo(skb, x->props.family, audit_buf);
if (xfrm_parse_spi(skb, proto, &net_spi, &net_seq) == 0) {
u32 spi = ntohl(net_spi);
audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
spi, spi, ntohl(net_seq));
}
audit_log_end(audit_buf);
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_icvfail);
#endif /* CONFIG_AUDITSYSCALL */

0 comments on commit 1d828df

Please sign in to comment.