mirror of https://gitee.com/openkylin/linux.git
sound fixes for 4.14-rc5
It's been a busy week for defending the attacks from fuzzer people; this pull request 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. -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEECxfAB4MH3rD5mfB6bDGAVD0pKaQFAlnePkwOHHRpd2FpQHN1 c2UuZGUACgkQbDGAVD0pKaSL3w/+Pc7+JNUwuhoXFbN3aq7/cH3v10+/2RMqfI9m TSi/F4u7wyYCSOkJOjK7CetSrMrzi6FVHhTqtTTKB4r9lcqLYuHOWRhE/6R4l8mx J8ZJaMiTXjSXl4nDWbNkBoDHxWH+JMN4XTaCTxJPUb/AKrxOYotahKIfTPgbWjAW GixnvGRpkmoRAKyAPlJDCFiD2pahDhf9zLFNkkQuYNH7oZH82nuXKS8h73oq9WDY 7TiGlLxK1afFSTcXFYOFd1njE8czocibVuarBlFA1CLLaCxZAYTo87Hg+WtYp30V 3nBK6ru/c0lQzhH9vv7uuT4XGzDKX1RfykF9AT8FNllNR/KqORu9O2gk9Zy+3ptq xWWPxjoWHUdPlp5igHGsSbjw6Y5MNAL0jc+SmfYzTI2aTrNji5ljwX2f9aNdsLf5 fW7AWSQk2KEd7i70TJ5TzMs30tF875wggoQYIFjUu+UF4ML728Ri/XvWmDIUaamq E+JVaCEAcFQ8HBEmwBGCT4ZL5P0cyZSH6DCnP4okg0nCBVwnsDkGJoWZayBP5lLL ts2f3PL1Vo0TdYlzY0HWQfiQvdlYPfJgmMPR5Hm8U1QptxbXZVnPkYAYzW3wGwnS tscgHHxW5zUl9/lQrc4VbGbzKCbGsCKlUoyrLbZ67LGN97lkq+u0bvNPf1UCkno/ 3ScZZFo= =sl20 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
7702f47623
|
@ -60,6 +60,7 @@ struct snd_virmidi_dev {
|
|||
int port; /* created/attached port */
|
||||
unsigned int flags; /* SNDRV_VIRMIDI_* */
|
||||
rwlock_t filelist_lock;
|
||||
struct rw_semaphore filelist_sem;
|
||||
struct list_head filelist;
|
||||
};
|
||||
|
||||
|
|
|
@ -1259,6 +1259,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)
|
|||
struct snd_seq_port_info *info = arg;
|
||||
struct snd_seq_client_port *port;
|
||||
struct snd_seq_port_callback *callback;
|
||||
int port_idx;
|
||||
|
||||
/* it is not allowed to create the port for an another client */
|
||||
if (info->addr.client != client->number)
|
||||
|
@ -1269,7 +1270,9 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)
|
|||
return -ENOMEM;
|
||||
|
||||
if (client->type == USER_CLIENT && info->kernel) {
|
||||
snd_seq_delete_port(client, port->addr.port);
|
||||
port_idx = port->addr.port;
|
||||
snd_seq_port_unlock(port);
|
||||
snd_seq_delete_port(client, port_idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (client->type == KERNEL_CLIENT) {
|
||||
|
@ -1290,6 +1293,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)
|
|||
|
||||
snd_seq_set_port_info(port, info);
|
||||
snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port);
|
||||
snd_seq_port_unlock(port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -122,7 +122,9 @@ static void port_subs_info_init(struct snd_seq_port_subs_info *grp)
|
|||
}
|
||||
|
||||
|
||||
/* create a port, port number is returned (-1 on failure) */
|
||||
/* create a port, port number is returned (-1 on failure);
|
||||
* the caller needs to unref the port via snd_seq_port_unlock() appropriately
|
||||
*/
|
||||
struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
|
||||
int port)
|
||||
{
|
||||
|
@ -151,6 +153,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
|
|||
snd_use_lock_init(&new_port->use_lock);
|
||||
port_subs_info_init(&new_port->c_src);
|
||||
port_subs_info_init(&new_port->c_dest);
|
||||
snd_use_lock_use(&new_port->use_lock);
|
||||
|
||||
num = port >= 0 ? port : 0;
|
||||
mutex_lock(&client->ports_mutex);
|
||||
|
@ -165,9 +168,9 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
|
|||
list_add_tail(&new_port->list, &p->list);
|
||||
client->num_ports++;
|
||||
new_port->addr.port = num; /* store the port number in the port */
|
||||
sprintf(new_port->name, "port-%d", num);
|
||||
write_unlock_irqrestore(&client->ports_lock, flags);
|
||||
mutex_unlock(&client->ports_mutex);
|
||||
sprintf(new_port->name, "port-%d", num);
|
||||
|
||||
return new_port;
|
||||
}
|
||||
|
|
|
@ -77,13 +77,17 @@ static void snd_virmidi_init_event(struct snd_virmidi *vmidi,
|
|||
* decode input event and put to read buffer of each opened file
|
||||
*/
|
||||
static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev,
|
||||
struct snd_seq_event *ev)
|
||||
struct snd_seq_event *ev,
|
||||
bool atomic)
|
||||
{
|
||||
struct snd_virmidi *vmidi;
|
||||
unsigned char msg[4];
|
||||
int len;
|
||||
|
||||
read_lock(&rdev->filelist_lock);
|
||||
if (atomic)
|
||||
read_lock(&rdev->filelist_lock);
|
||||
else
|
||||
down_read(&rdev->filelist_sem);
|
||||
list_for_each_entry(vmidi, &rdev->filelist, list) {
|
||||
if (!vmidi->trigger)
|
||||
continue;
|
||||
|
@ -97,7 +101,10 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev,
|
|||
snd_rawmidi_receive(vmidi->substream, msg, len);
|
||||
}
|
||||
}
|
||||
read_unlock(&rdev->filelist_lock);
|
||||
if (atomic)
|
||||
read_unlock(&rdev->filelist_lock);
|
||||
else
|
||||
up_read(&rdev->filelist_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -115,7 +122,7 @@ int snd_virmidi_receive(struct snd_rawmidi *rmidi, struct snd_seq_event *ev)
|
|||
struct snd_virmidi_dev *rdev;
|
||||
|
||||
rdev = rmidi->private_data;
|
||||
return snd_virmidi_dev_receive_event(rdev, ev);
|
||||
return snd_virmidi_dev_receive_event(rdev, ev, true);
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
|
@ -130,7 +137,7 @@ static int snd_virmidi_event_input(struct snd_seq_event *ev, int direct,
|
|||
rdev = private_data;
|
||||
if (!(rdev->flags & SNDRV_VIRMIDI_USE))
|
||||
return 0; /* ignored */
|
||||
return snd_virmidi_dev_receive_event(rdev, ev);
|
||||
return snd_virmidi_dev_receive_event(rdev, ev, atomic);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -209,7 +216,6 @@ static int snd_virmidi_input_open(struct snd_rawmidi_substream *substream)
|
|||
struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
|
||||
struct snd_rawmidi_runtime *runtime = substream->runtime;
|
||||
struct snd_virmidi *vmidi;
|
||||
unsigned long flags;
|
||||
|
||||
vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL);
|
||||
if (vmidi == NULL)
|
||||
|
@ -223,9 +229,11 @@ static int snd_virmidi_input_open(struct snd_rawmidi_substream *substream)
|
|||
vmidi->client = rdev->client;
|
||||
vmidi->port = rdev->port;
|
||||
runtime->private_data = vmidi;
|
||||
write_lock_irqsave(&rdev->filelist_lock, flags);
|
||||
down_write(&rdev->filelist_sem);
|
||||
write_lock_irq(&rdev->filelist_lock);
|
||||
list_add_tail(&vmidi->list, &rdev->filelist);
|
||||
write_unlock_irqrestore(&rdev->filelist_lock, flags);
|
||||
write_unlock_irq(&rdev->filelist_lock);
|
||||
up_write(&rdev->filelist_sem);
|
||||
vmidi->rdev = rdev;
|
||||
return 0;
|
||||
}
|
||||
|
@ -264,9 +272,11 @@ static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream)
|
|||
struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
|
||||
struct snd_virmidi *vmidi = substream->runtime->private_data;
|
||||
|
||||
down_write(&rdev->filelist_sem);
|
||||
write_lock_irq(&rdev->filelist_lock);
|
||||
list_del(&vmidi->list);
|
||||
write_unlock_irq(&rdev->filelist_lock);
|
||||
up_write(&rdev->filelist_sem);
|
||||
snd_midi_event_free(vmidi->parser);
|
||||
substream->runtime->private_data = NULL;
|
||||
kfree(vmidi);
|
||||
|
@ -520,6 +530,7 @@ int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmi
|
|||
rdev->rmidi = rmidi;
|
||||
rdev->device = device;
|
||||
rdev->client = -1;
|
||||
init_rwsem(&rdev->filelist_sem);
|
||||
rwlock_init(&rdev->filelist_lock);
|
||||
INIT_LIST_HEAD(&rdev->filelist);
|
||||
rdev->seq_mode = SNDRV_VIRMIDI_SEQ_DISPATCH;
|
||||
|
|
|
@ -469,10 +469,12 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
|
|||
|
||||
err = snd_usb_caiaq_send_command(cdev, EP1_CMD_GET_DEVICE_INFO, NULL, 0);
|
||||
if (err)
|
||||
return err;
|
||||
goto err_kill_urb;
|
||||
|
||||
if (!wait_event_timeout(cdev->ep1_wait_queue, cdev->spec_received, HZ))
|
||||
return -ENODEV;
|
||||
if (!wait_event_timeout(cdev->ep1_wait_queue, cdev->spec_received, HZ)) {
|
||||
err = -ENODEV;
|
||||
goto err_kill_urb;
|
||||
}
|
||||
|
||||
usb_string(usb_dev, usb_dev->descriptor.iManufacturer,
|
||||
cdev->vendor_name, CAIAQ_USB_STR_LEN);
|
||||
|
@ -507,6 +509,10 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
|
|||
|
||||
setup_card(cdev);
|
||||
return 0;
|
||||
|
||||
err_kill_urb:
|
||||
usb_kill_urb(&cdev->ep1_in_urb);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int snd_probe(struct usb_interface *intf,
|
||||
|
|
|
@ -779,9 +779,10 @@ int line6_probe(struct usb_interface *interface,
|
|||
return 0;
|
||||
|
||||
error:
|
||||
if (line6->disconnect)
|
||||
line6->disconnect(line6);
|
||||
snd_card_free(card);
|
||||
/* we can call disconnect callback here because no close-sync is
|
||||
* needed yet at this point
|
||||
*/
|
||||
line6_disconnect(interface);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(line6_probe);
|
||||
|
|
|
@ -301,7 +301,8 @@ static void podhd_disconnect(struct usb_line6 *line6)
|
|||
|
||||
intf = usb_ifnum_to_if(line6->usbdev,
|
||||
pod->line6.properties->ctrl_if);
|
||||
usb_driver_release_interface(&podhd_driver, intf);
|
||||
if (intf)
|
||||
usb_driver_release_interface(&podhd_driver, intf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,6 +318,9 @@ static int podhd_init(struct usb_line6 *line6,
|
|||
|
||||
line6->disconnect = podhd_disconnect;
|
||||
|
||||
init_timer(&pod->startup_timer);
|
||||
INIT_WORK(&pod->startup_work, podhd_startup_workqueue);
|
||||
|
||||
if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
|
||||
/* claim the data interface */
|
||||
intf = usb_ifnum_to_if(line6->usbdev,
|
||||
|
@ -358,8 +362,6 @@ static int podhd_init(struct usb_line6 *line6,
|
|||
}
|
||||
|
||||
/* init device and delay registering */
|
||||
init_timer(&pod->startup_timer);
|
||||
INIT_WORK(&pod->startup_work, podhd_startup_workqueue);
|
||||
podhd_startup(pod);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -2234,6 +2234,9 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
|
|||
|
||||
static void snd_usb_mixer_free(struct usb_mixer_interface *mixer)
|
||||
{
|
||||
/* kill pending URBs */
|
||||
snd_usb_mixer_disconnect(mixer);
|
||||
|
||||
kfree(mixer->id_elems);
|
||||
if (mixer->urb) {
|
||||
kfree(mixer->urb->transfer_buffer);
|
||||
|
@ -2584,8 +2587,13 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
|
|||
|
||||
void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer)
|
||||
{
|
||||
usb_kill_urb(mixer->urb);
|
||||
usb_kill_urb(mixer->rc_urb);
|
||||
if (mixer->disconnected)
|
||||
return;
|
||||
if (mixer->urb)
|
||||
usb_kill_urb(mixer->urb);
|
||||
if (mixer->rc_urb)
|
||||
usb_kill_urb(mixer->rc_urb);
|
||||
mixer->disconnected = true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
|
|
@ -22,6 +22,8 @@ struct usb_mixer_interface {
|
|||
struct urb *rc_urb;
|
||||
struct usb_ctrlrequest *rc_setup_packet;
|
||||
u8 rc_buffer[6];
|
||||
|
||||
bool disconnected;
|
||||
};
|
||||
|
||||
#define MAX_CHANNELS 16 /* max logical channels */
|
||||
|
|
|
@ -1138,6 +1138,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
|
|||
case USB_ID(0x047F, 0x0415): /* Plantronics BT-300 */
|
||||
case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */
|
||||
case USB_ID(0x047F, 0xC022): /* Plantronics C310 */
|
||||
case USB_ID(0x047F, 0xC02F): /* Plantronics P610 */
|
||||
case USB_ID(0x047F, 0xC036): /* Plantronics C520-M */
|
||||
case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
|
||||
case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */
|
||||
|
|
Loading…
Reference in New Issue