diff -urP linux-2.2.20-ow1/Documentation/Configure.help linux-2.2.20-hap-2/Documentation/Configure.help --- linux-2.2.20-ow1/Documentation/Configure.help Sat Nov 3 13:14:57 2001 +++ linux-2.2.20-hap-2/Documentation/Configure.help Fri Nov 9 19:16:17 2001 @@ -15291,6 +15291,17 @@ same as that of the directory or the FIFO is opened without the O_CREAT flag. +Allow links/pipes in non-world-writable +t dirs +CONFIG_SECURE_NOTSOMUCH + This makes the checks that CONFIG_SECURE_LINK and CONFIG_SECURE_PIPE + perform a little less restrictive. Namely, links/pipes will work + again in +t directories if the directory is not world-writable. Most + sticky directories (such as /tmp) *are* world-writable, but you may + have other +t directories which are not (to make safe group-writable + shared upload directories, for instance). Say Y only if you have had + problems using the CONFIG_SECURE_LINK or CONFIG_SECURE_PIPE options + and you think you need this. + Restricted /proc CONFIG_SECURE_PROC This option restricts the permissions on directories in /proc so @@ -15302,6 +15313,13 @@ disables dmesg(8) for the users. You might want to use this on an ISP shell server where privacy is an issue. +Unofficial bugfixes +CONFIG_SECURE_BUGFIX + Currently this fixes the following bug: + * stracing an unreadable binary (ie mode 111). Note that there + are still ways to get around this at least on x86. + Say Y here unless you know you shouldn't. + Special handling of fd 0, 1, and 2 CONFIG_SECURE_FD_0_1_2 File descriptors 0, 1, and 2 have a special meaning for the C library @@ -15343,6 +15361,102 @@ Note that this feature will do you no good unless you also configure your resource limits (in particular, RLIMIT_AS and RLIMIT_NPROC). Most systems don't need this. + +Extra logging of unusual events +CONFIG_SECURE_LOGGING + This turns on some extra kernel logging. Right now this includes: + * some extra verbosity in the network layer (reporting about arp cache + changes, and complaining if someone tries to route through us and + we're not a router) + * also causes some packets that used to be dropped silently to get + whined about + * logs of who/what/when the system time changes + * logs when/why forks fail + * logs certain "lethal" signals: SIGSEGV, SIGBUS, SIGABRT, SIGILL + This is of limited use, and has some extra overhead, but isn't likely + to cause any problems. + +Paranoid networking +CONFIG_SECURE_NETWORK + This turns on some extra paranoia in tcp and udp net code. + Currently it does (or tries to): + * warns on packets to unserved UDP ports + * warns on packets to unserved TCP ports + * optionally, denies such packets (CONFIG_SECURE_NET_SBD) + * warns & denies TCP packets with invalid combinations of flags + * adds extra info to all IPFW log lines: + * length of TCP & data / UDP as well as IP length + * print TCP ACK and SEQ numbers in addition to IP ids + * prints all TCP flags set (Syn, Ack, Fin, Urg, etc) + It also hopefully banishes a longstanding bug with IPFW/IPchains + log printing when under heavy IO, where different printk'ed lines + step on each other/get truncated, etc. + Say Y unless you think it's breaking stuff (or you don't want the + log volume, which will be high on a busy server). + +Blackhole networking +CONFIG_SECURE_NET_SBD + When CONFIG_SECURE_NETWORK is enabled, this disables the usual + behavior of responding to unsolicited/"unserved" TCP packets with + a TCP RST, and to unserved UDP packets with an ICMP port-unreach. + Note that the UDP behavior is superfluous (can be easily done with + ipchains rules) but there's no convenient, desirable way to block + the RSTs other than this. This is recommended for personal systems + and low-volume servers. However, it is rude and breaks RFCs, so + it should be left off (the default behavior) for most systems, + unless you are *really* paranoid. + +Restricted chroot +CONFIG_SECURE_CHROOT + This causes chroot processes to be a bit more restricted. Processes + which are already in a chroot(2)ed jail now cannot: + * chroot(2) again + * mknod(2) a character or block device + * mount(2) new/remounted filesystems + * ptrace(2) processes outside their jail + * kill(2) processes outside their jail (except sending SIGCHLD to parent) + These are a _few_ of the ways that a root-priv'ed process can break + out of a chrooted jail. They are not all of them. Basically, if + someone has root in a chrooted jail, no can defend -- they've got you. + But, this may help you detect the most common things such an intruder + would do. The only way to win is not to play, however -- don't let + anything in a chrooted jail get root! Simple, right? ;) + This may break systems that use initrd, as that implies an original + chroot. Or not -- the "is this process chrooted" test compares the + root of the current process to that of init; this may not break under + initrd (I have no initrd'd boxes on which to test). + +Restricted ptrace +CONFIG_SECURE_TRACE + When enabled this disables system call tracing (ptrace) entirely for + non-root users. It also prevents tracing syscalls the kernel itself + makes, which can confuse some programs such as strace. When this + option is set, CONFIG_SECURE_TRACE_USERGROUP can be used to enable + ptrace/strace for only certain users. + This option will also cause the logging of any *allowed* ptrace calls. + +Restricted ptrace usergroup +CONFIG_SECURE_TRACE_USERGROUP + Use this option to allow tracing by a special group (defaults to 0). + Users in this group (or processes with this group as egid) can use + the ptrace system call--but only against their own processes, unless + they are root. The allowed group can be changed at runtime when + CONFIG_SECURE_SYSCTL is enabled, by + echo XX > /proc/sys/kernel/security/trace_gid + For a number of boring reasons, the recommended way to use this is to + create a dedicated 'ptrace' group, put only trusted users in it, and + chgrp ptrace /usr/bin/strace; chmod 2110 /usr/bin/strace + (And do the same for other ptrace-using apps they need to run.) + +Security Sysctl +CONFIG_SECURE_SYSCTL + If you say Y here, you will be able to change security options that + without having to recompile your kernel. You can echo values to + files in /proc/sys/kernel/security to enable (1) or disable (0) various + features or change runtime configurables like the ptrace-allow group. + All features are enabled by default (and default to root-only). + Please note that this option could reduce the effectiveness of the + added security policy. # # A couple of things I keep forgetting: diff -urP linux-2.2.20-ow1/arch/alpha/defconfig linux-2.2.20-hap-2/arch/alpha/defconfig --- linux-2.2.20-ow1/arch/alpha/defconfig Sat Nov 3 13:14:57 2001 +++ linux-2.2.20-hap-2/arch/alpha/defconfig Fri Nov 9 19:16:17 2001 @@ -333,10 +333,15 @@ # CONFIG_SECURE_LINK=y CONFIG_SECURE_FIFO=y -# CONFIG_SECURE_PROC is not set +CONFIG_SECURE_NOTSOMUCH=y +CONFIG_SECURE_PROC=y CONFIG_SECURE_FD_0_1_2=y CONFIG_SECURE_RLIMIT_NPROC=y # CONFIG_SECURE_SHM is not set +CONFIG_SECURE_LOGGING=y +CONFIG_SECURE_NETWORK=y +# CONFIG_SECURE_NET_SBD is not set +CONFIG_SECURE_CHROOT=y # # Kernel hacking diff -urP linux-2.2.20-ow1/arch/alpha/kernel/ptrace.c linux-2.2.20-hap-2/arch/alpha/kernel/ptrace.c --- linux-2.2.20-ow1/arch/alpha/kernel/ptrace.c Fri Nov 2 11:39:05 2001 +++ linux-2.2.20-hap-2/arch/alpha/kernel/ptrace.c Fri Nov 9 19:16:17 2001 @@ -517,6 +517,9 @@ sys_ptrace(long request, long pid, long addr, long data, int a4, int a5, struct pt_regs regs) { +#ifdef CONFIG_SECURE_TRACE + extern int sysctl_security_trace, sysctl_security_trace_gid; +#endif struct task_struct *child; unsigned long tmp; long ret; @@ -555,6 +558,54 @@ /* the same process cannot be attached many times */ if (child->ptrace & PT_PTRACED) goto out; +#ifdef CONFIG_SECURE_CHROOT + if (!(hap_same_root_as_init(current)) && + !(hap_same_root(current, child)) ) { + /* + * This process is chrooted; don't let it ptrace + * any process not in the same jail with it + */ + security_alert("denied ptrace of %s[%d] within chrooted " + "jail [%s]:%lu by %s[%d], UID %d, EUID %d, parent %s[%d], UID %d, EUID %d", + "ptraces from a chrooted process", + child->comm, child->pid, kdevname(current->fs->root->d_inode->i_dev), + current->fs->root->d_inode->i_ino, current->comm, current->pid, + current->uid, current->euid, current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid ); + goto out; + } +#endif +#ifdef CONFIG_SECURE_TRACE + if (sysctl_security_trace && current->uid +#ifdef CONFIG_SECURE_TRACE_USERGROUP + && current->egid != sysctl_security_trace_gid +#endif + ) { + security_alert("denied ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptrace attempts", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); + goto out; + } + security_alert("ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptraces", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); +#endif child->ptrace |= PT_PTRACED; if (child->p_pptr != current) { REMOVE_LINKS(child); @@ -684,11 +735,18 @@ } asmlinkage void -syscall_trace(void) +syscall_trace(int unused) { +#ifdef CONFIG_SECURE_TRACE + struct pt_regs *regs = (struct pt_regs *) &unused; +#endif if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) != (PT_PTRACED|PT_TRACESYS)) return; +#ifdef CONFIG_SECURE_TRACE + if (!user_mode(regs)) + return; /* Don't trace the kernel's syscalls */ +#endif current->exit_code = SIGTRAP; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); diff -urP linux-2.2.20-ow1/arch/arm/defconfig linux-2.2.20-hap-2/arch/arm/defconfig --- linux-2.2.20-ow1/arch/arm/defconfig Sat Nov 3 13:14:57 2001 +++ linux-2.2.20-hap-2/arch/arm/defconfig Fri Nov 9 19:16:17 2001 @@ -488,10 +488,16 @@ # CONFIG_SECURE_LINK=y CONFIG_SECURE_FIFO=y -# CONFIG_SECURE_PROC is not set +CONFIG_SECURE_NOTSOMUCH=y +CONFIG_SECURE_PROC=y CONFIG_SECURE_FD_0_1_2=y CONFIG_SECURE_RLIMIT_NPROC=y # CONFIG_SECURE_SHM is not set +CONFIG_SECURE_BUGFIX=y +CONFIG_SECURE_LOGGING=y +CONFIG_SECURE_NETWORK=y +# CONFIG_SECURE_NET_SBD is not set +CONFIG_SECURE_CHROOT=y # # Kernel hacking diff -urP linux-2.2.20-ow1/arch/arm/kernel/ptrace.c linux-2.2.20-hap-2/arch/arm/kernel/ptrace.c --- linux-2.2.20-ow1/arch/arm/kernel/ptrace.c Fri Nov 2 11:39:05 2001 +++ linux-2.2.20-hap-2/arch/arm/kernel/ptrace.c Fri Nov 9 19:16:17 2001 @@ -792,6 +792,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { +#ifdef CONFIG_SECURE_TRACE + extern int sysctl_security_trace, sysctl_security_trace_gid; +#endif struct task_struct *child; int ret; @@ -828,6 +831,54 @@ /* the same process cannot be attached many times */ if (child->ptrace & PT_PTRACED) goto out; +#ifdef CONFIG_SECURE_CHROOT + if (!(hap_same_root_as_init(current)) && + !(hap_same_root(current, child)) ) { + /* + * This process is chrooted; don't let it ptrace + * any process not in the same jail with it + */ + security_alert("denied ptrace of %s[%d] within chrooted " + "jail [%s]:%lu by %s[%d], UID %d, EUID %d, parent %s[%d], UID %d, EUID %d", + "ptraces from a chrooted process", + child->comm, child->pid, kdevname(current->fs->root->d_inode->i_dev), + current->fs->root->d_inode->i_ino, current->comm, current->pid, + current->uid, current->euid, current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid ); + goto out; + } +#endif +#ifdef CONFIG_SECURE_TRACE + if (sysctl_security_trace && current->uid +#ifdef CONFIG_SECURE_TRACE_USERGROUP + && current->egid != sysctl_security_trace_gid +#endif + ) { + security_alert("denied ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptrace attempts", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); + goto out; + } + security_alert("ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptraces", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); +#endif child->ptrace |= PT_PTRACED; if (child->p_pptr != current) { @@ -855,12 +906,19 @@ return ret; } -asmlinkage void syscall_trace(void) +asmlinkage void syscall_trace(int unused) { +#ifdef CONFIG_SECURE_TRACE + struct pt_regs *regs = (struct pt_regs *) &unused; +#endif if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) != (PT_PTRACED|PT_TRACESYS)) return; current->exit_code = SIGTRAP; +#ifdef CONFIG_SECURE_TRACE + if (!user_mode(regs)) + return; /* Don't trace the kernel's syscalls */ +#endif current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); diff -urP linux-2.2.20-ow1/arch/i386/defconfig linux-2.2.20-hap-2/arch/i386/defconfig --- linux-2.2.20-ow1/arch/i386/defconfig Sat Nov 3 13:14:57 2001 +++ linux-2.2.20-hap-2/arch/i386/defconfig Fri Nov 9 19:16:17 2001 @@ -427,11 +427,17 @@ CONFIG_SECURE_STACK_SMART=y CONFIG_SECURE_LINK=y CONFIG_SECURE_FIFO=y -# CONFIG_SECURE_PROC is not set +CONFIG_SECURE_NOTSOMUCH=y +CONFIG_SECURE_PROC=y CONFIG_SECURE_FD_0_1_2=y CONFIG_SECURE_RLIMIT_NPROC=y # CONFIG_SECURE_SHM is not set - +CONFIG_SECURE_BUGFIX=y +CONFIG_SECURE_LOGGING=y +CONFIG_SECURE_NETWORK=y +# CONFIG_SECURE_NET_SBD is not set +CONFIG_SECURE_CHROOT=y +CONFIG_SECURE_TRACE=y # # Kernel hacking # diff -urP linux-2.2.20-ow1/arch/i386/kernel/ptrace.c linux-2.2.20-hap-2/arch/i386/kernel/ptrace.c --- linux-2.2.20-ow1/arch/i386/kernel/ptrace.c Fri Nov 2 11:39:05 2001 +++ linux-2.2.20-hap-2/arch/i386/kernel/ptrace.c Fri Nov 9 19:16:17 2001 @@ -385,6 +385,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { +#ifdef CONFIG_SECURE_TRACE + extern int sysctl_security_trace, sysctl_security_trace_gid; +#endif struct task_struct *child; struct user * dummy = NULL; unsigned long flags; @@ -425,6 +428,54 @@ /* the same process cannot be attached many times */ if (child->ptrace & PT_PTRACED) goto out; +#ifdef CONFIG_SECURE_CHROOT + if (!(hap_same_root_as_init(current)) && + !(hap_same_root(current, child)) ) { + /* + * This process is chrooted; don't let it ptrace + * any process not in the same jail with it + */ + security_alert("denied ptrace of %s[%d] within chrooted " + "jail [%s]:%lu by %s[%d], UID %d, EUID %d, parent %s[%d], UID %d, EUID %d", + "ptraces from a chrooted process", + child->comm, child->pid, kdevname(current->fs->root->d_inode->i_dev), + current->fs->root->d_inode->i_ino, current->comm, current->pid, + current->uid, current->euid, current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid ); + goto out; + } +#endif +#ifdef CONFIG_SECURE_TRACE + if (sysctl_security_trace && current->uid +#ifdef CONFIG_SECURE_TRACE_USERGROUP + && current->egid != sysctl_security_trace_gid +#endif + ) { + security_alert("denied ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptrace attempts", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); + goto out; + } + security_alert("ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptraces", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); +#endif child->ptrace |= PT_PTRACED; write_lock_irqsave(&tasklist_lock, flags); @@ -708,11 +759,18 @@ return ret; } -asmlinkage void syscall_trace(void) +asmlinkage void syscall_trace(int unused) { +#ifdef CONFIG_SECURE_TRACE + struct pt_regs *regs = (struct pt_regs *) &unused; +#endif if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) != (PT_PTRACED|PT_TRACESYS)) return; +#ifdef CONFIG_SECURE_TRACE + if (!user_mode(regs)) + return; /* Don't trace the kernel's syscalls */ +#endif current->exit_code = SIGTRAP; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); diff -urP linux-2.2.20-ow1/arch/i386/kernel/traps.c linux-2.2.20-hap-2/arch/i386/kernel/traps.c --- linux-2.2.20-ow1/arch/i386/kernel/traps.c Sat Nov 3 13:14:57 2001 +++ linux-2.2.20-hap-2/arch/i386/kernel/traps.c Fri Nov 9 19:16:17 2001 @@ -401,11 +401,13 @@ */ if ((addr & 0xFF800000) == 0xBF800000 || (addr >= PAGE_OFFSET - _STK_LIM && addr < PAGE_OFFSET)) - security_alert("return onto stack running as " - "UID %d, EUID %d, process %s:%d", + security_alert("return onto stack by %s[%d], UID %d, " + "EUID %d, parent %s[%d], UID %d, EUID %d", "returns onto stack", - current->uid, current->euid, - current->comm, current->pid); + current->comm, current->pid, current->uid, + current->euid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid); } #ifdef CONFIG_SECURE_STACK_SMART diff -urP linux-2.2.20-ow1/arch/m68k/defconfig linux-2.2.20-hap-2/arch/m68k/defconfig --- linux-2.2.20-ow1/arch/m68k/defconfig Sat Nov 3 13:14:57 2001 +++ linux-2.2.20-hap-2/arch/m68k/defconfig Fri Nov 9 19:16:17 2001 @@ -243,10 +243,15 @@ # CONFIG_SECURE_LINK=y CONFIG_SECURE_FIFO=y -# CONFIG_SECURE_PROC is not set +CONFIG_SECURE_NOTSOMUCH=y +CONFIG_SECURE_PROC=y CONFIG_SECURE_FD_0_1_2=y CONFIG_SECURE_RLIMIT_NPROC=y # CONFIG_SECURE_SHM is not set +CONFIG_SECURE_LOGGING=y +CONFIG_SECURE_NETWORK=y +# CONFIG_SECURE_NET_SBD is not set +CONFIG_SECURE_CHROOT=y # # Kernel hacking diff -urP linux-2.2.20-ow1/arch/m68k/kernel/ptrace.c linux-2.2.20-hap-2/arch/m68k/kernel/ptrace.c --- linux-2.2.20-ow1/arch/m68k/kernel/ptrace.c Fri Nov 2 11:39:05 2001 +++ linux-2.2.20-hap-2/arch/m68k/kernel/ptrace.c Fri Nov 9 19:16:17 2001 @@ -312,6 +312,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { +#ifdef CONFIG_SECURE_TRACE + extern int sysctl_security_trace, sysctl_security_trace_gid; +#endif struct task_struct *child; unsigned long flags; int ret; @@ -351,6 +354,54 @@ /* the same process cannot be attached many times */ if (child->ptrace & PT_PTRACED) goto out; +#ifdef CONFIG_SECURE_CHROOT + if (!(hap_same_root_as_init(current)) && + !(hap_same_root(current, child)) ) { + /* + * This process is chrooted; don't let it ptrace + * any process not in the same jail with it + */ + security_alert("denied ptrace of %s[%d] within chrooted " + "jail [%s]:%lu by %s[%d], UID %d, EUID %d, parent %s[%d], UID %d, EUID %d", + "ptraces from a chrooted process", + child->comm, child->pid, kdevname(current->fs->root->d_inode->i_dev), + current->fs->root->d_inode->i_ino, current->comm, current->pid, + current->uid, current->euid, current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid ); + goto out; + } +#endif +#ifdef CONFIG_SECURE_TRACE + if (sysctl_security_trace && current->uid +#ifdef CONFIG_SECURE_TRACE_USERGROUP + && current->egid != sysctl_security_trace_gid +#endif + ) { + security_alert("denied ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptrace attempts", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); + goto out; + } + security_alert("ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptraces", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); +#endif child->ptrace |= PT_PTRACED; write_lock_irqsave(&tasklist_lock, flags); @@ -604,13 +655,20 @@ return ret; } -asmlinkage void syscall_trace(void) +asmlinkage void syscall_trace(int unused) { +#ifdef CONFIG_SECURE_TRACE + struct pt_regs *regs = (struct pt_regs *) &unused; +#endif lock_kernel(); if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) != (PT_PTRACED|PT_TRACESYS)) goto out; current->exit_code = SIGTRAP; +#ifdef CONFIG_SECURE_TRACE + if (!user_mode(regs)) + return; /* Don't trace the kernel's syscalls */ +#endif current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); diff -urP linux-2.2.20-ow1/arch/mips/defconfig linux-2.2.20-hap-2/arch/mips/defconfig --- linux-2.2.20-ow1/arch/mips/defconfig Sat Nov 3 13:14:57 2001 +++ linux-2.2.20-hap-2/arch/mips/defconfig Fri Nov 9 19:16:17 2001 @@ -369,10 +369,15 @@ # CONFIG_SECURE_LINK=y CONFIG_SECURE_FIFO=y -# CONFIG_SECURE_PROC is not set +CONFIG_SECURE_NOTSOMUCH=y +CONFIG_SECURE_PROC=y CONFIG_SECURE_FD_0_1_2=y CONFIG_SECURE_RLIMIT_NPROC=y # CONFIG_SECURE_SHM is not set +CONFIG_SECURE_LOGGING=y +CONFIG_SECURE_NETWORK=y +# CONFIG_SECURE_NET_SBD is not set +CONFIG_SECURE_CHROOT=y # # Kernel hacking diff -urP linux-2.2.20-ow1/arch/mips/kernel/ptrace.c linux-2.2.20-hap-2/arch/mips/kernel/ptrace.c --- linux-2.2.20-ow1/arch/mips/kernel/ptrace.c Fri Nov 2 11:39:05 2001 +++ linux-2.2.20-hap-2/arch/mips/kernel/ptrace.c Fri Nov 9 19:16:17 2001 @@ -258,6 +258,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { +#ifdef CONFIG_SECURE_TRACE + extern int sysctl_security_trace, sysctl_security_trace_gid; +#endif struct task_struct *child; unsigned int flags; int res; @@ -308,6 +311,54 @@ /* the same process cannot be attached many times */ if (child->ptrace & PT_PTRACED) goto out; +#ifdef CONFIG_SECURE_CHROOT + if (!(hap_same_root_as_init(current)) && + !(hap_same_root(current, child)) ) { + /* + * This process is chrooted; don't let it ptrace + * any process not in the same jail with it + */ + security_alert("denied ptrace of %s[%d] within chrooted " + "jail [%s]:%lu by %s[%d], UID %d, EUID %d, parent %s[%d], UID %d, EUID %d", + "ptraces from a chrooted process", + child->comm, child->pid, kdevname(current->fs->root->d_inode->i_dev), + current->fs->root->d_inode->i_ino, current->comm, current->pid, + current->uid, current->euid, current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid ); + goto out; + } +#endif +#ifdef CONFIG_SECURE_TRACE + if (sysctl_security_trace && current->uid +#ifdef CONFIG_SECURE_TRACE_USERGROUP + && current->egid != sysctl_security_trace_gid +#endif + ) { + security_alert("denied ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptrace attempts", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); + goto out; + } + security_alert("ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptraces", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); +#endif child->ptrace |= PT_PTRACED; write_lock_irqsave(&tasklist_lock, flags); @@ -520,11 +571,18 @@ return res; } -asmlinkage void syscall_trace(void) +asmlinkage void syscall_trace(int unused) { +#ifdef CONFIG_SECURE_TRACE + struct pt_regs *regs = (struct pt_regs *) &unused; +#endif if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) != (PT_PTRACED|PT_TRACESYS)) return; +#ifdef CONFIG_SECURE_TRACE + if (!user_mode(regs)) + return; /* Don't trace the kernel's syscalls */ +#endif current->exit_code = SIGTRAP; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); diff -urP linux-2.2.20-ow1/arch/ppc/defconfig linux-2.2.20-hap-2/arch/ppc/defconfig --- linux-2.2.20-ow1/arch/ppc/defconfig Sat Nov 3 13:14:57 2001 +++ linux-2.2.20-hap-2/arch/ppc/defconfig Fri Nov 9 19:16:17 2001 @@ -499,10 +499,15 @@ # CONFIG_SECURE_LINK=y CONFIG_SECURE_FIFO=y -# CONFIG_SECURE_PROC is not set +CONFIG_SECURE_NOTSOMUCH=y +CONFIG_SECURE_PROC=y CONFIG_SECURE_FD_0_1_2=y CONFIG_SECURE_RLIMIT_NPROC=y # CONFIG_SECURE_SHM is not set +CONFIG_SECURE_LOGGING=y +CONFIG_SECURE_NETWORK=y +# CONFIG_SECURE_NET_SBD is not set +CONFIG_SECURE_CHROOT=y # # Kernel hacking diff -urP linux-2.2.20-ow1/arch/ppc/kernel/ptrace.c linux-2.2.20-hap-2/arch/ppc/kernel/ptrace.c --- linux-2.2.20-ow1/arch/ppc/kernel/ptrace.c Fri Nov 2 11:39:05 2001 +++ linux-2.2.20-hap-2/arch/ppc/kernel/ptrace.c Fri Nov 9 19:16:17 2001 @@ -334,6 +334,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { +#ifdef CONFIG_SECURE_TRACE + extern int sysctl_security_trace, sysctl_security_trace_gid; +#endif struct task_struct *child; int ret = -EPERM; unsigned long flags; @@ -372,6 +375,54 @@ /* the same process cannot be attached many times */ if (child->ptrace & PT_PTRACED) goto out; +#ifdef CONFIG_SECURE_CHROOT + if (!(hap_same_root_as_init(current)) && + !(hap_same_root(current, child)) ) { + /* + * This process is chrooted; don't let it ptrace + * any process not in the same jail with it + */ + security_alert("denied ptrace of %s[%d] within chrooted " + "jail [%s]:%lu by %s[%d], UID %d, EUID %d, parent %s[%d], UID %d, EUID %d", + "ptraces from a chrooted process", + child->comm, child->pid, kdevname(current->fs->root->d_inode->i_dev), + current->fs->root->d_inode->i_ino, current->comm, current->pid, + current->uid, current->euid, current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid ); + goto out; + } +#endif +#ifdef CONFIG_SECURE_TRACE + if (sysctl_security_trace && current->uid +#ifdef CONFIG_SECURE_TRACE_USERGROUP + && current->egid != sysctl_security_trace_gid +#endif + ) { + security_alert("denied ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptrace attempts", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); + goto out; + } + security_alert("ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptraces", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); +#endif child->ptrace |= PT_PTRACED; write_lock_irqsave(&tasklist_lock, flags); @@ -539,11 +590,18 @@ return ret; } -asmlinkage void syscall_trace(void) +asmlinkage void syscall_trace(int unused) { +#ifdef CONFIG_SECURE_TRACE + struct pt_regs *regs = (struct pt_regs *) &unused; +#endif if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) != (PT_PTRACED|PT_TRACESYS)) return; +#ifdef CONFIG_SECURE_TRACE + if (!user_mode(regs)) + return; /* Don't trace the kernel's syscalls */ +#endif current->exit_code = SIGTRAP; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); diff -urP linux-2.2.20-ow1/arch/s390/defconfig linux-2.2.20-hap-2/arch/s390/defconfig --- linux-2.2.20-ow1/arch/s390/defconfig Sat Nov 3 13:14:57 2001 +++ linux-2.2.20-hap-2/arch/s390/defconfig Fri Nov 9 19:16:17 2001 @@ -194,10 +194,15 @@ # CONFIG_SECURE_LINK=y CONFIG_SECURE_FIFO=y -# CONFIG_SECURE_PROC is not set +CONFIG_SECURE_NOTSOMUCH=y +CONFIG_SECURE_PROC=y CONFIG_SECURE_FD_0_1_2=y CONFIG_SECURE_RLIMIT_NPROC=y # CONFIG_SECURE_SHM is not set +CONFIG_SECURE_LOGGING=y +CONFIG_SECURE_NETWORK=y +# CONFIG_SECURE_NET_SBD is not set +CONFIG_SECURE_CHROOT=y # # Kernel hacking diff -urP linux-2.2.20-ow1/arch/s390/kernel/ptrace.c linux-2.2.20-hap-2/arch/s390/kernel/ptrace.c --- linux-2.2.20-ow1/arch/s390/kernel/ptrace.c Fri Nov 2 11:39:06 2001 +++ linux-2.2.20-hap-2/arch/s390/kernel/ptrace.c Fri Nov 9 19:16:17 2001 @@ -427,6 +427,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { +#ifdef CONFIG_SECURE_TRACE + extern int sysctl_security_trace, sysctl_security_trace_gid; +#endif struct task_struct *child; int ret = -EPERM; unsigned long tmp; @@ -461,6 +464,54 @@ /* the same process cannot be attached many times */ if (child->ptrace & PT_PTRACED) goto out; +#ifdef CONFIG_SECURE_CHROOT + if (!(hap_same_root_as_init(current)) && + !(hap_same_root(current, child)) ) { + /* + * This process is chrooted; don't let it ptrace + * any process not in the same jail with it + */ + security_alert("denied ptrace of %s[%d] within chrooted " + "jail [%s]:%lu by %s[%d], UID %d, EUID %d, parent %s[%d], UID %d, EUID %d", + "ptraces from a chrooted process", + child->comm, child->pid, kdevname(current->fs->root->d_inode->i_dev), + current->fs->root->d_inode->i_ino, current->comm, current->pid, + current->uid, current->euid, current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid ); + goto out; + } +#endif +#ifdef CONFIG_SECURE_TRACE + if (sysctl_security_trace && current->uid +#ifdef CONFIG_SECURE_TRACE_USERGROUP + && current->egid != sysctl_security_trace_gid +#endif + ) { + security_alert("denied ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptrace attempts", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); + goto out; + } + security_alert("ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptraces", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); +#endif child->ptrace |= PT_PTRACED; if (child->p_pptr != current) { @@ -590,12 +641,19 @@ return ret; } -asmlinkage void syscall_trace(void) +asmlinkage void syscall_trace(int unused) { +#ifdef CONFIG_SECURE_TRACE + struct pt_regs *regs = (struct pt_regs *) &unused; +#endif lock_kernel(); if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) != (PT_PTRACED|PT_TRACESYS)) goto out; +#ifdef CONFIG_SECURE_TRACE + if (!user_mode(regs)) + return; /* Don't trace the kernel's syscalls */ +#endif current->exit_code = SIGTRAP; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); diff -urP linux-2.2.20-ow1/arch/sparc/defconfig linux-2.2.20-hap-2/arch/sparc/defconfig --- linux-2.2.20-ow1/arch/sparc/defconfig Sat Nov 3 13:14:57 2001 +++ linux-2.2.20-hap-2/arch/sparc/defconfig Fri Nov 9 19:16:17 2001 @@ -340,10 +340,15 @@ # CONFIG_SECURE_LINK=y CONFIG_SECURE_FIFO=y -# CONFIG_SECURE_PROC is not set +CONFIG_SECURE_NOTSOMUCH=y +CONFIG_SECURE_PROC=y CONFIG_SECURE_FD_0_1_2=y CONFIG_SECURE_RLIMIT_NPROC=y # CONFIG_SECURE_SHM is not set +CONFIG_SECURE_LOGGING=y +CONFIG_SECURE_NETWORK=y +# CONFIG_SECURE_NET_SBD is not set +CONFIG_SECURE_CHROOT=y # # Kernel hacking diff -urP linux-2.2.20-ow1/arch/sparc/kernel/ptrace.c linux-2.2.20-hap-2/arch/sparc/kernel/ptrace.c --- linux-2.2.20-ow1/arch/sparc/kernel/ptrace.c Fri Nov 2 11:39:06 2001 +++ linux-2.2.20-hap-2/arch/sparc/kernel/ptrace.c Fri Nov 9 19:16:17 2001 @@ -508,6 +508,9 @@ asmlinkage void do_ptrace(struct pt_regs *regs) { +#ifdef CONFIG_SECURE_TRACE + extern int sysctl_security_trace, sysctl_security_trace_gid; +#endif unsigned long request = regs->u_regs[UREG_I0]; unsigned long pid = regs->u_regs[UREG_I1]; unsigned long addr = regs->u_regs[UREG_I2]; @@ -582,6 +585,55 @@ pt_error_return(regs, EPERM); goto out; } +#ifdef CONFIG_SECURE_CHROOT + if (!(hap_same_root_as_init(current)) && + !(hap_same_root(current, child)) ) { + /* + * This process is chrooted; don't let it ptrace + * any process not in the same jail with it + */ + security_alert("denied ptrace of %s[%d] within chrooted " + "jail [%s]:%lu by %s[%d], UID %d, EUID %d, parent %s[%d], UID %d, EUID %d", + "ptraces from a chrooted process", + child->comm, child->pid, kdevname(current->fs->root->d_inode->i_dev), + current->fs->root->d_inode->i_ino, current->comm, current->pid, + current->uid, current->euid, current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid ); + pt_error_return(regs, EPERM); + goto out; + } +#endif +#ifdef CONFIG_SECURE_TRACE + if (sysctl_security_trace && current->uid +#ifdef CONFIG_SECURE_TRACE_USERGROUP + && current->egid != sysctl_security_trace_gid +#endif + ) { + security_alert("denied ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptrace attempts", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); + goto out; + } + security_alert("ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptraces", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); +#endif child->ptrace |= PT_PTRACED; write_lock_irqsave(&tasklist_lock, flags); if(child->p_pptr != current) { @@ -922,14 +974,21 @@ unlock_kernel(); } -asmlinkage void syscall_trace(void) +asmlinkage void syscall_trace(int unused) { +#ifdef CONFIG_SECURE_TRACE + struct pt_regs *regs = (struct pt_regs *) &unused; +#endif #ifdef DEBUG_PTRACE printk("%s [%d]: syscall_trace\n", current->comm, current->pid); #endif if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) != (PT_PTRACED|PT_TRACESYS)) return; +#ifdef CONFIG_SECURE_TRACE + if (!user_mode(regs)) + return; /* Don't trace the kernel's syscalls */ +#endif current->exit_code = SIGTRAP; current->state = TASK_STOPPED; current->tss.flags ^= MAGIC_CONSTANT; diff -urP linux-2.2.20-ow1/arch/sparc64/defconfig linux-2.2.20-hap-2/arch/sparc64/defconfig --- linux-2.2.20-ow1/arch/sparc64/defconfig Sat Nov 3 13:14:57 2001 +++ linux-2.2.20-hap-2/arch/sparc64/defconfig Fri Nov 9 19:16:17 2001 @@ -391,10 +391,15 @@ # CONFIG_SECURE_LINK=y CONFIG_SECURE_FIFO=y -# CONFIG_SECURE_PROC is not set +CONFIG_SECURE_NOTSOMUCH=y +CONFIG_SECURE_PROC=y CONFIG_SECURE_FD_0_1_2=y CONFIG_SECURE_RLIMIT_NPROC=y # CONFIG_SECURE_SHM is not set +CONFIG_SECURE_LOGGING=y +CONFIG_SECURE_NETWORK=y +# CONFIG_SECURE_NET_SBD is not set +CONFIG_SECURE_CHROOT=y # # Watchdog diff -urP linux-2.2.20-ow1/arch/sparc64/kernel/ptrace.c linux-2.2.20-hap-2/arch/sparc64/kernel/ptrace.c --- linux-2.2.20-ow1/arch/sparc64/kernel/ptrace.c Fri Nov 2 11:39:06 2001 +++ linux-2.2.20-hap-2/arch/sparc64/kernel/ptrace.c Fri Nov 9 19:16:17 2001 @@ -537,6 +537,9 @@ asmlinkage void do_ptrace(struct pt_regs *regs) { +#ifdef CONFIG_SECURE_TRACE + extern int sysctl_security_trace, sysctl_security_trace_gid; +#endif int request = regs->u_regs[UREG_I0]; pid_t pid = regs->u_regs[UREG_I1]; unsigned long addr = regs->u_regs[UREG_I2]; @@ -620,6 +623,55 @@ pt_error_return(regs, EPERM); goto out; } +#ifdef CONFIG_SECURE_CHROOT + if (!(hap_same_root_as_init(current)) && + !(hap_same_root(current, child)) ) { + /* + * This process is chrooted; don't let it ptrace + * any process not in the same jail with it + */ + security_alert("denied ptrace of %s[%d] within chrooted " + "jail [%s]:%lu by %s[%d], UID %d, EUID %d, parent %s[%d], UID %d, EUID %d", + "ptraces from a chrooted process", + child->comm, child->pid, kdevname(current->fs->root->d_inode->i_dev), + current->fs->root->d_inode->i_ino, current->comm, current->pid, + current->uid, current->euid, current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid ); + pt_error_return(regs, EPERM); + goto out; + } +#endif +#ifdef CONFIG_SECURE_TRACE + if (sysctl_security_trace && current->uid +#ifdef CONFIG_SECURE_TRACE_USERGROUP + && current->egid != sysctl_security_trace_gid +#endif + ) { + security_alert("denied ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptrace attempts", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); + goto out; + } + security_alert("ptrace of %s[%d] by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptraces", + child->comm, child->pid, current->comm, + current->pid, current->uid, + current->euid, current->gid, + current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid, current->p_pptr->gid, + current->p_pptr->egid ); +#endif child->ptrace |= PT_PTRACED; write_lock_irqsave(&tasklist_lock, flags); if(child->p_pptr != current) { @@ -1134,14 +1186,21 @@ unlock_kernel(); } -asmlinkage void syscall_trace(void) +asmlinkage void syscall_trace(int unused) { +#ifdef CONFIG_SECURE_TRACE + struct pt_regs *regs = (struct pt_regs *) &unused; +#endif #ifdef DEBUG_PTRACE printk("%s [%d]: syscall_trace\n", current->comm, current->pid); #endif if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) != (PT_PTRACED|PT_TRACESYS)) return; +#ifdef CONFIG_SECURE_TRACE + if (!user_mode(regs)) + return; /* Don't trace the kernel's syscalls */ +#endif current->exit_code = SIGTRAP; current->state = TASK_STOPPED; current->tss.flags ^= MAGIC_CONSTANT; diff -urP linux-2.2.20-ow1/fs/exec.c linux-2.2.20-hap-2/fs/exec.c --- linux-2.2.20-ow1/fs/exec.c Sat Nov 3 13:14:57 2001 +++ linux-2.2.20-hap-2/fs/exec.c Sat Nov 10 02:37:07 2001 @@ -674,6 +674,9 @@ */ int prepare_binprm(struct linux_binprm *bprm) { +#ifdef CONFIG_SECURE_TRACE + extern int sysctl_security_trace, sysctl_security_trace_gid; +#endif int mode; int retval,id_change,cap_raised; struct inode * inode = bprm->dentry->d_inode; @@ -778,7 +781,55 @@ return retval; #endif } - +/* Total mess of ifdef's follow. */ +#if defined(CONFIG_SECURE_BUGFIX) || defined(CONFIG_SECURE_TRACE) + /* ptraced executables must be readable */ + if (current->ptrace & PT_PTRACED) { +#ifdef CONFIG_SECURE_TRACE + if (sysctl_security_trace && current->uid +#ifdef CONFIG_SECURE_TRACE_USERGROUP + && current->egid != sysctl_security_trace_gid +#endif + ) { + security_alert("denied ptrace of %s by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptrace attempts", + bprm->filename, current->comm, current->pid, current->uid, + current->euid, current->gid, current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, current->p_pptr->euid, + current->p_pptr->gid, current->p_pptr->egid); + return -EPERM; + } +#endif /* CONFIG_SECURE_TRACE */ +#ifdef CONFIG_SECURE_BUGFIX + if ((retval = permission(bprm->dentry->d_inode, MAY_READ)) != 0) { +#ifdef CONFIG_SECURE_LOGGING + security_alert("refused ptrace of unreadable executable %s by " + "%s[%d], UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "unreadable executables ptraced", + bprm->filename, current->comm, current->pid, current->uid, + current->euid, current->gid, current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, current->p_pptr->euid, + current->p_pptr->gid, current->p_pptr->egid); +#endif /* CONFIG_SECURE_LOGGING */ + return -EPERM; + } +#endif /* CONFIG_SECURE_BUGFIX */ +#ifdef CONFIG_SECURE_TRACE + /* log all permitted ptrace's */ + security_alert("ptrace of %s by %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d, parent %s[%d], " + "UID/EUID %d/%d, GID/EGID %d/%d", + "ptraces", + bprm->filename, current->comm, current->pid, current->uid, + current->euid, current->gid, current->egid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, current->p_pptr->euid, + current->p_pptr->gid, current->p_pptr->egid); +#endif /* CONFIG_SECURE_TRACE */ + } +#endif /* CONFIG_SECURE_BUGFIX || CONFIG_SECURE_TRACE */ memset(bprm->buf,0,sizeof(bprm->buf)); return read_exec(bprm->dentry,0,bprm->buf,128,1); } @@ -946,6 +997,22 @@ int retval; int i; +#ifdef CONFIG_SECURE_CHROOT + if (!(hap_same_root_as_init(current))) { + /* + * This process is in a chrooted jail; log everything it exec's + */ + security_alert("exec of %s within chrooted jail [%s]:%lu by " + "%s[%d], UID %d, EUID %d, parent %s[%d], UID %d, EUID %d", + "execs from a chrooted process", + filename, kdevname(current->fs->root->d_inode->i_dev), + current->fs->root->d_inode->i_ino,current->comm, + current->pid,current->uid, current->euid, + current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid ); + } +#endif /* CONFIG_SECURE_CHROOT */ + #ifdef CONFIG_SECURE_RLIMIT_NPROC /* * This check is similar to that done in kernel/fork.c, except that we diff -urP linux-2.2.20-ow1/fs/namei.c linux-2.2.20-hap-2/fs/namei.c --- linux-2.2.20-ow1/fs/namei.c Sat Nov 3 13:14:57 2001 +++ linux-2.2.20-hap-2/fs/namei.c Fri Nov 9 19:16:17 2001 @@ -306,18 +306,28 @@ if (S_ISLNK(inode->i_mode) && (base->d_inode->i_mode & S_ISVTX) && inode->i_uid != base->d_inode->i_uid && +#ifdef CONFIG_SECURE_NOTSOMUCH + /* + * Let this happen as long as the +t dir is + * not world-writable. + */ + (base->d_inode->i_mode & S_IWOTH) && +#endif current->fsuid != inode->i_uid) { - security_alert("not followed symlink of %d.%d " - "by UID %d, EUID %d, process %s:%d", + security_alert("not followed symlink of [%s]:%lu " + "owned by %d.%d by %s[%d], UID %d, " + "EUID %d, parent %s[%d], UID %d, EUID %d", "symlinks not followed", - inode->i_uid, inode->i_gid, - current->uid, current->euid, - current->comm, current->pid); + kdevname(inode->i_dev), inode->i_ino, + inode->i_uid, inode->i_gid, current->comm, + current->pid, current->uid, current->euid, + current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid); dput(dentry); dput(base); return ERR_PTR(-EACCES); } -#endif +#endif /* CONFIG_SECURE_LINK */ if (current->need_resched) { current->state = TASK_RUNNING; @@ -756,19 +766,28 @@ if (S_ISFIFO(inode->i_mode) && !(flag & O_EXCL) && (dir->d_inode->i_mode & S_ISVTX) && inode->i_uid != dir->d_inode->i_uid && +#ifdef CONFIG_SECURE_NOTSOMUCH + /* + * Let this happen as long as the +t dir isn't world-writable + */ + (dir->d_inode->i_mode & S_IWOTH) && +#endif current->fsuid != inode->i_uid) { if (!permission(inode, acc_mode)) - security_alert("denied writing FIFO of %d.%d " - "by UID %d, EUID %d, process %s:%d", + security_alert("denied writing FIFO [%s]:%lu owned " + "by %d.%d by %s[%d], UID %d, EUID %d, parent " + "%s[%d], UID %d, EUID %d", "writes into a FIFO denied", - inode->i_uid, inode->i_gid, - current->uid, current->euid, - current->comm, current->pid); + kdevname(inode->i_dev), inode->i_ino, + inode->i_uid, inode->i_gid, current->comm, + current->pid, current->uid, current->euid, + current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid); error = -EACCES; unlock_dir(dir); goto exit; } -#endif +#endif /* CONFIG_SECURE_FIFO */ /* * Somebody might have created the file while we @@ -909,6 +928,10 @@ { int error; char * tmp; + struct dentry * dentry; +#ifdef CONFIG_SECURE_CHROOT + char hap_dev_mode; +#endif lock_kernel(); error = -EPERM; @@ -927,7 +950,41 @@ tmp = getname(filename); error = PTR_ERR(tmp); if (!IS_ERR(tmp)) { - struct dentry * dentry = do_mknod(tmp,mode,dev); +#ifdef CONFIG_SECURE_CHROOT + if (!S_ISFIFO(mode)) { + if (!(hap_same_root_as_init(current))) { + /* + * This process is in a chrooted jail; don't let it + * make a raw device through which to break out (by + * double-mounting an fs, reading kmem, kybd, etc) + */ + switch (mode & S_IFMT) { + case S_IFREG: hap_dev_mode = 'r'; break; + case S_IFCHR: hap_dev_mode = 'c'; break; + case S_IFBLK: hap_dev_mode = 'b'; break; + case S_IFSOCK: hap_dev_mode = 's'; break; + default: hap_dev_mode = 'u'; + } + security_alert("refused attempt to mknod %c:[%s] (%s) " + "from chrooted jail [%s]:%lu owned by %d.%d by " + "%s[%d], UID %d, EUID %d, parent %s[%d], UID " + "%d, EUID %d", + "chrooted mknods denied", + hap_dev_mode, kdevname(dev), tmp, + kdevname(current->fs->root->d_inode->i_dev), + current->fs->root->d_inode->i_ino, + current->fs->root->d_inode->i_uid, + current->fs->root->d_inode->i_gid, current->comm, + current->pid, current->uid, current->euid, + current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid); + putname(tmp); + error = -EPERM; + goto out; + } + } +#endif + dentry = do_mknod(tmp,mode,dev); putname(tmp); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { @@ -1258,13 +1315,21 @@ ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) || (error = permission(inode, MAY_READ | MAY_WRITE))) && !capable(CAP_FOWNER) && +#ifdef CONFIG_SECURE_NOTSOMUCH + /* + * Let users hard link to files in their group. + */ + current->fsgid != inode->i_gid && +#endif current->uid) { - security_alert("denied hard link to %d.%d " - "for UID %d, EUID %d, process %s:%d", + security_alert("denied hard link to [%s]:%lu owned by %d.%d " + "by %s[%d], UID %d, EUID %d, parent %s[%d], UID %d, EUID %d", "hard links denied", + kdevname(inode->i_dev), inode->i_ino, inode->i_uid, inode->i_gid, - current->uid, current->euid, - current->comm, current->pid); + current->comm, current->pid, current->uid, current->euid, + current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid); goto exit_lock; } #endif diff -urP linux-2.2.20-ow1/fs/open.c linux-2.2.20-hap-2/fs/open.c --- linux-2.2.20-ow1/fs/open.c Fri Nov 2 11:39:08 2001 +++ linux-2.2.20-hap-2/fs/open.c Fri Nov 9 19:16:17 2001 @@ -402,6 +402,9 @@ int error; struct inode *inode; struct dentry *dentry, *tmp; +#ifdef CONFIG_SECURE_CHROOT + char * hap_new_chroot_path; +#endif lock_kernel(); @@ -423,11 +426,55 @@ error = -EPERM; if (!capable(CAP_SYS_CHROOT)) goto dput_and_out; +#ifdef CONFIG_SECURE_CHROOT + if (!(hap_same_root_as_init(current))) { + /* + * This process is already in a chrooted jail; don't let it chroot out. + */ + if (IS_ERR(hap_new_chroot_path = getname(filename))) + hap_new_chroot_path = "[err]"; + security_alert("refused attempt to chroot from [%s]:%lu to " + "[%s]:%lu (%s) owned by %d.%d, process %s[%d], UID %d, " + "EUID %d, parent %s[%d], UID %d, EUID %d", + "double chroots denied", + kdevname(current->fs->root->d_inode->i_dev), + current->fs->root->d_inode->i_ino, + kdevname(inode->i_dev), inode->i_ino, hap_new_chroot_path, + inode->i_uid, inode->i_gid, + current->comm, current->pid, current->uid, current->euid, + current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid); + putname(hap_new_chroot_path); + error = -EPERM; + goto dput_and_out; + } +#endif /* exchange dentries */ tmp = current->fs->root; current->fs->root = dentry; dentry = tmp; +#ifdef CONFIG_SECURE_CHROOT + /* drop various dangerous capabilities when chrooting + * note init is exempt for initrd-type games */ + if (current->pid && current->pid > 1) { + cap_lower(current->cap_permitted, + CAP_FOWNER & CAP_SETPCAP & CAP_LINUX_IMMUTABLE & + CAP_NET_ADMIN & CAP_SYS_MODULE & CAP_SYS_RAWIO & + CAP_SYS_PACCT & CAP_SYS_ADMIN & CAP_SYS_BOOT & + CAP_SYS_RESOURCE & CAP_SYS_TIME & CAP_SYS_TTY_CONFIG); + cap_lower(current->cap_inheritable, + CAP_FOWNER & CAP_SETPCAP & CAP_LINUX_IMMUTABLE & + CAP_NET_ADMIN & CAP_SYS_MODULE & CAP_SYS_RAWIO & + CAP_SYS_PACCT & CAP_SYS_ADMIN & CAP_SYS_BOOT & + CAP_SYS_RESOURCE & CAP_SYS_TIME & CAP_SYS_TTY_CONFIG); + cap_lower(current->cap_effective, + CAP_FOWNER & CAP_SETPCAP & CAP_LINUX_IMMUTABLE & + CAP_NET_ADMIN & CAP_SYS_MODULE & CAP_SYS_RAWIO & + CAP_SYS_PACCT & CAP_SYS_ADMIN & CAP_SYS_BOOT & + CAP_SYS_RESOURCE & CAP_SYS_TIME & CAP_SYS_TTY_CONFIG); + } +#endif error = 0; dput_and_out: @@ -464,6 +511,31 @@ goto out_putf; if (mode == (mode_t) -1) mode = inode->i_mode; +#ifdef CONFIG_SECURE_CHROOT + if ((mode & S_ISUID) || (mode & S_ISGID)) { + if (!(hap_same_root_as_init(current))) { + /* + * This process is chrooted; don't let it turn on the set[ug]id bits. + */ + security_alert("refused attempt to fchmod +s [%s]:%lu " + "owned by %d.%d to mode 0%07o from chrooted jail " + "[%s]:%lu owned by %d.%d by %s[%d], UID %d, EUID " + "%d, parent %s[%d], UID %d, EUID %d", + "chrooted fchmod +s's denied", + kdevname(inode->i_dev), inode->i_ino, + inode->i_uid, inode->i_gid, mode, + kdevname(current->fs->root->d_inode->i_dev), + current->fs->root->d_inode->i_ino, + current->fs->root->d_inode->i_uid, + current->fs->root->d_inode->i_gid, current->comm, + current->pid, current->uid, current->euid, + current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid); + err = -EPERM; + goto out_putf; + } + } +#endif newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; err = notify_change(dentry, &newattrs); @@ -481,6 +553,9 @@ struct inode * inode; int error; struct iattr newattrs; +#ifdef CONFIG_SECURE_CHROOT + char * hap_chmod_filename; +#endif lock_kernel(); dentry = namei(filename); @@ -500,6 +575,34 @@ if (mode == (mode_t) -1) mode = inode->i_mode; +#ifdef CONFIG_SECURE_CHROOT + if ((mode & S_ISUID) || (mode & S_ISGID)) { + if (!(hap_same_root_as_init(current))) { + /* + * This process is chrooted; don't let it turn on the set[gu]id bits. + */ + if (IS_ERR(hap_chmod_filename = getname(filename))) + hap_chmod_filename = "[err]"; + security_alert("refused attempt to chmod +s [%s]:%lu " + "(%s) owned by %d.%d to mode 0%07o from chrooted " + "jail [%s]:%lu owned by %d.%d by %s[%d], UID %d, " + "EUID %d, parent %s[%d], UID %d, EUID %d", + "chrooted chmod +s's denied", + kdevname(inode->i_dev), inode->i_ino, hap_chmod_filename, + inode->i_uid, inode->i_gid, mode, + kdevname(current->fs->root->d_inode->i_dev), + current->fs->root->d_inode->i_ino, + current->fs->root->d_inode->i_uid, + current->fs->root->d_inode->i_gid, current->comm, + current->pid, current->uid, current->euid, + current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid); + putname(hap_chmod_filename); + error = -EPERM; + goto dput_and_out; + } + } +#endif newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; error = notify_change(dentry, &newattrs); diff -urP linux-2.2.20-ow1/fs/super.c linux-2.2.20-hap-2/fs/super.c --- linux-2.2.20-ow1/fs/super.c Fri Nov 2 11:39:08 2001 +++ linux-2.2.20-hap-2/fs/super.c Fri Nov 9 19:16:17 2001 @@ -36,6 +36,10 @@ #include #endif +#ifdef CONFIG_SECURE_CHROOT +#include +#endif + /* * We use a semaphore to synchronize all mount/umount * activity - imagine the mess if we have a race between @@ -1045,10 +1049,42 @@ unsigned long flags = 0; unsigned long page = 0; struct file dummy; /* allows read-write or read-only flag */ +#ifdef CONFIG_SECURE_CHROOT + char * hap_mount_dev; + char * hap_mount_path; +#endif lock_kernel(); if (!capable(CAP_SYS_ADMIN)) goto out; +#ifdef CONFIG_SECURE_CHROOT + if (!(hap_same_root_as_init(current))) { + /* + * This process is in a chrooted jail; don't let it (re)mount any filesystems. + */ + if(IS_ERR(hap_mount_dev = getname(dev_name))) + hap_mount_dev = "nodev"; + if(IS_ERR(hap_mount_path = getname(dir_name))) + hap_mount_path = "[err]"; + security_alert("refused attempt to mount [%s] as %s " + "from chrooted jail [%s]:%lu owned by %d.%d by " + "%s[%d], UID %d, EUID %d, parent %s[%d], UID " + "%d, EUID %d", + "chrooted mounts denied", + hap_mount_dev, hap_mount_path, + kdevname(current->fs->root->d_inode->i_dev), + current->fs->root->d_inode->i_ino, + current->fs->root->d_inode->i_uid, + current->fs->root->d_inode->i_gid, current->comm, current->pid, + current->uid, current->euid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, + current->p_pptr->euid); + putname(hap_mount_dev); + putname(hap_mount_path); + retval = -EPERM; + goto out; + } +#endif if ((new_flags & (MS_MGC_MSK | MS_REMOUNT)) == (MS_MGC_VAL | MS_REMOUNT)) { retval = copy_mount_options (data, &page); diff -urP linux-2.2.20-ow1/include/linux/kernel.h linux-2.2.20-hap-2/include/linux/kernel.h --- linux-2.2.20-ow1/include/linux/kernel.h Sat Nov 3 13:14:57 2001 +++ linux-2.2.20-hap-2/include/linux/kernel.h Sat Nov 10 02:20:12 2001 @@ -89,18 +89,33 @@ \ spin_lock(&security_alert_lock); \ \ -/* Make sure at least one minute passed since the last warning logged */ \ - if (!warning_time || jiffies - warning_time > 60 * HZ) { \ +/* Make sure at least one second passed since the last warning logged */ \ + if (!warning_time || jiffies - warning_time > HZ) { \ warning_time = jiffies; no_flood_yet = 1; \ - printk(KERN_ALERT "Security: " normal_msg "\n", ## args); \ + printk(KERN_WARNING "Security: " normal_msg "\n", ## args); \ } else if (no_flood_yet) { \ warning_time = jiffies; no_flood_yet = 0; \ - printk(KERN_ALERT "Security: more " flood_msg \ - ", logging disabled for a minute\n"); \ + printk(KERN_WARNING "Security: more " flood_msg \ + ", logging disabled for one second\n"); \ } \ \ spin_unlock(&security_alert_lock); \ }) + +#ifdef CONFIG_SECURE_CHROOT +#define hap_same_root(haptask1, haptask2) \ + /* if root devices and inodes match, processes share a \ + * common root (neither, or both together, are chrooted) */ \ + ((haptask1->fs->root->d_inode->i_dev == \ + haptask2->fs->root->d_inode->i_dev) && \ + (haptask1->fs->root->d_inode->i_ino == \ + haptask2->fs->root->d_inode->i_ino) ) + +#define hap_same_root_as_init(haptask) \ + /* compare the given process to init */ \ + hap_same_root(haptask, \ + (task[smp_num_cpus] ? : task[0])) /* voodoo */ +#endif /* CONFIG_SECURE_CHROOT */ #endif /* __KERNEL__ */ diff -urP linux-2.2.20-ow1/include/linux/sysctl.h linux-2.2.20-hap-2/include/linux/sysctl.h --- linux-2.2.20-ow1/include/linux/sysctl.h Sun Mar 25 11:37:40 2001 +++ linux-2.2.20-hap-2/include/linux/sysctl.h Fri Nov 9 19:16:17 2001 @@ -107,7 +107,8 @@ KERN_SHMALL=41, /* int: maximum size of shared memory */ KERN_SPARC_STOP_A=44, /* int: Sparc Stop-A enable */ KERN_HOTPLUG=49, /* string: path to hotplug policy agent */ - KERN_IEEE_EMULATION_WARNINGS=50 /* int: unimplemented ieee instructions */ + KERN_IEEE_EMULATION_WARNINGS=50, /* int: unimplemented ieee instructions */ + KERN_SECURITY=51 /* Security */ }; diff -urP linux-2.2.20-ow1/include/linux/tasks.h linux-2.2.20-hap-2/include/linux/tasks.h --- linux-2.2.20-ow1/include/linux/tasks.h Sun Mar 25 11:31:03 2001 +++ linux-2.2.20-hap-2/include/linux/tasks.h Sat Nov 10 02:20:12 2001 @@ -11,7 +11,7 @@ #define NR_CPUS 1 #endif -#define NR_TASKS 4080 /* On x86 Max about 4000 */ +#define NR_TASKS 2048 /* On x86 Max about 4000 */ #define MAX_TASKS_PER_USER 256 #define MIN_TASKS_LEFT_FOR_ROOT 64 diff -urP linux-2.2.20-ow1/include/net/dst.h linux-2.2.20-hap-2/include/net/dst.h --- linux-2.2.20-ow1/include/net/dst.h Sun Mar 25 11:31:07 2001 +++ linux-2.2.20-hap-2/include/net/dst.h Sat Nov 10 02:21:36 2001 @@ -16,7 +16,11 @@ * 1 - rare events and bugs (default) * 2 - trace mode. */ -#define RT_CACHE_DEBUG 0 +#ifdef CONFIG_SECURE_LOGGING +#define RT_CACHE_DEBUG 1 +#else +#define RT_CACHE_DEBUG 0 +#endif #define DST_GC_MIN (1*HZ) #define DST_GC_INC (5*HZ) diff -urP linux-2.2.20-ow1/kernel/fork.c linux-2.2.20-hap-2/kernel/fork.c --- linux-2.2.20-ow1/kernel/fork.c Sat Nov 3 13:14:57 2001 +++ linux-2.2.20-hap-2/kernel/fork.c Fri Nov 9 19:16:17 2001 @@ -746,6 +746,15 @@ free_uid(p); bad_fork_free: free_task_struct(p); +#ifdef CONFIG_SECURE_LOGGING + security_alert("fork failure errno %d by %s[%d], UID %d, EUID %d, " + "parent %s[%d], UID %d, EUID %d", + "fork failures", + retval, current->comm, current->pid, + current->uid, current->euid, + current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid); +#endif goto bad_fork; } diff -urP linux-2.2.20-ow1/kernel/signal.c linux-2.2.20-hap-2/kernel/signal.c --- linux-2.2.20-ow1/kernel/signal.c Fri Nov 2 11:39:16 2001 +++ linux-2.2.20-hap-2/kernel/signal.c Fri Nov 9 19:16:17 2001 @@ -254,6 +254,9 @@ { unsigned long flags; int ret; +#ifdef CONFIG_SECURE_CHROOT + struct task_struct * hap_init_task; +#endif #if DEBUG_SIG printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig); @@ -270,13 +273,67 @@ && (current->uid ^ t->suid) && (current->uid ^ t->uid) && !capable(CAP_KILL)) goto out_nolock; - - /* The null signal is a permissions and process existance probe. - No signal is actually delivered. Same goes for zombies. - We have to grab the spinlock now so that we do not race + /* We have to grab the spinlock now so that we do not race with flush_signals. */ - ret = 0; spin_lock_irqsave(&t->sigmask_lock, flags); + +#ifdef CONFIG_SECURE_CHROOT + /* + * chrooted processes can only send signals to other processes in + * the same jail, with the exception that they can send SIGALRM and + * SIGIO to any process, and SIGCHLD to their parent, regardless. + */ + /* + * this is still needed with the hap_same_root macros because we + * have to check init's task struct to be careful not to deref a + * null pointer later + */ + hap_init_task = task[smp_num_cpus] ? : task[0]; /* find task for init */ + if ( /* noop for 'signal zero' */ + sig && + + /* be careful not to deref a null pointer later */ + t->pid && t->fs && t->fs->root && t->fs->root->d_inode && t->p_pptr && + current->pid && current->fs && current->fs->root && + current->fs->root->d_inode && current->p_pptr && + hap_init_task && hap_init_task->pid && hap_init_task->fs && + hap_init_task->fs->root && hap_init_task->fs->root->d_inode && + + /* real work starting: check if signal is "mostly harmless" */ + !( sig == SIGALRM || sig == SIGIO || + + /* check if current is not chrooted */ + (hap_same_root_as_init(current)) || + + /* else check if current && target are under same chroot */ + (hap_same_root(t, current)) || + + /* else check if child is sending parent SIGCHILD */ + (t->pid == current->p_pptr->pid && sig == SIGCHLD) ) ) { + + /* Note: if target is init, its parent is task 0 */ + security_alert("refused signal %d out of chrooted jail [%s]:%lu " + "owned by %d.%d by %s[%d], UID %d, EUID %d, parent " + "%s[%d], UID %d, EUID %d to %s[%d], UID %d, EUID %d with " + "root [%s]:%lu owned by %d.%d, parent %s[%d], UID %d, EUID %d", + "refused signals", + sig, kdevname(current->fs->root->d_inode->i_dev), + current->fs->root->d_inode->i_ino, current->fs->root->d_inode->i_uid, + current->fs->root->d_inode->i_gid, current->comm, + current->pid, current->uid, current->euid, current->p_pptr->comm, + current->p_pptr->pid, current->p_pptr->uid, current->p_pptr->euid, + t->comm, t->pid, t->uid, t->euid, kdevname(t->fs->root->d_inode->i_dev), + t->fs->root->d_inode->i_ino, t->fs->root->d_inode->i_uid, + t->fs->root->d_inode->i_gid, t->p_pptr->comm, t->p_pptr->pid, + t->p_pptr->uid, t->p_pptr->euid); + spin_unlock_irqrestore(&t->sigmask_lock, flags); + goto out_nolock; + } + +#endif + ret = 0; + /* The null signal is a permissions and process existance probe. + No signal is actually delivered. Same goes for zombies. */ if (!sig || !t->sig) { spin_unlock_irqrestore(&t->sigmask_lock, flags); goto out_nolock; @@ -301,6 +358,34 @@ /* Inflict this corner case with recalculations, not mainline */ recalc_sigpending(t); break; +#if CONFIG_SECURE_LOGGING + case SIGSEGV: case SIGILL: case SIGABRT: case SIGBUS: +#ifdef __i386__ + security_alert("signal %d (%s addr 0x%08lx) sent to " + "%s[%d], UID %d, EUID %d, parent %s[%d], UID %d, EUID %d, " + "by %s[%d], UID %d, EUID %d, parent %s[%d], UID %d, EUID %d", + "signal warnings", + sig, (t->tss.error_code & 2) ? "write" : "read or execute", + t->tss.cr2, + t->comm, t->pid, t->uid, t->euid, t->p_pptr->comm, + t->p_pptr->pid, t->p_pptr->uid, t->p_pptr->euid, + current->comm, current->pid, current->uid, current->euid, + current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid); +#else + security_alert("signal %d sent to " + "%s[%d], UID %d, EUID %d, parent %s[%d], UID %d, EUID %d, " + "by %s[%d], UID %d, EUID %d, parent %s[%d], UID %d, EUID %d", + "signal warnings", + sig, + t->comm, t->pid, t->uid, t->euid, t->p_pptr->comm, + t->p_pptr->pid, t->p_pptr->uid, t->p_pptr->euid, + current->comm, current->pid, current->uid, current->euid, + current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid); +#endif + break; +#endif } /* Optimize away the signal, if it's a signal that can be diff -urP linux-2.2.20-ow1/kernel/sysctl.c linux-2.2.20-hap-2/kernel/sysctl.c --- linux-2.2.20-ow1/kernel/sysctl.c Sat Nov 3 13:14:57 2001 +++ linux-2.2.20-hap-2/kernel/sysctl.c Fri Nov 9 19:16:17 2001 @@ -96,12 +96,20 @@ static ctl_table fs_table[]; static ctl_table debug_table[]; static ctl_table dev_table[]; - +static ctl_table security_table[]; /* /proc declarations: */ #ifdef CONFIG_PROC_FS +/* Keep these here reguardless if CONFIG_SECURE_SYSCTL is defined or not */ +int sysctl_security = 1; +int sysctl_security_trace = 1; + +#ifdef CONFIG_SECURE_TRACE +int sysctl_security_trace_gid = 0; +#endif + static ssize_t proc_readsys(struct file *, char *, size_t, loff_t *); static ssize_t proc_writesys(struct file *, const char *, size_t, loff_t *); static int proc_sys_permission(struct inode *, int); @@ -251,6 +259,18 @@ &sysctl_ieee_emulation_warnings,sizeof(int),0644,NULL,&proc_dointvec}, #endif #endif + {KERN_SECURITY, "security", NULL, 0, 0550, security_table}, + {0} +}; + +enum {SEC_TRACE=1, SEC_TRACE_GID , SEC_SYSCTL}; +static ctl_table security_table[] = { + {SEC_TRACE, "trace", &sysctl_security_trace, sizeof (int), + 0640, NULL, &proc_dointvec}, +#ifdef CONFIG_SECURE_TRACE_USERGROUP + {SEC_TRACE_GID, "trace_gid", &sysctl_security_trace_gid, sizeof (int), + 0640, NULL, &proc_dointvec}, +#endif {0} }; diff -urP linux-2.2.20-ow1/kernel/time.c linux-2.2.20-hap-2/kernel/time.c --- linux-2.2.20-ow1/kernel/time.c Sun Mar 25 11:31:02 2001 +++ linux-2.2.20-hap-2/kernel/time.c Fri Nov 9 19:16:17 2001 @@ -108,6 +108,14 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_unlock_irq(&xtime_lock); +#ifdef CONFIG_SECURE_LOGGING + security_alert("time set by %s[%d], UID %d, EUID %d, parent %s[%d], " + "UID %d, EUID %d", + "time sets", + current->comm, current->pid, current->uid, current->euid, + current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid); +#endif return 0; } @@ -184,6 +192,14 @@ * globally block out interrupts when it runs. */ do_settimeofday(tv); +#ifdef CONFIG_SECURE_LOGGING + security_alert("time set by %s[%d], UID %d, EUID %d, parent %s[%d], " + "UID %d, EUID %d", + "time sets", + current->comm, current->pid, current->uid, current->euid, + current->p_pptr->comm, current->p_pptr->pid, + current->p_pptr->uid, current->p_pptr->euid); +#endif } return 0; } diff -urP linux-2.2.20-ow1/net/core/utils.c linux-2.2.20-hap-2/net/core/utils.c --- linux-2.2.20-ow1/net/core/utils.c Sun Mar 25 11:31:12 2001 +++ linux-2.2.20-hap-2/net/core/utils.c Fri Nov 9 19:16:17 2001 @@ -35,12 +35,21 @@ net_random(); } +#ifdef CONFIG_SECURE_LOGGING +int net_msg_cost = HZ; +#else int net_msg_cost = 5*HZ; +#endif int net_msg_burst = 10*5*HZ; /* +#ifdef CONFIG_SECURE_LOGGING + * This enforces a rate limit: not more than one kernel message + * every 1secs to make a denial-of-service attack harder. +#else * This enforces a rate limit: not more than one kernel message * every 5secs to make a denial-of-service attack impossible. +#endif * * All warning printk()s should be guarded by this function. */ diff -urP linux-2.2.20-ow1/net/ipv4/ip_fw.c linux-2.2.20-hap-2/net/ipv4/ip_fw.c --- linux-2.2.20-ow1/net/ipv4/ip_fw.c Sun Mar 25 11:31:12 2001 +++ linux-2.2.20-hap-2/net/ipv4/ip_fw.c Fri Nov 9 19:16:17 2001 @@ -416,34 +416,83 @@ __u32 *opt = (__u32 *) (ip + 1); int opti; - if (f) - { + if (f) { +#ifdef CONFIG_SECURE_NETWORK + /* log any accepted packet at kern.debug instead of kern.info */ + if (f->simplebranch==FW_ACCEPT || + f->simplebranch==FW_REDIRECT || + f->simplebranch==FW_MASQUERADE) + printk(KERN_DEBUG "Packet log: %s ",chainlabel); + else +#endif printk(KERN_INFO "Packet log: %s ",chainlabel); - printk("%s ",branchname(f->branch,f->simplebranch)); if (f->simplebranch==FW_REDIRECT) printk("%d ",f->ipfw.fw_redirpt); } +#ifdef CONFIG_SECURE_NETWORK + if (ip->protocol == IPPROTO_TCP + && !(ip->frag_off & __constant_htons(IP_OFFSET))) { + struct tcphdr *tcp = (struct tcphdr *)((__u32 *)ip + ip->ihl); + printk("%s PROTO=TCP %d.%d.%d.%d:%hu %d.%d.%d.%d:%hu " + "L=%hu:%hu:%hu S=0x%2.2hX I=%hu:%u:%u F=0x%4.4hX " + "T=%hu %c%c%c%c%c%c", + ifname, + NIPQUAD(ip->saddr), src_port, + NIPQUAD(ip->daddr), dst_port, + ntohs(ip->tot_len), ntohs(ip->tot_len) - ip->ihl*4, + ntohs(ip->tot_len) - ip->ihl*4 - tcp->doff*4, + ip->tos, ntohs(ip->id), ntohl(tcp->seq), + ntohl(tcp->ack_seq), ip->frag_off, ip->ttl, + tcp->ack ? 'A' : '.', + tcp->syn ? 'S' : '.', + tcp->fin ? 'F' : '.', + tcp->rst ? 'R' : '.', + tcp->psh ? 'P' : '.', + tcp->urg ? 'U' : '.' ); + } else if (ip->protocol == IPPROTO_UDP + && !(ip->frag_off & __constant_htons(IP_OFFSET))) { + struct udphdr *udp = (struct udphdr *)((__u32 *)ip + ip->ihl); + printk("%s PROTO=UDP %d.%d.%d.%d:%hu %d.%d.%d.%d:%hu " + "L=%hu:%u S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu", + ifname, + NIPQUAD(ip->saddr), src_port, + NIPQUAD(ip->daddr), dst_port, + ntohs(ip->tot_len), ntohs(udp->len), + ip->tos, ntohs(ip->id), ip->frag_off, ip->ttl); + } else if (ip->protocol == IPPROTO_ICMP + && !(ip->frag_off & __constant_htons(IP_OFFSET))) { + struct icmphdr *icmp = (struct icmphdr *)((__u32 *)ip + ip->ihl); + printk("%s PROTO=ICMP/%d:%d %d.%d.%d.%d %d.%d.%d.%d L=%hu " + "S=0x%2.2hX I=%hu:%hu:%hu F=0x%4.4hX T=%hu", + ifname, icmp->type, icmp->code, + NIPQUAD(ip->saddr), + NIPQUAD(ip->daddr), + ntohs(ip->tot_len), ip->tos, + ntohs(ip->id), ntohs(icmp->un.echo.id), + ntohs(icmp->un.echo.sequence), + ip->frag_off, ip->ttl); + } else { +#endif printk("%s PROTO=%d %d.%d.%d.%d:%hu %d.%d.%d.%d:%hu" " L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu", ifname, ip->protocol, - (ntohl(ip->saddr)>>24)&0xFF, - (ntohl(ip->saddr)>>16)&0xFF, - (ntohl(ip->saddr)>>8)&0xFF, - (ntohl(ip->saddr))&0xFF, - src_port, - (ntohl(ip->daddr)>>24)&0xFF, - (ntohl(ip->daddr)>>16)&0xFF, - (ntohl(ip->daddr)>>8)&0xFF, - (ntohl(ip->daddr))&0xFF, - dst_port, + NIPQUAD(ip->saddr), src_port, + NIPQUAD(ip->daddr), dst_port, ntohs(ip->tot_len), ip->tos, ntohs(ip->id), ntohs(ip->frag_off), ip->ttl); +#ifdef CONFIG_SECURE_NETWORK + } +#endif for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++) printk(" O=0x%8.8X", *opt++); +#ifdef CONFIG_SECURE_NETWORK + printk(" (#%d)\n", count); +#else printk(" %s(#%d)\n", syn ? "SYN " : /* "PENANCE" */ "", count); +#endif } /* function for checking chain labels for user space. */ diff -urP linux-2.2.20-ow1/net/ipv4/route.c linux-2.2.20-hap-2/net/ipv4/route.c --- linux-2.2.20-ow1/net/ipv4/route.c Fri Nov 2 11:39:16 2001 +++ linux-2.2.20-hap-2/net/ipv4/route.c Fri Nov 9 19:16:17 2001 @@ -715,12 +715,20 @@ return; reject_redirect: +#ifdef CONFIG_SECURE_LOGGING + security_alert("redirect from %d.%d.%d.%d/%s to %d.%d.%d.%d ignored; " + "path = %d.%d.%d.%d -> %d.%d.%d.%d, tos %02x\n", + "redirects ignored", + NIPQUAD(old_gw), dev->name, NIPQUAD(new_gw), + NIPQUAD(saddr), NIPQUAD(daddr), tos); +#else #ifdef CONFIG_IP_ROUTE_VERBOSE if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) printk(KERN_INFO "Redirect from %X/%s to %X ignored." "Path = %X -> %X, tos %02x\n", ntohl(old_gw), dev->name, ntohl(new_gw), ntohl(saddr), ntohl(daddr), tos); +#endif #endif } diff -urP linux-2.2.20-ow1/net/ipv4/tcp_ipv4.c linux-2.2.20-hap-2/net/ipv4/tcp_ipv4.c --- linux-2.2.20-ow1/net/ipv4/tcp_ipv4.c Sun Mar 25 11:37:41 2001 +++ linux-2.2.20-hap-2/net/ipv4/tcp_ipv4.c Fri Nov 9 19:16:17 2001 @@ -1747,6 +1747,14 @@ len < (th->doff * 4)) goto bad_packet; +#ifdef CONFIG_SECURE_NETWORK + /* Throw out packets with clearly bogus flags. */ + if ( ! (th->ack || th->syn || th->rst) || + (th->fin && (th->syn || th->rst) ) || + (th->rst && (th->syn || th->urg) ) || + (th->syn && th->urg) ) + goto tcp_bad_flags; +#endif #ifdef CONFIG_IP_TRANSPARENT_PROXY if (IPCB(skb)->redirport) sk = tcp_v4_proxy_lookup(th->dest, skb->nh.iph->saddr, th->source, @@ -1762,7 +1770,11 @@ } #endif if (!sk) +#ifdef CONFIG_SECURE_NETWORK + goto tcp_unserved; +#else goto no_tcp_socket; +#endif if(!ipsec_sk_policy(sk,skb)) goto discard_it; @@ -1780,6 +1792,52 @@ __skb_queue_tail(&sk->back_log, skb); return 0; +#ifdef CONFIG_SECURE_NETWORK + +tcp_bad_flags: + if(net_ratelimit()) + printk(KERN_INFO + "Packet log: badflag DENY %s PROTO=TCP %d.%d.%d.%d:%d " + "%d.%d.%d.%d:%d L=%hu:%u:%u S=0x%2.2hX I=%hu:%u:%u " + "T=%hu %c%c%c%c%c%c\n", + skb->dev->name, NIPQUAD(skb->nh.iph->saddr), ntohs(th->source), + NIPQUAD(skb->nh.iph->daddr), ntohs(th->dest), + ntohs(skb->nh.iph->tot_len), skb->len, skb->len - th->doff*4, + skb->nh.iph->tos, ntohs(skb->nh.iph->id), ntohl(th->seq), + ntohl(th->ack_seq), skb->nh.iph->ttl, + th->ack ? 'A' : '.', + th->syn ? 'S' : '.', + th->fin ? 'F' : '.', + th->rst ? 'R' : '.', + th->psh ? 'P' : '.', + th->urg ? 'U' : '.' ); + /* + * This will cause tcp_send_reset to *not* send. + */ + th->rst=1; + goto no_tcp_socket; + +tcp_unserved: + if(net_ratelimit()) + printk(KERN_INFO + "Packet log: unserved DENY %s PROTO=TCP %d.%d.%d.%d:%d " + "%d.%d.%d.%d:%d L=%hu:%u:%u S=0x%2.2hX " + "I=%hu:%u:%u T=%hu %c%c%c%c%c%c\n", + skb->dev->name, NIPQUAD(skb->nh.iph->saddr), ntohs(th->source), + NIPQUAD(skb->nh.iph->daddr), ntohs(th->dest), + ntohs(skb->nh.iph->tot_len), skb->len, skb->len - th->doff*4, + skb->nh.iph->tos, ntohs(skb->nh.iph->id), ntohl(th->seq), + ntohl(th->ack_seq), skb->nh.iph->ttl, + th->ack ? 'A' : '.', + th->syn ? 'S' : '.', + th->fin ? 'F' : '.', + th->rst ? 'R' : '.', + th->psh ? 'P' : '.', + th->urg ? 'U' : '.' ); +#ifdef CONFIG_SECURE_NET_SBD + th->rst=1; +#endif +#endif /* CONFIG_SECURE_NETWORK */ no_tcp_socket: tcp_v4_send_reset(skb); diff -urP linux-2.2.20-ow1/net/ipv4/udp.c linux-2.2.20-hap-2/net/ipv4/udp.c --- linux-2.2.20-ow1/net/ipv4/udp.c Sun Mar 25 11:37:41 2001 +++ linux-2.2.20-hap-2/net/ipv4/udp.c Fri Nov 9 19:16:17 2001 @@ -1137,6 +1137,14 @@ goto csum_error; #endif udp_statistics.UdpNoPorts++; +#ifdef CONFIG_SECURE_NETWORK + /* + * This will cause a message for _every_ UDP packet we didn't + * ask for, _including_ broadcasts. If you don't care about + * broadcasts, move the following line inside the if { .. } below. + */ + goto udp_unserved_port; +#else icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); /* @@ -1145,9 +1153,29 @@ */ kfree_skb(skb); return(0); +#endif } udp_deliver(sk, skb); return 0; + +#ifdef CONFIG_SECURE_NETWORK + +udp_unserved_port: + if(net_ratelimit()) + printk( KERN_INFO + "Packet log: unserved DENY %s PROTO=UDP %d.%d.%d.%d:%d %d.%d.%d.%d:%d " + "L=%hu:%u S=0x%2.2hX I=%hu T=%hu\n", + skb->dev->name, NIPQUAD(saddr), ntohs(uh->source), + NIPQUAD(daddr), ntohs(uh->dest), ntohs(skb->nh.iph->tot_len), + ntohs(uh->len), skb->nh.iph->tos, ntohs(skb->nh.iph->id), + skb->nh.iph->ttl); +#ifndef CONFIG_SECURE_NET_SBD + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); +#endif + skb->sk = NULL; + kfree_skb(skb); + return(0); +#endif /* CONFIG_SECURE_NETWORK */ csum_error: /* diff -urP linux-2.2.20-ow1/security/Common.in linux-2.2.20-hap-2/security/Common.in --- linux-2.2.20-ow1/security/Common.in Sat Nov 3 13:14:57 2001 +++ linux-2.2.20-hap-2/security/Common.in Fri Nov 9 19:16:17 2001 @@ -4,9 +4,26 @@ bool 'Restricted links in /tmp' CONFIG_SECURE_LINK bool 'Restricted FIFOs in /tmp' CONFIG_SECURE_FIFO +if [ "$CONFIG_SECURE_LINK" = "y" -o "CONFIG_SECURE_FIFO" = "y" ]; then + bool 'Allow links/fifos in non-world-writable +t dirs' CONFIG_SECURE_NOTSOMUCH +fi bool 'Restricted /proc' CONFIG_SECURE_PROC bool 'Special handling of fd 0, 1, and 2' CONFIG_SECURE_FD_0_1_2 bool 'Enforce RLIMIT_NPROC on execve(2)' CONFIG_SECURE_RLIMIT_NPROC if [ "$CONFIG_SYSVIPC" = "y" ]; then bool 'Destroy shared memory segments not in use' CONFIG_SECURE_SHM +fi +bool 'Unofficial bugfixes' CONFIG_SECURE_BUGFIX +bool 'Extra logging of unusual events' CONFIG_SECURE_LOGGING +bool 'Paranoid networking' CONFIG_SECURE_NETWORK +if [ "$CONFIG_SECURE_NETWORK" = "y" ]; then + bool 'Blackhole networking' CONFIG_SECURE_NET_SBD +fi +bool 'Restricted chroot' CONFIG_SECURE_CHROOT +bool 'Restricted ptrace' CONFIG_SECURE_TRACE +if [ "$CONFIG_SECURE_TRACE" == "y" ]; then + bool ' Allow special group' CONFIG_SECURE_TRACE_USERGROUP +fi +if [ "$CONFIG_SYSCTL" == "y" ]; then + bool 'Security Sysctl Support' CONFIG_SECURE_SYSCTL fi