]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-5.1/alsa-seq-fix-race-of-get-subscription-call-vs-port-d.patch
move all the pending queues back to their "real" places
[thirdparty/kernel/stable-queue.git] / queue-5.1 / alsa-seq-fix-race-of-get-subscription-call-vs-port-d.patch
1 From 2f9f4566838c22c6201bade83fb74f8580f1a827 Mon Sep 17 00:00:00 2001
2 From: Takashi Iwai <tiwai@suse.de>
3 Date: Tue, 9 Apr 2019 18:04:17 +0200
4 Subject: ALSA: seq: Fix race of get-subscription call vs port-delete ioctls
5
6 [ Upstream commit 2eabc5ec8ab4d4748a82050dfcb994119b983750 ]
7
8 The snd_seq_ioctl_get_subscription() retrieves the port subscriber
9 information as a pointer, while the object isn't protected, hence it
10 may be deleted before the actual reference. This race was spotted by
11 syzkaller and may lead to a UAF.
12
13 The fix is simply copying the data in the lookup function that
14 performs in the rwsem to protect against the deletion.
15
16 Reported-by: syzbot+9437020c82413d00222d@syzkaller.appspotmail.com
17 Signed-off-by: Takashi Iwai <tiwai@suse.de>
18 Signed-off-by: Sasha Levin <sashal@kernel.org>
19 ---
20 sound/core/seq/seq_clientmgr.c | 10 ++--------
21 sound/core/seq/seq_ports.c | 13 ++++++++-----
22 sound/core/seq/seq_ports.h | 5 +++--
23 3 files changed, 13 insertions(+), 15 deletions(-)
24
25 diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
26 index b3280e81bfd1..8599f2937ac1 100644
27 --- a/sound/core/seq/seq_clientmgr.c
28 +++ b/sound/core/seq/seq_clientmgr.c
29 @@ -1900,20 +1900,14 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
30 int result;
31 struct snd_seq_client *sender = NULL;
32 struct snd_seq_client_port *sport = NULL;
33 - struct snd_seq_subscribers *p;
34
35 result = -EINVAL;
36 if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL)
37 goto __end;
38 if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL)
39 goto __end;
40 - p = snd_seq_port_get_subscription(&sport->c_src, &subs->dest);
41 - if (p) {
42 - result = 0;
43 - *subs = p->info;
44 - } else
45 - result = -ENOENT;
46 -
47 + result = snd_seq_port_get_subscription(&sport->c_src, &subs->dest,
48 + subs);
49 __end:
50 if (sport)
51 snd_seq_port_unlock(sport);
52 diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
53 index da31aa8e216e..16289aefb443 100644
54 --- a/sound/core/seq/seq_ports.c
55 +++ b/sound/core/seq/seq_ports.c
56 @@ -635,20 +635,23 @@ int snd_seq_port_disconnect(struct snd_seq_client *connector,
57
58
59 /* get matched subscriber */
60 -struct snd_seq_subscribers *snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp,
61 - struct snd_seq_addr *dest_addr)
62 +int snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp,
63 + struct snd_seq_addr *dest_addr,
64 + struct snd_seq_port_subscribe *subs)
65 {
66 - struct snd_seq_subscribers *s, *found = NULL;
67 + struct snd_seq_subscribers *s;
68 + int err = -ENOENT;
69
70 down_read(&src_grp->list_mutex);
71 list_for_each_entry(s, &src_grp->list_head, src_list) {
72 if (addr_match(dest_addr, &s->info.dest)) {
73 - found = s;
74 + *subs = s->info;
75 + err = 0;
76 break;
77 }
78 }
79 up_read(&src_grp->list_mutex);
80 - return found;
81 + return err;
82 }
83
84 /*
85 diff --git a/sound/core/seq/seq_ports.h b/sound/core/seq/seq_ports.h
86 index 26bd71f36c41..06003b36652e 100644
87 --- a/sound/core/seq/seq_ports.h
88 +++ b/sound/core/seq/seq_ports.h
89 @@ -135,7 +135,8 @@ int snd_seq_port_subscribe(struct snd_seq_client_port *port,
90 struct snd_seq_port_subscribe *info);
91
92 /* get matched subscriber */
93 -struct snd_seq_subscribers *snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp,
94 - struct snd_seq_addr *dest_addr);
95 +int snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp,
96 + struct snd_seq_addr *dest_addr,
97 + struct snd_seq_port_subscribe *subs);
98
99 #endif
100 --
101 2.20.1
102