aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-12-05 13:06:23 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-12-05 13:06:23 -0500
commit6a5e05a47b6cb8e59bfad351444322b1e4012326 (patch)
tree3387834d1084fbd53d86dcc4c23097db0d51f45b
parent1fbd55c0ccd842a976d16431b57121b7892ed8ce (diff)
parent66bc5df31110652a31c91f14b4e23f7c51e5328e (diff)
Merge tag 'char-misc-4.15-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
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.
-rw-r--r--MAINTAINERS3
-rw-r--r--drivers/android/binder.c40
-rw-r--r--drivers/firmware/google/vpd.c48
-rw-r--r--drivers/hv/channel.c10
-rw-r--r--drivers/hv/channel_mgmt.c7
-rw-r--r--include/linux/hyperv.h1
-rw-r--r--tools/hv/hv_kvp_daemon.c70
7 files changed, 95 insertions, 84 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 745337ed01f6..64c1ceaef4be 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -859,7 +859,8 @@ F: kernel/configs/android*
859ANDROID DRIVERS 859ANDROID DRIVERS
860M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> 860M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
861M: Arve Hjønnevåg <arve@android.com> 861M: Arve Hjønnevåg <arve@android.com>
862M: Riley Andrews <riandrews@android.com> 862M: Todd Kjos <tkjos@android.com>
863M: Martijn Coenen <maco@android.com>
863T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git 864T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
864L: devel@driverdev.osuosl.org 865L: devel@driverdev.osuosl.org
865S: Supported 866S: Supported
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index a73596a4f804..bccec9de0533 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1948,6 +1948,26 @@ static void binder_send_failed_reply(struct binder_transaction *t,
1948} 1948}
1949 1949
1950/** 1950/**
1951 * binder_cleanup_transaction() - cleans up undelivered transaction
1952 * @t: transaction that needs to be cleaned up
1953 * @reason: reason the transaction wasn't delivered
1954 * @error_code: error to return to caller (if synchronous call)
1955 */
1956static void binder_cleanup_transaction(struct binder_transaction *t,
1957 const char *reason,
1958 uint32_t error_code)
1959{
1960 if (t->buffer->target_node && !(t->flags & TF_ONE_WAY)) {
1961 binder_send_failed_reply(t, error_code);
1962 } else {
1963 binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
1964 "undelivered transaction %d, %s\n",
1965 t->debug_id, reason);
1966 binder_free_transaction(t);
1967 }
1968}
1969
1970/**
1951 * binder_validate_object() - checks for a valid metadata object in a buffer. 1971 * binder_validate_object() - checks for a valid metadata object in a buffer.
1952 * @buffer: binder_buffer that we're parsing. 1972 * @buffer: binder_buffer that we're parsing.
1953 * @offset: offset in the buffer at which to validate an object. 1973 * @offset: offset in the buffer at which to validate an object.
@@ -4015,12 +4035,20 @@ retry:
4015 if (put_user(cmd, (uint32_t __user *)ptr)) { 4035 if (put_user(cmd, (uint32_t __user *)ptr)) {
4016 if (t_from) 4036 if (t_from)
4017 binder_thread_dec_tmpref(t_from); 4037 binder_thread_dec_tmpref(t_from);
4038
4039 binder_cleanup_transaction(t, "put_user failed",
4040 BR_FAILED_REPLY);
4041
4018 return -EFAULT; 4042 return -EFAULT;
4019 } 4043 }
4020 ptr += sizeof(uint32_t); 4044 ptr += sizeof(uint32_t);
4021 if (copy_to_user(ptr, &tr, sizeof(tr))) { 4045 if (copy_to_user(ptr, &tr, sizeof(tr))) {
4022 if (t_from) 4046 if (t_from)
4023 binder_thread_dec_tmpref(t_from); 4047 binder_thread_dec_tmpref(t_from);
4048
4049 binder_cleanup_transaction(t, "copy_to_user failed",
4050 BR_FAILED_REPLY);
4051
4024 return -EFAULT; 4052 return -EFAULT;
4025 } 4053 }
4026 ptr += sizeof(tr); 4054 ptr += sizeof(tr);
@@ -4090,15 +4118,9 @@ static void binder_release_work(struct binder_proc *proc,
4090 struct binder_transaction *t; 4118 struct binder_transaction *t;
4091 4119
4092 t = container_of(w, struct binder_transaction, work); 4120 t = container_of(w, struct binder_transaction, work);
4093 if (t->buffer->target_node && 4121
4094 !(t->flags & TF_ONE_WAY)) { 4122 binder_cleanup_transaction(t, "process died.",
4095 binder_send_failed_reply(t, BR_DEAD_REPLY); 4123 BR_DEAD_REPLY);
4096 } else {
4097 binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
4098 "undelivered transaction %d\n",
4099 t->debug_id);
4100 binder_free_transaction(t);
4101 }
4102 } break; 4124 } break;
4103 case BINDER_WORK_RETURN_ERROR: { 4125 case BINDER_WORK_RETURN_ERROR: {
4104 struct binder_error *e = container_of( 4126 struct binder_error *e = container_of(
diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c
index 35e553b3b190..e4b40f2b4627 100644
--- a/drivers/firmware/google/vpd.c
+++ b/drivers/firmware/google/vpd.c
@@ -295,38 +295,60 @@ static int vpd_probe(struct platform_device *pdev)
295 if (ret) 295 if (ret)
296 return ret; 296 return ret;
297 297
298 return vpd_sections_init(entry.cbmem_addr); 298 vpd_kobj = kobject_create_and_add("vpd", firmware_kobj);
299 if (!vpd_kobj)
300 return -ENOMEM;
301
302 ret = vpd_sections_init(entry.cbmem_addr);
303 if (ret) {
304 kobject_put(vpd_kobj);
305 return ret;
306 }
307
308 return 0;
309}
310
311static int vpd_remove(struct platform_device *pdev)
312{
313 vpd_section_destroy(&ro_vpd);
314 vpd_section_destroy(&rw_vpd);
315
316 kobject_put(vpd_kobj);
317
318 return 0;
299} 319}
300 320
301static struct platform_driver vpd_driver = { 321static struct platform_driver vpd_driver = {
302 .probe = vpd_probe, 322 .probe = vpd_probe,
323 .remove = vpd_remove,
303 .driver = { 324 .driver = {
304 .name = "vpd", 325 .name = "vpd",
305 }, 326 },
306}; 327};
307 328
329static struct platform_device *vpd_pdev;
330
308static int __init vpd_platform_init(void) 331static int __init vpd_platform_init(void)
309{ 332{
310 struct platform_device *pdev; 333 int ret;
311
312 pdev = platform_device_register_simple("vpd", -1, NULL, 0);
313 if (IS_ERR(pdev))
314 return PTR_ERR(pdev);
315 334
316 vpd_kobj = kobject_create_and_add("vpd", firmware_kobj); 335 ret = platform_driver_register(&vpd_driver);
317 if (!vpd_kobj) 336 if (ret)
318 return -ENOMEM; 337 return ret;
319 338
320 platform_driver_register(&vpd_driver); 339 vpd_pdev = platform_device_register_simple("vpd", -1, NULL, 0);
340 if (IS_ERR(vpd_pdev)) {
341 platform_driver_unregister(&vpd_driver);
342 return PTR_ERR(vpd_pdev);
343 }
321 344
322 return 0; 345 return 0;
323} 346}
324 347
325static void __exit vpd_platform_exit(void) 348static void __exit vpd_platform_exit(void)
326{ 349{
327 vpd_section_destroy(&ro_vpd); 350 platform_device_unregister(vpd_pdev);
328 vpd_section_destroy(&rw_vpd); 351 platform_driver_unregister(&vpd_driver);
329 kobject_put(vpd_kobj);
330} 352}
331 353
332module_init(vpd_platform_init); 354module_init(vpd_platform_init);
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index 19f0cf37e0ed..ba0a092ae085 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -659,22 +659,28 @@ void vmbus_close(struct vmbus_channel *channel)
659 */ 659 */
660 return; 660 return;
661 } 661 }
662 mutex_lock(&vmbus_connection.channel_mutex);
663 /* 662 /*
664 * Close all the sub-channels first and then close the 663 * Close all the sub-channels first and then close the
665 * primary channel. 664 * primary channel.
666 */ 665 */
667 list_for_each_safe(cur, tmp, &channel->sc_list) { 666 list_for_each_safe(cur, tmp, &channel->sc_list) {
668 cur_channel = list_entry(cur, struct vmbus_channel, sc_list); 667 cur_channel = list_entry(cur, struct vmbus_channel, sc_list);
669 vmbus_close_internal(cur_channel);
670 if (cur_channel->rescind) { 668 if (cur_channel->rescind) {
669 wait_for_completion(&cur_channel->rescind_event);
670 mutex_lock(&vmbus_connection.channel_mutex);
671 vmbus_close_internal(cur_channel);
671 hv_process_channel_removal( 672 hv_process_channel_removal(
672 cur_channel->offermsg.child_relid); 673 cur_channel->offermsg.child_relid);
674 } else {
675 mutex_lock(&vmbus_connection.channel_mutex);
676 vmbus_close_internal(cur_channel);
673 } 677 }
678 mutex_unlock(&vmbus_connection.channel_mutex);
674 } 679 }
675 /* 680 /*
676 * Now close the primary. 681 * Now close the primary.
677 */ 682 */
683 mutex_lock(&vmbus_connection.channel_mutex);
678 vmbus_close_internal(channel); 684 vmbus_close_internal(channel);
679 mutex_unlock(&vmbus_connection.channel_mutex); 685 mutex_unlock(&vmbus_connection.channel_mutex);
680} 686}
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index ec5454f3f4a6..c21020b69114 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -333,6 +333,7 @@ static struct vmbus_channel *alloc_channel(void)
333 return NULL; 333 return NULL;
334 334
335 spin_lock_init(&channel->lock); 335 spin_lock_init(&channel->lock);
336 init_completion(&channel->rescind_event);
336 337
337 INIT_LIST_HEAD(&channel->sc_list); 338 INIT_LIST_HEAD(&channel->sc_list);
338 INIT_LIST_HEAD(&channel->percpu_list); 339 INIT_LIST_HEAD(&channel->percpu_list);
@@ -898,6 +899,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
898 /* 899 /*
899 * Now wait for offer handling to complete. 900 * Now wait for offer handling to complete.
900 */ 901 */
902 vmbus_rescind_cleanup(channel);
901 while (READ_ONCE(channel->probe_done) == false) { 903 while (READ_ONCE(channel->probe_done) == false) {
902 /* 904 /*
903 * We wait here until any channel offer is currently 905 * We wait here until any channel offer is currently
@@ -913,7 +915,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
913 if (channel->device_obj) { 915 if (channel->device_obj) {
914 if (channel->chn_rescind_callback) { 916 if (channel->chn_rescind_callback) {
915 channel->chn_rescind_callback(channel); 917 channel->chn_rescind_callback(channel);
916 vmbus_rescind_cleanup(channel);
917 return; 918 return;
918 } 919 }
919 /* 920 /*
@@ -922,7 +923,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
922 */ 923 */
923 dev = get_device(&channel->device_obj->device); 924 dev = get_device(&channel->device_obj->device);
924 if (dev) { 925 if (dev) {
925 vmbus_rescind_cleanup(channel);
926 vmbus_device_unregister(channel->device_obj); 926 vmbus_device_unregister(channel->device_obj);
927 put_device(dev); 927 put_device(dev);
928 } 928 }
@@ -936,13 +936,14 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
936 * 2. Then close the primary channel. 936 * 2. Then close the primary channel.
937 */ 937 */
938 mutex_lock(&vmbus_connection.channel_mutex); 938 mutex_lock(&vmbus_connection.channel_mutex);
939 vmbus_rescind_cleanup(channel);
940 if (channel->state == CHANNEL_OPEN_STATE) { 939 if (channel->state == CHANNEL_OPEN_STATE) {
941 /* 940 /*
942 * The channel is currently not open; 941 * The channel is currently not open;
943 * it is safe for us to cleanup the channel. 942 * it is safe for us to cleanup the channel.
944 */ 943 */
945 hv_process_channel_removal(rescind->child_relid); 944 hv_process_channel_removal(rescind->child_relid);
945 } else {
946 complete(&channel->rescind_event);
946 } 947 }
947 mutex_unlock(&vmbus_connection.channel_mutex); 948 mutex_unlock(&vmbus_connection.channel_mutex);
948 } 949 }
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index f3e97c5f94c9..6c9336626592 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -708,6 +708,7 @@ struct vmbus_channel {
708 u8 monitor_bit; 708 u8 monitor_bit;
709 709
710 bool rescind; /* got rescind msg */ 710 bool rescind; /* got rescind msg */
711 struct completion rescind_event;
711 712
712 u32 ringbuffer_gpadlhandle; 713 u32 ringbuffer_gpadlhandle;
713 714
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index eaa3bec273c8..4c99c57736ce 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -193,11 +193,14 @@ static void kvp_update_mem_state(int pool)
193 for (;;) { 193 for (;;) {
194 readp = &record[records_read]; 194 readp = &record[records_read];
195 records_read += fread(readp, sizeof(struct kvp_record), 195 records_read += fread(readp, sizeof(struct kvp_record),
196 ENTRIES_PER_BLOCK * num_blocks, 196 ENTRIES_PER_BLOCK * num_blocks - records_read,
197 filep); 197 filep);
198 198
199 if (ferror(filep)) { 199 if (ferror(filep)) {
200 syslog(LOG_ERR, "Failed to read file, pool: %d", pool); 200 syslog(LOG_ERR,
201 "Failed to read file, pool: %d; error: %d %s",
202 pool, errno, strerror(errno));
203 kvp_release_lock(pool);
201 exit(EXIT_FAILURE); 204 exit(EXIT_FAILURE);
202 } 205 }
203 206
@@ -210,6 +213,7 @@ static void kvp_update_mem_state(int pool)
210 213
211 if (record == NULL) { 214 if (record == NULL) {
212 syslog(LOG_ERR, "malloc failed"); 215 syslog(LOG_ERR, "malloc failed");
216 kvp_release_lock(pool);
213 exit(EXIT_FAILURE); 217 exit(EXIT_FAILURE);
214 } 218 }
215 continue; 219 continue;
@@ -224,15 +228,11 @@ static void kvp_update_mem_state(int pool)
224 fclose(filep); 228 fclose(filep);
225 kvp_release_lock(pool); 229 kvp_release_lock(pool);
226} 230}
231
227static int kvp_file_init(void) 232static int kvp_file_init(void)
228{ 233{
229 int fd; 234 int fd;
230 FILE *filep;
231 size_t records_read;
232 char *fname; 235 char *fname;
233 struct kvp_record *record;
234 struct kvp_record *readp;
235 int num_blocks;
236 int i; 236 int i;
237 int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK; 237 int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK;
238 238
@@ -246,61 +246,19 @@ static int kvp_file_init(void)
246 246
247 for (i = 0; i < KVP_POOL_COUNT; i++) { 247 for (i = 0; i < KVP_POOL_COUNT; i++) {
248 fname = kvp_file_info[i].fname; 248 fname = kvp_file_info[i].fname;
249 records_read = 0;
250 num_blocks = 1;
251 sprintf(fname, "%s/.kvp_pool_%d", KVP_CONFIG_LOC, i); 249 sprintf(fname, "%s/.kvp_pool_%d", KVP_CONFIG_LOC, i);
252 fd = open(fname, O_RDWR | O_CREAT | O_CLOEXEC, 0644 /* rw-r--r-- */); 250 fd = open(fname, O_RDWR | O_CREAT | O_CLOEXEC, 0644 /* rw-r--r-- */);
253 251
254 if (fd == -1) 252 if (fd == -1)
255 return 1; 253 return 1;
256 254
257
258 filep = fopen(fname, "re");
259 if (!filep) {
260 close(fd);
261 return 1;
262 }
263
264 record = malloc(alloc_unit * num_blocks);
265 if (record == NULL) {
266 fclose(filep);
267 close(fd);
268 return 1;
269 }
270 for (;;) {
271 readp = &record[records_read];
272 records_read += fread(readp, sizeof(struct kvp_record),
273 ENTRIES_PER_BLOCK,
274 filep);
275
276 if (ferror(filep)) {
277 syslog(LOG_ERR, "Failed to read file, pool: %d",
278 i);
279 exit(EXIT_FAILURE);
280 }
281
282 if (!feof(filep)) {
283 /*
284 * We have more data to read.
285 */
286 num_blocks++;
287 record = realloc(record, alloc_unit *
288 num_blocks);
289 if (record == NULL) {
290 fclose(filep);
291 close(fd);
292 return 1;
293 }
294 continue;
295 }
296 break;
297 }
298 kvp_file_info[i].fd = fd; 255 kvp_file_info[i].fd = fd;
299 kvp_file_info[i].num_blocks = num_blocks; 256 kvp_file_info[i].num_blocks = 1;
300 kvp_file_info[i].records = record; 257 kvp_file_info[i].records = malloc(alloc_unit);
301 kvp_file_info[i].num_records = records_read; 258 if (kvp_file_info[i].records == NULL)
302 fclose(filep); 259 return 1;
303 260 kvp_file_info[i].num_records = 0;
261 kvp_update_mem_state(i);
304 } 262 }
305 263
306 return 0; 264 return 0;