@@ -505,8 +505,9 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
505505 char * k_platform , * k_base_platform ;
506506 char __user * u_platform , * u_base_platform , * p ;
507507 int loop ;
508- int nr ; /* reset for each csp adjustment */
509508 unsigned long flags = 0 ;
509+ int ei_index ;
510+ elf_addr_t * elf_info ;
510511
511512#ifdef CONFIG_MMU
512513 /* In some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
@@ -601,44 +602,24 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
601602 csp -= sp & 15UL ;
602603 sp -= sp & 15UL ;
603604
604- /* put the ELF interpreter info on the stack */
605- #define NEW_AUX_ENT (id , val ) \
606- do { \
607- struct { unsigned long _id, _val; } __user *ent, v; \
608- \
609- ent = (void __user *) csp; \
610- v._id = (id); \
611- v._val = (val); \
612- if (copy_to_user(ent + nr, &v, sizeof(v))) \
613- return -EFAULT; \
614- nr++; \
605+ /* Create the ELF interpreter info */
606+ elf_info = (elf_addr_t * )mm -> saved_auxv ;
607+ /* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */
608+ #define NEW_AUX_ENT (id , val ) \
609+ do { \
610+ *elf_info++ = id; \
611+ *elf_info++ = val; \
615612 } while (0)
616613
617- nr = 0 ;
618- csp -= 2 * sizeof (unsigned long );
619- NEW_AUX_ENT (AT_NULL , 0 );
620- if (k_platform ) {
621- nr = 0 ;
622- csp -= 2 * sizeof (unsigned long );
623- NEW_AUX_ENT (AT_PLATFORM ,
624- (elf_addr_t ) (unsigned long ) u_platform );
625- }
626-
627- if (k_base_platform ) {
628- nr = 0 ;
629- csp -= 2 * sizeof (unsigned long );
630- NEW_AUX_ENT (AT_BASE_PLATFORM ,
631- (elf_addr_t ) (unsigned long ) u_base_platform );
632- }
633-
634- if (bprm -> have_execfd ) {
635- nr = 0 ;
636- csp -= 2 * sizeof (unsigned long );
637- NEW_AUX_ENT (AT_EXECFD , bprm -> execfd );
638- }
639-
640- nr = 0 ;
641- csp -= DLINFO_ITEMS * 2 * sizeof (unsigned long );
614+ #ifdef ARCH_DLINFO
615+ /*
616+ * ARCH_DLINFO must come first so PPC can do its special alignment of
617+ * AUXV.
618+ * update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT() in
619+ * ARCH_DLINFO changes
620+ */
621+ ARCH_DLINFO ;
622+ #endif
642623 NEW_AUX_ENT (AT_HWCAP , ELF_HWCAP );
643624#ifdef ELF_HWCAP2
644625 NEW_AUX_ENT (AT_HWCAP2 , ELF_HWCAP2 );
@@ -659,17 +640,29 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
659640 NEW_AUX_ENT (AT_EGID , (elf_addr_t ) from_kgid_munged (cred -> user_ns , cred -> egid ));
660641 NEW_AUX_ENT (AT_SECURE , bprm -> secureexec );
661642 NEW_AUX_ENT (AT_EXECFN , bprm -> exec );
643+ if (k_platform )
644+ NEW_AUX_ENT (AT_PLATFORM ,
645+ (elf_addr_t )(unsigned long )u_platform );
646+ if (k_base_platform )
647+ NEW_AUX_ENT (AT_BASE_PLATFORM ,
648+ (elf_addr_t )(unsigned long )u_base_platform );
649+ if (bprm -> have_execfd )
650+ NEW_AUX_ENT (AT_EXECFD , bprm -> execfd );
651+ #undef NEW_AUX_ENT
652+ /* AT_NULL is zero; clear the rest too */
653+ memset (elf_info , 0 , (char * )mm -> saved_auxv +
654+ sizeof (mm -> saved_auxv ) - (char * )elf_info );
662655
663- #ifdef ARCH_DLINFO
664- nr = 0 ;
665- csp -= AT_VECTOR_SIZE_ARCH * 2 * sizeof (unsigned long );
656+ /* And advance past the AT_NULL entry. */
657+ elf_info += 2 ;
666658
667- /* ARCH_DLINFO must come last so platform specific code can enforce
668- * special alignment requirements on the AUXV if necessary (eg. PPC).
669- */
670- ARCH_DLINFO ;
671- #endif
672- #undef NEW_AUX_ENT
659+ ei_index = elf_info - (elf_addr_t * )mm -> saved_auxv ;
660+ csp -= ei_index * sizeof (elf_addr_t );
661+
662+ /* Put the elf_info on the stack in the right place. */
663+ if (copy_to_user ((void __user * )csp , mm -> saved_auxv ,
664+ ei_index * sizeof (elf_addr_t )))
665+ return - EFAULT ;
673666
674667 /* allocate room for argv[] and envv[] */
675668 csp -= (bprm -> envc + 1 ) * sizeof (elf_caddr_t );
0 commit comments