diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/exec.c | 23 | ||||
-rw-r--r-- | fs/proc/base.c | 6 |
2 files changed, 25 insertions, 4 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; |
diff --git a/fs/proc/base.c b/fs/proc/base.c index e31903aadd96..ace151fa4878 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -314,7 +314,7 @@ static int may_ptrace_attach(struct task_struct *task) | |||
314 | (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) | 314 | (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) |
315 | goto out; | 315 | goto out; |
316 | rmb(); | 316 | rmb(); |
317 | if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE)) | 317 | if (task->mm->dumpable != 1 && !capable(CAP_SYS_PTRACE)) |
318 | goto out; | 318 | goto out; |
319 | if (security_ptrace(current, task)) | 319 | if (security_ptrace(current, task)) |
320 | goto out; | 320 | goto out; |
@@ -1113,7 +1113,9 @@ static int task_dumpable(struct task_struct *task) | |||
1113 | if (mm) | 1113 | if (mm) |
1114 | dumpable = mm->dumpable; | 1114 | dumpable = mm->dumpable; |
1115 | task_unlock(task); | 1115 | task_unlock(task); |
1116 | return dumpable; | 1116 | if(dumpable == 1) |
1117 | return 1; | ||
1118 | return 0; | ||
1117 | } | 1119 | } |
1118 | 1120 | ||
1119 | 1121 | ||