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

Commit 6a5e05a4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull char/misc fixes from Greg KH:
 "Here are some small misc driver fixes for 4.15-rc3 to resolve reported
  issues. Specifically these are:

   - binder fix for a memory leak

   - vpd driver fixes for a number of reported problems

   - hyperv driver fix for memory accesses where it shouldn't be.

  All of these have been in linux-next for a while. There's also one
  more MAINTAINERS file update that came in today to get the Android
  developer's emails correct, which is also in this pull request, that
  was not in linux-next, but should not be an issue"

* tag 'char-misc-4.15-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc:
  MAINTAINERS: update Android driver maintainers.
  firmware: vpd: Fix platform driver and device registration/unregistration
  firmware: vpd: Tie firmware kobject to device lifetime
  firmware: vpd: Destroy vpd sections in remove function
  hv: kvp: Avoid reading past allocated blocks from KVP file
  Drivers: hv: vmbus: Fix a rescind issue
  ANDROID: binder: fix transaction leak.
parents 1fbd55c0 66bc5df3
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -859,7 +859,8 @@ F: kernel/configs/android*
ANDROID DRIVERS
M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
M:	Arve Hjønnevåg <arve@android.com>
M:	Riley Andrews <riandrews@android.com>
M:	Todd Kjos <tkjos@android.com>
M:	Martijn Coenen <maco@android.com>
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
L:	devel@driverdev.osuosl.org
S:	Supported
+31 −9
Original line number Diff line number Diff line
@@ -1947,6 +1947,26 @@ static void binder_send_failed_reply(struct binder_transaction *t,
	}
}

/**
 * binder_cleanup_transaction() - cleans up undelivered transaction
 * @t:		transaction that needs to be cleaned up
 * @reason:	reason the transaction wasn't delivered
 * @error_code:	error to return to caller (if synchronous call)
 */
static void binder_cleanup_transaction(struct binder_transaction *t,
				       const char *reason,
				       uint32_t error_code)
{
	if (t->buffer->target_node && !(t->flags & TF_ONE_WAY)) {
		binder_send_failed_reply(t, error_code);
	} else {
		binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
			"undelivered transaction %d, %s\n",
			t->debug_id, reason);
		binder_free_transaction(t);
	}
}

