]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.13.6/isdn-i4l-fetch-the-ppp_write-buffer-in-one-shot.patch
fixes for 4.19
[thirdparty/kernel/stable-queue.git] / releases / 4.13.6 / isdn-i4l-fetch-the-ppp_write-buffer-in-one-shot.patch
CommitLineData
014275a0
GKH
1From foo@baz Mon Oct 9 09:32:35 CEST 2017
2From: Meng Xu <mengxu.gatech@gmail.com>
3Date: Tue, 19 Sep 2017 21:49:55 -0400
4Subject: isdn/i4l: fetch the ppp_write buffer in one shot
5
6From: Meng Xu <mengxu.gatech@gmail.com>
7
8
9[ Upstream commit 02388bf87f72e1d47174cd8f81c34443920eb5a0 ]
10
11In isdn_ppp_write(), the header (i.e., protobuf) of the buffer is
12fetched twice from userspace. The first fetch is used to peek at the
13protocol of the message and reset the huptimer if necessary; while the
14second fetch copies in the whole buffer. However, given that buf resides
15in userspace memory, a user process can race to change its memory content
16across fetches. By doing so, we can either avoid resetting the huptimer
17for any type of packets (by first setting proto to PPP_LCP and later
18change to the actual type) or force resetting the huptimer for LCP
19packets.
20
21This patch changes this double-fetch behavior into two single fetches
22decided by condition (lp->isdn_device < 0 || lp->isdn_channel <0).
23A more detailed discussion can be found at
24https://marc.info/?l=linux-kernel&m=150586376926123&w=2
25
26Signed-off-by: Meng Xu <mengxu.gatech@gmail.com>
27Signed-off-by: David S. Miller <davem@davemloft.net>
28Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
29---
30 drivers/isdn/i4l/isdn_ppp.c | 37 +++++++++++++++++++++++++------------
31 1 file changed, 25 insertions(+), 12 deletions(-)
32
33--- a/drivers/isdn/i4l/isdn_ppp.c
34+++ b/drivers/isdn/i4l/isdn_ppp.c
35@@ -825,7 +825,6 @@ isdn_ppp_write(int min, struct file *fil
36 isdn_net_local *lp;
37 struct ippp_struct *is;
38 int proto;
39- unsigned char protobuf[4];
40
41 is = file->private_data;
42
43@@ -839,24 +838,28 @@ isdn_ppp_write(int min, struct file *fil
44 if (!lp)
45 printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n");
46 else {
47- /*
48- * Don't reset huptimer for
49- * LCP packets. (Echo requests).
50- */
51- if (copy_from_user(protobuf, buf, 4))
52- return -EFAULT;
53- proto = PPP_PROTOCOL(protobuf);
54- if (proto != PPP_LCP)
55- lp->huptimer = 0;
56+ if (lp->isdn_device < 0 || lp->isdn_channel < 0) {
57+ unsigned char protobuf[4];
58+ /*
59+ * Don't reset huptimer for
60+ * LCP packets. (Echo requests).
61+ */
62+ if (copy_from_user(protobuf, buf, 4))
63+ return -EFAULT;
64+
65+ proto = PPP_PROTOCOL(protobuf);
66+ if (proto != PPP_LCP)
67+ lp->huptimer = 0;
68
69- if (lp->isdn_device < 0 || lp->isdn_channel < 0)
70 return 0;
71+ }
72
73 if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) &&
74 lp->dialstate == 0 &&
75 (lp->flags & ISDN_NET_CONNECTED)) {
76 unsigned short hl;
77 struct sk_buff *skb;
78+ unsigned char *cpy_buf;
79 /*
80 * we need to reserve enough space in front of
81 * sk_buff. old call to dev_alloc_skb only reserved
82@@ -869,11 +872,21 @@ isdn_ppp_write(int min, struct file *fil
83 return count;
84 }
85 skb_reserve(skb, hl);
86- if (copy_from_user(skb_put(skb, count), buf, count))
87+ cpy_buf = skb_put(skb, count);
88+ if (copy_from_user(cpy_buf, buf, count))
89 {
90 kfree_skb(skb);
91 return -EFAULT;
92 }
93+
94+ /*
95+ * Don't reset huptimer for
96+ * LCP packets. (Echo requests).
97+ */
98+ proto = PPP_PROTOCOL(cpy_buf);
99+ if (proto != PPP_LCP)
100+ lp->huptimer = 0;
101+
102 if (is->debug & 0x40) {
103 printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len);
104 isdn_ppp_frame_log("xmit", skb->data, skb->len, 32, is->unit, lp->ppp_slot);