diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 59 |
1 files changed, 27 insertions, 32 deletions
@@ -123,7 +123,7 @@ SYSCALL_DEFINE1(uselib, const char __user *, library) | |||
123 | goto out; | 123 | goto out; |
124 | 124 | ||
125 | error = -EINVAL; | 125 | error = -EINVAL; |
126 | if (!S_ISREG(file->f_path.dentry->d_inode->i_mode)) | 126 | if (!S_ISREG(file_inode(file)->i_mode)) |
127 | goto exit; | 127 | goto exit; |
128 | 128 | ||
129 | error = -EACCES; | 129 | error = -EACCES; |
@@ -355,7 +355,7 @@ static bool valid_arg_len(struct linux_binprm *bprm, long len) | |||
355 | * flags, permissions, and offset, so we use temporary values. We'll update | 355 | * flags, permissions, and offset, so we use temporary values. We'll update |
356 | * them later in setup_arg_pages(). | 356 | * them later in setup_arg_pages(). |
357 | */ | 357 | */ |
358 | int bprm_mm_init(struct linux_binprm *bprm) | 358 | static int bprm_mm_init(struct linux_binprm *bprm) |
359 | { | 359 | { |
360 | int err; | 360 | int err; |
361 | struct mm_struct *mm = NULL; | 361 | struct mm_struct *mm = NULL; |
@@ -434,8 +434,9 @@ static int count(struct user_arg_ptr argv, int max) | |||
434 | if (IS_ERR(p)) | 434 | if (IS_ERR(p)) |
435 | return -EFAULT; | 435 | return -EFAULT; |
436 | 436 | ||
437 | if (i++ >= max) | 437 | if (i >= max) |
438 | return -E2BIG; | 438 | return -E2BIG; |
439 | ++i; | ||
439 | 440 | ||
440 | if (fatal_signal_pending(current)) | 441 | if (fatal_signal_pending(current)) |
441 | return -ERESTARTNOHAND; | 442 | return -ERESTARTNOHAND; |
@@ -763,7 +764,7 @@ struct file *open_exec(const char *name) | |||
763 | goto out; | 764 | goto out; |
764 | 765 | ||
765 | err = -EACCES; | 766 | err = -EACCES; |
766 | if (!S_ISREG(file->f_path.dentry->d_inode->i_mode)) | 767 | if (!S_ISREG(file_inode(file)->i_mode)) |
767 | goto exit; | 768 | goto exit; |
768 | 769 | ||
769 | if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) | 770 | if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) |
@@ -1097,7 +1098,7 @@ EXPORT_SYMBOL(flush_old_exec); | |||
1097 | 1098 | ||
1098 | void would_dump(struct linux_binprm *bprm, struct file *file) | 1099 | void would_dump(struct linux_binprm *bprm, struct file *file) |
1099 | { | 1100 | { |
1100 | if (inode_permission(file->f_path.dentry->d_inode, MAY_READ) < 0) | 1101 | if (inode_permission(file_inode(file), MAY_READ) < 0) |
1101 | bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP; | 1102 | bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP; |
1102 | } | 1103 | } |
1103 | EXPORT_SYMBOL(would_dump); | 1104 | EXPORT_SYMBOL(would_dump); |
@@ -1110,7 +1111,7 @@ void setup_new_exec(struct linux_binprm * bprm) | |||
1110 | current->sas_ss_sp = current->sas_ss_size = 0; | 1111 | current->sas_ss_sp = current->sas_ss_size = 0; |
1111 | 1112 | ||
1112 | if (uid_eq(current_euid(), current_uid()) && gid_eq(current_egid(), current_gid())) | 1113 | if (uid_eq(current_euid(), current_uid()) && gid_eq(current_egid(), current_gid())) |
1113 | set_dumpable(current->mm, SUID_DUMPABLE_ENABLED); | 1114 | set_dumpable(current->mm, SUID_DUMP_USER); |
1114 | else | 1115 | else |
1115 | set_dumpable(current->mm, suid_dumpable); | 1116 | set_dumpable(current->mm, suid_dumpable); |
1116 | 1117 | ||
@@ -1175,9 +1176,24 @@ void free_bprm(struct linux_binprm *bprm) | |||
1175 | mutex_unlock(¤t->signal->cred_guard_mutex); | 1176 | mutex_unlock(¤t->signal->cred_guard_mutex); |
1176 | abort_creds(bprm->cred); | 1177 | abort_creds(bprm->cred); |
1177 | } | 1178 | } |
1179 | /* If a binfmt changed the interp, free it. */ | ||
1180 | if (bprm->interp != bprm->filename) | ||
1181 | kfree(bprm->interp); | ||
1178 | kfree(bprm); | 1182 | kfree(bprm); |
1179 | } | 1183 | } |
1180 | 1184 | ||
1185 | int bprm_change_interp(char *interp, struct linux_binprm *bprm) | ||
1186 | { | ||
1187 | /* If a binfmt changed the interp, free it first. */ | ||
1188 | if (bprm->interp != bprm->filename) | ||
1189 | kfree(bprm->interp); | ||
1190 | bprm->interp = kstrdup(interp, GFP_KERNEL); | ||
1191 | if (!bprm->interp) | ||
1192 | return -ENOMEM; | ||
1193 | return 0; | ||
1194 | } | ||
1195 | EXPORT_SYMBOL(bprm_change_interp); | ||
1196 | |||
1181 | /* | 1197 | /* |
1182 | * install the new credentials for this executable | 1198 | * install the new credentials for this executable |
1183 | */ | 1199 | */ |
@@ -1254,7 +1270,7 @@ static int check_unsafe_exec(struct linux_binprm *bprm) | |||
1254 | int prepare_binprm(struct linux_binprm *bprm) | 1270 | int prepare_binprm(struct linux_binprm *bprm) |
1255 | { | 1271 | { |
1256 | umode_t mode; | 1272 | umode_t mode; |
1257 | struct inode * inode = bprm->file->f_path.dentry->d_inode; | 1273 | struct inode * inode = file_inode(bprm->file); |
1258 | int retval; | 1274 | int retval; |
1259 | 1275 | ||
1260 | mode = inode->i_mode; | 1276 | mode = inode->i_mode; |
@@ -1623,17 +1639,17 @@ EXPORT_SYMBOL(set_binfmt); | |||
1623 | void set_dumpable(struct mm_struct *mm, int value) | 1639 | void set_dumpable(struct mm_struct *mm, int value) |
1624 | { | 1640 | { |
1625 | switch (value) { | 1641 | switch (value) { |
1626 | case SUID_DUMPABLE_DISABLED: | 1642 | case SUID_DUMP_DISABLE: |
1627 | clear_bit(MMF_DUMPABLE, &mm->flags); | 1643 | clear_bit(MMF_DUMPABLE, &mm->flags); |
1628 | smp_wmb(); | 1644 | smp_wmb(); |
1629 | clear_bit(MMF_DUMP_SECURELY, &mm->flags); | 1645 | clear_bit(MMF_DUMP_SECURELY, &mm->flags); |
1630 | break; | 1646 | break; |
1631 | case SUID_DUMPABLE_ENABLED: | 1647 | case SUID_DUMP_USER: |
1632 | set_bit(MMF_DUMPABLE, &mm->flags); | 1648 | set_bit(MMF_DUMPABLE, &mm->flags); |
1633 | smp_wmb(); | 1649 | smp_wmb(); |
1634 | clear_bit(MMF_DUMP_SECURELY, &mm->flags); | 1650 | clear_bit(MMF_DUMP_SECURELY, &mm->flags); |
1635 | break; | 1651 | break; |
1636 | case SUID_DUMPABLE_SAFE: | 1652 | case SUID_DUMP_ROOT: |
1637 | set_bit(MMF_DUMP_SECURELY, &mm->flags); | 1653 | set_bit(MMF_DUMP_SECURELY, &mm->flags); |
1638 | smp_wmb(); | 1654 | smp_wmb(); |
1639 | set_bit(MMF_DUMPABLE, &mm->flags); | 1655 | set_bit(MMF_DUMPABLE, &mm->flags); |
@@ -1646,7 +1662,7 @@ int __get_dumpable(unsigned long mm_flags) | |||
1646 | int ret; | 1662 | int ret; |
1647 | 1663 | ||
1648 | ret = mm_flags & MMF_DUMPABLE_MASK; | 1664 | ret = mm_flags & MMF_DUMPABLE_MASK; |
1649 | return (ret > SUID_DUMPABLE_ENABLED) ? SUID_DUMPABLE_SAFE : ret; | 1665 | return (ret > SUID_DUMP_USER) ? SUID_DUMP_ROOT : ret; |
1650 | } | 1666 | } |
1651 | 1667 | ||
1652 | int get_dumpable(struct mm_struct *mm) | 1668 | int get_dumpable(struct mm_struct *mm) |
@@ -1654,7 +1670,6 @@ int get_dumpable(struct mm_struct *mm) | |||
1654 | return __get_dumpable(mm->flags); | 1670 | return __get_dumpable(mm->flags); |
1655 | } | 1671 | } |
1656 | 1672 | ||
1657 | #ifdef __ARCH_WANT_SYS_EXECVE | ||
1658 | SYSCALL_DEFINE3(execve, | 1673 | SYSCALL_DEFINE3(execve, |
1659 | const char __user *, filename, | 1674 | const char __user *, filename, |
1660 | const char __user *const __user *, argv, | 1675 | const char __user *const __user *, argv, |
@@ -1682,23 +1697,3 @@ asmlinkage long compat_sys_execve(const char __user * filename, | |||
1682 | return error; | 1697 | return error; |
1683 | } | 1698 | } |
1684 | #endif | 1699 | #endif |
1685 | #endif | ||
1686 | |||
1687 | #ifdef __ARCH_WANT_KERNEL_EXECVE | ||
1688 | int kernel_execve(const char *filename, | ||
1689 | const char *const argv[], | ||
1690 | const char *const envp[]) | ||
1691 | { | ||
1692 | int ret = do_execve(filename, | ||
1693 | (const char __user *const __user *)argv, | ||
1694 | (const char __user *const __user *)envp); | ||
1695 | if (ret < 0) | ||
1696 | return ret; | ||
1697 | |||
1698 | /* | ||
1699 | * We were successful. We won't be returning to our caller, but | ||
1700 | * instead to user space by manipulating the kernel stack. | ||
1701 | */ | ||
1702 | ret_from_kernel_execve(current_pt_regs()); | ||
1703 | } | ||
1704 | #endif | ||