Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 34591
b: refs/heads/master
c: df0ba92
h: refs/heads/master
i:
  34589: b6b4501
  34587: 9d0f27d
  34583: 778db9d
  34575: 1f35f1b
  34559: e8c2e9d
v: v3
  • Loading branch information
Masahide NAKAMURA authored and David S. Miller committed Sep 22, 2006
1 parent 9ec8060 commit 4095a9b
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 8 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: 2ce4272a699c731b9736d76126dc742353e381db
refs/heads/master: df0ba92a99ca757039dfa84a929281ea3f7a50e8
1 change: 1 addition & 0 deletions trunk/include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ struct xfrm_type
void (*destructor)(struct xfrm_state *);
int (*input)(struct xfrm_state *, struct sk_buff *skb);
int (*output)(struct xfrm_state *, struct sk_buff *pskb);
int (*reject)(struct xfrm_state *, struct sk_buff *, struct flowi *);
int (*hdr_offset)(struct xfrm_state *, struct sk_buff *, u8 **);
xfrm_address_t *(*local_addr)(struct xfrm_state *, xfrm_address_t *);
xfrm_address_t *(*remote_addr)(struct xfrm_state *, xfrm_address_t *);
Expand Down
55 changes: 48 additions & 7 deletions trunk/net/xfrm/xfrm_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,23 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
}
EXPORT_SYMBOL(xfrm_lookup);

static inline int
xfrm_secpath_reject(int idx, struct sk_buff *skb, struct flowi *fl)
{
struct xfrm_state *x;
int err;

if (!skb->sp || idx < 0 || idx >= skb->sp->len)
return 0;
x = skb->sp->xvec[idx];
if (!x->type->reject)
return 0;
xfrm_state_hold(x);
err = x->type->reject(x, skb, fl);
xfrm_state_put(x);
return err;
}

/* When skb is transformed back to its "native" form, we have to
* check policy restrictions. At the moment we make this in maximally
* stupid way. Shame on me. :-) Of course, connected sockets must
Expand All @@ -1010,6 +1027,13 @@ xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x,
xfrm_state_addr_cmp(tmpl, x, family));
}

/*
* 0 or more than 0 is returned when validation is succeeded (either bypass
* because of optional transport mode, or next index of the mathced secpath
* state with the template.
* -1 is returned when no matching template is found.
* Otherwise "-2 - errored_index" is returned.
*/
static inline int
xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start,
unsigned short family)
Expand All @@ -1024,8 +1048,11 @@ xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start,
for (; idx < sp->len; idx++) {
if (xfrm_state_ok(tmpl, sp->xvec[idx], family))
return ++idx;
if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT)
if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) {
if (start == -1)
start = -2-idx;
break;
}
}
return start;
}
Expand All @@ -1046,11 +1073,14 @@ xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family
}
EXPORT_SYMBOL(xfrm_decode_session);

static inline int secpath_has_nontransport(struct sec_path *sp, int k)
static inline int secpath_has_nontransport(struct sec_path *sp, int k, int *idxp)
{
for (; k < sp->len; k++) {
if (sp->xvec[k]->props.mode != XFRM_MODE_TRANSPORT)
if (sp->xvec[k]->props.mode != XFRM_MODE_TRANSPORT) {
if (idxp)
*idxp = k;
return 1;
}
}

return 0;
Expand All @@ -1062,6 +1092,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
struct xfrm_policy *pol;
struct flowi fl;
u8 fl_dir = policy_to_flow_dir(dir);
int xerr_idx = -1;
int *xerr_idxp = &xerr_idx;

if (xfrm_decode_session(skb, &fl, family) < 0)
return 0;
Expand All @@ -1086,8 +1118,13 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
pol = flow_cache_lookup(&fl, family, fl_dir,
xfrm_policy_lookup);

if (!pol)
return !skb->sp || !secpath_has_nontransport(skb->sp, 0);
if (!pol) {
if (skb->sp && secpath_has_nontransport(skb->sp, 0, xerr_idxp)) {
xfrm_secpath_reject(xerr_idx, skb, &fl);
return 0;
}
return 1;
}

pol->curlft.use_time = (unsigned long)xtime.tv_sec;

Expand All @@ -1107,18 +1144,22 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
*/
for (i = pol->xfrm_nr-1, k = 0; i >= 0; i--) {
k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k, family);
if (k < 0)
if (k < 0) {
if (k < -1 && xerr_idxp)
*xerr_idxp = -(2+k);
goto reject;
}
}

if (secpath_has_nontransport(sp, k))
if (secpath_has_nontransport(sp, k, xerr_idxp))
goto reject;

xfrm_pol_put(pol);
return 1;
}

reject:
xfrm_secpath_reject(xerr_idx, skb, &fl);
xfrm_pol_put(pol);
return 0;
}
Expand Down

0 comments on commit 4095a9b

Please sign in to comment.