diff -rc2P linux-2.4.17ctx-5/Makefile linux-2.4.17ctx-6/Makefile
*** linux-2.4.17ctx-5/Makefile  Sun Jan 13 21:17:40 2002
--- linux-2.4.17ctx-6/Makefile  Tue Jan  8 23:35:19 2002
***************
*** 2,6 ****
 PATCHLEVEL = 4
 SUBLEVEL = 17
! EXTRAVERSION =ctx-5

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

 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff -rc2P linux-2.4.17ctx-5/fs/devpts/inode.c linux-2.4.17ctx-6/fs/devpts/inode.c
*** linux-2.4.17ctx-5/fs/devpts/inode.c Wed Oct 10 11:58:19 2001
--- linux-2.4.17ctx-6/fs/devpts/inode.c Sun Jan 27 00:34:45 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.17ctx-5/fs/devpts/root.c linux-2.4.17ctx-6/fs/devpts/root.c
*** linux-2.4.17ctx-5/fs/devpts/root.c  Sat Dec 22 22:38:37 2001
--- linux-2.4.17ctx-6/fs/devpts/root.c  Sun Jan 27 00:34:20 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,72 ----
               while ( nr - 2 < sbi->max_ptys ) {
                       int ptynr = nr - 2;
!                       struct inode *inode = sbi->inodes[ptynr];
!                       if ( inode != NULL
!                               && 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 ****
--- 104,108 ----
       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;
 }
--- 131,146 ----
               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.17ctx-5/fs/namei.c linux-2.4.17ctx-6/fs/namei.c
*** linux-2.4.17ctx-5/fs/namei.c        Sun Jan 13 21:17:40 2002
--- linux-2.4.17ctx-6/fs/namei.c        Wed Jan 23 22:41:06 2002
***************
*** 152,155 ****
--- 152,162 ----
       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 && current->s_context != 0) return -EACCES;
       if (mask & MAY_WRITE) {
               /*
diff -rc2P linux-2.4.17ctx-5/fs/proc/array.c linux-2.4.17ctx-6/fs/proc/array.c
*** linux-2.4.17ctx-5/fs/proc/array.c   Sun Jan 13 21:17:40 2002
--- linux-2.4.17ctx-6/fs/proc/array.c   Sun Jan 27 15:23:51 2002
***************
*** 148,153 ****
 {
       int g;
!
       read_lock(&tasklist_lock);
       buffer += sprintf(buffer,
               "State:\t%s\n"
--- 148,156 ----
 {
       int g;
!       pid_t ppid;
       read_lock(&tasklist_lock);
+       ppid = p->p_opptr->pid;
+       if (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);
--- 162,166 ----
               "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);
***************
*** 299,305 ****
--- 302,311 ----
               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");
       }
 #if defined(CONFIG_ARCH_S390)
***************
*** 356,359 ****
--- 362,367 ----
       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.17ctx-5/fs/proc/base.c linux-2.4.17ctx-6/fs/proc/base.c
*** linux-2.4.17ctx-5/fs/proc/base.c    Sun Jan 13 21:17:40 2002
--- linux-2.4.17ctx-6/fs/proc/base.c    Sun Jan 27 15:01:44 2002
***************
*** 1028,1031 ****
--- 1028,1034 ----
                       && 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.17ctx-5/include/linux/devpts_fs_info.h linux-2.4.17ctx-6/include/linux/devpts_fs_info.h
*** linux-2.4.17ctx-5/include/linux/devpts_fs_info.h    Wed Dec 31 19:00:00 1969
--- linux-2.4.17ctx-6/include/linux/devpts_fs_info.h    Thu Jan 24 23:28:00 2002
***************
*** 0 ****
--- 1,4 ----
+ struct devpts_inode_info{
+       int s_context;
+ };
+
diff -rc2P linux-2.4.17ctx-5/include/linux/fs.h linux-2.4.17ctx-6/include/linux/fs.h
*** linux-2.4.17ctx-5/include/linux/fs.h        Sun Jan 13 21:17:40 2002
--- linux-2.4.17ctx-6/include/linux/fs.h        Thu Jan 24 23:27:35 2002
***************
*** 318,321 ****
--- 318,322 ----
 #include <linux/jffs2_fs_i.h>
 #include <linux/cramfs_fs_sb.h>
+ #include <linux/devpts_fs_info.h>

 /*
***************
*** 509,512 ****
--- 510,514 ----
               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.17ctx-5/include/linux/sched.h linux-2.4.17ctx-6/include/linux/sched.h
*** linux-2.4.17ctx-5/include/linux/sched.h     Sun Jan 13 21:17:40 2002
--- linux-2.4.17ctx-6/include/linux/sched.h     Thu Jan 24 23:30:50 2002
***************
*** 287,290 ****
--- 287,293 ----
 #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 */


***************
*** 297,300 ****
--- 300,305 ----
       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 */
 };

