]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.18.60/xfrm-fix-stack-access-out-of-bounds-with-config_xfrm_sub_policy.patch
3.18-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.18.60 / xfrm-fix-stack-access-out-of-bounds-with-config_xfrm_sub_policy.patch
1 From 9b3eb54106cf6acd03f07cf0ab01c13676a226c2 Mon Sep 17 00:00:00 2001
2 From: Sabrina Dubroca <sd@queasysnail.net>
3 Date: Wed, 3 May 2017 16:43:19 +0200
4 Subject: xfrm: fix stack access out of bounds with CONFIG_XFRM_SUB_POLICY
5
6 From: Sabrina Dubroca <sd@queasysnail.net>
7
8 commit 9b3eb54106cf6acd03f07cf0ab01c13676a226c2 upstream.
9
10 When CONFIG_XFRM_SUB_POLICY=y, xfrm_dst stores a copy of the flowi for
11 that dst. Unfortunately, the code that allocates and fills this copy
12 doesn't care about what type of flowi (flowi, flowi4, flowi6) gets
13 passed. In multiple code paths (from raw_sendmsg, from TCP when
14 replying to a FIN, in vxlan, geneve, and gre), the flowi that gets
15 passed to xfrm is actually an on-stack flowi4, so we end up reading
16 stuff from the stack past the end of the flowi4 struct.
17
18 Since xfrm_dst->origin isn't used anywhere following commit
19 ca116922afa8 ("xfrm: Eliminate "fl" and "pol" args to
20 xfrm_bundle_ok()."), just get rid of it. xfrm_dst->partner isn't used
21 either, so get rid of that too.
22
23 Fixes: 9d6ec938019c ("ipv4: Use flowi4 in public route lookup interfaces.")
24 Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
25 Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
26 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
27
28 ---
29 include/net/xfrm.h | 10 ----------
30 net/xfrm/xfrm_policy.c | 47 -----------------------------------------------
31 2 files changed, 57 deletions(-)
32
33 --- a/include/net/xfrm.h
34 +++ b/include/net/xfrm.h
35 @@ -949,10 +949,6 @@ struct xfrm_dst {
36 struct flow_cache_object flo;
37 struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
38 int num_pols, num_xfrms;
39 -#ifdef CONFIG_XFRM_SUB_POLICY
40 - struct flowi *origin;
41 - struct xfrm_selector *partner;
42 -#endif
43 u32 xfrm_genid;
44 u32 policy_genid;
45 u32 route_mtu_cached;
46 @@ -968,12 +964,6 @@ static inline void xfrm_dst_destroy(stru
47 dst_release(xdst->route);
48 if (likely(xdst->u.dst.xfrm))
49 xfrm_state_put(xdst->u.dst.xfrm);
50 -#ifdef CONFIG_XFRM_SUB_POLICY
51 - kfree(xdst->origin);
52 - xdst->origin = NULL;
53 - kfree(xdst->partner);
54 - xdst->partner = NULL;
55 -#endif
56 }
57 #endif
58
59 --- a/net/xfrm/xfrm_policy.c
60 +++ b/net/xfrm/xfrm_policy.c
61 @@ -1751,43 +1751,6 @@ free_dst:
62 goto out;
63 }
64
65 -#ifdef CONFIG_XFRM_SUB_POLICY
66 -static int xfrm_dst_alloc_copy(void **target, const void *src, int size)
67 -{
68 - if (!*target) {
69 - *target = kmalloc(size, GFP_ATOMIC);
70 - if (!*target)
71 - return -ENOMEM;
72 - }
73 -
74 - memcpy(*target, src, size);
75 - return 0;
76 -}
77 -#endif
78 -
79 -static int xfrm_dst_update_parent(struct dst_entry *dst,
80 - const struct xfrm_selector *sel)
81 -{
82 -#ifdef CONFIG_XFRM_SUB_POLICY
83 - struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
84 - return xfrm_dst_alloc_copy((void **)&(xdst->partner),
85 - sel, sizeof(*sel));
86 -#else
87 - return 0;
88 -#endif
89 -}
90 -
91 -static int xfrm_dst_update_origin(struct dst_entry *dst,
92 - const struct flowi *fl)
93 -{
94 -#ifdef CONFIG_XFRM_SUB_POLICY
95 - struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
96 - return xfrm_dst_alloc_copy((void **)&(xdst->origin), fl, sizeof(*fl));
97 -#else
98 - return 0;
99 -#endif
100 -}
101 -
102 static int xfrm_expand_policies(const struct flowi *fl, u16 family,
103 struct xfrm_policy **pols,
104 int *num_pols, int *num_xfrms)
105 @@ -1859,16 +1822,6 @@ xfrm_resolve_and_create_bundle(struct xf
106
107 xdst = (struct xfrm_dst *)dst;
108 xdst->num_xfrms = err;
109 - if (num_pols > 1)
110 - err = xfrm_dst_update_parent(dst, &pols[1]->selector);
111 - else
112 - err = xfrm_dst_update_origin(dst, fl);
113 - if (unlikely(err)) {
114 - dst_free(dst);
115 - XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
116 - return ERR_PTR(err);
117 - }
118 -
119 xdst->num_pols = num_pols;
120 memcpy(xdst->pols, pols, sizeof(struct xfrm_policy *) * num_pols);
121 xdst->policy_genid = atomic_read(&pols[0]->genid);