diff -rc2P linux-2.4.18/Makefile linux-2.4.18ctx-8/Makefile
*** linux-2.4.18/Makefile       Tue Feb 26 22:21:48 2002
--- linux-2.4.18ctx-8/Makefile  Tue Feb 26 22:31:23 2002
***************
*** 2,6 ****
 PATCHLEVEL = 4
 SUBLEVEL = 18
! EXTRAVERSION =

 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
--- 2,6 ----
 PATCHLEVEL = 4
 SUBLEVEL = 18
! EXTRAVERSION =ctx-8

 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff -rc2P linux-2.4.18/arch/i386/kernel/entry.S linux-2.4.18ctx-8/arch/i386/kernel/entry.S
*** linux-2.4.18/arch/i386/kernel/entry.S       Tue Feb 26 22:21:49 2002
--- linux-2.4.18ctx-8/arch/i386/kernel/entry.S  Wed Feb 27 14:36:44 2002
***************
*** 635,638 ****
--- 635,640 ----
       .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
diff -rc2P linux-2.4.18/arch/i386/kernel/ptrace.c linux-2.4.18ctx-8/arch/i386/kernel/ptrace.c
*** linux-2.4.18/arch/i386/kernel/ptrace.c      Fri Nov 23 15:07:41 2001
--- linux-2.4.18ctx-8/arch/i386/kernel/ptrace.c Tue Feb 26 22:31:23 2002
***************
*** 171,175 ****
               get_task_struct(child);
       read_unlock(&tasklist_lock);
!       if (!child)
               goto out;

--- 171,175 ----
               get_task_struct(child);
       read_unlock(&tasklist_lock);
!       if (!child || child->s_context != current->s_context)
               goto out;

diff -rc2P linux-2.4.18/fs/devpts/inode.c linux-2.4.18ctx-8/fs/devpts/inode.c
*** linux-2.4.18/fs/devpts/inode.c      Wed Oct 10 11:58:19 2001
--- linux-2.4.18ctx-8/fs/devpts/inode.c Tue Feb 26 22:31:23 2002
***************
*** 25,28 ****
--- 25,29 ----
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
+ #include <linux/sched.h>

 #include "devpts_i.h"
***************
*** 153,157 ****
       inode->i_fop = &devpts_root_operations;
       inode->i_nlink = 2;
-
       s->u.generic_sbp = (void *) sbi;
       s->s_blocksize = 1024;
--- 154,157 ----
***************
*** 181,184 ****
--- 181,197 ----
 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)
 {
***************
*** 199,202 ****
--- 212,217 ----
       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));

diff -rc2P linux-2.4.18/fs/devpts/root.c linux-2.4.18ctx-8/fs/devpts/root.c
*** linux-2.4.18/fs/devpts/root.c       Sat Dec 22 22:38:37 2001
--- linux-2.4.18ctx-8/fs/devpts/root.c  Tue Feb 26 22:31:23 2002
***************
*** 15,18 ****
--- 15,19 ----
 #include <linux/param.h>
 #include <linux/string.h>
+ #include <linux/sched.h>
 #include "devpts_i.h"

***************
*** 65,69 ****
               while ( nr - 2 < sbi->max_ptys ) {
                       int ptynr = nr - 2;
!                       if ( sbi->inodes[ptynr] ) {
                               genptsname(numbuf, ptynr);
                               if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr, DT_CHR) < 0 )
--- 66,73 ----
               while ( nr - 2 < sbi->max_ptys ) {
                       int ptynr = nr - 2;
!                       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 )
***************
*** 101,104 ****
--- 105,109 ----
       int i;
       const char *p;
+       struct inode *inode;

       dentry->d_op    = &devpts_dentry_operations;
***************
*** 127,135 ****
               return NULL;

!       if ( sbi->inodes[entry] )
!               atomic_inc(&sbi->inodes[entry]->i_count);

!       d_add(dentry, sbi->inodes[entry]);

       return NULL;
 }
--- 132,147 ----
               return NULL;

!       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, inode);

       return NULL;
 }
+
+
diff -rc2P linux-2.4.18/fs/exec.c linux-2.4.18ctx-8/fs/exec.c
*** linux-2.4.18/fs/exec.c      Sat Dec 22 22:38:37 2001
--- linux-2.4.18ctx-8/fs/exec.c Tue Feb 26 22:31:23 2002
***************
*** 686,690 ****
       int do_unlock = 0;

!       new_permitted = cap_intersect(bprm->cap_permitted, cap_bset);
       working = cap_intersect(bprm->cap_inheritable,
                               current->cap_inheritable);
--- 686,690 ----
       int do_unlock = 0;

!       new_permitted = cap_intersect(bprm->cap_permitted, current->cap_bset);
       working = cap_intersect(bprm->cap_inheritable,
                               current->cap_inheritable);
diff -rc2P linux-2.4.18/fs/ext2/ialloc.c linux-2.4.18ctx-8/fs/ext2/ialloc.c
*** linux-2.4.18/fs/ext2/ialloc.c       Tue Feb 26 22:22:03 2002
--- linux-2.4.18ctx-8/fs/ext2/ialloc.c  Tue Feb 26 22:31:23 2002
***************
*** 389,393 ****
       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_block_group = group;
       if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL)
--- 389,393 ----
       inode->u.ext2_i.i_flags = dir->u.ext2_i.i_flags;
       if (S_ISLNK(mode))
!               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)
diff -rc2P linux-2.4.18/fs/ext2/inode.c linux-2.4.18ctx-8/fs/ext2/inode.c
*** linux-2.4.18/fs/ext2/inode.c        Tue Feb 26 22:22:03 2002
--- linux-2.4.18ctx-8/fs/ext2/inode.c   Tue Feb 26 22:31:23 2002
***************
*** 801,805 ****
           S_ISLNK(inode->i_mode)))
               return;
!       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
               return;

--- 801,805 ----
           S_ISLNK(inode->i_mode)))
               return;
!       if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode))
               return;

***************
*** 1007,1013 ****
               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_NOATIME_FL) {
--- 1007,1017 ----
               inode->i_flags |= S_APPEND;
       }
!       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) {
diff -rc2P linux-2.4.18/fs/ext2/ioctl.c linux-2.4.18ctx-8/fs/ext2/ioctl.c
*** linux-2.4.18/fs/ext2/ioctl.c        Wed Sep 27 16:41:33 2000
--- linux-2.4.18ctx-8/fs/ext2/ioctl.c   Tue Feb 26 22:31:23 2002
***************
*** 45,49 ****
                * This test looks nicer. Thanks to Pauline Middelink
                */
!               if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) {
                       if (!capable(CAP_LINUX_IMMUTABLE))
                               return -EPERM;
--- 45,49 ----
                * This test looks nicer. Thanks to Pauline Middelink
                */
!               if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FILE_FL | EXT2_IMMUTABLE_LINK_FL)) {
                       if (!capable(CAP_LINUX_IMMUTABLE))
                               return -EPERM;
***************
*** 62,69 ****
               else
                       inode->i_flags &= ~S_APPEND;
!               if (flags & EXT2_IMMUTABLE_FL)
!                       inode->i_flags |= S_IMMUTABLE;
               else
!                       inode->i_flags &= ~S_IMMUTABLE;
               if (flags & EXT2_NOATIME_FL)
                       inode->i_flags |= S_NOATIME;
--- 62,76 ----
               else
                       inode->i_flags &= ~S_APPEND;
!
!               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_LINK;
!
               if (flags & EXT2_NOATIME_FL)
                       inode->i_flags |= S_NOATIME;
diff -rc2P linux-2.4.18/fs/ext3/ialloc.c linux-2.4.18ctx-8/fs/ext3/ialloc.c
*** linux-2.4.18/fs/ext3/ialloc.c       Tue Feb 26 22:22:04 2002
--- linux-2.4.18ctx-8/fs/ext3/ialloc.c  Tue Feb 26 22:31:23 2002
***************
*** 486,490 ****
       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);
 #ifdef EXT3_FRAGMENTS
       inode->u.ext3_i.i_faddr = 0;
