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;