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

Commit 23105b4c authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ANDROID: sound: rawmidi: Hold lock around realloc"

parents 76c0fd9e 6d021f4b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ struct snd_rawmidi_runtime {
	size_t xruns;		/* over/underruns counter */
	/* misc */
	spinlock_t lock;
	struct mutex realloc_mutex;
	wait_queue_head_t sleep;
	/* event handler (new bytes, input only) */
	void (*event)(struct snd_rawmidi_substream *substream);
+39 −5
Original line number Diff line number Diff line
@@ -115,6 +115,7 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream)
		return -ENOMEM;
	runtime->substream = substream;
	spin_lock_init(&runtime->lock);
	mutex_init(&runtime->realloc_mutex);
	init_waitqueue_head(&runtime->sleep);
	INIT_WORK(&runtime->event_work, snd_rawmidi_input_event_work);
	runtime->event = NULL;
@@ -627,7 +628,9 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
			      struct snd_rawmidi_params * params)
{
	char *newbuf;
	char *oldbuf;
	struct snd_rawmidi_runtime *runtime = substream->runtime;
	unsigned long flags;

	if (substream->append && substream->use_count > 1)
		return -EBUSY;
@@ -639,13 +642,22 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
		return -EINVAL;
	}
	if (params->buffer_size != runtime->buffer_size) {
		newbuf = krealloc(runtime->buffer, params->buffer_size,
		mutex_lock(&runtime->realloc_mutex);
		newbuf = __krealloc(runtime->buffer, params->buffer_size,
				  GFP_KERNEL);
		if (!newbuf)
		if (!newbuf) {
			mutex_unlock(&runtime->realloc_mutex);
			return -ENOMEM;
		}
		spin_lock_irqsave(&runtime->lock, flags);
		oldbuf = runtime->buffer;
		runtime->buffer = newbuf;
		runtime->buffer_size = params->buffer_size;
		runtime->avail = runtime->buffer_size;
		spin_unlock_irqrestore(&runtime->lock, flags);
		if (oldbuf != newbuf)
			kfree(oldbuf);
		mutex_unlock(&runtime->realloc_mutex);
	}
	runtime->avail_min = params->avail_min;
	substream->active_sensing = !params->no_active_sensing;
@@ -657,7 +669,9 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
			     struct snd_rawmidi_params * params)
{
	char *newbuf;
	char *oldbuf;
	struct snd_rawmidi_runtime *runtime = substream->runtime;
	unsigned long flags;

	snd_rawmidi_drain_input(substream);
	if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) {
@@ -667,12 +681,21 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
		return -EINVAL;
	}
	if (params->buffer_size != runtime->buffer_size) {
		newbuf = krealloc(runtime->buffer, params->buffer_size,
		mutex_lock(&runtime->realloc_mutex);
		newbuf = __krealloc(runtime->buffer, params->buffer_size,
				  GFP_KERNEL);
		if (!newbuf)
		if (!newbuf) {
			mutex_unlock(&runtime->realloc_mutex);
			return -ENOMEM;
		}
		spin_lock_irqsave(&runtime->lock, flags);
		oldbuf = runtime->buffer;
		runtime->buffer = newbuf;
		runtime->buffer_size = params->buffer_size;
		spin_unlock_irqrestore(&runtime->lock, flags);
		if (oldbuf != newbuf)
			kfree(oldbuf);
		mutex_unlock(&runtime->realloc_mutex);
	}
	runtime->avail_min = params->avail_min;
	return 0;
@@ -945,6 +968,8 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
	unsigned long appl_ptr;

	spin_lock_irqsave(&runtime->lock, flags);
	if (userbuf)
		mutex_lock(&runtime->realloc_mutex);
	while (count > 0 && runtime->avail) {
		count1 = runtime->buffer_size - runtime->appl_ptr;
		if (count1 > count)
@@ -964,6 +989,7 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
			spin_unlock_irqrestore(&runtime->lock, flags);
			if (copy_to_user(userbuf + result,
					 runtime->buffer + appl_ptr, count1)) {
				mutex_unlock(&runtime->realloc_mutex);
				return result > 0 ? result : -EFAULT;
			}
			spin_lock_irqsave(&runtime->lock, flags);
@@ -972,6 +998,8 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
		count -= count1;
	}
	spin_unlock_irqrestore(&runtime->lock, flags);
	if (userbuf)
		mutex_unlock(&runtime->realloc_mutex);
	return result;
}

@@ -1236,10 +1264,14 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
		return -EINVAL;

	result = 0;
	if (userbuf)
		mutex_lock(&runtime->realloc_mutex);
	spin_lock_irqsave(&runtime->lock, flags);
	if (substream->append) {
		if ((long)runtime->avail < count) {
			spin_unlock_irqrestore(&runtime->lock, flags);
			if (userbuf)
				mutex_unlock(&runtime->realloc_mutex);
			return -EAGAIN;
		}
	}
@@ -1275,6 +1307,8 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
      __end:
	count1 = runtime->avail < runtime->buffer_size;
	spin_unlock_irqrestore(&runtime->lock, flags);
	if (userbuf)
		mutex_unlock(&runtime->realloc_mutex);
	if (count1)
		snd_rawmidi_output_trigger(substream, 1);
	return result;
+5 −1
Original line number Diff line number Diff line
@@ -1260,6 +1260,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client,
	struct snd_seq_client_port *port;
	struct snd_seq_port_info info;
	struct snd_seq_port_callback *callback;
	int port_idx;

	if (copy_from_user(&info, arg, sizeof(info)))
		return -EFAULT;
@@ -1273,7 +1274,9 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client,
		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) {
@@ -1294,6 +1297,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client,

	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);

	if (copy_to_user(arg, &info, sizeof(info)))
		return -EFAULT;
+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;
}