--- 486,490 ----
       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_FILE_FL | EXT3_IMMUTABLE_LINK_FL | EXT3_APPEND_FL);
 #ifdef EXT3_FRAGMENTS
       inode->u.ext3_i.i_faddr = 0;
diff -rc2P linux-2.4.18/fs/ext3/inode.c linux-2.4.18ctx-8/fs/ext3/inode.c
*** linux-2.4.18/fs/ext3/inode.c        Tue Feb 26 22:22:04 2002
--- linux-2.4.18ctx-8/fs/ext3/inode.c   Tue Feb 26 22:31:23 2002
***************
*** 1846,1850 ****
           S_ISLNK(inode->i_mode)))
               return;
!       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
               return;

--- 1846,1850 ----
           S_ISLNK(inode->i_mode)))
               return;
!       if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode))
               return;

***************
*** 2150,2156 ****
               inode->i_flags |= S_APPEND;
       }
!       if (inode->u.ext3_i.i_flags & EXT3_IMMUTABLE_FL) {
               /* inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE;  unused */
!               inode->i_flags |= S_IMMUTABLE;
       }
       if (inode->u.ext3_i.i_flags & EXT3_NOATIME_FL) {
--- 2150,2159 ----
               inode->i_flags |= S_APPEND;
       }
!       if (inode->u.ext3_i.i_flags & EXT3_IMMUTABLE_FILE_FL) {
               /* inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE;  unused */
!               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) {
diff -rc2P linux-2.4.18/fs/ext3/ioctl.c linux-2.4.18ctx-8/fs/ext3/ioctl.c
*** linux-2.4.18/fs/ext3/ioctl.c        Fri Nov 23 15:07:49 2001
--- linux-2.4.18ctx-8/fs/ext3/ioctl.c   Tue Feb 26 22:31:23 2002
***************
*** 54,58 ****
                * This test looks nicer. Thanks to Pauline Middelink
                */
!               if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) {
                       if (!capable(CAP_LINUX_IMMUTABLE))
                               return -EPERM;
--- 54,58 ----
                * This test looks nicer. Thanks to Pauline Middelink
                */
!               if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FILE_FL | EXT3_IMMUTABLE_LINK_FL)) {
                       if (!capable(CAP_LINUX_IMMUTABLE))
                               return -EPERM;
***************
*** 90,97 ****
               else
                       inode->i_flags &= ~S_APPEND;
!               if (flags & EXT3_IMMUTABLE_FL)
!                       inode->i_flags |= S_IMMUTABLE;
               else
!                       inode->i_flags &= ~S_IMMUTABLE;
               if (flags & EXT3_NOATIME_FL)
                       inode->i_flags |= S_NOATIME;
--- 90,101 ----
               else
                       inode->i_flags &= ~S_APPEND;
!               if (flags & EXT3_IMMUTABLE_FILE_FL)
!                       inode->i_flags |= S_IMMUTABLE_FILE;
               else
!                       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;
diff -rc2P linux-2.4.18/fs/fat/file.c linux-2.4.18ctx-8/fs/fat/file.c
*** linux-2.4.18/fs/fat/file.c  Sun Aug 12 13:56:56 2001
--- linux-2.4.18ctx-8/fs/fat/file.c     Tue Feb 26 22:31:23 2002
***************
*** 120,124 ****
       if (IS_RDONLY (inode))
               return /* -EPERM */;
!       if (IS_IMMUTABLE(inode))
               return /* -EPERM */;
       cluster = 1 << sbi->cluster_bits;
--- 120,124 ----
       if (IS_RDONLY (inode))
               return /* -EPERM */;
!       if (IS_IMMUTABLE_FILE(inode))
               return /* -EPERM */;
       cluster = 1 << sbi->cluster_bits;
diff -rc2P linux-2.4.18/fs/fat/inode.c linux-2.4.18ctx-8/fs/fat/inode.c
*** linux-2.4.18/fs/fat/inode.c Tue Feb 26 22:22:04 2002
--- linux-2.4.18ctx-8/fs/fat/inode.c    Tue Feb 26 22:31:23 2002
***************
*** 948,952 ****
       if(de->attr & ATTR_SYS)
               if (sbi->options.sys_immutable)
!                       inode->i_flags |= S_IMMUTABLE;
       MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;
       /* this is as close to the truth as we can get ... */
--- 948,952 ----
       if(de->attr & ATTR_SYS)
               if (sbi->options.sys_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 ... */
diff -rc2P linux-2.4.18/fs/hpfs/file.c linux-2.4.18ctx-8/fs/hpfs/file.c
*** linux-2.4.18/fs/hpfs/file.c Sun Aug 12 20:37:53 2001
--- linux-2.4.18ctx-8/fs/hpfs/file.c    Tue Feb 26 22:31:23 2002
***************
*** 61,65 ****
 void hpfs_truncate(struct inode *i)
 {
!       if (IS_IMMUTABLE(i)) return /*-EPERM*/;
       i->i_hpfs_n_secs = 0;
       i->i_blocks = 1 + ((i->i_size + 511) >> 9);
--- 61,65 ----
 void hpfs_truncate(struct inode *i)
 {
!       if (IS_IMMUTABLE_FILE(i)) return /*-EPERM*/;
       i->i_hpfs_n_secs = 0;
       i->i_blocks = 1 + ((i->i_size + 511) >> 9);
diff -rc2P linux-2.4.18/fs/intermezzo/vfs.c linux-2.4.18ctx-8/fs/intermezzo/vfs.c
*** linux-2.4.18/fs/intermezzo/vfs.c    Tue Feb 26 22:22:04 2002
--- linux-2.4.18ctx-8/fs/intermezzo/vfs.c       Tue Feb 26 22:31:23 2002
***************
*** 90,94 ****
                 return -EPERM;
         if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||
!             IS_IMMUTABLE(victim->d_inode))
                 return -EPERM;
         if (isdir) {
--- 90,94 ----
                 return -EPERM;
         if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||
!             IS_IMMUTABLE_LINK(victim->d_inode))
                 return -EPERM;
         if (isdir) {
***************
*** 191,195 ****
         }

!         if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
                 EXIT;
                 return -EPERM;
--- 191,195 ----
         }

!         if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode)) {
                 EXIT;
                 return -EPERM;
***************
*** 232,236 ****
         }

!         if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
                 EXIT;
                 return -EPERM;
--- 232,236 ----
         }

!         if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode)) {
                 EXIT;
                 return -EPERM;
***************
*** 619,623 ****
          */
         error = -EPERM;
!         if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) {
                 EXIT;
                 goto exit_lock;
--- 619,623 ----
          */
         error = -EPERM;
!         if (IS_APPEND(inode) || IS_IMMUTABLE_LINK(inode)) {
                 EXIT;
                 goto exit_lock;
***************
*** 2221,2225 ****
         }

!         if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
                 EXIT;
                 return -EPERM;
--- 2221,2225 ----
         }

!         if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode)) {
                 EXIT;
                 return -EPERM;
diff -rc2P linux-2.4.18/fs/namei.c linux-2.4.18ctx-8/fs/namei.c
*** linux-2.4.18/fs/namei.c     Tue Feb 26 22:22:07 2002
--- linux-2.4.18ctx-8/fs/namei.c        Tue Feb 26 22:31:23 2002
***************
*** 153,156 ****
--- 153,165 ----
       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) {
               /*
***************
*** 164,168 ****
                * Nobody gets write access to an immutable file.
                */
!               if (IS_IMMUTABLE(inode))
                       return -EACCES;
       }
--- 173,177 ----
                * Nobody gets write access to an immutable file.
                */
!               if (IS_IMMUTABLE_FILE(inode))
                       return -EACCES;
       }
***************
*** 879,884 ****
       if (IS_APPEND(dir))
               return -EPERM;
!       if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||
!           IS_IMMUTABLE(victim->d_inode))
               return -EPERM;
       if (isdir) {
--- 888,892 ----
       if (IS_APPEND(dir))
               return -EPERM;
!       if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||IS_IMMUTABLE_LINK(victim->d_inode))
               return -EPERM;
       if (isdir) {
***************
*** 1596,1600 ****
        */
       error = -EPERM;
!       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
               goto exit_lock;
       if (!dir->i_op || !dir->i_op->link)
--- 1604,1608 ----
        */
       error = -EPERM;
!       if (IS_APPEND(inode) || IS_IMMUTABLE_LINK(inode))
               goto exit_lock;
       if (!dir->i_op || !dir->i_op->link)
diff -rc2P linux-2.4.18/fs/nfsd/vfs.c linux-2.4.18ctx-8/fs/nfsd/vfs.c
*** linux-2.4.18/fs/nfsd/vfs.c  Sat Dec 22 22:38:38 2001
--- linux-2.4.18ctx-8/fs/nfsd/vfs.c     Tue Feb 26 22:31:23 2002
***************
*** 1485,1489 ****
               return 0;
 #if 0
!       dprintk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s\n",
               acc,
               (acc & MAY_READ)?       " read"  : "",
--- 1485,1489 ----
               return 0;
 #if 0
!       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"  : "",
***************
*** 1495,1499 ****
               (acc & MAY_OWNER_OVERRIDE)? " owneroverride" : "",
               inode->i_mode,
!               IS_IMMUTABLE(inode)?    " immut" : "",
               IS_APPEND(inode)?       " append" : "",
               IS_RDONLY(inode)?       " ro" : "");
--- 1495,1500 ----
               (acc & MAY_OWNER_OVERRIDE)? " owneroverride" : "",
               inode->i_mode,
!               IS_IMMUTABLE_FILE(inode)? " immut(F)" : "",
!               IS_IMMUTABLE_LINK(inode)? " immut(L)" : "",
               IS_APPEND(inode)?       " append" : "",
               IS_RDONLY(inode)?       " ro" : "");
***************
*** 1510,1514 ****
                       if (EX_RDONLY(exp) || IS_RDONLY(inode))
                               return nfserr_rofs;
!                       if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
                               return nfserr_perm;
               }
--- 1511,1515 ----
                       if (EX_RDONLY(exp) || IS_RDONLY(inode))
                               return nfserr_rofs;
!                       if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE_FILE(inode))
                               return nfserr_perm;
               }
diff -rc2P linux-2.4.18/fs/open.c linux-2.4.18ctx-8/fs/open.c
*** linux-2.4.18/fs/open.c      Wed Oct 31 15:32:41 2001
--- linux-2.4.18ctx-8/fs/open.c Tue Feb 26 22:31:23 2002
***************
*** 123,127 ****

       error = -EPERM;
!       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
               goto dput_and_out;

--- 123,127 ----

       error = -EPERM;
!       if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode))
               goto dput_and_out;

***************
*** 471,475 ****
               goto out_putf;
       err = -EPERM;
!       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
               goto out_putf;
       if (mode == (mode_t) -1)
--- 471,475 ----
               goto out_putf;
       err = -EPERM;
!       if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode))
               goto out_putf;
       if (mode == (mode_t) -1)
***************
*** 502,506 ****

       error = -EPERM;
!       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
               goto dput_and_out;

--- 502,506 ----

       error = -EPERM;
!       if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode))
               goto dput_and_out;

***************
*** 532,536 ****
               goto out;
       error = -EPERM;
!       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
               goto out;
       if (user == (uid_t) -1)
--- 532,536 ----
               goto out;
       error = -EPERM;
!       if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode))
               goto out;
       if (user == (uid_t) -1)
diff -rc2P linux-2.4.18/fs/proc/array.c linux-2.4.18ctx-8/fs/proc/array.c
*** linux-2.4.18/fs/proc/array.c        Wed Oct 31 15:32:41 2001
--- linux-2.4.18ctx-8/fs/proc/array.c   Tue Feb 26 22:31:23 2002
***************
*** 76,79 ****
--- 76,80 ----
 #include <asm/io.h>
 #include <asm/processor.h>
+ #include <asm/unistd.h>

 /* Gcc optimizes away "strlen(x)" for constant x */
***************
*** 148,153 ****
 {
       int g;
!
       read_lock(&tasklist_lock);
       buffer += sprintf(buffer,
               "State:\t%s\n"
--- 149,158 ----
 {
       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"
***************
*** 159,163 ****
               "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->uid, p->euid, p->suid, p->fsuid,
               p->gid, p->egid, p->sgid, p->fsgid);
--- 164,168 ----
               "Gid:\t%d\t%d\t%d\t%d\n",
               get_task_state(p), p->tgid,
!               p->pid, p->pid ? ppid : 0, 0,
               p->uid, p->euid, p->suid, p->fsuid,
               p->gid, p->egid, p->sgid, p->fsgid);
***************
*** 264,271 ****
     return buffer + sprintf(buffer, "CapInh:\t%016x\n"
                           "CapPrm:\t%016x\n"
!                           "CapEff:\t%016x\n",
                           cap_t(p->cap_inheritable),
                           cap_t(p->cap_permitted),
!                           cap_t(p->cap_effective));
 }

--- 269,278 ----
     return buffer + sprintf(buffer, "CapInh:\t%016x\n"
                           "CapPrm:\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_bset));
 }

***************
*** 289,292 ****
--- 296,316 ----
       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);
+       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\n",__NR_set_ipv4root);
 #if defined(CONFIG_ARCH_S390)
       buffer = task_show_regs(task, buffer);
***************
*** 342,345 ****
--- 366,371 ----
       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 \
diff -rc2P linux-2.4.18/fs/proc/base.c linux-2.4.18ctx-8/fs/proc/base.c
*** linux-2.4.18/fs/proc/base.c Tue Feb 26 22:22:07 2002
--- linux-2.4.18ctx-8/fs/proc/base.c    Tue Feb 26 22:31:23 2002
***************
*** 973,976 ****
--- 973,982 ----
               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);

***************
*** 983,987 ****
       inode->i_fop = &proc_base_operations;
       inode->i_nlink = 3;
!       inode->i_flags|=S_IMMUTABLE;

       dentry->d_op = &pid_base_dentry_operations;
--- 989,993 ----
       inode->i_fop = &proc_base_operations;
       inode->i_nlink = 3;
!       inode->i_flags|=S_IMMUTABLE_FILE;

       dentry->d_op = &pid_base_dentry_operations;
***************
*** 1019,1022 ****
--- 1025,1041 ----
               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;
diff -rc2P linux-2.4.18/fs/udf/inode.c linux-2.4.18ctx-8/fs/udf/inode.c
*** linux-2.4.18/fs/udf/inode.c Tue Feb 26 22:22:08 2002
--- linux-2.4.18ctx-8/fs/udf/inode.c    Tue Feb 26 22:31:23 2002
***************
*** 864,868 ****
                       S_ISLNK(inode->i_mode)))
               return;
!       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
               return;

--- 864,868 ----
                       S_ISLNK(inode->i_mode)))
               return;
!       if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode))
               return;

diff -rc2P linux-2.4.18/fs/ufs/truncate.c linux-2.4.18ctx-8/fs/ufs/truncate.c
*** linux-2.4.18/fs/ufs/truncate.c      Tue Feb 26 22:22:08 2002
--- linux-2.4.18ctx-8/fs/ufs/truncate.c Tue Feb 26 22:31:23 2002
***************
*** 435,439 ****
       if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)))
               return;
!       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
               return;
       while (1) {
--- 435,439 ----
       if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)))
               return;
!       if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode))
               return;
       while (1) {
diff -rc2P linux-2.4.18/include/asm-i386/unistd.h linux-2.4.18ctx-8/include/asm-i386/unistd.h
*** linux-2.4.18/include/asm-i386/unistd.h      Tue Feb 26 22:22:08 2002
--- linux-2.4.18ctx-8/include/asm-i386/unistd.h Wed Feb 27 14:36:00 2002
***************
*** 243,246 ****
--- 243,248 ----
 #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 <asm-i386/errno.h> */
diff -rc2P linux-2.4.18/include/linux/capability.h linux-2.4.18ctx-8/include/linux/capability.h
*** linux-2.4.18/include/linux/capability.h     Fri Nov 23 15:07:52 2001
--- linux-2.4.18ctx-8/include/linux/capability.h        Wed Feb 27 14:56:16 2002
***************
*** 232,235 ****
--- 232,236 ----
    arbitrary SCSI commands */
 /* Allow setting encryption key on loopback filesystem */
+ /* Allow the selection of a security context */

 #define CAP_SYS_ADMIN        21
***************
*** 279,282 ****
--- 280,287 ----

 #define CAP_LEASE            28
+
+ /* Allow opening special device file */
+
+ #define CAP_OPENDEV          29

 #ifdef __KERNEL__
diff -rc2P linux-2.4.18/include/linux/devpts_fs_info.h linux-2.4.18ctx-8/include/linux/devpts_fs_info.h
*** linux-2.4.18/include/linux/devpts_fs_info.h Wed Dec 31 19:00:00 1969
--- linux-2.4.18ctx-8/include/linux/devpts_fs_info.h    Tue Feb 26 22:31:23 2002
***************
*** 0 ****
--- 1,4 ----
+ struct devpts_inode_info{
+       int s_context;
+ };
+
diff -rc2P linux-2.4.18/include/linux/ext2_fs.h linux-2.4.18ctx-8/include/linux/ext2_fs.h
*** linux-2.4.18/include/linux/ext2_fs.h        Wed Oct 31 15:32:45 2001
--- linux-2.4.18ctx-8/include/linux/ext2_fs.h   Wed Feb 27 14:57:04 2002
***************
*** 188,192 ****
 #define       EXT2_COMPR_FL                   0x00000004 /* Compress file */
 #define EXT2_SYNC_FL                  0x00000008 /* Synchronous updates */
! #define EXT2_IMMUTABLE_FL             0x00000010 /* Immutable file */
 #define EXT2_APPEND_FL                        0x00000020 /* writes to file may only append */
 #define EXT2_NODUMP_FL                        0x00000040 /* do not dump file */
--- 188,192 ----
 #define       EXT2_COMPR_FL                   0x00000004 /* Compress file */
 #define EXT2_SYNC_FL                  0x00000008 /* Synchronous updates */
! #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 */
***************
*** 199,206 ****
 /* End compression flags --- maybe not all used */
 #define EXT2_BTREE_FL                 0x00001000 /* btree format dir */
 #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 */

 /*
--- 199,207 ----
 /* 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          0x00009FFF /* User visible flags */
! #define EXT2_FL_USER_MODIFIABLE               0x000080FF /* User modifiable flags */

 /*
diff -rc2P linux-2.4.18/include/linux/ext3_fs.h linux-2.4.18ctx-8/include/linux/ext3_fs.h
*** linux-2.4.18/include/linux/ext3_fs.h        Tue Feb 26 22:22:11 2002
--- linux-2.4.18ctx-8/include/linux/ext3_fs.h   Wed Feb 27 15:00:17 2002
***************
*** 191,195 ****
 #define       EXT3_COMPR_FL                   0x00000004 /* Compress file */
 #define EXT3_SYNC_FL                  0x00000008 /* Synchronous updates */
! #define EXT3_IMMUTABLE_FL             0x00000010 /* Immutable file */
 #define EXT3_APPEND_FL                        0x00000020 /* writes to file may only append */
 #define EXT3_NODUMP_FL                        0x00000040 /* do not dump file */
--- 191,195 ----
 #define       EXT3_COMPR_FL                   0x00000004 /* Compress file */
 #define EXT3_SYNC_FL                  0x00000008 /* Synchronous updates */
! #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 */
***************
*** 204,211 ****
 #define EXT3_IMAGIC_FL                        0x00002000 /* AFS directory */
 #define EXT3_JOURNAL_DATA_FL          0x00004000 /* file data should be journaled */
 #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 */

 /*
--- 204,212 ----
 #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          0x0000DFFF /* User visible flags */
! #define EXT3_FL_USER_MODIFIABLE               0x000080FF /* User modifiable flags */

 /*
diff -rc2P linux-2.4.18/include/linux/fs.h linux-2.4.18ctx-8/include/linux/fs.h
*** linux-2.4.18/include/linux/fs.h     Tue Feb 26 22:22:11 2002
--- linux-2.4.18ctx-8/include/linux/fs.h        Wed Feb 27 14:56:16 2002
***************
*** 129,139 ****
 /* 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 */

 /*
--- 129,140 ----
 /* 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_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 */

 /*
***************
*** 159,163 ****
 #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_NOATIME(inode)     (__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME))
 #define IS_NODIRATIME(inode)  __IS_FLG(inode, MS_NODIRATIME)
--- 160,165 ----
 #define IS_NOQUOTA(inode)     ((inode)->i_flags & S_NOQUOTA)
 #define IS_APPEND(inode)      ((inode)->i_flags & S_APPEND)
! #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)
***************
*** 317,320 ****
--- 319,323 ----
 #include <linux/jffs2_fs_i.h>
 #include <linux/cramfs_fs_sb.h>
+ #include <linux/devpts_fs_info.h>

 /*
***************
*** 358,366 ****
  * 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 */

 /*
--- 361,370 ----
  * 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_FILE      8       /* Immutable file */
! #define ATTR_FLAG_NODIRATIME          16      /* Don't update atime for directory */
! #define ATTR_FLAG_IMMUTABLE_LINK      32      /* Immutable file */

 /*
***************
*** 507,510 ****
--- 511,515 ----
               struct usbdev_inode_info        usbdev_i;
               struct jffs2_inode_info         jffs2_i;
+               struct devpts_inode_info        devpts_i;
               void                            *generic_ip;
       } u;
diff -rc2P linux-2.4.18/include/linux/sched.h linux-2.4.18ctx-8/include/linux/sched.h
*** linux-2.4.18/include/linux/sched.h  Sat Dec 22 22:38:45 2001
--- linux-2.4.18ctx-8/include/linux/sched.h     Wed Feb 27 14:56:17 2002
***************
*** 269,272 ****
--- 269,273 ----
       struct user_struct *next, **pprev;
       uid_t uid;
+       int s_context;
 };

***************
*** 276,279 ****
--- 277,309 ----
       __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)
***************
*** 400,403 ****
--- 430,439 ----
       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 */
+       struct context_info *s_info;
       void *notifier_data;
       sigset_t *notifier_mask;
***************
*** 502,505 ****
--- 538,542 ----
     alloc_lock:               SPIN_LOCK_UNLOCKED,                             \
     journal_info:     NULL,                                           \
+     cap_bset:         CAP_INIT_EFF_SET,                               \
 }

