[PATCH] Capability theft prevention

Topi Miettinen (Topi.Miettinen@medialab.sonera.fi)
Sun, 07 Mar 1999 21:20:23 +0200


This patch should prevent processes with less capabilities but with same
uid from messing with more capable processes. It would seem that
/proc/#/mem is protected from attack because of the ptracing requirement.
Indirect attacks will still be successful, for example through file system,
IPC etc, but fixing those are beyond my skills.

I hope I got the logic right, de Morgan and double negatives suck.

-Topi

diff -ru ./arch/i386/kernel/ptrace.c.orig ./arch/i386/kernel/ptrace.c
--- ./arch/i386/kernel/ptrace.c.orig Sat Mar 6 23:00:50 1999
+++ ./arch/i386/kernel/ptrace.c Sun Mar 7 20:39:50 1999
@@ -380,13 +380,15 @@
if (request == PTRACE_ATTACH) {
if (child == current)
goto out;
- if ((!child->dumpable ||
+ if (((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
- (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+ (current->gid != child->gid)) &&
+ !capable(CAP_SYS_PTRACE)) ||
+ !cap_issubset(child->cap_permitted, current->cap_permitted))
goto out;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
diff -ru ./arch/alpha/kernel/ptrace.c.orig ./arch/alpha/kernel/ptrace.c
--- ./arch/alpha/kernel/ptrace.c.orig Wed Dec 30 02:17:00 1998
+++ ./arch/alpha/kernel/ptrace.c Sun Mar 7 20:39:27 1999
@@ -500,14 +500,15 @@
ret = -EPERM;
if (child == current)
goto out;
- if ((!child->dumpable ||
+ if (((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
- (current->gid != child->gid))
- && !capable(CAP_SYS_PTRACE))
+ (current->gid != child->gid)) &&
+ !capable(CAP_SYS_PTRACE)) ||
+ !cap_issubset(child->cap_permitted, current->cap_permitted))
goto out;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
diff -ru ./arch/sparc/kernel/ptrace.c.orig ./arch/sparc/kernel/ptrace.c
--- ./arch/sparc/kernel/ptrace.c.orig Wed Dec 30 02:35:08 1998
+++ ./arch/sparc/kernel/ptrace.c Sun Mar 7 20:40:31 1999
@@ -535,12 +535,13 @@
pt_error_return(regs, EPERM);
goto out;
}
- if((!child->dumpable ||
+ if(((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
- (current->gid != child->gid)) &&
- !capable(CAP_SYS_PTRACE)) {
+ (current->gid != child->gid)) &&
+ !capable(CAP_SYS_PTRACE)) ||
+ !cap_issubset(child->cap_permitted, current->cap_permitted)) {
pt_error_return(regs, EPERM);
goto out;
}
diff -ru ./arch/mips/kernel/ptrace.c.orig ./arch/mips/kernel/ptrace.c
--- ./arch/mips/kernel/ptrace.c.orig Tue Oct 20 23:52:54 1998
+++ ./arch/mips/kernel/ptrace.c Sun Mar 7 20:40:10 1999
@@ -291,14 +291,15 @@
res = -EPERM;
goto out;
}
- if ((!child->dumpable ||
+ if (((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
- (current->gid != child->gid)) &&
- !capable(CAP_SYS_PTRACE)) {
+ (current->gid != child->gid)) &&
+ !capable(CAP_SYS_PTRACE)) ||
+ !cap_issubset(child->cap_permitted, current->cap_permitted)) {
res = -EPERM;
goto out;
}
diff -ru ./arch/ppc/kernel/ptrace.c.orig ./arch/ppc/kernel/ptrace.c
--- ./arch/ppc/kernel/ptrace.c.orig Wed Dec 30 02:32:36 1998
+++ ./arch/ppc/kernel/ptrace.c Sun Mar 7 20:40:21 1999
@@ -327,11 +327,13 @@
if (request == PTRACE_ATTACH) {
if (child == current)
goto out;
- if ((!child->dumpable ||
+ if (((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
- (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+ (current->gid != child->gid)) &&
+ !capable(CAP_SYS_PTRACE)) ||
+ !cap_issubset(child->cap_permitted, current->cap_permitted))
goto out;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
diff -ru ./arch/m68k/kernel/ptrace.c.orig ./arch/m68k/kernel/ptrace.c
--- ./arch/m68k/kernel/ptrace.c.orig Tue Jan 19 20:58:34 1999
+++ ./arch/m68k/kernel/ptrace.c Sun Mar 7 20:40:01 1999
@@ -337,13 +337,15 @@
if (request == PTRACE_ATTACH) {
if (child == current)
goto out;
- if ((!child->dumpable ||
+ if (((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
- (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+ (current->gid != child->gid)) &&
+ !capable(CAP_SYS_PTRACE)) ||
+ !cap_issubset(child->cap_permitted, current->cap_permitted))
goto out;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
diff -ru ./arch/sparc64/kernel/ptrace.c.orig ./arch/sparc64/kernel/ptrace.c
--- ./arch/sparc64/kernel/ptrace.c.orig Tue Oct 27 19:52:20 1998
+++ ./arch/sparc64/kernel/ptrace.c Sun Mar 7 20:46:20 1999
@@ -598,12 +598,13 @@
pt_error_return(regs, EPERM);
goto out;
}
- if((!child->dumpable ||
+ if(((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
- (current->gid != child->gid)) &&
- !capable(CAP_SYS_PTRACE)) {
+ (current->gid != child->gid)) &&
+ !capable(CAP_SYS_PTRACE)) ||
+ !cap_issubset(child->cap_permitted, current->cap_permitted)) {
pt_error_return(regs, EPERM);
goto out;
}
diff -ru ./arch/arm/kernel/ptrace.c.orig ./arch/arm/kernel/ptrace.c
--- ./arch/arm/kernel/ptrace.c.orig Wed Sep 9 18:56:58 1998
+++ ./arch/arm/kernel/ptrace.c Sun Mar 7 20:39:39 1999
@@ -574,13 +574,15 @@
if (request == PTRACE_ATTACH) {
if (child == current)
goto out;
- if ((!child->dumpable ||
+ if (((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
- (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+ (current->gid != child->gid)) &&
+ !capable(CAP_SYS_PTRACE)) ||
+ !cap_issubset(child->cap_permitted, current->cap_permitted))
goto out;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
diff -ru ./kernel/sched.c.orig ./kernel/sched.c
--- ./kernel/sched.c.orig Fri Feb 19 09:56:05 1999
+++ ./kernel/sched.c Sun Mar 7 20:44:09 1999
@@ -1657,8 +1657,9 @@
if ((policy == SCHED_FIFO || policy == SCHED_RR) &&
!capable(CAP_SYS_NICE))
goto out_unlock;
- if ((current->euid != p->euid) && (current->euid != p->uid) &&
- !capable(CAP_SYS_NICE))
+ if (((current->euid != p->euid) && (current->euid != p->uid) &&
+ !capable(CAP_SYS_NICE)) ||
+ !cap_issubset(p->cap_permitted, current->cap_permitted))
goto out_unlock;

retval = 0;
diff -ru ./kernel/sys.c.orig ./kernel/sys.c
--- ./kernel/sys.c.orig Fri Nov 20 21:43:19 1998
+++ ./kernel/sys.c Sun Mar 7 20:44:05 1999
@@ -99,8 +99,9 @@
for_each_task(p) {
if (!proc_sel(p, which, who))
continue;
- if (p->uid != current->euid &&
- p->uid != current->uid && !capable(CAP_SYS_NICE)) {
+ if ((p->uid != current->euid &&
+ p->uid != current->uid && !capable(CAP_SYS_NICE)) ||
+ !cap_issubset(p->cap_permitted, current->cap_permitted)) {
error = EPERM;
continue;
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/