diff -rc2P linux-2.4.13/Makefile linux-2.4.13-ctx-3/Makefile
*** linux-2.4.13/Makefile       Wed Oct 31 15:32:24 2001
--- linux-2.4.13-ctx-3/Makefile Wed Nov  7 16:56:29 2001
***************
*** 2,6 ****
 PATCHLEVEL = 4
 SUBLEVEL = 13
! EXTRAVERSION =

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

 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff -rc2P linux-2.4.13/arch/i386/kernel/entry.S linux-2.4.13-ctx-3/arch/i386/kernel/entry.S
*** linux-2.4.13/arch/i386/kernel/entry.S       Wed Oct 31 15:32:24 2001
--- linux-2.4.13-ctx-3/arch/i386/kernel/entry.S Wed Oct 31 16:11:22 2001
***************
*** 623,626 ****
--- 623,628 ----
       .long SYMBOL_NAME(sys_gettid)
       .long SYMBOL_NAME(sys_readahead)        /* 225 */
+       .long SYMBOL_NAME(sys_new_s_context)
+       .long SYMBOL_NAME(sys_set_ipv4root)

       .rept NR_syscalls-(.-sys_call_table)/4
diff -rc2P linux-2.4.13/arch/i386/kernel/ptrace.c linux-2.4.13-ctx-3/arch/i386/kernel/ptrace.c
*** linux-2.4.13/arch/i386/kernel/ptrace.c      Tue Sep 18 20:04:23 2001
--- linux-2.4.13-ctx-3/arch/i386/kernel/ptrace.c        Wed Oct 31 16:05:00 2001
***************
*** 171,175 ****
               get_task_struct(child);
       read_unlock(&tasklist_lock);
!       if (!child)
               goto out;

--- 171,175 ----
               get_task_struct(child);
       read_unlock(&tasklist_lock);
!       if (!child || child->s_context != current->s_context)
               goto out;

diff -rc2P linux-2.4.13/fs/exec.c linux-2.4.13-ctx-3/fs/exec.c
*** linux-2.4.13/fs/exec.c      Tue Sep 18 16:39:32 2001
--- linux-2.4.13-ctx-3/fs/exec.c        Wed Oct 31 16:05:00 2001
***************
*** 685,689 ****
       int do_unlock = 0;

!       new_permitted = cap_intersect(bprm->cap_permitted, cap_bset);
       working = cap_intersect(bprm->cap_inheritable,
                               current->cap_inheritable);
--- 685,689 ----
       int do_unlock = 0;

!       new_permitted = cap_intersect(bprm->cap_permitted, current->cap_bset);
       working = cap_intersect(bprm->cap_inheritable,
                               current->cap_inheritable);
diff -rc2P linux-2.4.13/fs/ext2/ialloc.c linux-2.4.13-ctx-3/fs/ext2/ialloc.c
*** linux-2.4.13/fs/ext2/ialloc.c       Wed Oct 10 11:58:19 2001
--- linux-2.4.13-ctx-3/fs/ext2/ialloc.c Mon Nov  5 14:54:21 2001
***************
*** 439,443 ****
       inode->u.ext2_i.i_flags = dir->u.ext2_i.i_flags;
       if (S_ISLNK(mode))
!               inode->u.ext2_i.i_flags &= ~(EXT2_IMMUTABLE_FL | EXT2_APPEND_FL);
       inode->u.ext2_i.i_faddr = 0;
       inode->u.ext2_i.i_frag_no = 0;
--- 439,443 ----
       inode->u.ext2_i.i_flags = dir->u.ext2_i.i_flags;
       if (S_ISLNK(mode))
!               inode->u.ext2_i.i_flags &= ~(EXT2_IMMUTABLE_FILE_FL | EXT2_IMMUTABLE_LINK_FL | EXT2_APPEND_FL);
       inode->u.ext2_i.i_faddr = 0;
       inode->u.ext2_i.i_frag_no = 0;
diff -rc2P linux-2.4.13/fs/ext2/inode.c linux-2.4.13-ctx-3/fs/ext2/inode.c
*** linux-2.4.13/fs/ext2/inode.c        Wed Oct 31 15:32:41 2001
--- linux-2.4.13-ctx-3/fs/ext2/inode.c  Mon Nov  5 14:54:21 2001
***************
*** 797,801 ****
           S_ISLNK(inode->i_mode)))
               return;
!       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
               return;

--- 797,801 ----
           S_ISLNK(inode->i_mode)))
               return;
!       if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode))
               return;

***************
*** 1003,1009 ****
               inode->i_flags |= S_APPEND;
       }
!       if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL) {
!               inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE;
!               inode->i_flags |= S_IMMUTABLE;
       }
       if (inode->u.ext2_i.i_flags & EXT2_NOATIME_FL) {
--- 1003,1013 ----
               inode->i_flags |= S_APPEND;
       }
