diff options
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r-- | fs/binfmt_elf.c | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 8fcfa398d350..e3ff2b9e602f 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -152,12 +152,14 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | |||
152 | elf_addr_t __user *sp; | 152 | elf_addr_t __user *sp; |
153 | elf_addr_t __user *u_platform; | 153 | elf_addr_t __user *u_platform; |
154 | elf_addr_t __user *u_base_platform; | 154 | elf_addr_t __user *u_base_platform; |
155 | elf_addr_t __user *u_rand_bytes; | ||
155 | const char *k_platform = ELF_PLATFORM; | 156 | const char *k_platform = ELF_PLATFORM; |
156 | const char *k_base_platform = ELF_BASE_PLATFORM; | 157 | const char *k_base_platform = ELF_BASE_PLATFORM; |
158 | unsigned char k_rand_bytes[16]; | ||
157 | int items; | 159 | int items; |
158 | elf_addr_t *elf_info; | 160 | elf_addr_t *elf_info; |
159 | int ei_index = 0; | 161 | int ei_index = 0; |
160 | struct task_struct *tsk = current; | 162 | const struct cred *cred = current_cred(); |
161 | struct vm_area_struct *vma; | 163 | struct vm_area_struct *vma; |
162 | 164 | ||
163 | /* | 165 | /* |
@@ -196,6 +198,15 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | |||
196 | return -EFAULT; | 198 | return -EFAULT; |
197 | } | 199 | } |
198 | 200 | ||
201 | /* | ||
202 | * Generate 16 random bytes for userspace PRNG seeding. | ||
203 | */ | ||
204 | get_random_bytes(k_rand_bytes, sizeof(k_rand_bytes)); | ||
205 | u_rand_bytes = (elf_addr_t __user *) | ||
206 | STACK_ALLOC(p, sizeof(k_rand_bytes)); | ||
207 | if (__copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes))) | ||
208 | return -EFAULT; | ||
209 | |||
199 | /* Create the ELF interpreter info */ | 210 | /* Create the ELF interpreter info */ |
200 | elf_info = (elf_addr_t *)current->mm->saved_auxv; | 211 | elf_info = (elf_addr_t *)current->mm->saved_auxv; |
201 | /* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */ | 212 | /* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */ |
@@ -223,11 +234,12 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | |||
223 | NEW_AUX_ENT(AT_BASE, interp_load_addr); | 234 | NEW_AUX_ENT(AT_BASE, interp_load_addr); |
224 | NEW_AUX_ENT(AT_FLAGS, 0); | 235 | NEW_AUX_ENT(AT_FLAGS, 0); |
225 | NEW_AUX_ENT(AT_ENTRY, exec->e_entry); | 236 | NEW_AUX_ENT(AT_ENTRY, exec->e_entry); |
226 | NEW_AUX_ENT(AT_UID, tsk->uid); | 237 | NEW_AUX_ENT(AT_UID, cred->uid); |
227 | NEW_AUX_ENT(AT_EUID, tsk->euid); | 238 | NEW_AUX_ENT(AT_EUID, cred->euid); |
228 | NEW_AUX_ENT(AT_GID, tsk->gid); | 239 | NEW_AUX_ENT(AT_GID, cred->gid); |
229 | NEW_AUX_ENT(AT_EGID, tsk->egid); | 240 | NEW_AUX_ENT(AT_EGID, cred->egid); |
230 | NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm)); | 241 | NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm)); |
242 | NEW_AUX_ENT(AT_RANDOM, (elf_addr_t)(unsigned long)u_rand_bytes); | ||
231 | NEW_AUX_ENT(AT_EXECFN, bprm->exec); | 243 | NEW_AUX_ENT(AT_EXECFN, bprm->exec); |
232 | if (k_platform) { | 244 | if (k_platform) { |
233 | NEW_AUX_ENT(AT_PLATFORM, | 245 | NEW_AUX_ENT(AT_PLATFORM, |
@@ -949,14 +961,14 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
949 | set_binfmt(&elf_format); | 961 | set_binfmt(&elf_format); |
950 | 962 | ||
951 | #ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES | 963 | #ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES |
952 | retval = arch_setup_additional_pages(bprm, executable_stack); | 964 | retval = arch_setup_additional_pages(bprm, !!elf_interpreter); |
953 | if (retval < 0) { | 965 | if (retval < 0) { |
954 | send_sig(SIGKILL, current, 0); | 966 | send_sig(SIGKILL, current, 0); |
955 | goto out; | 967 | goto out; |
956 | } | 968 | } |
957 | #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ | 969 | #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ |
958 | 970 | ||
959 | compute_creds(bprm); | 971 | install_exec_creds(bprm); |
960 | current->flags &= ~PF_FORKNOEXEC; | 972 | current->flags &= ~PF_FORKNOEXEC; |
961 | retval = create_elf_tables(bprm, &loc->elf_ex, | 973 | retval = create_elf_tables(bprm, &loc->elf_ex, |
962 | load_addr, interp_load_addr); | 974 | load_addr, interp_load_addr); |
@@ -1361,6 +1373,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus, | |||
1361 | static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, | 1373 | static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, |
1362 | struct mm_struct *mm) | 1374 | struct mm_struct *mm) |
1363 | { | 1375 | { |
1376 | const struct cred *cred; | ||
1364 | unsigned int i, len; | 1377 | unsigned int i, len; |
1365 | 1378 | ||
1366 | /* first copy the parameters from user space */ | 1379 | /* first copy the parameters from user space */ |
@@ -1388,8 +1401,11 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, | |||
1388 | psinfo->pr_zomb = psinfo->pr_sname == 'Z'; | 1401 | psinfo->pr_zomb = psinfo->pr_sname == 'Z'; |
1389 | psinfo->pr_nice = task_nice(p); | 1402 | psinfo->pr_nice = task_nice(p); |
1390 | psinfo->pr_flag = p->flags; | 1403 | psinfo->pr_flag = p->flags; |
1391 | SET_UID(psinfo->pr_uid, p->uid); | 1404 | rcu_read_lock(); |
1392 | SET_GID(psinfo->pr_gid, p->gid); | 1405 | cred = __task_cred(p); |
1406 | SET_UID(psinfo->pr_uid, cred->uid); | ||
1407 | SET_GID(psinfo->pr_gid, cred->gid); | ||
1408 | rcu_read_unlock(); | ||
1393 | strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname)); | 1409 | strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname)); |
1394 | 1410 | ||
1395 | return 0; | 1411 | return 0; |