diff options
Diffstat (limited to 'fs/exec.c')
| -rw-r--r-- | fs/exec.c | 23 |
1 files changed, 21 insertions, 2 deletions
| @@ -58,6 +58,9 @@ | |||
| 58 | 58 | ||
| 59 | int core_uses_pid; | 59 | int core_uses_pid; |
| 60 | char core_pattern[65] = "core"; | 60 | char core_pattern[65] = "core"; |
| 61 | int suid_dumpable = 0; | ||
| 62 | |||
| 63 | EXPORT_SYMBOL(suid_dumpable); | ||
| 61 | /* The maximal length of core_pattern is also specified in sysctl.c */ | 64 | /* The maximal length of core_pattern is also specified in sysctl.c */ |
| 62 | 65 | ||
| 63 | static struct linux_binfmt *formats; | 66 | static struct linux_binfmt *formats; |
| @@ -864,6 +867,9 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
| 864 | 867 | ||
| 865 | if (current->euid == current->uid && current->egid == current->gid) | 868 | if (current->euid == current->uid && current->egid == current->gid) |
| 866 | current->mm->dumpable = 1; | 869 | current->mm->dumpable = 1; |
| 870 | else | ||
| 871 | current->mm->dumpable = suid_dumpable; | ||
| 872 | |||
| 867 | name = bprm->filename; | 873 | name = bprm->filename; |
| 868 | 874 | ||
| 869 | /* Copies the binary name from after last slash */ | 875 | /* Copies the binary name from after last slash */ |
| @@ -884,7 +890,7 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
| 884 | permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL) || | 890 | permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL) || |
| 885 | (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) { | 891 | (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) { |
| 886 | suid_keys(current); | 892 | suid_keys(current); |
| 887 | current->mm->dumpable = 0; | 893 | current->mm->dumpable = suid_dumpable; |
| 888 | } | 894 | } |
| 889 | 895 | ||
| 890 | /* An exec changes our domain. We are no longer part of the thread | 896 | /* An exec changes our domain. We are no longer part of the thread |
| @@ -1432,6 +1438,8 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
| 1432 | struct inode * inode; | 1438 | struct inode * inode; |
| 1433 | struct file * file; | 1439 | struct file * file; |
| 1434 | int retval = 0; | 1440 | int retval = 0; |
| 1441 | int fsuid = current->fsuid; | ||
| 1442 | int flag = 0; | ||
| 1435 | 1443 | ||
| 1436 | binfmt = current->binfmt; | 1444 | binfmt = current->binfmt; |
| 1437 | if (!binfmt || !binfmt->core_dump) | 1445 | if (!binfmt || !binfmt->core_dump) |
| @@ -1441,6 +1449,16 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
| 1441 | up_write(&mm->mmap_sem); | 1449 | up_write(&mm->mmap_sem); |
| 1442 | goto fail; | 1450 | goto fail; |
| 1443 | } | 1451 | } |
| 1452 | |||
| 1453 | /* | ||
| 1454 | * We cannot trust fsuid as being the "true" uid of the | ||
| 1455 | * process nor do we know its entire history. We only know it | ||
| 1456 | * was tainted so we dump it as root in mode 2. | ||
| 1457 | */ | ||
| 1458 | if (mm->dumpable == 2) { /* Setuid core dump mode */ | ||
| 1459 | flag = O_EXCL; /* Stop rewrite attacks */ | ||
| 1460 | current->fsuid = 0; /* Dump root private */ | ||
| 1461 | } | ||
| 1444 | mm->dumpable = 0; | 1462 | mm->dumpable = 0; |
| 1445 | init_completion(&mm->core_done); | 1463 | init_completion(&mm->core_done); |
| 1446 | spin_lock_irq(¤t->sighand->siglock); | 1464 | spin_lock_irq(¤t->sighand->siglock); |
| @@ -1466,7 +1484,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
| 1466 | lock_kernel(); | 1484 | lock_kernel(); |
| 1467 | format_corename(corename, core_pattern, signr); | 1485 | format_corename(corename, core_pattern, signr); |
| 1468 | unlock_kernel(); | 1486 | unlock_kernel(); |
| 1469 | file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE, 0600); | 1487 | file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, 0600); |
| 1470 | if (IS_ERR(file)) | 1488 | if (IS_ERR(file)) |
| 1471 | goto fail_unlock; | 1489 | goto fail_unlock; |
| 1472 | inode = file->f_dentry->d_inode; | 1490 | inode = file->f_dentry->d_inode; |
| @@ -1491,6 +1509,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
| 1491 | close_fail: | 1509 | close_fail: |
| 1492 | filp_close(file, NULL); | 1510 | filp_close(file, NULL); |
| 1493 | fail_unlock: | 1511 | fail_unlock: |
| 1512 | current->fsuid = fsuid; | ||
| 1494 | complete_all(&mm->core_done); | 1513 | complete_all(&mm->core_done); |
| 1495 | fail: | 1514 | fail: |
| 1496 | return retval; | 1515 | return retval; |