!       if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FILE_FL) {
!               inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE_FILE;
!               inode->i_flags |= S_IMMUTABLE_FILE;
!       }
!       if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_LINK_FL) {
!               inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE_LINK;
!               inode->i_flags |= S_IMMUTABLE_LINK;
       }
       if (inode->u.ext2_i.i_flags & EXT2_NOATIME_FL) {
diff -rc2P linux-2.4.13/fs/ext2/ioctl.c linux-2.4.13-ctx-3/fs/ext2/ioctl.c
*** linux-2.4.13/fs/ext2/ioctl.c        Wed Sep 27 16:41:33 2000
--- linux-2.4.13-ctx-3/fs/ext2/ioctl.c  Mon Nov  5 14:54:21 2001
***************
*** 45,49 ****
                * This test looks nicer. Thanks to Pauline Middelink
                */
!               if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) {
                       if (!capable(CAP_LINUX_IMMUTABLE))
                               return -EPERM;
--- 45,49 ----
                * This test looks nicer. Thanks to Pauline Middelink
                */
!               if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FILE_FL | EXT2_IMMUTABLE_LINK_FL)) {
                       if (!capable(CAP_LINUX_IMMUTABLE))
                               return -EPERM;
***************
*** 62,69 ****
               else
                       inode->i_flags &= ~S_APPEND;
!               if (flags & EXT2_IMMUTABLE_FL)
!                       inode->i_flags |= S_IMMUTABLE;
               else
!                       inode->i_flags &= ~S_IMMUTABLE;
               if (flags & EXT2_NOATIME_FL)
                       inode->i_flags |= S_NOATIME;
--- 62,76 ----
               else
                       inode->i_flags &= ~S_APPEND;
!
!               if (flags & EXT2_IMMUTABLE_FILE_FL)
!                       inode->i_flags |= S_IMMUTABLE_FILE;
!               else
!                       inode->i_flags &= ~S_IMMUTABLE_FILE;
!
!               if (flags & EXT2_IMMUTABLE_LINK_FL)
!                       inode->i_flags |= S_IMMUTABLE_LINK;
               else
!                       inode->i_flags &= ~S_IMMUTABLE_LINK;
!
               if (flags & EXT2_NOATIME_FL)
                       inode->i_flags |= S_NOATIME;
diff -rc2P linux-2.4.13/fs/fat/file.c linux-2.4.13-ctx-3/fs/fat/file.c
*** linux-2.4.13/fs/fat/file.c  Sun Aug 12 13:56:56 2001
--- linux-2.4.13-ctx-3/fs/fat/file.c    Mon Nov  5 14:54:21 2001
***************
*** 120,124 ****
       if (IS_RDONLY (inode))
               return /* -EPERM */;
!       if (IS_IMMUTABLE(inode))
               return /* -EPERM */;
       cluster = 1 << sbi->cluster_bits;
--- 120,124 ----
       if (IS_RDONLY (inode))
               return /* -EPERM */;
!       if (IS_IMMUTABLE_FILE(inode))
               return /* -EPERM */;
       cluster = 1 << sbi->cluster_bits;
diff -rc2P linux-2.4.13/fs/fat/inode.c linux-2.4.13-ctx-3/fs/fat/inode.c
*** linux-2.4.13/fs/fat/inode.c Wed Oct 31 15:32:41 2001
--- linux-2.4.13-ctx-3/fs/fat/inode.c   Mon Nov  5 14:54:21 2001
***************
*** 946,950 ****
       if(de->attr & ATTR_SYS)
               if (sbi->options.sys_immutable)
!                       inode->i_flags |= S_IMMUTABLE;
       MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;
       /* this is as close to the truth as we can get ... */
--- 946,950 ----
       if(de->attr & ATTR_SYS)
               if (sbi->options.sys_immutable)
!                       inode->i_flags |= S_IMMUTABLE_FILE;
       MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;
       /* this is as close to the truth as we can get ... */
diff -rc2P linux-2.4.13/fs/hpfs/file.c linux-2.4.13-ctx-3/fs/hpfs/file.c
*** linux-2.4.13/fs/hpfs/file.c Sun Aug 12 20:37:53 2001
--- linux-2.4.13-ctx-3/fs/hpfs/file.c   Mon Nov  5 14:54:21 2001
***************
*** 61,65 ****
 void hpfs_truncate(struct inode *i)
 {
!       if (IS_IMMUTABLE(i)) return /*-EPERM*/;
       i->i_hpfs_n_secs = 0;
       i->i_blocks = 1 + ((i->i_size + 511) >> 9);
--- 61,65 ----
 void hpfs_truncate(struct inode *i)
 {
!       if (IS_IMMUTABLE_FILE(i)) return /*-EPERM*/;
       i->i_hpfs_n_secs = 0;
       i->i_blocks = 1 + ((i->i_size + 511) >> 9);
diff -rc2P linux-2.4.13/fs/namei.c linux-2.4.13-ctx-3/fs/namei.c
*** linux-2.4.13/fs/namei.c     Wed Oct 31 15:32:41 2001
--- linux-2.4.13-ctx-3/fs/namei.c       Mon Nov  5 14:54:21 2001
***************
*** 163,167 ****
                * Nobody gets write access to an immutable file.
                */
!               if (IS_IMMUTABLE(inode))
                       return -EACCES;
       }
--- 163,167 ----
                * Nobody gets write access to an immutable file.
                */
!               if (IS_IMMUTABLE_FILE(inode))
                       return -EACCES;
       }
***************
*** 878,883 ****
       if (IS_APPEND(dir))
               return -EPERM;
!       if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||
!           IS_IMMUTABLE(victim->d_inode))
               return -EPERM;
       if (isdir) {
--- 878,882 ----
       if (IS_APPEND(dir))
               return -EPERM;
!       if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||IS_IMMUTABLE_LINK(victim->d_inode))
               return -EPERM;
       if (isdir) {
***************
*** 1595,1599 ****
        */
       error = -EPERM;
!       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
               goto exit_lock;
       if (!dir->i_op || !dir->i_op->link)
--- 1594,1598 ----
        */
       error = -EPERM;
!       if (IS_APPEND(inode) || IS_IMMUTABLE_LINK(inode))
               goto exit_lock;
       if (!dir->i_op || !dir->i_op->link)
diff -rc2P linux-2.4.13/fs/nfsd/vfs.c linux-2.4.13-ctx-3/fs/nfsd/vfs.c
*** linux-2.4.13/fs/nfsd/vfs.c  Wed Oct 10 11:58:19 2001
--- linux-2.4.13-ctx-3/fs/nfsd/vfs.c    Mon Nov  5 14:54:21 2001
***************
*** 1481,1485 ****
               return 0;
 #if 0
!       dprintk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s\n",
               acc,
               (acc & MAY_READ)?       " read"  : "",
--- 1481,1485 ----
               return 0;
 #if 0
!       dprintk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s%s\n",
               acc,
               (acc & MAY_READ)?       " read"  : "",
***************
*** 1491,1495 ****
               (acc & MAY_OWNER_OVERRIDE)? " owneroverride" : "",
               inode->i_mode,
!               IS_IMMUTABLE(inode)?    " immut" : "",
               IS_APPEND(inode)?       " append" : "",
               IS_RDONLY(inode)?       " ro" : "");
