Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 2950
b: refs/heads/master
c: d6e7114
h: refs/heads/master
v: v3
  • Loading branch information
Alan Cox authored and Linus Torvalds committed Jun 23, 2005
1 parent 85e23aa commit 8d8d49b
Show file tree
Hide file tree
Showing 11 changed files with 75 additions and 19 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8b0914ea7475615c7c8965c1ac8fe4069270f25c
refs/heads/master: d6e711448137ca3301512cec41a2c2ce852b3d0a
20 changes: 20 additions & 0 deletions trunk/Documentation/sysctl/kernel.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ show up in /proc/sys/kernel:
- shmmax [ sysv ipc ]
- shmmni
- stop-a [ SPARC only ]
- suid_dumpable
- sysrq ==> Documentation/sysrq.txt
- tainted
- threads-max
Expand Down Expand Up @@ -300,6 +301,25 @@ kernel. This value defaults to SHMMAX.

==============================================================

suid_dumpable:

This value can be used to query and set the core dump mode for setuid
or otherwise protected/tainted binaries. The modes are

0 - (default) - traditional behaviour. Any process which has changed
privilege levels or is execute only will not be dumped
1 - (debug) - all processes dump core when possible. The core dump is
owned by the current user and no security is applied. This is
intended for system debugging situations only. Ptrace is unchecked.
2 - (suidsafe) - any binary which normally would not be dumped is dumped
readable by root only. This allows the end user to remove
such a dump but not access it directly. For security reasons
core dumps in this mode will not overwrite one another or
other files. This mode is appropriate when adminstrators are
attempting to debug problems in a normal environment.

==============================================================

tainted:

Non-zero if the kernel has been tainted. Numeric values, which
Expand Down
23 changes: 21 additions & 2 deletions trunk/fs/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@

int core_uses_pid;
char core_pattern[65] = "core";
int suid_dumpable = 0;

EXPORT_SYMBOL(suid_dumpable);
/* The maximal length of core_pattern is also specified in sysctl.c */

static struct linux_binfmt *formats;
Expand Down Expand Up @@ -864,6 +867,9 @@ int flush_old_exec(struct linux_binprm * bprm)

if (current->euid == current->uid && current->egid == current->gid)
current->mm->dumpable = 1;
else
current->mm->dumpable = suid_dumpable;

name = bprm->filename;

/* Copies the binary name from after last slash */
Expand All @@ -884,7 +890,7 @@ int flush_old_exec(struct linux_binprm * bprm)
permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL) ||
(bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) {
suid_keys(current);
current->mm->dumpable = 0;
current->mm->dumpable = suid_dumpable;
}

/* An exec changes our domain. We are no longer part of the thread
Expand Down Expand Up @@ -1432,6 +1438,8 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
struct inode * inode;
struct file * file;
int retval = 0;
int fsuid = current->fsuid;
int flag = 0;

binfmt = current->binfmt;
if (!binfmt || !binfmt->core_dump)
Expand All @@ -1441,6 +1449,16 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
up_write(&mm->mmap_sem);
goto fail;
}

/*
* We cannot trust fsuid as being the "true" uid of the
* 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 */
flag = O_EXCL; /* Stop rewrite attacks */
current->fsuid = 0; /* Dump root private */
}
mm->dumpable = 0;
init_completion(&mm->core_done);
spin_lock_irq(&current->sighand->siglock);
Expand All @@ -1466,7 +1484,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
lock_kernel();
format_corename(corename, core_pattern, signr);
unlock_kernel();
file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE, 0600);
file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, 0600);
if (IS_ERR(file))
goto fail_unlock;
inode = file->f_dentry->d_inode;
Expand All @@ -1491,6 +1509,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
close_fail:
filp_close(file, NULL);
fail_unlock:
current->fsuid = fsuid;
complete_all(&mm->core_done);
fail:
return retval;
Expand Down
6 changes: 4 additions & 2 deletions trunk/fs/proc/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ static int may_ptrace_attach(struct task_struct *task)
(current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
goto out;
rmb();
if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
if (task->mm->dumpable != 1 && !capable(CAP_SYS_PTRACE))
goto out;
if (security_ptrace(current, task))
goto out;
Expand Down Expand Up @@ -1113,7 +1113,9 @@ static int task_dumpable(struct task_struct *task)
if (mm)
dumpable = mm->dumpable;
task_unlock(task);
return dumpable;
if(dumpable == 1)
return 1;
return 0;
}


Expand Down
5 changes: 5 additions & 0 deletions trunk/include/linux/binfmts.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ extern void remove_arg_zero(struct linux_binprm *);
extern int search_binary_handler(struct linux_binprm *,struct pt_regs *);
extern int flush_old_exec(struct linux_binprm * bprm);

extern int suid_dumpable;
#define SUID_DUMP_DISABLE 0 /* No setuid dumping */
#define SUID_DUMP_USER 1 /* Dump as user of process */
#define SUID_DUMP_ROOT 2 /* Dump as root */

