diff -Pur linux.orig/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- linux.orig/arch/i386/kernel/entry.S	Sat Jun 20 20:22:44 1998
+++ linux/arch/i386/kernel/entry.S	Fri Jun 26 21:50:38 1998
@@ -548,6 +548,12 @@
 	.long SYMBOL_NAME(sys_capset)           /* 185 */
 	.long SYMBOL_NAME(sys_sigaltstack)
 	
-	.rept NR_syscalls-186
+	.rept 199-186
+		.long SYMBOL_NAME(sys_ni_syscall)
+	.endr
+
+	.long SYMBOL_NAME(sys_chtmp)
+
+	.rept NR_syscalls-200
 		.long SYMBOL_NAME(sys_ni_syscall)
 	.endr
diff -Pur linux.orig/fs/open.c linux/fs/open.c
--- linux.orig/fs/open.c	Sun May 17 16:50:57 1998
+++ linux/fs/open.c	Fri Jun 26 20:24:38 1998
@@ -396,6 +396,46 @@
 	return error;
 }
 
+asmlinkage int sys_chtmp(const char * filename)
+{
+	int error;
+	struct inode *inode;
+	struct dentry *dentry, *tmp;
+
+	lock_kernel();
+	
+	dentry = namei(filename);
+	error = PTR_ERR(dentry);
+	if (IS_ERR(dentry))
+		goto out;
+
+	inode = dentry->d_inode;
+
+	error = -ENOTDIR;
+	if (!S_ISDIR(inode->i_mode))
+		goto dput_and_out;
+
+	error = permission(inode,MAY_EXEC);
+	if (error)
+		goto dput_and_out;
+
+	error = -EPERM;
+	if (!capable(CAP_SYS_CHROOT))
+		goto dput_and_out;
+
+	/* exchange dentries */
+	tmp = current->fs->tmp;
+	current->fs->tmp = dentry;
+	dentry = tmp;
+	error = 0;
+
+dput_and_out:
+	dput(dentry);
+out:
+	unlock_kernel();
+	return error;
+}
+
 asmlinkage int sys_chroot(const char * filename)
 {
 	int error;
diff -Pur linux.orig/fs/proc/base.c linux/fs/proc/base.c
--- linux.orig/fs/proc/base.c	Wed Mar 11 23:45:53 1998
+++ linux/fs/proc/base.c	Sat Jun 27 16:24:17 1998
@@ -108,6 +108,12 @@
 	0, &proc_link_inode_operations,
 	NULL, proc_pid_fill_inode,
 };
+static struct proc_dir_entry proc_pid_tmp = {
+	PROC_PID_TMP, 3, "tmp",
+	S_IFLNK | S_IRWXUGO, 1, 0, 0,
+	0, &proc_link_inode_operations,
+	NULL, proc_pid_fill_inode,
+};
 static struct proc_dir_entry proc_pid_exe = {
 	PROC_PID_EXE, 3, "exe",
 	S_IFLNK | S_IRWXU, 1, 0, 0,
@@ -188,14 +194,6 @@
 #ifdef __SMP__	
 	proc_register(&proc_pid, &proc_pid_cpu);
 #endif	
+	proc_register(&proc_pid, &proc_pid_tmp);
 };
-
-
 
diff -Pur linux.orig/fs/proc/link.c linux/fs/proc/link.c
--- linux.orig/fs/proc/link.c	Sat May  9 15:11:01 1998
+++ linux/fs/proc/link.c	Fri Jun 26 20:12:22 1998
@@ -95,6 +95,12 @@
 			result = p->fs->root;
 			goto out_dget;
 