--- 1491,1496 ----
               (acc & MAY_OWNER_OVERRIDE)? " owneroverride" : "",
               inode->i_mode,
!               IS_IMMUTABLE_FILE(inode)? " immut(F)" : "",
!               IS_IMMUTABLE_LINK(inode)? " immut(L)" : "",
               IS_APPEND(inode)?       " append" : "",
               IS_RDONLY(inode)?       " ro" : "");
***************
*** 1506,1510 ****
                       if (EX_RDONLY(exp) || IS_RDONLY(inode))
                               return nfserr_rofs;
!                       if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
                               return nfserr_perm;
               }
--- 1507,1511 ----
                       if (EX_RDONLY(exp) || IS_RDONLY(inode))
                               return nfserr_rofs;
!                       if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE_FILE(inode))
                               return nfserr_perm;
               }
diff -rc2P linux-2.4.13/fs/open.c linux-2.4.13-ctx-3/fs/open.c
*** linux-2.4.13/fs/open.c      Wed Oct 31 15:32:41 2001
--- linux-2.4.13-ctx-3/fs/open.c        Mon Nov  5 15:07:36 2001
***************
*** 123,127 ****

       error = -EPERM;
!       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
               goto dput_and_out;

--- 123,127 ----

       error = -EPERM;
!       if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode))
               goto dput_and_out;

***************
*** 471,475 ****
               goto out_putf;
       err = -EPERM;
!       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
               goto out_putf;
       if (mode == (mode_t) -1)
--- 471,475 ----
               goto out_putf;
       err = -EPERM;
!       if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode))
               goto out_putf;
       if (mode == (mode_t) -1)
***************
*** 502,506 ****

       error = -EPERM;
!       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
               goto dput_and_out;

--- 502,506 ----

       error = -EPERM;
!       if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode))
               goto dput_and_out;

***************
*** 532,536 ****
               goto out;
       error = -EPERM;
!       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
               goto out;
       if (user == (uid_t) -1)
--- 532,536 ----
               goto out;
       error = -EPERM;
!       if (IS_IMMUTABLE_FILE(inode) || IS_APPEND(inode))
               goto out;
       if (user == (uid_t) -1)
diff -rc2P linux-2.4.13/fs/proc/array.c linux-2.4.13-ctx-3/fs/proc/array.c
*** linux-2.4.13/fs/proc/array.c        Wed Oct 31 15:32:41 2001
--- linux-2.4.13-ctx-3/fs/proc/array.c  Wed Oct 31 16:05:00 2001
***************
*** 264,271 ****
     return buffer + sprintf(buffer, "CapInh:\t%016x\n"
                           "CapPrm:\t%016x\n"
!                           "CapEff:\t%016x\n",
                           cap_t(p->cap_inheritable),
                           cap_t(p->cap_permitted),
!                           cap_t(p->cap_effective));
 }

--- 264,273 ----
     return buffer + sprintf(buffer, "CapInh:\t%016x\n"
                           "CapPrm:\t%016x\n"
!                           "CapEff:\t%016x\n"
!                           "CapBset:\t%016x\n",
                           cap_t(p->cap_inheritable),
                           cap_t(p->cap_permitted),
!                           cap_t(p->cap_effective),
!                           cap_t(p->cap_bset));
 }

***************
*** 289,292 ****
--- 291,306 ----
       buffer = task_sig(task, buffer);
       buffer = task_cap(task, buffer);
+       buffer += sprintf (buffer,"s_context: %d\n",task->s_context);
+       buffer += sprintf (buffer,"ipv4root: %08lx\n",task->ipv4root);
+       if (task->s_info != NULL){
+               buffer += sprintf (buffer,"ctxticks: %d %d %d\n"
+                       ,atomic_read(&task->s_info->ticks),task->counter
+                       ,task->s_info->refcount);
+               buffer += sprintf (buffer,"ctxflags: %d\n"
+                       ,task->s_info->flags);
+       }else{
+               buffer += sprintf (buffer,"ctxticks: none\n");
+               buffer += sprintf (buffer,"ctxflags: none\n");
+       }
 #if defined(CONFIG_ARCH_S390)
       buffer = task_show_regs(task, buffer);
diff -rc2P linux-2.4.13/fs/proc/base.c linux-2.4.13-ctx-3/fs/proc/base.c
*** linux-2.4.13/fs/proc/base.c Tue Oct 16 09:33:55 2001
--- linux-2.4.13-ctx-3/fs/proc/base.c   Mon Nov  5 14:54:21 2001
***************
*** 977,981 ****
       inode->i_fop = &proc_base_operations;
       inode->i_nlink = 3;
!       inode->i_flags|=S_IMMUTABLE;

       dentry->d_op = &pid_base_dentry_operations;
--- 977,981 ----
       inode->i_fop = &proc_base_operations;
       inode->i_nlink = 3;
!       inode->i_flags|=S_IMMUTABLE_FILE;

       dentry->d_op = &pid_base_dentry_operations;
***************
*** 1013,1016 ****
--- 1013,1026 ----
               if (!pid)
                       continue;
+               /* Even if the pid 1 is not part of the security context */
+               /* we show it anyway. This makes the security box */
+               /* more standard (and helps pstree do its job) */
+               /* So current process "knows" pid 1 exist anyway and can't */
+               /* send any signal either */
+
+               /* A process with security context 1 can see all processes */
+               if (pid != 1
+                       && current->s_context != 1
+                       && p->s_context != current->s_context) continue;
               if (--index >= 0)
                       continue;
diff -rc2P linux-2.4.13/fs/udf/inode.c linux-2.4.13-ctx-3/fs/udf/inode.c
*** linux-2.4.13/fs/udf/inode.c Wed Oct 31 15:32:42 2001
--- linux-2.4.13-ctx-3/fs/udf/inode.c   Mon Nov  5 14:54:21 2001
***************
*** 864,868 ****
                       S_ISLNK(inode->i_mode)))
               return;
