diff -urN linux-2.4.18/Makefile linux-2.4.18-ctx9/Makefile --- linux-2.4.18/Makefile Mon Mar 4 08:40:14 2002 +++ linux-2.4.18-ctx9/Makefile Mon Mar 25 17:58:39 2002 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 18 -EXTRAVERSION = +EXTRAVERSION =ctx-9 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -urN linux-2.4.18/arch/i386/kernel/entry.S linux-2.4.18-ctx9/arch/i386/kernel/entry.S --- linux-2.4.18/arch/i386/kernel/entry.S Mon Mar 4 08:40:15 2002 +++ linux-2.4.18-ctx9/arch/i386/kernel/entry.S Mon Mar 25 17:58:39 2002 @@ -634,6 +634,8 @@ .long SYMBOL_NAME(sys_ni_syscall) /* 235 reserved for removexattr */ .long SYMBOL_NAME(sys_ni_syscall) /* reserved for lremovexattr */ .long SYMBOL_NAME(sys_ni_syscall) /* reserved for fremovexattr */ + .long SYMBOL_NAME(sys_new_s_context) + .long SYMBOL_NAME(sys_set_ipv4root) .rept NR_syscalls-(.-sys_call_table)/4 .long SYMBOL_NAME(sys_ni_syscall) diff -urN linux-2.4.18/arch/i386/kernel/ptrace.c linux-2.4.18-ctx9/arch/i386/kernel/ptrace.c --- linux-2.4.18/arch/i386/kernel/ptrace.c Tue Dec 18 15:16:34 2001 +++ linux-2.4.18-ctx9/arch/i386/kernel/ptrace.c Mon Mar 25 17:58:39 2002 @@ -170,7 +170,7 @@ if (child) get_task_struct(child); read_unlock(&tasklist_lock); - if (!child) + if (!child || child->s_context != current->s_context) goto out; ret = -EPERM; diff -urN linux-2.4.18/fs/devpts/inode.c linux-2.4.18-ctx9/fs/devpts/inode.c --- linux-2.4.18/fs/devpts/inode.c Mon Oct 29 17:03:55 2001 +++ linux-2.4.18-ctx9/fs/devpts/inode.c Mon Mar 25 17:58:39 2002 @@ -24,6 +24,7 @@ #include #include #include +#include #include "devpts_i.h" @@ -152,7 +153,6 @@ inode->i_op = &devpts_root_inode_operations; inode->i_fop = &devpts_root_operations; inode->i_nlink = 2; - s->u.generic_sbp = (void *) sbi; s->s_blocksize = 1024; s->s_blocksize_bits = 10; @@ -180,6 +180,19 @@ static DECLARE_FSTYPE(devpts_fs_type, "devpts", devpts_read_super, FS_SINGLE); +static int devpts_tty_permission(struct inode *inode, int mask) +{ + int ret = -EACCES; + if (current->s_context == inode->u.devpts_i.s_context){ + ret = vfs_permission(inode, mask); + } + return ret; +} + +struct inode_operations devpts_tty_inode_operations = { + permission: devpts_tty_permission, +}; + void devpts_pty_new(int number, kdev_t device) { struct super_block *sb = devpts_mnt->mnt_sb; @@ -198,6 +211,8 @@ inode->i_uid = sbi->setuid ? sbi->uid : current->fsuid; inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; + inode->u.devpts_i.s_context = current->s_context; + inode->i_op = &devpts_tty_inode_operations; init_special_inode(inode, S_IFCHR|sbi->mode, kdev_t_to_nr(device)); if ( sbi->inodes[number] ) { diff -urN linux-2.4.18/fs/devpts/root.c linux-2.4.18-ctx9/fs/devpts/root.c --- linux-2.4.18/fs/devpts/root.c Thu Dec 27 10:44:11 2001 +++ linux-2.4.18-ctx9/fs/devpts/root.c Mon Mar 25 17:58:39 2002 @@ -14,6 +14,7 @@ #include #include #include +#include #include "devpts_i.h" static int devpts_root_readdir(struct file *,void *,filldir_t); @@ -64,7 +65,10 @@ default: while ( nr - 2 < sbi->max_ptys ) { int ptynr = nr - 2; - if ( sbi->inodes[ptynr] ) { + struct inode *inode = sbi->inodes[ptynr]; + if ( inode != NULL + && (current->s_context == 1 + || inode->u.devpts_i.s_context == current->s_context)) { genptsname(numbuf, ptynr); if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr, DT_CHR) < 0 ) return 0; @@ -100,6 +104,7 @@ unsigned int entry; int i; const char *p; + struct inode *inode; dentry->d_op = &devpts_dentry_operations; @@ -126,10 +131,17 @@ if ( entry >= sbi->max_ptys ) return NULL; - if ( sbi->inodes[entry] ) - atomic_inc(&sbi->inodes[entry]->i_count); + inode = sbi->inodes[entry]; + if (inode != NULL + && inode->u.devpts_i.s_context == current->s_context){ + atomic_inc(&inode->i_count); + }else{ + inode = NULL; + } - d_add(dentry, sbi->inodes[entry]); + d_add(dentry, inode); return NULL; } + + diff -urN linux-2.4.18/fs/exec.c linux-2.4.18-ctx9/fs/exec.c --- linux-2.4.18/fs/exec.c Thu Dec 27 10:44:11 2001 +++ linux-2.4.18-ctx9/fs/exec.c Mon Mar 25 17:58:39 2002 @@ -685,7 +685,7 @@ kernel_cap_t new_permitted, working; int do_unlock = 0; - new_permitted = cap_intersect(bprm->cap_permitted, cap_bset); + new_permitted = cap_intersect(bprm->cap_permitted, current->cap_bset); working = cap_intersect(bprm->cap_inheritable, current->cap_inheritable); new_permitted = cap_combine(new_permitted, working); diff -urN linux-2.4.18/fs/ext2/ialloc.c linux-2.4.18-ctx9/fs/ext2/ialloc.c --- linux-2.4.18/fs/ext2/ialloc.c Mon Mar 4 08:40:25 2002 +++ linux-2.4.18-ctx9/fs/ext2/ialloc.c Mon Mar 25 17:58:39 2002 @@ -388,7 +388,7 @@ inode->u.ext2_i.i_new_inode = 1; inode->u.ext2_i.i_flags = dir->u.ext2_i.i_flags; if (S_ISLNK(mode)) - inode->u.ext2_i.i_flags &= ~(EXT2_IMMUTABLE_FL|EXT2_APPEND_FL); + inode->u.ext2_i.i_flags &= ~(EXT2_IMMUTABLE_FILE_FL | EXT2_IMMUTABLE_LINK_FL | EXT2_APPEND_FL); inode->u.ext2_i.i_block_group = group; if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) inode->i_flags |= S_SYNC; diff -urN linux-2.4.18/fs/ext2/inode.c linux-2.4.18-ctx9/fs/ext2/inode.c --- linux-2.4.18/fs/ext2/inode.c Mon Mar 4 08:40:25 2002 +++ linux-2.4.18-ctx9/fs/ext2/inode.c Mon Mar 25 17:58:39 2002 @@ -800,7 +800,7 @@ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) + if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode)) return; ext2_discard_prealloc(inode); @@ -1006,9 +1006,13 @@ inode->i_attr_flags |= ATTR_FLAG_APPEND; inode->i_flags |= S_APPEND; } - if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL) { - inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE; - inode->i_flags |= S_IMMUTABLE; + if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FILE_FL) { + inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE_FILE; + inode->i_flags |= S_IMMUTABLE_FILE; + } + if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_LINK_FL) { + inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE_LINK; + inode->i_flags |= S_IMMUTABLE_LINK; } if (inode->u.ext2_i.i_flags & EXT2_NOATIME_FL) { inode->i_attr_flags |= ATTR_FLAG_NOATIME; diff -urN linux-2.4.18/fs/ext2/ioctl.c linux-2.4.18-ctx9/fs/ext2/ioctl.c --- linux-2.4.18/fs/ext2/ioctl.c Wed Sep 27 22:41:33 2000 +++ linux-2.4.18-ctx9/fs/ext2/ioctl.c Mon Mar 25 17:58:39 2002 @@ -44,7 +44,7 @@ * * This test looks nicer. Thanks to Pauline Middelink */ - if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) { + if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FILE_FL | EXT2_IMMUTABLE_LINK_FL)) { if (!capable(CAP_LINUX_IMMUTABLE)) return -EPERM; } @@ -61,10 +61,17 @@ inode->i_flags |= S_APPEND; else inode->i_flags &= ~S_APPEND; - if (flags & EXT2_IMMUTABLE_FL) - inode->i_flags |= S_IMMUTABLE; + + if (flags & EXT2_IMMUTABLE_FILE_FL) + inode->i_flags |= S_IMMUTABLE_FILE; + else + inode->i_flags &= ~S_IMMUTABLE_FILE; + + if (flags & EXT2_IMMUTABLE_LINK_FL) + inode->i_flags |= S_IMMUTABLE_LINK; else - inode->i_flags &= ~S_IMMUTABLE; + inode->i_flags &= ~S_IMMUTABLE_LINK; + if (flags & EXT2_NOATIME_FL) inode->i_flags |= S_NOATIME; else diff -urN linux-2.4.18/fs/ext3/ialloc.c linux-2.4.18-ctx9/fs/ext3/ialloc.c --- linux-2.4.18/fs/ext3/ialloc.c Mon Mar 4 08:40:25 2002 +++ linux-2.4.18-ctx9/fs/ext3/ialloc.c Mon Mar 25 17:58:39 2002 @@ -485,7 +485,7 @@ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->u.ext3_i.i_flags = dir->u.ext3_i.i_flags & ~EXT3_INDEX_FL; if (S_ISLNK(mode)) - inode->u.ext3_i.i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL); + inode->u.ext3_i.i_flags &= ~(EXT3_IMMUTABLE_FILE_FL | EXT3_IMMUTABLE_LINK_FL | EXT3_APPEND_FL); #ifdef EXT3_FRAGMENTS inode->u.ext3_i.i_faddr = 0; inode->u.ext3_i.i_frag_no = 0; diff -urN linux-2.4.18/fs/ext3/inode.c linux-2.4.18-ctx9/fs/ext3/inode.c --- linux-2.4.18/fs/ext3/inode.c Mon Mar 4 08:40:25 2002 +++ linux-2.4.18-ctx9/fs/ext3/inode.c Mon Mar 25 17:58:39 2002 @@ -1845,7 +1845,7 @@ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) + if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode)) return; ext3_discard_prealloc(inode); @@ -2149,9 +2149,12 @@ /* inode->i_attr_flags |= ATTR_FLAG_APPEND; unused */ inode->i_flags |= S_APPEND; } - if (inode->u.ext3_i.i_flags & EXT3_IMMUTABLE_FL) { + if (inode->u.ext3_i.i_flags & EXT3_IMMUTABLE_FILE_FL) { /* inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE; unused */ - inode->i_flags |= S_IMMUTABLE; + inode->i_flags |= S_IMMUTABLE_FILE; + } + if (inode->u.ext3_i.i_flags & EXT3_IMMUTABLE_LINK_FL) { + inode->i_flags |= S_IMMUTABLE_LINK; } if (inode->u.ext3_i.i_flags & EXT3_NOATIME_FL) { /* inode->i_attr_flags |= ATTR_FLAG_NOATIME; unused */ diff -urN linux-2.4.18/fs/ext3/ioctl.c linux-2.4.18-ctx9/fs/ext3/ioctl.c --- linux-2.4.18/fs/ext3/ioctl.c Tue Dec 18 15:16:49 2001 +++ linux-2.4.18-ctx9/fs/ext3/ioctl.c Mon Mar 25 17:58:39 2002 @@ -53,7 +53,7 @@ * * This test looks nicer. Thanks to Pauline Middelink */ - if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) { + if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FILE_FL | EXT3_IMMUTABLE_LINK_FL)) { if (!capable(CAP_LINUX_IMMUTABLE)) return -EPERM; } @@ -89,10 +89,14 @@ inode->i_flags |= S_APPEND; else inode->i_flags &= ~S_APPEND; - if (flags & EXT3_IMMUTABLE_FL) - inode->i_flags |= S_IMMUTABLE; + if (flags & EXT3_IMMUTABLE_FILE_FL) + inode->i_flags |= S_IMMUTABLE_FILE; else - inode->i_flags &= ~S_IMMUTABLE; + inode->i_flags &= ~S_IMMUTABLE_FILE; + if (flags & EXT3_IMMUTABLE_LINK_FL) + inode->i_flags |= S_IMMUTABLE_LINK; + else + inode->i_flags &= ~S_IMMUTABLE_LINK; if (flags & EXT3_NOATIME_FL) inode->i_flags |= S_NOATIME; else diff -urN linux-2.4.18/fs/fat/file.c linux-2.4.18-ctx9/fs/fat/file.c --- linux-2.4.18/fs/fat/file.c Mon Oct 15 15:23:55 2001 +++ linux-2.4.18-ctx9/fs/fat/file.c Mon Mar 25 17:58:39 2002 @@ -119,7 +119,7 @@ /* Why no return value? Surely the disk could fail... */ if (IS_RDONLY (inode)) return /* -EPERM */; - if (IS_IMMUTABLE(inode)) + if (IS_IMMUTABLE_FILE(inode)) return /* -EPERM */; cluster = 1 << sbi->cluster_bits; /* diff -urN linux-2.4.18/fs/fat/inode.c linux-2.4.18-ctx9/fs/fat/inode.c --- linux-2.4.18/fs/fat/inode.c Mon Mar 4 08:40:25 2002 +++ linux-2.4.18-ctx9/fs/fat/inode.c Mon Mar 25 17:58:39 2002 @@ -947,7 +947,7 @@ } if(de->attr & ATTR_SYS) if (sbi->options.sys_immutable) - inode->i_flags |= S_IMMUTABLE; + inode->i_flags |= S_IMMUTABLE_FILE; MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED; /* this is as close to the truth as we can get ... */ inode->i_blksize = 1 << sbi->cluster_bits; diff -urN linux-2.4.18/fs/hpfs/file.c linux-2.4.18-ctx9/fs/hpfs/file.c --- linux-2.4.18/fs/hpfs/file.c Mon Oct 15 15:23:55 2001 +++ linux-2.4.18-ctx9/fs/hpfs/file.c Mon Mar 25 17:58:39 2002 @@ -60,7 +60,7 @@ void hpfs_truncate(struct inode *i) { - if (IS_IMMUTABLE(i)) return /*-EPERM*/; + if (IS_IMMUTABLE_FILE(i)) return /*-EPERM*/; i->i_hpfs_n_secs = 0; i->i_blocks = 1 + ((i->i_size + 511) >> 9); i->u.hpfs_i.mmu_private = i->i_size; diff -urN linux-2.4.18/fs/intermezzo/vfs.c linux-2.4.18-ctx9/fs/intermezzo/vfs.c --- linux-2.4.18/fs/intermezzo/vfs.c Mon Mar 4 08:40:26 2002 +++ linux-2.4.18-ctx9/fs/intermezzo/vfs.c Mon Mar 25 17:58:39 2002 @@ -89,7 +89,7 @@ if (IS_APPEND(dir)) return -EPERM; if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)|| - IS_IMMUTABLE(victim->d_inode)) + IS_IMMUTABLE_LINK(victim->d_inode)) return -EPERM; if (isdir) { if (!S_ISDIR(victim->d_inode->i_mode)) @@ -190,7 +190,7 @@ return -EROFS; } - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { + if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode)) { EXIT; return -EPERM; } @@ -231,7 +231,7 @@ return -EROFS; } - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { + if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode)) { EXIT; return -EPERM; } @@ -618,7 +618,7 @@ * A link to an append-only or immutable file cannot be created. */ error = -EPERM; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) { + if (IS_APPEND(inode) || IS_IMMUTABLE_LINK(inode)) { EXIT; goto exit_lock; } @@ -2220,7 +2220,7 @@ return -EROFS; } - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { + if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode)) { EXIT; return -EPERM; } diff -urN linux-2.4.18/fs/namei.c linux-2.4.18-ctx9/fs/namei.c --- linux-2.4.18/fs/namei.c Mon Mar 4 08:40:26 2002 +++ linux-2.4.18-ctx9/fs/namei.c Mon Mar 25 17:58:39 2002 @@ -152,6 +152,15 @@ { umode_t mode = inode->i_mode; + /* + A dir with permission bit all 0s is a dead zone for + process running in a vserver. By doing + chmod 000 /vservers + you fix the "escape from chroot" bug. + */ + if ((mode & 0777) == 0 + && S_ISDIR(mode) + && current->s_context != 0) return -EACCES; if (mask & MAY_WRITE) { /* * Nobody gets write access to a read-only fs. @@ -163,7 +172,7 @@ /* * Nobody gets write access to an immutable file. */ - if (IS_IMMUTABLE(inode)) + if (IS_IMMUTABLE_FILE(inode)) return -EACCES; } @@ -878,8 +887,7 @@ return error; if (IS_APPEND(dir)) return -EPERM; - if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)|| - IS_IMMUTABLE(victim->d_inode)) + if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||IS_IMMUTABLE_LINK(victim->d_inode)) return -EPERM; if (isdir) { if (!S_ISDIR(victim->d_inode->i_mode)) @@ -1595,7 +1603,7 @@ * A link to an append-only or immutable file cannot be created. */ error = -EPERM; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) + if (IS_APPEND(inode) || IS_IMMUTABLE_LINK(inode)) goto exit_lock; if (!dir->i_op || !dir->i_op->link) goto exit_lock; diff -urN linux-2.4.18/fs/nfsd/vfs.c linux-2.4.18-ctx9/fs/nfsd/vfs.c --- linux-2.4.18/fs/nfsd/vfs.c Thu Dec 27 10:44:13 2001 +++ linux-2.4.18-ctx9/fs/nfsd/vfs.c Mon Mar 25 17:58:39 2002 @@ -1484,7 +1484,7 @@ if (acc == MAY_NOP) return 0; #if 0 - dprintk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s\n", + dprintk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s%s\n", acc, (acc & MAY_READ)? " read" : "", (acc & MAY_WRITE)? " write" : "", @@ -1494,7 +1494,8 @@ (acc & MAY_LOCK)? " lock" : "", (acc & MAY_OWNER_OVERRIDE)? " owneroverride" : "", inode->i_mode, - IS_IMMUTABLE(inode)? " immut" : "", + IS_IMMUTABLE_FILE(inode)? " immut(F)" : "", + IS_IMMUTABLE_LINK(inode)? " immut(L)" : "", IS_APPEND(inode)? " append" : "", IS_RDONLY(inode)? " ro" : ""); dprintk(" owner %d/%d user %d/%d\n", @@ -1509,7 +1510,7 @@ if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) { if (EX_RDONLY(exp) || IS_RDONLY(inode)) return nfserr_rofs; - if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode)) + if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE_FILE(inode)) return nfserr_perm; } if ((acc & MAY_TRUNC) && IS_APPEND(inode)) diff -urN linux-2.4.18/fs/open.c linux-2.4.18-ctx9/fs/open.c --- linux-2.4.18/fs/open.c Mon Oct 29 17:04:22 2001 +++ linux-2.4.18-ctx9/fs/open.c Mon Mar 25 17:58:39 2002 @@ -122,7 +122,7 @@ goto dput_and_out; error = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) + if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode)) goto dput_and_out; /* @@ -470,7 +470,7 @@ if (IS_RDONLY(inode)) goto out_putf; err = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) + if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode)) goto out_putf; if (mode == (mode_t) -1) mode = inode->i_mode; @@ -501,7 +501,7 @@ goto dput_and_out; error = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) + if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode)) goto dput_and_out; if (mode == (mode_t) -1) @@ -531,7 +531,7 @@ if (IS_RDONLY(inode)) goto out; error = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) + if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode)) goto out; if (user == (uid_t) -1) user = inode->i_uid; diff -urN linux-2.4.18/fs/proc/array.c linux-2.4.18-ctx9/fs/proc/array.c --- linux-2.4.18/fs/proc/array.c Mon Oct 29 17:04:22 2001 +++ linux-2.4.18-ctx9/fs/proc/array.c Mon Mar 25 17:58:39 2002 @@ -75,6 +75,7 @@ #include #include #include +#include /* Gcc optimizes away "strlen(x)" for constant x */ #define ADDBUF(buffer, string) \ @@ -147,8 +148,12 @@ static inline char * task_state(struct task_struct *p, char *buffer) { int g; - + pid_t ppid; read_lock(&tasklist_lock); + ppid = p->p_opptr->pid; + if (ppid != 0 + && current->s_info != NULL + && current->s_info->initpid == ppid) ppid = 1; buffer += sprintf(buffer, "State:\t%s\n" "Tgid:\t%d\n" @@ -158,7 +163,7 @@ "Uid:\t%d\t%d\t%d\t%d\n" "Gid:\t%d\t%d\t%d\t%d\n", get_task_state(p), p->tgid, - p->pid, p->pid ? p->p_opptr->pid : 0, 0, + p->pid, p->pid ? ppid : 0, 0, p->uid, p->euid, p->suid, p->fsuid, p->gid, p->egid, p->sgid, p->fsgid); read_unlock(&tasklist_lock); @@ -263,10 +268,12 @@ { return buffer + sprintf(buffer, "CapInh:\t%016x\n" "CapPrm:\t%016x\n" - "CapEff:\t%016x\n", + "CapEff:\t%016x\n" + "CapBset:\t%016x\n", cap_t(p->cap_inheritable), cap_t(p->cap_permitted), - cap_t(p->cap_effective)); + cap_t(p->cap_effective), + cap_t(p->cap_bset)); } @@ -288,6 +295,24 @@ } buffer = task_sig(task, buffer); buffer = task_cap(task, buffer); + buffer += sprintf (buffer,"s_context: %d\n",task->s_context); + buffer += sprintf (buffer,"ipv4root: %08lx\n",task->ipv4root); + buffer += sprintf (buffer,"ipv4root_bcast: %08lx\n",task->ipv4root_bcast); + if (task->s_info != NULL){ + buffer += sprintf (buffer,"ctxticks: %d %ld %d\n" + ,atomic_read(&task->s_info->ticks),task->counter + ,task->s_info->refcount); + buffer += sprintf (buffer,"ctxflags: %d\n" + ,task->s_info->flags); + buffer += sprintf (buffer,"initpid: %d\n" + ,task->s_info->initpid); + }else{ + buffer += sprintf (buffer,"ctxticks: none\n"); + buffer += sprintf (buffer,"ctxflags: none\n"); + buffer += sprintf (buffer,"initpid: none\n"); + } + buffer += sprintf (buffer,"__NR_new_s_context: %d\n",__NR_new_s_context); + buffer += sprintf (buffer,"__NR_set_ipv4root: %d rev1\n",__NR_set_ipv4root); #if defined(CONFIG_ARCH_S390) buffer = task_show_regs(task, buffer); #endif @@ -341,6 +366,8 @@ read_lock(&tasklist_lock); ppid = task->pid ? task->p_opptr->pid : 0; + if (current->s_info != NULL + && current->s_info->initpid == ppid) ppid = 1; read_unlock(&tasklist_lock); res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \ diff -urN linux-2.4.18/fs/proc/base.c linux-2.4.18-ctx9/fs/proc/base.c --- linux-2.4.18/fs/proc/base.c Mon Mar 4 08:40:26 2002 +++ linux-2.4.18-ctx9/fs/proc/base.c Mon Mar 25 17:58:39 2002 @@ -972,6 +972,12 @@ if (!task) goto out; + if (pid != 1 + && current->s_context != 1 + && task->s_context != current->s_context){ + free_task_struct(task); + goto out; + } inode = proc_pid_make_inode(dir->i_sb, task, PROC_PID_INO); free_task_struct(task); @@ -982,7 +988,7 @@ inode->i_op = &proc_base_inode_operations; inode->i_fop = &proc_base_operations; inode->i_nlink = 3; - inode->i_flags|=S_IMMUTABLE; + inode->i_flags|=S_IMMUTABLE_FILE; dentry->d_op = &pid_base_dentry_operations; d_add(dentry, inode); @@ -1018,6 +1024,19 @@ int pid = p->pid; if (!pid) continue; + /* Even if the pid 1 is not part of the security context */ + /* we show it anyway. This makes the security box */ + /* more standard (and helps pstree do its job) */ + /* So current process "knows" pid 1 exist anyway and can't */ + /* send any signal either */ + + /* A process with security context 1 can see all processes */ + if (pid != 1 + && current->s_context != 1 + && p->s_context != current->s_context) continue; + /* We hide the fakeinit process since we show it as process 1 */ + if (current->s_info != NULL + && current->s_info->initpid == pid) continue; if (--index >= 0) continue; pids[nr_pids] = pid; diff -urN linux-2.4.18/fs/udf/inode.c linux-2.4.18-ctx9/fs/udf/inode.c --- linux-2.4.18/fs/udf/inode.c Mon Mar 4 08:40:27 2002 +++ linux-2.4.18-ctx9/fs/udf/inode.c Mon Mar 25 17:58:39 2002 @@ -863,7 +863,7 @@ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) + if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode)) return; if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) diff -urN linux-2.4.18/fs/ufs/truncate.c linux-2.4.18-ctx9/fs/ufs/truncate.c --- linux-2.4.18/fs/ufs/truncate.c Mon Mar 4 08:40:27 2002 +++ linux-2.4.18-ctx9/fs/ufs/truncate.c Mon Mar 25 17:58:39 2002 @@ -434,7 +434,7 @@ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) return; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) + if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode)) return; while (1) { retry = ufs_trunc_direct(inode); diff -urN linux-2.4.18/include/asm-i386/unistd.h linux-2.4.18-ctx9/include/asm-i386/unistd.h --- linux-2.4.18/include/asm-i386/unistd.h Mon Mar 4 08:40:28 2002 +++ linux-2.4.18-ctx9/include/asm-i386/unistd.h Mon Mar 25 17:58:39 2002 @@ -242,6 +242,8 @@ #define __NR_removexattr 235 #define __NR_lremovexattr 236 #define __NR_fremovexattr 237 +#define __NR_new_s_context 238 +#define __NR_set_ipv4root 239 /* user-visible error numbers are in the range -1 - -124: see */ diff -urN linux-2.4.18/include/linux/capability.h linux-2.4.18-ctx9/include/linux/capability.h --- linux-2.4.18/include/linux/capability.h Tue Mar 19 19:29:37 2002 +++ linux-2.4.18-ctx9/include/linux/capability.h Mon Mar 25 17:58:39 2002 @@ -231,6 +231,7 @@ /* Allow enabling/disabling tagged queuing on SCSI controllers and sending arbitrary SCSI commands */ /* Allow setting encryption key on loopback filesystem */ +/* Allow the selection of a security context */ #define CAP_SYS_ADMIN 21 @@ -278,6 +279,10 @@ /* Allow taking of leases on files */ #define CAP_LEASE 28 + +/* Allow opening special device file */ + +#define CAP_OPENDEV 29 #ifdef __KERNEL__ /* diff -urN linux-2.4.18/include/linux/devpts_fs_info.h linux-2.4.18-ctx9/include/linux/devpts_fs_info.h --- linux-2.4.18/include/linux/devpts_fs_info.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.18-ctx9/include/linux/devpts_fs_info.h Mon Mar 25 17:58:39 2002 @@ -0,0 +1,4 @@ +struct devpts_inode_info{ + int s_context; +}; + diff -urN linux-2.4.18/include/linux/ext2_fs.h linux-2.4.18-ctx9/include/linux/ext2_fs.h --- linux-2.4.18/include/linux/ext2_fs.h Tue Mar 19 19:29:41 2002 +++ linux-2.4.18-ctx9/include/linux/ext2_fs.h Mon Mar 25 17:58:39 2002 @@ -187,7 +187,7 @@ #define EXT2_UNRM_FL 0x00000002 /* Undelete */ #define EXT2_COMPR_FL 0x00000004 /* Compress file */ #define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */ -#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */ +#define EXT2_IMMUTABLE_FILE_FL 0x00000010 /* Immutable file */ #define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */ #define EXT2_NODUMP_FL 0x00000040 /* do not dump file */ #define EXT2_NOATIME_FL 0x00000080 /* do not update atime */ @@ -198,10 +198,11 @@ #define EXT2_ECOMPR_FL 0x00000800 /* Compression error */ /* End compression flags --- maybe not all used */ #define EXT2_BTREE_FL 0x00001000 /* btree format dir */ +#define EXT2_IMMUTABLE_LINK_FL 0x00008000 /* Immutable link */ #define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ -#define EXT2_FL_USER_VISIBLE 0x00001FFF /* User visible flags */ -#define EXT2_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */ +#define EXT2_FL_USER_VISIBLE 0x00009FFF /* User visible flags */ +#define EXT2_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */ /* * ioctl commands diff -urN linux-2.4.18/include/linux/ext3_fs.h linux-2.4.18-ctx9/include/linux/ext3_fs.h --- linux-2.4.18/include/linux/ext3_fs.h Tue Mar 19 19:30:39 2002 +++ linux-2.4.18-ctx9/include/linux/ext3_fs.h Mon Mar 25 17:58:39 2002 @@ -190,7 +190,7 @@ #define EXT3_UNRM_FL 0x00000002 /* Undelete */ #define EXT3_COMPR_FL 0x00000004 /* Compress file */ #define EXT3_SYNC_FL 0x00000008 /* Synchronous updates */ -#define EXT3_IMMUTABLE_FL 0x00000010 /* Immutable file */ +#define EXT3_IMMUTABLE_FILE_FL 0x00000010 /* Immutable file */ #define EXT3_APPEND_FL 0x00000020 /* writes to file may only append */ #define EXT3_NODUMP_FL 0x00000040 /* do not dump file */ #define EXT3_NOATIME_FL 0x00000080 /* do not update atime */ @@ -203,10 +203,11 @@ #define EXT3_INDEX_FL 0x00001000 /* hash-indexed directory */ #define EXT3_IMAGIC_FL 0x00002000 /* AFS directory */ #define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */ +#define EXT3_IMMUTABLE_LINK_FL 0x00008000 /* Immutable link */ #define EXT3_RESERVED_FL 0x80000000 /* reserved for ext3 lib */ -#define EXT3_FL_USER_VISIBLE 0x00005FFF /* User visible flags */ -#define EXT3_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */ +#define EXT3_FL_USER_VISIBLE 0x0000DFFF /* User visible flags */ +#define EXT3_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */ /* * Inode dynamic state flags diff -urN linux-2.4.18/include/linux/fs.h linux-2.4.18-ctx9/include/linux/fs.h --- linux-2.4.18/include/linux/fs.h Mon Mar 4 08:40:29 2002 +++ linux-2.4.18-ctx9/include/linux/fs.h Mon Mar 25 17:58:39 2002 @@ -128,13 +128,14 @@ /* Inode flags - they have nothing to superblock flags now */ -#define S_SYNC 1 /* Writes are synced at once */ -#define S_NOATIME 2 /* Do not update access times */ -#define S_QUOTA 4 /* Quota initialized for file */ -#define S_APPEND 8 /* Append-only file */ -#define S_IMMUTABLE 16 /* Immutable file */ -#define S_DEAD 32 /* removed, but still open directory */ -#define S_NOQUOTA 64 /* Inode is not counted to quota */ +#define S_SYNC 1 /* Writes are synced at once */ +#define S_NOATIME 2 /* Do not update access times */ +#define S_QUOTA 4 /* Quota initialized for file */ +#define S_APPEND 8 /* Append-only file */ +#define S_IMMUTABLE_FILE 16 /* Immutable file */ +#define S_DEAD 32 /* removed, but still open directory */ +#define S_NOQUOTA 64 /* Inode is not counted to quota */ +#define S_IMMUTABLE_LINK 128 /* Immutable links */ /* * Note that nosuid etc flags are inode-specific: setting some file-system @@ -158,7 +159,8 @@ #define IS_QUOTAINIT(inode) ((inode)->i_flags & S_QUOTA) #define IS_NOQUOTA(inode) ((inode)->i_flags & S_NOQUOTA) #define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) -#define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE) +#define IS_IMMUTABLE_FILE(inode) ((inode)->i_flags & S_IMMUTABLE_FILE) +#define IS_IMMUTABLE_LINK(inode) ((((inode)->i_flags & S_IMMUTABLE_FILE) << 3) ^ ((inode)->i_flags & S_IMMUTABLE_LINK) ) #define IS_NOATIME(inode) (__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME)) #define IS_NODIRATIME(inode) __IS_FLG(inode, MS_NODIRATIME) @@ -316,6 +318,7 @@ #include #include #include +#include /* * Attribute flags. These should be or-ed together to figure out what @@ -357,11 +360,12 @@ /* * This is the inode attributes flag definitions */ -#define ATTR_FLAG_SYNCRONOUS 1 /* Syncronous write */ -#define ATTR_FLAG_NOATIME 2 /* Don't update atime */ -#define ATTR_FLAG_APPEND 4 /* Append-only file */ -#define ATTR_FLAG_IMMUTABLE 8 /* Immutable file */ -#define ATTR_FLAG_NODIRATIME 16 /* Don't update atime for directory */ +#define ATTR_FLAG_SYNCRONOUS 1 /* Syncronous write */ +#define ATTR_FLAG_NOATIME 2 /* Don't update atime */ +#define ATTR_FLAG_APPEND 4 /* Append-only file */ +#define ATTR_FLAG_IMMUTABLE_FILE 8 /* Immutable file */ +#define ATTR_FLAG_NODIRATIME 16 /* Don't update atime for directory */ +#define ATTR_FLAG_IMMUTABLE_LINK 32 /* Immutable file */ /* * Includes for diskquotas and mount structures. @@ -506,6 +510,7 @@ struct socket socket_i; struct usbdev_inode_info usbdev_i; struct jffs2_inode_info jffs2_i; + struct devpts_inode_info devpts_i; void *generic_ip; } u; }; diff -urN linux-2.4.18/include/linux/sched.h linux-2.4.18-ctx9/include/linux/sched.h --- linux-2.4.18/include/linux/sched.h Fri Feb 15 19:30:45 2002 +++ linux-2.4.18-ctx9/include/linux/sched.h Mon Mar 25 17:58:39 2002 @@ -268,6 +268,7 @@ /* Hash table maintenance information */ struct user_struct *next, **pprev; uid_t uid; + int s_context; }; #define get_current_user() ({ \ @@ -275,6 +276,35 @@ atomic_inc(&__user->__count); \ __user; }) + +/* + We may have a different domainname and nodename for each security + context. By default, a security context share the same as its + parent, potentially the information in system_utsname +*/ +#define S_CTX_INFO_LOCK 1 /* Can't request a new s_context */ +#define S_CTX_INFO_SCHED 2 /* All process in the s_context */ + /* Contribute to the schedular */ +#define S_CTX_INFO_NPROC 4 /* Limit number of processes in a context */ +#define S_CTX_INFO_PRIVATE 8 /* Noone can join this security context */ +#define S_CTX_INFO_INIT 16 /* This process wants to become the */ + /* logical process 1 of the security */ + /* context */ + + +struct context_info{ + int refcount; + int s_context; + char nodename[65]; + char domainname[65]; + int flags; /* S_CTX_INFO_xxx */ + atomic_t ticks; /* Number of ticks used by all process */ + /* in the s_context */ + int initpid; /* PID of the logical process 1 of the */ + /* of the context */ +}; + + extern struct user_struct root_user; #define INIT_USER (&root_user) @@ -399,6 +429,13 @@ unsigned long sas_ss_sp; size_t sas_ss_size; int (*notifier)(void *priv); +/* Field to make virtual server running in chroot more isolated */ + int s_context; /* Process can only deal with other processes */ + /* with the same s_context */ + __u32 cap_bset; /* Maximum capability of this process and children */ + unsigned long ipv4root; /* Process can only bind to this iP */ + unsigned long ipv4root_bcast; + struct context_info *s_info; void *notifier_data; sigset_t *notifier_mask; @@ -501,6 +538,7 @@ blocked: {{0}}, \ alloc_lock: SPIN_LOCK_UNLOCKED, \ journal_info: NULL, \ + cap_bset: CAP_INIT_EFF_SET, \ } @@ -565,7 +603,7 @@ } /* per-UID process charging. */ -extern struct user_struct * alloc_uid(uid_t); +extern struct user_struct * alloc_uid(int, uid_t); extern void free_uid(struct user_struct *); #include @@ -926,6 +964,11 @@ mntput(rootmnt); return res; } + +/* Manage the reference count of the context_info pointer */ +void sys_release_s_info (struct task_struct *); +void sys_assign_s_info (struct task_struct *); +void sys_alloc_s_info (void); #endif /* __KERNEL__ */ diff -urN linux-2.4.18/include/net/route.h linux-2.4.18-ctx9/include/net/route.h --- linux-2.4.18/include/net/route.h Mon Mar 4 08:40:29 2002 +++ linux-2.4.18-ctx9/include/net/route.h Mon Mar 25 17:58:39 2002 @@ -160,6 +160,16 @@ static inline int ip_route_connect(struct rtable **rp, u32 dst, u32 src, u32 tos, int oif) { int err; + if (current->ipv4root != 0){ + if (src == 0){ + src = current->ipv4root; + }else if (current->ipv4root != src){ + return -EPERM; + } + if (dst == 0x0100007f && current->s_context != 0){ + dst = current->ipv4root; + } + } err = ip_route_output(rp, dst, src, tos, oif); if (err || (dst && src)) return err; diff -urN linux-2.4.18/include/net/sock.h linux-2.4.18-ctx9/include/net/sock.h --- linux-2.4.18/include/net/sock.h Fri Feb 15 19:33:26 2002 +++ linux-2.4.18-ctx9/include/net/sock.h Mon Mar 25 17:58:39 2002 @@ -490,6 +490,7 @@ /* Socket demultiplex comparisons on incoming packets. */ __u32 daddr; /* Foreign IPv4 addr */ __u32 rcv_saddr; /* Bound local IPv4 addr */ + __u32 bcast_addr; /* Local bcast addr, for ipv4root */ __u16 dport; /* Destination port */ unsigned short num; /* Local port */ int bound_dev_if; /* Bound device index if != 0 */ @@ -668,7 +669,10 @@ /* RPC layer private data */ void *user_data; - + + /* Context of process creating this socket */ + int s_context; + /* Callbacks */ void (*state_change)(struct sock *sk); void (*data_ready)(struct sock *sk,int bytes); diff -urN linux-2.4.18/include/net/tcp.h linux-2.4.18-ctx9/include/net/tcp.h --- linux-2.4.18/include/net/tcp.h Fri Feb 15 19:34:34 2002 +++ linux-2.4.18-ctx9/include/net/tcp.h Mon Mar 25 17:58:39 2002 @@ -190,6 +190,7 @@ struct in6_addr v6_daddr; struct in6_addr v6_rcv_saddr; #endif + int s_context; }; extern kmem_cache_t *tcp_timewait_cachep; diff -urN linux-2.4.18/ipc/util.c linux-2.4.18-ctx9/ipc/util.c --- linux-2.4.18/ipc/util.c Mon Oct 15 15:23:57 2001 +++ linux-2.4.18-ctx9/ipc/util.c Mon Mar 25 17:58:39 2002 @@ -93,6 +93,7 @@ struct kern_ipc_perm* p; for (id = 0; id <= ids->max_id; id++) { + if (ids->entries[id].s_context != current->s_context) continue; p = ids->entries[id].p; if(p==NULL) continue; @@ -167,6 +168,7 @@ spin_lock(&ids->ary); ids->entries[id].p = new; + ids->entries[id].s_context = current->s_context; return id; } diff -urN linux-2.4.18/ipc/util.h linux-2.4.18-ctx9/ipc/util.h --- linux-2.4.18/ipc/util.h Thu Jul 5 13:25:28 2001 +++ linux-2.4.18-ctx9/ipc/util.h Mon Mar 25 17:58:39 2002 @@ -25,6 +25,7 @@ struct ipc_id { struct kern_ipc_perm* p; + int s_context; // Context owning this ID }; @@ -74,8 +75,12 @@ spin_lock(&ids->ary); out = ids->entries[lid].p; - if(out==NULL) + if(out==NULL + || (ids->entries[lid].s_context != current->s_context + && current->s_context != 1)){ spin_unlock(&ids->ary); + out = NULL; + } return out; } diff -urN linux-2.4.18/kernel/exit.c linux-2.4.18-ctx9/kernel/exit.c --- linux-2.4.18/kernel/exit.c Mon Mar 4 08:40:29 2002 +++ linux-2.4.18-ctx9/kernel/exit.c Mon Mar 25 17:58:39 2002 @@ -65,6 +65,7 @@ current->counter += p->counter; if (current->counter >= MAX_COUNTER) current->counter = MAX_COUNTER; + sys_release_s_info(p); p->pid = 0; free_task_struct(p); } else { @@ -158,13 +159,21 @@ static inline void forget_original_parent(struct task_struct * father) { struct task_struct * p, *reaper; + struct task_struct *vchild_reaper = child_reaper; read_lock(&tasklist_lock); - + if (father->s_info != NULL){ + pid_t initpid = father->s_info->initpid; + if (initpid != 0 + && father->pid != initpid){ + struct task_struct *r = find_task_by_pid(initpid); + if (r != NULL) vchild_reaper = r; + } + } /* Next in our thread group */ reaper = next_thread(father); if (reaper == father) - reaper = child_reaper; + reaper = vchild_reaper; for_each_task(p) { if (p->p_opptr == father) { @@ -174,7 +183,7 @@ /* Make sure we're not reparenting to ourselves */ if (p == reaper) - p->p_opptr = child_reaper; + p->p_opptr = vchild_reaper; else p->p_opptr = reaper; diff -urN linux-2.4.18/kernel/fork.c linux-2.4.18-ctx9/kernel/fork.c --- linux-2.4.18/kernel/fork.c Mon Mar 4 08:40:29 2002 +++ linux-2.4.18-ctx9/kernel/fork.c Mon Mar 25 17:58:39 2002 @@ -588,6 +588,10 @@ *p = *current; retval = -EAGAIN; + if (p->s_info != NULL && (p->s_info->flags & S_CTX_INFO_NPROC)!=0){ + if (p->s_info->refcount >= p->rlim[RLIMIT_NPROC].rlim_max) + goto bad_fork_free; + } /* * Check if we are over our maximum process limit, but be sure to * exclude root. This is needed to make it possible for login and @@ -597,6 +601,8 @@ if (atomic_read(&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur && !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE)) goto bad_fork_free; + + sys_assign_s_info (p); atomic_inc(&p->user->__count); atomic_inc(&p->user->processes); diff -urN linux-2.4.18/kernel/printk.c linux-2.4.18-ctx9/kernel/printk.c --- linux-2.4.18/kernel/printk.c Mon Mar 4 08:40:29 2002 +++ linux-2.4.18-ctx9/kernel/printk.c Mon Mar 25 17:58:39 2002 @@ -172,6 +172,8 @@ char c; int error = 0; + if (!capable(CAP_SYS_ADMIN) && current->s_context != 0) return -EPERM; + switch (type) { case 0: /* Close log */ break; diff -urN linux-2.4.18/kernel/sched.c linux-2.4.18-ctx9/kernel/sched.c --- linux-2.4.18/kernel/sched.c Thu Dec 27 10:44:16 2001 +++ linux-2.4.18-ctx9/kernel/sched.c Mon Mar 25 17:58:39 2002 @@ -165,7 +165,13 @@ * Don't do any other calculations if the time slice is * over.. */ - weight = p->counter; + if (p->s_info != NULL + && (p->s_info->flags & S_CTX_INFO_SCHED)!=0){ + weight = atomic_read (&p->s_info->ticks)/p->s_info->refcount; + weight = (weight+p->counter)>>1; + }else{ + weight = p->counter; + } if (!weight) goto out; @@ -620,8 +626,23 @@ spin_unlock_irq(&runqueue_lock); read_lock(&tasklist_lock); - for_each_task(p) + /* + Reset the s_info->ticks to the sum off all + member processes p->counter + */ + for_each_task(p){ + if (p->s_info != NULL + && (p->s_info->flags & S_CTX_INFO_SCHED)!=0){ + atomic_set (&p->s_info->ticks,0); + } + } + for_each_task(p){ p->counter = (p->counter >> 1) + NICE_TO_TICKS(p->nice); + if (p->s_info != NULL + && (p->s_info->flags & S_CTX_INFO_SCHED)!=0){ + atomic_add (p->counter,&p->s_info->ticks); + } + } read_unlock(&tasklist_lock); spin_lock_irq(&runqueue_lock); goto repeat_schedule; diff -urN linux-2.4.18/kernel/signal.c linux-2.4.18-ctx9/kernel/signal.c --- linux-2.4.18/kernel/signal.c Tue Dec 18 15:16:54 2001 +++ linux-2.4.18-ctx9/kernel/signal.c Mon Mar 25 17:58:39 2002 @@ -592,7 +592,9 @@ retval = -ESRCH; read_lock(&tasklist_lock); for_each_task(p) { - if (p->pgrp == pgrp) { + if (p->pgrp == pgrp + && ((long)info==1 + || p->s_context == current->s_context)) { int err = send_sig_info(sig, info, p); if (retval) retval = err; @@ -639,8 +641,24 @@ read_lock(&tasklist_lock); p = find_task_by_pid(pid); error = -ESRCH; - if (p) - error = send_sig_info(sig, info, p); + if (p != NULL){ + switch((unsigned long)info) { + case 0: + if(p->s_context == current->s_context){ + error = send_sig_info(sig, info, p); + } + break; + case 1: + error = send_sig_info(sig, info, p); + break; + default: + if( info->si_code == SI_KERNEL + || p->s_context == current->s_context){ + error = send_sig_info(sig, info, p); + } + break; + } + } read_unlock(&tasklist_lock); return error; } @@ -663,7 +681,7 @@ read_lock(&tasklist_lock); for_each_task(p) { - if (p->pid > 1 && p != current) { + if (p->pid > 1 && p != current && p->s_context == current->s_context) { int err = send_sig_info(sig, info, p); ++count; if (err != -EPERM) @@ -1256,3 +1274,147 @@ return ret ? ret : (unsigned long)old_sa.sa.sa_handler; } #endif /* !alpha && !__ia64__ && !defined(__mips__) */ + +static int set_initpid (int flags) +{ + int ret = 0; + if ((flags & S_CTX_INFO_INIT)!=0){ + if (current->s_info == NULL){ + ret = -EINVAL; + }else if (current->s_info->initpid != 0){ + ret = -EPERM; + }else{ + current->s_info->initpid = current->tgid; + } + } + return ret; +} + +static inline int switch_user_struct(int new_context) +{ + struct user_struct *new_user; + + new_user = alloc_uid(new_context, current->uid); + if (!new_user) + return -ENOMEM; + + if (new_user != current->user) { + struct user_struct *old_user = current->user; + + atomic_inc(&new_user->processes); + atomic_dec(&old_user->processes); + current->user = new_user; + free_uid(old_user); + } + return 0; +} + +/* + Change to a new security context and reduce the capability + basic set of the current process +*/ +asmlinkage int +sys_new_s_context(int ctx, __u32 remove_cap, int flags) +{ + #define MAX_S_CONTEXT 65535 /* Arbitrary limit */ + int ret = -EPERM; + if (ctx == -1){ + if (current->s_info == NULL + || (current->s_info->flags & S_CTX_INFO_LOCK) == 0){ + /* Ok we allocate a new context. For now, we just increase */ + /* it. Wrap around possible, so we loop */ + static int alloc_ctx=1; + static spinlock_t alloc_ctx_lock = SPIN_LOCK_UNLOCKED; + spin_lock(&alloc_ctx_lock); + while (1){ + int found = 0; + struct task_struct *p; + alloc_ctx++; + /* The s_context 1 is special. It sess all processes */ + if (alloc_ctx == 1){ + alloc_ctx++; + }else if (alloc_ctx > MAX_S_CONTEXT){ + // No need to grow and grow + alloc_ctx = 2; + } + /* Check if in use */ + read_lock(&tasklist_lock); + for_each_task(p) { + if (p->s_context == alloc_ctx){ + found = 1; + break; + } + } + read_unlock(&tasklist_lock); + if (!found) break; + } + ret = switch_user_struct(alloc_ctx); + if (ret == 0) { + current->s_context = alloc_ctx; + current->cap_bset &= (~remove_cap); + ret = alloc_ctx; + sys_alloc_s_info(); + if (current->s_info != NULL) { + set_initpid (flags); + current->s_info->flags |= flags; + } + } + spin_unlock(&alloc_ctx_lock); + } + }else if (ctx == -2){ + ret = set_initpid(flags); + if (ret == 0){ + /* We keep the same s_context, but lower the capabilities */ + current->cap_bset &= (~remove_cap); + ret = current->s_context; + if (current->s_info != NULL){ + if ((flags & S_CTX_INFO_INIT)!=0){ + current->s_info->initpid = current->tgid; + } + current->s_info->flags |= flags; + } + } + }else if (ctx <= 0 || ctx > MAX_S_CONTEXT){ + ret = -EINVAL; + }else if (current->s_context == 0 + && capable(CAP_SYS_ADMIN) + && (current->s_info == NULL + ||(current->s_info->flags & S_CTX_INFO_LOCK) == 0)){ + /* The root context can become any context it wants */ + int found = 0; + struct task_struct *p; + /* Check if in use so we reuse the same context_info */ + read_lock(&tasklist_lock); + ret = ctx; + for_each_task(p) { + if (p->s_context == ctx){ + found = 1; + if (p->s_info == NULL + || (p->s_info->flags & S_CTX_INFO_PRIVATE)==0){ + sys_release_s_info(current); + sys_assign_s_info (p); + current->s_info = p->s_info; + }else{ + ret = -EPERM; + } + break; + } + } + read_unlock(&tasklist_lock); + if (ret == ctx) { + ret = switch_user_struct(ctx); + if (ret == 0) { + current->s_context = ctx; + current->cap_bset &= (~remove_cap); + if (!found) { + sys_alloc_s_info(); + } + if (current->s_info != NULL) { + current->s_info->flags |= flags; + } + } + } + } + return ret; +} + diff -urN linux-2.4.18/kernel/sys.c linux-2.4.18-ctx9/kernel/sys.c --- linux-2.4.18/kernel/sys.c Mon Mar 4 08:40:29 2002 +++ linux-2.4.18-ctx9/kernel/sys.c Mon Mar 25 17:58:39 2002 @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -499,7 +500,7 @@ * cheaply with the new uid cache, so if it matters * we should be checking for it. -DaveM */ - new_user = alloc_uid(new_ruid); + new_user = alloc_uid(current->s_context, new_ruid); if (!new_user) return -EAGAIN; old_user = current->user; @@ -1015,17 +1016,81 @@ asmlinkage long sys_newuname(struct new_utsname * name) { int errno = 0; + struct new_utsname tmp,*pttmp; down_read(&uts_sem); - if (copy_to_user(name,&system_utsname,sizeof *name)) + if (current->s_info != NULL){ + tmp = system_utsname; + strcpy (tmp.nodename,current->s_info->nodename); + strcpy (tmp.domainname,current->s_info->domainname); + pttmp = &tmp; + }else{ + pttmp = &system_utsname; + } + if (copy_to_user(name,pttmp,sizeof *name)) errno = -EFAULT; up_read(&uts_sem); return errno; } +/* + Decrease the reference count on the context_info member of a task + Free the struct if the reference count reach 0. +*/ +void sys_release_s_info (struct task_struct *p) +{ + down_write (&uts_sem); + if (p->s_info != NULL){ + p->s_info->refcount--; + if (p->s_info->refcount == 0){ + // printk ("vfree s_info %d\n",p->pid); + vfree (p->s_info); + p->s_info = NULL; + } + } + up_write (&uts_sem); +} +/* + Increase the reference count on the context_info member of a task +*/ +void sys_assign_s_info (struct task_struct *p) +{ + down_write (&uts_sem); + if (p->s_info != NULL) p->s_info->refcount++; + up_write (&uts_sem); +} + +/* + Alloc a new s_info to the current process and release + the one currently owned by the current process. +*/ +void sys_alloc_s_info() +{ + struct context_info *s_info = vmalloc(sizeof(struct context_info)); + // printk ("new s_info %d\n",current->pid); + s_info->s_context = current->s_context; + s_info->refcount = 1; + atomic_set (&s_info->ticks,current->counter); + s_info->flags = 0; + s_info->initpid = 0; + down_read (&uts_sem); + if (current->s_info != NULL){ + strcpy (s_info->nodename,current->s_info->nodename); + strcpy (s_info->domainname,current->s_info->domainname); + }else{ + strcpy (s_info->nodename,system_utsname.nodename); + strcpy (s_info->domainname,system_utsname.domainname); + } + up_read (&uts_sem); + sys_release_s_info (current); + current->s_info = s_info; +} + + asmlinkage long sys_sethostname(char *name, int len) { int errno; + char *nodename; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -1033,8 +1098,10 @@ return -EINVAL; down_write(&uts_sem); errno = -EFAULT; - if (!copy_from_user(system_utsname.nodename, name, len)) { - system_utsname.nodename[len] = 0; + nodename = system_utsname.nodename; + if (current->s_info) nodename = current->s_info->nodename; + if (!copy_from_user(nodename, name, len)) { + nodename[len] = 0; errno = 0; } up_write(&uts_sem); @@ -1044,15 +1111,18 @@ asmlinkage long sys_gethostname(char *name, int len) { int i, errno; + char *nodename; if (len < 0) return -EINVAL; down_read(&uts_sem); - i = 1 + strlen(system_utsname.nodename); + nodename = system_utsname.nodename; + if (current->s_info != NULL) nodename = current->s_info->nodename; + i = 1 + strlen(nodename); if (i > len) i = len; errno = 0; - if (copy_to_user(name, system_utsname.nodename, i)) + if (copy_to_user(name, nodename, i)) errno = -EFAULT; up_read(&uts_sem); return errno; @@ -1065,6 +1135,7 @@ asmlinkage long sys_setdomainname(char *name, int len) { int errno; + char *domainname; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -1072,10 +1143,12 @@ return -EINVAL; down_write(&uts_sem); + domainname = system_utsname.domainname; + if (current->s_info) domainname = current->s_info->domainname; errno = -EFAULT; - if (!copy_from_user(system_utsname.domainname, name, len)) { + if (!copy_from_user(domainname, name, len)) { errno = 0; - system_utsname.domainname[len] = 0; + domainname[len] = 0; } up_write(&uts_sem); return errno; diff -urN linux-2.4.18/kernel/sysctl.c linux-2.4.18-ctx9/kernel/sysctl.c --- linux-2.4.18/kernel/sysctl.c Thu Dec 27 10:44:16 2001 +++ linux-2.4.18-ctx9/kernel/sysctl.c Mon Mar 25 17:58:39 2002 @@ -379,6 +379,7 @@ static int test_perm(int mode, int op) { + if (!capable(CAP_SYS_ADMIN)) mode &= ~(0222); if (!current->euid) mode >>= 6; else if (in_egroup_p(0)) @@ -793,7 +794,18 @@ void *buffer, size_t *lenp) { int r; + ctl_table tmp; + /* HACK for per s_context hostname and domainname */ + if (current->s_info != NULL){ + tmp = *table; + table = &tmp; + if (table->data == (void*)&system_utsname.nodename){ + tmp.data = ¤t->s_info->nodename; + }else if (table->data == (void*)&system_utsname.domainname){ + tmp.data = ¤t->s_info->domainname; + } + } if (!write) { down_read(&uts_sem); r=proc_dostring(table,0,filp,buffer,lenp); diff -urN linux-2.4.18/kernel/timer.c linux-2.4.18-ctx9/kernel/timer.c --- linux-2.4.18/kernel/timer.c Mon Oct 29 17:03:59 2001 +++ linux-2.4.18-ctx9/kernel/timer.c Mon Mar 25 17:58:39 2002 @@ -583,6 +583,11 @@ update_one_process(p, user_tick, system, cpu); if (p->pid) { + if (p->s_info != NULL + && (p->s_info->flags & S_CTX_INFO_SCHED)!=0){ + // atomic_sub (ticks*p->s_info->refcount, &p->s_info->ticks); + atomic_dec (&p->s_info->ticks); + } if (--p->counter <= 0) { p->counter = 0; p->need_resched = 1; @@ -719,6 +724,11 @@ asmlinkage long sys_getpid(void) { /* This is SMP safe - current->pid doesn't change */ + if (current->s_info != NULL + && current->s_info->initpid == current->tgid){ + /* We are faking process 1 for this security context */ + return 1; + } return current->tgid; } @@ -764,6 +774,12 @@ } #endif break; + } + if (pid != 0 + && current->s_info != NULL + && current->s_info->initpid == pid){ + /* We are faking process 1 for this security context */ + pid = 1; } return pid; } diff -urN linux-2.4.18/kernel/user.c linux-2.4.18-ctx9/kernel/user.c --- linux-2.4.18/kernel/user.c Wed Nov 29 07:43:39 2000 +++ linux-2.4.18-ctx9/kernel/user.c Mon Mar 25 17:58:39 2002 @@ -6,6 +6,19 @@ * We have a per-user structure to keep track of how many * processes, files etc the user has claimed, in order to be * able to have per-user limits for system resources. + * + * For the vserver project, the key is extended from UID to (SC,UID), + * with SC being the security context ID. Thus, each security context + * has independant per-UID resource usage counters. + * + * As a consequence, even if two UIDs are the same, the 'struct user *' + * in their task_struct could be different. I don't think any code cares. + * + * (vserver modifications done Sun Jan 13 08:48:45 CET 2002 by bof@bof.de) + * + * NOTE: For now, the hash function is unmodified: the same uid in several + * security contexts, will always sit on the same hash chain. This could + * be changed easily. */ #include @@ -56,7 +69,7 @@ *pprev = next; } -static inline struct user_struct *uid_hash_find(uid_t uid, struct user_struct **hashent) +static inline struct user_struct *uid_hash_find(int s_context, uid_t uid, struct user_struct **hashent) { struct user_struct *next; @@ -65,7 +78,7 @@ struct user_struct *up = next; if (next) { next = up->next; - if (up->uid != uid) + if (up->uid != uid || up->s_context != s_context) continue; atomic_inc(&up->__count); } @@ -82,13 +95,13 @@ } } -struct user_struct * alloc_uid(uid_t uid) +struct user_struct * alloc_uid(int s_context, uid_t uid) { struct user_struct **hashent = uidhashentry(uid); struct user_struct *up; spin_lock(&uidhash_lock); - up = uid_hash_find(uid, hashent); + up = uid_hash_find(s_context, uid, hashent); spin_unlock(&uidhash_lock); if (!up) { @@ -98,6 +111,7 @@ if (!new) return NULL; new->uid = uid; + new->s_context = s_context; atomic_set(&new->__count, 1); atomic_set(&new->processes, 0); atomic_set(&new->files, 0); @@ -107,7 +121,7 @@ * on adding the same user already.. */ spin_lock(&uidhash_lock); - up = uid_hash_find(uid, hashent); + up = uid_hash_find(s_context, uid, hashent); if (up) { kmem_cache_free(uid_cachep, new); } else { diff -urN linux-2.4.18/net/ipv4/af_inet.c linux-2.4.18-ctx9/net/ipv4/af_inet.c --- linux-2.4.18/net/ipv4/af_inet.c Thu Dec 27 10:44:17 2001 +++ linux-2.4.18-ctx9/net/ipv4/af_inet.c Mon Mar 25 17:58:39 2002 @@ -393,6 +393,8 @@ sk->protinfo.af_inet.mc_index = 0; sk->protinfo.af_inet.mc_list = NULL; + sk->s_context = current->s_context; + #ifdef INET_REFCNT_DEBUG atomic_inc(&inet_sock_nr); #endif @@ -477,6 +479,8 @@ unsigned short snum; int chk_addr_ret; int err; + __u32 s_addr; + __u32 bcast_addr = 0xffffffffl; /* If the socket has its own bind function then use it. (RAW) */ if(sk->prot->bind) @@ -485,7 +489,20 @@ if (addr_len < sizeof(struct sockaddr_in)) return -EINVAL; - chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr); + s_addr = addr->sin_addr.s_addr; + if (current->ipv4root != 0){ + // printk ("ipv4root0 %08lx %08x\n",current->ipv4root,s_addr); + if (s_addr == 0){ + s_addr = current->ipv4root; + bcast_addr = current->ipv4root_bcast; + }else if (s_addr == 0x0100007f){ + s_addr = current->ipv4root; + }else if (s_addr != current->ipv4root){ + return -EADDRNOTAVAIL; + } + } + chk_addr_ret = inet_addr_type(s_addr); + // printk ("ipv4root %08lx %08x %d\n",current->ipv4root,s_addr,chk_addr_ret); /* Not specified by any standard per-se, however it breaks too * many applications when removed. It is unfortunate since @@ -496,7 +513,7 @@ */ if (sysctl_ip_nonlocal_bind == 0 && sk->protinfo.af_inet.freebind == 0 && - addr->sin_addr.s_addr != INADDR_ANY && + s_addr != INADDR_ANY && chk_addr_ret != RTN_LOCAL && chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) @@ -521,7 +538,8 @@ (sk->num != 0)) goto out; - sk->rcv_saddr = sk->saddr = addr->sin_addr.s_addr; + sk->rcv_saddr = sk->saddr = s_addr; + sk->bcast_addr = bcast_addr; if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) sk->saddr = 0; /* Use device */ diff -urN linux-2.4.18/net/ipv4/devinet.c linux-2.4.18-ctx9/net/ipv4/devinet.c --- linux-2.4.18/net/ipv4/devinet.c Thu Dec 27 10:44:17 2001 +++ linux-2.4.18-ctx9/net/ipv4/devinet.c Mon Mar 25 17:58:39 2002 @@ -558,7 +558,13 @@ ret = -EADDRNOTAVAIL; goto done; } - + if (ifa != NULL + && current->s_context != 0 + && current->ipv4root != 0 + && current->ipv4root != ifa->ifa_local){ + ret = -EADDRNOTAVAIL; + goto done; + } switch(cmd) { case SIOCGIFADDR: /* Get interface address */ sin->sin_addr.s_addr = ifa->ifa_local; @@ -691,6 +697,10 @@ return 0; for ( ; ifa; ifa = ifa->ifa_next) { + // We do not show other IP devices to vservers + if (current->s_context != 0 + && current->ipv4root != 0 + && current->ipv4root != ifa->ifa_local) continue; if (!buf) { done += sizeof(ifr); continue; @@ -908,6 +918,9 @@ read_lock(&in_dev->lock); for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; ifa = ifa->ifa_next, ip_idx++) { + if (current->s_context != 0 + && current->ipv4root != 0 + && current->ipv4root != ifa->ifa_local) continue; if (ip_idx < s_ip_idx) continue; if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, diff -urN linux-2.4.18/net/ipv4/raw.c linux-2.4.18-ctx9/net/ipv4/raw.c --- linux-2.4.18/net/ipv4/raw.c Mon Jul 30 11:10:52 2001 +++ linux-2.4.18-ctx9/net/ipv4/raw.c Mon Mar 25 17:58:39 2002 @@ -657,7 +657,7 @@ struct sock *sk; for (sk = raw_v4_htable[i]; sk; sk = sk->next, num++) { - if (sk->family != PF_INET) + if (sk->family != PF_INET || (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += 128; if (pos <= offset) diff -urN linux-2.4.18/net/ipv4/tcp_ipv4.c linux-2.4.18-ctx9/net/ipv4/tcp_ipv4.c --- linux-2.4.18/net/ipv4/tcp_ipv4.c Mon Mar 4 08:40:30 2002 +++ linux-2.4.18-ctx9/net/ipv4/tcp_ipv4.c Mon Mar 25 17:58:39 2002 @@ -2073,6 +2073,9 @@ int uid; struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + if (current->s_context != 1 && sk->s_context != current->s_context) + continue; + if (!TCP_INET_FAMILY(sk->family)) goto skip_listen; @@ -2126,7 +2129,7 @@ read_lock(&head->lock); for(sk = head->chain; sk; sk = sk->next, num++) { - if (!TCP_INET_FAMILY(sk->family)) + if (!TCP_INET_FAMILY(sk->family) || (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += TMPSZ; if (pos <= offset) @@ -2141,7 +2144,7 @@ for (tw = (struct tcp_tw_bucket *)tcp_ehash[i+tcp_ehash_size].chain; tw != NULL; tw = (struct tcp_tw_bucket *)tw->next, num++) { - if (!TCP_INET_FAMILY(tw->family)) + if (!TCP_INET_FAMILY(tw->family) || (current->s_context != 1 && tw->s_context != current->s_context)) continue; pos += TMPSZ; if (pos <= offset) diff -urN linux-2.4.18/net/ipv4/tcp_minisocks.c linux-2.4.18-ctx9/net/ipv4/tcp_minisocks.c --- linux-2.4.18/net/ipv4/tcp_minisocks.c Mon Oct 29 17:03:59 2001 +++ linux-2.4.18-ctx9/net/ipv4/tcp_minisocks.c Mon Mar 25 17:58:39 2002 @@ -381,6 +381,8 @@ tw->ts_recent_stamp= tp->ts_recent_stamp; tw->pprev_death = NULL; + tw->s_context = sk->s_context; + #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) if(tw->family == PF_INET6) { memcpy(&tw->v6_daddr, diff -urN linux-2.4.18/net/ipv4/udp.c linux-2.4.18-ctx9/net/ipv4/udp.c --- linux-2.4.18/net/ipv4/udp.c Mon Mar 4 08:40:30 2002 +++ linux-2.4.18-ctx9/net/ipv4/udp.c Mon Mar 25 17:58:39 2002 @@ -272,7 +272,7 @@ if ((s->num != hnum) || (s->daddr && s->daddr!=rmt_addr) || (s->dport != rmt_port && s->dport != 0) || - (s->rcv_saddr && s->rcv_saddr != loc_addr) || + (s->rcv_saddr && s->rcv_saddr != loc_addr && s->bcast_addr != loc_addr) || (s->bound_dev_if && s->bound_dev_if != dif)) continue; break; @@ -987,7 +987,7 @@ struct sock *sk; for (sk = udp_hash[i]; sk; sk = sk->next, num++) { - if (sk->family != PF_INET) + if (sk->family != PF_INET || (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += 128; if (pos <= offset) diff -urN linux-2.4.18/net/ipv6/raw.c linux-2.4.18-ctx9/net/ipv6/raw.c --- linux-2.4.18/net/ipv6/raw.c Mon Oct 15 15:24:43 2001 +++ linux-2.4.18-ctx9/net/ipv6/raw.c Mon Mar 25 17:58:39 2002 @@ -797,7 +797,7 @@ struct sock *sk; for (sk = raw_v6_htable[i]; sk; sk = sk->next, num++) { - if (sk->family != PF_INET6) + if (sk->family != PF_INET6 || (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += LINE_LEN+1; if (pos <= offset) diff -urN linux-2.4.18/net/ipv6/tcp_ipv6.c linux-2.4.18-ctx9/net/ipv6/tcp_ipv6.c --- linux-2.4.18/net/ipv6/tcp_ipv6.c Mon Mar 4 08:40:30 2002 +++ linux-2.4.18-ctx9/net/ipv6/tcp_ipv6.c Mon Mar 25 17:58:39 2002 @@ -2006,7 +2006,7 @@ int uid; struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); - if (sk->family != PF_INET6) + if (sk->family != PF_INET6 || (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += LINE_LEN+1; if (pos >= offset) { @@ -2056,7 +2056,7 @@ read_lock(&head->lock); for(sk = head->chain; sk; sk = sk->next, num++) { - if (sk->family != PF_INET6) + if (sk->family != PF_INET6 || (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += LINE_LEN+1; if (pos <= offset) @@ -2071,7 +2071,7 @@ for (tw = (struct tcp_tw_bucket *)tcp_ehash[i+tcp_ehash_size].chain; tw != NULL; tw = (struct tcp_tw_bucket *)tw->next, num++) { - if (tw->family != PF_INET6) + if (tw->family != PF_INET6 || (current->s_context != 1 && tw->s_context != current->s_context)) continue; pos += LINE_LEN+1; if (pos <= offset) diff -urN linux-2.4.18/net/ipv6/udp.c linux-2.4.18-ctx9/net/ipv6/udp.c --- linux-2.4.18/net/ipv6/udp.c Mon Oct 15 15:24:43 2001 +++ linux-2.4.18-ctx9/net/ipv6/udp.c Mon Mar 25 17:58:39 2002 @@ -952,7 +952,7 @@ struct sock *sk; for (sk = udp_hash[i]; sk; sk = sk->next, num++) { - if (sk->family != PF_INET6) + if (sk->family != PF_INET6 || (current->s_context != 1 && sk->s_context != current->s_context)) continue; pos += LINE_LEN+1; if (pos <= offset) diff -urN linux-2.4.18/net/socket.c linux-2.4.18-ctx9/net/socket.c --- linux-2.4.18/net/socket.c Thu Dec 27 10:44:18 2001 +++ linux-2.4.18-ctx9/net/socket.c Mon Mar 25 17:58:39 2002 @@ -1763,3 +1763,16 @@ len = 0; return len; } + +asmlinkage int sys_set_ipv4root (unsigned long ip, unsigned long bcast) +{ + int ret = -EPERM; + if (current->ipv4root == 0 + || capable(CAP_SYS_ADMIN)){ + ret = 0; + current->ipv4root = ip; + current->ipv4root_bcast = bcast; + } + return ret; +} + diff -urN linux-2.4.18/net/unix/af_unix.c linux-2.4.18-ctx9/net/unix/af_unix.c --- linux-2.4.18/net/unix/af_unix.c Mon Mar 4 08:40:30 2002 +++ linux-2.4.18-ctx9/net/unix/af_unix.c Mon Mar 25 17:58:39 2002 @@ -479,6 +479,8 @@ sk->write_space = unix_write_space; + sk->s_context = current->s_context; + sk->max_ack_backlog = sysctl_unix_max_dgram_qlen; sk->destruct = unix_sock_destructor; sk->protinfo.af_unix.dentry=NULL; @@ -1750,6 +1752,9 @@ read_lock(&unix_table_lock); forall_unix_sockets (i,s) { + if (current->s_context != 1 && s->s_context != current->s_context) + continue; + unix_state_rlock(s); len+=sprintf(buffer+len,"%p: %08X %08X %08X %04X %02X %5ld",