diff -rc2P linux-2.4.18ctx-10/Makefile linux-2.4.18ctx-12/Makefile
*** linux-2.4.18ctx-10/Makefile	Tue Mar 19 23:20:34 2002
--- linux-2.4.18ctx-12/Makefile	Tue Jul  2 12:11:33 2002
***************
*** 2,6 ****
  PATCHLEVEL = 4
  SUBLEVEL = 18
! EXTRAVERSION =ctx-10
  
  KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
--- 2,6 ----
  PATCHLEVEL = 4
  SUBLEVEL = 18
! EXTRAVERSION =ctxsmp-12
  
  KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff -rc2P linux-2.4.18ctx-10/fs/proc/array.c linux-2.4.18ctx-12/fs/proc/array.c
*** linux-2.4.18ctx-10/fs/proc/array.c	Wed Apr  3 16:41:02 2002
--- linux-2.4.18ctx-12/fs/proc/array.c	Mon Jul  1 00:08:26 2002
***************
*** 297,304 ****
  	buffer = task_cap(task, buffer);
  #ifdef __NR_new_s_context
- 	buffer += sprintf (buffer,"s_context: %d\n",task->s_context);
- 	buffer += sprintf (buffer,"ipv4root: %08x\n",task->ipv4root);
- 	buffer += sprintf (buffer,"ipv4root_bcast: %08x\n",task->ipv4root_bcast);
  	if (task->s_info != NULL){
  		buffer += sprintf (buffer,"ctxticks: %d %ld %d\n"
  			,atomic_read(&task->s_info->ticks),task->counter
--- 297,310 ----
  	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
***************
*** 309,318 ****
  			,task->s_info->initpid);
  	}else{
  		buffer += sprintf (buffer,"ctxticks: none\n");
  		buffer += sprintf (buffer,"ctxflags: none\n");
  		buffer += sprintf (buffer,"initpid: none\n");
  	}
  	buffer += sprintf (buffer,"__NR_new_s_context: %d\n",__NR_new_s_context);
! 	buffer += sprintf (buffer,"__NR_set_ipv4root: %d rev1\n",__NR_set_ipv4root);
  #endif
  #if defined(CONFIG_ARCH_S390)
--- 315,339 ----
  			,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)
diff -rc2P linux-2.4.18ctx-10/include/linux/sched.h linux-2.4.18ctx-12/include/linux/sched.h
*** linux-2.4.18ctx-10/include/linux/sched.h	Wed Apr  3 16:41:02 2002
--- linux-2.4.18ctx-12/include/linux/sched.h	Tue Jul  2 12:15:42 2002
***************
*** 292,299 ****
  					/* context */
  
  
  struct context_info{
  	int refcount;
! 	int s_context;
  	char nodename[65];
  	char domainname[65];
--- 292,302 ----
  					/* 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];
***************
*** 305,308 ****
--- 308,322 ----
  };
  
+ 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;
***************
*** 434,440 ****
  			/* with the same s_context */
  	__u32 cap_bset;	/* Maximum capability of this process and children */
- 	__u32 ipv4root;	/* Process can only bind to this iP */
- 	__u32 ipv4root_bcast;
  	struct context_info *s_info;
  	void *notifier_data;
  	sigset_t *notifier_mask;
--- 448,453 ----
  			/* 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;
***************
*** 970,973 ****
--- 983,989 ----
  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.18ctx-10/include/net/route.h linux-2.4.18ctx-12/include/net/route.h
*** linux-2.4.18ctx-10/include/net/route.h	Wed Apr  3 16:45:16 2002
--- linux-2.4.18ctx-12/include/net/route.h	Tue Jul  2 12:17:34 2002
***************
*** 161,172 ****
  {
  	int err;
! 	if (current->ipv4root != 0){
! 		if (src == 0){
! 			src = current->ipv4root;
! 		}else if (current->ipv4root != src){
! 			return -EPERM;
! 		}
! 		if (dst == 0x0100007f && current->s_context != 0){
! 			dst = current->ipv4root;
  		}
  	}
--- 161,176 ----
  {
  	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;
! 			}
  		}
  	}
diff -rc2P linux-2.4.18ctx-10/kernel/exit.c linux-2.4.18ctx-12/kernel/exit.c
*** linux-2.4.18ctx-10/kernel/exit.c	Wed Feb 27 14:45:32 2002
--- linux-2.4.18ctx-12/kernel/exit.c	Sun Jun 30 07:10:45 2002
***************
*** 67,70 ****
--- 67,71 ----
  			current->counter = MAX_COUNTER;
  		sys_release_s_info(p);
+ 		sys_release_ip_info(p);
  		p->pid = 0;
  		free_task_struct(p);
diff -rc2P linux-2.4.18ctx-10/kernel/fork.c linux-2.4.18ctx-12/kernel/fork.c
*** linux-2.4.18ctx-10/kernel/fork.c	Wed Feb 27 14:48:50 2002
--- linux-2.4.18ctx-12/kernel/fork.c	Sun Jun 30 07:11:23 2002
***************
*** 604,607 ****
--- 604,608 ----
  
  	sys_assign_s_info (p);
+ 	sys_assign_ip_info (p);
  
  	atomic_inc(&p->user->__count);
diff -rc2P linux-2.4.18ctx-10/kernel/sys.c linux-2.4.18ctx-12/kernel/sys.c
*** linux-2.4.18ctx-10/kernel/sys.c	Tue Feb 26 22:31:23 2002
--- linux-2.4.18ctx-12/kernel/sys.c	Sun Jun 30 23:44:14 2002
***************
*** 1068,1088 ****
  {
  	struct context_info *s_info = vmalloc(sizeof(struct context_info));
! 	// printk ("new s_info %d\n",current->pid);
! 	s_info->s_context = current->s_context;
! 	s_info->refcount = 1;
! 	atomic_set (&s_info->ticks,current->counter);
! 	s_info->flags = 0;
! 	s_info->initpid = 0;
! 	down_read (&uts_sem);
! 	if (current->s_info != NULL){
! 		strcpy (s_info->nodename,current->s_info->nodename);
! 		strcpy (s_info->domainname,current->s_info->domainname);
! 	}else{
! 		strcpy (s_info->nodename,system_utsname.nodename);
! 		strcpy (s_info->domainname,system_utsname.domainname);
  	}
! 	up_read (&uts_sem);
! 	sys_release_s_info (current);	
! 	current->s_info = s_info;
  }
  
--- 1068,1131 ----
  {
  	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;
  }
  
diff -rc2P linux-2.4.18ctx-10/net/ipv4/af_inet.c linux-2.4.18ctx-12/net/ipv4/af_inet.c
*** linux-2.4.18ctx-10/net/ipv4/af_inet.c	Mon Mar 18 12:26:22 2002
--- linux-2.4.18ctx-12/net/ipv4/af_inet.c	Sun Jun 30 11:47:55 2002
***************
*** 482,485 ****
--- 482,486 ----
  	__u32 s_addr;
  	__u32 bcast_addr = 0xffffffffl;
+ 	__u32 ipv4root;
  
  	/* If the socket has its own bind function then use it. (RAW) */
***************
*** 491,507 ****
  
  	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;
! 			bcast_addr = current->ipv4root_bcast;
  		}else if (s_addr == 0x0100007f){
! 			s_addr = current->ipv4root;
! 		}else if (s_addr != current->ipv4root){
! 			return -EADDRNOTAVAIL;
  		}
  	}
  	chk_addr_ret = inet_addr_type(s_addr);