***************
*** 566,570 ****

 /* per-UID process charging. */
! extern struct user_struct * alloc_uid(uid_t);
 extern void free_uid(struct user_struct *);

--- 603,607 ----

 /* per-UID process charging. */
! extern struct user_struct * alloc_uid(int, uid_t);
 extern void free_uid(struct user_struct *);

***************
*** 927,930 ****
--- 964,972 ----
       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 -rc2P linux-2.4.18/include/net/route.h linux-2.4.18ctx-8/include/net/route.h
*** linux-2.4.18/include/net/route.h    Tue Feb 26 22:22:12 2002
--- linux-2.4.18ctx-8/include/net/route.h       Wed Feb 27 14:58:16 2002
***************
*** 161,164 ****
--- 161,174 ----
 {
       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))
diff -rc2P linux-2.4.18/include/net/sock.h linux-2.4.18ctx-8/include/net/sock.h
*** linux-2.4.18/include/net/sock.h     Sat Dec 22 22:38:45 2001
--- linux-2.4.18ctx-8/include/net/sock.h        Wed Feb 27 14:58:16 2002
***************
*** 669,673 ****
       /* RPC layer private data */
       void                    *user_data;
!
       /* Callbacks */
       void                    (*state_change)(struct sock *sk);
--- 669,676 ----
       /* RPC layer private data */
       void                    *user_data;
!
!       /* Context of process creating this socket */
!       int                     s_context;
!
       /* Callbacks */
       void                    (*state_change)(struct sock *sk);
diff -rc2P linux-2.4.18/include/net/tcp.h linux-2.4.18ctx-8/include/net/tcp.h
*** linux-2.4.18/include/net/tcp.h      Wed Oct 10 11:58:22 2001
--- linux-2.4.18ctx-8/include/net/tcp.h Wed Feb 27 15:06:38 2002
***************
*** 191,194 ****
--- 191,195 ----
       struct in6_addr         v6_rcv_saddr;
 #endif
+       int                     s_context;
 };

diff -rc2P linux-2.4.18/ipc/util.c linux-2.4.18ctx-8/ipc/util.c
*** linux-2.4.18/ipc/util.c     Sun Aug 12 20:37:53 2001
--- linux-2.4.18ctx-8/ipc/util.c        Tue Feb 26 22:31:23 2002
***************
*** 94,97 ****
--- 94,98 ----

       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)
***************
*** 168,171 ****
--- 169,173 ----
       spin_lock(&ids->ary);
       ids->entries[id].p = new;
+       ids->entries[id].s_context = current->s_context;
       return id;
 }
diff -rc2P linux-2.4.18/ipc/util.h linux-2.4.18ctx-8/ipc/util.h
*** linux-2.4.18/ipc/util.h     Mon Feb 19 13:18:18 2001
--- linux-2.4.18ctx-8/ipc/util.h        Tue Feb 26 22:31:23 2002
***************
*** 26,29 ****
--- 26,30 ----
 struct ipc_id {
       struct kern_ipc_perm* p;
+       int s_context;  // Context owning this ID
 };

***************
*** 75,80 ****
       spin_lock(&ids->ary);
       out = ids->entries[lid].p;
!       if(out==NULL)
               spin_unlock(&ids->ary);
       return out;
 }
--- 76,85 ----
       spin_lock(&ids->ary);
       out = ids->entries[lid].p;
!       if(out==NULL
!               || (ids->entries[lid].s_context != current->s_context
!                       && current->s_context != 1)){
               spin_unlock(&ids->ary);
+               out = NULL;
+       }
       return out;
 }
diff -rc2P linux-2.4.18/kernel/exit.c linux-2.4.18ctx-8/kernel/exit.c
*** linux-2.4.18/kernel/exit.c  Tue Feb 26 22:22:12 2002
--- linux-2.4.18ctx-8/kernel/exit.c     Wed Feb 27 14:45:32 2002
***************
*** 66,69 ****
--- 66,70 ----
               if (current->counter >= MAX_COUNTER)
                       current->counter = MAX_COUNTER;
+               sys_release_s_info(p);
               p->pid = 0;
               free_task_struct(p);
