diff -rc2P linux-2.4.13/Makefile linux-2.4.13-ctx-4/Makefile
*** linux-2.4.13/Makefile	Wed Oct 31 15:32:24 2001
--- linux-2.4.13-ctx-4/Makefile	Fri Nov 16 14:35:23 2001
***************
*** 2,6 ****
  PATCHLEVEL = 4
  SUBLEVEL = 13
! EXTRAVERSION =
  
  KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
--- 2,6 ----
  PATCHLEVEL = 4
  SUBLEVEL = 13
! EXTRAVERSION =ctx-4
  
  KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff -rc2P linux-2.4.13/arch/i386/kernel/entry.S linux-2.4.13-ctx-4/arch/i386/kernel/entry.S
*** linux-2.4.13/arch/i386/kernel/entry.S	Wed Oct 31 15:32:24 2001
--- linux-2.4.13-ctx-4/arch/i386/kernel/entry.S	Wed Oct 31 16:11:22 2001
***************
*** 623,626 ****
--- 623,628 ----
  	.long SYMBOL_NAME(sys_gettid)
  	.long SYMBOL_NAME(sys_readahead)	/* 225 */
+ 	.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.13/arch/i386/kernel/ptrace.c linux-2.4.13-ctx-4/arch/i386/kernel/ptrace.c
*** linux-2.4.13/arch/i386/kernel/ptrace.c	Tue Sep 18 20:04:23 2001
--- linux-2.4.13-ctx-4/arch/i386/kernel/ptrace.c	Wed Oct 31 16:05:00 2001
***************
*** 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.13/fs/exec.c linux-2.4.13-ctx-4/fs/exec.c
*** linux-2.4.13/fs/exec.c	Tue Sep 18 16:39:32 2001
--- linux-2.4.13-ctx-4/fs/exec.c	Wed Oct 31 16:05:00 2001
***************
*** 685,689 ****
  	int do_unlock = 0;
  
! 	new_permitted = cap_intersect(bprm->cap_permitted, cap_bset);
  	working = cap_intersect(bprm->cap_inheritable,
  				current->cap_inheritable);
--- 685,689 ----
  	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.13/fs/ext2/ialloc.c linux-2.4.13-ctx-4/fs/ext2/ialloc.c
*** linux-2.4.13/fs/ext2/ialloc.c	Wed Oct 10 11:58:19 2001
--- linux-2.4.13-ctx-4/fs/ext2/ialloc.c	Mon Nov  5 14:54:21 2001
***************
*** 439,443 ****
  	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_faddr = 0;
  	inode->u.ext2_i.i_frag_no = 0;
--- 439,443 ----
  	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_faddr = 0;
  	inode->u.ext2_i.i_frag_no = 0;
diff -rc2P linux-2.4.13/fs/ext2/inode.c linux-2.4.13-ctx-4/fs/ext2/inode.c
*** linux-2.4.13/fs/ext2/inode.c	Wed Oct 31 15:32:41 2001
--- linux-2.4.13-ctx-4/fs/ext2/inode.c	Mon Nov  5 14:54:21 2001
***************
*** 797,801 ****
  	    S_ISLNK(inode->i_mode)))
  		return;
! 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
  		return;
  
--- 797,801 ----
  	    S_ISLNK(inode->i_mode)))
  		return;
! 	if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode))
  		return;
  
***************
*** 1003,1009 ****
  		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.13/fs/ext2/ioctl.c linux-2.4.13-ctx-4/fs/ext2/ioctl.c
*** linux-2.4.13/fs/ext2/ioctl.c	Wed Sep 27 16:41:33 2000
--- linux-2.4.13-ctx-4/fs/ext2/ioctl.c	Mon Nov  5 14:54:21 2001
***************
*** 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.13/fs/fat/file.c linux-2.4.13-ctx-4/fs/fat/file.c
*** linux-2.4.13/fs/fat/file.c	Sun Aug 12 13:56:56 2001
--- linux-2.4.13-ctx-4/fs/fat/file.c	Mon Nov  5 14:54:21 2001
***************
*** 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.13/fs/fat/inode.c linux-2.4.13-ctx-4/fs/fat/inode.c
*** linux-2.4.13/fs/fat/inode.c	Wed Oct 31 15:32:41 2001
--- linux-2.4.13-ctx-4/fs/fat/inode.c	Mon Nov  5 14:54:21 2001
***************
*** 946,950 ****
  	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 ... */