!       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
               return;

--- 864,868 ----
                       S_ISLNK(inode->i_mode)))
               return;
!       if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode))
               return;

diff -rc2P linux-2.4.13/fs/ufs/truncate.c linux-2.4.13-ctx-3/fs/ufs/truncate.c
*** linux-2.4.13/fs/ufs/truncate.c      Mon Sep 10 12:06:10 2001
--- linux-2.4.13-ctx-3/fs/ufs/truncate.c        Mon Nov  5 14:54:21 2001
***************
*** 443,447 ****
       if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)))
               return;
!       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
               return;
       while (1) {
--- 443,447 ----
       if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)))
               return;
!       if (IS_APPEND(inode) || IS_IMMUTABLE_FILE(inode))
               return;
       while (1) {
diff -rc2P linux-2.4.13/include/asm-i386/unistd.h linux-2.4.13-ctx-3/include/asm-i386/unistd.h
*** linux-2.4.13/include/asm-i386/unistd.h      Wed Oct 31 15:32:43 2001
--- linux-2.4.13-ctx-3/include/asm-i386/unistd.h        Wed Oct 31 16:08:10 2001
***************
*** 231,234 ****
--- 231,236 ----
 #define __NR_gettid           224
 #define __NR_readahead                225
+ #define __NR_new_s_context      226
+ #define __NR_set_ipv4root       227

 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
diff -rc2P linux-2.4.13/include/linux/capability.h linux-2.4.13-ctx-3/include/linux/capability.h
*** linux-2.4.13/include/linux/capability.h     Sun Sep 23 13:31:02 2001
--- linux-2.4.13-ctx-3/include/linux/capability.h       Wed Nov  7 22:00:55 2001
***************
*** 232,235 ****
--- 232,236 ----
    arbitrary SCSI commands */
 /* Allow setting encryption key on loopback filesystem */
+ /* Allow the selection of a security context */

 #define CAP_SYS_ADMIN        21
***************
*** 277,280 ****
--- 278,285 ----

 #define CAP_LEASE            28
+
+ /* Allow opening special device file */
+
+ #define CAP_OPENDEV          29

 #ifdef __KERNEL__
diff -rc2P linux-2.4.13/include/linux/ext2_fs.h linux-2.4.13-ctx-3/include/linux/ext2_fs.h
*** linux-2.4.13/include/linux/ext2_fs.h        Wed Oct 31 15:32:45 2001
--- linux-2.4.13-ctx-3/include/linux/ext2_fs.h  Wed Nov  7 17:01:36 2001
***************
*** 188,192 ****
 #define       EXT2_COMPR_FL                   0x00000004 /* Compress file */
 #define EXT2_SYNC_FL                  0x00000008 /* Synchronous updates */
! #define EXT2_IMMUTABLE_FL             0x00000010 /* Immutable file */
 #define EXT2_APPEND_FL                        0x00000020 /* writes to file may only append */
 #define EXT2_NODUMP_FL                        0x00000040 /* do not dump file */
--- 188,192 ----
 #define       EXT2_COMPR_FL                   0x00000004 /* Compress file */
 #define EXT2_SYNC_FL                  0x00000008 /* Synchronous updates */
! #define EXT2_IMMUTABLE_FILE_FL                0x00000010 /* Immutable file */
 #define EXT2_APPEND_FL                        0x00000020 /* writes to file may only append */
 #define EXT2_NODUMP_FL                        0x00000040 /* do not dump file */
***************
*** 199,206 ****
 /* End compression flags --- maybe not all used */
 #define EXT2_BTREE_FL                 0x00001000 /* btree format dir */
 #define EXT2_RESERVED_FL              0x80000000 /* reserved for ext2 lib */

! #define EXT2_FL_USER_VISIBLE          0x00001FFF /* User visible flags */
! #define EXT2_FL_USER_MODIFIABLE               0x000000FF /* User modifiable flags */

 /*
--- 199,207 ----
 /* End compression flags --- maybe not all used */
 #define EXT2_BTREE_FL                 0x00001000 /* btree format dir */
+ #define EXT2_IMMUTABLE_LINK_FL          0x00008000 /* Immutable link */
 #define EXT2_RESERVED_FL              0x80000000 /* reserved for ext2 lib */

! #define EXT2_FL_USER_VISIBLE          0x00009FFF /* User visible flags */
! #define EXT2_FL_USER_MODIFIABLE               0x000080FF /* User modifiable flags */

 /*
diff -rc2P linux-2.4.13/include/linux/fs.h linux-2.4.13-ctx-3/include/linux/fs.h
*** linux-2.4.13/include/linux/fs.h     Wed Oct 31 15:32:45 2001
--- linux-2.4.13-ctx-3/include/linux/fs.h       Wed Nov  7 22:00:55 2001
***************
*** 127,137 ****
 /* Inode flags - they have nothing to superblock flags now */

! #define S_SYNC                1       /* Writes are synced at once */
! #define S_NOATIME     2       /* Do not update access times */
! #define S_QUOTA               4       /* Quota initialized for file */
! #define S_APPEND      8       /* Append-only file */
! #define S_IMMUTABLE   16      /* Immutable file */
! #define S_DEAD                32      /* removed, but still open directory */
! #define S_NOQUOTA     64      /* Inode is not counted to quota */

 /*
--- 127,138 ----
 /* Inode flags - they have nothing to superblock flags now */

! #define S_SYNC                        1       /* Writes are synced at once */
! #define S_NOATIME             2       /* Do not update access times */
! #define S_QUOTA                       4       /* Quota initialized for file */
! #define S_APPEND              8       /* Append-only file */
! #define S_IMMUTABLE_FILE      16      /* Immutable file */
! #define S_DEAD                        32      /* removed, but still open directory */
! #define S_NOQUOTA             64      /* Inode is not counted to quota */
! #define S_IMMUTABLE_LINK      128     /* Immutable links */

 /*
***************
*** 157,161 ****
 #define IS_NOQUOTA(inode)     ((inode)->i_flags & S_NOQUOTA)
 #define IS_APPEND(inode)      ((inode)->i_flags & S_APPEND)
! #define IS_IMMUTABLE(inode)   ((inode)->i_flags & S_IMMUTABLE)
 #define IS_NOATIME(inode)     (__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME))
 #define IS_NODIRATIME(inode)  __IS_FLG(inode, MS_NODIRATIME)
--- 158,163 ----
 #define IS_NOQUOTA(inode)     ((inode)->i_flags & S_NOQUOTA)
 #define IS_APPEND(inode)      ((inode)->i_flags & S_APPEND)
! #define IS_IMMUTABLE_FILE(inode)      ((inode)->i_flags & S_IMMUTABLE_FILE)
! #define IS_IMMUTABLE_LINK(inode) ((((inode)->i_flags & S_IMMUTABLE_FILE) << 3) ^ ((inode)->i_flags & S_IMMUTABLE_LINK) )
 #define IS_NOATIME(inode)     (__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME))
 #define IS_NODIRATIME(inode)  __IS_FLG(inode, MS_NODIRATIME)
***************
*** 354,362 ****
  * This is the inode attributes flag definitions
  */
! #define ATTR_FLAG_SYNCRONOUS  1       /* Syncronous write */
! #define ATTR_FLAG_NOATIME     2       /* Don't update atime */
! #define ATTR_FLAG_APPEND      4       /* Append-only file */
! #define ATTR_FLAG_IMMUTABLE   8       /* Immutable file */
! #define ATTR_FLAG_NODIRATIME  16      /* Don't update atime for directory */

 /*
--- 356,365 ----
  * This is the inode attributes flag definitions
  */
! #define ATTR_FLAG_SYNCRONOUS          1       /* Syncronous write */
! #define ATTR_FLAG_NOATIME             2       /* Don't update atime */
! #define ATTR_FLAG_APPEND              4       /* Append-only file */
! #define ATTR_FLAG_IMMUTABLE_FILE      8       /* Immutable file */
! #define ATTR_FLAG_NODIRATIME          16      /* Don't update atime for directory */
! #define ATTR_FLAG_IMMUTABLE_LINK      32      /* Immutable file */

 /*
diff -rc2P linux-2.4.13/include/linux/sched.h linux-2.4.13-ctx-3/include/linux/sched.h
*** linux-2.4.13/include/linux/sched.h  Tue Oct 16 09:33:55 2001
--- linux-2.4.13-ctx-3/include/linux/sched.h    Wed Nov  7 22:00:55 2001
***************
*** 276,279 ****
--- 276,299 ----
       __user; })

+
+ /*
+       We may have a different domainname and nodename for each security
+       context. By default, a security context share the same as its
+       parent, potentially the information in system_utsname
+ */
+ #define S_CTX_INFO_LOCK               1       /* Can't request a new s_context */
+ #define S_CTX_INFO_SCHED      2       /* All process in the s_context */
+                                       /* Contribute to the schedular */
+ struct context_info{
+       int refcount;
+       int s_context;
+       char nodename[65];
+       char domainname[65];
+       int flags;              /* S_CTX_INFO_xxx */
+       atomic_t ticks;         /* Number of ticks used by all process */
+                               /* in the s_context */
+ };
+
+
 extern struct user_struct root_user;
 #define INIT_USER (&root_user)
***************
*** 400,403 ****
--- 420,429 ----
 /* Protection of (de-)allocation: mm, files, fs, tty */
       spinlock_t alloc_lock;
+ /* Field to make virtual server running in chroot more  isolated */
+       int s_context;  /* Process can only deal with other processes */
+                       /* with the same s_context */
+       __u32 cap_bset; /* Maximum capability of this process and children */
+       unsigned long ipv4root; /* Process can only bind to this iP */
+       struct context_info *s_info;
 };

