]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.14.53/media-dvb_frontend-fix-locking-issues-at-dvb_frontend_get_event.patch
5.1-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.14.53 / media-dvb_frontend-fix-locking-issues-at-dvb_frontend_get_event.patch
CommitLineData
0f714131
GKH
1From 76d81243a487c09619822ef8e7201a756e58a87d Mon Sep 17 00:00:00 2001
2From: Mauro Carvalho Chehab <mchehab@s-opensource.com>
3Date: Thu, 5 Apr 2018 05:30:52 -0400
4Subject: media: dvb_frontend: fix locking issues at dvb_frontend_get_event()
5
6From: Mauro Carvalho Chehab <mchehab@s-opensource.com>
7
8commit 76d81243a487c09619822ef8e7201a756e58a87d upstream.
9
10As warned by smatch:
11 drivers/media/dvb-core/dvb_frontend.c:314 dvb_frontend_get_event() warn: inconsistent returns 'sem:&fepriv->sem'.
12 Locked on: line 288
13 line 295
14 line 306
15 line 314
16 Unlocked on: line 303
17
18The lock implementation for get event is wrong, as, if an
19interrupt occurs, down_interruptible() will fail, and the
20routine will call up() twice when userspace calls the ioctl
21again.
22
23The bad code is there since when Linux migrated to git, in
242005.
25
26Cc: stable@vger.kernel.org
27Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
28Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
29
30---
31 drivers/media/dvb-core/dvb_frontend.c | 23 +++++++++++++++--------
32 1 file changed, 15 insertions(+), 8 deletions(-)
33
34--- a/drivers/media/dvb-core/dvb_frontend.c
35+++ b/drivers/media/dvb-core/dvb_frontend.c
36@@ -275,8 +275,20 @@ static void dvb_frontend_add_event(struc
37 wake_up_interruptible (&events->wait_queue);
38 }
39
40+static int dvb_frontend_test_event(struct dvb_frontend_private *fepriv,
41+ struct dvb_fe_events *events)
42+{
43+ int ret;
44+
45+ up(&fepriv->sem);
46+ ret = events->eventw != events->eventr;
47+ down(&fepriv->sem);
48+
49+ return ret;
50+}
51+
52 static int dvb_frontend_get_event(struct dvb_frontend *fe,
53- struct dvb_frontend_event *event, int flags)
54+ struct dvb_frontend_event *event, int flags)
55 {
56 struct dvb_frontend_private *fepriv = fe->frontend_priv;
57 struct dvb_fe_events *events = &fepriv->events;
58@@ -294,13 +306,8 @@ static int dvb_frontend_get_event(struct
59 if (flags & O_NONBLOCK)
60 return -EWOULDBLOCK;
61
62- up(&fepriv->sem);
63-
64- ret = wait_event_interruptible (events->wait_queue,
65- events->eventw != events->eventr);
66-
67- if (down_interruptible (&fepriv->sem))
68- return -ERESTARTSYS;
69+ ret = wait_event_interruptible(events->wait_queue,
70+ dvb_frontend_test_event(fepriv, events));
71
72 if (ret < 0)
73 return ret;