From: Greg Kroah-Hartman Date: Fri, 1 Dec 2017 15:10:37 +0000 (+0000) Subject: 3.18-stable patches X-Git-Tag: v3.18.86~30 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=565dbcead31f4231fa28615438ab5ad361b06275;p=thirdparty%2Fkernel%2Fstable-queue.git 3.18-stable patches added patches: ipsec-fix-aborted-xfrm-policy-dump-crash.patch netlink-add-a-start-callback-for-starting-a-netlink-dump.patch --- diff --git a/queue-3.18/ipsec-fix-aborted-xfrm-policy-dump-crash.patch b/queue-3.18/ipsec-fix-aborted-xfrm-policy-dump-crash.patch new file mode 100644 index 00000000000..a4ac8ea7e20 --- /dev/null +++ b/queue-3.18/ipsec-fix-aborted-xfrm-policy-dump-crash.patch @@ -0,0 +1,102 @@ +From 1137b5e2529a8f5ca8ee709288ecba3e68044df2 Mon Sep 17 00:00:00 2001 +From: Herbert Xu +Date: Thu, 19 Oct 2017 20:51:10 +0800 +Subject: ipsec: Fix aborted xfrm policy dump crash + +From: Herbert Xu + +commit 1137b5e2529a8f5ca8ee709288ecba3e68044df2 upstream. + +An independent security researcher, Mohamed Ghannam, has reported +this vulnerability to Beyond Security's SecuriTeam Secure Disclosure +program. + +The xfrm_dump_policy_done function expects xfrm_dump_policy to +have been called at least once or it will crash. This can be +triggered if a dump fails because the target socket's receive +buffer is full. + +This patch fixes it by using the cb->start mechanism to ensure that +the initialisation is always done regardless of the buffer situation. + +Fixes: 12a169e7d8f4 ("ipsec: Put dumpers on the dump list") +Signed-off-by: Herbert Xu +Signed-off-by: Steffen Klassert +Cc: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman + +--- + net/xfrm/xfrm_user.c | 25 +++++++++++++++---------- + 1 file changed, 15 insertions(+), 10 deletions(-) + +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -1625,32 +1625,34 @@ static int dump_one_policy(struct xfrm_p + + static int xfrm_dump_policy_done(struct netlink_callback *cb) + { +- struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; ++ struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args; + struct net *net = sock_net(cb->skb->sk); + + xfrm_policy_walk_done(walk, net); + return 0; + } + ++static int xfrm_dump_policy_start(struct netlink_callback *cb) ++{ ++ struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args; ++ ++ BUILD_BUG_ON(sizeof(*walk) > sizeof(cb->args)); ++ ++ xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY); ++ return 0; ++} ++ + static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) + { + struct net *net = sock_net(skb->sk); +- struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; ++ struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args; + struct xfrm_dump_info info; + +- BUILD_BUG_ON(sizeof(struct xfrm_policy_walk) > +- sizeof(cb->args) - sizeof(cb->args[0])); +- + info.in_skb = cb->skb; + info.out_skb = skb; + info.nlmsg_seq = cb->nlh->nlmsg_seq; + info.nlmsg_flags = NLM_F_MULTI; + +- if (!cb->args[0]) { +- cb->args[0] = 1; +- xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY); +- } +- + (void) xfrm_policy_walk(net, walk, dump_one_policy, &info); + + return skb->len; +@@ -2384,6 +2386,7 @@ static const struct nla_policy xfrma_spd + + static const struct xfrm_link { + int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **); ++ int (*start)(struct netlink_callback *); + int (*dump)(struct sk_buff *, struct netlink_callback *); + int (*done)(struct netlink_callback *); + const struct nla_policy *nla_pol; +@@ -2397,6 +2400,7 @@ static const struct xfrm_link { + [XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, + [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy }, + [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy, ++ .start = xfrm_dump_policy_start, + .dump = xfrm_dump_policy, + .done = xfrm_dump_policy_done }, + [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi }, +@@ -2443,6 +2447,7 @@ static int xfrm_user_rcv_msg(struct sk_b + + { + struct netlink_dump_control c = { ++ .start = link->start, + .dump = link->dump, + .done = link->done, + }; diff --git a/queue-3.18/netlink-add-a-start-callback-for-starting-a-netlink-dump.patch b/queue-3.18/netlink-add-a-start-callback-for-starting-a-netlink-dump.patch new file mode 100644 index 00000000000..ecd5c9efcd5 --- /dev/null +++ b/queue-3.18/netlink-add-a-start-callback-for-starting-a-netlink-dump.patch @@ -0,0 +1,120 @@ +From fc9e50f5a5a4e1fa9ba2756f745a13e693cf6a06 Mon Sep 17 00:00:00 2001 +From: Tom Herbert +Date: Tue, 15 Dec 2015 15:41:37 -0800 +Subject: netlink: add a start callback for starting a netlink dump + +From: Tom Herbert + +commit fc9e50f5a5a4e1fa9ba2756f745a13e693cf6a06 upstream. + +The start callback allows the caller to set up a context for the +dump callbacks. Presumably, the context can then be destroyed in +the done callback. + +Signed-off-by: Tom Herbert +Signed-off-by: David S. Miller +Cc: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/netlink.h | 2 ++ + include/net/genetlink.h | 2 ++ + net/netlink/af_netlink.c | 4 ++++ + net/netlink/genetlink.c | 16 ++++++++++++++++ + 4 files changed, 24 insertions(+) + +--- a/include/linux/netlink.h ++++ b/include/linux/netlink.h +@@ -120,6 +120,7 @@ netlink_skb_clone(struct sk_buff *skb, g + struct netlink_callback { + struct sk_buff *skb; + const struct nlmsghdr *nlh; ++ int (*start)(struct netlink_callback *); + int (*dump)(struct sk_buff * skb, + struct netlink_callback *cb); + int (*done)(struct netlink_callback *cb); +@@ -142,6 +143,7 @@ struct nlmsghdr * + __nlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, int type, int len, int flags); + + struct netlink_dump_control { ++ int (*start)(struct netlink_callback *); + int (*dump)(struct sk_buff *skb, struct netlink_callback *); + int (*done)(struct netlink_callback *); + void *data; +--- a/include/net/genetlink.h ++++ b/include/net/genetlink.h +@@ -106,6 +106,7 @@ static inline void genl_info_net_set(str + * @flags: flags + * @policy: attribute validation policy + * @doit: standard command callback ++ * @start: start callback for dumps + * @dumpit: callback for dumpers + * @done: completion callback for dumps + * @ops_list: operations list +@@ -114,6 +115,7 @@ struct genl_ops { + const struct nla_policy *policy; + int (*doit)(struct sk_buff *skb, + struct genl_info *info); ++ int (*start)(struct netlink_callback *cb); + int (*dumpit)(struct sk_buff *skb, + struct netlink_callback *cb); + int (*done)(struct netlink_callback *cb); +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -2043,6 +2043,7 @@ int __netlink_dump_start(struct sock *ss + + cb = &nlk->cb; + memset(cb, 0, sizeof(*cb)); ++ cb->start = control->start; + cb->dump = control->dump; + cb->done = control->done; + cb->nlh = nlh; +@@ -2056,6 +2057,9 @@ int __netlink_dump_start(struct sock *ss + + mutex_unlock(nlk->cb_mutex); + ++ if (cb->start) ++ cb->start(cb); ++ + ret = netlink_dump(sk); + sock_put(sk); + +--- a/net/netlink/genetlink.c ++++ b/net/netlink/genetlink.c +@@ -507,6 +507,20 @@ void *genlmsg_put(struct sk_buff *skb, u + } + EXPORT_SYMBOL(genlmsg_put); + ++static int genl_lock_start(struct netlink_callback *cb) ++{ ++ /* our ops are always const - netlink API doesn't propagate that */ ++ const struct genl_ops *ops = cb->data; ++ int rc = 0; ++ ++ if (ops->start) { ++ genl_lock(); ++ rc = ops->start(cb); ++ genl_unlock(); ++ } ++ return rc; ++} ++ + static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb) + { + /* our ops are always const - netlink API doesn't propagate that */ +@@ -571,6 +585,7 @@ static int genl_family_rcv_msg(struct ge + .module = family->module, + /* we have const, but the netlink API doesn't */ + .data = (void *)ops, ++ .start = genl_lock_start, + .dump = genl_lock_dumpit, + .done = genl_lock_done, + }; +@@ -582,6 +597,7 @@ static int genl_family_rcv_msg(struct ge + } else { + struct netlink_dump_control c = { + .module = family->module, ++ .start = ops->start, + .dump = ops->dumpit, + .done = ops->done, + }; diff --git a/queue-3.18/series b/queue-3.18/series new file mode 100644 index 00000000000..7d15d29329e --- /dev/null +++ b/queue-3.18/series @@ -0,0 +1,2 @@ +netlink-add-a-start-callback-for-starting-a-netlink-dump.patch +ipsec-fix-aborted-xfrm-policy-dump-crash.patch diff --git a/queue-4.4/series b/queue-4.4/series new file mode 100644 index 00000000000..7d15d29329e --- /dev/null +++ b/queue-4.4/series @@ -0,0 +1,2 @@ +netlink-add-a-start-callback-for-starting-a-netlink-dump.patch +ipsec-fix-aborted-xfrm-policy-dump-crash.patch