diff -rc2P linux-2.4.19/Makefile linux-2.4.19ctx-14/Makefile
*** linux-2.4.19/Makefile	Tue Aug  6 15:01:25 2002
--- linux-2.4.19ctx-14/Makefile	Sun Oct 13 23:58:54 2002
***************
*** 2,6 ****
  PATCHLEVEL = 4
  SUBLEVEL = 19
! EXTRAVERSION =
  
  KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
--- 2,6 ----
  PATCHLEVEL = 4
  SUBLEVEL = 19
! EXTRAVERSION =ctx-14
  
  KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff -rc2P linux-2.4.19/arch/i386/kernel/entry.S linux-2.4.19ctx-14/arch/i386/kernel/entry.S
*** linux-2.4.19/arch/i386/kernel/entry.S	Tue Aug  6 15:01:28 2002
--- linux-2.4.19ctx-14/arch/i386/kernel/entry.S	Sun Oct 13 23:58:54 2002
***************
*** 640,643 ****
--- 640,645 ----
  	.long SYMBOL_NAME(sys_ni_syscall)	/* reserved for sched_setaffinity */
  	.long SYMBOL_NAME(sys_ni_syscall)	/* reserved for sched_getaffinity */
+ 	.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.19/arch/i386/kernel/ptrace.c linux-2.4.19ctx-14/arch/i386/kernel/ptrace.c
*** linux-2.4.19/arch/i386/kernel/ptrace.c	Tue Aug  6 15:01:28 2002
--- linux-2.4.19ctx-14/arch/i386/kernel/ptrace.c	Sun Oct 13 23:58:54 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.19/arch/ppc/kernel/misc.S linux-2.4.19ctx-14/arch/ppc/kernel/misc.S
*** linux-2.4.19/arch/ppc/kernel/misc.S	Tue Aug  6 15:01:39 2002
--- linux-2.4.19ctx-14/arch/ppc/kernel/misc.S	Sun Oct 13 23:58:54 2002
***************
*** 1158,1161 ****
--- 1158,1163 ----
  	.long sys_gettid
  	.long sys_tkill
+ 	.long sys_new_s_context
+ 	.long sys_set_ipv4root
  	.rept NR_syscalls-(.-sys_call_table)/4
  		.long sys_ni_syscall
diff -rc2P linux-2.4.19/arch/ppc/kernel/ptrace.c linux-2.4.19ctx-14/arch/ppc/kernel/ptrace.c
*** linux-2.4.19/arch/ppc/kernel/ptrace.c	Tue Aug  6 15:01:39 2002
--- linux-2.4.19ctx-14/arch/ppc/kernel/ptrace.c	Sun Oct 13 23:58:54 2002
***************
*** 180,184 ****
  		get_task_struct(child);
  	read_unlock(&tasklist_lock);
! 	if (!child)
  		goto out;
  
--- 180,184 ----
  		get_task_struct(child);
  	read_unlock(&tasklist_lock);
! 	if (!child || child->s_context != current->s_context)
  		goto out;
  
diff -rc2P linux-2.4.19/arch/sparc/kernel/systbls.S linux-2.4.19ctx-14/arch/sparc/kernel/systbls.S
*** linux-2.4.19/arch/sparc/kernel/systbls.S	Tue Aug  6 15:01:41 2002
--- linux-2.4.19ctx-14/arch/sparc/kernel/systbls.S	Sun Oct 13 23:58:55 2002
***************
*** 71,75 ****
  /*245*/	.long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
  /*250*/	.long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
! /*255*/	.long sys_nis_syscall, sys_nis_syscall
  
  #ifdef CONFIG_SUNOS_EMUL
--- 71,77 ----
  /*245*/	.long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
  /*250*/	.long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
! /*255*/	.long sys_nis_syscall
! 	.long sys_new_s_context
! 	.long sys_set_ipv4root
  
  #ifdef CONFIG_SUNOS_EMUL
diff -rc2P linux-2.4.19/arch/sparc64/kernel/entry.S linux-2.4.19ctx-14/arch/sparc64/kernel/entry.S
*** linux-2.4.19/arch/sparc64/kernel/entry.S	Sat Dec 22 22:38:33 2001
--- linux-2.4.19ctx-14/arch/sparc64/kernel/entry.S	Mon Oct 14 00:00:26 2002
***************
*** 26,30 ****
  #define curptr      g6
  
! #define NR_SYSCALLS 256      /* Each OS is different... */
  
  	.text
--- 26,30 ----
  #define curptr      g6
  
! #define NR_SYSCALLS 258      /* Each OS is different... */
  
  	.text
diff -rc2P linux-2.4.19/arch/sparc64/kernel/ptrace.c linux-2.4.19ctx-14/arch/sparc64/kernel/ptrace.c
*** linux-2.4.19/arch/sparc64/kernel/ptrace.c	Tue Aug  6 15:01:44 2002
--- linux-2.4.19ctx-14/arch/sparc64/kernel/ptrace.c	Mon Oct 14 00:00:26 2002
***************
*** 157,161 ****
  	read_unlock(&tasklist_lock);
  
! 	if (!child) {
  		pt_error_return(regs, ESRCH);
  		goto out;
--- 157,161 ----
  	read_unlock(&tasklist_lock);
  
! 	if (!child || child->s_context != current->s_context) {
  		pt_error_return(regs, ESRCH);
  		goto out;
diff -rc2P linux-2.4.19/arch/sparc64/kernel/systbls.S linux-2.4.19ctx-14/arch/sparc64/kernel/systbls.S
*** linux-2.4.19/arch/sparc64/kernel/systbls.S	Tue Aug  6 15:01:45 2002
--- linux-2.4.19ctx-14/arch/sparc64/kernel/systbls.S	Mon Oct 14 00:00:26 2002
***************
*** 72,75 ****
--- 72,77 ----
  /*250*/	.word sys32_mremap, sys32_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl
  	.word sys_aplib
+ 	.word sys_new_s_context
+ 	.word sys_set_ipv4root
  
  	/* Now the 64-bit native Linux syscall table. */
***************
*** 131,134 ****
--- 133,138 ----
  /*250*/	.word sys64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
  	.word sys_aplib
+ 	.word sys_new_s_context
+ 	.word sys_set_ipv4root
  
  #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
***************
*** 226,229 ****
--- 230,234 ----
  /*250*/	.word sunos_nosys, sunos_nosys, sunos_nosys
  	.word sunos_nosys, sunos_nosys, sys_aplib
+ 	.word sunos_nosys, sunos_nosys
  
  #endif
diff -rc2P linux-2.4.19/fs/devpts/inode.c linux-2.4.19ctx-14/fs/devpts/inode.c
*** linux-2.4.19/fs/devpts/inode.c	Wed Oct 10 11:58:19 2001
--- linux-2.4.19ctx-14/fs/devpts/inode.c	Sun Oct 13 23:58:55 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.19/fs/devpts/root.c linux-2.4.19ctx-14/fs/devpts/root.c
*** linux-2.4.19/fs/devpts/root.c	Sat Dec 22 22:38:37 2001
--- linux-2.4.19ctx-14/fs/devpts/root.c	Sun Oct 13 23:58:55 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.19/fs/exec.c linux-2.4.19ctx-14/fs/exec.c
*** linux-2.4.19/fs/exec.c	Tue Aug  6 15:02:23 2002
--- linux-2.4.19ctx-14/fs/exec.c	Sun Oct 13 23:58:55 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.19/fs/ext2/ialloc.c linux-2.4.19ctx-14/fs/ext2/ialloc.c
*** linux-2.4.19/fs/ext2/ialloc.c	Tue Feb 26 22:22:03 2002
--- linux-2.4.19ctx-14/fs/ext2/ialloc.c	Sun Oct 13 23:58:55 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.19/fs/ext2/inode.c linux-2.4.19ctx-14/fs/ext2/inode.c
*** linux-2.4.19/fs/ext2/inode.c	Tue Aug  6 15:02:23 2002
--- linux-2.4.19ctx-14/fs/ext2/inode.c	Sun Oct 13 23:58:55 2002
***************
*** 47,50 ****
--- 47,52 ----
  }
  
+ static void ext2_truncate_nocheck (struct inode * inode);
+ 
  /*
   * Called at the last iput() if i_nlink is zero.
***************
*** 63,67 ****
  	inode->i_size = 0;
  	if (inode->i_blocks)
! 		ext2_truncate (inode);
  	ext2_free_inode (inode);
  
--- 65,69 ----
  	inode->i_size = 0;
  	if (inode->i_blocks)
! 		ext2_truncate_nocheck (inode);
  	ext2_free_inode (inode);
  
***************
*** 778,782 ****
  }
  
! void ext2_truncate (struct inode * inode)
  {
  	u32 *i_data = inode->u.ext2_i.i_data;
--- 780,784 ----
  }
  
! static void ext2_truncate_nocheck (struct inode * inode)
  {
  	u32 *i_data = inode->u.ext2_i.i_data;
***************
*** 793,798 ****
  	    S_ISLNK(inode->i_mode)))
  		return;
- 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- 		return;
  
  	ext2_discard_prealloc(inode);
--- 795,798 ----
***************
*** 868,871 ****
--- 868,877 ----
  	}
  }
+ void ext2_truncate (struct inode * inode)
+ {
+ 	if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode))
+ 		return;
+ 	ext2_truncate_nocheck (inode);
+ }
  
  void ext2_read_inode (struct inode * inode)
***************
*** 997,1003 ****
  		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) {
--- 1003,1013 ----
  		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.19/fs/ext2/ioctl.c linux-2.4.19ctx-14/fs/ext2/ioctl.c
*** linux-2.4.19/fs/ext2/ioctl.c	Wed Sep 27 16:41:33 2000
--- linux-2.4.19ctx-14/fs/ext2/ioctl.c	Sun Oct 13 23:58:55 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.19/fs/ext3/ialloc.c linux-2.4.19ctx-14/fs/ext3/ialloc.c
*** linux-2.4.19/fs/ext3/ialloc.c	Tue Feb 26 22:22:04 2002
--- linux-2.4.19ctx-14/fs/ext3/ialloc.c	Sun Oct 13 23:58:55 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.19/fs/ext3/inode.c linux-2.4.19ctx-14/fs/ext3/inode.c
*** linux-2.4.19/fs/ext3/inode.c	Tue Aug  6 15:02:23 2002
--- linux-2.4.19ctx-14/fs/ext3/inode.c	Sun Oct 13 23:58:55 2002
***************
*** 158,161 ****
--- 158,162 ----
  }
  
+ static void ext3_truncate_nocheck (struct inode *inode);
  /*
   * Called at the last iput() if i_nlink is zero.
***************
*** 187,191 ****
  	inode->i_size = 0;
  	if (inode->i_blocks)
! 		ext3_truncate(inode);
  	/*
  	 * Kill off the orphan record which ext3_truncate created.
--- 188,192 ----
  	inode->i_size = 0;
  	if (inode->i_blocks)
! 		ext3_truncate_nocheck(inode);
  	/*
  	 * Kill off the orphan record which ext3_truncate created.
***************
*** 1828,1832 ****
   */
  
! void ext3_truncate(struct inode * inode)
  {
  	handle_t *handle;
--- 1829,1833 ----
   */
  
! static void ext3_truncate_nocheck(struct inode * inode)
  {
  	handle_t *handle;
***************
*** 1844,1849 ****
  	    S_ISLNK(inode->i_mode)))
  		return;
- 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- 		return;
  
  	ext3_discard_prealloc(inode);
--- 1845,1848 ----
***************
*** 1975,1978 ****
--- 1974,1984 ----
  }
  
+ void ext3_truncate(struct inode * inode)
+ {
+ 	if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode))
+ 		return;
+ 	ext3_truncate_nocheck (inode);
+ }
+ 
  /* 
   * ext3_get_inode_loc returns with an extra refcount against the
***************
*** 2148,2154 ****
  		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) {
--- 2154,2163 ----
  		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.19/fs/ext3/ioctl.c linux-2.4.19ctx-14/fs/ext3/ioctl.c
*** linux-2.4.19/fs/ext3/ioctl.c	Fri Nov 23 15:07:49 2001
--- linux-2.4.19ctx-14/fs/ext3/ioctl.c	Sun Oct 13 23:58:55 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.19/fs/fat/file.c linux-2.4.19ctx-14/fs/fat/file.c
*** linux-2.4.19/fs/fat/file.c	Sun Aug 12 13:56:56 2001
--- linux-2.4.19ctx-14/fs/fat/file.c	Sun Oct 13 23:58:55 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.19/fs/fat/inode.c linux-2.4.19ctx-14/fs/fat/inode.c
*** linux-2.4.19/fs/fat/inode.c	Tue Aug  6 15:02:23 2002
--- linux-2.4.19ctx-14/fs/fat/inode.c	Sun Oct 13 23:58:55 2002
***************
*** 950,954 ****
  	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 ... */
--- 950,954 ----
  	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.19/fs/hpfs/file.c linux-2.4.19ctx-14/fs/hpfs/file.c
*** linux-2.4.19/fs/hpfs/file.c	Sun Aug 12 20:37:53 2001
--- linux-2.4.19ctx-14/fs/hpfs/file.c	Sun Oct 13 23:58:55 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.19/fs/intermezzo/vfs.c linux-2.4.19ctx-14/fs/intermezzo/vfs.c
*** linux-2.4.19/fs/intermezzo/vfs.c	Tue Aug  6 15:02:23 2002
--- linux-2.4.19ctx-14/fs/intermezzo/vfs.c	Sun Oct 13 23:58:55 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.19/fs/namei.c linux-2.4.19ctx-14/fs/namei.c
*** linux-2.4.19/fs/namei.c	Tue Aug  6 15:02:24 2002
--- linux-2.4.19ctx-14/fs/namei.c	Sun Oct 13 23:58:55 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;
  	}
