lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Message-Id: <200709061900.10508.joakim.koskela@hiit.fi> Date: Thu, 6 Sep 2007 19:00:10 +0300 From: Joakim Koskela <joakim.koskela@...t.fi> To: netdev@...r.kernel.org Subject: [PATCH net-2.6.23-rc5] ipsec interfamily route handling fix Hi, This patch addresses a couple of issues related to interfamily ipsec modes. The problem is that the structure of the routing info changes with the family during the __xfrmX_bundle_create, which hasn't been taken properly into account. Seems that by coincidence it hasn't caused problems on 32bit platforms, but crashes for example on x86_64 in 6-4 around line 209 of xfrm6_policy.c as rt doesn't point to a rt6_info anymore, but actually a struct rtable. With 64bit pointers, the rt->rt6i_node pointer seems to hit something usually not null in the rtable that rt now points to, making it go for the path_cookie assignment and subsequently crashing. Tested on both 32/64bit with all four (44/46/64/66) combinations of transformation. I'm still a bit worried about how for example nested transformations work with all of this and would appreciate if someone more familiar with the details of these structs could comment. Signed-off-by: Joakim Koskela <jookos@...il.com> --- diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 4ff8ed3..7410c0d 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -72,6 +72,7 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int struct dst_entry *dst, *dst_prev; struct rtable *rt0 = (struct rtable*)(*dst_p); struct rtable *rt = rt0; + unsigned short encap_family = AF_INET; struct flowi fl_tunnel = { .nl_u = { .ip4_u = { @@ -118,7 +119,7 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int trailer_len += xfrm[i]->props.trailer_len; if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL) { - unsigned short encap_family = xfrm[i]->props.family; + encap_family = xfrm[i]->props.family; switch (encap_family) { case AF_INET: fl_tunnel.fl4_dst = xfrm[i]->id.daddr.a4; @@ -180,16 +181,19 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int } dst_prev->output = afinfo->output; xfrm_state_put_afinfo(afinfo); - if (dst_prev->xfrm->props.family == AF_INET && rt->peer) - atomic_inc(&rt->peer->refcnt); - x->u.rt.peer = rt->peer; + + if (encap_family == AF_INET) { + if (dst_prev->xfrm->props.family == AF_INET && rt->peer) + atomic_inc(&rt->peer->refcnt); + x->u.rt.peer = rt->peer; + x->u.rt.rt_type = rt->rt_type; + x->u.rt.rt_gateway = rt->rt_gateway; + } /* Sheit... I remember I did this right. Apparently, * it was magically lost, so this code needs audit */ x->u.rt.rt_flags = rt0->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST| RTCF_LOCAL); - x->u.rt.rt_type = rt->rt_type; x->u.rt.rt_src = rt0->rt_src; x->u.rt.rt_dst = rt0->rt_dst; - x->u.rt.rt_gateway = rt->rt_gateway; x->u.rt.rt_spec_dst = rt0->rt_spec_dst; x->u.rt.idev = rt0->idev; in_dev_hold(rt0->idev); diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 3ec0c47..9733f39 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -131,6 +131,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int struct dst_entry *dst, *dst_prev; struct rt6_info *rt0 = (struct rt6_info*)(*dst_p); struct rt6_info *rt = rt0; + unsigned short encap_family = AF_INET6; struct flowi fl_tunnel = { .nl_u = { .ip6_u = { @@ -180,11 +181,13 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL || xfrm[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION) { - unsigned short encap_family = xfrm[i]->props.family; + encap_family = xfrm[i]->props.family; switch(encap_family) { case AF_INET: fl_tunnel.fl4_dst = xfrm[i]->id.daddr.a4; fl_tunnel.fl4_src = xfrm[i]->props.saddr.a4; + fl_tunnel.fl4_tos = 0; + fl_tunnel.fl4_scope = 0; break; case AF_INET6: ipv6_addr_copy(&fl_tunnel.fl6_dst, __xfrm6_bundle_addr_remote(xfrm[i], &fl->fl6_dst)); @@ -205,7 +208,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int dst_prev->child = &rt->u.dst; dst->path = &rt->u.dst; - if (rt->rt6i_node) + if (encap_family == AF_INET6 && rt->rt6i_node) ((struct xfrm_dst *)dst)->path_cookie = rt->rt6i_node->fn_sernum; *dst_p = dst; - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists