diff -rc2P linux-2.4.17ctx-7/Makefile linux-2.4.17ctx-8/Makefile
*** linux-2.4.17ctx-7/Makefile  Wed Feb  6 15:28:08 2002
--- linux-2.4.17ctx-8/Makefile  Wed Feb  6 15:52:50 2002
***************
*** 2,6 ****
 PATCHLEVEL = 4
 SUBLEVEL = 17
! EXTRAVERSION =ctx-7

 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
--- 2,6 ----
 PATCHLEVEL = 4
 SUBLEVEL = 17
! EXTRAVERSION =ctx-8

 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff -rc2P linux-2.4.17ctx-7/fs/proc/array.c linux-2.4.17ctx-8/fs/proc/array.c
*** linux-2.4.17ctx-7/fs/proc/array.c   Wed Feb  6 12:33:49 2002
--- linux-2.4.17ctx-8/fs/proc/array.c   Thu Feb  7 23:15:24 2002
***************
*** 76,79 ****
--- 76,80 ----
 #include <asm/io.h>
 #include <asm/processor.h>
+ #include <asm/unistd.h>

 /* Gcc optimizes away "strlen(x)" for constant x */
***************
*** 298,302 ****
       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);
--- 299,303 ----
       buffer += sprintf (buffer,"ipv4root: %08lx\n",task->ipv4root);
       if (task->s_info != NULL){
!               buffer += sprintf (buffer,"ctxticks: %d %ld %d\n"
                       ,atomic_read(&task->s_info->ticks),task->counter
                       ,task->s_info->refcount);
***************
*** 310,313 ****
--- 311,316 ----
               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\n",__NR_set_ipv4root);
 #if defined(CONFIG_ARCH_S390)
       buffer = task_show_regs(task, buffer);
diff -rc2P linux-2.4.17ctx-7/include/linux/sched.h linux-2.4.17ctx-8/include/linux/sched.h
*** linux-2.4.17ctx-7/include/linux/sched.h     Wed Feb  6 13:31:58 2002
--- linux-2.4.17ctx-8/include/linux/sched.h     Wed Feb 20 20:39:33 2002
***************
*** 269,272 ****
--- 269,273 ----
       struct user_struct *next, **pprev;
       uid_t uid;
+       int s_context;
 };

***************
*** 602,606 ****

 /* per-UID process charging. */
! extern struct user_struct * alloc_uid(uid_t);
 extern void free_uid(struct user_struct *);

--- 603,607 ----

 /* per-UID process charging. */
! extern struct user_struct * alloc_uid(int, uid_t);
 extern void free_uid(struct user_struct *);

diff -rc2P linux-2.4.17ctx-7/include/net/route.h linux-2.4.17ctx-8/include/net/route.h
*** linux-2.4.17ctx-7/include/net/route.h       Wed Feb  6 13:33:57 2002
--- linux-2.4.17ctx-8/include/net/route.h       Wed Feb 20 20:49:58 2002
***************
*** 166,169 ****
--- 166,172 ----
                       return -EPERM;
               }
+               if (dst == 0x0100007f && current->s_context != 0){
+                       dst = current->ipv4root;
+               }
       }
       err = ip_route_output(rp, dst, src, tos, oif);
diff -rc2P linux-2.4.17ctx-7/include/net/sock.h linux-2.4.17ctx-8/include/net/sock.h
*** linux-2.4.17ctx-7/include/net/sock.h        Wed Feb  6 13:33:57 2002
--- linux-2.4.17ctx-8/include/net/sock.h        Thu Feb 21 14:42:39 2002
***************
*** 669,673 ****
       /* RPC layer private data */
       void                    *user_data;
!
       /* Callbacks */
       void                    (*state_change)(struct sock *sk);
--- 669,676 ----
       /* RPC layer private data */
       void                    *user_data;
!
!       /* Context of process creating this socket */
!       int                     s_context;
!
       /* Callbacks */
       void                    (*state_change)(struct sock *sk);
diff -rc2P linux-2.4.17ctx-7/include/net/tcp.h linux-2.4.17ctx-8/include/net/tcp.h
*** linux-2.4.17ctx-7/include/net/tcp.h Wed Feb  6 13:40:14 2002
--- linux-2.4.17ctx-8/include/net/tcp.h Thu Feb 21 14:52:49 2002
***************
*** 191,194 ****
--- 191,195 ----
       struct in6_addr         v6_rcv_saddr;
 #endif
+       int                     s_context;
 };

diff -rc2P linux-2.4.17ctx-7/kernel/signal.c linux-2.4.17ctx-8/kernel/signal.c
*** linux-2.4.17ctx-7/kernel/signal.c   Wed Jan  9 14:18:51 2002
--- linux-2.4.17ctx-8/kernel/signal.c   Wed Feb 20 20:43:06 2002
***************
*** 1291,1294 ****
--- 1291,1313 ----
 }

+ static inline int switch_user_struct(int new_context)
+ {
+       struct user_struct *new_user;
+
+       new_user = alloc_uid(new_context, current->uid);
+       if (!new_user)
+               return -ENOMEM;
+
+       if (new_user != current->user) {
+               struct user_struct *old_user = current->user;
+
+               atomic_inc(&new_user->processes);
+               atomic_dec(&old_user->processes);
+               current->user = new_user;
+               free_uid(old_user);
+       }
+       return 0;
+ }
+
 /*
       Change to a new security context and reduce the capability
***************
*** 1330,1340 ****
                               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){
!                               set_initpid (flags);
!                               current->s_info->flags |= flags;
                       }
                       spin_unlock(&alloc_ctx_lock);
--- 1349,1362 ----
                               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);
***************
*** 1380,1391 ****
               }
               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;
                       }
               }
--- 1402,1416 ----
               }
               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;
!                               }
                       }
               }
diff -rc2P linux-2.4.17ctx-7/kernel/sys.c linux-2.4.17ctx-8/kernel/sys.c
*** linux-2.4.17ctx-7/kernel/sys.c      Wed Jan  9 14:09:08 2002
--- linux-2.4.17ctx-8/kernel/sys.c      Wed Feb 20 20:39:33 2002
***************
*** 501,505 ****
        * we should be checking for it.  -DaveM
        */
!       new_user = alloc_uid(new_ruid);
       if (!new_user)
               return -EAGAIN;
--- 501,505 ----
        * we should be checking for it.  -DaveM
        */
!       new_user = alloc_uid(current->s_context, new_ruid);
       if (!new_user)
               return -EAGAIN;
diff -rc2P linux-2.4.17ctx-7/kernel/user.c linux-2.4.17ctx-8/kernel/user.c
*** linux-2.4.17ctx-7/kernel/user.c     Wed Nov 29 01:43:39 2000
--- linux-2.4.17ctx-8/kernel/user.c     Wed Feb 20 20:39:33 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 [email protected])
+  *
+  * NOTE: For now, the hash function is unmodified: the same uid in several
+  * security contexts, will always sit on the same hash chain. This could
+  * be changed easily.
  */

***************
*** 57,61 ****
 }

! static inline struct user_struct *uid_hash_find(uid_t uid, struct user_struct **hashent)
 {
       struct user_struct *next;
--- 70,74 ----
 }

