aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-10-12 12:01:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-10-12 12:01:18 -0400
commit7702f47623e6c029b4ce59ce0ad39b869d5cc933 (patch)
treeae6a9ea2cc9445f43a9e05a35c717fe69134b274
parent467251c69b1b39df78638d0d0cc60cf4d1d639a8 (diff)
parent99fee508245825765ff60155fed43f970ff83a8f (diff)
Merge tag 'sound-4.14-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai: "It's been a busy week for defending the attacks from fuzzer people. This contains various USB-audio driver fixes and sequencer core fixes spotted by syzkaller and other fuzzer, as well as one quirk for a Plantronics USB audio device" * tag 'sound-4.14-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ALSA: caiaq: Fix stray URB at probe error path ALSA: seq: Fix use-after-free at creating a port ALSA: usb-audio: Kill stray URB at exiting ALSA: line6: Fix leftover URB at error-path during probe ALSA: line6: Fix NULL dereference at podhd_disconnect() ALSA: line6: Fix missing initialization before error path ALSA: seq: Fix copy_from_user() call inside lock ALSA: usb-audio: Add sample rate quirk for Plantronics P610
-rw-r--r--include/sound/seq_virmidi.h1
-rw-r--r--sound/core/seq/seq_clientmgr.c6
-rw-r--r--sound/core/seq/seq_ports.c7
-rw-r--r--sound/core/seq/seq_virmidi.c27
-rw-r--r--sound/usb/caiaq/device.c12
-rw-r--r--sound/usb/line6/driver.c7
-rw-r--r--sound/usb/line6/podhd.c8
-rw-r--r--sound/usb/mixer.c12
-rw-r--r--sound/usb/mixer.h2
-rw-r--r--sound/usb/quirks.c1
10 files changed, 61 insertions, 22 deletions
diff --git a/include/sound/seq_virmidi.h b/include/sound/seq_virmidi.h
index a03acd0d398a..695257ae64ac 100644
--- a/include/sound/seq_virmidi.h
+++ b/include/sound/seq_virmidi.h
@@ -60,6 +60,7 @@ struct snd_virmidi_dev {
60 int port; /* created/attached port */ 60 int port; /* created/attached port */
61 unsigned int flags; /* SNDRV_VIRMIDI_* */ 61 unsigned int flags; /* SNDRV_VIRMIDI_* */
62 rwlock_t filelist_lock; 62 rwlock_t filelist_lock;
63 struct rw_semaphore filelist_sem;
63 struct list_head filelist; 64 struct list_head filelist;
64}; 65};
65 66
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index ea2d0ae85bd3..6c9cba2166d9 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -1259,6 +1259,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)
1259 struct snd_seq_port_info *info = arg; 1259 struct snd_seq_port_info *info = arg;
1260 struct snd_seq_client_port *port; 1260 struct snd_seq_client_port *port;
1261 struct snd_seq_port_callback *callback; 1261 struct snd_seq_port_callback *callback;
1262 int port_idx;
1262 1263
1263 /* it is not allowed to create the port for an another client */ 1264 /* it is not allowed to create the port for an another client */
1264 if (info->addr.client != client->number) 1265 if (info->addr.client != client->number)
@@ -1269,7 +1270,9 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)
1269 return -ENOMEM; 1270 return -ENOMEM;
1270 1271
1271 if (client->type == USER_CLIENT && info->kernel) { 1272 if (client->type == USER_CLIENT && info->kernel) {
1272 snd_seq_delete_port(client, port->addr.port); 1273 port_idx = port->addr.port;
1274 snd_seq_port_unlock(port);
1275 snd_seq_delete_port(client, port_idx);
1273 return -EINVAL; 1276 return -EINVAL;
1274 } 1277 }
1275 if (client->type == KERNEL_CLIENT) { 1278 if (client->type == KERNEL_CLIENT) {
@@ -1290,6 +1293,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)
1290 1293
1291 snd_seq_set_port_info(port, info); 1294 snd_seq_set_port_info(port, info);
1292 snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port); 1295 snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port);
1296 snd_seq_port_unlock(port);
1293 1297
1294 return 0; 1298 return 0;
1295} 1299}
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 0a7020c82bfc..d21ece9f8d73 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -122,7 +122,9 @@ static void port_subs_info_init(struct snd_seq_port_subs_info *grp)
122} 122}
123 123
124 124
125/* create a port, port number is returned (-1 on failure) */ 125/* create a port, port number is returned (-1 on failure);
126 * the caller needs to unref the port via snd_seq_port_unlock() appropriately
127 */
126struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, 128struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
127 int port) 129 int port)
128{ 130{
@@ -151,6 +153,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
151 snd_use_lock_init(&new_port->use_lock); 153 snd_use_lock_init(&new_port->use_lock);
152 port_subs_info_init(&new_port->c_src); 154 port_subs_info_init(&new_port->c_src);
153 port_subs_info_init(&new_port->c_dest); 155 port_subs_info_init(&new_port->c_dest);
156 snd_use_lock_use(&new_port->use_lock);
154 157
155 num = port >= 0 ? port : 0; 158 num = port >= 0 ? port : 0;
156 mutex_lock(&client->ports_mutex); 159 mutex_lock(&client->ports_mutex);
@@ -165,9 +168,9 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
165 list_add_tail(&new_port->list, &p->list); 168 list_add_tail(&new_port->list, &p->list);
166 client->num_ports++; 169 client->num_ports++;
167 new_port->addr.port = num; /* store the port number in the port */ 170 new_port->addr.port = num; /* store the port number in the port */
171 sprintf(new_port->name, "port-%d", num);
168 write_unlock_irqrestore(&client->ports_lock, flags); 172 write_unlock_irqrestore(&client->ports_lock, flags);
169 mutex_unlock(&client->ports_mutex); 173 mutex_unlock(&client->ports_mutex);
170 sprintf(new_port->name, "port-%d", num);
171 174
172 return new_port; 175 return new_port;
173} 176}
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index 8d93a4021c78..f48a4cd24ffc 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -77,13 +77,17 @@ static void snd_virmidi_init_event(struct snd_virmidi *vmidi,
77 * decode input event and put to read buffer of each opened file 77 * decode input event and put to read buffer of each opened file
78 */ 78 */
79static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, 79static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev,
80 struct snd_seq_event *ev) 80 struct snd_seq_event *ev,
81 bool atomic)
81{ 82{
82 struct snd_virmidi *vmidi; 83 struct snd_virmidi *vmidi;
83 unsigned char msg[4]; 84 unsigned char msg[4];
84 int len; 85 int len;
85 86
86 read_lock(&rdev->filelist_lock); 87 if (atomic)
88 read_lock(&rdev->filelist_lock);
89 else
90 down_read(&rdev->filelist_sem);
87 list_for_each_entry(vmidi, &rdev->filelist, list) { 91 list_for_each_entry(vmidi, &rdev->filelist, list) {
88 if (!vmidi->trigger) 92 if (!vmidi->trigger)
89 continue; 93 continue;
@@ -97,7 +101,10 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev,
97 snd_rawmidi_receive(vmidi->substream, msg, len); 101 snd_rawmidi_receive(vmidi->substream, msg, len);
98 } 102 }
99 } 103 }
100 read_unlock(&rdev->filelist_lock); 104 if (atomic)
105 read_unlock(&rdev->filelist_lock);
106 else
107 up_read(&rdev->filelist_sem);
101 108
102 return 0; 109 return 0;
103} 110}
@@ -115,7 +122,7 @@ int snd_virmidi_receive(struct snd_rawmidi *rmidi, struct snd_seq_event *ev)
115 struct snd_virmidi_dev *rdev; 122 struct snd_virmidi_dev *rdev;
116 123
117 rdev = rmidi->private_data; 124 rdev = rmidi->private_data;
118 return snd_virmidi_dev_receive_event(rdev, ev); 125 return snd_virmidi_dev_receive_event(rdev, ev, true);
119} 126}
120#endif /* 0 */ 127#endif /* 0 */
121 128
@@ -130,7 +137,7 @@ static int snd_virmidi_event_input(struct snd_seq_event *ev, int direct,
130 rdev = private_data; 137 rdev = private_data;
131 if (!(rdev->flags & SNDRV_VIRMIDI_USE)) 138 if (!(rdev->flags & SNDRV_VIRMIDI_USE))
132 return 0; /* ignored */ 139 return 0; /* ignored */
133 return snd_virmidi_dev_receive_event(rdev, ev); 140 return snd_virmidi_dev_receive_event(rdev, ev, atomic);
134} 141}
135 142
136/* 143/*
@@ -209,7 +216,6 @@ static int snd_virmidi_input_open(struct snd_rawmidi_substream *substream)
209 struct snd_virmidi_dev *rdev = substream->rmidi->private_data; 216 struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
210 struct snd_rawmidi_runtime *runtime = substream->runtime; 217 struct snd_rawmidi_runtime *runtime = substream->runtime;
211 struct snd_virmidi *vmidi; 218 struct snd_virmidi *vmidi;
212 unsigned long flags;
213 219
214 vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL); 220 vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL);
215 if (vmidi == NULL) 221 if (vmidi == NULL)
@@ -223,9 +229,11 @@ static int snd_virmidi_input_open(struct snd_rawmidi_substream *substream)
223 vmidi->client = rdev->client; 229 vmidi->client = rdev->client;
224 vmidi->port = rdev->port; 230 vmidi->port = rdev->port;
225 runtime->private_data = vmidi; 231 runtime->private_data = vmidi;
226 write_lock_irqsave(&rdev->filelist_lock, flags); 232 down_write(&rdev->filelist_sem);
233 write_lock_irq(&rdev->filelist_lock);
227 list_add_tail(&vmidi->list, &rdev->filelist); 234 list_add_tail(&vmidi->list, &rdev->filelist);
228 write_unlock_irqrestore(&rdev->filelist_lock, flags); 235 write_unlock_irq(&rdev->filelist_lock);
236 up_write(&rdev->filelist_sem);
229 vmidi->rdev = rdev; 237 vmidi->rdev = rdev;
230 return 0; 238 return 0;
231} 239}
@@ -264,9 +272,11 @@ static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream)
264 struct snd_virmidi_dev *rdev = substream->rmidi->private_data; 272 struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
265 struct snd_virmidi *vmidi = substream->runtime->private_data; 273 struct snd_virmidi *vmidi = substream->runtime->private_data;
266 274
275 down_write(&rdev->filelist_sem);
267 write_lock_irq(&rdev->filelist_lock); 276 write_lock_irq(&rdev->filelist_lock);
268 list_del(&vmidi->list); 277 list_del(&vmidi->list);
269 write_unlock_irq(&rdev->filelist_lock); 278 write_unlock_irq(&rdev->filelist_lock);
279 up_write(&rdev->filelist_sem);
270 snd_midi_event_free(vmidi->parser); 280 snd_midi_event_free(vmidi->parser);
271 substream->runtime->private_data = NULL; 281 substream->runtime->private_data = NULL;
272 kfree(vmidi); 282 kfree(vmidi);
@@ -520,6 +530,7 @@ int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmi
520 rdev->rmidi = rmidi; 530 rdev->rmidi = rmidi;
521 rdev->device = device; 531 rdev->device = device;
522 rdev->client = -1; 532 rdev->client = -1;
533 init_rwsem(&rdev->filelist_sem);
523 rwlock_init(&rdev->filelist_lock); 534 rwlock_init(&rdev->filelist_lock);
524 INIT_LIST_HEAD(&rdev->filelist); 535 INIT_LIST_HEAD(&rdev->filelist);
525 rdev->seq_mode = SNDRV_VIRMIDI_SEQ_DISPATCH; 536 rdev->seq_mode = SNDRV_VIRMIDI_SEQ_DISPATCH;
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index 0fb6b1b79261..d8409d9ae55b 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -469,10 +469,12 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
469 469
470 err = snd_usb_caiaq_send_command(cdev, EP1_CMD_GET_DEVICE_INFO, NULL, 0); 470 err = snd_usb_caiaq_send_command(cdev, EP1_CMD_GET_DEVICE_INFO, NULL, 0);
471 if (err) 471 if (err)
472 return err; 472 goto err_kill_urb;
473 473
474 if (!wait_event_timeout(cdev->ep1_wait_queue, cdev->spec_received, HZ)) 474 if (!wait_event_timeout(cdev->ep1_wait_queue, cdev->spec_received, HZ)) {
475 return -ENODEV; 475 err = -ENODEV;
476 goto err_kill_urb;
477 }
476 478
477 usb_string(usb_dev, usb_dev->descriptor.iManufacturer, 479 usb_string(usb_dev, usb_dev->descriptor.iManufacturer,
478 cdev->vendor_name, CAIAQ_USB_STR_LEN); 480 cdev->vendor_name, CAIAQ_USB_STR_LEN);
@@ -507,6 +509,10 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
507 509
508 setup_card(cdev); 510 setup_card(cdev);
509 return 0; 511 return 0;
512
513 err_kill_urb:
514 usb_kill_urb(&cdev->ep1_in_urb);
515 return err;
510} 516}
511 517
512static int snd_probe(struct usb_interface *intf, 518static int snd_probe(struct usb_interface *intf,
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index 0ff5a7d2e19f..c8f723c3a033 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -779,9 +779,10 @@ int line6_probe(struct usb_interface *interface,
779 return 0; 779 return 0;
780 780
781 error: 781 error:
782 if (line6->disconnect) 782 /* we can call disconnect callback here because no close-sync is
783 line6->disconnect(line6); 783 * needed yet at this point
784 snd_card_free(card); 784 */
785 line6_disconnect(interface);
785 return ret; 786 return ret;
786} 787}
787EXPORT_SYMBOL_GPL(line6_probe); 788EXPORT_SYMBOL_GPL(line6_probe);
diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c
index 956f847a96e4..451007c27743 100644
--- a/sound/usb/line6/podhd.c
+++ b/sound/usb/line6/podhd.c
@@ -301,7 +301,8 @@ static void podhd_disconnect(struct usb_line6 *line6)
301 301
302 intf = usb_ifnum_to_if(line6->usbdev, 302 intf = usb_ifnum_to_if(line6->usbdev,
303 pod->line6.properties->ctrl_if); 303 pod->line6.properties->ctrl_if);
304 usb_driver_release_interface(&podhd_driver, intf); 304 if (intf)
305 usb_driver_release_interface(&podhd_driver, intf);
305 } 306 }
306} 307}
307 308
@@ -317,6 +318,9 @@ static int podhd_init(struct usb_line6 *line6,
317 318
318 line6->disconnect = podhd_disconnect; 319 line6->disconnect = podhd_disconnect;
319 320
321 init_timer(&pod->startup_timer);
322 INIT_WORK(&pod->startup_work, podhd_startup_workqueue);
323
320 if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) { 324 if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
321 /* claim the data interface */ 325 /* claim the data interface */
322 intf = usb_ifnum_to_if(line6->usbdev, 326 intf = usb_ifnum_to_if(line6->usbdev,
@@ -358,8 +362,6 @@ static int podhd_init(struct usb_line6 *line6,
358 } 362 }
359 363
360 /* init device and delay registering */ 364 /* init device and delay registering */
361 init_timer(&pod->startup_timer);
362 INIT_WORK(&pod->startup_work, podhd_startup_workqueue);
363 podhd_startup(pod); 365 podhd_startup(pod);
364 return 0; 366 return 0;
365} 367}
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 9732edf77f86..91bc8f18791e 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -2234,6 +2234,9 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
2234 2234
2235static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) 2235static void snd_usb_mixer_free(struct usb_mixer_interface *mixer)
2236{ 2236{
2237 /* kill pending URBs */
2238 snd_usb_mixer_disconnect(mixer);
2239
2237 kfree(mixer->id_elems); 2240 kfree(mixer->id_elems);
2238 if (mixer->urb) { 2241 if (mixer->urb) {
2239 kfree(mixer->urb->transfer_buffer); 2242 kfree(mixer->urb->transfer_buffer);
@@ -2584,8 +2587,13 @@ _error:
2584 2587
2585void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer) 2588void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer)
2586{ 2589{
2587 usb_kill_urb(mixer->urb); 2590 if (mixer->disconnected)
2588 usb_kill_urb(mixer->rc_urb); 2591 return;
2592 if (mixer->urb)
2593 usb_kill_urb(mixer->urb);
2594 if (mixer->rc_urb)
2595 usb_kill_urb(mixer->rc_urb);
2596 mixer->disconnected = true;
2589} 2597}
2590 2598
2591#ifdef CONFIG_PM 2599#ifdef CONFIG_PM
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index 2b4b067646ab..545d99b09706 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -22,6 +22,8 @@ struct usb_mixer_interface {
22 struct urb *rc_urb; 22 struct urb *rc_urb;
23 struct usb_ctrlrequest *rc_setup_packet; 23 struct usb_ctrlrequest *rc_setup_packet;
24 u8 rc_buffer[6]; 24 u8 rc_buffer[6];
25
26 bool disconnected;
25}; 27};
26 28
27#define MAX_CHANNELS 16 /* max logical channels */ 29#define MAX_CHANNELS 16 /* max logical channels */
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index b8cb57aeec77..9ddaae3784f5 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1138,6 +1138,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
1138 case USB_ID(0x047F, 0x0415): /* Plantronics BT-300 */ 1138 case USB_ID(0x047F, 0x0415): /* Plantronics BT-300 */
1139 case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */ 1139 case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */
1140 case USB_ID(0x047F, 0xC022): /* Plantronics C310 */ 1140 case USB_ID(0x047F, 0xC022): /* Plantronics C310 */
1141 case USB_ID(0x047F, 0xC02F): /* Plantronics P610 */
1141 case USB_ID(0x047F, 0xC036): /* Plantronics C520-M */ 1142 case USB_ID(0x047F, 0xC036): /* Plantronics C520-M */
1142 case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */ 1143 case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
1143 case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */ 1144 case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */