diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-07-26 11:48:49 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-26 11:48:49 -0400 |
commit | c3cc99ff5d24e2eeaf7ec2032e720681916990e3 (patch) | |
tree | c3e74171bbbd2adde9d60b9db1c440415c8d2831 /fs/binfmt_elf.c | |
parent | 38ffbe66d59051fd9cfcfc8545f164700e2fa3bc (diff) | |
parent | 024e8ac04453b3525448c31ef39848cf675ba6db (diff) |
Merge branch 'linus' into x86/xen
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r-- | fs/binfmt_elf.c | 99 |
1 files changed, 60 insertions, 39 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 639d2d8b5710..3b6ff854d983 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 */ |
@@ -209,6 +233,10 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | |||
209 | NEW_AUX_ENT(AT_PLATFORM, | 233 | NEW_AUX_ENT(AT_PLATFORM, |
210 | (elf_addr_t)(unsigned long)u_platform); | 234 | (elf_addr_t)(unsigned long)u_platform); |
211 | } | 235 | } |
236 | if (k_base_platform) { | ||
237 | NEW_AUX_ENT(AT_BASE_PLATFORM, | ||
238 | (elf_addr_t)(unsigned long)u_base_platform); | ||
239 | } | ||
212 | if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) { | 240 | if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) { |
213 | NEW_AUX_ENT(AT_EXECFD, bprm->interp_data); | 241 | NEW_AUX_ENT(AT_EXECFD, bprm->interp_data); |
214 | } | 242 | } |
@@ -1478,7 +1506,7 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, | |||
1478 | const struct user_regset_view *view = task_user_regset_view(dump_task); | 1506 | const struct user_regset_view *view = task_user_regset_view(dump_task); |
1479 | struct elf_thread_core_info *t; | 1507 | struct elf_thread_core_info *t; |
1480 | struct elf_prpsinfo *psinfo; | 1508 | struct elf_prpsinfo *psinfo; |
1481 | struct task_struct *g, *p; | 1509 | struct core_thread *ct; |
1482 | unsigned int i; | 1510 | unsigned int i; |
1483 | 1511 | ||
1484 | info->size = 0; | 1512 | info->size = 0; |
@@ -1517,31 +1545,26 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, | |||
1517 | /* | 1545 | /* |
1518 | * Allocate a structure for each thread. | 1546 | * Allocate a structure for each thread. |
1519 | */ | 1547 | */ |
1520 | rcu_read_lock(); | 1548 | for (ct = &dump_task->mm->core_state->dumper; ct; ct = ct->next) { |
1521 | do_each_thread(g, p) | 1549 | t = kzalloc(offsetof(struct elf_thread_core_info, |
1522 | if (p->mm == dump_task->mm) { | 1550 | notes[info->thread_notes]), |
1523 | t = kzalloc(offsetof(struct elf_thread_core_info, | 1551 | GFP_KERNEL); |
1524 | notes[info->thread_notes]), | 1552 | if (unlikely(!t)) |
1525 | GFP_ATOMIC); | 1553 | return 0; |
1526 | if (unlikely(!t)) { | 1554 | |
1527 | rcu_read_unlock(); | 1555 | t->task = ct->task; |
1528 | return 0; | 1556 | if (ct->task == dump_task || !info->thread) { |
1529 | } | 1557 | t->next = info->thread; |
1530 | t->task = p; | 1558 | info->thread = t; |
1531 | if (p == dump_task || !info->thread) { | 1559 | } else { |
1532 | t->next = info->thread; | 1560 | /* |
1533 | info->thread = t; | 1561 | * Make sure to keep the original task at |
1534 | } else { | 1562 | * the head of the list. |
1535 | /* | 1563 | */ |
1536 | * Make sure to keep the original task at | 1564 | t->next = info->thread->next; |
1537 | * the head of the list. | 1565 | info->thread->next = t; |
1538 | */ | ||
1539 | t->next = info->thread->next; | ||
1540 | info->thread->next = t; | ||
1541 | } | ||
1542 | } | 1566 | } |
1543 | while_each_thread(g, p); | 1567 | } |
1544 | rcu_read_unlock(); | ||
1545 | 1568 | ||
1546 | /* | 1569 | /* |
1547 | * Now fill in each thread's information. | 1570 | * Now fill in each thread's information. |
@@ -1688,7 +1711,6 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, | |||
1688 | { | 1711 | { |
1689 | #define NUM_NOTES 6 | 1712 | #define NUM_NOTES 6 |
1690 | struct list_head *t; | 1713 | struct list_head *t; |
1691 | struct task_struct *g, *p; | ||
1692 | 1714 | ||
1693 | info->notes = NULL; | 1715 | info->notes = NULL; |
1694 | info->prstatus = NULL; | 1716 | info->prstatus = NULL; |
@@ -1720,20 +1742,19 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, | |||
1720 | 1742 | ||
1721 | info->thread_status_size = 0; | 1743 | info->thread_status_size = 0; |
1722 | if (signr) { | 1744 | if (signr) { |
1745 | struct core_thread *ct; | ||
1723 | struct elf_thread_status *ets; | 1746 | struct elf_thread_status *ets; |
1724 | rcu_read_lock(); | 1747 | |
1725 | do_each_thread(g, p) | 1748 | for (ct = current->mm->core_state->dumper.next; |
1726 | if (current->mm == p->mm && current != p) { | 1749 | ct; ct = ct->next) { |
1727 | ets = kzalloc(sizeof(*ets), GFP_ATOMIC); | 1750 | ets = kzalloc(sizeof(*ets), GFP_KERNEL); |
1728 | if (!ets) { | 1751 | if (!ets) |
1729 | rcu_read_unlock(); | 1752 | return 0; |
1730 | return 0; | 1753 | |
1731 | } | 1754 | ets->thread = ct->task; |
1732 | ets->thread = p; | 1755 | list_add(&ets->list, &info->thread_list); |
1733 | list_add(&ets->list, &info->thread_list); | 1756 | } |
1734 | } | 1757 | |
1735 | while_each_thread(g, p); | ||
1736 | rcu_read_unlock(); | ||
1737 | list_for_each(t, &info->thread_list) { | 1758 | list_for_each(t, &info->thread_list) { |
1738 | int sz; | 1759 | int sz; |
1739 | 1760 | ||