! static inline struct user_struct *uid_hash_find(int s_context, uid_t uid, struct user_struct **hashent)
 {
       struct user_struct *next;
***************
*** 66,70 ****
               if (next) {
                       next = up->next;
!                       if (up->uid != uid)
                               continue;
                       atomic_inc(&up->__count);
--- 79,83 ----
               if (next) {
                       next = up->next;
!                       if (up->uid != uid || up->s_context != s_context)
                               continue;
                       atomic_inc(&up->__count);
***************
*** 83,87 ****
 }

! struct user_struct * alloc_uid(uid_t uid)
 {
       struct user_struct **hashent = uidhashentry(uid);
--- 96,100 ----
 }

! struct user_struct * alloc_uid(int s_context, uid_t uid)
 {
       struct user_struct **hashent = uidhashentry(uid);
***************
*** 89,93 ****

       spin_lock(&uidhash_lock);
!       up = uid_hash_find(uid, hashent);
       spin_unlock(&uidhash_lock);

--- 102,106 ----

       spin_lock(&uidhash_lock);
!       up = uid_hash_find(s_context, uid, hashent);
       spin_unlock(&uidhash_lock);

***************
*** 99,102 ****
--- 112,116 ----
                       return NULL;
               new->uid = uid;
+               new->s_context = s_context;
               atomic_set(&new->__count, 1);
               atomic_set(&new->processes, 0);
***************
*** 108,112 ****
                */
               spin_lock(&uidhash_lock);
!               up = uid_hash_find(uid, hashent);
               if (up) {
                       kmem_cache_free(uid_cachep, new);
--- 122,126 ----
                */
               spin_lock(&uidhash_lock);
!               up = uid_hash_find(s_context, uid, hashent);
               if (up) {
                       kmem_cache_free(uid_cachep, new);
diff -rc2P linux-2.4.17ctx-7/net/ipv4/af_inet.c linux-2.4.17ctx-8/net/ipv4/af_inet.c
*** linux-2.4.17ctx-7/net/ipv4/af_inet.c        Sat Dec 22 22:52:48 2001
--- linux-2.4.17ctx-8/net/ipv4/af_inet.c        Thu Feb 21 14:42:39 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);
***************
*** 490,494 ****
       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){
--- 492,496 ----
       if (current->ipv4root != 0){
               // printk ("ipv4root0 %08lx %08x\n",current->ipv4root,s_addr);
!               if (s_addr == 0 || s_addr == 0x0100007f){
                       s_addr = current->ipv4root;
               }else if (s_addr != current->ipv4root){
diff -rc2P linux-2.4.17ctx-7/net/ipv4/devinet.c linux-2.4.17ctx-8/net/ipv4/devinet.c
*** linux-2.4.17ctx-7/net/ipv4/devinet.c        Thu Jan 31 14:37:27 2002
--- linux-2.4.17ctx-8/net/ipv4/devinet.c        Wed Feb 13 13:33:31 2002
***************
*** 919,922 ****
--- 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;
diff -rc2P linux-2.4.17ctx-7/net/ipv4/raw.c linux-2.4.17ctx-8/net/ipv4/raw.c
*** linux-2.4.17ctx-7/net/ipv4/raw.c    Tue Jul 10 19:11:43 2001
--- linux-2.4.17ctx-8/net/ipv4/raw.c    Thu Feb 21 14:42:39 2002
***************
*** 658,662 ****

               for (sk = raw_v4_htable[i]; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET)
                               continue;
                       pos += 128;
--- 658,662 ----

               for (sk = raw_v4_htable[i]; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET || (current->s_context != 1 && sk->s_context != current->s_context))
                               continue;
                       pos += 128;
diff -rc2P linux-2.4.17ctx-7/net/ipv4/tcp_ipv4.c linux-2.4.17ctx-8/net/ipv4/tcp_ipv4.c
*** linux-2.4.17ctx-7/net/ipv4/tcp_ipv4.c       Sat Dec 22 22:38:46 2001
--- linux-2.4.17ctx-8/net/ipv4/tcp_ipv4.c       Thu Feb 21 14:42:39 2002
***************
*** 2074,2077 ****
--- 2074,2080 ----
                       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;
***************
*** 2127,2131 ****
               read_lock(&head->lock);
               for(sk = head->chain; sk; sk = sk->next, num++) {
!                       if (!TCP_INET_FAMILY(sk->family))
                               continue;
                       pos += TMPSZ;
--- 2130,2134 ----
               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;
***************
*** 2142,2146 ****
                    tw != NULL;
                    tw = (struct tcp_tw_bucket *)tw->next, num++) {
!                       if (!TCP_INET_FAMILY(tw->family))
                               continue;
                       pos += TMPSZ;
--- 2145,2149 ----
                    tw != NULL;
                    tw = (struct tcp_tw_bucket *)tw->next, num++) {
!                       if (!TCP_INET_FAMILY(tw->family) || (current->s_context != 1 && tw->s_context != current->s_context))
                               continue;
                       pos += TMPSZ;
diff -rc2P linux-2.4.17ctx-7/net/ipv4/tcp_minisocks.c linux-2.4.17ctx-8/net/ipv4/tcp_minisocks.c
*** linux-2.4.17ctx-7/net/ipv4/tcp_minisocks.c  Wed Oct 10 11:58:23 2001
--- linux-2.4.17ctx-8/net/ipv4/tcp_minisocks.c  Thu Feb 21 14:42:39 2002
***************
*** 382,385 ****
--- 382,387 ----
               tw->pprev_death = NULL;

+               tw->s_context   = sk->s_context;
+
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
               if(tw->family == PF_INET6) {
diff -rc2P linux-2.4.17ctx-7/net/ipv4/udp.c linux-2.4.17ctx-8/net/ipv4/udp.c
*** linux-2.4.17ctx-7/net/ipv4/udp.c    Wed Oct 31 15:32:46 2001
--- linux-2.4.17ctx-8/net/ipv4/udp.c    Thu Feb 21 14:42:39 2002
***************
*** 984,988 ****

               for (sk = udp_hash[i]; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET)
                               continue;
                       pos += 128;
--- 984,988 ----

               for (sk = udp_hash[i]; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET || (current->s_context != 1 && sk->s_context != current->s_context))
                               continue;
                       pos += 128;
diff -rc2P linux-2.4.17ctx-7/net/ipv6/raw.c linux-2.4.17ctx-8/net/ipv6/raw.c
*** linux-2.4.17ctx-7/net/ipv6/raw.c    Thu Sep 20 17:12:56 2001
--- linux-2.4.17ctx-8/net/ipv6/raw.c    Thu Feb 21 14:42:39 2002
***************
*** 798,802 ****

               for (sk = raw_v6_htable[i]; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET6)
                               continue;
                       pos += LINE_LEN+1;
--- 798,802 ----

               for (sk = raw_v6_htable[i]; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET6 || (current->s_context != 1 && sk->s_context != current->s_context))
                               continue;
                       pos += LINE_LEN+1;
diff -rc2P linux-2.4.17ctx-7/net/ipv6/tcp_ipv6.c linux-2.4.17ctx-8/net/ipv6/tcp_ipv6.c
*** linux-2.4.17ctx-7/net/ipv6/tcp_ipv6.c       Sat Dec 22 22:38:46 2001
--- linux-2.4.17ctx-8/net/ipv6/tcp_ipv6.c       Thu Feb 21 14:42:39 2002
***************
*** 2006,2010 ****
                       struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);

!                       if (sk->family != PF_INET6)
                               continue;
                       pos += LINE_LEN+1;
--- 2006,2010 ----
                       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;
***************
*** 2056,2060 ****
               read_lock(&head->lock);
               for(sk = head->chain; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET6)
                               continue;
                       pos += LINE_LEN+1;
--- 2056,2060 ----
               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;
***************
*** 2071,2075 ****
                    tw != NULL;
                    tw = (struct tcp_tw_bucket *)tw->next, num++) {
!                       if (tw->family != PF_INET6)
                               continue;
                       pos += LINE_LEN+1;
--- 2071,2075 ----
                    tw != NULL;
                    tw = (struct tcp_tw_bucket *)tw->next, num++) {
!                       if (tw->family != PF_INET6 || (current->s_context != 1 && tw->s_context != current->s_context))
                               continue;
                       pos += LINE_LEN+1;
diff -rc2P linux-2.4.17ctx-7/net/ipv6/udp.c linux-2.4.17ctx-8/net/ipv6/udp.c
*** linux-2.4.17ctx-7/net/ipv6/udp.c    Fri Sep  7 14:01:21 2001
--- linux-2.4.17ctx-8/net/ipv6/udp.c    Thu Feb 21 14:42:39 2002
***************
*** 953,957 ****

               for (sk = udp_hash[i]; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET6)
                               continue;
                       pos += LINE_LEN+1;
--- 953,957 ----

               for (sk = udp_hash[i]; sk; sk = sk->next, num++) {
!                       if (sk->family != PF_INET6 || (current->s_context != 1 && sk->s_context != current->s_context))
                               continue;
                       pos += LINE_LEN+1;
diff -rc2P linux-2.4.17ctx-7/net/unix/af_unix.c linux-2.4.17ctx-8/net/unix/af_unix.c
*** linux-2.4.17ctx-7/net/unix/af_unix.c        Sat Dec 22 22:38:47 2001
--- linux-2.4.17ctx-8/net/unix/af_unix.c        Thu Feb 21 14:42:39 2002
***************
*** 479,482 ****
--- 479,484 ----
       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;
***************
*** 1741,1744 ****
--- 1743,1749 ----
       forall_unix_sockets (i,s)
       {
+               if (current->s_context != 1 && s->s_context != current->s_context)
+                       continue;
+
               unix_state_rlock(s);