Skip to content

Commit 10e2925

Browse files
jcmvbkbckees
authored andcommitted
binfmt_elf_fdpic: fix /proc/<pid>/auxv
Althought FDPIC linux kernel provides /proc/<pid>/auxv files they are empty because there's no code that initializes mm->saved_auxv in the FDPIC ELF loader. Synchronize FDPIC ELF aux vector setup with ELF. Replace entry-by-entry aux vector copying to userspace with initialization of mm->saved_auxv first and then copying it to userspace as a whole. Signed-off-by: Max Filippov <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Kees Cook <[email protected]>
1 parent 2a5eb99 commit 10e2925

File tree

1 file changed

+39
-46
lines changed

1 file changed

+39
-46
lines changed

fs/binfmt_elf_fdpic.c

Lines changed: 39 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)