diff options
-rw-r--r-- | arch/parisc/hpux/fs.c | 15 | ||||
-rw-r--r-- | fs/exec.c | 45 | ||||
-rw-r--r-- | fs/namei.c | 30 | ||||
-rw-r--r-- | include/linux/binfmts.h | 1 | ||||
-rw-r--r-- | include/linux/fs.h | 1 | ||||
-rw-r--r-- | include/linux/sched.h | 3 | ||||
-rw-r--r-- | init/main.c | 2 | ||||
-rw-r--r-- | kernel/auditsc.c | 2 | ||||
-rw-r--r-- | kernel/kmod.c | 2 |
9 files changed, 58 insertions, 43 deletions
diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c index 88d0962de65a..2bedafea3d94 100644 --- a/arch/parisc/hpux/fs.c +++ b/arch/parisc/hpux/fs.c | |||
@@ -33,22 +33,9 @@ | |||
33 | 33 | ||
34 | int hpux_execve(struct pt_regs *regs) | 34 | int hpux_execve(struct pt_regs *regs) |
35 | { | 35 | { |
36 | int error; | 36 | return do_execve(getname((const char __user *) regs->gr[26]), |
37 | struct filename *filename; | ||
38 | |||
39 | filename = getname((const char __user *) regs->gr[26]); | ||
40 | error = PTR_ERR(filename); | ||
41 | if (IS_ERR(filename)) | ||
42 | goto out; | ||
43 | |||
44 | error = do_execve(filename->name, | ||
45 | (const char __user *const __user *) regs->gr[25], | 37 | (const char __user *const __user *) regs->gr[25], |
46 | (const char __user *const __user *) regs->gr[24]); | 38 | (const char __user *const __user *) regs->gr[24]); |
47 | |||
48 | putname(filename); | ||
49 | |||
50 | out: | ||
51 | return error; | ||
52 | } | 39 | } |
53 | 40 | ||
54 | struct hpux_dirent { | 41 | struct hpux_dirent { |
@@ -748,11 +748,10 @@ EXPORT_SYMBOL(setup_arg_pages); | |||
748 | 748 | ||
749 | #endif /* CONFIG_MMU */ | 749 | #endif /* CONFIG_MMU */ |
750 | 750 | ||
751 | struct file *open_exec(const char *name) | 751 | static struct file *do_open_exec(struct filename *name) |
752 | { | 752 | { |
753 | struct file *file; | 753 | struct file *file; |
754 | int err; | 754 | int err; |
755 | struct filename tmp = { .name = name }; | ||
756 | static const struct open_flags open_exec_flags = { | 755 | static const struct open_flags open_exec_flags = { |
757 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, | 756 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, |
758 | .acc_mode = MAY_EXEC | MAY_OPEN, | 757 | .acc_mode = MAY_EXEC | MAY_OPEN, |
@@ -760,7 +759,7 @@ struct file *open_exec(const char *name) | |||
760 | .lookup_flags = LOOKUP_FOLLOW, | 759 | .lookup_flags = LOOKUP_FOLLOW, |
761 | }; | 760 | }; |
762 | 761 | ||
763 | file = do_filp_open(AT_FDCWD, &tmp, &open_exec_flags); | 762 | file = do_filp_open(AT_FDCWD, name, &open_exec_flags); |
764 | if (IS_ERR(file)) | 763 | if (IS_ERR(file)) |
765 | goto out; | 764 | goto out; |
766 | 765 | ||
@@ -784,6 +783,12 @@ exit: | |||
784 | fput(file); | 783 | fput(file); |
785 | return ERR_PTR(err); | 784 | return ERR_PTR(err); |
786 | } | 785 | } |
786 | |||
787 | struct file *open_exec(const char *name) | ||
788 | { | ||
789 | struct filename tmp = { .name = name }; | ||
790 | return do_open_exec(&tmp); | ||
791 | } | ||
787 | EXPORT_SYMBOL(open_exec); | 792 | EXPORT_SYMBOL(open_exec); |
788 | 793 | ||
789 | int kernel_read(struct file *file, loff_t offset, | 794 | int kernel_read(struct file *file, loff_t offset, |
@@ -1162,7 +1167,7 @@ int prepare_bprm_creds(struct linux_binprm *bprm) | |||
1162 | return -ENOMEM; | 1167 | return -ENOMEM; |
1163 | } | 1168 | } |
1164 | 1169 | ||
1165 | void free_bprm(struct linux_binprm *bprm) | 1170 | static void free_bprm(struct linux_binprm *bprm) |
1166 | { | 1171 | { |
1167 | free_arg_pages(bprm); | 1172 | free_arg_pages(bprm); |
1168 | if (bprm->cred) { | 1173 | if (bprm->cred) { |
@@ -1432,7 +1437,7 @@ static int exec_binprm(struct linux_binprm *bprm) | |||
1432 | /* | 1437 | /* |
1433 | * sys_execve() executes a new program. | 1438 | * sys_execve() executes a new program. |
1434 | */ | 1439 | */ |
1435 | static int do_execve_common(const char *filename, | 1440 | static int do_execve_common(struct filename *filename, |
1436 | struct user_arg_ptr argv, | 1441 | struct user_arg_ptr argv, |
1437 | struct user_arg_ptr envp) | 1442 | struct user_arg_ptr envp) |
1438 | { | 1443 | { |
@@ -1441,6 +1446,9 @@ static int do_execve_common(const char *filename, | |||
1441 | struct files_struct *displaced; | 1446 | struct files_struct *displaced; |
1442 | int retval; | 1447 | int retval; |
1443 | 1448 | ||
1449 | if (IS_ERR(filename)) | ||
1450 | return PTR_ERR(filename); | ||
1451 | |||
1444 | /* | 1452 | /* |
1445 | * We move the actual failure in case of RLIMIT_NPROC excess from | 1453 | * We move the actual failure in case of RLIMIT_NPROC excess from |
1446 | * set*uid() to execve() because too many poorly written programs | 1454 | * set*uid() to execve() because too many poorly written programs |
@@ -1473,7 +1481,7 @@ static int do_execve_common(const char *filename, | |||
1473 | check_unsafe_exec(bprm); | 1481 | check_unsafe_exec(bprm); |
1474 | current->in_execve = 1; | 1482 | current->in_execve = 1; |
1475 | 1483 | ||
1476 | file = open_exec(filename); | 1484 | file = do_open_exec(filename); |
1477 | retval = PTR_ERR(file); | 1485 | retval = PTR_ERR(file); |
1478 | if (IS_ERR(file)) | 1486 | if (IS_ERR(file)) |
1479 | goto out_unmark; | 1487 | goto out_unmark; |
@@ -1481,8 +1489,7 @@ static int do_execve_common(const char *filename, | |||
1481 | sched_exec(); | 1489 | sched_exec(); |
1482 | 1490 | ||
1483 | bprm->file = file; | 1491 | bprm->file = file; |
1484 | bprm->filename = filename; | 1492 | bprm->filename = bprm->interp = filename->name; |
1485 | bprm->interp = filename; | ||
1486 | 1493 | ||
1487 | retval = bprm_mm_init(bprm); | 1494 | retval = bprm_mm_init(bprm); |
1488 | if (retval) | 1495 | if (retval) |
@@ -1523,6 +1530,7 @@ static int do_execve_common(const char *filename, | |||
1523 | acct_update_integrals(current); | 1530 | acct_update_integrals(current); |
1524 | task_numa_free(current); | 1531 | task_numa_free(current); |
1525 | free_bprm(bprm); | 1532 | free_bprm(bprm); |
1533 | putname(filename); | ||
1526 | if (displaced) | 1534 | if (displaced) |
1527 | put_files_struct(displaced); | 1535 | put_files_struct(displaced); |
1528 | return retval; | 1536 | return retval; |
@@ -1544,10 +1552,11 @@ out_files: | |||
1544 | if (displaced) | 1552 | if (displaced) |
1545 | reset_files_struct(displaced); | 1553 | reset_files_struct(displaced); |
1546 | out_ret: | 1554 | out_ret: |
1555 | putname(filename); | ||
1547 | return retval; | 1556 | return retval; |
1548 | } | 1557 | } |
1549 | 1558 | ||
1550 | int do_execve(const char *filename, | 1559 | int do_execve(struct filename *filename, |
1551 | const char __user *const __user *__argv, | 1560 | const char __user *const __user *__argv, |
1552 | const char __user *const __user *__envp) | 1561 | const char __user *const __user *__envp) |
1553 | { | 1562 | { |
@@ -1557,7 +1566,7 @@ int do_execve(const char *filename, | |||
1557 | } | 1566 | } |
1558 | 1567 | ||
1559 | #ifdef CONFIG_COMPAT | 1568 | #ifdef CONFIG_COMPAT |
1560 | static int compat_do_execve(const char *filename, | 1569 | static int compat_do_execve(struct filename *filename, |
1561 | const compat_uptr_t __user *__argv, | 1570 | const compat_uptr_t __user *__argv, |
1562 | const compat_uptr_t __user *__envp) | 1571 | const compat_uptr_t __user *__envp) |
1563 | { | 1572 | { |
@@ -1607,25 +1616,13 @@ SYSCALL_DEFINE3(execve, | |||
1607 | const char __user *const __user *, argv, | 1616 | const char __user *const __user *, argv, |
1608 | const char __user *const __user *, envp) | 1617 | const char __user *const __user *, envp) |
1609 | { | 1618 | { |
1610 | struct filename *path = getname(filename); | 1619 | return do_execve(getname(filename), argv, envp); |
1611 | int error = PTR_ERR(path); | ||
1612 | if (!IS_ERR(path)) { | ||
1613 | error = do_execve(path->name, argv, envp); | ||
1614 | putname(path); | ||
1615 | } | ||
1616 | return error; | ||
1617 | } | 1620 | } |
1618 | #ifdef CONFIG_COMPAT | 1621 | #ifdef CONFIG_COMPAT |
1619 | asmlinkage long compat_sys_execve(const char __user * filename, | 1622 | asmlinkage long compat_sys_execve(const char __user * filename, |
1620 | const compat_uptr_t __user * argv, | 1623 | const compat_uptr_t __user * argv, |
1621 | const compat_uptr_t __user * envp) | 1624 | const compat_uptr_t __user * envp) |
1622 | { | 1625 | { |
1623 | struct filename *path = getname(filename); | 1626 | return compat_do_execve(getname(filename), argv, envp); |
1624 | int error = PTR_ERR(path); | ||
1625 | if (!IS_ERR(path)) { | ||
1626 | error = compat_do_execve(path->name, argv, envp); | ||
1627 | putname(path); | ||
1628 | } | ||
1629 | return error; | ||
1630 | } | 1627 | } |
1631 | #endif | 1628 | #endif |
diff --git a/fs/namei.c b/fs/namei.c index d580df2e6804..385f7817bfcc 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -196,6 +196,7 @@ recopy: | |||
196 | goto error; | 196 | goto error; |
197 | 197 | ||
198 | result->uptr = filename; | 198 | result->uptr = filename; |
199 | result->aname = NULL; | ||
199 | audit_getname(result); | 200 | audit_getname(result); |
200 | return result; | 201 | return result; |
201 | 202 | ||
@@ -210,6 +211,35 @@ getname(const char __user * filename) | |||
210 | return getname_flags(filename, 0, NULL); | 211 | return getname_flags(filename, 0, NULL); |
211 | } | 212 | } |
212 | 213 | ||
214 | /* | ||
215 | * The "getname_kernel()" interface doesn't do pathnames longer | ||
216 | * than EMBEDDED_NAME_MAX. Deal with it - you're a kernel user. | ||
217 | */ | ||
218 | struct filename * | ||
219 | getname_kernel(const char * filename) | ||
220 | { | ||
221 | struct filename *result; | ||
222 | char *kname; | ||
223 | int len; | ||
224 | |||
225 | len = strlen(filename); | ||
226 | if (len >= EMBEDDED_NAME_MAX) | ||
227 | return ERR_PTR(-ENAMETOOLONG); | ||
228 | |||
229 | result = __getname(); | ||
230 | if (unlikely(!result)) | ||
231 | return ERR_PTR(-ENOMEM); | ||
232 | |||
233 | kname = (char *)result + sizeof(*result); | ||
234 | result->name = kname; | ||
235 | result->uptr = NULL; | ||
236 | result->aname = NULL; | ||
237 | result->separate = false; | ||
238 | |||
239 | strlcpy(kname, filename, EMBEDDED_NAME_MAX); | ||
240 | return result; | ||
241 | } | ||
242 | |||
213 | #ifdef CONFIG_AUDITSYSCALL | 243 | #ifdef CONFIG_AUDITSYSCALL |
214 | void putname(struct filename *name) | 244 | void putname(struct filename *name) |
215 | { | 245 | { |
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index fd8bf3219ef7..b4a745d7d9a9 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h | |||
@@ -115,7 +115,6 @@ extern int copy_strings_kernel(int argc, const char *const *argv, | |||
115 | extern int prepare_bprm_creds(struct linux_binprm *bprm); | 115 | extern int prepare_bprm_creds(struct linux_binprm *bprm); |
116 | extern void install_exec_creds(struct linux_binprm *bprm); | 116 | extern void install_exec_creds(struct linux_binprm *bprm); |
117 | extern void set_binfmt(struct linux_binfmt *new); | 117 | extern void set_binfmt(struct linux_binfmt *new); |
118 | extern void free_bprm(struct linux_binprm *); | ||
119 | extern ssize_t read_code(struct file *, unsigned long, loff_t, size_t); | 118 | extern ssize_t read_code(struct file *, unsigned long, loff_t, size_t); |
120 | 119 | ||
121 | #endif /* _LINUX_BINFMTS_H */ | 120 | #endif /* _LINUX_BINFMTS_H */ |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 09f553c59813..d79678c188ad 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2079,6 +2079,7 @@ extern struct file * dentry_open(const struct path *, int, const struct cred *); | |||
2079 | extern int filp_close(struct file *, fl_owner_t id); | 2079 | extern int filp_close(struct file *, fl_owner_t id); |
2080 | 2080 | ||
2081 | extern struct filename *getname(const char __user *); | 2081 | extern struct filename *getname(const char __user *); |
2082 | extern struct filename *getname_kernel(const char *); | ||
2082 | 2083 | ||
2083 | enum { | 2084 | enum { |
2084 | FILE_CREATED = 1, | 2085 | FILE_CREATED = 1, |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 68a0e84463a0..a781dec1cd0b 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -128,6 +128,7 @@ struct bio_list; | |||
128 | struct fs_struct; | 128 | struct fs_struct; |
129 | struct perf_event_context; | 129 | struct perf_event_context; |
130 | struct blk_plug; | 130 | struct blk_plug; |
131 | struct filename; | ||
131 | 132 | ||
132 | /* | 133 | /* |
133 | * List of flags we want to share for kernel threads, | 134 | * List of flags we want to share for kernel threads, |
@@ -2311,7 +2312,7 @@ extern void do_group_exit(int); | |||
2311 | extern int allow_signal(int); | 2312 | extern int allow_signal(int); |
2312 | extern int disallow_signal(int); | 2313 | extern int disallow_signal(int); |
2313 | 2314 | ||
2314 | extern int do_execve(const char *, | 2315 | extern int do_execve(struct filename *, |
2315 | const char __user * const __user *, | 2316 | const char __user * const __user *, |
2316 | const char __user * const __user *); | 2317 | const char __user * const __user *); |
2317 | extern long do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *); | 2318 | extern long do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *); |
diff --git a/init/main.c b/init/main.c index 2fd9cef70ee8..eb03090cdced 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -812,7 +812,7 @@ void __init load_default_modules(void) | |||
812 | static int run_init_process(const char *init_filename) | 812 | static int run_init_process(const char *init_filename) |
813 | { | 813 | { |
814 | argv_init[0] = init_filename; | 814 | argv_init[0] = init_filename; |
815 | return do_execve(init_filename, | 815 | return do_execve(getname_kernel(init_filename), |
816 | (const char __user *const __user *)argv_init, | 816 | (const char __user *const __user *)argv_init, |
817 | (const char __user *const __user *)envp_init); | 817 | (const char __user *const __user *)envp_init); |
818 | } | 818 | } |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 10176cd5956a..7aef2f4b6c64 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -1719,7 +1719,7 @@ void audit_putname(struct filename *name) | |||
1719 | struct audit_context *context = current->audit_context; | 1719 | struct audit_context *context = current->audit_context; |
1720 | 1720 | ||
1721 | BUG_ON(!context); | 1721 | BUG_ON(!context); |
1722 | if (!context->in_syscall) { | 1722 | if (!name->aname || !context->in_syscall) { |
1723 | #if AUDIT_DEBUG == 2 | 1723 | #if AUDIT_DEBUG == 2 |
1724 | printk(KERN_ERR "%s:%d(:%d): final_putname(%p)\n", | 1724 | printk(KERN_ERR "%s:%d(:%d): final_putname(%p)\n", |
1725 | __FILE__, __LINE__, context->serial, name); | 1725 | __FILE__, __LINE__, context->serial, name); |
diff --git a/kernel/kmod.c b/kernel/kmod.c index b086006c59e7..6b375af4958d 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c | |||
@@ -239,7 +239,7 @@ static int ____call_usermodehelper(void *data) | |||
239 | 239 | ||
240 | commit_creds(new); | 240 | commit_creds(new); |
241 | 241 | ||
242 | retval = do_execve(sub_info->path, | 242 | retval = do_execve(getname_kernel(sub_info->path), |
243 | (const char __user *const __user *)sub_info->argv, | 243 | (const char __user *const __user *)sub_info->argv, |
244 | (const char __user *const __user *)sub_info->envp); | 244 | (const char __user *const __user *)sub_info->envp); |
245 | if (!retval) | 245 | if (!retval) |