/**
 * binder_validate_object() - checks for a valid metadata object in a buffer.
 * @buffer:	binder_buffer that we're parsing.
@@ -4015,12 +4035,20 @@ static int binder_thread_read(struct binder_proc *proc,
		if (put_user(cmd, (uint32_t __user *)ptr)) {
			if (t_from)
				binder_thread_dec_tmpref(t_from);

			binder_cleanup_transaction(t, "put_user failed",
						   BR_FAILED_REPLY);

			return -EFAULT;
		}
		ptr += sizeof(uint32_t);
		if (copy_to_user(ptr, &tr, sizeof(tr))) {
			if (t_from)
				binder_thread_dec_tmpref(t_from);

			binder_cleanup_transaction(t, "copy_to_user failed",
						   BR_FAILED_REPLY);

			return -EFAULT;
		}
		ptr += sizeof(tr);
@@ -4090,15 +4118,9 @@ static void binder_release_work(struct binder_proc *proc,
			struct binder_transaction *t;

			t = container_of(w, struct binder_transaction, work);
			if (t->buffer->target_node &&
			    !(t->flags & TF_ONE_WAY)) {
				binder_send_failed_reply(t, BR_DEAD_REPLY);
			} else {
				binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
					"undelivered transaction %d\n",
					t->debug_id);
				binder_free_transaction(t);
			}

			binder_cleanup_transaction(t, "process died.",
						   BR_DEAD_REPLY);
		} break;
		case BINDER_WORK_RETURN_ERROR: {
			struct binder_error *e = container_of(
+35 −13
Original line number Diff line number Diff line
@@ -295,38 +295,60 @@ static int vpd_probe(struct platform_device *pdev)
	if (ret)
		return ret;

	return vpd_sections_init(entry.cbmem_addr);
	vpd_kobj = kobject_create_and_add("vpd", firmware_kobj);
	if (!vpd_kobj)
		return -ENOMEM;

	ret = vpd_sections_init(entry.cbmem_addr);
	if (ret) {
		kobject_put(vpd_kobj);
		return ret;
	}

	return 0;
}

static int vpd_remove(struct platform_device *pdev)
{
	vpd_section_destroy(&ro_vpd);
	vpd_section_destroy(&rw_vpd);

	kobject_put(vpd_kobj);

	return 0;
}

static struct platform_driver vpd_driver = {
	.probe = vpd_probe,
	.remove = vpd_remove,
	.driver = {
		.name = "vpd",
	},
};

static struct platform_device *vpd_pdev;

static int __init vpd_platform_init(void)
{
	struct platform_device *pdev;

	pdev = platform_device_register_simple("vpd", -1, NULL, 0);
	if (IS_ERR(pdev))
		return PTR_ERR(pdev);
	int ret;

	vpd_kobj = kobject_create_and_add("vpd", firmware_kobj);
	if (!vpd_kobj)
		return -ENOMEM;
	ret = platform_driver_register(&vpd_driver);
	if (ret)
		return ret;

	platform_driver_register(&vpd_driver);
	vpd_pdev = platform_device_register_simple("vpd", -1, NULL, 0);
	if (IS_ERR(vpd_pdev)) {
		platform_driver_unregister(&vpd_driver);
		return PTR_ERR(vpd_pdev);
	}

	return 0;
}

static void __exit vpd_platform_exit(void)
{
	vpd_section_destroy(&ro_vpd);
	vpd_section_destroy(&rw_vpd);
	kobject_put(vpd_kobj);
	platform_device_unregister(vpd_pdev);
	platform_driver_unregister(&vpd_driver);
}

module_init(vpd_platform_init);
+8 −2
Original line number Diff line number Diff line
@@ -659,22 +659,28 @@ void vmbus_close(struct vmbus_channel *channel)
		 */
		return;
	}
	mutex_lock(&vmbus_connection.channel_mutex);
	/*
	 * Close all the sub-channels first and then close the
	 * primary channel.
	 */
	list_for_each_safe(cur, tmp, &channel->sc_list) {
		cur_channel = list_entry(cur, struct vmbus_channel, sc_list);
		vmbus_close_internal(cur_channel);
		if (cur_channel->rescind) {
			wait_for_completion(&cur_channel->rescind_event);
			mutex_lock(&vmbus_connection.channel_mutex);
			vmbus_close_internal(cur_channel);
			hv_process_channel_removal(
					   cur_channel->offermsg.child_relid);
		} else {
			mutex_lock(&vmbus_connection.channel_mutex);
			vmbus_close_internal(cur_channel);
		}
		mutex_unlock(&vmbus_connection.channel_mutex);
	}
	/*
	 * Now close the primary.
	 */
	mutex_lock(&vmbus_connection.channel_mutex);
	vmbus_close_internal(channel);
	mutex_unlock(&vmbus_connection.channel_mutex);
}
+4 −3
Original line number Diff line number Diff line
@@ -333,6 +333,7 @@ static struct vmbus_channel *alloc_channel(void)
		return NULL;

	spin_lock_init(&channel->lock);
	init_completion(&channel->rescind_event);

	INIT_LIST_HEAD(&channel->sc_list);
	INIT_LIST_HEAD(&channel->percpu_list);
@@ -898,6 +899,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
	/*
	 * Now wait for offer handling to complete.
	 */
	vmbus_rescind_cleanup(channel);
	while (READ_ONCE(channel->probe_done) == false) {
		/*
		 * We wait here until any channel offer is currently
@@ -913,7 +915,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
	if (channel->device_obj) {
		if (channel->chn_rescind_callback) {
			channel->chn_rescind_callback(channel);
			vmbus_rescind_cleanup(channel);
			return;
		}
		/*
@@ -922,7 +923,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
		 */
		dev = get_device(&channel->device_obj->device);
		if (dev) {
			vmbus_rescind_cleanup(channel);
			vmbus_device_unregister(channel->device_obj);
			put_device(dev);
		}
@@ -936,13 +936,14 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
		 * 2. Then close the primary channel.
		 */
		mutex_lock(&vmbus_connection.channel_mutex);
		vmbus_rescind_cleanup(channel);
		if (channel->state == CHANNEL_OPEN_STATE) {
			/*
			 * The channel is currently not open;
			 * it is safe for us to cleanup the channel.
			 */
			hv_process_channel_removal(rescind->child_relid);
		} else {
			complete(&channel->rescind_event);
		}
		mutex_unlock(&vmbus_connection.channel_mutex);
	}
Loading