Skip to content

Commit 6a5e05a

Browse files
committed
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.
2 parents 1fbd55c + 66bc5df commit 6a5e05a

File tree

7 files changed

+95
-84
lines changed

7 files changed

+95
-84
lines changed

MAINTAINERS

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -859,7 +859,8 @@ F: kernel/configs/android*
859859
ANDROID DRIVERS
860860
M: Greg Kroah-Hartman <[email protected]>
861861
M: Arve Hjønnevåg <[email protected]>
862-
M: Riley Andrews <[email protected]>
862+
M: Todd Kjos <[email protected]>
863+
M: Martijn Coenen <[email protected]>
863864
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
864865
865866
S: Supported

drivers/android/binder.c

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1947,6 +1947,26 @@ static void binder_send_failed_reply(struct binder_transaction *t,
19471947
}
19481948
}
19491949

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+
*/
1956+
static 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+
19501970
/**
19511971
* binder_validate_object() - checks for a valid metadata object in a buffer.
19521972
* @buffer: binder_buffer that we're parsing.
@@ -4015,12 +4035,20 @@ static int binder_thread_read(struct binder_proc *proc,
40154035
if (put_user(cmd, (uint32_t __user *)ptr)) {
40164036
if (t_from)
40174037
binder_thread_dec_tmpref(t_from);
4038+
4039+
binder_cleanup_transaction(t, "put_user failed",
4040+
BR_FAILED_REPLY);
4041+
40184042
return -EFAULT;
40194043
}
40204044
ptr += sizeof(uint32_t);
40214045
if (copy_to_user(ptr, &tr, sizeof(tr))) {
40224046
if (t_from)
40234047
binder_thread_dec_tmpref(t_from);
4048+
4049+
binder_cleanup_transaction(t, "copy_to_user failed",
4050+
BR_FAILED_REPLY);
4051+
40244052
return -EFAULT;
40254053
}
40264054
ptr += sizeof(tr);
@@ -4090,15 +4118,9 @@ static void binder_release_work(struct binder_proc *proc,
40904118
struct binder_transaction *t;
40914119

40924120
t = container_of(w, struct binder_transaction, work);
4093-
if (t->buffer->target_node &&
4094-
!(t->flags & TF_ONE_WAY)) {
4095-
binder_send_failed_reply(t, 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-
}
4121+
4122+
binder_cleanup_transaction(t, "process died.",
4123+
BR_DEAD_REPLY);
41024124
} break;
41034125
case BINDER_WORK_RETURN_ERROR: {
41044126
struct binder_error *e = container_of(

drivers/firmware/google/vpd.c

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -295,38 +295,60 @@ static int vpd_probe(struct platform_device *pdev)
295295
if (ret)
296296
return ret;
297297

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+
311+
static 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;
299319
}
300320

301321
static struct platform_driver vpd_driver = {
302322
.probe = vpd_probe,
323+
.remove = vpd_remove,
303324
.driver = {
304325
.name = "vpd",
305326
},
306327
};
307328

329+
static struct platform_device *vpd_pdev;
330+
308331
static int __init vpd_platform_init(void)
309332
{
310-
struct platform_device *pdev;
311-
312-
pdev = platform_device_register_simple("vpd", -1, NULL, 0);
313-
if (IS_ERR(pdev))
314-
return PTR_ERR(pdev);
333+
int ret;
315334

316-
vpd_kobj = kobject_create_and_add("vpd", firmware_kobj);
317-
if (!vpd_kobj)
318-
return -ENOMEM;
335+
ret = platform_driver_register(&vpd_driver);
336+
if (ret)
337+
return ret;
319338

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+
}
321344

322345
return 0;
323346
}
324347

325348
static void __exit vpd_platform_exit(void)
326349
{
327-
vpd_section_destroy(&ro_vpd);
328-
vpd_section_destroy(&rw_vpd);
329-
kobject_put(vpd_kobj);
350+
platform_device_unregister(vpd_pdev);
351+
platform_driver_unregister(&vpd_driver);
330352
}
331353

332354
module_init(vpd_platform_init);

drivers/hv/channel.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -659,22 +659,28 @@ void vmbus_close(struct vmbus_channel *channel)
659659
*/
660660
return;
661661
}
662-
mutex_lock(&vmbus_connection.channel_mutex);
663662
/*
664663
* Close all the sub-channels first and then close the
665664
* primary channel.
666665
*/
667666
list_for_each_safe(cur, tmp, &channel->sc_list) {
668667
cur_channel = list_entry(cur, struct vmbus_channel, sc_list);
669-
vmbus_close_internal(cur_channel);
670668
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);
671672
hv_process_channel_removal(
672673
cur_channel->offermsg.child_relid);
674+
} else {
675+
mutex_lock(&vmbus_connection.channel_mutex);
676+
vmbus_close_internal(cur_channel);
673677
}
678+
mutex_unlock(&vmbus_connection.channel_mutex);
674679
}
675680
/*
676681
* Now close the primary.
677682
*/
683+
mutex_lock(&vmbus_connection.channel_mutex);
678684
vmbus_close_internal(channel);
679685
mutex_unlock(&vmbus_connection.channel_mutex);
680686
}