***************
*** 486,490 ****
     pending:          { NULL, &tsk.pending.head, {{0}}},              \
     blocked:          {{0}},                                          \
!     alloc_lock:               SPIN_LOCK_UNLOCKED                              \
 }

--- 512,517 ----
     pending:          { NULL, &tsk.pending.head, {{0}}},              \
     blocked:          {{0}},                                          \
!     alloc_lock:               SPIN_LOCK_UNLOCKED,                             \
!     cap_bset:         CAP_INIT_EFF_SET,                               \
 }

***************
*** 899,902 ****
--- 926,934 ----
       return res;
 }
+
+ /* Manage the reference count of the context_info pointer */
+ void sys_release_s_info (struct task_struct *);
+ void sys_assign_s_info (struct task_struct *);
+ void sys_alloc_s_info (void);

 #endif /* __KERNEL__ */
diff -rc2P linux-2.4.13/include/net/route.h linux-2.4.13-ctx-3/include/net/route.h
*** linux-2.4.13/include/net/route.h    Wed Oct 31 15:32:45 2001
--- linux-2.4.13-ctx-3/include/net/route.h      Wed Nov  7 22:02:39 2001
***************
*** 165,168 ****
--- 165,175 ----
 {
       int err;
+       if (current->ipv4root != 0){
+               if (src == 0){
+                       src = current->ipv4root;
+               }else if (current->ipv4root != src){
+                       return -EPERM;
+               }
+       }
       err = ip_route_output(rp, dst, src, tos, oif);
       if (err || (dst && src))
diff -rc2P linux-2.4.13/kernel/exit.c linux-2.4.13-ctx-3/kernel/exit.c
*** linux-2.4.13/kernel/exit.c  Wed Oct 31 15:32:45 2001
--- linux-2.4.13-ctx-3/kernel/exit.c    Wed Oct 31 16:05:00 2001
***************
*** 65,68 ****
--- 65,69 ----
               if (current->counter >= MAX_COUNTER)
                       current->counter = MAX_COUNTER;
+               sys_release_s_info(p);
               p->pid = 0;
               free_task_struct(p);
diff -rc2P linux-2.4.13/kernel/fork.c linux-2.4.13-ctx-3/kernel/fork.c
*** linux-2.4.13/kernel/fork.c  Tue Sep 18 00:46:04 2001
--- linux-2.4.13-ctx-3/kernel/fork.c    Wed Oct 31 16:05:00 2001
***************
*** 584,587 ****
--- 584,588 ----

       *p = *current;
+       sys_assign_s_info (p);

       retval = -EAGAIN;
diff -rc2P linux-2.4.13/kernel/sched.c linux-2.4.13-ctx-3/kernel/sched.c
*** linux-2.4.13/kernel/sched.c Wed Oct 31 15:32:46 2001
--- linux-2.4.13-ctx-3/kernel/sched.c   Wed Oct 31 16:05:00 2001
***************
*** 165,169 ****
                * over..
                */
!               weight = p->counter;
               if (!weight)
                       goto out;
--- 165,175 ----
                * over..
                */
!               if (p->s_info != NULL
!                       && (p->s_info->flags & S_CTX_INFO_SCHED)!=0){
!                       weight = atomic_read (&p->s_info->ticks)/p->s_info->refcount;
!                       weight = (weight+p->counter)>>1;
!               }else{
!                       weight = p->counter;
!               }
               if (!weight)
                       goto out;
***************
*** 687,692 ****
               spin_unlock_irq(&runqueue_lock);
               read_lock(&tasklist_lock);
!               for_each_task(p)
                       p->counter = (p->counter >> 1) + NICE_TO_TICKS(p->nice);
               read_unlock(&tasklist_lock);
               spin_lock_irq(&runqueue_lock);
--- 693,713 ----
               spin_unlock_irq(&runqueue_lock);
               read_lock(&tasklist_lock);
!               /*
!                       Reset the s_info->ticks to the sum off all
!                       member processes p->counter
!               */
!               for_each_task(p){
!                       if (p->s_info != NULL
!                               && (p->s_info->flags & S_CTX_INFO_SCHED)!=0){
!                               atomic_set (&p->s_info->ticks,0);
!                       }
!               }
!               for_each_task(p){
                       p->counter = (p->counter >> 1) + NICE_TO_TICKS(p->nice);
+                       if (p->s_info != NULL
+                               && (p->s_info->flags & S_CTX_INFO_SCHED)!=0){
+                               atomic_add (p->counter,&p->s_info->ticks);
+                       }
+               }
               read_unlock(&tasklist_lock);
               spin_lock_irq(&runqueue_lock);
diff -rc2P linux-2.4.13/kernel/signal.c linux-2.4.13-ctx-3/kernel/signal.c
*** linux-2.4.13/kernel/signal.c        Mon Sep 17 19:40:01 2001
--- linux-2.4.13-ctx-3/kernel/signal.c  Wed Oct 31 16:05:00 2001
***************
*** 593,597 ****
               read_lock(&tasklist_lock);
               for_each_task(p) {
!                       if (p->pgrp == pgrp) {
                               int err = send_sig_info(sig, info, p);
                               if (retval)
--- 593,597 ----
               read_lock(&tasklist_lock);
               for_each_task(p) {
!                       if (p->pgrp == pgrp && p->s_context == current->s_context) {
                               int err = send_sig_info(sig, info, p);
                               if (retval)
***************
*** 640,644 ****
       p = find_task_by_pid(pid);
       error = -ESRCH;
!       if (p)
               error = send_sig_info(sig, info, p);
       read_unlock(&tasklist_lock);
--- 640,644 ----
       p = find_task_by_pid(pid);
       error = -ESRCH;
!       if (p && p->s_context == current->s_context)
               error = send_sig_info(sig, info, p);
       read_unlock(&tasklist_lock);
***************
*** 664,668 ****
               read_lock(&tasklist_lock);
               for_each_task(p) {
!                       if (p->pid > 1 && p != current) {
                               int err = send_sig_info(sig, info, p);
                               ++count;
--- 664,668 ----
               read_lock(&tasklist_lock);
               for_each_task(p) {
!                       if (p->pid > 1 && p != current && p->s_context == current->s_context) {
                               int err = send_sig_info(sig, info, p);
                               ++count;
***************
*** 1257,1258 ****
--- 1257,1348 ----
 }
 #endif /* !alpha && !__ia64__ && !defined(__mips__) */
+
+ /*
+       Change to a new security context and reduce the capability
+       basic set of the current process
+ */
+ asmlinkage int
+ sys_new_s_context(int ctx, __u32 remove_cap, int flags)
+ {
+       #define MAX_S_CONTEXT 65535     /* Arbitrary limit */
+       int ret = -EPERM;
+       if (ctx == -1){
+               if (current->s_info == NULL
+                       || (current->s_info->flags & S_CTX_INFO_LOCK) == 0){
+                       /* Ok we allocate a new context. For now, we just increase */
+                       /* it. Wrap around possible, so we loop */
+                       static int alloc_ctx=1;
+                       static spinlock_t alloc_ctx_lock = SPIN_LOCK_UNLOCKED;
+                       spin_lock(&alloc_ctx_lock);
+                       while (1){
+                               int found = 0;
+                               struct task_struct *p;
+                               alloc_ctx++;
+                               /* The s_context 1 is special. It sess all processes */
+                               if (alloc_ctx == 1){
+                                       alloc_ctx++;
+                               }else if (alloc_ctx > MAX_S_CONTEXT){
+                                       // No need to grow and grow
+                                       alloc_ctx = 2;
+                               }
+                               /* Check if in use */
+                               read_lock(&tasklist_lock);
+                               for_each_task(p) {
+                                       if (p->s_context == alloc_ctx){
+                                               found = 1;
+                                               break;
+                                       }
+                               }
+                               read_unlock(&tasklist_lock);
+                               if (!found) break;
+                       }
+                       current->s_context = alloc_ctx;
+                       current->cap_bset &= (~remove_cap);
+                       ret = alloc_ctx;
+                       sys_alloc_s_info();
+                       if (current->s_info != NULL){
+                               current->s_info->flags |= flags;
+                       }
+                       spin_unlock(&alloc_ctx_lock);
+               }
+       }else if (ctx == -2){
+               /* We keep the same s_context, but lower the capabilities */
+               current->cap_bset &= (~remove_cap);
+               ret = current->s_context;
+               if (current->s_info != NULL){
+                       current->s_info->flags |= flags;
+               }
+       }else if (ctx < 0 || ctx > MAX_S_CONTEXT){
+               ret = -EINVAL;
+       }else if (current->s_context == 0
+               && capable(CAP_SYS_ADMIN)
+               && current->s_info == NULL
+                       ||(current->s_info->flags & S_CTX_INFO_LOCK) == 0){
+               if (ctx != 0){
+                       /* The root context can become any context it wants */
+                       int found = 0;
+                       struct task_struct *p;
+                       current->s_context = ctx;
+                       current->cap_bset &= (~remove_cap);
+                       /* Check if in use so we reuse the same context_info */
+                       read_lock(&tasklist_lock);
+                       for_each_task(p) {
+                               if (p->s_context == ctx){
+                                       found = 1;
+                                       sys_release_s_info(current);
+                                       sys_assign_s_info (p);
+                                       current->s_info = p->s_info;
+                                       break;
+                               }
+                       }
+                       read_unlock(&tasklist_lock);
+                       if (!found) sys_alloc_s_info();
+                       if (current->s_info != NULL){
+                               current->s_info->flags |= flags;
+                       }
+               }
+               ret = ctx;
+       }
+       return ret;
+ }
+
diff -rc2P linux-2.4.13/kernel/sys.c linux-2.4.13-ctx-3/kernel/sys.c
*** linux-2.4.13/kernel/sys.c   Tue Sep 18 17:10:43 2001
--- linux-2.4.13-ctx-3/kernel/sys.c     Wed Oct 31 16:05:00 2001
***************
*** 1016,1022 ****
 {
       int errno = 0;

       down_read(&uts_sem);
!       if (copy_to_user(name,&system_utsname,sizeof *name))
               errno = -EFAULT;
       up_read(&uts_sem);
--- 1016,1031 ----
 {
       int errno = 0;
+       struct new_utsname tmp,*pttmp;

       down_read(&uts_sem);
!       if (current->s_info != NULL){
!               tmp = system_utsname;
!               strcpy (tmp.nodename,current->s_info->nodename);
!               strcpy (tmp.domainname,current->s_info->domainname);
!               pttmp = &tmp;
!       }else{
!               pttmp = &system_utsname;
!       }
!       if (copy_to_user(name,pttmp,sizeof *name))
               errno = -EFAULT;
       up_read(&uts_sem);
***************
*** 1024,1030 ****
--- 1033,1093 ----
 }

+ /*
+       Decrease the reference count on the context_info member of a task
+       Free the struct if the reference count reach 0.
+ */
+ void sys_release_s_info (struct task_struct *p)
+ {
+       down_write (&uts_sem);
+       if (p->s_info != NULL){
+               p->s_info->refcount--;
+               if (p->s_info->refcount == 0){
+                       // printk ("vfree s_info %d\n",p->pid);
+                       vfree (p->s_info);
+                       p->s_info = NULL;
+               }
+       }
+       up_write (&uts_sem);
+ }
+ /*
+       Increase the reference count on the context_info member of a task
+ */
+ void sys_assign_s_info (struct task_struct *p)
+ {
+       down_write (&uts_sem);
+       if (p->s_info != NULL) p->s_info->refcount++;
+       up_write (&uts_sem);
+ }
+
+ /*
+       Alloc a new s_info to the current process and release
+       the one currently owned by the current process.
+ */
+ void sys_alloc_s_info()
+ {
+       struct context_info *s_info = vmalloc(sizeof(struct context_info));
+       // printk ("new s_info %d\n",current->pid);
+       s_info->s_context = current->s_context;
+       s_info->refcount = 1;
+       atomic_set (&s_info->ticks,current->counter);
+       s_info->flags = 0;
+       down_read (&uts_sem);
+       if (current->s_info != NULL){
+               strcpy (s_info->nodename,current->s_info->nodename);
+               strcpy (s_info->domainname,current->s_info->domainname);
+       }else{
+               strcpy (s_info->nodename,system_utsname.nodename);
+               strcpy (s_info->domainname,system_utsname.domainname);
+       }
+       up_read (&uts_sem);
+       sys_release_s_info (current);
+       current->s_info = s_info;
+ }
+
+
 asmlinkage long sys_sethostname(char *name, int len)
 {
       int errno;
+       char *nodename;

       if (!capable(CAP_SYS_ADMIN))
***************
*** 1034,1039 ****
       down_write(&uts_sem);
       errno = -EFAULT;
!       if (!copy_from_user(system_utsname.nodename, name, len)) {
!               system_utsname.nodename[len] = 0;
               errno = 0;
       }
--- 1097,1104 ----
       down_write(&uts_sem);
       errno = -EFAULT;
!       nodename = system_utsname.nodename;
!       if (current->s_info) nodename = current->s_info->nodename;
!       if (!copy_from_user(nodename, name, len)) {
!               nodename[len] = 0;
               errno = 0;
       }
***************
*** 1045,1057 ****
 {
       int i, errno;

       if (len < 0)
               return -EINVAL;
       down_read(&uts_sem);
!       i = 1 + strlen(system_utsname.nodename);
       if (i > len)
               i = len;
       errno = 0;
!       if (copy_to_user(name, system_utsname.nodename, i))
               errno = -EFAULT;
       up_read(&uts_sem);
--- 1110,1125 ----
 {
       int i, errno;
+       char *nodename;

       if (len < 0)
               return -EINVAL;
       down_read(&uts_sem);
!       nodename = system_utsname.nodename;
!       if (current->s_info != NULL) nodename = current->s_info->nodename;
!       i = 1 + strlen(nodename);
       if (i > len)
               i = len;
       errno = 0;
!       if (copy_to_user(name, nodename, i))
               errno = -EFAULT;
       up_read(&uts_sem);
***************
*** 1066,1069 ****
--- 1134,1138 ----
 {
       int errno;
+       char *domainname;

       if (!capable(CAP_SYS_ADMIN))
***************
*** 1073,1080 ****

       down_write(&uts_sem);
       errno = -EFAULT;
!       if (!copy_from_user(system_utsname.domainname, name, len)) {
               errno = 0;
!               system_utsname.domainname[len] = 0;
       }
       up_write(&uts_sem);
--- 1142,1151 ----

       down_write(&uts_sem);
+       domainname = system_utsname.domainname;
+       if (current->s_info) domainname = current->s_info->domainname;
       errno = -EFAULT;
!       if (!copy_from_user(domainname, name, len)) {
               errno = 0;
!               domainname[len] = 0;
       }
       up_write(&uts_sem);
diff -rc2P linux-2.4.13/kernel/sysctl.c linux-2.4.13-ctx-3/kernel/sysctl.c
*** linux-2.4.13/kernel/sysctl.c        Wed Oct 10 11:58:22 2001
--- linux-2.4.13-ctx-3/kernel/sysctl.c  Wed Oct 31 16:05:00 2001
***************
*** 375,378 ****
--- 375,379 ----
 static int test_perm(int mode, int op)
 {
+       if (!capable(CAP_SYS_ADMIN)) mode &= ~(0222);
       if (!current->euid)
               mode >>= 6;
***************
*** 789,793 ****
--- 790,805 ----
 {
       int r;
+       ctl_table tmp;

+       /* HACK for per s_context hostname and domainname */
+       if (current->s_info != NULL){
+               tmp = *table;
+               table = &tmp;
+               if (table->data == (void*)&system_utsname.nodename){
+                       tmp.data = &current->s_info->nodename;
+               }else if (table->data == (void*)&system_utsname.domainname){
+                       tmp.data = &current->s_info->domainname;
+               }
+       }
       if (!write) {
               down_read(&uts_sem);
diff -rc2P linux-2.4.13/kernel/timer.c linux-2.4.13-ctx-3/kernel/timer.c
*** linux-2.4.13/kernel/timer.c Wed Oct 10 11:58:22 2001
--- linux-2.4.13-ctx-3/kernel/timer.c   Wed Oct 31 16:05:00 2001
***************
*** 584,587 ****
--- 584,591 ----
       update_one_process(p, user_tick, system, cpu);
       if (p->pid) {
+               if (p->s_info != NULL
+                       && (p->s_info->flags & S_CTX_INFO_SCHED)!=0){
+                       atomic_dec (&p->s_info->ticks);
+               }
               if (--p->counter <= 0) {
                       p->counter = 0;
diff -rc2P linux-2.4.13/net/ipv4/af_inet.c linux-2.4.13-ctx-3/net/ipv4/af_inet.c
*** linux-2.4.13/net/ipv4/af_inet.c     Tue Aug  7 11:30:50 2001
--- linux-2.4.13-ctx-3/net/ipv4/af_inet.c       Wed Oct 31 16:05:00 2001
***************
*** 474,477 ****
--- 474,478 ----
       int chk_addr_ret;
       int err;
+       __u32 s_addr;

       /* If the socket has its own bind function then use it. (RAW) */
***************
*** 482,486 ****
               return -EINVAL;

!       chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr);

       /* Not specified by any standard per-se, however it breaks too
--- 483,497 ----
               return -EINVAL;

!       s_addr = addr->sin_addr.s_addr;
!       if (current->ipv4root != 0){
!               // printk ("ipv4root0 %08lx %08x\n",current->ipv4root,s_addr);
!               if (s_addr == 0){
!                       s_addr = current->ipv4root;
!               }else if (s_addr != current->ipv4root){
!                       return -EADDRNOTAVAIL;
!               }
!       }
!       chk_addr_ret = inet_addr_type(s_addr);
!       // printk ("ipv4root %08lx %08x %d\n",current->ipv4root,s_addr,chk_addr_ret);

       /* Not specified by any standard per-se, however it breaks too
***************
*** 493,497 ****
       if (sysctl_ip_nonlocal_bind == 0 &&
           sk->protinfo.af_inet.freebind == 0 &&
!           addr->sin_addr.s_addr != INADDR_ANY &&
           chk_addr_ret != RTN_LOCAL &&
           chk_addr_ret != RTN_MULTICAST &&
--- 504,508 ----
       if (sysctl_ip_nonlocal_bind == 0 &&
           sk->protinfo.af_inet.freebind == 0 &&
!           s_addr != INADDR_ANY &&
           chk_addr_ret != RTN_LOCAL &&
           chk_addr_ret != RTN_MULTICAST &&
***************
*** 518,522 ****
               goto out;

!       sk->rcv_saddr = sk->saddr = addr->sin_addr.s_addr;
       if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
               sk->saddr = 0;  /* Use device */
--- 529,533 ----
               goto out;

!       sk->rcv_saddr = sk->saddr = s_addr;
       if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
               sk->saddr = 0;  /* Use device */
diff -rc2P linux-2.4.13/net/socket.c linux-2.4.13-ctx-3/net/socket.c
*** linux-2.4.13/net/socket.c   Wed Oct 31 15:32:46 2001
--- linux-2.4.13-ctx-3/net/socket.c     Wed Oct 31 16:05:00 2001
***************
*** 1766,1767 ****
--- 1766,1779 ----
       return len;
 }
+
+ asmlinkage int sys_set_ipv4root (unsigned long ip)
+ {
+       int ret = -EPERM;
+       if (current->ipv4root == 0
+               || capable(CAP_SYS_ADMIN)){
+               ret = 0;
+               current->ipv4root = ip;
+       }
+       return ret;
+ }
+