diff options
Diffstat (limited to 'fs/binfmt_elf_fdpic.c')
-rw-r--r-- | fs/binfmt_elf_fdpic.c | 85 |
1 files changed, 62 insertions, 23 deletions
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 80c1f952ef78..0e8367c54624 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/fcntl.h> | 25 | #include <linux/fcntl.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/pagemap.h> | 27 | #include <linux/pagemap.h> |
28 | #include <linux/security.h> | ||
28 | #include <linux/highmem.h> | 29 | #include <linux/highmem.h> |
29 | #include <linux/highuid.h> | 30 | #include <linux/highuid.h> |
30 | #include <linux/personality.h> | 31 | #include <linux/personality.h> |
@@ -455,8 +456,19 @@ error_kill: | |||
455 | } | 456 | } |
456 | 457 | ||
457 | /*****************************************************************************/ | 458 | /*****************************************************************************/ |
459 | |||
460 | #ifndef ELF_BASE_PLATFORM | ||
458 | /* | 461 | /* |
459 | * present useful information to the program | 462 | * AT_BASE_PLATFORM indicates the "real" hardware/microarchitecture. |
463 | * If the arch defines ELF_BASE_PLATFORM (in asm/elf.h), the value | ||
464 | * will be copied to the user stack in the same manner as AT_PLATFORM. | ||
465 | */ | ||
466 | #define ELF_BASE_PLATFORM NULL | ||
467 | #endif | ||
468 | |||
469 | /* | ||
470 | * present useful information to the program by shovelling it onto the new | ||
471 | * process's stack | ||
460 | */ | 472 | */ |
461 | static int create_elf_fdpic_tables(struct linux_binprm *bprm, | 473 | static int create_elf_fdpic_tables(struct linux_binprm *bprm, |
462 | struct mm_struct *mm, | 474 | struct mm_struct *mm, |
@@ -466,15 +478,19 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, | |||
466 | unsigned long sp, csp, nitems; | 478 | unsigned long sp, csp, nitems; |
467 | elf_caddr_t __user *argv, *envp; | 479 | elf_caddr_t __user *argv, *envp; |
468 | size_t platform_len = 0, len; | 480 | size_t platform_len = 0, len; |
469 | char *k_platform; | 481 | char *k_platform, *k_base_platform; |
470 | char __user *u_platform, *p; | 482 | char __user *u_platform, *u_base_platform, *p; |
471 | long hwcap; | 483 | long hwcap; |
472 | int loop; | 484 | int loop; |
473 | int nr; /* reset for each csp adjustment */ | 485 | int nr; /* reset for each csp adjustment */ |
474 | 486 | ||
475 | /* we're going to shovel a whole load of stuff onto the stack */ | ||
476 | #ifdef CONFIG_MMU | 487 | #ifdef CONFIG_MMU |
477 | sp = bprm->p; | 488 | /* In some cases (e.g. Hyper-Threading), we want to avoid L1 evictions |
489 | * by the processes running on the same package. One thing we can do is | ||
490 | * to shuffle the initial stack for them, so we give the architecture | ||
491 | * an opportunity to do so here. | ||
492 | */ | ||
493 | sp = arch_align_stack(bprm->p); | ||
478 | #else | 494 | #else |
479 | sp = mm->start_stack; | 495 | sp = mm->start_stack; |
480 | 496 | ||
@@ -483,11 +499,14 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, | |||
483 | return -EFAULT; | 499 | return -EFAULT; |
484 | #endif | 500 | #endif |
485 | 501 | ||
486 | /* get hold of platform and hardware capabilities masks for the machine | ||
487 | * we are running on. In some cases (Sparc), this info is impossible | ||
488 | * to get, in others (i386) it is merely difficult. | ||
489 | */ | ||
490 | hwcap = ELF_HWCAP; | 502 | hwcap = ELF_HWCAP; |
503 | |||
504 | /* | ||
505 | * If this architecture has a platform capability string, copy it | ||
506 | * to userspace. In some cases (Sparc), this info is impossible | ||
507 | * for userspace to get any other way, in others (i386) it is | ||
508 | * merely difficult. | ||
509 | */ | ||
491 | k_platform = ELF_PLATFORM; | 510 | k_platform = ELF_PLATFORM; |
492 | u_platform = NULL; | 511 | u_platform = NULL; |
493 | 512 | ||
@@ -499,19 +518,20 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, | |||
499 | return -EFAULT; | 518 | return -EFAULT; |
500 | } | 519 | } |
501 | 520 | ||
502 | #if defined(__i386__) && defined(CONFIG_SMP) | 521 | /* |
503 | /* in some cases (e.g. Hyper-Threading), we want to avoid L1 evictions | 522 | * If this architecture has a "base" platform capability |
504 | * by the processes running on the same package. One thing we can do is | 523 | * string, copy it to userspace. |
505 | * to shuffle the initial stack for them. | ||
506 | * | ||
507 | * the conditionals here are unneeded, but kept in to make the code | ||
508 | * behaviour the same as pre change unless we have hyperthreaded | ||
509 | * processors. This keeps Mr Marcelo Person happier but should be | ||
510 | * removed for 2.5 | ||
511 | */ | 524 | */ |
512 | if (smp_num_siblings > 1) | 525 | k_base_platform = ELF_BASE_PLATFORM; |
513 | sp = sp - ((current->pid % 64) << 7); | 526 | u_base_platform = NULL; |
514 | #endif | 527 | |
528 | if (k_base_platform) { | ||
529 | platform_len = strlen(k_base_platform) + 1; | ||
530 | sp -= platform_len; | ||
531 | u_base_platform = (char __user *) sp; | ||
532 | if (__copy_to_user(u_base_platform, k_base_platform, platform_len) != 0) | ||
533 | return -EFAULT; | ||
534 | } | ||
515 | 535 | ||
516 | sp &= ~7UL; | 536 | sp &= ~7UL; |
517 | 537 | ||
@@ -541,9 +561,13 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, | |||
541 | } | 561 | } |
542 | 562 | ||
543 | /* force 16 byte _final_ alignment here for generality */ | 563 | /* force 16 byte _final_ alignment here for generality */ |
544 | #define DLINFO_ITEMS 13 | 564 | #define DLINFO_ITEMS 15 |
565 | |||
566 | nitems = 1 + DLINFO_ITEMS + (k_platform ? 1 : 0) + | ||
567 | (k_base_platform ? 1 : 0) + AT_VECTOR_SIZE_ARCH; | ||
545 | 568 | ||
546 | nitems = 1 + DLINFO_ITEMS + (k_platform ? 1 : 0) + AT_VECTOR_SIZE_ARCH; | 569 | if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) |
570 | nitems++; | ||
547 | 571 | ||
548 | csp = sp; | 572 | csp = sp; |
549 | sp -= nitems * 2 * sizeof(unsigned long); | 573 | sp -= nitems * 2 * sizeof(unsigned long); |
@@ -575,6 +599,19 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, | |||
575 | (elf_addr_t) (unsigned long) u_platform); | 599 | (elf_addr_t) (unsigned long) u_platform); |
576 | } | 600 | } |
577 | 601 | ||
602 | if (k_base_platform) { | ||
603 | nr = 0; | ||
604 | csp -= 2 * sizeof(unsigned long); | ||
605 | NEW_AUX_ENT(AT_BASE_PLATFORM, | ||
606 | (elf_addr_t) (unsigned long) u_base_platform); | ||
607 | } | ||
608 | |||
609 | if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) { | ||
610 | nr = 0; | ||
611 | csp -= 2 * sizeof(unsigned long); | ||
612 | NEW_AUX_ENT(AT_EXECFD, bprm->interp_data); | ||
613 | } | ||
614 | |||
578 | nr = 0; | 615 | nr = 0; |
579 | csp -= DLINFO_ITEMS * 2 * sizeof(unsigned long); | 616 | csp -= DLINFO_ITEMS * 2 * sizeof(unsigned long); |
580 | NEW_AUX_ENT(AT_HWCAP, hwcap); | 617 | NEW_AUX_ENT(AT_HWCAP, hwcap); |
@@ -590,6 +627,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, | |||
590 | NEW_AUX_ENT(AT_EUID, (elf_addr_t) current->euid); | 627 | NEW_AUX_ENT(AT_EUID, (elf_addr_t) current->euid); |
591 | NEW_AUX_ENT(AT_GID, (elf_addr_t) current->gid); | 628 | NEW_AUX_ENT(AT_GID, (elf_addr_t) current->gid); |
592 | NEW_AUX_ENT(AT_EGID, (elf_addr_t) current->egid); | 629 | NEW_AUX_ENT(AT_EGID, (elf_addr_t) current->egid); |
630 | NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm)); | ||
631 | NEW_AUX_ENT(AT_EXECFN, bprm->exec); | ||
593 | 632 | ||
594 | #ifdef ARCH_DLINFO | 633 | #ifdef ARCH_DLINFO |
595 | nr = 0; | 634 | nr = 0; |