diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 80 |
1 files changed, 22 insertions, 58 deletions
@@ -52,17 +52,13 @@ | |||
52 | #include <linux/audit.h> | 52 | #include <linux/audit.h> |
53 | #include <linux/tracehook.h> | 53 | #include <linux/tracehook.h> |
54 | #include <linux/kmod.h> | 54 | #include <linux/kmod.h> |
55 | #include <linux/fsnotify.h> | ||
55 | 56 | ||
56 | #include <asm/uaccess.h> | 57 | #include <asm/uaccess.h> |
57 | #include <asm/mmu_context.h> | 58 | #include <asm/mmu_context.h> |
58 | #include <asm/tlb.h> | 59 | #include <asm/tlb.h> |
59 | #include "internal.h" | 60 | #include "internal.h" |
60 | 61 | ||
61 | #ifdef __alpha__ | ||
62 | /* for /sbin/loader handling in search_binary_handler() */ | ||
63 | #include <linux/a.out.h> | ||
64 | #endif | ||
65 | |||
66 | int core_uses_pid; | 62 | int core_uses_pid; |
67 | char core_pattern[CORENAME_MAX_SIZE] = "core"; | 63 | char core_pattern[CORENAME_MAX_SIZE] = "core"; |
68 | int suid_dumpable = 0; | 64 | int suid_dumpable = 0; |
@@ -104,7 +100,7 @@ static inline void put_binfmt(struct linux_binfmt * fmt) | |||
104 | * | 100 | * |
105 | * Also note that we take the address to load from from the file itself. | 101 | * Also note that we take the address to load from from the file itself. |
106 | */ | 102 | */ |
107 | asmlinkage long sys_uselib(const char __user * library) | 103 | SYSCALL_DEFINE1(uselib, const char __user *, library) |
108 | { | 104 | { |
109 | struct file *file; | 105 | struct file *file; |
110 | struct nameidata nd; | 106 | struct nameidata nd; |
@@ -128,7 +124,8 @@ asmlinkage long sys_uselib(const char __user * library) | |||
128 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) | 124 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) |
129 | goto exit; | 125 | goto exit; |
130 | 126 | ||
131 | error = vfs_permission(&nd, MAY_READ | MAY_EXEC | MAY_OPEN); | 127 | error = inode_permission(nd.path.dentry->d_inode, |
128 | MAY_READ | MAY_EXEC | MAY_OPEN); | ||
132 | if (error) | 129 | if (error) |
133 | goto exit; | 130 | goto exit; |
134 | error = ima_path_check(&nd.path, MAY_READ | MAY_EXEC | MAY_OPEN); | 131 | error = ima_path_check(&nd.path, MAY_READ | MAY_EXEC | MAY_OPEN); |
@@ -140,6 +137,8 @@ asmlinkage long sys_uselib(const char __user * library) | |||
140 | if (IS_ERR(file)) | 137 | if (IS_ERR(file)) |
141 | goto out; | 138 | goto out; |
142 | 139 | ||
140 | fsnotify_open(file->f_path.dentry); | ||
141 | |||
143 | error = -ENOEXEC; | 142 | error = -ENOEXEC; |
144 | if(file->f_op) { | 143 | if(file->f_op) { |
145 | struct linux_binfmt * fmt; | 144 | struct linux_binfmt * fmt; |
@@ -237,13 +236,13 @@ static void flush_arg_page(struct linux_binprm *bprm, unsigned long pos, | |||
237 | 236 | ||
238 | static int __bprm_mm_init(struct linux_binprm *bprm) | 237 | static int __bprm_mm_init(struct linux_binprm *bprm) |
239 | { | 238 | { |
240 | int err = -ENOMEM; | 239 | int err; |
241 | struct vm_area_struct *vma = NULL; | 240 | struct vm_area_struct *vma = NULL; |
242 | struct mm_struct *mm = bprm->mm; | 241 | struct mm_struct *mm = bprm->mm; |
243 | 242 | ||
244 | bprm->vma = vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); | 243 | bprm->vma = vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); |
245 | if (!vma) | 244 | if (!vma) |
246 | goto err; | 245 | return -ENOMEM; |
247 | 246 | ||
248 | down_write(&mm->mmap_sem); | 247 | down_write(&mm->mmap_sem); |
249 | vma->vm_mm = mm; | 248 | vma->vm_mm = mm; |
@@ -256,28 +255,20 @@ static int __bprm_mm_init(struct linux_binprm *bprm) | |||
256 | */ | 255 | */ |
257 | vma->vm_end = STACK_TOP_MAX; | 256 | vma->vm_end = STACK_TOP_MAX; |
258 | vma->vm_start = vma->vm_end - PAGE_SIZE; | 257 | vma->vm_start = vma->vm_end - PAGE_SIZE; |
259 | |||
260 | vma->vm_flags = VM_STACK_FLAGS; | 258 | vma->vm_flags = VM_STACK_FLAGS; |
261 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); | 259 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); |
262 | err = insert_vm_struct(mm, vma); | 260 | err = insert_vm_struct(mm, vma); |
263 | if (err) { | 261 | if (err) |
264 | up_write(&mm->mmap_sem); | ||
265 | goto err; | 262 | goto err; |
266 | } | ||
267 | 263 | ||
268 | mm->stack_vm = mm->total_vm = 1; | 264 | mm->stack_vm = mm->total_vm = 1; |
269 | up_write(&mm->mmap_sem); | 265 | up_write(&mm->mmap_sem); |
270 | |||
271 | bprm->p = vma->vm_end - sizeof(void *); | 266 | bprm->p = vma->vm_end - sizeof(void *); |
272 | |||
273 | return 0; | 267 | return 0; |
274 | |||
275 | err: | 268 | err: |
276 | if (vma) { | 269 | up_write(&mm->mmap_sem); |
277 | bprm->vma = NULL; | 270 | bprm->vma = NULL; |
278 | kmem_cache_free(vm_area_cachep, vma); | 271 | kmem_cache_free(vm_area_cachep, vma); |
279 | } | ||
280 | |||
281 | return err; | 272 | return err; |
282 | } | 273 | } |
283 | 274 | ||
@@ -684,7 +675,7 @@ struct file *open_exec(const char *name) | |||
684 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) | 675 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) |
685 | goto out_path_put; | 676 | goto out_path_put; |
686 | 677 | ||
687 | err = vfs_permission(&nd, MAY_EXEC | MAY_OPEN); | 678 | err = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_OPEN); |
688 | if (err) | 679 | if (err) |
689 | goto out_path_put; | 680 | goto out_path_put; |
690 | err = ima_path_check(&nd.path, MAY_EXEC | MAY_OPEN); | 681 | err = ima_path_check(&nd.path, MAY_EXEC | MAY_OPEN); |
@@ -695,6 +686,8 @@ struct file *open_exec(const char *name) | |||
695 | if (IS_ERR(file)) | 686 | if (IS_ERR(file)) |
696 | return file; | 687 | return file; |
697 | 688 | ||
689 | fsnotify_open(file->f_path.dentry); | ||
690 | |||
698 | err = deny_write_access(file); | 691 | err = deny_write_access(file); |
699 | if (err) { | 692 | if (err) { |
700 | fput(file); | 693 | fput(file); |
@@ -1178,41 +1171,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) | |||
1178 | unsigned int depth = bprm->recursion_depth; | 1171 | unsigned int depth = bprm->recursion_depth; |
1179 | int try,retval; | 1172 | int try,retval; |
1180 | struct linux_binfmt *fmt; | 1173 | struct linux_binfmt *fmt; |
1181 | #ifdef __alpha__ | ||
1182 | /* handle /sbin/loader.. */ | ||
1183 | { | ||
1184 | struct exec * eh = (struct exec *) bprm->buf; | ||
1185 | |||
1186 | if (!bprm->loader && eh->fh.f_magic == 0x183 && | ||
1187 | (eh->fh.f_flags & 0x3000) == 0x3000) | ||
1188 | { | ||
1189 | struct file * file; | ||
1190 | unsigned long loader; | ||
1191 | 1174 | ||
1192 | allow_write_access(bprm->file); | ||
1193 | fput(bprm->file); | ||
1194 | bprm->file = NULL; | ||
1195 | |||
1196 | loader = bprm->vma->vm_end - sizeof(void *); | ||
1197 | |||
1198 | file = open_exec("/sbin/loader"); | ||
1199 | retval = PTR_ERR(file); | ||
1200 | if (IS_ERR(file)) | ||
1201 | return retval; | ||
1202 | |||
1203 | /* Remember if the application is TASO. */ | ||
1204 | bprm->taso = eh->ah.entry < 0x100000000UL; | ||
1205 | |||
1206 | bprm->file = file; | ||
1207 | bprm->loader = loader; | ||
1208 | retval = prepare_binprm(bprm); | ||
1209 | if (retval<0) | ||
1210 | return retval; | ||
1211 | /* should call search_binary_handler recursively here, | ||
1212 | but it does not matter */ | ||
1213 | } | ||
1214 | } | ||
1215 | #endif | ||
1216 | retval = security_bprm_check(bprm); | 1175 | retval = security_bprm_check(bprm); |
1217 | if (retval) | 1176 | if (retval) |
1218 | return retval; | 1177 | return retval; |
@@ -1737,7 +1696,7 @@ int get_dumpable(struct mm_struct *mm) | |||
1737 | return (ret >= 2) ? 2 : ret; | 1696 | return (ret >= 2) ? 2 : ret; |
1738 | } | 1697 | } |
1739 | 1698 | ||
1740 | int do_coredump(long signr, int exit_code, struct pt_regs * regs) | 1699 | void do_coredump(long signr, int exit_code, struct pt_regs *regs) |
1741 | { | 1700 | { |
1742 | struct core_state core_state; | 1701 | struct core_state core_state; |
1743 | char corename[CORENAME_MAX_SIZE + 1]; | 1702 | char corename[CORENAME_MAX_SIZE + 1]; |
@@ -1821,6 +1780,11 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1821 | 1780 | ||
1822 | if (ispipe) { | 1781 | if (ispipe) { |
1823 | helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); | 1782 | helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); |
1783 | if (!helper_argv) { | ||
1784 | printk(KERN_WARNING "%s failed to allocate memory\n", | ||
1785 | __func__); | ||
1786 | goto fail_unlock; | ||
1787 | } | ||
1824 | /* Terminate the string before the first option */ | 1788 | /* Terminate the string before the first option */ |
1825 | delimit = strchr(corename, ' '); | 1789 | delimit = strchr(corename, ' '); |
1826 | if (delimit) | 1790 | if (delimit) |
@@ -1888,5 +1852,5 @@ fail_unlock: | |||
1888 | put_cred(cred); | 1852 | put_cred(cred); |
1889 | coredump_finish(mm); | 1853 | coredump_finish(mm); |
1890 | fail: | 1854 | fail: |
1891 | return retval; | 1855 | return; |
1892 | } | 1856 | } |