diff -rc2P linux-2.4.17ctx-5/ipc/util.c linux-2.4.17ctx-6/ipc/util.c
*** linux-2.4.17ctx-5/ipc/util.c        Sun Aug 12 20:37:53 2001
--- linux-2.4.17ctx-6/ipc/util.c        Thu Jan 24 16:28:58 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.17ctx-5/ipc/util.h linux-2.4.17ctx-6/ipc/util.h
*** linux-2.4.17ctx-5/ipc/util.h        Mon Feb 19 13:18:18 2001
--- linux-2.4.17ctx-6/ipc/util.h        Sun Jan 27 00:51:19 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.17ctx-5/kernel/exit.c linux-2.4.17ctx-6/kernel/exit.c
*** linux-2.4.17ctx-5/kernel/exit.c     Sun Jan 13 21:17:41 2002
--- linux-2.4.17ctx-6/kernel/exit.c     Wed Jan  9 23:13:43 2002
***************
*** 158,164 ****
 {
       struct task_struct * p;

       read_lock(&tasklist_lock);
!
       for_each_task(p) {
               if (p->p_opptr == father) {
--- 158,172 ----
 {
       struct task_struct * p;
+       struct task_struct *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) reaper = r;
!               }
!       }
       for_each_task(p) {
               if (p->p_opptr == father) {
***************
*** 166,170 ****
                       p->exit_signal = SIGCHLD;
                       p->self_exec_id++;
!                       p->p_opptr = child_reaper;
                       if (p->pdeath_signal) send_sig(p->pdeath_signal, p, 0);
               }
--- 174,178 ----
                       p->exit_signal = SIGCHLD;
                       p->self_exec_id++;
!                       p->p_opptr = reaper;
                       if (p->pdeath_signal) send_sig(p->pdeath_signal, p, 0);
               }
diff -rc2P linux-2.4.17ctx-5/kernel/printk.c linux-2.4.17ctx-6/kernel/printk.c
*** linux-2.4.17ctx-5/kernel/printk.c   Sat Dec 22 22:38:45 2001
--- linux-2.4.17ctx-6/kernel/printk.c   Mon Jan 21 21:46:10 2002
***************
*** 169,172 ****
--- 169,174 ----
       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.17ctx-5/kernel/signal.c linux-2.4.17ctx-6/kernel/signal.c
*** linux-2.4.17ctx-5/kernel/signal.c   Sun Jan 13 21:17:41 2002
--- linux-2.4.17ctx-6/kernel/signal.c   Wed Jan  9 14:18:51 2002
***************
*** 593,597 ****
               read_lock(&tasklist_lock);
               for_each_task(p) {
!                       if (p->pgrp == pgrp && p->s_context == current->s_context) {
                               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 && p->s_context == current->s_context)
!               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;
***************
*** 1258,1261 ****
--- 1276,1294 ----
 #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;
+ }
+
 /*
       Change to a new security context and reduce the capability
***************
*** 1302,1305 ****
--- 1335,1339 ----
                       sys_alloc_s_info();
                       if (current->s_info != NULL){
+                               set_initpid (flags);
                               current->s_info->flags |= flags;
                       }
***************
*** 1307,1315 ****
               }
       }else if (ctx == -2){
!               /* We keep the same s_context, but lower the capabilities */
!               current->cap_bset &= (~remove_cap);
!               ret = current->s_context;
!               if (current->s_info != NULL){
!                       current->s_info->flags |= flags;
               }
       }else if (ctx <= 0 || ctx > MAX_S_CONTEXT){
--- 1341,1355 ----
               }
       }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){
diff -rc2P linux-2.4.17ctx-5/kernel/sys.c linux-2.4.17ctx-6/kernel/sys.c
*** linux-2.4.17ctx-5/kernel/sys.c      Sun Jan 13 21:17:41 2002
--- linux-2.4.17ctx-6/kernel/sys.c      Wed Jan  9 14:09:08 2002
***************
*** 1073,1076 ****
--- 1073,1077 ----
       atomic_set (&s_info->ticks,current->counter);
       s_info->flags = 0;
+       s_info->initpid = 0;
       down_read (&uts_sem);
       if (current->s_info != NULL){
diff -rc2P linux-2.4.17ctx-5/kernel/timer.c linux-2.4.17ctx-6/kernel/timer.c
*** linux-2.4.17ctx-5/kernel/timer.c    Sun Jan 13 21:17:41 2002
--- linux-2.4.17ctx-6/kernel/timer.c    Sun Jan 27 14:49:24 2002
***************
*** 725,728 ****
--- 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;
 }
***************
*** 770,773 ****
--- 775,783 ----
 #endif
               break;
+       }
+       if (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.17ctx-5/net/ipv4/devinet.c linux-2.4.17ctx-6/net/ipv4/devinet.c
*** linux-2.4.17ctx-5/net/ipv4/devinet.c        Sat Dec 22 22:38:46 2001
--- linux-2.4.17ctx-6/net/ipv4/devinet.c        Thu Jan 24 12:06:09 2002
***************
*** 559,563 ****
               goto done;
       }
!
       switch(cmd) {
               case SIOCGIFADDR:       /* Get interface address */
--- 559,568 ----
               goto done;
       }
!       if (ifa != NULL
!               && current->ipv4root != 0
!               && current->ipv4root != ifa->ifa_local){
!               ret = -EADDRNOTAVAIL;
!               goto done;
!       }
       switch(cmd) {
               case SIOCGIFADDR:       /* Get interface address */
***************
*** 692,695 ****
--- 697,703 ----

       for ( ; ifa; ifa = ifa->ifa_next) {
+               // We do not show other IP devices to vservers
+               if (current->ipv4root != 0
+                       && current->ipv4root != ifa->ifa_local) continue;
               if (!buf) {
                       done += sizeof(ifr);