diff options
| author | Ingo Molnar <mingo@elte.hu> | 2008-08-14 06:19:59 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-08-14 06:19:59 -0400 |
| commit | 8d7ccaa545490cdffdfaff0842436a8dd85cf47b (patch) | |
| tree | 8129b5907161bc6ae26deb3645ce1e280c5e1f51 /fs/binfmt_elf.c | |
| parent | b2139aa0eec330c711c5a279db361e5ef1178e78 (diff) | |
| parent | 30a2f3c60a84092c8084dfe788b710f8d0768cd4 (diff) | |
Merge commit 'v2.6.27-rc3' into x86/prototypes
Conflicts:
include/asm-x86/dma-mapping.h
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'fs/binfmt_elf.c')
| -rw-r--r-- | fs/binfmt_elf.c | 106 |
1 files changed, 61 insertions, 45 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index d48ff5f370f4..655ed8d30a86 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
| @@ -131,6 +131,15 @@ static int padzero(unsigned long elf_bss) | |||
| 131 | #define STACK_ALLOC(sp, len) ({ sp -= len ; sp; }) | 131 | #define STACK_ALLOC(sp, len) ({ sp -= len ; sp; }) |
| 132 | #endif | 132 | #endif |
| 133 | 133 | ||
| 134 | #ifndef ELF_BASE_PLATFORM | ||
| 135 | /* | ||
| 136 | * AT_BASE_PLATFORM indicates the "real" hardware/microarchitecture. | ||
| 137 | * If the arch defines ELF_BASE_PLATFORM (in asm/elf.h), the value | ||
| 138 | * will be copied to the user stack in the same manner as AT_PLATFORM. | ||
| 139 | */ | ||
| 140 | #define ELF_BASE_PLATFORM NULL | ||
| 141 | #endif | ||
| 142 | |||
| 134 | static int | 143 | static int |
| 135 | create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | 144 | create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, |
| 136 | unsigned long load_addr, unsigned long interp_load_addr) | 145 | unsigned long load_addr, unsigned long interp_load_addr) |
| @@ -142,7 +151,9 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | |||
| 142 | elf_addr_t __user *envp; | 151 | elf_addr_t __user *envp; |
| 143 | elf_addr_t __user *sp; | 152 | elf_addr_t __user *sp; |
| 144 | elf_addr_t __user *u_platform; | 153 | elf_addr_t __user *u_platform; |
| 154 | elf_addr_t __user *u_base_platform; | ||
| 145 | const char *k_platform = ELF_PLATFORM; | 155 | const char *k_platform = ELF_PLATFORM; |
| 156 | const char *k_base_platform = ELF_BASE_PLATFORM; | ||
| 146 | int items; | 157 | int items; |
| 147 | elf_addr_t *elf_info; | 158 | elf_addr_t *elf_info; |
| 148 | int ei_index = 0; | 159 | int ei_index = 0; |
| @@ -172,6 +183,19 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | |||
| 172 | return -EFAULT; | 183 | return -EFAULT; |
| 173 | } | 184 | } |
| 174 | 185 | ||
| 186 | /* | ||
| 187 | * If this architecture has a "base" platform capability | ||
| 188 | * string, copy it to userspace. | ||
| 189 | */ | ||
| 190 | u_base_platform = NULL; | ||
| 191 | if (k_base_platform) { | ||
| 192 | size_t len = strlen(k_base_platform) + 1; | ||
| 193 | |||
| 194 | u_base_platform = (elf_addr_t __user *)STACK_ALLOC(p, len); | ||
| 195 | if (__copy_to_user(u_base_platform, k_base_platform, len)) | ||
| 196 | return -EFAULT; | ||
| 197 | } | ||
| 198 | |||
| 175 | /* Create the ELF interpreter info */ | 199 | /* Create the ELF interpreter info */ |
| 176 | elf_info = (elf_addr_t *)current->mm->saved_auxv; | 200 | elf_info = (elf_addr_t *)current->mm->saved_auxv; |
| 177 | /* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */ | 201 | /* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */ |
| @@ -204,10 +228,15 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | |||
| 204 | NEW_AUX_ENT(AT_GID, tsk->gid); | 228 | NEW_AUX_ENT(AT_GID, tsk->gid); |
| 205 | NEW_AUX_ENT(AT_EGID, tsk->egid); | 229 | NEW_AUX_ENT(AT_EGID, tsk->egid); |
| 206 | NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm)); | 230 | NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm)); |
| 231 | NEW_AUX_ENT(AT_EXECFN, bprm->exec); | ||
| 207 | if (k_platform) { | 232 | if (k_platform) { |
| 208 | NEW_AUX_ENT(AT_PLATFORM, | 233 | NEW_AUX_ENT(AT_PLATFORM, |
| 209 | (elf_addr_t)(unsigned long)u_platform); | 234 | (elf_addr_t)(unsigned long)u_platform); |
| 210 | } | 235 | } |
| 236 | if (k_base_platform) { | ||
| 237 | NEW_AUX_ENT(AT_BASE_PLATFORM, | ||
| 238 | (elf_addr_t)(unsigned long)u_base_platform); | ||
| 239 | } | ||
| 211 | if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) { | 240 | if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) { |
| 212 | NEW_AUX_ENT(AT_EXECFD, bprm->interp_data); | 241 | NEW_AUX_ENT(AT_EXECFD, bprm->interp_data); |
| 213 | } | 242 | } |
| @@ -974,12 +1003,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
| 974 | #endif | 1003 | #endif |
| 975 | 1004 | ||
| 976 | start_thread(regs, elf_entry, bprm->p); | 1005 | start_thread(regs, elf_entry, bprm->p); |
| 977 | if (unlikely(current->ptrace & PT_PTRACED)) { | ||
| 978 | if (current->ptrace & PT_TRACE_EXEC) | ||
| 979 | ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP); | ||
| 980 | else | ||
| 981 | send_sig(SIGTRAP, current, 0); | ||
| 982 | } | ||
| 983 | retval = 0; | 1006 | retval = 0; |
| 984 | out: | 1007 | out: |
| 985 | kfree(loc); | 1008 | kfree(loc); |
| @@ -1477,7 +1500,7 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, | |||
| 1477 | const struct user_regset_view *view = task_user_regset_view(dump_task); | 1500 | const struct user_regset_view *view = task_user_regset_view(dump_task); |
| 1478 | struct elf_thread_core_info *t; | 1501 | struct elf_thread_core_info *t; |
| 1479 | struct elf_prpsinfo *psinfo; | 1502 | struct elf_prpsinfo *psinfo; |
| 1480 | struct task_struct *g, *p; | 1503 | struct core_thread *ct; |
| 1481 | unsigned int i; | 1504 | unsigned int i; |
| 1482 | 1505 | ||
| 1483 | info->size = 0; | 1506 | info->size = 0; |
| @@ -1516,31 +1539,26 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, | |||
| 1516 | /* | 1539 | /* |
| 1517 | * Allocate a structure for each thread. | 1540 | * Allocate a structure for each thread. |
| 1518 | */ | 1541 | */ |
| 1519 | rcu_read_lock(); | 1542 | for (ct = &dump_task->mm->core_state->dumper; ct; ct = ct->next) { |
| 1520 | do_each_thread(g, p) | 1543 | t = kzalloc(offsetof(struct elf_thread_core_info, |
| 1521 | if (p->mm == dump_task->mm) { | 1544 | notes[info->thread_notes]), |
| 1522 | t = kzalloc(offsetof(struct elf_thread_core_info, | 1545 | GFP_KERNEL); |
| 1523 | notes[info->thread_notes]), | 1546 | if (unlikely(!t)) |
| 1524 | GFP_ATOMIC); | 1547 | return 0; |
| 1525 | if (unlikely(!t)) { | 1548 | |
| 1526 | rcu_read_unlock(); | 1549 | t->task = ct->task; |
| 1527 | return 0; | 1550 | if (ct->task == dump_task || !info->thread) { |
| 1528 | } | 1551 | t->next = info->thread; |
| 1529 | t->task = p; | 1552 | info->thread = t; |
| 1530 | if (p == dump_task || !info->thread) { | 1553 | } else { |
| 1531 | t->next = info->thread; | 1554 | /* |
| 1532 | info->thread = t; | 1555 | * Make sure to keep the original task at |
| 1533 | } else { | 1556 | * the head of the list. |
| 1534 | /* | 1557 | */ |
| 1535 | * Make sure to keep the original task at | 1558 | t->next = info->thread->next; |
| 1536 | * the head of the list. | 1559 | info->thread->next = t; |
| 1537 | */ | ||
| 1538 | t->next = info->thread->next; | ||
| 1539 | info->thread->next = t; | ||
| 1540 | } | ||
| 1541 | } | 1560 | } |
| 1542 | while_each_thread(g, p); | 1561 | } |
| 1543 | rcu_read_unlock(); | ||
| 1544 | 1562 | ||
| 1545 | /* | 1563 | /* |
| 1546 | * Now fill in each thread's information. | 1564 | * Now fill in each thread's information. |
| @@ -1687,7 +1705,6 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, | |||
| 1687 | { | 1705 | { |
| 1688 | #define NUM_NOTES 6 | 1706 | #define NUM_NOTES 6 |
| 1689 | struct list_head *t; | 1707 | struct list_head *t; |
| 1690 | struct task_struct *g, *p; | ||
| 1691 | 1708 | ||
| 1692 | info->notes = NULL; | 1709 | info->notes = NULL; |
| 1693 | info->prstatus = NULL; | 1710 | info->prstatus = NULL; |
| @@ -1719,20 +1736,19 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, | |||
| 1719 | 1736 | ||
| 1720 | info->thread_status_size = 0; | 1737 | info->thread_status_size = 0; |
| 1721 | if (signr) { | 1738 | if (signr) { |
| 1739 | struct core_thread *ct; | ||
| 1722 | struct elf_thread_status *ets; | 1740 | struct elf_thread_status *ets; |
| 1723 | rcu_read_lock(); | 1741 | |
| 1724 | do_each_thread(g, p) | 1742 | for (ct = current->mm->core_state->dumper.next; |
| 1725 | if (current->mm == p->mm && current != p) { | 1743 | ct; ct = ct->next) { |
| 1726 | ets = kzalloc(sizeof(*ets), GFP_ATOMIC); | 1744 | ets = kzalloc(sizeof(*ets), GFP_KERNEL); |
| 1727 | if (!ets) { | 1745 | if (!ets) |
| 1728 | rcu_read_unlock(); | 1746 | return 0; |
| 1729 | return 0; | 1747 | |
| 1730 | } | 1748 | ets->thread = ct->task; |
| 1731 | ets->thread = p; | 1749 | list_add(&ets->list, &info->thread_list); |
| 1732 | list_add(&ets->list, &info->thread_list); | 1750 | } |
| 1733 | } | 1751 | |
| 1734 | while_each_thread(g, p); | ||
| 1735 | rcu_read_unlock(); | ||
| 1736 | list_for_each(t, &info->thread_list) { | 1752 | list_for_each(t, &info->thread_list) { |
| 1737 | int sz; | 1753 | int sz; |
| 1738 | 1754 | ||