--- 946,950 ----
  	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.13/fs/hpfs/file.c linux-2.4.13-ctx-4/fs/hpfs/file.c
*** linux-2.4.13/fs/hpfs/file.c	Sun Aug 12 20:37:53 2001
--- linux-2.4.13-ctx-4/fs/hpfs/file.c	Mon Nov  5 14:54:21 2001
***************
*** 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.13/fs/namei.c linux-2.4.13-ctx-4/fs/namei.c
*** linux-2.4.13/fs/namei.c	Wed Oct 31 15:32:41 2001
--- linux-2.4.13-ctx-4/fs/namei.c	Mon Nov  5 14:54:21 2001
***************
*** 163,167 ****
  		 * Nobody gets write access to an immutable file.
  		 */
! 		if (IS_IMMUTABLE(inode))
  			return -EACCES;
  	}
--- 163,167 ----
  		 * Nobody gets write access to an immutable file.
  		 */
! 		if (IS_IMMUTABLE_FILE(inode))
  			return -EACCES;
  	}
***************
*** 878,883 ****
  	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) {
--- 878,882 ----
  	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) {
***************
*** 1595,1599 ****
  	 */
  	error = -EPERM;
! 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
  		goto exit_lock;
  	if (!dir->i_op || !dir->i_op->link)
--- 1594,1598 ----
  	 */
  	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.13/fs/nfsd/vfs.c linux-2.4.13-ctx-4/fs/nfsd/vfs.c
*** linux-2.4.13/fs/nfsd/vfs.c	Wed Oct 10 11:58:19 2001
--- linux-2.4.13-ctx-4/fs/nfsd/vfs.c	Mon Nov  5 14:54:21 2001
***************
*** 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.13/fs/open.c linux-2.4.13-ctx-4/fs/open.c
*** linux-2.4.13/fs/open.c	Wed Oct 31 15:32:41 2001
--- linux-2.4.13-ctx-4/fs/open.c	Mon Nov  5 15:07:36 2001
***************
*** 123,127 ****
  
  	error = -EPERM;
! 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  		goto dput_and_out;
  
--- 123,127 ----
  
  	error = -EPERM;
! 	if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode))
  		goto dput_and_out;
  
***************
*** 471,475 ****
  		goto out_putf;
  	err = -EPERM;
! 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  		goto out_putf;
  	if (mode == (mode_t) -1)
--- 471,475 ----
  		goto out_putf;
  	err = -EPERM;
! 	if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode))
  		goto out_putf;
  	if (mode == (mode_t) -1)
***************
*** 502,506 ****
  
  	error = -EPERM;
! 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  		goto dput_and_out;
  
--- 502,506 ----
  
  	error = -EPERM;
! 	if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode))
  		goto dput_and_out;
  
***************
*** 532,536 ****
  		goto out;
  	error = -EPERM;
! 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  		goto out;
  	if (user == (uid_t) -1)
--- 532,536 ----
  		goto out;
  	error = -EPERM;
! 	if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode))
  		goto out;
  	if (user == (uid_t) -1)
diff -rc2P linux-2.4.13/fs/proc/array.c linux-2.4.13-ctx-4/fs/proc/array.c
*** linux-2.4.13/fs/proc/array.c	Wed Oct 31 15:32:41 2001
--- linux-2.4.13-ctx-4/fs/proc/array.c	Wed Oct 31 16:05:00 2001
***************
*** 264,271 ****
      return buffer + sprintf(buffer, "CapInh:\t%016x\n"
  			    "CapPrm:\t%016x\n"
! 			    "CapEff:\t%016x\n",
  			    cap_t(p->cap_inheritable),
  			    cap_t(p->cap_permitted),
! 			    cap_t(p->cap_effective));
  }
  
--- 264,273 ----
      return buffer + sprintf(buffer, "CapInh:\t%016x\n"
  			    "CapPrm:\t%016x\n"
! 			    "CapEff:\t%016x\n"
! 			    "CapBset:\t%016x\n",
  			    cap_t(p->cap_inheritable),
  			    cap_t(p->cap_permitted),
! 			    cap_t(p->cap_effective),
! 			    cap_t(p->cap_bset));
  }
  
***************
*** 289,292 ****
--- 291,306 ----
  	buffer = task_sig(task, buffer);
  	buffer = task_cap(task, buffer);
+ 	buffer += sprintf (buffer,"s_context: %d\n",task->s_context);
+ 	buffer += sprintf (buffer,"ipv4root: %08lx\n",task->ipv4root);
+ 	if (task->s_info != NULL){
+ 		buffer += sprintf (buffer,"ctxticks: %d %d %d\n"
+ 			,atomic_read(&task->s_info->ticks),task->counter
+ 			,task->s_info->refcount);
+ 		buffer += sprintf (buffer,"ctxflags: %d\n"
+ 			,task->s_info->flags);
+ 	}else{
+ 		buffer += sprintf (buffer,"ctxticks: none\n");
+ 		buffer += sprintf (buffer,"ctxflags: none\n");
+ 	}
  #if defined(CONFIG_ARCH_S390)
  	buffer = task_show_regs(task, buffer);
diff -rc2P linux-2.4.13/fs/proc/base.c linux-2.4.13-ctx-4/fs/proc/base.c
*** linux-2.4.13/fs/proc/base.c	Tue Oct 16 09:33:55 2001
--- linux-2.4.13-ctx-4/fs/proc/base.c	Wed Nov 14 12:04:44 2001
***************
*** 967,970 ****
--- 967,975 ----
  		goto out;
  
+ 	if (pid != 1
+ 		&& current->s_context != 1
+ 		&& task->s_context != current->s_context){
+ 		goto out;
+ 	}
  	inode = proc_pid_make_inode(dir->i_sb, task, PROC_PID_INO);
  
***************
*** 977,981 ****
  	inode->i_fop = &proc_base_operations;
  	inode->i_nlink = 3;
! 	inode->i_flags|=S_IMMUTABLE;
  
  	dentry->d_op = &pid_base_dentry_operations;
--- 982,986 ----
  	inode->i_fop = &proc_base_operations;
  	inode->i_nlink = 3;
! 	inode->i_flags|=S_IMMUTABLE_FILE;
  
  	dentry->d_op = &pid_base_dentry_operations;
***************
*** 1013,1016 ****
--- 1018,1031 ----
  		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;
  		if (--index >= 0)
  			continue;
diff -rc2P linux-2.4.13/fs/udf/inode.c linux-2.4.13-ctx-4/fs/udf/inode.c
*** linux-2.4.13/fs/udf/inode.c	Wed Oct 31 15:32:42 2001
--- linux-2.4.13-ctx-4/fs/udf/inode.c	Mon Nov  5 14:54:21 2001
***************
*** 864,868 ****
  			S_ISLNK(inode->i_mode)))
  		return;
! 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
  		return;
  
--- 864,868 ----
  			S_ISLNK(inode->i_mode)))
  		return;
! 	if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode))
  		return;
  
diff -rc2P linux-2.4.13/fs/ufs/truncate.c linux-2.4.13-ctx-4/fs/ufs/truncate.c
*** linux-2.4.13/fs/ufs/truncate.c	Mon Sep 10 12:06:10 2001
--- linux-2.4.13-ctx-4/fs/ufs/truncate.c	Mon Nov  5 14:54:21 2001
***************
*** 443,447 ****
  	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) {
--- 443,447 ----
  	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.13/include/asm-i386/unistd.h linux-2.4.13-ctx-4/include/asm-i386/unistd.h
*** linux-2.4.13/include/asm-i386/unistd.h	Wed Oct 31 15:32:43 2001
--- linux-2.4.13-ctx-4/include/asm-i386/unistd.h	Wed Oct 31 16:08:10 2001
***************
*** 231,234 ****
--- 231,236 ----
  #define __NR_gettid		224
  #define __NR_readahead		225
+ #define __NR_new_s_context      226
+ #define __NR_set_ipv4root       227
  
  /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
diff -rc2P linux-2.4.13/include/linux/capability.h linux-2.4.13-ctx-4/include/linux/capability.h
*** linux-2.4.13/include/linux/capability.h	Sun Sep 23 13:31:02 2001
--- linux-2.4.13-ctx-4/include/linux/capability.h	Thu Nov  8 00:42:42 2001
***************
*** 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
***************
*** 277,280 ****
--- 278,285 ----
  
  #define CAP_LEASE            28
+ 
+ /* Allow opening special device file */
+ 
+ #define CAP_OPENDEV          29
  
  #ifdef __KERNEL__
diff -rc2P linux-2.4.13/include/linux/ext2_fs.h linux-2.4.13-ctx-4/include/linux/ext2_fs.h
*** linux-2.4.13/include/linux/ext2_fs.h	Wed Oct 31 15:32:45 2001
--- linux-2.4.13-ctx-4/include/linux/ext2_fs.h	Thu Nov  8 00:43:17 2001
***************
*** 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.13/include/linux/fs.h linux-2.4.13-ctx-4/include/linux/fs.h
*** linux-2.4.13/include/linux/fs.h	Wed Oct 31 15:32:45 2001
--- linux-2.4.13-ctx-4/include/linux/fs.h	Thu Nov  8 00:42:42 2001
***************
*** 127,137 ****
  /* 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 */
  
  /*
--- 127,138 ----
  /* 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 */
  
  /*
***************
*** 157,161 ****
  #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)
--- 158,163 ----
  #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)
***************
*** 354,362 ****
   * 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 */
  
  /*
--- 356,365 ----
   * 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 */
  
  /*
diff -rc2P linux-2.4.13/include/linux/sched.h linux-2.4.13-ctx-4/include/linux/sched.h
*** linux-2.4.13/include/linux/sched.h	Tue Oct 16 09:33:55 2001
--- linux-2.4.13-ctx-4/include/linux/sched.h	Fri Nov 16 14:36:27 2001
***************
*** 276,279 ****
--- 276,303 ----
  	__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 */
+ 
+ 
+ struct context_info{
+ 	int refcount;
+ 	int s_context;
+ 	char nodename[65];
+ 	char domainname[65];
+ 	int flags;		/* S_CTX_INFO_xxx */
+ 	atomic_t ticks;		/* Number of ticks used by all process */
+ 				/* in the s_context */
+ };
+ 
+ 
  extern struct user_struct root_user;
  #define INIT_USER (&root_user)
***************
*** 400,403 ****
--- 424,433 ----
  /* Protection of (de-)allocation: mm, files, fs, tty */
  	spinlock_t alloc_lock;
+ /* Field to make virtual server running in chroot more  isolated */
+ 	int s_context;	/* Process can only deal with other processes */
+ 			/* with the same s_context */
+ 	__u32 cap_bset;	/* Maximum capability of this process and children */
+ 	unsigned long ipv4root;	/* Process can only bind to this iP */
+ 	struct context_info *s_info;
  };
  
***************
*** 486,490 ****
      pending:		{ NULL, &tsk.pending.head, {{0}}},		\
      blocked:		{{0}},						\
!     alloc_lock:		SPIN_LOCK_UNLOCKED				\
  }
  
--- 516,521 ----
      pending:		{ NULL, &tsk.pending.head, {{0}}},		\
      blocked:		{{0}},						\
!     alloc_lock:		SPIN_LOCK_UNLOCKED,				\
!     cap_bset:		CAP_INIT_EFF_SET,				\
  }
  
***************
*** 899,902 ****
--- 930,938 ----
  	return res;
  }
+ 
+ /* Manage the reference count of the context_info pointer */
+ void sys_release_s_info (struct task_struct *);
+ void sys_assign_s_info (struct task_struct *);
+ void sys_alloc_s_info (void);
  
  #endif /* __KERNEL__ */
diff -rc2P linux-2.4.13/include/net/route.h linux-2.4.13-ctx-4/include/net/route.h
*** linux-2.4.13/include/net/route.h	Wed Oct 31 15:32:45 2001
--- linux-2.4.13-ctx-4/include/net/route.h	Fri Nov 16 14:50:01 2001
***************
*** 165,168 ****
--- 165,175 ----
  {
  	int err;
+ 	if (current->ipv4root != 0){
+ 		if (src == 0){
+ 			src = current->ipv4root;
+ 		}else if (current->ipv4root != src){
+ 			return -EPERM;
+ 		}
+ 	}
  	err = ip_route_output(rp, dst, src, tos, oif);
  	if (err || (dst && src))
diff -rc2P linux-2.4.13/kernel/exit.c linux-2.4.13-ctx-4/kernel/exit.c
*** linux-2.4.13/kernel/exit.c	Wed Oct 31 15:32:45 2001
--- linux-2.4.13-ctx-4/kernel/exit.c	Wed Oct 31 16:05:00 2001
***************
*** 65,68 ****
--- 65,69 ----
  		if (current->counter >= MAX_COUNTER)
  			current->counter = MAX_COUNTER;
+ 		sys_release_s_info(p);
  		p->pid = 0;
  		free_task_struct(p);
diff -rc2P linux-2.4.13/kernel/fork.c linux-2.4.13-ctx-4/kernel/fork.c
*** linux-2.4.13/kernel/fork.c	Tue Sep 18 00:46:04 2001
--- linux-2.4.13-ctx-4/kernel/fork.c	Wed Nov 14 12:49:45 2001
***************
*** 586,591 ****
--- 586,597 ----
  
  	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;
+ 	}
  	if (atomic_read(&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur)
  		goto bad_fork_free;
+ 
+ 	sys_assign_s_info (p);
  
  	atomic_inc(&p->user->__count);
diff -rc2P linux-2.4.13/kernel/sched.c linux-2.4.13-ctx-4/kernel/sched.c
*** linux-2.4.13/kernel/sched.c	Wed Oct 31 15:32:46 2001
--- linux-2.4.13-ctx-4/kernel/sched.c	Wed Oct 31 16:05:00 2001
***************
*** 165,169 ****
  		 * over..
  		 */
! 		weight = p->counter;
  		if (!weight)
  			goto out;
--- 165,175 ----
  		 * 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;
***************
*** 687,692 ****
  		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);
--- 693,713 ----
  		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.13/kernel/signal.c linux-2.4.13-ctx-4/kernel/signal.c
*** linux-2.4.13/kernel/signal.c	Mon Sep 17 19:40:01 2001
--- linux-2.4.13-ctx-4/kernel/signal.c	Fri Nov 16 20:31:46 2001
***************
*** 593,597 ****
  		read_lock(&tasklist_lock);
  		for_each_task(p) {
! 			if (p->pgrp == pgrp) {
  				int err = send_sig_info(sig, info, p);
  				if (retval)
--- 593,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)
***************
*** 640,644 ****
  	p = find_task_by_pid(pid);
  	error = -ESRCH;
! 	if (p)
  		error = send_sig_info(sig, info, p);
  	read_unlock(&tasklist_lock);
--- 640,644 ----
  	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);
