diff -NurpP --minimal linux-2.4.24-vs1.22/Makefile linux-2.4.24-vs1.23/Makefile
--- linux-2.4.24-vs1.22/Makefile	Mon Jan  5 20:24:17 2004
+++ linux-2.4.24-vs1.23/Makefile	Mon Jan 12 05:03:14 2004
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 24
-EXTRAVERSION = -vs1.22
+EXTRAVERSION = -vs1.23
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -NurpP --minimal linux-2.4.24-vs1.22/fs/ioctl.c linux-2.4.24-vs1.23/fs/ioctl.c
--- linux-2.4.24-vs1.22/fs/ioctl.c	Mon Aug 25 13:44:43 2003
+++ linux-2.4.24-vs1.23/fs/ioctl.c	Mon Jan 12 05:03:14 2004
@@ -7,10 +7,14 @@
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/file.h>
+#include <linux/proc_fs.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 
+extern int vx_proc_ioctl(struct inode *, struct file *,
+        unsigned int, unsigned long);
+
 static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
 {
 	int error;
@@ -110,6 +114,12 @@ asmlinkage long sys_ioctl(unsigned int f
 			}
 			else
 				error = -ENOTTY;
+			break;
+		case FIOC_GETXFLG:
+		case FIOC_SETXFLG:
+			error = -ENOTTY;
+			if (filp->f_dentry->d_inode->i_sb->s_magic == PROC_SUPER_MAGIC)
+				error = vx_proc_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
 			break;
 		default:
 			error = -ENOTTY;
diff -NurpP --minimal linux-2.4.24-vs1.22/fs/proc/array.c linux-2.4.24-vs1.23/fs/proc/array.c
--- linux-2.4.24-vs1.22/fs/proc/array.c	Mon Jan  5 20:24:19 2004
+++ linux-2.4.24-vs1.23/fs/proc/array.c	Mon Jan 12 05:03:14 2004
@@ -281,6 +281,7 @@ static inline char *task_cap(struct task
 			    cap_t(p->cap_bset));
 }
 