***************
*** 894,899 ****
  	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) {
--- 903,907 ----
  	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) {
***************
*** 1615,1619 ****
  	 */
  	error = -EPERM;
! 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
  		goto exit_lock;
  	if (!dir->i_op || !dir->i_op->link)
--- 1623,1627 ----
  	 */
  	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.19/fs/nfsd/vfs.c linux-2.4.19ctx-14/fs/nfsd/vfs.c
*** linux-2.4.19/fs/nfsd/vfs.c	Tue Aug  6 15:02:24 2002
--- linux-2.4.19ctx-14/fs/nfsd/vfs.c	Sun Oct 13 23:58:55 2002
***************
*** 1481,1485 ****
  		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"  : "",
--- 1481,1485 ----
  		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"  : "",
***************
*** 1491,1495 ****
  		(acc & MAY_OWNER_OVERRIDE)? " owneroverride" : "",
  		inode->i_mode,
! 		IS_IMMUTABLE(inode)?	" immut" : "",
  		IS_APPEND(inode)?	" append" : "",
  		IS_RDONLY(inode)?	" ro" : "");
--- 1491,1496 ----
  		(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" : "");
***************
*** 1506,1510 ****
  			if (EX_RDONLY(exp) || IS_RDONLY(inode))
  				return nfserr_rofs;
! 			if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
  				return nfserr_perm;
  		}
--- 1507,1511 ----
  			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.19/fs/open.c linux-2.4.19ctx-14/fs/open.c
*** linux-2.4.19/fs/open.c	Tue Aug  6 15:02:24 2002
--- linux-2.4.19ctx-14/fs/open.c	Sun Oct 13 23:58:55 2002
***************
*** 147,151 ****
  
  	error = -EPERM;
! 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  		goto dput_and_out;
  
--- 147,151 ----
  
  	error = -EPERM;
! 	if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode))
  		goto dput_and_out;
  
***************
*** 496,500 ****
  		goto out_putf;
  	err = -EPERM;
! 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  		goto out_putf;
  	if (mode == (mode_t) -1)
--- 496,500 ----
  		goto out_putf;
  	err = -EPERM;
! 	if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode))
  		goto out_putf;
  	if (mode == (mode_t) -1)
***************
*** 527,531 ****
  
  	error = -EPERM;
! 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  		goto dput_and_out;
  
--- 527,531 ----
  
  	error = -EPERM;
! 	if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode))
  		goto dput_and_out;
  
***************
*** 557,561 ****
  		goto out;
  	error = -EPERM;
! 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  		goto out;
  	if (user == (uid_t) -1)
--- 557,561 ----
  		goto out;
  	error = -EPERM;
! 	if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode))
  		goto out;
  	if (user == (uid_t) -1)
diff -rc2P linux-2.4.19/fs/proc/array.c linux-2.4.19ctx-14/fs/proc/array.c
*** linux-2.4.19/fs/proc/array.c	Tue Aug  6 15:02:24 2002
--- linux-2.4.19ctx-14/fs/proc/array.c	Sun Oct 13 23:58:55 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);
***************
*** 267,274 ****
      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));
  }
  
--- 272,281 ----
      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));
  }
  
***************
*** 292,295 ****
--- 299,343 ----
  	buffer = task_sig(task, buffer);
  	buffer = task_cap(task, buffer);
+ #ifdef __NR_new_s_context
+ 	if (task->s_info != NULL){
+ 		int i;
+ 		buffer += sprintf (buffer,"s_context: %d [",task->s_context);
+ 		for (i=0; i<NB_S_CONTEXT; i++){
+ 			short int ctx = task->s_info->s_context[i];
+ 			if (ctx == 0) break;
+ 			buffer += sprintf (buffer," %d",ctx);
+ 		}
+ 		*buffer++ = ']';
+ 		*buffer++ = '\n';
+ 		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,"s_context: %d\n",task->s_context);
+ 		buffer += sprintf (buffer,"ctxticks: none\n");
+ 		buffer += sprintf (buffer,"ctxflags: none\n");
+ 		buffer += sprintf (buffer,"initpid: none\n");
+ 	}
+ 	if (task->ip_info != NULL){
+ 		int i;
+ 		buffer += sprintf (buffer,"ipv4root:");
+ 		for (i=0; i<task->ip_info->nbipv4; i++){
+ 			buffer += sprintf (buffer," %08x"
+ 				,task->ip_info->ipv4[i]);
+ 		}
+ 		*buffer++ = '\n';
+ 		buffer += sprintf (buffer,"ipv4root_bcast: %08x\n"
+ 			,task->ip_info->v4_bcast);
+ 	}else{
+ 		buffer += sprintf (buffer,"ipv4root: 0\n");
+ 		buffer += sprintf (buffer,"ipv4root_bcast: 0\n");
+ 	}
+ 	buffer += sprintf (buffer,"__NR_new_s_context: %d\n",__NR_new_s_context);
+ 	buffer += sprintf (buffer,"__NR_set_ipv4root: %d rev2\n",__NR_set_ipv4root);
+ #endif
  #if defined(CONFIG_ARCH_S390)
  	buffer = task_show_regs(task, buffer);
***************
*** 345,348 ****
--- 393,398 ----
  	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.19/fs/proc/base.c linux-2.4.19ctx-14/fs/proc/base.c
*** linux-2.4.19/fs/proc/base.c	Tue Aug  6 15:02:24 2002
--- linux-2.4.19ctx-14/fs/proc/base.c	Sun Oct 13 23:58:55 2002
***************
*** 1020,1023 ****
--- 1020,1029 ----
  		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);
  
***************
*** 1030,1034 ****
  	inode->i_fop = &proc_base_operations;
  	inode->i_nlink = 3;
! 	inode->i_flags|=S_IMMUTABLE;
  
  	dentry->d_op = &pid_base_dentry_operations;
--- 1036,1040 ----
  	inode->i_fop = &proc_base_operations;
  	inode->i_nlink = 3;
! 	inode->i_flags|=S_IMMUTABLE_FILE;
  
  	dentry->d_op = &pid_base_dentry_operations;
***************
*** 1066,1069 ****
--- 1072,1088 ----
  		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.19/fs/reiserfs/inode.c linux-2.4.19ctx-14/fs/reiserfs/inode.c
*** linux-2.4.19/fs/reiserfs/inode.c	Tue Aug  6 15:02:24 2002
--- linux-2.4.19ctx-14/fs/reiserfs/inode.c	Sun Oct 13 23:58:55 2002
***************
*** 1588,1592 ****
      /* symlink cannot be immutable or append only, right? */
      if( S_ISLNK( inode -> i_mode ) )
! 	    inode -> i_flags &= ~ ( S_IMMUTABLE | S_APPEND );
  
      inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
--- 1588,1592 ----
      /* symlink cannot be immutable or append only, right? */
      if( S_ISLNK( inode -> i_mode ) )
! 	    inode -> i_flags &= ~ ( S_IMMUTABLE_FILE | S_APPEND );
  
      inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
***************
*** 2125,2132 ****
  		else
  			inode -> i_flags &= ~S_SYNC;
! 		if( sd_attrs & REISERFS_IMMUTABLE_FL )
! 			inode -> i_flags |= S_IMMUTABLE;
  		else
! 			inode -> i_flags &= ~S_IMMUTABLE;
  		if( sd_attrs & REISERFS_NOATIME_FL )
  			inode -> i_flags |= S_NOATIME;
--- 2125,2136 ----
  		else
  			inode -> i_flags &= ~S_SYNC;
! 		if( sd_attrs & REISERFS_IMMUTABLE_FILE_FL )
! 			inode -> i_flags |= S_IMMUTABLE_FILE;
  		else
! 			inode -> i_flags &= ~S_IMMUTABLE_FILE;
! 		if( sd_attrs & REISERFS_IMMUTABLE_LINK_FL )
! 			inode -> i_flags |= S_IMMUTABLE_LINK;
! 		else
! 			inode -> i_flags &= ~S_IMMUTABLE_LINK;
  		if( sd_attrs & REISERFS_NOATIME_FL )
  			inode -> i_flags |= S_NOATIME;
***************
*** 2143,2150 ****
  {
  	if( reiserfs_attrs( inode -> i_sb ) ) {
! 		if( inode -> i_flags & S_IMMUTABLE )
! 			*sd_attrs |= REISERFS_IMMUTABLE_FL;
  		else
! 			*sd_attrs &= ~REISERFS_IMMUTABLE_FL;
  		if( inode -> i_flags & S_SYNC )
  			*sd_attrs |= REISERFS_SYNC_FL;
--- 2147,2158 ----
  {
  	if( reiserfs_attrs( inode -> i_sb ) ) {
! 		if( inode -> i_flags & S_IMMUTABLE_FILE )
! 			*sd_attrs |= REISERFS_IMMUTABLE_FILE_FL;
! 		else
! 			*sd_attrs &= ~REISERFS_IMMUTABLE_FILE_FL;
! 		if( inode -> i_flags & S_IMMUTABLE_LINK )
! 			*sd_attrs |= REISERFS_IMMUTABLE_LINK_FL;
  		else
! 			*sd_attrs &= ~REISERFS_IMMUTABLE_LINK_FL;
  		if( inode -> i_flags & S_SYNC )
  			*sd_attrs |= REISERFS_SYNC_FL;
diff -rc2P linux-2.4.19/fs/reiserfs/ioctl.c linux-2.4.19ctx-14/fs/reiserfs/ioctl.c
*** linux-2.4.19/fs/reiserfs/ioctl.c	Tue Aug  6 15:02:24 2002
--- linux-2.4.19ctx-14/fs/reiserfs/ioctl.c	Sun Oct 13 23:58:55 2002
***************
*** 48,52 ****
  			return -EFAULT;
  
! 		if ( ( flags & REISERFS_IMMUTABLE_FL ) && 
  		     !capable( CAP_LINUX_IMMUTABLE ) )
  			return -EPERM;
--- 48,52 ----
  			return -EFAULT;
  
! 		if ( ( flags & (REISERFS_IMMUTABLE_FILE_FL | REISERFS_IMMUTABLE_LINK_FL) ) && 
  		     !capable( CAP_LINUX_IMMUTABLE ) )
  			return -EPERM;
diff -rc2P linux-2.4.19/fs/udf/inode.c linux-2.4.19ctx-14/fs/udf/inode.c
*** linux-2.4.19/fs/udf/inode.c	Tue Aug  6 15:02:25 2002
--- linux-2.4.19ctx-14/fs/udf/inode.c	Sun Oct 13 23:58:55 2002
***************
*** 861,865 ****
  			S_ISLNK(inode->i_mode)))
  		return;
! 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
  		return;
  
--- 861,865 ----
  			S_ISLNK(inode->i_mode)))
  		return;
! 	if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode))
  		return;
  
diff -rc2P linux-2.4.19/fs/ufs/truncate.c linux-2.4.19ctx-14/fs/ufs/truncate.c
*** linux-2.4.19/fs/ufs/truncate.c	Tue Feb 26 22:22:08 2002
--- linux-2.4.19ctx-14/fs/ufs/truncate.c	Sun Oct 13 23:58:55 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.19/include/asm-i386/unistd.h linux-2.4.19ctx-14/include/asm-i386/unistd.h
*** linux-2.4.19/include/asm-i386/unistd.h	Tue Aug  6 15:02:28 2002
--- linux-2.4.19ctx-14/include/asm-i386/unistd.h	Sun Oct 13 23:58:55 2002
***************
*** 248,251 ****
--- 248,253 ----
  #define __NR_sched_setaffinity	241
  #define __NR_sched_getaffinity	242
+ #define __NR_new_s_context      243
+ #define __NR_set_ipv4root       244
  
  /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
diff -rc2P linux-2.4.19/include/asm-ppc/unistd.h linux-2.4.19ctx-14/include/asm-ppc/unistd.h
*** linux-2.4.19/include/asm-ppc/unistd.h	Tue Aug  6 15:02:38 2002
--- linux-2.4.19ctx-14/include/asm-ppc/unistd.h	Sun Oct 13 23:58:55 2002
***************
*** 217,220 ****
--- 217,222 ----
  #define __NR_gettid		207
  #define __NR_tkill		208
+ #define __NR_new_s_context	209
+ #define __NR_set_ipv4root	210
  
  #define __NR(n)	#n
diff -rc2P linux-2.4.19/include/asm-sparc/unistd.h linux-2.4.19ctx-14/include/asm-sparc/unistd.h
*** linux-2.4.19/include/asm-sparc/unistd.h	Tue Aug  6 15:02:39 2002
--- linux-2.4.19ctx-14/include/asm-sparc/unistd.h	Sun Oct 13 23:58:55 2002
***************
*** 272,275 ****
--- 272,277 ----
  #define __NR_nfsservctl         254
  #define __NR_aplib              255
+ #define __NR_new_s_context	256
+ #define __NR_set_ipv4root	257
  
  #define _syscall0(type,name) \
diff -rc2P linux-2.4.19/include/asm-sparc64/unistd.h linux-2.4.19ctx-14/include/asm-sparc64/unistd.h
*** linux-2.4.19/include/asm-sparc64/unistd.h	Tue Aug  6 15:02:40 2002
--- linux-2.4.19ctx-14/include/asm-sparc64/unistd.h	Sun Oct 13 23:58:55 2002
***************
*** 274,277 ****
--- 274,279 ----
  #define __NR_nfsservctl         254
  #define __NR_aplib              255
+ #define __NR_new_s_context	256
+ #define __NR_set_ipv4root	257
  
  #define _syscall0(type,name) \
diff -rc2P linux-2.4.19/include/linux/capability.h linux-2.4.19ctx-14/include/linux/capability.h
*** linux-2.4.19/include/linux/capability.h	Fri Nov 23 15:07:52 2001
--- linux-2.4.19ctx-14/include/linux/capability.h	Mon Oct 14 00:06:57 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.19/include/linux/devpts_fs_info.h linux-2.4.19ctx-14/include/linux/devpts_fs_info.h
*** linux-2.4.19/include/linux/devpts_fs_info.h	Wed Dec 31 19:00:00 1969
--- linux-2.4.19ctx-14/include/linux/devpts_fs_info.h	Sun Oct 13 23:58:55 2002
***************
*** 0 ****
--- 1,4 ----
+ struct devpts_inode_info{
+ 	int s_context;
+ };
+ 
diff -rc2P linux-2.4.19/include/linux/ext2_fs.h linux-2.4.19ctx-14/include/linux/ext2_fs.h
*** linux-2.4.19/include/linux/ext2_fs.h	Wed Oct 31 15:32:45 2001
--- linux-2.4.19ctx-14/include/linux/ext2_fs.h	Mon Oct 14 00:13:38 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.19/include/linux/ext3_fs.h linux-2.4.19ctx-14/include/linux/ext3_fs.h
*** linux-2.4.19/include/linux/ext3_fs.h	Tue Feb 26 22:22:11 2002
--- linux-2.4.19ctx-14/include/linux/ext3_fs.h	Mon Oct 14 00:13:59 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.19/include/linux/fs.h linux-2.4.19ctx-14/include/linux/fs.h
*** linux-2.4.19/include/linux/fs.h	Tue Aug  6 15:02:42 2002
--- linux-2.4.19ctx-14/include/linux/fs.h	Mon Oct 14 00:06:57 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)
***************
*** 320,323 ****
--- 322,326 ----
  #include <linux/jffs2_fs_i.h>
  #include <linux/cramfs_fs_sb.h>
+ #include <linux/devpts_fs_info.h>
  
  /*
***************
*** 361,369 ****
   * 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 */
  
  /*
--- 364,373 ----
   * 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 */
  
  /*
***************
*** 510,513 ****
--- 514,518 ----
  		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.19/include/linux/reiserfs_fs.h linux-2.4.19ctx-14/include/linux/reiserfs_fs.h
*** linux-2.4.19/include/linux/reiserfs_fs.h	Tue Aug  6 15:02:43 2002
--- linux-2.4.19ctx-14/include/linux/reiserfs_fs.h	Mon Oct 14 00:16:27 2002
***************
*** 724,728 ****
  /* we want common flags to have the same values as in ext2,
     so chattr(1) will work without problems */
! #define REISERFS_IMMUTABLE_FL EXT2_IMMUTABLE_FL
  #define REISERFS_SYNC_FL      EXT2_SYNC_FL
  #define REISERFS_NOATIME_FL   EXT2_NOATIME_FL
--- 724,729 ----
  /* we want common flags to have the same values as in ext2,
     so chattr(1) will work without problems */
! #define REISERFS_IMMUTABLE_FILE_FL EXT2_IMMUTABLE_FILE_FL
! #define REISERFS_IMMUTABLE_LINK_FL EXT2_IMMUTABLE_LINK_FL
  #define REISERFS_SYNC_FL      EXT2_SYNC_FL
  #define REISERFS_NOATIME_FL   EXT2_NOATIME_FL
***************
*** 740,744 ****
  
  /* persistent flags that file inherits from the parent directory */
! #define REISERFS_INHERIT_MASK ( REISERFS_IMMUTABLE_FL |	\
  				REISERFS_SYNC_FL |	\
  				REISERFS_NOATIME_FL |	\
--- 741,746 ----
  
  /* persistent flags that file inherits from the parent directory */
! #define REISERFS_INHERIT_MASK ( REISERFS_IMMUTABLE_FILE_FL |	\
! 				REISERFS_IMMUTABLE_LINK_FL |	\
  				REISERFS_SYNC_FL |	\
  				REISERFS_NOATIME_FL |	\
diff -rc2P linux-2.4.19/include/linux/sched.h linux-2.4.19ctx-14/include/linux/sched.h
*** linux-2.4.19/include/linux/sched.h	Tue Aug  6 15:02:43 2002
--- linux-2.4.19ctx-14/include/linux/sched.h	Mon Oct 14 00:06:57 2002
***************
*** 275,278 ****
--- 275,279 ----
  	struct user_struct *next, **pprev;
  	uid_t uid;
+ 	int s_context;
  };
  
***************
*** 282,285 ****
--- 283,334 ----
  	__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 */
+ #define S_CTX_INFO_HIDEINFO	32	/* Hide some information in /proc */
+ 
+ #define NB_IPV4ROOT	16
+ #define NB_S_CONTEXT	16
+ 
+ struct context_info{
+ 	int refcount;
+ 	short int s_context[NB_S_CONTEXT];/* root is allowed to switch the current */
+ 				/* security context using any in this table */
+ 	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 */
+ 	void *data1;
+ 	void *data2;
+ 	void *data3;
+ 	void *data4;
+ };
+ 
+ struct iproot_info{
+ 	int refcount;
+ 	int nbipv4;
+ 	__u32 ipv4[NB_IPV4ROOT];/* Process can only bind to these IPs */
+ 				/* The first one is used to connect */
+ 				/* and for bind any service */
+ 				/* The other must be used explicity when */
+ 				/* binding */
+ 	__u32 v4_bcast;	/* Broadcast address used to receive UDP packets */
+ };
+ 
+ 
  extern struct user_struct root_user;
  #define INIT_USER (&root_user)
***************
*** 408,411 ****
--- 457,466 ----
  	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 */
+ 	struct context_info *s_info;
+ 	struct iproot_info *ip_info;
  	void *notifier_data;
  	sigset_t *notifier_mask;
***************
*** 512,515 ****
--- 567,571 ----
      alloc_lock:		SPIN_LOCK_UNLOCKED,				\
      journal_info:	NULL,						\
+     cap_bset:		CAP_INIT_EFF_SET,				\
  }
  
***************
*** 576,580 ****
  
  /* per-UID process charging. */
! extern struct user_struct * alloc_uid(uid_t);
  extern void free_uid(struct user_struct *);
  
--- 632,636 ----
  
  /* per-UID process charging. */
! extern struct user_struct * alloc_uid(int, uid_t);
  extern void free_uid(struct user_struct *);
  
***************
*** 944,947 ****
--- 1000,1011 ----
  	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);
+ void sys_release_ip_info (struct task_struct *);
+ void sys_assign_ip_info (struct task_struct *);
+ void sys_alloc_ip_info (void);
  
  #endif /* __KERNEL__ */
