Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7702f476 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 467251c6 99fee508
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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;
};

+5 −1
Original line number Diff line number Diff line
@@ -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;
}
+5 −2
Original line number Diff line number Diff line
@@ -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;
}
+19 −8
Original line number Diff line number Diff line
@@ -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;

	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);
		}
	}
	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;
+9 −3
Original line number Diff line number Diff line
@@ -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,
Loading