+extern rwlock_t ctx_ref_lock;
 
 int proc_pid_status(struct task_struct *task, char * buffer)
 {
@@ -300,6 +301,7 @@ int proc_pid_status(struct task_struct *
 	}
 	buffer = task_sig(task, buffer);
 	buffer = task_cap(task, buffer);
+	read_lock(&ctx_ref_lock);
 	if (task->s_info) {
 		int i;
 
@@ -345,6 +347,7 @@ int proc_pid_status(struct task_struct *
 		buffer += sprintf (buffer,"ipv4root: 0\n");
 		buffer += sprintf (buffer,"ipv4root_bcast: 0\n");
 	}
+	read_unlock(&ctx_ref_lock);
 #if defined(CONFIG_ARCH_S390)
 	buffer = task_show_regs(task, buffer);
 #endif
diff -NurpP --minimal linux-2.4.24-vs1.22/fs/proc/generic.c linux-2.4.24-vs1.23/fs/proc/generic.c
--- linux-2.4.24-vs1.22/fs/proc/generic.c	Fri Nov 28 19:26:21 2003
+++ linux-2.4.24-vs1.23/fs/proc/generic.c	Mon Jan 12 05:03:14 2004
@@ -16,6 +16,7 @@
 #include <linux/stat.h>
 #define __NO_VERSION__
 #include <linux/module.h>
+#include <linux/vcontext.h>
 #include <asm/bitops.h>
 
 static ssize_t proc_file_read(struct file * file, char * buf,
@@ -265,6 +266,8 @@ struct dentry *proc_lookup(struct inode 
 				continue;
 			if (de->namelen != dentry->d_name.len)
 				continue;
+			if (!vx_weak_check(0, de->vx_flags))
+				continue;
 			if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
 				int ino = de->low_ino;
 				error = -EINVAL;
@@ -332,9 +335,12 @@ int proc_readdir(struct file * filp,
 			}
 
 			do {
+				if (!vx_weak_check(0, de->vx_flags))
+					goto skip;
 				if (filldir(dirent, de->name, de->namelen, filp->f_pos,
 					    de->low_ino, de->mode >> 12) < 0)
 					return 0;
+			skip:
 				filp->f_pos++;
 				de = de->next;
 			} while (de);
@@ -441,6 +447,7 @@ static struct proc_dir_entry *proc_creat
 	ent->namelen = len;
 	ent->mode = mode;
 	ent->nlink = nlink;
+	ent->vx_flags = 0;  /* will become VX_ADMIN */
  out:
 	return ent;
 }
@@ -461,7 +468,8 @@ struct proc_dir_entry *proc_symlink(cons
 				kfree(ent->data);
 				kfree(ent);
 				ent = NULL;
-			}
+			} else
+				ent->vx_flags = 0;
 		} else {
 			kfree(ent);
 			ent = NULL;
diff -NurpP --minimal linux-2.4.24-vs1.22/include/linux/capability.h linux-2.4.24-vs1.23/include/linux/capability.h
--- linux-2.4.24-vs1.22/include/linux/capability.h	Mon Jan 12 02:50:09 2004
+++ linux-2.4.24-vs1.23/include/linux/capability.h	Mon Jan 12 05:03:32 2004
@@ -285,6 +285,11 @@ typedef __u32 kernel_cap_t;
 
 #define CAP_QUOTACTL         29
 
+/* Allow context manipulations */
+/* Allow changing context info on files */
+
+#define CAP_CONTEXT          30
+
 #ifdef __KERNEL__
 /* 
  * Bounding set
diff -NurpP --minimal linux-2.4.24-vs1.22/include/linux/proc_fs.h linux-2.4.24-vs1.23/include/linux/proc_fs.h
--- linux-2.4.24-vs1.22/include/linux/proc_fs.h	Mon Jan 12 02:50:09 2004
+++ linux-2.4.24-vs1.23/include/linux/proc_fs.h	Mon Jan 12 05:03:39 2004
@@ -58,6 +58,7 @@ struct proc_dir_entry {
 	nlink_t nlink;
 	uid_t uid;
 	gid_t gid;
+	int vx_flags;
 	unsigned long size;
 	struct inode_operations * proc_iops;
 	struct file_operations * proc_fops;
diff -NurpP --minimal linux-2.4.24-vs1.22/include/linux/vcontext.h linux-2.4.24-vs1.23/include/linux/vcontext.h
--- linux-2.4.24-vs1.22/include/linux/vcontext.h	Wed Jan  7 05:29:51 2004
+++ linux-2.4.24-vs1.23/include/linux/vcontext.h	Mon Jan 12 05:03:32 2004
@@ -85,6 +85,8 @@ struct iproot_info {
 /* required to resolve recursive dependancies */
 #define vx_check(c,m)	__vx_check(current->vx_id,c,m)
 
+#define vx_weak_check(c,m)     ((m) ? vx_check(c,m) : 1)
+
 /*
  * check current context for ADMIN/WATCH and
  * optionally agains supplied argument
@@ -110,5 +112,10 @@ void vx_release_ip_info(struct iproot_in
 
 int vc_new_s_context(uint32_t, void *);
 int vc_set_ipv4root(uint32_t, void *);
+
+/* procfs ioctls */
+
+#define	FIOC_GETXFLG	_IOR('x', 5, long)
+#define	FIOC_SETXFLG	_IOW('x', 6, long)
 
 #endif
diff -NurpP --minimal linux-2.4.24-vs1.22/kernel/exit.c linux-2.4.24-vs1.23/kernel/exit.c
--- linux-2.4.24-vs1.22/kernel/exit.c	Mon Jan  5 20:24:21 2004
+++ linux-2.4.24-vs1.23/kernel/exit.c	Mon Jan 12 05:03:14 2004
@@ -24,6 +24,7 @@
 
 extern void sem_exit (void);
 extern struct task_struct *child_reaper;
+extern rwlock_t ctx_ref_lock;
 
 int getrusage(struct task_struct *, int, struct rusage *);
 
@@ -165,6 +166,7 @@ static inline void forget_original_paren
 	struct task_struct *vchild_reaper = child_reaper;
 
 	read_lock(&tasklist_lock);
+	read_lock(&ctx_ref_lock);
 	if (father->s_info) {
 		pid_t initpid = father->s_info->initpid;
 		if ((initpid != 0) && (father->pid != initpid)) {
@@ -174,6 +176,7 @@ static inline void forget_original_paren
 				vchild_reaper = r;
 		}
 	}
+	read_unlock(&ctx_ref_lock);
 
 	for_each_task(p) {
 		if (p->p_opptr == father) {
diff -NurpP --minimal linux-2.4.24-vs1.22/kernel/fork.c linux-2.4.24-vs1.23/kernel/fork.c
--- linux-2.4.24-vs1.22/kernel/fork.c	Mon Jan  5 20:24:21 2004
+++ linux-2.4.24-vs1.23/kernel/fork.c	Mon Jan 12 05:03:14 2004
@@ -660,9 +660,8 @@ int do_fork(unsigned long clone_flags, u
 	if (!p)
 		goto fork_out;
 
-	*p = *current;
-
 	retval = -EAGAIN;
+	*p = *current;
 	if (p->s_info && (p->s_info->flags & VX_INFO_NPROC)) {
 		if (atomic_read(&p->s_info->refcount) >= p->rlim[RLIMIT_NPROC].rlim_max)
 			goto bad_fork_free;
diff -NurpP --minimal linux-2.4.24-vs1.22/kernel/sched.c linux-2.4.24-vs1.23/kernel/sched.c
--- linux-2.4.24-vs1.22/kernel/sched.c	Mon Jan  5 20:24:21 2004
+++ linux-2.4.24-vs1.23/kernel/sched.c	Mon Jan 12 05:03:14 2004
@@ -112,6 +112,7 @@ static union {
 
 struct kernel_stat kstat;
 extern struct task_struct *child_reaper;
+extern rwlock_t ctx_ref_lock;
 
 #ifdef CONFIG_SMP
 
@@ -166,12 +167,14 @@ static inline int goodness(struct task_s
 		 * Don't do any other calculations if the time slice is
 		 * over..
 		 */
+		read_lock(&ctx_ref_lock);
 		if (p->s_info && (p->s_info->flags & VX_INFO_SCHED)) {
 			weight = atomic_read(&p->s_info->ticks) /
 				atomic_read(&p->s_info->refcount);
 			weight = (weight+p->counter) >> 1;
 		} else
 			weight = p->counter;
+		read_unlock(&ctx_ref_lock);
 		if (!weight)
 			goto out;
 			
@@ -628,6 +631,7 @@ repeat_schedule:
 			Reset the s_info->ticks to the sum off all
 			member processes p->counter
 		*/
+		read_lock(&ctx_ref_lock);
 		for_each_task(p) {
 			if (p->s_info && (p->s_info->flags & VX_INFO_SCHED))
 				atomic_set(&p->s_info->ticks, 0);
@@ -637,6 +641,7 @@ repeat_schedule:
 			if (p->s_info && (p->s_info->flags & VX_INFO_SCHED))
 				atomic_add(p->counter, &p->s_info->ticks);
 		}
+		read_unlock(&ctx_ref_lock);
 		read_unlock(&tasklist_lock);
 		spin_lock_irq(&runqueue_lock);
 		goto repeat_schedule;
diff -NurpP --minimal linux-2.4.24-vs1.22/kernel/vcontext.c linux-2.4.24-vs1.23/kernel/vcontext.c
--- linux-2.4.24-vs1.22/kernel/vcontext.c	Mon Jan  5 20:24:21 2004
+++ linux-2.4.24-vs1.23/kernel/vcontext.c	Mon Jan 12 05:03:14 2004
@@ -152,17 +152,17 @@ static void vx_alloc_info(void)
 	}
 }
 
-static spinlock_t ctx_ref_lock = SPIN_LOCK_UNLOCKED;
+rwlock_t ctx_ref_lock = RW_LOCK_UNLOCKED;
 
 /*
  *	Increase the reference count on the context_info member of a task
  */
 void vx_assign_info (struct task_struct *p)
 {
-	spin_lock (&ctx_ref_lock);
+	read_lock(&ctx_ref_lock);
 	if (p->s_info)
 		atomic_inc(&p->s_info->refcount);
-	spin_unlock (&ctx_ref_lock);
+	read_unlock(&ctx_ref_lock);
 }
 
 /*
@@ -171,14 +171,17 @@ void vx_assign_info (struct task_struct 
  */
 void vx_release_info (struct task_struct *p)
 {
-	spin_lock (&ctx_ref_lock);
+	write_lock(&ctx_ref_lock);
 	if (p->s_info) {
 		if (atomic_dec_and_test(&p->s_info->refcount)) {
-			kfree(p->s_info);
+			struct context_info *s_info;
+
+			s_info = p->s_info;
 			p->s_info = NULL;
+			kfree(s_info);
 		}
 	}
-	spin_unlock (&ctx_ref_lock);
+	write_unlock(&ctx_ref_lock);
 }
 
 /*
@@ -351,7 +354,7 @@ int vc_new_s_context(uint32_t ctx, void 
 				if (p->s_info == NULL
 					|| !(p->s_info->flags & VX_INFO_PRIVATE)) {
 					vx_release_info(current);
-					vx_assign_info (p);
+					vx_assign_info(p);
 					current->s_info = p->s_info;
 				}
 				else
@@ -425,3 +428,50 @@ int vc_set_ipv4root(uint32_t nbip, void 
 	}
 	return ret;
 }
+
+
+#include <linux/proc_fs.h>
+
+int vx_proc_ioctl(struct inode * inode, struct file * filp,
+	unsigned int cmd, unsigned long arg)
+{
+	struct proc_dir_entry *entry;
+	int error = 0;
+	int flags;
+
+	if (inode->i_ino < PROC_DYNAMIC_FIRST ||
+		inode->i_ino >= PROC_DYNAMIC_FIRST+PROC_NDYNAMIC)
+		return -ENOTTY;
+
+	entry = (struct proc_dir_entry *) inode->u.generic_ip;
+
+	switch(cmd) {
+	case FIOC_GETXFLG: {
+		/* fixme: if stealth, return -ENOTTY */
+		error = -EPERM;
+		flags = entry->vx_flags;
+		if (capable(CAP_CONTEXT))
+			error = put_user(flags, (int *) arg);
+		break;
+	}
+	case FIOC_SETXFLG: {
+		/* fixme: if stealth, return -ENOTTY */
+		error = -EPERM;
+		if (!capable(CAP_CONTEXT))
+			break;
+		error = -EROFS;
+		if (IS_RDONLY(inode))
+			break;
+		error = -EFAULT;
+		if (get_user(flags, (int *) arg))
+			break;
+		error = 0;
+		entry->vx_flags = flags;
+		break;
+	}
+	default:
+		return -ENOTTY;
+	}
+	return error;
+}
+
