diff -rc2P linux.orig/Makefile linux/Makefile
*** linux.orig/Makefile	Thu Oct 17 12:26:21 2002
--- linux/Makefile	Fri Oct 25 17:10:43 2002
***************
*** 2,6 ****
  PATCHLEVEL = 4
  SUBLEVEL = 18
! EXTRAVERSION = -10BOOT
  
  KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
--- 2,6 ----
  PATCHLEVEL = 4
  SUBLEVEL = 18
! EXTRAVERSION = -10-ctx12
  
  KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff -rc2P linux.orig/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
*** linux.orig/arch/i386/kernel/entry.S	Thu Oct 17 12:25:54 2002
--- linux/arch/i386/kernel/entry.S	Sat Oct 26 23:31:24 2002
***************
*** 650,653 ****
--- 650,655 ----
  	.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)    /* 243 */
+ 	.long SYMBOL_NAME(sys_set_ipv4root)     /* 234 */
  
  	.rept NR_syscalls-(.-sys_call_table)/4
diff -rc2P linux.orig/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
*** linux.orig/arch/i386/kernel/ptrace.c	Thu Oct 17 12:25:56 2002
--- linux/arch/i386/kernel/ptrace.c	Fri Oct 25 16:32:05 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.orig/fs/devpts/inode.c linux/fs/devpts/inode.c
*** linux.orig/fs/devpts/inode.c	Thu Oct 25 11:02:26 2001
--- linux/fs/devpts/inode.c	Fri Oct 25 16:32:05 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.orig/fs/devpts/root.c linux/fs/devpts/root.c
*** linux.orig/fs/devpts/root.c	Fri Dec 21 20:41:55 2001
--- linux/fs/devpts/root.c	Fri Oct 25 16:32:05 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.orig/fs/exec.c linux/fs/exec.c
*** linux.orig/fs/exec.c	Thu Oct 17 12:25:55 2002
--- linux/fs/exec.c	Fri Oct 25 16:32:05 2002
***************
*** 693,697 ****
  	int do_unlock = 0;
  
! 	new_permitted = cap_intersect(bprm->cap_permitted, cap_bset);
  	working = cap_intersect(bprm->cap_inheritable,
  				current->cap_inheritable);
--- 693,697 ----
  	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.orig/fs/proc/array.c linux/fs/proc/array.c
*** linux.orig/fs/proc/array.c	Thu Oct 17 12:25:55 2002
--- linux/fs/proc/array.c	Mon Oct 28 18:14:47 2002
***************
*** 71,74 ****
--- 71,75 ----
  #include <linux/signal.h>
  #include <linux/highmem.h>
+ #include <linux/s_context.h>
  
  #include <asm/uaccess.h>
***************
*** 76,79 ****
--- 77,81 ----
  #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"
--- 150,159 ----
  {
  	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);
--- 165,169 ----
  		"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));
  }
  
--- 273,282 ----
      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 ****
--- 300,346 ----
  	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);
***************
*** 344,347 ****
--- 395,400 ----
  	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.orig/fs/proc/base.c linux/fs/proc/base.c
*** linux.orig/fs/proc/base.c	Thu Oct 17 12:25:52 2002
--- linux/fs/proc/base.c	Mon Oct 28 18:13:35 2002
***************
*** 26,29 ****
--- 26,30 ----
  #include <linux/seq_file.h>
  #include <linux/namespace.h>
+ #include <linux/s_context.h>
  
  /*
***************
*** 1020,1023 ****
--- 1021,1030 ----
  		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;
--- 1037,1041 ----
  	inode->i_fop = &proc_base_operations;
  	inode->i_nlink = 3;
!  	inode->i_flags|=S_IMMUTABLE;	
  
  	dentry->d_op = &pid_base_dentry_operations;
***************
*** 1066,1069 ****
--- 1073,1089 ----
  		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.orig/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
*** linux.orig/include/asm-i386/unistd.h	Thu Oct 17 12:25:52 2002
--- linux/include/asm-i386/unistd.h	Sat Oct 26 23:45:00 2002
***************
*** 248,251 ****
--- 248,254 ----
  #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.orig/include/linux/capability.h linux/include/linux/capability.h
*** linux.orig/include/linux/capability.h	Thu Oct 24 12:31:22 2002
--- linux/include/linux/capability.h	Sat Oct 26 09:30:34 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
***************
*** 280,283 ****
--- 281,288 ----
  #define CAP_LEASE            28
  
+ /* Allow opening special device file */
+ 
+ #define CAP_OPENDEV          29
+ 
  #ifdef __KERNEL__
  /* 
diff -rc2P linux.orig/include/linux/devpts_fs_info.h linux/include/linux/devpts_fs_info.h
*** linux.orig/include/linux/devpts_fs_info.h	Thu Jan  1 03:00:00 1970
--- linux/include/linux/devpts_fs_info.h	Fri Oct 25 16:32:05 2002
***************
*** 0 ****
--- 1,4 ----
+ struct devpts_inode_info{
+ 	int s_context;
+ };
+ 
diff -rc2P linux.orig/include/linux/fs.h linux/include/linux/fs.h
*** linux.orig/include/linux/fs.h	Thu Oct 24 12:31:22 2002
--- linux/include/linux/fs.h	Sat Oct 26 09:30:10 2002
***************
*** 320,323 ****
--- 320,324 ----
  #include <linux/jffs2_fs_i.h>
  #include <linux/cramfs_fs_sb.h>
+ #include <linux/devpts_fs_info.h>
  
  /*
***************
*** 512,515 ****
--- 513,517 ----
  		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.orig/include/linux/s_context.h linux/include/linux/s_context.h
*** linux.orig/include/linux/s_context.h	Thu Jan  1 03:00:00 1970
--- linux/include/linux/s_context.h	Mon Oct 28 17:31:31 2002
***************
*** 0 ****
--- 1,65 ----
+ #ifndef _S_CONTEXT_H_
+ 
+ #define _S_CONTEXT_H_
+ 
+ #include <asm/atomic.h>
+ #include <linux/types.h>
+ 
+ /*
+ 	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 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 */
+ };
+ 
+ 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 */
+ };
+ 
+ static int set_initpid (int flags);
+ static inline int switch_user_struct(int new_context);
+ 
+ /* syscall */
+ int sys_new_s_context(int ctx, __u32 remove_cap, int flags);
+ int sys_set_ipv4root (__u32 ip[], int nbip, __u32 bcast);
+ /***********************/
+ /* Manage the reference count of the context_info pointer */
+ void sys_release_s_info (struct task_struct *p);
+ void sys_assign_s_info (struct task_struct *p);
+ void sys_alloc_s_info(void);
+ void sys_release_ip_info (struct task_struct *p);
+ void sys_assign_ip_info (struct task_struct *p);
+ void sys_alloc_ip_info(void);
+ /**/
+ 
+ #endif
diff -rc2P linux.orig/include/linux/sched.h linux/include/linux/sched.h
*** linux.orig/include/linux/sched.h	Thu Oct 24 12:31:22 2002
--- linux/include/linux/sched.h	Mon Oct 28 17:34:54 2002
***************
*** 130,133 ****
--- 130,136 ----
  #include <linux/spinlock.h>
  
+ struct context_info;
+ struct iproot_info;
+ 
  /*
   * This serializes "schedule()" and also protects
***************
*** 276,279 ****
--- 279,283 ----
  	struct user_struct *next, **pprev;
  	uid_t uid;
+ 	int s_context;
  };
  
***************
*** 283,286 ****
--- 287,291 ----
  	__user; })
  
+ 
  extern struct user_struct root_user;
  #define INIT_USER (&root_user)
***************
*** 400,403 ****
--- 405,414 ----
  	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;
***************
*** 407,411 ****
  	void (*tux_exit)(void);
  
- 	
  /* Thread group tracking */
     	u32 parent_exec_id;
--- 418,421 ----
***************
*** 515,518 ****
--- 525,529 ----
      alloc_lock:		SPIN_LOCK_UNLOCKED,				\
      journal_info:	NULL,						\
+     cap_bset:		CAP_INIT_EFF_SET,				\
  }
  
***************
*** 566,570 ****
  
  /* per-UID process charging. */
! extern struct user_struct * alloc_uid(uid_t);
  extern void free_uid(struct user_struct *);
  
--- 577,581 ----
  
  /* per-UID process charging. */
! extern struct user_struct * alloc_uid(int, uid_t);
  extern void free_uid(struct user_struct *);
  
diff -rc2P linux.orig/include/net/route.h linux/include/net/route.h
*** linux.orig/include/net/route.h	Thu Oct 24 12:31:22 2002
--- linux/include/net/route.h	Mon Oct 28 17:52:27 2002
***************
*** 33,36 ****
--- 33,37 ----
  #include <linux/ip.h>
  #include <linux/cache.h>
+ #include <linux/s_context.h>
  
  #ifndef __KERNEL__
***************
*** 165,168 ****
--- 166,183 ----
  {
  	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.orig/include/net/sock.h linux/include/net/sock.h
*** linux.orig/include/net/sock.h	Thu Oct 24 12:31:22 2002
--- linux/include/net/sock.h	Mon Oct 28 17:35:03 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 and TUX layer private data */
  	void			*user_data;
!   
  	/* Callbacks */
  	void			(*state_change)(struct sock *sk);
--- 670,677 ----
  	/* RPC and TUX 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.orig/include/net/tcp.h linux/include/net/tcp.h
*** linux.orig/include/net/tcp.h	Thu Oct 24 12:31:22 2002
--- linux/include/net/tcp.h	Mon Oct 28 17:52:33 2002
***************
*** 191,194 ****
--- 191,195 ----
  	struct in6_addr		v6_rcv_saddr;
  #endif
+ 	int			s_context;
  };
  
diff -rc2P linux.orig/ipc/util.c linux/ipc/util.c
*** linux.orig/ipc/util.c	Mon Aug 13 04:37:53 2001
--- linux/ipc/util.c	Fri Oct 25 16:32:05 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.orig/ipc/util.h linux/ipc/util.h
*** linux.orig/ipc/util.h	Mon Feb 19 21:18:18 2001
--- linux/ipc/util.h	Fri Oct 25 16:32:05 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.orig/kernel/Makefile linux/kernel/Makefile
*** linux.orig/kernel/Makefile	Thu Oct 17 12:26:06 2002
--- linux/kernel/Makefile	Sun Oct 27 14:43:21 2002
***************
*** 11,20 ****
  
  export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o \
! 	      syscall_ksyms.o
  
  obj-y     = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
  	    module.o exit.o itimer.o info.o time.o softirq.o resource.o \
  	    sysctl.o acct.o capability.o ptrace.o timer.o user.o \
! 	    signal.o sys.o kmod.o context.o kksymoops.o syscall_ksyms.o
  
  obj-$(CONFIG_UID16) += uid16.o
--- 11,21 ----
  
  export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o \
! 	      syscall_ksyms.o s_context.o
  
  obj-y     = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
  	    module.o exit.o itimer.o info.o time.o softirq.o resource.o \
  	    sysctl.o acct.o capability.o ptrace.o timer.o user.o \
! 	    signal.o sys.o kmod.o context.o kksymoops.o syscall_ksyms.o \
! 	    s_context.o
  
  obj-$(CONFIG_UID16) += uid16.o
diff -rc2P linux.orig/kernel/exit.c linux/kernel/exit.c
*** linux.orig/kernel/exit.c	Thu Oct 17 12:25:55 2002
--- linux/kernel/exit.c	Mon Oct 28 17:38:09 2002
***************
*** 17,20 ****
--- 17,21 ----
  #include <linux/acct.h>
  #endif
+ #include <linux/s_context.h>
  
  #include <asm/uaccess.h>
***************
*** 42,47 ****
  	current->cmaj_flt += p->maj_flt + p->cmaj_flt;
  	current->cnswap += p->nswap + p->cnswap;
! 	sched_exit(p);
! 	p->pid = 0;
  	free_task_struct(p);
  }
--- 43,50 ----
  	current->cmaj_flt += p->maj_flt + p->cmaj_flt;
  	current->cnswap += p->nswap + p->cnswap;
! 	sched_exit(p);	
! 	sys_release_s_info(p);
! 	sys_release_ip_info(p);
! 	p->pid = 0;	
  	free_task_struct(p);
  }
***************
*** 206,211 ****
--- 209,227 ----
  {
  	struct task_struct * p, *reaper;
+  	struct task_struct *vchild_reaper = child_reaper;
  
  	read_lock(&tasklist_lock);
+ 	/* if fake init find init task this context */
+  	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 */
***************
*** 218,222 ****
  
  	if (reaper == father)
! 		reaper = child_reaper;
  
  	for_each_task(p) {
--- 234,238 ----
  
  	if (reaper == father)
! 		reaper = vchild_reaper;
  
  	for_each_task(p) {
***************
*** 228,232 ****
  			/* Make sure we're not reparenting to ourselves */
  			if (p == reaper)
! 				p->p_opptr = child_reaper;
  			else
  				p->p_opptr = reaper;
--- 244,248 ----
  			/* Make sure we're not reparenting to ourselves */
  			if (p == reaper)
! 				p->p_opptr = vchild_reaper;
  			else
  				p->p_opptr = reaper;
diff -rc2P linux.orig/kernel/fork.c linux/kernel/fork.c
*** linux.orig/kernel/fork.c	Thu Oct 17 12:25:54 2002
--- linux/kernel/fork.c	Mon Oct 28 17:36:25 2002
***************
*** 11,15 ****
   * management can be a bitch. See 'mm/memory.c': 'copy_page_range()'
   */
- 
  #include <linux/config.h>
  #include <linux/slab.h>
--- 11,14 ----
***************
*** 18,26 ****
  #include <linux/smp_lock.h>
  #include <linux/module.h>
- #include <linux/vmalloc.h>
  #include <linux/completion.h>
  #include <linux/namespace.h>
  #include <linux/personality.h>
  #include <linux/mman.h>
  
  #include <asm/pgtable.h>
--- 17,25 ----
  #include <linux/smp_lock.h>
  #include <linux/module.h>
  #include <linux/completion.h>
  #include <linux/namespace.h>
  #include <linux/personality.h>
  #include <linux/mman.h>
+ #include <linux/s_context.h>
  
  #include <asm/pgtable.h>
***************
*** 615,618 ****
--- 614,621 ----
  
  	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
***************
*** 625,628 ****
--- 628,634 ----
  		goto bad_fork_free;
  
+ 	sys_assign_s_info (p);
+ 	sys_assign_ip_info (p);
+ 
  	atomic_inc(&p->user->__count);
  	atomic_inc(&p->user->processes);
diff -rc2P linux.orig/kernel/printk.c linux/kernel/printk.c
*** linux.orig/kernel/printk.c	Thu Oct 17 12:25:43 2002
--- linux/kernel/printk.c	Fri Oct 25 16:32:05 2002
***************
*** 174,177 ****
--- 174,179 ----
  	int error = 0;
  
+ 	if (!capable(CAP_SYS_ADMIN) && current->s_context != 0) return -EPERM;
+ 
  	switch (type) {
  	case 0:		/* Close log */
diff -rc2P linux.orig/kernel/s_context.c linux/kernel/s_context.c
*** linux.orig/kernel/s_context.c	Thu Jan  1 03:00:00 1970
--- linux/kernel/s_context.c	Mon Oct 28 17:43:27 2002
***************
*** 0 ****
--- 1,316 ----
+ #include <linux/sched.h>
+ #include <linux/s_context.h>
+ #include <linux/proc_fs.h>
+ #include <linux/vmalloc.h>
+ #include <linux/utsname.h>
+ 
+ #include <asm/uaccess.h>
+ 
+ #define MAX_S_CONTEXT 65535	/* Arbitrary limit */
+ 
+ /*
+ static proc_dir_entry *vserver_root;
+ s_context_proc_init()
+ {
+     struct device_node *root;
+ 
+     root = find_path_device("/");
+     if (root == 0) 
+     {
+ 	printk(KERN_ERR "vservers /proc: can't find root\n");
+ 	return;
+     }
+ 
+ 
+     vserver_root = proc_mkdir("vservers",0);
+     if( vserver_root == NULL )
+     {
+ 	return;
+     }    
+     add_node(root, vserver_root );    
+ }
+ */
+ 
+ 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;
+ }
+ 
+ /*
+ 	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(void)
+ {
+ 	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(void)
+ {
+ 	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;
+ }
+ 
+ 
+ /*
+ 	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)
+ {
+ 	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;
+ }
+ 
+ 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.orig/kernel/signal.c linux/kernel/signal.c
*** linux.orig/kernel/signal.c	Thu Oct 17 12:25:53 2002
--- linux/kernel/signal.c	Mon Oct 28 16:18:16 2002
***************
*** 619,623 ****
  		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)
--- 619,627 ----
  		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)
***************
*** 673,676 ****
--- 677,699 ----
                                 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;
+  		}
  		error = send_sig_info(sig, info, p);
  	}
***************
*** 697,701 ****
  		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;
--- 720,726 ----
  		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;
diff -rc2P linux.orig/kernel/sys.c linux/kernel/sys.c
*** linux.orig/kernel/sys.c	Thu Oct 17 12:25:43 2002
--- linux/kernel/sys.c	Mon Oct 28 17:41:50 2002
***************
*** 15,18 ****
--- 15,19 ----
  #include <linux/init.h>
  #include <linux/highuid.h>
+ #include <linux/s_context.h>
  
  #include <asm/uaccess.h>
***************
*** 501,505 ****
  	 * we should be checking for it.  -DaveM
  	 */
! 	new_user = alloc_uid(new_ruid);
  	if (!new_user)
  		return -EAGAIN;
--- 502,506 ----
  	 * 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,1042 ----
  }
  
+ 
  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;
  	}
--- 1046,1053 ----
  	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);