/* Stack area protections */
#define EXSTACK_DEFAULT 0 /* Whatever the arch defaults to */
#define EXSTACK_DISABLE_X 1 /* Disable executable stacks */
Expand Down
2 changes: 1 addition & 1 deletion trunk/include/linux/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ struct mm_struct {

unsigned long saved_auxv[42]; /* for /proc/PID/auxv */

unsigned dumpable:1;
unsigned dumpable:2;
cpumask_t cpu_vm_mask;

/* Architecture-specific MM context */
Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/sysctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ enum
KERN_UNKNOWN_NMI_PANIC=66, /* int: unknown nmi panic flag */
KERN_BOOTLOADER_TYPE=67, /* int: boot loader type */
KERN_RANDOMIZE=68, /* int: randomize virtual address space */
KERN_SETUID_DUMPABLE=69, /* int: behaviour of dumps for setuid core */
};


Expand Down
22 changes: 11 additions & 11 deletions trunk/kernel/sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
}
if (new_egid != old_egid)
{
current->mm->dumpable = 0;
current->mm->dumpable = suid_dumpable;
smp_wmb();
}
if (rgid != (gid_t) -1 ||
Expand Down Expand Up @@ -556,7 +556,7 @@ asmlinkage long sys_setgid(gid_t gid)
{
if(old_egid != gid)
{
current->mm->dumpable=0;
current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->gid = current->egid = current->sgid = current->fsgid = gid;
Expand All @@ -565,7 +565,7 @@ asmlinkage long sys_setgid(gid_t gid)
{
if(old_egid != gid)
{
current->mm->dumpable=0;
current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->egid = current->fsgid = gid;
Expand Down Expand Up @@ -596,7 +596,7 @@ static int set_user(uid_t new_ruid, int dumpclear)

if(dumpclear)
{
current->mm->dumpable = 0;
current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->uid = new_ruid;
Expand Down Expand Up @@ -653,7 +653,7 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)

if (new_euid != old_euid)
{
current->mm->dumpable=0;
current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->fsuid = current->euid = new_euid;
Expand Down Expand Up @@ -703,7 +703,7 @@ asmlinkage long sys_setuid(uid_t uid)

if (old_euid != uid)
{
current->mm->dumpable = 0;
current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->fsuid = current->euid = uid;
Expand Down Expand Up @@ -748,7 +748,7 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
if (euid != (uid_t) -1) {
if (euid != current->euid)
{
current->mm->dumpable = 0;
current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->euid = euid;
Expand Down Expand Up @@ -798,7 +798,7 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
if (egid != (gid_t) -1) {
if (egid != current->egid)
{
current->mm->dumpable = 0;
current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->egid = egid;
Expand Down Expand Up @@ -845,7 +845,7 @@ asmlinkage long sys_setfsuid(uid_t uid)
{
if (uid != old_fsuid)
{
current->mm->dumpable = 0;
current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->fsuid = uid;
Expand Down Expand Up @@ -875,7 +875,7 @@ asmlinkage long sys_setfsgid(gid_t gid)
{
if (gid != old_fsgid)
{
current->mm->dumpable = 0;
current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->fsgid = gid;
Expand Down Expand Up @@ -1652,7 +1652,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
error = 1;
break;
case PR_SET_DUMPABLE:
if (arg2 != 0 && arg2 != 1) {
if (arg2 < 0 || arg2 > 2) {
error = -EINVAL;
break;
}
Expand Down
9 changes: 9 additions & 0 deletions trunk/kernel/sysctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ extern int sysctl_overcommit_ratio;
extern int max_threads;
extern int sysrq_enabled;
extern int core_uses_pid;
extern int suid_dumpable;
extern char core_pattern[];
extern int cad_pid;
extern int pid_max;
Expand Down Expand Up @@ -950,6 +951,14 @@ static ctl_table fs_table[] = {
.proc_handler = &proc_dointvec,
},
#endif
{
.ctl_name = KERN_SETUID_DUMPABLE,
.procname = "suid_dumpable",
.data = &suid_dumpable,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{ .ctl_name = 0 }
};

Expand Down
2 changes: 1 addition & 1 deletion trunk/security/commoncap.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)

if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
!cap_issubset (new_permitted, current->cap_permitted)) {
current->mm->dumpable = 0;
current->mm->dumpable = suid_dumpable;

if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
if (!capable(CAP_SETUID)) {
Expand Down
2 changes: 1 addition & 1 deletion trunk/security/dummy.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ static void dummy_bprm_free_security (struct linux_binprm *bprm)
static void dummy_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
{
if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
current->mm->dumpable = 0;
current->mm->dumpable = suid_dumpable;

if ((unsafe & ~LSM_UNSAFE_PTRACE_CAP) && !capable(CAP_SETUID)) {
bprm->e_uid = current->uid;
Expand Down

0 comments on commit 8d8d49b

Please sign in to comment.