drivers/hv/channel_mgmt.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ static struct vmbus_channel *alloc_channel(void)
333333
return NULL;
334334

335335
spin_lock_init(&channel->lock);
336+
init_completion(&channel->rescind_event);
336337

337338
INIT_LIST_HEAD(&channel->sc_list);
338339
INIT_LIST_HEAD(&channel->percpu_list);
@@ -898,6 +899,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
898899
/*
899900
* Now wait for offer handling to complete.
900901
*/
902+
vmbus_rescind_cleanup(channel);
901903
while (READ_ONCE(channel->probe_done) == false) {
902904
/*
903905
* We wait here until any channel offer is currently
@@ -913,7 +915,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
913915
if (channel->device_obj) {
914916
if (channel->chn_rescind_callback) {
915917
channel->chn_rescind_callback(channel);
916-
vmbus_rescind_cleanup(channel);
917918
return;
918919
}
919920
/*
@@ -922,7 +923,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
922923
*/
923924
dev = get_device(&channel->device_obj->device);
924925
if (dev) {
925-
vmbus_rescind_cleanup(channel);
926926
vmbus_device_unregister(channel->device_obj);
927927
put_device(dev);
928928
}
@@ -936,13 +936,14 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
936936
* 2. Then close the primary channel.
937937
*/
938938
mutex_lock(&vmbus_connection.channel_mutex);
939-
vmbus_rescind_cleanup(channel);
940939
if (channel->state == CHANNEL_OPEN_STATE) {
941940
/*
942941
* The channel is currently not open;
943942
* it is safe for us to cleanup the channel.
944943
*/
945944
hv_process_channel_removal(rescind->child_relid);
945+
} else {
946+
complete(&channel->rescind_event);
946947
}
947948
mutex_unlock(&vmbus_connection.channel_mutex);
948949
}

include/linux/hyperv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,7 @@ struct vmbus_channel {
708708
u8 monitor_bit;
709709

710710
bool rescind; /* got rescind msg */
711+
struct completion rescind_event;
711712

712713
u32 ringbuffer_gpadlhandle;
713714

tools/hv/hv_kvp_daemon.c

Lines changed: 14 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,14 @@ static void kvp_update_mem_state(int pool)
193193
for (;;) {
194194
readp = &record[records_read];
195195
records_read += fread(readp, sizeof(struct kvp_record),
196-
ENTRIES_PER_BLOCK * num_blocks,
197-
filep);
196+
ENTRIES_PER_BLOCK * num_blocks - records_read,
197+
filep);
198198

199199
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);
201204
exit(EXIT_FAILURE);
202205
}
203206

@@ -210,6 +213,7 @@ static void kvp_update_mem_state(int pool)
210213

211214
if (record == NULL) {
212215
syslog(LOG_ERR, "malloc failed");
216+
kvp_release_lock(pool);
213217
exit(EXIT_FAILURE);
214218
}
215219
continue;
@@ -224,15 +228,11 @@ static void kvp_update_mem_state(int pool)
224228
fclose(filep);
225229
kvp_release_lock(pool);
226230
}
231+
227232
static int kvp_file_init(void)
228233
{
229234
int fd;
230-
FILE *filep;
231-
size_t records_read;
232235
char *fname;
233-
struct kvp_record *record;
234-
struct kvp_record *readp;
235-
int num_blocks;
236236
int i;
237237
int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK;
238238

@@ -246,61 +246,19 @@ static int kvp_file_init(void)
246246

247247
for (i = 0; i < KVP_POOL_COUNT; i++) {
248248
fname = kvp_file_info[i].fname;
249-
records_read = 0;
250-
num_blocks = 1;
251249
sprintf(fname, "%s/.kvp_pool_%d", KVP_CONFIG_LOC, i);
252250
fd = open(fname, O_RDWR | O_CREAT | O_CLOEXEC, 0644 /* rw-r--r-- */);
253251

254252
if (fd == -1)
255253
return 1;
256254

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-
}
298255
kvp_file_info[i].fd = fd;
299-
kvp_file_info[i].num_blocks = num_blocks;
300-
kvp_file_info[i].records = record;
301-
kvp_file_info[i].num_records = records_read;
302-
fclose(filep);
303-
256+
kvp_file_info[i].num_blocks = 1;
257+
kvp_file_info[i].records = malloc(alloc_unit);
258+
if (kvp_file_info[i].records == NULL)
259+
return 1;
260+
kvp_file_info[i].num_records = 0;
261+
kvp_update_mem_state(i);
304262
}
305263

306264
return 0;

0 commit comments

Comments
 (0)