@@ -386,6 +386,59 @@ static unsigned long total_mapping_size(struct elf_phdr *cmds, int nr)
386386 ELF_PAGESTART (cmds [first_idx ].p_vaddr );
387387}
388388
389+ /**
390+ * load_elf_phdrs() - load ELF program headers
391+ * @elf_ex: ELF header of the binary whose program headers should be loaded
392+ * @elf_file: the opened ELF binary file
393+ *
394+ * Loads ELF program headers from the binary file elf_file, which has the ELF
395+ * header pointed to by elf_ex, into a newly allocated array. The caller is
396+ * responsible for freeing the allocated data. Returns an ERR_PTR upon failure.
397+ */
398+ static struct elf_phdr * load_elf_phdrs (struct elfhdr * elf_ex ,
399+ struct file * elf_file )
400+ {
401+ struct elf_phdr * elf_phdata = NULL ;
402+ int retval , size , err = -1 ;
403+
404+ /*
405+ * If the size of this structure has changed, then punt, since
406+ * we will be doing the wrong thing.
407+ */
408+ if (elf_ex -> e_phentsize != sizeof (struct elf_phdr ))
409+ goto out ;
410+
411+ /* Sanity check the number of program headers... */
412+ if (elf_ex -> e_phnum < 1 ||
413+ elf_ex -> e_phnum > 65536U / sizeof (struct elf_phdr ))
414+ goto out ;
415+
416+ /* ...and their total size. */
417+ size = sizeof (struct elf_phdr ) * elf_ex -> e_phnum ;
418+ if (size > ELF_MIN_ALIGN )
419+ goto out ;
420+
421+ elf_phdata = kmalloc (size , GFP_KERNEL );
422+ if (!elf_phdata )
423+ goto out ;
424+
425+ /* Read in the program headers */
426+ retval = kernel_read (elf_file , elf_ex -> e_phoff ,
427+ (char * )elf_phdata , size );
428+ if (retval != size ) {
429+ err = (retval < 0 ) ? retval : - EIO ;
430+ goto out ;
431+ }
432+
433+ /* Success! */
434+ err = 0 ;
435+ out :
436+ if (err ) {
437+ kfree (elf_phdata );
438+ elf_phdata = NULL ;
439+ }
440+ return elf_phdata ;
441+ }
389442
390443/* This is much more generalized than the library routine read function,
391444 so we keep this separate. Technically the library read function
@@ -403,7 +456,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
403456 unsigned long last_bss = 0 , elf_bss = 0 ;
404457 unsigned long error = ~0UL ;
405458 unsigned long total_size ;
406- int retval , i , size ;
459+ int i ;
407460
408461 /* First of all, some simple consistency checks */
409462 if (interp_elf_ex -> e_type != ET_EXEC &&
@@ -414,33 +467,10 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
414467 if (!interpreter -> f_op -> mmap )
415468 goto out ;
416469
417- /*
418- * If the size of this structure has changed, then punt, since
419- * we will be doing the wrong thing.
420- */
421- if (interp_elf_ex -> e_phentsize != sizeof (struct elf_phdr ))
422- goto out ;
423- if (interp_elf_ex -> e_phnum < 1 ||
424- interp_elf_ex -> e_phnum > 65536U / sizeof (struct elf_phdr ))
425- goto out ;
426-
427- /* Now read in all of the header information */
428- size = sizeof (struct elf_phdr ) * interp_elf_ex -> e_phnum ;
429- if (size > ELF_MIN_ALIGN )
430- goto out ;
431- elf_phdata = kmalloc (size , GFP_KERNEL );
470+ elf_phdata = load_elf_phdrs (interp_elf_ex , interpreter );
432471 if (!elf_phdata )
433472 goto out ;
434473
435- retval = kernel_read (interpreter , interp_elf_ex -> e_phoff ,
436- (char * )elf_phdata , size );
437- error = - EIO ;
438- if (retval != size ) {
439- if (retval < 0 )
440- error = retval ;
441- goto out_close ;
442- }
443-
444474 total_size = total_mapping_size (elf_phdata , interp_elf_ex -> e_phnum );
445475 if (!total_size ) {
446476 error = - EINVAL ;
@@ -578,7 +608,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
578608 struct elf_phdr * elf_ppnt , * elf_phdata ;
579609 unsigned long elf_bss , elf_brk ;
580610 int retval , i ;
581- unsigned int size ;
582611 unsigned long elf_entry ;
583612 unsigned long interp_load_addr = 0 ;
584613 unsigned long start_code , end_code , start_data , end_data ;
@@ -611,26 +640,10 @@ static int load_elf_binary(struct linux_binprm *bprm)
611640 if (!bprm -> file -> f_op -> mmap )
612641 goto out ;
613642
614- /* Now read in all of the header information */
615- if (loc -> elf_ex .e_phentsize != sizeof (struct elf_phdr ))
616- goto out ;
617- if (loc -> elf_ex .e_phnum < 1 ||
618- loc -> elf_ex .e_phnum > 65536U / sizeof (struct elf_phdr ))
619- goto out ;
620- size = loc -> elf_ex .e_phnum * sizeof (struct elf_phdr );
621- retval = - ENOMEM ;
622- elf_phdata = kmalloc (size , GFP_KERNEL );
643+ elf_phdata = load_elf_phdrs (& loc -> elf_ex , bprm -> file );
623644 if (!elf_phdata )
624645 goto out ;
625646
626- retval = kernel_read (bprm -> file , loc -> elf_ex .e_phoff ,
627- (char * )elf_phdata , size );
628- if (retval != size ) {
629- if (retval >= 0 )
630- retval = - EIO ;
631- goto out_free_ph ;
632- }
633-
634647 elf_ppnt = elf_phdata ;
635648 elf_bss = 0 ;
636649 elf_brk = 0 ;
0 commit comments