***************
*** 664,668 ****
  		read_lock(&tasklist_lock);
  		for_each_task(p) {
! 			if (p->pid > 1 && p != current) {
  				int err = send_sig_info(sig, info, p);
  				++count;
--- 664,668 ----
  		read_lock(&tasklist_lock);
  		for_each_task(p) {
! 			if (p->pid > 1 && p != current && p->s_context == current->s_context) {
  				int err = send_sig_info(sig, info, p);
  				++count;
***************
*** 1257,1258 ****
--- 1257,1355 ----
  }
  #endif /* !alpha && !__ia64__ && !defined(__mips__) */
+ 
+ /*
+ 	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;
+ 			}
+ 			current->s_context = alloc_ctx;
+ 			current->cap_bset &= (~remove_cap);
+ 			ret = alloc_ctx;
+ 			sys_alloc_s_info();
+ 			if (current->s_info != NULL){
+ 				current->s_info->flags |= flags;
+ 			}
+ 			spin_unlock(&alloc_ctx_lock);
+ 		}
+ 	}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){
+ 		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){
+ 			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.13/kernel/sys.c linux-2.4.13-ctx-4/kernel/sys.c
*** linux-2.4.13/kernel/sys.c	Tue Sep 18 17:10:43 2001
--- linux-2.4.13-ctx-4/kernel/sys.c	Wed Oct 31 16:05:00 2001
***************
*** 1016,1022 ****
  {
  	int errno = 0;
  
  	down_read(&uts_sem);
! 	if (copy_to_user(name,&system_utsname,sizeof *name))
  		errno = -EFAULT;
  	up_read(&uts_sem);
--- 1016,1031 ----
  {
  	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 ****
--- 1033,1093 ----
  }
  
+ /*
+ 	Decrease the reference count on the context_info member of a task
+ 	Free the struct if the reference count reach 0.
+ */
+ void sys_release_s_info (struct task_struct *p)
+ {
+ 	down_write (&uts_sem);
+ 	if (p->s_info != NULL){
+ 		p->s_info->refcount--;
+ 		if (p->s_info->refcount == 0){
+ 			// printk ("vfree s_info %d\n",p->pid);
+ 			vfree (p->s_info);
+ 			p->s_info = NULL;
+ 		}
+ 	}
+ 	up_write (&uts_sem);
+ }
+ /*
+ 	Increase the reference count on the context_info member of a task
+ */
+ void sys_assign_s_info (struct task_struct *p)
+ {
+ 	down_write (&uts_sem);
+ 	if (p->s_info != NULL) p->s_info->refcount++;
+ 	up_write (&uts_sem);
+ }
+ 
+ /*
+ 	Alloc a new s_info to the current process and release
+ 	the one currently owned by the current process.
+ */
+ void sys_alloc_s_info()
+ {
+ 	struct context_info *s_info = vmalloc(sizeof(struct context_info));
+ 	// printk ("new s_info %d\n",current->pid);
+ 	s_info->s_context = current->s_context;
+ 	s_info->refcount = 1;
+ 	atomic_set (&s_info->ticks,current->counter);
+ 	s_info->flags = 0;
+ 	down_read (&uts_sem);
+ 	if (current->s_info != NULL){
+ 		strcpy (s_info->nodename,current->s_info->nodename);
+ 		strcpy (s_info->domainname,current->s_info->domainname);
+ 	}else{
+ 		strcpy (s_info->nodename,system_utsname.nodename);
+ 		strcpy (s_info->domainname,system_utsname.domainname);
+ 	}
+ 	up_read (&uts_sem);
+ 	sys_release_s_info (current);	
+ 	current->s_info = s_info;
+ }
+ 
+ 
  asmlinkage long sys_sethostname(char *name, int len)
  {
  	int errno;
+ 	char *nodename;
  
  	if (!capable(CAP_SYS_ADMIN))
***************
*** 1034,1039 ****
  	down_write(&uts_sem);
  	errno = -EFAULT;
! 	if (!copy_from_user(system_utsname.nodename, name, len)) {
! 		system_utsname.nodename[len] = 0;
  		errno = 0;
  	}
--- 1097,1104 ----
  	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);
--- 1110,1125 ----
  {
  	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 ****
--- 1134,1138 ----
  {
  	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);
--- 1142,1151 ----
  
  	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.13/kernel/sysctl.c linux-2.4.13-ctx-4/kernel/sysctl.c
*** linux-2.4.13/kernel/sysctl.c	Wed Oct 10 11:58:22 2001
--- linux-2.4.13-ctx-4/kernel/sysctl.c	Wed Oct 31 16:05:00 2001
***************
*** 375,378 ****
--- 375,379 ----
  static int test_perm(int mode, int op)
  {
+ 	if (!capable(CAP_SYS_ADMIN)) mode &= ~(0222);
  	if (!current->euid)
  		mode >>= 6;
***************
*** 789,793 ****
--- 790,805 ----
  {
  	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.13/kernel/timer.c linux-2.4.13-ctx-4/kernel/timer.c
*** linux-2.4.13/kernel/timer.c	Wed Oct 10 11:58:22 2001
--- linux-2.4.13-ctx-4/kernel/timer.c	Wed Nov 14 12:08:22 2001
***************
*** 584,587 ****
--- 584,592 ----
  	update_one_process(p, user_tick, system, cpu);
  	if (p->pid) {
+ 		if (p->s_info != NULL
+ 			&& (p->s_info->flags & S_CTX_INFO_SCHED)!=0){
+ 			// atomic_sub (ticks*p->s_info->refcount, &p->s_info->ticks);
+ 			atomic_dec (&p->s_info->ticks);
+ 		}
  		if (--p->counter <= 0) {
  			p->counter = 0;
diff -rc2P linux-2.4.13/net/ipv4/af_inet.c linux-2.4.13-ctx-4/net/ipv4/af_inet.c
*** linux-2.4.13/net/ipv4/af_inet.c	Tue Aug  7 11:30:50 2001
--- linux-2.4.13-ctx-4/net/ipv4/af_inet.c	Wed Oct 31 16:05:00 2001
***************
*** 474,477 ****
--- 474,478 ----
  	int chk_addr_ret;
  	int err;
+ 	__u32 s_addr;
  
  	/* If the socket has its own bind function then use it. (RAW) */
***************
*** 482,486 ****
  		return -EINVAL;
  
! 	chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr);
  
  	/* Not specified by any standard per-se, however it breaks too
--- 483,497 ----
  		return -EINVAL;
  
! 	s_addr = addr->sin_addr.s_addr;
! 	if (current->ipv4root != 0){
! 		// printk ("ipv4root0 %08lx %08x\n",current->ipv4root,s_addr);
! 		if (s_addr == 0){
! 			s_addr = current->ipv4root;
! 		}else if (s_addr != current->ipv4root){
! 			return -EADDRNOTAVAIL;
! 		}
! 	}
! 	chk_addr_ret = inet_addr_type(s_addr);
! 	// printk ("ipv4root %08lx %08x %d\n",current->ipv4root,s_addr,chk_addr_ret);
  
  	/* Not specified by any standard per-se, however it breaks too
***************
*** 493,497 ****
  	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 &&
--- 504,508 ----
  	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 &&
***************
*** 518,522 ****
  		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 */
--- 529,533 ----
  		goto out;
  
! 	sk->rcv_saddr = sk->saddr = s_addr;
  	if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
  		sk->saddr = 0;  /* Use device */
diff -rc2P linux-2.4.13/net/socket.c linux-2.4.13-ctx-4/net/socket.c
*** linux-2.4.13/net/socket.c	Wed Oct 31 15:32:46 2001
--- linux-2.4.13-ctx-4/net/socket.c	Wed Oct 31 16:05:00 2001
***************
*** 1766,1767 ****
--- 1766,1779 ----
  	return len;
  }
+ 
+ asmlinkage int sys_set_ipv4root (unsigned long ip)
+ {
+ 	int ret = -EPERM;
+ 	if (current->ipv4root == 0
+ 		|| capable(CAP_SYS_ADMIN)){
+ 		ret = 0;
+ 		current->ipv4root = ip;
+ 	}
+ 	return ret;
+ }
+