***************
*** 159,169 ****
 {
       struct task_struct * p, *reaper;

       read_lock(&tasklist_lock);
!
       /* Next in our thread group */
       reaper = next_thread(father);
       if (reaper == father)
!               reaper = child_reaper;

       for_each_task(p) {
--- 160,178 ----
 {
       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 = vchild_reaper;

       for_each_task(p) {
***************
*** 175,179 ****
                       /* Make sure we're not reparenting to ourselves */
                       if (p == reaper)
!                               p->p_opptr = child_reaper;
                       else
                               p->p_opptr = reaper;
--- 184,188 ----
                       /* Make sure we're not reparenting to ourselves */
                       if (p == reaper)
!                               p->p_opptr = vchild_reaper;
                       else
                               p->p_opptr = reaper;
diff -rc2P linux-2.4.18/kernel/fork.c linux-2.4.18ctx-8/kernel/fork.c
*** linux-2.4.18/kernel/fork.c  Tue Feb 26 22:22:12 2002
--- linux-2.4.18ctx-8/kernel/fork.c     Wed Feb 27 14:48:50 2002
***************
*** 589,592 ****
--- 589,596 ----

       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
***************
*** 598,601 ****
--- 602,607 ----
                     && !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE))
               goto bad_fork_free;
+
+       sys_assign_s_info (p);

       atomic_inc(&p->user->__count);
diff -rc2P linux-2.4.18/kernel/printk.c linux-2.4.18ctx-8/kernel/printk.c
*** linux-2.4.18/kernel/printk.c        Tue Feb 26 22:22:12 2002
--- linux-2.4.18ctx-8/kernel/printk.c   Tue Feb 26 22:31:23 2002
***************
*** 173,176 ****
--- 173,178 ----
       int error = 0;

+       if (!capable(CAP_SYS_ADMIN) && current->s_context != 0) return -EPERM;
+
       switch (type) {
       case 0:         /* Close log */
diff -rc2P linux-2.4.18/kernel/sched.c linux-2.4.18ctx-8/kernel/sched.c
*** linux-2.4.18/kernel/sched.c Sat Dec 22 22:38:45 2001
--- linux-2.4.18ctx-8/kernel/sched.c    Tue Feb 26 22:31:23 2002
***************
*** 166,170 ****
                * over..
                */
!               weight = p->counter;
               if (!weight)
                       goto out;
--- 166,176 ----
                * over..
                */
!               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;
***************
*** 621,626 ****
               spin_unlock_irq(&runqueue_lock);
               read_lock(&tasklist_lock);
!               for_each_task(p)
                       p->counter = (p->counter >> 1) + NICE_TO_TICKS(p->nice);
               read_unlock(&tasklist_lock);
               spin_lock_irq(&runqueue_lock);
--- 627,647 ----
               spin_unlock_irq(&runqueue_lock);
               read_lock(&tasklist_lock);
!               /*
!                       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);
diff -rc2P linux-2.4.18/kernel/signal.c linux-2.4.18ctx-8/kernel/signal.c
*** linux-2.4.18/kernel/signal.c        Fri Nov 23 15:07:52 2001
--- linux-2.4.18ctx-8/kernel/signal.c   Tue Feb 26 22:31:23 2002
***************
*** 593,597 ****
               read_lock(&tasklist_lock);
               for_each_task(p) {
!                       if (p->pgrp == pgrp) {
                               int err = send_sig_info(sig, info, p);
                               if (retval)
--- 593,599 ----
               read_lock(&tasklist_lock);
               for_each_task(p) {
!                       if (p->pgrp == pgrp
!                               && ((long)info==1
!                                       || p->s_context == current->s_context)) {
                               int err = send_sig_info(sig, info, p);
                               if (retval)
***************
*** 640,645 ****
       p = find_task_by_pid(pid);
       error = -ESRCH;
!       if (p)
!               error = send_sig_info(sig, info, p);
       read_unlock(&tasklist_lock);
       return error;
--- 642,663 ----
       p = find_task_by_pid(pid);
       error = -ESRCH;
!       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;
***************
*** 664,668 ****
               read_lock(&tasklist_lock);
               for_each_task(p) {
!                       if (p->pid > 1 && p != current) {
                               int err = send_sig_info(sig, info, p);
                               ++count;
--- 682,686 ----
               read_lock(&tasklist_lock);
               for_each_task(p) {
!                       if (p->pid > 1 && p != current && p->s_context == current->s_context) {
                               int err = send_sig_info(sig, info, p);
                               ++count;
***************
*** 1257,1258 ****
--- 1275,1420 ----
 }
 #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 -rc2P linux-2.4.18/kernel/sys.c linux-2.4.18ctx-8/kernel/sys.c
*** linux-2.4.18/kernel/sys.c   Tue Feb 26 22:22:12 2002
--- linux-2.4.18ctx-8/kernel/sys.c      Tue Feb 26 22:31:23 2002
***************
*** 7,10 ****
--- 7,11 ----
 #include <linux/module.h>
 #include <linux/mm.h>
+ #include <linux/vmalloc.h>
 #include <linux/utsname.h>
 #include <linux/mman.h>
***************
*** 500,504 ****
        * we should be checking for it.  -DaveM
        */
!       new_user = alloc_uid(new_ruid);
       if (!new_user)
               return -EAGAIN;
--- 501,505 ----
        * we should be checking for it.  -DaveM
        */
!       new_user = alloc_uid(current->s_context, new_ruid);
       if (!new_user)
               return -EAGAIN;
***************
*** 1016,1022 ****
 {
       int errno = 0;

       down_read(&uts_sem);
!       if (copy_to_user(name,&system_utsname,sizeof *name))
               errno = -EFAULT;
       up_read(&uts_sem);
--- 1017,1032 ----
 {
       int errno = 0;
+       struct new_utsname tmp,*pttmp;

       down_read(&uts_sem);
!       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);
***************
*** 1024,1030 ****
--- 1034,1095 ----
 }

+ /*
+       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))
***************
*** 1034,1039 ****
       down_write(&uts_sem);
       errno = -EFAULT;
!       if (!copy_from_user(system_utsname.nodename, name, len)) {
!               system_utsname.nodename[len] = 0;
               errno = 0;
       }
--- 1099,1106 ----
       down_write(&uts_sem);
       errno = -EFAULT;
!       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;
       }
***************
*** 1045,1057 ****
 {
       int i, errno;

       if (len < 0)
               return -EINVAL;
       down_read(&uts_sem);
!       i = 1 + strlen(system_utsname.nodename);
       if (i > len)
               i = len;
       errno = 0;
!       if (copy_to_user(name, system_utsname.nodename, i))
               errno = -EFAULT;
       up_read(&uts_sem);
--- 1112,1127 ----
 {
       int i, errno;
+       char *nodename;

       if (len < 0)
               return -EINVAL;
       down_read(&uts_sem);
!       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, nodename, i))
               errno = -EFAULT;
       up_read(&uts_sem);
***************
*** 1066,1069 ****
--- 1136,1140 ----
 {
       int errno;
+       char *domainname;

       if (!capable(CAP_SYS_ADMIN))
***************
*** 1073,1080 ****

       down_write(&uts_sem);
       errno = -EFAULT;
!       if (!copy_from_user(system_utsname.domainname, name, len)) {
               errno = 0;
!               system_utsname.domainname[len] = 0;
       }
       up_write(&uts_sem);
--- 1144,1153 ----

       down_write(&uts_sem);
+       domainname = system_utsname.domainname;
+       if (current->s_info) domainname = current->s_info->domainname;
       errno = -EFAULT;
!       if (!copy_from_user(domainname, name, len)) {
               errno = 0;
!               domainname[len] = 0;
       }
       up_write(&uts_sem);
diff -rc2P linux-2.4.18/kernel/sysctl.c linux-2.4.18ctx-8/kernel/sysctl.c
*** linux-2.4.18/kernel/sysctl.c        Sat Dec 22 22:38:45 2001
--- linux-2.4.18ctx-8/kernel/sysctl.c   Tue Feb 26 22:31:23 2002
***************
*** 380,383 ****
--- 380,384 ----
 static int test_perm(int mode, int op)
 {
+       if (!capable(CAP_SYS_ADMIN)) mode &= ~(0222);
       if (!current->euid)
               mode >>= 6;
***************
*** 794,798 ****
--- 795,810 ----
 {
       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 = &current->s_info->nodename;
+               }else if (table->data == (void*)&system_utsname.domainname){
+                       tmp.data = &current->s_info->domainname;
+               }
+       }
       if (!write) {
               down_read(&uts_sem);
diff -rc2P linux-2.4.18/kernel/timer.c linux-2.4.18ctx-8/kernel/timer.c
*** linux-2.4.18/kernel/timer.c Wed Oct 10 11:58:22 2001
--- linux-2.4.18ctx-8/kernel/timer.c    Tue Feb 26 22:31:23 2002
***************
*** 584,587 ****
--- 584,592 ----
       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;
***************
*** 720,723 ****
--- 725,733 ----
 {
       /* 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;
 }
***************
*** 765,768 ****
--- 775,784 ----
 #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 -rc2P linux-2.4.18/kernel/user.c linux-2.4.18ctx-8/kernel/user.c
*** linux-2.4.18/kernel/user.c  Wed Nov 29 01:43:39 2000
--- linux-2.4.18ctx-8/kernel/user.c     Tue Feb 26 22:31:23 2002
***************
*** 7,10 ****
--- 7,23 ----
  * 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 [email protected])
+  *
+  * 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.
  */

***************
*** 57,61 ****
 }

! static inline struct user_struct *uid_hash_find(uid_t uid, struct user_struct **hashent)
 {
       struct user_struct *next;
--- 70,74 ----
 }

! static inline struct user_struct *uid_hash_find(int s_context, uid_t uid, struct user_struct **hashent)
 {
       struct user_struct *next;
***************
*** 66,70 ****
               if (next) {
                       next = up->next;
!                       if (up->uid != uid)
                               continue;
                       atomic_inc(&up->__count);
--- 79,83 ----
               if (next) {
                       next = up->next;
!                       if (up->uid != uid || up->s_context != s_context)
                               continue;
                       atomic_inc(&up->__count);
***************
*** 83,87 ****
 }

! struct user_struct * alloc_uid(uid_t uid)
 {
       struct user_struct **hashent = uidhashentry(uid);
--- 96,100 ----
 }

! struct user_struct * alloc_uid(int s_context, uid_t uid)
 {
       struct user_struct **hashent = uidhashentry(uid);
***************
*** 89,93 ****

       spin_lock(&uidhash_lock);
!       up = uid_hash_find(uid, hashent);
       spin_unlock(&uidhash_lock);

--- 102,106 ----

       spin_lock(&uidhash_lock);
!       up = uid_hash_find(s_context, uid, hashent);
       spin_unlock(&uidhash_lock);

***************
*** 99,102 ****
--- 112,116 ----
                       return NULL;
               new->uid = uid;
+               new->s_context = s_context;
               atomic_set(&new->__count, 1);
               atomic_set(&new->processes, 0);
***************
*** 108,112 ****
                */
               spin_lock(&uidhash_lock);
!               up = uid_hash_find(uid, hashent);
               if (up) {
                       kmem_cache_free(uid_cachep, new);
--- 122,126 ----
                */
               spin_lock(&uidhash_lock);
!               up = uid_hash_find(s_context, uid, hashent);
               if (up) {
                       kmem_cache_free(uid_cachep, new);
diff -rc2P linux-2.4.18/net/ipv4/af_inet.c linux-2.4.18ctx-8/net/ipv4/af_inet.c
*** linux-2.4.18/net/ipv4/af_inet.c     Sat Dec 22 22:38:46 2001
--- linux-2.4.18ctx-8/net/ipv4/af_inet.c        Tue Feb 26 22:31:23 2002
***************
*** 394,397 ****
--- 394,399 ----
       sk->protinfo.af_inet.mc_list    = NULL;

+       sk->s_context = current->s_context;
+
 #ifdef INET_REFCNT_DEBUG
       atomic_inc(&inet_sock_nr);
***************
*** 478,481 ****
--- 480,484 ----
       int chk_addr_ret;
       int err;
+       __u32 s_addr;

       /* If the socket has its own bind function then use it. (RAW) */
***************
*** 486,490 ****
               return -EINVAL;

!       chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr);

       /* Not specified by any standard per-se, however it breaks too
--- 489,503 ----
               return -EINVAL;

!       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 == 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
***************
*** 497,501 ****
       if (sysctl_ip_nonlocal_bind == 0 &&
           sk->protinfo.af_inet.freebind == 0 &&
!           addr->sin_addr.s_addr != INADDR_ANY &&
           chk_addr_ret != RTN_LOCAL &&
           chk_addr_ret != RTN_MULTICAST &&
--- 510,514 ----
       if (sysctl_ip_nonlocal_bind == 0 &&
           sk->protinfo.af_inet.freebind == 0 &&
!           s_addr != INADDR_ANY &&
           chk_addr_ret != RTN_LOCAL &&
           chk_addr_ret != RTN_MULTICAST &&
***************
*** 522,526 ****
               goto out;

!       sk->rcv_saddr = sk->saddr = addr->sin_addr.s_addr;
       if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
               sk->saddr = 0;  /* Use device */
--- 535,539 ----
               goto out;

!       sk->rcv_saddr = sk->saddr = s_addr;
       if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
               sk->saddr = 0;  /* Use device */
diff -rc2P linux-2.4.18/net/ipv4/devinet.c linux-2.4.18ctx-8/net/ipv4/devinet.c
*** linux-2.4.18/net/ipv4/devinet.c     Sat Dec 22 22:38:46 2001
--- linux-2.4.18ctx-8/net/ipv4/devinet.c        Tue Feb 26 22:31:23 2002
***************
*** 559,563 ****
               goto done;
       }
!
       switch(cmd) {
               case SIOCGIFADDR:       /* Get interface address */
--- 559,569 ----
               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 */
***************
*** 692,695 ****
--- 698,705 ----

       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);
***************
*** 909,912 ****
--- 919,925 ----
               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;
diff -rc2P linux-2.4.18/net/ipv4/raw.c linux-2.4.18ctx-8/net/ipv4/raw.c
*** linux-2.4.18/net/ipv4/raw.c Tue Jul 10 19:11:43 2001
--- linux-2.4.18ctx-8/net/ipv4/raw.c    Tue Feb 26 22:31:23 2002
***************
*** 658,662 ****

               for (sk = raw_v4_htable[i]; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET)
                               continue;
                       pos += 128;
--- 658,662 ----

               for (sk = raw_v4_htable[i]; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET || (current->s_context != 1 && sk->s_context != current->s_context))
                               continue;
                       pos += 128;
diff -rc2P linux-2.4.18/net/ipv4/tcp_ipv4.c linux-2.4.18ctx-8/net/ipv4/tcp_ipv4.c
*** linux-2.4.18/net/ipv4/tcp_ipv4.c    Tue Feb 26 22:22:12 2002
--- linux-2.4.18ctx-8/net/ipv4/tcp_ipv4.c       Tue Feb 26 22:31:23 2002
***************
*** 2074,2077 ****
--- 2074,2080 ----
                       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;
***************
*** 2127,2131 ****
               read_lock(&head->lock);
               for(sk = head->chain; sk; sk = sk->next, num++) {
!                       if (!TCP_INET_FAMILY(sk->family))
                               continue;
                       pos += TMPSZ;
--- 2130,2134 ----
               read_lock(&head->lock);
               for(sk = head->chain; sk; sk = sk->next, num++) {
!                       if (!TCP_INET_FAMILY(sk->family) || (current->s_context != 1 && sk->s_context != current->s_context))
                               continue;
                       pos += TMPSZ;
***************
*** 2142,2146 ****
                    tw != NULL;
                    tw = (struct tcp_tw_bucket *)tw->next, num++) {
!                       if (!TCP_INET_FAMILY(tw->family))
                               continue;
                       pos += TMPSZ;
--- 2145,2149 ----
                    tw != NULL;
                    tw = (struct tcp_tw_bucket *)tw->next, num++) {
!                       if (!TCP_INET_FAMILY(tw->family) || (current->s_context != 1 && tw->s_context != current->s_context))
                               continue;
                       pos += TMPSZ;
diff -rc2P linux-2.4.18/net/ipv4/tcp_minisocks.c linux-2.4.18ctx-8/net/ipv4/tcp_minisocks.c
*** linux-2.4.18/net/ipv4/tcp_minisocks.c       Wed Oct 10 11:58:23 2001
--- linux-2.4.18ctx-8/net/ipv4/tcp_minisocks.c  Tue Feb 26 22:31:23 2002
***************
*** 382,385 ****
--- 382,387 ----
               tw->pprev_death = NULL;

+               tw->s_context   = sk->s_context;
+
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
               if(tw->family == PF_INET6) {
diff -rc2P linux-2.4.18/net/ipv4/udp.c linux-2.4.18ctx-8/net/ipv4/udp.c
*** linux-2.4.18/net/ipv4/udp.c Tue Feb 26 22:22:12 2002
--- linux-2.4.18ctx-8/net/ipv4/udp.c    Tue Feb 26 22:31:23 2002
***************
*** 988,992 ****

               for (sk = udp_hash[i]; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET)
                               continue;
                       pos += 128;
--- 988,992 ----

               for (sk = udp_hash[i]; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET || (current->s_context != 1 && sk->s_context != current->s_context))
                               continue;
                       pos += 128;
diff -rc2P linux-2.4.18/net/ipv6/raw.c linux-2.4.18ctx-8/net/ipv6/raw.c
*** linux-2.4.18/net/ipv6/raw.c Thu Sep 20 17:12:56 2001
--- linux-2.4.18ctx-8/net/ipv6/raw.c    Tue Feb 26 22:31:23 2002
***************
*** 798,802 ****

               for (sk = raw_v6_htable[i]; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET6)
                               continue;
                       pos += LINE_LEN+1;
--- 798,802 ----

               for (sk = raw_v6_htable[i]; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET6 || (current->s_context != 1 && sk->s_context != current->s_context))
                               continue;
                       pos += LINE_LEN+1;
diff -rc2P linux-2.4.18/net/ipv6/tcp_ipv6.c linux-2.4.18ctx-8/net/ipv6/tcp_ipv6.c
*** linux-2.4.18/net/ipv6/tcp_ipv6.c    Tue Feb 26 22:22:13 2002
--- linux-2.4.18ctx-8/net/ipv6/tcp_ipv6.c       Tue Feb 26 22:31:23 2002
***************
*** 2007,2011 ****
                       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);

!                       if (sk->family != PF_INET6)
                               continue;
                       pos += LINE_LEN+1;
--- 2007,2011 ----
                       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);

!                       if (sk->family != PF_INET6 || (current->s_context != 1 && sk->s_context != current->s_context))
                               continue;
                       pos += LINE_LEN+1;
***************
*** 2057,2061 ****
               read_lock(&head->lock);
               for(sk = head->chain; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET6)
                               continue;
                       pos += LINE_LEN+1;
--- 2057,2061 ----
               read_lock(&head->lock);
               for(sk = head->chain; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET6 || (current->s_context != 1 && sk->s_context != current->s_context))
                               continue;
                       pos += LINE_LEN+1;
***************
*** 2072,2076 ****
                    tw != NULL;
                    tw = (struct tcp_tw_bucket *)tw->next, num++) {
!                       if (tw->family != PF_INET6)
                               continue;
                       pos += LINE_LEN+1;
--- 2072,2076 ----
                    tw != NULL;
                    tw = (struct tcp_tw_bucket *)tw->next, num++) {
!                       if (tw->family != PF_INET6 || (current->s_context != 1 && tw->s_context != current->s_context))
                               continue;
                       pos += LINE_LEN+1;
diff -rc2P linux-2.4.18/net/ipv6/udp.c linux-2.4.18ctx-8/net/ipv6/udp.c
*** linux-2.4.18/net/ipv6/udp.c Fri Sep  7 14:01:21 2001
--- linux-2.4.18ctx-8/net/ipv6/udp.c    Tue Feb 26 22:31:23 2002
***************
*** 953,957 ****

               for (sk = udp_hash[i]; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET6)
                               continue;
                       pos += LINE_LEN+1;
--- 953,957 ----

               for (sk = udp_hash[i]; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET6 || (current->s_context != 1 && sk->s_context != current->s_context))
                               continue;
                       pos += LINE_LEN+1;
diff -rc2P linux-2.4.18/net/socket.c linux-2.4.18ctx-8/net/socket.c
*** linux-2.4.18/net/socket.c   Sat Dec 22 22:38:47 2001
--- linux-2.4.18ctx-8/net/socket.c      Tue Feb 26 22:31:23 2002
***************
*** 1764,1765 ****
--- 1764,1777 ----
       return len;
 }
+
+ asmlinkage int sys_set_ipv4root (unsigned long ip)
+ {
+       int ret = -EPERM;
+       if (current->ipv4root == 0
+               || capable(CAP_SYS_ADMIN)){
+               ret = 0;
+               current->ipv4root = ip;
+       }
+       return ret;
+ }
+
diff -rc2P linux-2.4.18/net/unix/af_unix.c linux-2.4.18ctx-8/net/unix/af_unix.c
*** linux-2.4.18/net/unix/af_unix.c     Tue Feb 26 22:22:13 2002
--- linux-2.4.18ctx-8/net/unix/af_unix.c        Tue Feb 26 22:31:23 2002
***************
*** 480,483 ****
--- 480,485 ----
       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;
***************
*** 1751,1754 ****
--- 1753,1759 ----
       forall_unix_sockets (i,s)
       {
+               if (current->s_context != 1 && s->s_context != current->s_context)
+                       continue;
+
               unix_state_rlock(s);