diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 165 |
1 files changed, 46 insertions, 119 deletions
@@ -62,7 +62,6 @@ | |||
62 | 62 | ||
63 | #include <trace/events/task.h> | 63 | #include <trace/events/task.h> |
64 | #include "internal.h" | 64 | #include "internal.h" |
65 | #include "coredump.h" | ||
66 | 65 | ||
67 | #include <trace/events/sched.h> | 66 | #include <trace/events/sched.h> |
68 | 67 | ||
@@ -749,11 +748,10 @@ EXPORT_SYMBOL(setup_arg_pages); | |||
749 | 748 | ||
750 | #endif /* CONFIG_MMU */ | 749 | #endif /* CONFIG_MMU */ |
751 | 750 | ||
752 | struct file *open_exec(const char *name) | 751 | static struct file *do_open_exec(struct filename *name) |
753 | { | 752 | { |
754 | struct file *file; | 753 | struct file *file; |
755 | int err; | 754 | int err; |
756 | struct filename tmp = { .name = name }; | ||
757 | static const struct open_flags open_exec_flags = { | 755 | static const struct open_flags open_exec_flags = { |
758 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, | 756 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, |
759 | .acc_mode = MAY_EXEC | MAY_OPEN, | 757 | .acc_mode = MAY_EXEC | MAY_OPEN, |
@@ -761,7 +759,7 @@ struct file *open_exec(const char *name) | |||
761 | .lookup_flags = LOOKUP_FOLLOW, | 759 | .lookup_flags = LOOKUP_FOLLOW, |
762 | }; | 760 | }; |
763 | 761 | ||
764 | file = do_filp_open(AT_FDCWD, &tmp, &open_exec_flags); | 762 | file = do_filp_open(AT_FDCWD, name, &open_exec_flags); |
765 | if (IS_ERR(file)) | 763 | if (IS_ERR(file)) |
766 | goto out; | 764 | goto out; |
767 | 765 | ||
@@ -785,6 +783,12 @@ exit: | |||
785 | fput(file); | 783 | fput(file); |
786 | return ERR_PTR(err); | 784 | return ERR_PTR(err); |
787 | } | 785 | } |
786 | |||
787 | struct file *open_exec(const char *name) | ||
788 | { | ||
789 | struct filename tmp = { .name = name }; | ||
790 | return do_open_exec(&tmp); | ||
791 | } | ||
788 | EXPORT_SYMBOL(open_exec); | 792 | EXPORT_SYMBOL(open_exec); |
789 | 793 | ||
790 | int kernel_read(struct file *file, loff_t offset, | 794 | int kernel_read(struct file *file, loff_t offset, |
@@ -843,7 +847,6 @@ static int exec_mmap(struct mm_struct *mm) | |||
843 | tsk->active_mm = mm; | 847 | tsk->active_mm = mm; |
844 | activate_mm(active_mm, mm); | 848 | activate_mm(active_mm, mm); |
845 | task_unlock(tsk); | 849 | task_unlock(tsk); |
846 | arch_pick_mmap_layout(mm); | ||
847 | if (old_mm) { | 850 | if (old_mm) { |
848 | up_read(&old_mm->mmap_sem); | 851 | up_read(&old_mm->mmap_sem); |
849 | BUG_ON(active_mm != old_mm); | 852 | BUG_ON(active_mm != old_mm); |
@@ -1088,8 +1091,8 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
1088 | bprm->mm = NULL; /* We're using it now */ | 1091 | bprm->mm = NULL; /* We're using it now */ |
1089 | 1092 | ||
1090 | set_fs(USER_DS); | 1093 | set_fs(USER_DS); |
1091 | current->flags &= | 1094 | current->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | |
1092 | ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | PF_NOFREEZE); | 1095 | PF_NOFREEZE | PF_NO_SETAFFINITY); |
1093 | flush_thread(); | 1096 | flush_thread(); |
1094 | current->personality &= ~bprm->per_clear; | 1097 | current->personality &= ~bprm->per_clear; |
1095 | 1098 | ||
@@ -1139,9 +1142,7 @@ void setup_new_exec(struct linux_binprm * bprm) | |||
1139 | 1142 | ||
1140 | /* An exec changes our domain. We are no longer part of the thread | 1143 | /* An exec changes our domain. We are no longer part of the thread |
1141 | group */ | 1144 | group */ |
1142 | |||
1143 | current->self_exec_id++; | 1145 | current->self_exec_id++; |
1144 | |||
1145 | flush_signal_handlers(current, 0); | 1146 | flush_signal_handlers(current, 0); |
1146 | do_close_on_exec(current->files); | 1147 | do_close_on_exec(current->files); |
1147 | } | 1148 | } |
@@ -1166,13 +1167,17 @@ int prepare_bprm_creds(struct linux_binprm *bprm) | |||
1166 | return -ENOMEM; | 1167 | return -ENOMEM; |
1167 | } | 1168 | } |
1168 | 1169 | ||
1169 | void free_bprm(struct linux_binprm *bprm) | 1170 | static void free_bprm(struct linux_binprm *bprm) |
1170 | { | 1171 | { |
1171 | free_arg_pages(bprm); | 1172 | free_arg_pages(bprm); |
1172 | if (bprm->cred) { | 1173 | if (bprm->cred) { |
1173 | mutex_unlock(¤t->signal->cred_guard_mutex); | 1174 | mutex_unlock(¤t->signal->cred_guard_mutex); |
1174 | abort_creds(bprm->cred); | 1175 | abort_creds(bprm->cred); |
1175 | } | 1176 | } |
1177 | if (bprm->file) { | ||
1178 | allow_write_access(bprm->file); | ||
1179 | fput(bprm->file); | ||
1180 | } | ||
1176 | /* If a binfmt changed the interp, free it. */ | 1181 | /* If a binfmt changed the interp, free it. */ |
1177 | if (bprm->interp != bprm->filename) | 1182 | if (bprm->interp != bprm->filename) |
1178 | kfree(bprm->interp); | 1183 | kfree(bprm->interp); |
@@ -1224,11 +1229,10 @@ EXPORT_SYMBOL(install_exec_creds); | |||
1224 | * - the caller must hold ->cred_guard_mutex to protect against | 1229 | * - the caller must hold ->cred_guard_mutex to protect against |
1225 | * PTRACE_ATTACH | 1230 | * PTRACE_ATTACH |
1226 | */ | 1231 | */ |
1227 | static int check_unsafe_exec(struct linux_binprm *bprm) | 1232 | static void check_unsafe_exec(struct linux_binprm *bprm) |
1228 | { | 1233 | { |
1229 | struct task_struct *p = current, *t; | 1234 | struct task_struct *p = current, *t; |
1230 | unsigned n_fs; | 1235 | unsigned n_fs; |
1231 | int res = 0; | ||
1232 | 1236 | ||
1233 | if (p->ptrace) { | 1237 | if (p->ptrace) { |
1234 | if (p->ptrace & PT_PTRACE_CAP) | 1238 | if (p->ptrace & PT_PTRACE_CAP) |
@@ -1244,31 +1248,25 @@ static int check_unsafe_exec(struct linux_binprm *bprm) | |||
1244 | if (current->no_new_privs) | 1248 | if (current->no_new_privs) |
1245 | bprm->unsafe |= LSM_UNSAFE_NO_NEW_PRIVS; | 1249 | bprm->unsafe |= LSM_UNSAFE_NO_NEW_PRIVS; |
1246 | 1250 | ||
1251 | t = p; | ||
1247 | n_fs = 1; | 1252 | n_fs = 1; |
1248 | spin_lock(&p->fs->lock); | 1253 | spin_lock(&p->fs->lock); |
1249 | rcu_read_lock(); | 1254 | rcu_read_lock(); |
1250 | for (t = next_thread(p); t != p; t = next_thread(t)) { | 1255 | while_each_thread(p, t) { |
1251 | if (t->fs == p->fs) | 1256 | if (t->fs == p->fs) |
1252 | n_fs++; | 1257 | n_fs++; |
1253 | } | 1258 | } |
1254 | rcu_read_unlock(); | 1259 | rcu_read_unlock(); |
1255 | 1260 | ||
1256 | if (p->fs->users > n_fs) { | 1261 | if (p->fs->users > n_fs) |
1257 | bprm->unsafe |= LSM_UNSAFE_SHARE; | 1262 | bprm->unsafe |= LSM_UNSAFE_SHARE; |
1258 | } else { | 1263 | else |
1259 | res = -EAGAIN; | 1264 | p->fs->in_exec = 1; |
1260 | if (!p->fs->in_exec) { | ||
1261 | p->fs->in_exec = 1; | ||
1262 | res = 1; | ||
1263 | } | ||
1264 | } | ||
1265 | spin_unlock(&p->fs->lock); | 1265 | spin_unlock(&p->fs->lock); |
1266 | |||
1267 | return res; | ||
1268 | } | 1266 | } |
1269 | 1267 | ||
1270 | /* | 1268 | /* |
1271 | * Fill the binprm structure from the inode. | 1269 | * Fill the binprm structure from the inode. |
1272 | * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes | 1270 | * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes |
1273 | * | 1271 | * |
1274 | * This may be called multiple times for binary chains (scripts for example). | 1272 | * This may be called multiple times for binary chains (scripts for example). |
@@ -1430,14 +1428,7 @@ static int exec_binprm(struct linux_binprm *bprm) | |||
1430 | audit_bprm(bprm); | 1428 | audit_bprm(bprm); |
1431 | trace_sched_process_exec(current, old_pid, bprm); | 1429 | trace_sched_process_exec(current, old_pid, bprm); |
1432 | ptrace_event(PTRACE_EVENT_EXEC, old_vpid); | 1430 | ptrace_event(PTRACE_EVENT_EXEC, old_vpid); |
1433 | current->did_exec = 1; | ||
1434 | proc_exec_connector(current); | 1431 | proc_exec_connector(current); |
1435 | |||
1436 | if (bprm->file) { | ||
1437 | allow_write_access(bprm->file); | ||
1438 | fput(bprm->file); | ||
1439 | bprm->file = NULL; /* to catch use-after-free */ | ||
1440 | } | ||
1441 | } | 1432 | } |
1442 | 1433 | ||
1443 | return ret; | 1434 | return ret; |
@@ -1446,16 +1437,18 @@ static int exec_binprm(struct linux_binprm *bprm) | |||
1446 | /* | 1437 | /* |
1447 | * sys_execve() executes a new program. | 1438 | * sys_execve() executes a new program. |
1448 | */ | 1439 | */ |
1449 | static int do_execve_common(const char *filename, | 1440 | static int do_execve_common(struct filename *filename, |
1450 | struct user_arg_ptr argv, | 1441 | struct user_arg_ptr argv, |
1451 | struct user_arg_ptr envp) | 1442 | struct user_arg_ptr envp) |
1452 | { | 1443 | { |
1453 | struct linux_binprm *bprm; | 1444 | struct linux_binprm *bprm; |
1454 | struct file *file; | 1445 | struct file *file; |
1455 | struct files_struct *displaced; | 1446 | struct files_struct *displaced; |
1456 | bool clear_in_exec; | ||
1457 | int retval; | 1447 | int retval; |
1458 | 1448 | ||
1449 | if (IS_ERR(filename)) | ||
1450 | return PTR_ERR(filename); | ||
1451 | |||
1459 | /* | 1452 | /* |
1460 | * 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 |
1461 | * set*uid() to execve() because too many poorly written programs | 1454 | * set*uid() to execve() because too many poorly written programs |
@@ -1485,13 +1478,10 @@ static int do_execve_common(const char *filename, | |||
1485 | if (retval) | 1478 | if (retval) |
1486 | goto out_free; | 1479 | goto out_free; |
1487 | 1480 | ||
1488 | retval = check_unsafe_exec(bprm); | 1481 | check_unsafe_exec(bprm); |
1489 | if (retval < 0) | ||
1490 | goto out_free; | ||
1491 | clear_in_exec = retval; | ||
1492 | current->in_execve = 1; | 1482 | current->in_execve = 1; |
1493 | 1483 | ||
1494 | file = open_exec(filename); | 1484 | file = do_open_exec(filename); |
1495 | retval = PTR_ERR(file); | 1485 | retval = PTR_ERR(file); |
1496 | if (IS_ERR(file)) | 1486 | if (IS_ERR(file)) |
1497 | goto out_unmark; | 1487 | goto out_unmark; |
@@ -1499,12 +1489,11 @@ static int do_execve_common(const char *filename, | |||
1499 | sched_exec(); | 1489 | sched_exec(); |
1500 | 1490 | ||
1501 | bprm->file = file; | 1491 | bprm->file = file; |
1502 | bprm->filename = filename; | 1492 | bprm->filename = bprm->interp = filename->name; |
1503 | bprm->interp = filename; | ||
1504 | 1493 | ||
1505 | retval = bprm_mm_init(bprm); | 1494 | retval = bprm_mm_init(bprm); |
1506 | if (retval) | 1495 | if (retval) |
1507 | goto out_file; | 1496 | goto out_unmark; |
1508 | 1497 | ||
1509 | bprm->argc = count(argv, MAX_ARG_STRINGS); | 1498 | bprm->argc = count(argv, MAX_ARG_STRINGS); |
1510 | if ((retval = bprm->argc) < 0) | 1499 | if ((retval = bprm->argc) < 0) |
@@ -1541,6 +1530,7 @@ static int do_execve_common(const char *filename, | |||
1541 | acct_update_integrals(current); | 1530 | acct_update_integrals(current); |
1542 | task_numa_free(current); | 1531 | task_numa_free(current); |
1543 | free_bprm(bprm); | 1532 | free_bprm(bprm); |
1533 | putname(filename); | ||
1544 | if (displaced) | 1534 | if (displaced) |
1545 | put_files_struct(displaced); | 1535 | put_files_struct(displaced); |
1546 | return retval; | 1536 | return retval; |
@@ -1551,15 +1541,8 @@ out: | |||
1551 | mmput(bprm->mm); | 1541 | mmput(bprm->mm); |
1552 | } | 1542 | } |
1553 | 1543 | ||
1554 | out_file: | ||
1555 | if (bprm->file) { | ||
1556 | allow_write_access(bprm->file); | ||
1557 | fput(bprm->file); | ||
1558 | } | ||
1559 | |||
1560 | out_unmark: | 1544 | out_unmark: |
1561 | if (clear_in_exec) | 1545 | current->fs->in_exec = 0; |
1562 | current->fs->in_exec = 0; | ||
1563 | current->in_execve = 0; | 1546 | current->in_execve = 0; |
1564 | 1547 | ||
1565 | out_free: | 1548 | out_free: |
@@ -1569,10 +1552,11 @@ out_files: | |||
1569 | if (displaced) | 1552 | if (displaced) |
1570 | reset_files_struct(displaced); | 1553 | reset_files_struct(displaced); |
1571 | out_ret: | 1554 | out_ret: |
1555 | putname(filename); | ||
1572 | return retval; | 1556 | return retval; |
1573 | } | 1557 | } |
1574 | 1558 | ||
1575 | int do_execve(const char *filename, | 1559 | int do_execve(struct filename *filename, |
1576 | const char __user *const __user *__argv, | 1560 | const char __user *const __user *__argv, |
1577 | const char __user *const __user *__envp) | 1561 | const char __user *const __user *__envp) |
1578 | { | 1562 | { |
@@ -1582,7 +1566,7 @@ int do_execve(const char *filename, | |||
1582 | } | 1566 | } |
1583 | 1567 | ||
1584 | #ifdef CONFIG_COMPAT | 1568 | #ifdef CONFIG_COMPAT |
1585 | static int compat_do_execve(const char *filename, | 1569 | static int compat_do_execve(struct filename *filename, |
1586 | const compat_uptr_t __user *__argv, | 1570 | const compat_uptr_t __user *__argv, |
1587 | const compat_uptr_t __user *__envp) | 1571 | const compat_uptr_t __user *__envp) |
1588 | { | 1572 | { |
@@ -1609,67 +1593,22 @@ void set_binfmt(struct linux_binfmt *new) | |||
1609 | if (new) | 1593 | if (new) |
1610 | __module_get(new->module); | 1594 | __module_get(new->module); |
1611 | } | 1595 | } |
1612 | |||
1613 | EXPORT_SYMBOL(set_binfmt); | 1596 | EXPORT_SYMBOL(set_binfmt); |
1614 | 1597 | ||
1615 | /* | 1598 | /* |
1616 | * set_dumpable converts traditional three-value dumpable to two flags and | 1599 | * set_dumpable stores three-value SUID_DUMP_* into mm->flags. |
1617 | * stores them into mm->flags. It modifies lower two bits of mm->flags, but | ||
1618 | * these bits are not changed atomically. So get_dumpable can observe the | ||
1619 | * intermediate state. To avoid doing unexpected behavior, get get_dumpable | ||
1620 | * return either old dumpable or new one by paying attention to the order of | ||
1621 | * modifying the bits. | ||
1622 | * | ||
1623 | * dumpable | mm->flags (binary) | ||
1624 | * old new | initial interim final | ||
1625 | * ---------+----------------------- | ||
1626 | * 0 1 | 00 01 01 | ||
1627 | * 0 2 | 00 10(*) 11 | ||
1628 | * 1 0 | 01 00 00 | ||
1629 | * 1 2 | 01 11 11 | ||
1630 | * 2 0 | 11 10(*) 00 | ||
1631 | * 2 1 | 11 11 01 | ||
1632 | * | ||
1633 | * (*) get_dumpable regards interim value of 10 as 11. | ||
1634 | */ | 1600 | */ |
1635 | void set_dumpable(struct mm_struct *mm, int value) | 1601 | void set_dumpable(struct mm_struct *mm, int value) |
1636 | { | 1602 | { |
1637 | switch (value) { | 1603 | unsigned long old, new; |
1638 | case SUID_DUMP_DISABLE: | ||
1639 | clear_bit(MMF_DUMPABLE, &mm->flags); | ||
1640 | smp_wmb(); | ||
1641 | clear_bit(MMF_DUMP_SECURELY, &mm->flags); | ||
1642 | break; | ||
1643 | case SUID_DUMP_USER: | ||
1644 | set_bit(MMF_DUMPABLE, &mm->flags); | ||
1645 | smp_wmb(); | ||
1646 | clear_bit(MMF_DUMP_SECURELY, &mm->flags); | ||
1647 | break; | ||
1648 | case SUID_DUMP_ROOT: | ||
1649 | set_bit(MMF_DUMP_SECURELY, &mm->flags); | ||
1650 | smp_wmb(); | ||
1651 | set_bit(MMF_DUMPABLE, &mm->flags); | ||
1652 | break; | ||
1653 | } | ||
1654 | } | ||
1655 | 1604 | ||
1656 | int __get_dumpable(unsigned long mm_flags) | 1605 | if (WARN_ON((unsigned)value > SUID_DUMP_ROOT)) |
1657 | { | 1606 | return; |
1658 | int ret; | ||
1659 | |||
1660 | ret = mm_flags & MMF_DUMPABLE_MASK; | ||
1661 | return (ret > SUID_DUMP_USER) ? SUID_DUMP_ROOT : ret; | ||
1662 | } | ||
1663 | 1607 | ||
1664 | /* | 1608 | do { |
1665 | * This returns the actual value of the suid_dumpable flag. For things | 1609 | old = ACCESS_ONCE(mm->flags); |
1666 | * that are using this for checking for privilege transitions, it must | 1610 | new = (old & ~MMF_DUMPABLE_MASK) | value; |
1667 | * test against SUID_DUMP_USER rather than treating it as a boolean | 1611 | } while (cmpxchg(&mm->flags, old, new) != old); |
1668 | * value. | ||
1669 | */ | ||
1670 | int get_dumpable(struct mm_struct *mm) | ||
1671 | { | ||
1672 | return __get_dumpable(mm->flags); | ||
1673 | } | 1612 | } |
1674 | 1613 | ||
1675 | SYSCALL_DEFINE3(execve, | 1614 | SYSCALL_DEFINE3(execve, |
@@ -1677,25 +1616,13 @@ SYSCALL_DEFINE3(execve, | |||
1677 | const char __user *const __user *, argv, | 1616 | const char __user *const __user *, argv, |
1678 | const char __user *const __user *, envp) | 1617 | const char __user *const __user *, envp) |
1679 | { | 1618 | { |
1680 | struct filename *path = getname(filename); | 1619 | return do_execve(getname(filename), argv, envp); |
1681 | int error = PTR_ERR(path); | ||
1682 | if (!IS_ERR(path)) { | ||
1683 | error = do_execve(path->name, argv, envp); | ||
1684 | putname(path); | ||
1685 | } | ||
1686 | return error; | ||
1687 | } | 1620 | } |
1688 | #ifdef CONFIG_COMPAT | 1621 | #ifdef CONFIG_COMPAT |
1689 | asmlinkage long compat_sys_execve(const char __user * filename, | 1622 | asmlinkage long compat_sys_execve(const char __user * filename, |
1690 | const compat_uptr_t __user * argv, | 1623 | const compat_uptr_t __user * argv, |
1691 | const compat_uptr_t __user * envp) | 1624 | const compat_uptr_t __user * envp) |
1692 | { | 1625 | { |
1693 | struct filename *path = getname(filename); | 1626 | return compat_do_execve(getname(filename), argv, envp); |
1694 | int error = PTR_ERR(path); | ||
1695 | if (!IS_ERR(path)) { | ||
1696 | error = compat_do_execve(path->name, argv, envp); | ||
1697 | putname(path); | ||
1698 | } | ||
1699 | return error; | ||
1700 | } | 1627 | } |
1701 | #endif | 1628 | #endif |