@@ -464,7 +464,17 @@ static bool dump_interrupted(void)
464
464
* but then we need to teach dump_write() to restart and clear
465
465
* TIF_SIGPENDING.
466
466
*/
467
- return fatal_signal_pending (current ) || freezing (current );
467
+ if (fatal_signal_pending (current )) {
468
+ coredump_report_failure ("interrupted: fatal signal pending" );
469
+ return true;
470
+ }
471
+
472
+ if (freezing (current )) {
473
+ coredump_report_failure ("interrupted: freezing" );
474
+ return true;
475
+ }
476
+
477
+ return false;
468
478
}
469
479
470
480
static void wait_for_dump_helpers (struct file * file )
@@ -519,15 +529,15 @@ static int umh_pipe_setup(struct subprocess_info *info, struct cred *new)
519
529
return err ;
520
530
}
521
531
522
- void do_coredump (const kernel_siginfo_t * siginfo )
532
+ int do_coredump (const kernel_siginfo_t * siginfo )
523
533
{
524
534
struct core_state core_state ;
525
535
struct core_name cn ;
526
536
struct mm_struct * mm = current -> mm ;
527
537
struct linux_binfmt * binfmt ;
528
538
const struct cred * old_cred ;
529
539
struct cred * cred ;
530
- int retval = 0 ;
540
+ int retval ;
531
541
int ispipe ;
532
542
size_t * argv = NULL ;
533
543
int argc = 0 ;
@@ -551,14 +561,20 @@ void do_coredump(const kernel_siginfo_t *siginfo)
551
561
audit_core_dumps (siginfo -> si_signo );
552
562
553
563
binfmt = mm -> binfmt ;
554
- if (!binfmt || !binfmt -> core_dump )
564
+ if (!binfmt || !binfmt -> core_dump ) {
565
+ retval = - ENOEXEC ;
555
566
goto fail ;
556
- if (!__get_dumpable (cprm .mm_flags ))
567
+ }
568
+ if (!__get_dumpable (cprm .mm_flags )) {
569
+ retval = - EACCES ;
557
570
goto fail ;
571
+ }
558
572
559
573
cred = prepare_creds ();
560
- if (!cred )
574
+ if (!cred ) {
575
+ retval = - EPERM ;
561
576
goto fail ;
577
+ }
562
578
/*
563
579
* We cannot trust fsuid as being the "true" uid of the process
564
580
* nor do we know its entire history. We only know it was tainted
@@ -587,6 +603,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
587
603
588
604
if (ispipe < 0 ) {
589
605
coredump_report_failure ("format_corename failed, aborting core" );
606
+ retval = ispipe ;
590
607
goto fail_unlock ;
591
608
}
592
609
@@ -607,20 +624,23 @@ void do_coredump(const kernel_siginfo_t *siginfo)
607
624
* core_pattern process dies.
608
625
*/
609
626
coredump_report_failure ("RLIMIT_CORE is set to 1, aborting core" );
627
+ retval = - EPERM ;
610
628
goto fail_unlock ;
611
629
}
612
630
cprm .limit = RLIM_INFINITY ;
613
631
614
632
dump_count = atomic_inc_return (& core_dump_count );
615
633
if (core_pipe_limit && (core_pipe_limit < dump_count )) {
616
634
coredump_report_failure ("over core_pipe_limit, skipping core dump" );
635
+ retval = - E2BIG ;
617
636
goto fail_dropcount ;
618
637
}
619
638
620
639
helper_argv = kmalloc_array (argc + 1 , sizeof (* helper_argv ),
621
640
GFP_KERNEL );
622
641
if (!helper_argv ) {
623
642
coredump_report_failure ("%s failed to allocate memory" , __func__ );
643
+ retval = - ENOMEM ;
624
644
goto fail_dropcount ;
625
645
}
626
646
for (argi = 0 ; argi < argc ; argi ++ )
@@ -646,12 +666,16 @@ void do_coredump(const kernel_siginfo_t *siginfo)
646
666
int open_flags = O_CREAT | O_WRONLY | O_NOFOLLOW |
647
667
O_LARGEFILE | O_EXCL ;
648
668
649
- if (cprm .limit < binfmt -> min_coredump )
669
+ if (cprm .limit < binfmt -> min_coredump ) {
670
+ coredump_report_failure ("over coredump resource limit, skipping core dump" );
671
+ retval = - E2BIG ;
650
672
goto fail_unlock ;
673
+ }
651
674
652
675
if (need_suid_safe && cn .corename [0 ] != '/' ) {
653
676
coredump_report_failure (
654
677
"this process can only dump core to a fully qualified path, skipping core dump" );
678
+ retval = - EPERM ;
655
679
goto fail_unlock ;
656
680
}
657
681
@@ -697,20 +721,28 @@ void do_coredump(const kernel_siginfo_t *siginfo)
697
721
} else {
698
722
cprm .file = filp_open (cn .corename , open_flags , 0600 );
699
723
}
700
- if (IS_ERR (cprm .file ))
724
+ if (IS_ERR (cprm .file )) {
725
+ retval = PTR_ERR (cprm .file );
701
726
goto fail_unlock ;
727
+ }
702
728
703
729
inode = file_inode (cprm .file );
704
- if (inode -> i_nlink > 1 )
730
+ if (inode -> i_nlink > 1 ) {
731
+ retval = - EMLINK ;
705
732
goto close_fail ;
706
- if (d_unhashed (cprm .file -> f_path .dentry ))
733
+ }
734
+ if (d_unhashed (cprm .file -> f_path .dentry )) {
735
+ retval = - EEXIST ;
707
736
goto close_fail ;
737
+ }
708
738
/*
709
739
* AK: actually i see no reason to not allow this for named
710
740
* pipes etc, but keep the previous behaviour for now.
711
741
*/
712
- if (!S_ISREG (inode -> i_mode ))
742
+ if (!S_ISREG (inode -> i_mode )) {
743
+ retval = - EISDIR ;
713
744
goto close_fail ;
745
+ }
714
746
/*
715
747
* Don't dump core if the filesystem changed owner or mode
716
748
* of the file during file creation. This is an issue when
@@ -722,17 +754,22 @@ void do_coredump(const kernel_siginfo_t *siginfo)
722
754
current_fsuid ())) {
723
755
coredump_report_failure ("Core dump to %s aborted: "
724
756
"cannot preserve file owner" , cn .corename );
757
+ retval = - EPERM ;
725
758
goto close_fail ;
726
759
}
727
760
if ((inode -> i_mode & 0677 ) != 0600 ) {
728
761
coredump_report_failure ("Core dump to %s aborted: "
729
762
"cannot preserve file permissions" , cn .corename );
763
+ retval = - EPERM ;
730
764
goto close_fail ;
731
765
}
732
- if (!(cprm .file -> f_mode & FMODE_CAN_WRITE ))
766
+ if (!(cprm .file -> f_mode & FMODE_CAN_WRITE )) {
767
+ retval = - EACCES ;
733
768
goto close_fail ;
734
- if (do_truncate (idmap , cprm .file -> f_path .dentry ,
735
- 0 , 0 , cprm .file ))
769
+ }
770
+ retval = do_truncate (idmap , cprm .file -> f_path .dentry ,
771
+ 0 , 0 , cprm .file );
772
+ if (retval )
736
773
goto close_fail ;
737
774
}
738
775
@@ -748,10 +785,15 @@ void do_coredump(const kernel_siginfo_t *siginfo)
748
785
*/
749
786
if (!cprm .file ) {
750
787
coredump_report_failure ("Core dump to |%s disabled" , cn .corename );
788
+ retval = - EPERM ;
751
789
goto close_fail ;
752
790
}
753
- if (!dump_vma_snapshot (& cprm ))
791
+ if (!dump_vma_snapshot (& cprm )) {
792
+ coredump_report_failure ("Can't get VMA snapshot for core dump |%s" ,
793
+ cn .corename );
794
+ retval = - EACCES ;
754
795
goto close_fail ;
796
+ }
755
797
756
798
file_start_write (cprm .file );
757
799
core_dumped = binfmt -> core_dump (& cprm );
@@ -767,9 +809,21 @@ void do_coredump(const kernel_siginfo_t *siginfo)
767
809
}
768
810
file_end_write (cprm .file );
769
811
free_vma_snapshot (& cprm );
812
+ } else {
813
+ coredump_report_failure ("Core dump to %s%s has been interrupted" ,
814
+ ispipe ? "|" : "" , cn .corename );
815
+ retval = - EAGAIN ;
816
+ goto fail ;
770
817
}
818
+ coredump_report (
819
+ "written to %s%s: VMAs: %d, size %zu; core: %lld bytes, pos %lld" ,
820
+ ispipe ? "|" : "" , cn .corename ,
821
+ cprm .vma_count , cprm .vma_data_size , cprm .written , cprm .pos );
771
822
if (ispipe && core_pipe_limit )
772
823
wait_for_dump_helpers (cprm .file );
824
+
825
+ retval = 0 ;
826
+
773
827
close_fail :
774
828
if (cprm .file )
775
829
filp_close (cprm .file , NULL );
@@ -784,7 +838,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
784
838
fail_creds :
785
839
put_cred (cred );
786
840
fail :
787
- return ;
841
+ return retval ;
788
842
}
789
843
790
844
/*
@@ -804,8 +858,16 @@ static int __dump_emit(struct coredump_params *cprm, const void *addr, int nr)
804
858
if (dump_interrupted ())
805
859
return 0 ;
806
860
n = __kernel_write (file , addr , nr , & pos );
807
- if (n != nr )
861
+ if (n != nr ) {
862
+ if (n < 0 )
863
+ coredump_report_failure ("failed when writing out, error %zd" , n );
864
+ else
865
+ coredump_report_failure (
866
+ "partially written out, only %zd(of %d) bytes written" ,
867
+ n , nr );
868
+
808
869
return 0 ;
870
+ }
809
871
file -> f_pos = pos ;
810
872
cprm -> written += n ;
811
873
cprm -> pos += n ;
@@ -818,9 +880,16 @@ static int __dump_skip(struct coredump_params *cprm, size_t nr)
818
880
static char zeroes [PAGE_SIZE ];
819
881
struct file * file = cprm -> file ;
820
882
if (file -> f_mode & FMODE_LSEEK ) {
821
- if (dump_interrupted () ||
822
- vfs_llseek (file , nr , SEEK_CUR ) < 0 )
883
+ int ret ;
884
+
885
+ if (dump_interrupted ())
823
886
return 0 ;
887
+
888
+ ret = vfs_llseek (file , nr , SEEK_CUR );
889
+ if (ret < 0 ) {
890
+ coredump_report_failure ("failed when seeking, error %d" , ret );
891
+ return 0 ;
892
+ }
824
893
cprm -> pos += nr ;
825
894
return 1 ;
826
895
} else {
0 commit comments