--- 1059,1074 ----
  {
  	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 ****
--- 1083,1087 ----
  {
  	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);
--- 1091,1100 ----
  
  	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.orig/kernel/sysctl.c linux/kernel/sysctl.c
*** linux.orig/kernel/sysctl.c	Thu Oct 17 12:25:56 2002
--- linux/kernel/sysctl.c	Mon Oct 28 17:39:44 2002
***************
*** 31,34 ****
--- 31,35 ----
  #include <linux/sysrq.h>
  #include <linux/highuid.h>
+ #include <linux/s_context.h>
  
  #include <asm/uaccess.h>
***************
*** 393,396 ****
--- 394,398 ----
  static int test_perm(int mode, int op)
  {
+ 	if (!capable(CAP_SYS_ADMIN)) mode &= ~(0222);
  	if (!current->euid)
  		mode >>= 6;
***************
*** 807,811 ****
--- 809,824 ----
  {
  	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.orig/kernel/timer.c linux/kernel/timer.c
*** linux.orig/kernel/timer.c	Thu Oct 17 12:25:53 2002
--- linux/kernel/timer.c	Mon Oct 28 17:41:01 2002
***************
*** 23,26 ****
--- 23,27 ----
  #include <linux/interrupt.h>
  #include <linux/kernel_stat.h>
+ #include <linux/s_context.h>
  
  #include <asm/uaccess.h>
***************
*** 727,730 ****
--- 728,736 ----
  {
  	/* 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;
  }
***************
*** 773,776 ****
--- 779,788 ----
  		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.orig/kernel/user.c linux/kernel/user.c
*** linux.orig/kernel/user.c	Wed Nov 29 09:43:39 2000
--- linux/kernel/user.c	Fri Oct 25 16:32:05 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.orig/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
*** linux.orig/net/ipv4/af_inet.c	Thu Oct 17 12:25:53 2002
--- linux/net/ipv4/af_inet.c	Fri Oct 25 16:32:05 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.orig/net/ipv4/devinet.c linux/net/ipv4/devinet.c
*** linux.orig/net/ipv4/devinet.c	Thu Oct 17 12:25:53 2002
--- linux/net/ipv4/devinet.c	Fri Oct 25 16:32:05 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.orig/net/ipv4/raw.c linux/net/ipv4/raw.c
*** linux.orig/net/ipv4/raw.c	Thu Oct 17 12:25:53 2002
--- linux/net/ipv4/raw.c	Fri Oct 25 16:32:05 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.orig/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
*** linux.orig/net/ipv4/tcp_ipv4.c	Thu Oct 17 12:26:00 2002
--- linux/net/ipv4/tcp_ipv4.c	Fri Oct 25 16:32:05 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.orig/net/ipv4/tcp_minisocks.c linux/net/ipv4/tcp_minisocks.c
*** linux.orig/net/ipv4/tcp_minisocks.c	Thu Oct 17 12:26:07 2002
--- linux/net/ipv4/tcp_minisocks.c	Fri Oct 25 16:32:05 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.orig/net/ipv4/udp.c linux/net/ipv4/udp.c
*** linux.orig/net/ipv4/udp.c	Thu Oct 17 12:25:54 2002
--- linux/net/ipv4/udp.c	Fri Oct 25 16:32:05 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.orig/net/ipv6/raw.c linux/net/ipv6/raw.c
*** linux.orig/net/ipv6/raw.c	Thu Oct 17 12:26:00 2002
--- linux/net/ipv6/raw.c	Fri Oct 25 16:32:05 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.orig/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
*** linux.orig/net/ipv6/tcp_ipv6.c	Thu Oct 17 12:25:54 2002
--- linux/net/ipv6/tcp_ipv6.c	Fri Oct 25 16:32:05 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.orig/net/ipv6/udp.c linux/net/ipv6/udp.c
*** linux.orig/net/ipv6/udp.c	Thu Oct 17 12:25:54 2002
--- linux/net/ipv6/udp.c	Fri Oct 25 16:32:05 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.orig/net/socket.c linux/net/socket.c
*** linux.orig/net/socket.c	Thu Oct 17 12:25:54 2002
--- linux/net/socket.c	Mon Oct 28 16:55:37 2002
***************
*** 1764,1771 ****
--- 1764,1773 ----
  		len = length;
  	if (len < 0)
+ 
  		len = 0;
  	return len;
  }
  
+ 
  int tux_Dprintk;
  int tux_TDprintk;
diff -rc2P linux.orig/net/unix/af_unix.c linux/net/unix/af_unix.c
*** linux.orig/net/unix/af_unix.c	Thu Oct 17 12:25:54 2002
--- linux/net/unix/af_unix.c	Fri Oct 25 16:32:06 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;
***************
*** 1749,1752 ****
--- 1751,1757 ----
  	forall_unix_sockets (i,s)
  	{
+ 		if (current->s_context != 1 && s->s_context != current->s_context)
+ 			continue;
+ 
  		unix_state_rlock(s);
  
