@@ -440,19 +440,18 @@ static ssize_t
440
440
read_kcore (struct file * file , char __user * buffer , size_t buflen , loff_t * fpos )
441
441
{
442
442
char * buf = file -> private_data ;
443
- ssize_t acc = 0 ;
444
443
size_t size , tsz ;
445
444
size_t elf_buflen ;
446
445
int nphdr ;
447
446
unsigned long start ;
447
+ size_t orig_buflen = buflen ;
448
+ int ret = 0 ;
448
449
449
450
down_read (& kclist_lock );
450
451
size = get_kcore_size (& nphdr , & elf_buflen );
451
452
452
- if (buflen == 0 || * fpos >= size ) {
453
- up_read (& kclist_lock );
454
- return 0 ;
455
- }
453
+ if (buflen == 0 || * fpos >= size )
454
+ goto out ;
456
455
457
456
/* trim buflen to not go beyond EOF */
458
457
if (buflen > size - * fpos )
@@ -465,28 +464,26 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
465
464
tsz = elf_buflen - * fpos ;
466
465
if (buflen < tsz )
467
466
tsz = buflen ;
468
- elf_buf = kzalloc (elf_buflen , GFP_ATOMIC );
467
+ elf_buf = kzalloc (elf_buflen , GFP_KERNEL );
469
468
if (!elf_buf ) {
470
- up_read ( & kclist_lock ) ;
471
- return - ENOMEM ;
469
+ ret = - ENOMEM ;
470
+ goto out ;
472
471
}
473
472
elf_kcore_store_hdr (elf_buf , nphdr , elf_buflen );
474
- up_read (& kclist_lock );
475
473
if (copy_to_user (buffer , elf_buf + * fpos , tsz )) {
476
474
kfree (elf_buf );
477
- return - EFAULT ;
475
+ ret = - EFAULT ;
476
+ goto out ;
478
477
}
479
478
kfree (elf_buf );
480
479
buflen -= tsz ;
481
480
* fpos += tsz ;
482
481
buffer += tsz ;
483
- acc += tsz ;
484
482
485
483
/* leave now if filled buffer already */
486
484
if (buflen == 0 )
487
- return acc ;
488
- } else
489
- up_read (& kclist_lock );
485
+ goto out ;
486
+ }
490
487
491
488
/*
492
489
* Check to see if our file offset matches with any of
@@ -499,52 +496,65 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
499
496
while (buflen ) {
500
497
struct kcore_list * m ;
501
498
502
- down_read (& kclist_lock );
503
499
list_for_each_entry (m , & kclist_head , list ) {
504
500
if (start >= m -> addr && start < (m -> addr + m -> size ))
505
501
break ;
506
502
}
507
- up_read (& kclist_lock );
508
503
509
504
if (& m -> list == & kclist_head ) {
510
- if (clear_user (buffer , tsz ))
511
- return - EFAULT ;
505
+ if (clear_user (buffer , tsz )) {
506
+ ret = - EFAULT ;
507
+ goto out ;
508
+ }
512
509
} else if (m -> type == KCORE_VMALLOC ) {
513
510
vread (buf , (char * )start , tsz );
514
511
/* we have to zero-fill user buffer even if no read */
515
- if (copy_to_user (buffer , buf , tsz ))
516
- return - EFAULT ;
512
+ if (copy_to_user (buffer , buf , tsz )) {
513
+ ret = - EFAULT ;
514
+ goto out ;
515
+ }
517
516
} else if (m -> type == KCORE_USER ) {
518
517
/* User page is handled prior to normal kernel page: */
519
- if (copy_to_user (buffer , (char * )start , tsz ))
520
- return - EFAULT ;
518
+ if (copy_to_user (buffer , (char * )start , tsz )) {
519
+ ret = - EFAULT ;
520
+ goto out ;
521
+ }
521
522
} else {
522
523
if (kern_addr_valid (start )) {
523
524
/*
524
525
* Using bounce buffer to bypass the
525
526
* hardened user copy kernel text checks.
526
527
*/
527
528
if (probe_kernel_read (buf , (void * ) start , tsz )) {
528
- if (clear_user (buffer , tsz ))
529
- return - EFAULT ;
529
+ if (clear_user (buffer , tsz )) {
530
+ ret = - EFAULT ;
531
+ goto out ;
532
+ }
530
533
} else {
531
- if (copy_to_user (buffer , buf , tsz ))
532
- return - EFAULT ;
534
+ if (copy_to_user (buffer , buf , tsz )) {
535
+ ret = - EFAULT ;
536
+ goto out ;
537
+ }
533
538
}
534
539
} else {
535
- if (clear_user (buffer , tsz ))
536
- return - EFAULT ;
540
+ if (clear_user (buffer , tsz )) {
541
+ ret = - EFAULT ;
542
+ goto out ;
543
+ }
537
544
}
538
545
}
539
546
buflen -= tsz ;
540
547
* fpos += tsz ;
541
548
buffer += tsz ;
542
- acc += tsz ;
543
549
start += tsz ;
544
550
tsz = (buflen > PAGE_SIZE ? PAGE_SIZE : buflen );
545
551
}
546
552
547
- return acc ;
553
+ out :
554
+ up_read (& kclist_lock );
555
+ if (ret )
556
+ return ret ;
557
+ return orig_buflen - buflen ;
548
558
}
549
559
550
560
0 commit comments