diff -rc2P linux-2.4.19/include/net/route.h linux-2.4.19ctx-14/include/net/route.h
*** linux-2.4.19/include/net/route.h	Tue Aug  6 15:02:44 2002
--- linux-2.4.19ctx-14/include/net/route.h	Mon Oct 14 00:10:46 2002
***************
*** 165,168 ****
--- 165,182 ----
  {
  	int err;
+ 	if (current->ip_info != NULL){
+ 		__u32 ipv4root = current->ip_info->ipv4[0];
+ 		if (ipv4root != 0){
+ 			if (src == 0){
+ 				src = dst == 0x0100007f
+ 					? 0x0100007f: ipv4root;
+ 			}else if (ipv4root != src){
+ 				return -EPERM;
+ 			}
+ 			if (dst == 0x0100007f && current->s_context != 0){
+ 				dst = ipv4root;
+ 			}
+ 		}
+ 	}
  	err = ip_route_output(rp, dst, src, tos, oif);
  	if (err || (dst && src))
diff -rc2P linux-2.4.19/include/net/sock.h linux-2.4.19ctx-14/include/net/sock.h
*** linux-2.4.19/include/net/sock.h	Tue Aug  6 15:02:44 2002
--- linux-2.4.19ctx-14/include/net/sock.h	Mon Oct 14 00:10:46 2002
***************
*** 526,529 ****
--- 526,530 ----
  	unsigned int		allocation;	/* Allocation mode			*/
  	int			sndbuf;		/* Size of send buffer in bytes		*/
+ 	__u32			bcast_addr;	/* Local bcast addr, for ipv4root */
  	struct sock		*prev;
  
***************
*** 669,673 ****
  	/* RPC layer private data */
  	void			*user_data;
!   
  	/* Callbacks */
  	void			(*state_change)(struct sock *sk);
--- 670,677 ----
  	/* 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.19/include/net/tcp.h linux-2.4.19ctx-14/include/net/tcp.h
*** linux-2.4.19/include/net/tcp.h	Tue Aug  6 15:02:44 2002
--- linux-2.4.19ctx-14/include/net/tcp.h	Mon Oct 14 00:18:52 2002
***************
*** 191,194 ****
--- 191,195 ----
  	struct in6_addr		v6_rcv_saddr;
  #endif
+ 	int			s_context;
  };
  
diff -rc2P linux-2.4.19/ipc/util.c linux-2.4.19ctx-14/ipc/util.c
*** linux-2.4.19/ipc/util.c	Sun Aug 12 20:37:53 2001
--- linux-2.4.19ctx-14/ipc/util.c	Sun Oct 13 23:58:55 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.19/ipc/util.h linux-2.4.19ctx-14/ipc/util.h
*** linux-2.4.19/ipc/util.h	Mon Feb 19 13:18:18 2001
--- linux-2.4.19ctx-14/ipc/util.h	Sun Oct 13 23:58:55 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.19/kernel/exit.c linux-2.4.19ctx-14/kernel/exit.c
*** linux-2.4.19/kernel/exit.c	Tue Aug  6 15:02:44 2002
--- linux-2.4.19ctx-14/kernel/exit.c	Sun Oct 13 23:58:55 2002
***************
*** 67,70 ****
--- 67,72 ----
  		if (current->counter >= MAX_COUNTER)
  			current->counter = MAX_COUNTER;
+ 		sys_release_s_info(p);
+ 		sys_release_ip_info(p);
  		p->pid = 0;
  		free_task_struct(p);
***************
*** 160,165 ****
--- 162,176 ----
  {
  	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, if they're not already exiting */
***************
*** 172,176 ****
  
  	if (reaper == father)
! 		reaper = child_reaper;
  
  	for_each_task(p) {
--- 183,187 ----
  
  	if (reaper == father)
! 		reaper = vchild_reaper;
  
  	for_each_task(p) {
***************
*** 182,186 ****
  			/* Make sure we're not reparenting to ourselves */
  			if (p == reaper)
! 				p->p_opptr = child_reaper;
  			else
  				p->p_opptr = reaper;
--- 193,197 ----
  			/* 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.19/kernel/fork.c linux-2.4.19ctx-14/kernel/fork.c
*** linux-2.4.19/kernel/fork.c	Tue Aug  6 15:02:44 2002
--- linux-2.4.19ctx-14/kernel/fork.c	Sun Oct 13 23:58:55 2002
***************
*** 604,607 ****
--- 604,611 ----
  
  	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
***************
*** 613,616 ****
--- 617,623 ----
  	              && !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE))
  		goto bad_fork_free;
+ 
+ 	sys_assign_s_info (p);
+ 	sys_assign_ip_info (p);
  
  	atomic_inc(&p->user->__count);
diff -rc2P linux-2.4.19/kernel/printk.c linux-2.4.19ctx-14/kernel/printk.c
*** linux-2.4.19/kernel/printk.c	Tue Aug  6 15:02:44 2002
--- linux-2.4.19ctx-14/kernel/printk.c	Sun Oct 13 23:58:55 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.19/kernel/sched.c linux-2.4.19ctx-14/kernel/sched.c
*** linux-2.4.19/kernel/sched.c	Tue Aug  6 15:02:44 2002
--- linux-2.4.19ctx-14/kernel/sched.c	Sun Oct 13 23:58:55 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.19/kernel/signal.c linux-2.4.19ctx-14/kernel/signal.c
*** linux-2.4.19/kernel/signal.c	Tue Aug  6 15:02:44 2002
--- linux-2.4.19ctx-14/kernel/signal.c	Sun Oct 13 23:58:55 2002
***************
*** 622,626 ****
  		read_lock(&tasklist_lock);
  		for_each_task(p) {
! 			if (p->pgrp == pgrp && thread_group_leader(p)) {
  				int err = send_sig_info(sig, info, p);
  				if (retval)
--- 622,628 ----
  		read_lock(&tasklist_lock);
  		for_each_task(p) {
! 			if (p->pgrp == pgrp && thread_group_leader(p)
! 				&& ((long)info==1
! 					|| p->s_context == current->s_context)) {
  				int err = send_sig_info(sig, info, p);
  				if (retval)
***************
*** 676,680 ****
                                 p = tg;
                  }
! 		error = send_sig_info(sig, info, p);
  	}
  	read_unlock(&tasklist_lock);
--- 678,697 ----
                                 p = tg;
                  }
! 		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);
***************
*** 700,704 ****
  		read_lock(&tasklist_lock);
  		for_each_task(p) {
! 			if (p->pid > 1 && p != current && thread_group_leader(p)) {
  				int err = send_sig_info(sig, info, p);
  				++count;
--- 717,722 ----
  		read_lock(&tasklist_lock);
  		for_each_task(p) {
! 			if (p->pid > 1 && p != current && thread_group_leader(p)
! 				&& p->s_context == current->s_context) {
  				int err = send_sig_info(sig, info, p);
  				++count;
***************
*** 1324,1325 ****
--- 1342,1487 ----
  }
  #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.19/kernel/sys.c linux-2.4.19ctx-14/kernel/sys.c
*** linux-2.4.19/kernel/sys.c	Tue Aug  6 15:02:44 2002
--- linux-2.4.19ctx-14/kernel/sys.c	Sun Oct 13 23:58:55 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,1138 ----
  }
  
+ /*
+ 	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));
+ 	if (s_info != NULL){
+ 		memset (s_info,0,sizeof(*s_info));
+ 		// printk ("new s_info %d\n",current->pid);
+ 		s_info->s_context[0] = 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;
+ 	}
+ }
+ /*
+ 	Decrease the reference count on the ip_info member of a task
+ 	Free the struct if the reference count reach 0.
+ */
+ void sys_release_ip_info (struct task_struct *p)
+ {
+ 	down_write (&uts_sem);
+ 	if (p->ip_info != NULL){
+ 		p->ip_info->refcount--;
+ 		if (p->ip_info->refcount == 0){
+ 			// printk ("vfree s_info %d\n",p->pid);
+ 			vfree (p->ip_info);
+ 			p->ip_info = NULL;
+ 		}
+ 	}
+ 	up_write (&uts_sem);
+ }
+ /*
+ 	Increase the reference count on the ip_info member of a task
+ */
+ void sys_assign_ip_info (struct task_struct *p)
+ {
+ 	down_write (&uts_sem);
+ 	if (p->ip_info != NULL) p->ip_info->refcount++;
+ 	up_write (&uts_sem);
+ }
+ 
+ /*
+ 	Alloc a new ip_info to the current process and release
+ 	the one currently owned by the current process.
+ */
+ void sys_alloc_ip_info()
+ {
+ 	struct iproot_info *ip_info = vmalloc(sizeof(struct iproot_info));
+ 	// printk ("new s_info %d\n",current->pid);
+ 	memset (ip_info,0,sizeof(*ip_info));
+ 	ip_info->refcount = 1;
+ 	sys_release_ip_info (current);	
+ 	current->ip_info = ip_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;
  	}
--- 1142,1149 ----
  	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);
--- 1155,1170 ----
  {
  	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 ****
--- 1179,1183 ----
  {
  	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);
--- 1187,1196 ----
  
  	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.19/kernel/sysctl.c linux-2.4.19ctx-14/kernel/sysctl.c
*** linux-2.4.19/kernel/sysctl.c	Tue Aug  6 15:02:44 2002
--- linux-2.4.19ctx-14/kernel/sysctl.c	Sun Oct 13 23:58:55 2002
***************
*** 382,385 ****
--- 382,386 ----
  static int test_perm(int mode, int op)
  {
+ 	if (!capable(CAP_SYS_ADMIN)) mode &= ~(0222);
  	if (!current->euid)
  		mode >>= 6;
***************
*** 796,800 ****
--- 797,812 ----
  {
  	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.19/kernel/timer.c linux-2.4.19ctx-14/kernel/timer.c
*** linux-2.4.19/kernel/timer.c	Tue Aug  6 15:02:44 2002
--- linux-2.4.19ctx-14/kernel/timer.c	Sun Oct 13 23:58:55 2002
***************
*** 600,603 ****
--- 600,608 ----
  	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;
***************
*** 736,739 ****
--- 741,749 ----
  {
  	/* 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;
  }
***************
*** 781,784 ****
--- 791,800 ----
  #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.19/kernel/user.c linux-2.4.19ctx-14/kernel/user.c
*** linux-2.4.19/kernel/user.c	Wed Nov 29 01:43:39 2000
--- linux-2.4.19ctx-14/kernel/user.c	Sun Oct 13 23:58:55 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 bof@bof.de)
+  *
+  * NOTE: For now, the hash function is unmodified: the same uid in several
+  * security contexts, will always sit on the same hash chain. This could
+  * be changed easily.
   */
  
***************
*** 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.19/net/ipv4/af_inet.c linux-2.4.19ctx-14/net/ipv4/af_inet.c
*** linux-2.4.19/net/ipv4/af_inet.c	Tue Aug  6 15:02:45 2002
--- linux-2.4.19ctx-14/net/ipv4/af_inet.c	Sun Oct 13 23:58:55 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,486 ----
  	int chk_addr_ret;
  	int err;
+ 	__u32 s_addr;
+ 	__u32 bcast_addr = 0xffffffffl;
+ 	__u32 ipv4root;
  
  	/* 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
--- 491,518 ----
  		return -EINVAL;
  
! 	s_addr = addr->sin_addr.s_addr;
! 	ipv4root = current->ip_info != NULL ? current->ip_info->ipv4[0] : 0;
! 	if (ipv4root != 0){
! 		// printk ("ipv4root0 %08lx %08x\n",ipv4root,s_addr);
! 		__u32 v4_bcast =  current->ip_info->v4_bcast;
! 		if (s_addr == 0){
! 			s_addr = ipv4root;
! 			bcast_addr = v4_bcast;
! 		}else if (s_addr == 0x0100007f){
! 			s_addr = ipv4root;
! 		}else if (s_addr != v4_bcast
! 			&& s_addr != ipv4root){
! 			int i;
! 			int nbipv4 = current->ip_info->nbipv4;
! 			for (i=0; i<nbipv4; i++){
! 				if (s_addr == current->ip_info->ipv4[i]){
! 					break;
! 				}
! 			}
! 			if (i == nbipv4) return -EADDRNOTAVAIL;
! 		}
! 	}
! 	chk_addr_ret = inet_addr_type(s_addr);
! 	// printk ("ipv4root %08lx %08x %d\n",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 &&
--- 525,529 ----
  	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 */
--- 550,555 ----
  		goto out;
  
! 	sk->rcv_saddr = sk->saddr = s_addr;
! 	sk->bcast_addr = bcast_addr;
  	if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
  		sk->saddr = 0;  /* Use device */
diff -rc2P linux-2.4.19/net/ipv4/devinet.c linux-2.4.19ctx-14/net/ipv4/devinet.c
*** linux-2.4.19/net/ipv4/devinet.c	Tue Aug  6 15:02:45 2002
--- linux-2.4.19ctx-14/net/ipv4/devinet.c	Sun Oct 13 23:58:55 2002
***************
*** 456,459 ****
--- 456,485 ----
  }
  
+ /*
+ 	Check that a device is not member of the ipv4root assigned to the process
+ 	Return true if this is the case
+ 
+ 	If the process is not bound to specific IP, then it returns 0 (all
+ 	interface are fine).
+ */
+ static int devinet_notiproot (struct in_ifaddr *ifa)
+ {
+ 	int ret = 0;
+ 	struct iproot_info *info = current->ip_info;
+ 	if (current->s_context != 0 && info != NULL){
+ 		int i;
+ 		int nbip = info->nbipv4;
+ 		__u32 addr = ifa->ifa_local;
+ 		ret = 1;
+ 		for (i=0; i<nbip; i++){
+ 			if(info->ipv4[i] == addr){
+ 				ret = 0;
+ 				break;
+ 			}
+ 		}
+ 	}
+ 	return ret;
+ }
+ 
  
  int devinet_ioctl(unsigned int cmd, void *arg)
***************
*** 559,563 ****
  		goto done;
  	}
! 
  	switch(cmd) {
  		case SIOCGIFADDR:	/* Get interface address */
--- 585,593 ----
  		goto done;
  	}
! 	if (ifa != NULL
! 		&& devinet_notiproot (ifa)){
! 		ret = -EADDRNOTAVAIL;
! 		goto done;
! 	}
  	switch(cmd) {
  		case SIOCGIFADDR:	/* Get interface address */
***************
*** 692,695 ****
--- 722,727 ----
  
  	for ( ; ifa; ifa = ifa->ifa_next) {
+ 		// We do not show other IP devices to vservers
+ 		if (devinet_notiproot(ifa)) continue;
  		if (!buf) {
  			done += sizeof(ifr);
***************
*** 909,912 ****
--- 941,945 ----
  		for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
  		     ifa = ifa->ifa_next, ip_idx++) {
+ 			if (devinet_notiproot(ifa)) continue;
  			if (ip_idx < s_ip_idx)
  				continue;
diff -rc2P linux-2.4.19/net/ipv4/raw.c linux-2.4.19ctx-14/net/ipv4/raw.c
*** linux-2.4.19/net/ipv4/raw.c	Tue Aug  6 15:02:45 2002
--- linux-2.4.19ctx-14/net/ipv4/raw.c	Sun Oct 13 23:58:55 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.19/net/ipv4/tcp_ipv4.c linux-2.4.19ctx-14/net/ipv4/tcp_ipv4.c
*** linux-2.4.19/net/ipv4/tcp_ipv4.c	Tue Aug  6 15:02:46 2002
--- linux-2.4.19ctx-14/net/ipv4/tcp_ipv4.c	Sun Oct 13 23:58:55 2002
***************
*** 2184,2187 ****
--- 2184,2190 ----
  			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;
***************
*** 2237,2241 ****
  		read_lock(&head->lock);
  		for(sk = head->chain; sk; sk = sk->next, num++) {
! 			if (!TCP_INET_FAMILY(sk->family))
  				continue;
  			pos += TMPSZ;
--- 2240,2244 ----
  		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;
***************
*** 2252,2256 ****
  		     tw != NULL;
  		     tw = (struct tcp_tw_bucket *)tw->next, num++) {
! 			if (!TCP_INET_FAMILY(tw->family))
  				continue;
  			pos += TMPSZ;
--- 2255,2259 ----
  		     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.19/net/ipv4/tcp_minisocks.c linux-2.4.19ctx-14/net/ipv4/tcp_minisocks.c
*** linux-2.4.19/net/ipv4/tcp_minisocks.c	Tue Aug  6 15:02:47 2002
--- linux-2.4.19ctx-14/net/ipv4/tcp_minisocks.c	Sun Oct 13 23:58:55 2002
***************
*** 381,384 ****
--- 381,386 ----
  		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.19/net/ipv4/udp.c linux-2.4.19ctx-14/net/ipv4/udp.c
*** linux-2.4.19/net/ipv4/udp.c	Tue Aug  6 15:02:47 2002
--- linux-2.4.19ctx-14/net/ipv4/udp.c	Sun Oct 13 23:58:55 2002
***************
*** 273,277 ****
  		    (s->daddr && s->daddr!=rmt_addr)			||
  		    (s->dport != rmt_port && s->dport != 0)			||
! 		    (s->rcv_saddr  && s->rcv_saddr != loc_addr)		||
  		    (s->bound_dev_if && s->bound_dev_if != dif))
  			continue;
--- 273,277 ----
  		    (s->daddr && s->daddr!=rmt_addr)			||
  		    (s->dport != rmt_port && s->dport != 0)			||
! 		    (s->rcv_saddr  && s->rcv_saddr != loc_addr && s->bcast_addr != loc_addr)		||
  		    (s->bound_dev_if && s->bound_dev_if != dif))
  			continue;
***************
*** 1005,1009 ****
  
  		for (sk = udp_hash[i]; sk; sk = sk->next, num++) {
! 			if (sk->family != PF_INET)
  				continue;
  			pos += 128;
--- 1005,1009 ----
  
  		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.19/net/ipv6/raw.c linux-2.4.19ctx-14/net/ipv6/raw.c
*** linux-2.4.19/net/ipv6/raw.c	Tue Aug  6 15:02:47 2002
--- linux-2.4.19ctx-14/net/ipv6/raw.c	Sun Oct 13 23:58:55 2002
***************
*** 880,884 ****
  
  		for (sk = raw_v6_htable[i]; sk; sk = sk->next, num++) {
! 			if (sk->family != PF_INET6)
  				continue;
  			pos += LINE_LEN+1;
--- 880,884 ----
  
  		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.19/net/ipv6/tcp_ipv6.c linux-2.4.19ctx-14/net/ipv6/tcp_ipv6.c
*** linux-2.4.19/net/ipv6/tcp_ipv6.c	Tue Aug  6 15:02:47 2002
--- linux-2.4.19ctx-14/net/ipv6/tcp_ipv6.c	Sun Oct 13 23:58:55 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.19/net/ipv6/udp.c linux-2.4.19ctx-14/net/ipv6/udp.c
*** linux-2.4.19/net/ipv6/udp.c	Tue Aug  6 15:02:47 2002
--- linux-2.4.19ctx-14/net/ipv6/udp.c	Sun Oct 13 23:58:55 2002
***************
*** 958,962 ****
  
  		for (sk = udp_hash[i]; sk; sk = sk->next, num++) {
! 			if (sk->family != PF_INET6)
  				continue;
  			pos += LINE_LEN+1;
--- 958,962 ----
  
  		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.19/net/socket.c linux-2.4.19ctx-14/net/socket.c
*** linux-2.4.19/net/socket.c	Tue Aug  6 15:02:48 2002
--- linux-2.4.19ctx-14/net/socket.c	Sun Oct 13 23:58:55 2002
***************
*** 1754,1755 ****
--- 1754,1800 ----
  	return len;
  }
+ 
+ asmlinkage int sys_set_ipv4root (__u32 ip[], int nbip, __u32 bcast)
+ {
+ 	int ret = -EPERM;
+ 	__u32 tbip[NB_IPV4ROOT];
+ 	struct iproot_info *ip_info = current->ip_info;
+ 	if (nbip < 0 || nbip > NB_IPV4ROOT){
+ 		ret = -EINVAL;
+ 	}else if (copy_from_user(tbip,ip,nbip*sizeof(ip[0]))!=0){
+ 		ret = -EFAULT;
+ 	}else if (ip_info == NULL
+ 		|| ip_info->ipv4[0] == 0
+ 		|| capable(CAP_NET_ADMIN)){
+ 		// We are allowed to change everything
+ 		ret = 0;
+ 	}else if (current->ip_info != NULL){
+ 		// We are allowed to select a subset of the currently
+ 		// installed IP numbers. No new one allowed
+ 		// We can't change the broadcast address though
+ 		int i;
+ 		int found = 0;
+ 		for (i=0; i<nbip; i++){
+ 			int j;
+ 			__u32 ipi = tbip[i];
+ 			for (j=0; j<ip_info->nbipv4; j++){
+ 				if (ipi == ip_info->ipv4[j]){
+ 					found++;
+ 					break;
+ 				}
+ 			}
+ 		}
+ 		if (found == nbip && bcast == ip_info->v4_bcast){
+ 			ret = 0;
+ 		}
+ 
+ 	}
+ 	if (ret == 0){
+ 		sys_alloc_ip_info();
+ 		current->ip_info->nbipv4 = nbip;
+ 		memcpy (current->ip_info->ipv4,tbip,nbip*sizeof(tbip[0]));
+ 		current->ip_info->v4_bcast = bcast;
+ 	}
+ 	return ret;
+ }
+ 
diff -rc2P linux-2.4.19/net/unix/af_unix.c linux-2.4.19ctx-14/net/unix/af_unix.c
*** linux-2.4.19/net/unix/af_unix.c	Tue Aug  6 15:02:48 2002
--- linux-2.4.19ctx-14/net/unix/af_unix.c	Sun Oct 13 23:58:55 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);