diff options
Diffstat (limited to 'fs/exec.c')
| -rw-r--r-- | fs/exec.c | 78 |
1 files changed, 21 insertions, 57 deletions
| @@ -51,17 +51,13 @@ | |||
| 51 | #include <linux/audit.h> | 51 | #include <linux/audit.h> |
| 52 | #include <linux/tracehook.h> | 52 | #include <linux/tracehook.h> |
| 53 | #include <linux/kmod.h> | 53 | #include <linux/kmod.h> |
| 54 | #include <linux/fsnotify.h> | ||
| 54 | 55 | ||
| 55 | #include <asm/uaccess.h> | 56 | #include <asm/uaccess.h> |
| 56 | #include <asm/mmu_context.h> | 57 | #include <asm/mmu_context.h> |
| 57 | #include <asm/tlb.h> | 58 | #include <asm/tlb.h> |
| 58 | #include "internal.h" | 59 | #include "internal.h" |
| 59 | 60 | ||
| 60 | #ifdef __alpha__ | ||
| 61 | /* for /sbin/loader handling in search_binary_handler() */ | ||
| 62 | #include <linux/a.out.h> | ||
| 63 | #endif | ||
| 64 | |||
| 65 | int core_uses_pid; | 61 | int core_uses_pid; |
| 66 | char core_pattern[CORENAME_MAX_SIZE] = "core"; | 62 | char core_pattern[CORENAME_MAX_SIZE] = "core"; |
| 67 | int suid_dumpable = 0; | 63 | int suid_dumpable = 0; |
| @@ -127,7 +123,8 @@ asmlinkage long sys_uselib(const char __user * library) | |||
| 127 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) | 123 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) |
| 128 | goto exit; | 124 | goto exit; |
| 129 | 125 | ||
| 130 | error = vfs_permission(&nd, MAY_READ | MAY_EXEC | MAY_OPEN); | 126 | error = inode_permission(nd.path.dentry->d_inode, |
| 127 | MAY_READ | MAY_EXEC | MAY_OPEN); | ||
| 131 | if (error) | 128 | if (error) |
| 132 | goto exit; | 129 | goto exit; |
| 133 | 130 | ||
| @@ -136,6 +133,8 @@ asmlinkage long sys_uselib(const char __user * library) | |||
| 136 | if (IS_ERR(file)) | 133 | if (IS_ERR(file)) |
| 137 | goto out; | 134 | goto out; |
| 138 | 135 | ||
| 136 | fsnotify_open(file->f_path.dentry); | ||
| 137 | |||
| 139 | error = -ENOEXEC; | 138 | error = -ENOEXEC; |
| 140 | if(file->f_op) { | 139 | if(file->f_op) { |
| 141 | struct linux_binfmt * fmt; | 140 | struct linux_binfmt * fmt; |
| @@ -233,13 +232,13 @@ static void flush_arg_page(struct linux_binprm *bprm, unsigned long pos, | |||
| 233 | 232 | ||
| 234 | static int __bprm_mm_init(struct linux_binprm *bprm) | 233 | static int __bprm_mm_init(struct linux_binprm *bprm) |
| 235 | { | 234 | { |
| 236 | int err = -ENOMEM; | 235 | int err; |
| 237 | struct vm_area_struct *vma = NULL; | 236 | struct vm_area_struct *vma = NULL; |
| 238 | struct mm_struct *mm = bprm->mm; | 237 | struct mm_struct *mm = bprm->mm; |
| 239 | 238 | ||
| 240 | bprm->vma = vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); | 239 | bprm->vma = vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); |
| 241 | if (!vma) | 240 | if (!vma) |
| 242 | goto err; | 241 | return -ENOMEM; |
| 243 | 242 | ||
| 244 | down_write(&mm->mmap_sem); | 243 | down_write(&mm->mmap_sem); |
| 245 | vma->vm_mm = mm; | 244 | vma->vm_mm = mm; |
| @@ -252,28 +251,20 @@ static int __bprm_mm_init(struct linux_binprm *bprm) | |||
| 252 | */ | 251 | */ |
| 253 | vma->vm_end = STACK_TOP_MAX; | 252 | vma->vm_end = STACK_TOP_MAX; |
| 254 | vma->vm_start = vma->vm_end - PAGE_SIZE; | 253 | vma->vm_start = vma->vm_end - PAGE_SIZE; |
| 255 | |||
| 256 | vma->vm_flags = VM_STACK_FLAGS; | 254 | vma->vm_flags = VM_STACK_FLAGS; |
| 257 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); | 255 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); |
| 258 | err = insert_vm_struct(mm, vma); | 256 | err = insert_vm_struct(mm, vma); |
| 259 | if (err) { | 257 | if (err) |
| 260 | up_write(&mm->mmap_sem); | ||
| 261 | goto err; | 258 | goto err; |
| 262 | } | ||
| 263 | 259 | ||
| 264 | mm->stack_vm = mm->total_vm = 1; | 260 | mm->stack_vm = mm->total_vm = 1; |
| 265 | up_write(&mm->mmap_sem); | 261 | up_write(&mm->mmap_sem); |
| 266 | |||
| 267 | bprm->p = vma->vm_end - sizeof(void *); | 262 | bprm->p = vma->vm_end - sizeof(void *); |
| 268 | |||
| 269 | return 0; | 263 | return 0; |
| 270 | |||
| 271 | err: | 264 | err: |
| 272 | if (vma) { | 265 | up_write(&mm->mmap_sem); |
| 273 | bprm->vma = NULL; | 266 | bprm->vma = NULL; |
| 274 | kmem_cache_free(vm_area_cachep, vma); | 267 | kmem_cache_free(vm_area_cachep, vma); |
| 275 | } | ||
| 276 | |||
| 277 | return err; | 268 | return err; |
| 278 | } | 269 | } |
| 279 | 270 | ||
| @@ -680,7 +671,7 @@ struct file *open_exec(const char *name) | |||
| 680 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) | 671 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) |
| 681 | goto out_path_put; | 672 | goto out_path_put; |
| 682 | 673 | ||
| 683 | err = vfs_permission(&nd, MAY_EXEC | MAY_OPEN); | 674 | err = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_OPEN); |
| 684 | if (err) | 675 | if (err) |
| 685 | goto out_path_put; | 676 | goto out_path_put; |
| 686 | 677 | ||
| @@ -688,6 +679,8 @@ struct file *open_exec(const char *name) | |||
| 688 | if (IS_ERR(file)) | 679 | if (IS_ERR(file)) |
| 689 | return file; | 680 | return file; |
| 690 | 681 | ||
| 682 | fsnotify_open(file->f_path.dentry); | ||
| 683 | |||
| 691 | err = deny_write_access(file); | 684 | err = deny_write_access(file); |
| 692 | if (err) { | 685 | if (err) { |
| 693 | fput(file); | 686 | fput(file); |
| @@ -1171,41 +1164,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) | |||
| 1171 | unsigned int depth = bprm->recursion_depth; | 1164 | unsigned int depth = bprm->recursion_depth; |
| 1172 | int try,retval; | 1165 | int try,retval; |
| 1173 | struct linux_binfmt *fmt; | 1166 | struct linux_binfmt *fmt; |
| 1174 | #ifdef __alpha__ | ||
| 1175 | /* handle /sbin/loader.. */ | ||
| 1176 | { | ||
| 1177 | struct exec * eh = (struct exec *) bprm->buf; | ||
| 1178 | |||
| 1179 | if (!bprm->loader && eh->fh.f_magic == 0x183 && | ||
| 1180 | (eh->fh.f_flags & 0x3000) == 0x3000) | ||
| 1181 | { | ||
| 1182 | struct file * file; | ||
| 1183 | unsigned long loader; | ||
| 1184 | 1167 | ||
| 1185 | allow_write_access(bprm->file); | ||
| 1186 | fput(bprm->file); | ||
| 1187 | bprm->file = NULL; | ||
| 1188 | |||
| 1189 | loader = bprm->vma->vm_end - sizeof(void *); | ||
| 1190 | |||
| 1191 | file = open_exec("/sbin/loader"); | ||
| 1192 | retval = PTR_ERR(file); | ||
| 1193 | if (IS_ERR(file)) | ||
| 1194 | return retval; | ||
| 1195 | |||
| 1196 | /* Remember if the application is TASO. */ | ||
| 1197 | bprm->taso = eh->ah.entry < 0x100000000UL; | ||
| 1198 | |||
| 1199 | bprm->file = file; | ||
| 1200 | bprm->loader = loader; | ||
| 1201 | retval = prepare_binprm(bprm); | ||
| 1202 | if (retval<0) | ||
| 1203 | return retval; | ||
| 1204 | /* should call search_binary_handler recursively here, | ||
| 1205 | but it does not matter */ | ||
| 1206 | } | ||
| 1207 | } | ||
| 1208 | #endif | ||
| 1209 | retval = security_bprm_check(bprm); | 1168 | retval = security_bprm_check(bprm); |
| 1210 | if (retval) | 1169 | if (retval) |
| 1211 | return retval; | 1170 | return retval; |
| @@ -1727,7 +1686,7 @@ int get_dumpable(struct mm_struct *mm) | |||
| 1727 | return (ret >= 2) ? 2 : ret; | 1686 | return (ret >= 2) ? 2 : ret; |
| 1728 | } | 1687 | } |
| 1729 | 1688 | ||
| 1730 | int do_coredump(long signr, int exit_code, struct pt_regs * regs) | 1689 | void do_coredump(long signr, int exit_code, struct pt_regs *regs) |
| 1731 | { | 1690 | { |
| 1732 | struct core_state core_state; | 1691 | struct core_state core_state; |
| 1733 | char corename[CORENAME_MAX_SIZE + 1]; | 1692 | char corename[CORENAME_MAX_SIZE + 1]; |
| @@ -1811,6 +1770,11 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
| 1811 | 1770 | ||
| 1812 | if (ispipe) { | 1771 | if (ispipe) { |
| 1813 | helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); | 1772 | helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); |
| 1773 | if (!helper_argv) { | ||
| 1774 | printk(KERN_WARNING "%s failed to allocate memory\n", | ||
| 1775 | __func__); | ||
| 1776 | goto fail_unlock; | ||
| 1777 | } | ||
| 1814 | /* Terminate the string before the first option */ | 1778 | /* Terminate the string before the first option */ |
| 1815 | delimit = strchr(corename, ' '); | 1779 | delimit = strchr(corename, ' '); |
| 1816 | if (delimit) | 1780 | if (delimit) |
| @@ -1878,5 +1842,5 @@ fail_unlock: | |||
| 1878 | put_cred(cred); | 1842 | put_cred(cred); |
| 1879 | coredump_finish(mm); | 1843 | coredump_finish(mm); |
| 1880 | fail: | 1844 | fail: |
| 1881 | return retval; | 1845 | return; |
| 1882 | } | 1846 | } |