! 	// printk ("ipv4root %08lx %08x %d\n",current->ipv4root,s_addr,chk_addr_ret);
  
  	/* Not specified by any standard per-se, however it breaks too
--- 492,518 ----
  
  	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
diff -rc2P linux-2.4.18ctx-10/net/ipv4/devinet.c linux-2.4.18ctx-12/net/ipv4/devinet.c
*** linux-2.4.18ctx-10/net/ipv4/devinet.c	Tue Feb 26 22:31:23 2002
--- linux-2.4.18ctx-12/net/ipv4/devinet.c	Mon Jul  1 00:06:39 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)
***************
*** 560,566 ****
  	}
  	if (ifa != NULL
! 		&& current->s_context != 0
! 		&& current->ipv4root != 0
! 		&& current->ipv4root != ifa->ifa_local){
  		ret = -EADDRNOTAVAIL;
  		goto done;
--- 586,590 ----
  	}
  	if (ifa != NULL
! 		&& devinet_notiproot (ifa)){
  		ret = -EADDRNOTAVAIL;
  		goto done;
***************
*** 699,705 ****
  	for ( ; ifa; ifa = ifa->ifa_next) {
  		// We do not show other IP devices to vservers
! 		if (current->s_context != 0
! 			&& current->ipv4root != 0
! 			&& current->ipv4root != ifa->ifa_local) continue;
  		if (!buf) {
  			done += sizeof(ifr);
--- 723,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);
***************
*** 919,925 ****
  		for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
  		     ifa = ifa->ifa_next, ip_idx++) {
! 			if (current->s_context != 0
! 				&& current->ipv4root != 0
! 				&& current->ipv4root != ifa->ifa_local) continue;
  			if (ip_idx < s_ip_idx)
  				continue;
--- 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.18ctx-10/net/socket.c linux-2.4.18ctx-12/net/socket.c
*** linux-2.4.18ctx-10/net/socket.c	Wed Apr  3 16:41:02 2002
--- linux-2.4.18ctx-12/net/socket.c	Sun Jun 30 15:22:04 2002
***************
*** 1765,1776 ****
  }
  
! asmlinkage int sys_set_ipv4root (__u32 ip, __u32 bcast)
  {
  	int ret = -EPERM;
! 	if (current->ipv4root == 0
! 		|| capable(CAP_SYS_ADMIN)){
  		ret = 0;
! 		current->ipv4root = ip;
! 		current->ipv4root_bcast = bcast;
  	}
  	return ret;
--- 1765,1808 ----
  }
  
! 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;