mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
coredump masking: reimplementation of dumpable using two flags
This patch changes mm_struct.dumpable to a pair of bit flags. set_dumpable() converts three-value dumpable to two flags and stores it into lower two bits of mm_struct.flags instead of mm_struct.dumpable. get_dumpable() behaves in the opposite way. [[email protected]: export set_dumpable] Signed-off-by: Hidehiro Kawai <[email protected]> Cc: Alan Cox <[email protected]> Cc: David Howells <[email protected]> Cc: Hugh Dickins <[email protected]> Cc: Nick Piggin <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
parent
76fdbb25f9
commit
6c5d523826
8 changed files with 82 additions and 25 deletions
62
fs/exec.c
62
fs/exec.c
|
|
@ -1058,9 +1058,9 @@ int flush_old_exec(struct linux_binprm * bprm)
|
|||
current->sas_ss_sp = current->sas_ss_size = 0;
|
||||
|
||||
if (current->euid == current->uid && current->egid == current->gid)
|
||||
current->mm->dumpable = 1;
|
||||
set_dumpable(current->mm, 1);
|
||||
else
|
||||
current->mm->dumpable = suid_dumpable;
|
||||
set_dumpable(current->mm, suid_dumpable);
|
||||
|
||||
name = bprm->filename;
|
||||
|
||||
|
|
@ -1088,7 +1088,7 @@ int flush_old_exec(struct linux_binprm * bprm)
|
|||
file_permission(bprm->file, MAY_READ) ||
|
||||
(bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) {
|
||||
suid_keys(current);
|
||||
current->mm->dumpable = suid_dumpable;
|
||||
set_dumpable(current->mm, suid_dumpable);
|
||||
}
|
||||
|
||||
/* An exec changes our domain. We are no longer part of the thread
|
||||
|
|
@ -1665,6 +1665,56 @@ fail:
|
|||
return core_waiters;
|
||||
}
|
||||
|
||||
/*
|
||||
* set_dumpable converts traditional three-value dumpable to two flags and
|
||||
* stores them into mm->flags. It modifies lower two bits of mm->flags, but
|
||||
* these bits are not changed atomically. So get_dumpable can observe the
|
||||
* intermediate state. To avoid doing unexpected behavior, get get_dumpable
|
||||
* return either old dumpable or new one by paying attention to the order of
|
||||
* modifying the bits.
|
||||
*
|
||||
* dumpable | mm->flags (binary)
|
||||
* old new | initial interim final
|
||||
* ---------+-----------------------
|
||||
* 0 1 | 00 01 01
|
||||
* 0 2 | 00 10(*) 11
|
||||
* 1 0 | 01 00 00
|
||||
* 1 2 | 01 11 11
|
||||
* 2 0 | 11 10(*) 00
|
||||
* 2 1 | 11 11 01
|
||||
*
|
||||
* (*) get_dumpable regards interim value of 10 as 11.
|
||||
*/
|
||||
void set_dumpable(struct mm_struct *mm, int value)
|
||||
{
|
||||
switch (value) {
|
||||
case 0:
|
||||
clear_bit(MMF_DUMPABLE, &mm->flags);
|
||||
smp_wmb();
|
||||
clear_bit(MMF_DUMP_SECURELY, &mm->flags);
|
||||
break;
|
||||
case 1:
|
||||
set_bit(MMF_DUMPABLE, &mm->flags);
|
||||
smp_wmb();
|
||||
clear_bit(MMF_DUMP_SECURELY, &mm->flags);
|
||||
break;
|
||||
case 2:
|
||||
set_bit(MMF_DUMP_SECURELY, &mm->flags);
|
||||
smp_wmb();
|
||||
set_bit(MMF_DUMPABLE, &mm->flags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(set_dumpable);
|
||||
|
||||
int get_dumpable(struct mm_struct *mm)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mm->flags & 0x3;
|
||||
return (ret >= 2) ? 2 : ret;
|
||||
}
|
||||
|
||||
int do_coredump(long signr, int exit_code, struct pt_regs * regs)
|
||||
{
|
||||
char corename[CORENAME_MAX_SIZE + 1];
|
||||
|
|
@ -1683,7 +1733,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
|
|||
if (!binfmt || !binfmt->core_dump)
|
||||
goto fail;
|
||||
down_write(&mm->mmap_sem);
|
||||
if (!mm->dumpable) {
|
||||
if (!get_dumpable(mm)) {
|
||||
up_write(&mm->mmap_sem);
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -1693,11 +1743,11 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
|
|||
* process nor do we know its entire history. We only know it
|
||||
* was tainted so we dump it as root in mode 2.
|
||||
*/
|
||||
if (mm->dumpable == 2) { /* Setuid core dump mode */
|
||||
if (get_dumpable(mm) == 2) { /* Setuid core dump mode */
|
||||
flag = O_EXCL; /* Stop rewrite attacks */
|
||||
current->fsuid = 0; /* Dump root private */
|
||||
}
|
||||
mm->dumpable = 0;
|
||||
set_dumpable(mm, 0);
|
||||
|
||||
retval = coredump_wait(exit_code);
|
||||
if (retval < 0)
|
||||
|
|
|
|||
Loading…
Reference in a new issue