+		case PROC_PID_TMP:
+			if (!p->fs || !p->fs->root)
+				goto out_unlock;
+			result = p->fs->tmp;
+			goto out_dget;
+
 		case PROC_PID_EXE: {
 			struct vm_area_struct * vma;
 			if (!p->mm)
diff -Pur linux.orig/fs/super.c linux/fs/super.c
--- linux.orig/fs/super.c	Sun May 17 16:50:58 1998
+++ linux/fs/super.c	Fri Jun 26 21:31:35 1998
@@ -1111,6 +1111,7 @@
 					sb->s_type = fs_type;
 					current->fs->root = dget(sb->s_root);
 					current->fs->pwd = dget(sb->s_root);
+					current->fs->tmp = dget(sb->s_root);
 					ROOT_DEV = sb->s_dev;
 					printk (KERN_NOTICE "VFS: Mounted root (nfs filesystem).\n");
 					return;
@@ -1168,6 +1169,7 @@
 			sb->s_flags = root_mountflags;
 			current->fs->root = dget(sb->s_root);
 			current->fs->pwd = dget(sb->s_root);
+			current->fs->tmp = dget(sb->s_root);
 			printk ("VFS: Mounted root (%s filesystem)%s.\n",
 				fs_type->name,
 				(sb->s_flags & MS_RDONLY) ? " readonly" : "");
@@ -1206,11 +1208,12 @@
 {
 	kdev_t old_root_dev;
 	struct vfsmount *vfsmnt;
-	struct dentry *old_root,*old_pwd,*dir_d = NULL;
+	struct dentry *old_root,*old_pwd,*old_tmp,*dir_d = NULL;
 	int error;
 
 	old_root = current->fs->root;
 	old_pwd = current->fs->pwd;
+	old_tmp = current->fs->tmp;
 	old_root_dev = ROOT_DEV;
 	if (!fs_may_mount(new_root_dev)) {
 		printk(KERN_CRIT "New root is busy. Staying in initrd.\n");
@@ -1220,6 +1223,7 @@
 	do_mount_root();
 	dput(old_root);
 	dput(old_pwd);
+	dput(old_tmp);
 #if 1
 	shrink_dcache();
 	printk("do_change_root: old root has d_count=%d\n", old_root->d_count);
diff -Pur linux.orig/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
--- linux.orig/include/asm-i386/unistd.h	Sat Jun 20 20:23:06 1998
+++ linux/include/asm-i386/unistd.h	Fri Jun 26 20:26:17 1998
@@ -192,6 +192,7 @@
 #define __NR_capget		184
 #define __NR_capset		185
 #define __NR_sigaltstack	186
+#define __NR_chtmp		200
 
 /* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */
 
diff -Pur linux.orig/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- linux.orig/include/linux/proc_fs.h	Sat Jun 20 20:23:09 1998
+++ linux/include/linux/proc_fs.h	Fri Jun 26 20:28:21 1998
@@ -72,6 +72,7 @@
 	PROC_PID_RINGBUF,
 #endif
 	PROC_PID_CPU,
+	PROC_PID_TMP,
 };
 
 enum pid_subdirectory_inos {
diff -Pur linux.orig/include/linux/sched.h linux/include/linux/sched.h
--- linux.orig/include/linux/sched.h	Sat Jun 20 20:23:10 1998
+++ linux/include/linux/sched.h	Fri Jun 26 20:28:21 1998
@@ -144,13 +144,13 @@
 struct fs_struct {
 	int count;
 	int umask;
-	struct dentry * root, * pwd;
+	struct dentry * root, * pwd, * tmp;
 };
 
 #define INIT_FS { \
 	1, \
 	0022, \
-	NULL, NULL \
+	NULL, NULL, NULL \
 }
 
 /* Maximum number of active map areas.. This is a random (large) number */
diff -Pur linux.orig/kernel/fork.c linux/kernel/fork.c
--- linux.orig/kernel/fork.c	Sat Jun 20 20:23:11 1998
+++ linux/kernel/fork.c	Fri Jun 26 21:27:30 1998
@@ -353,6 +353,7 @@
 	tsk->fs->umask = current->fs->umask;
 	tsk->fs->root = dget(current->fs->root);
 	tsk->fs->pwd = dget(current->fs->pwd);
+	tsk->fs->tmp = dget(current->fs->tmp);
 	return 0;
 }
 

