--- linux-2.6.11.11/fs/attr.c	2005-03-02 12:38:43 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/attr.c	2005-06-01 14:34:17 +0200
@@ -56,6 +59,28 @@ int inode_change_ok(struct inode *inode,
 		if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
 			goto error;
 	}
+
+	/* Check for evil vserver activity */
+	if (vx_check(0, VX_ADMIN))
+		goto fine;
+
+	if (IS_BARRIER(inode)) {
+		vxwprintk(1, "xid=%d messing with the barrier.",
+			vx_current_xid());
+		goto error;
+	}
+	switch (inode->i_sb->s_magic) {
+		case PROC_SUPER_MAGIC:
+			vxwprintk(1, "xid=%d messing with the procfs.",
+				vx_current_xid());
+			goto error;
+		case DEVPTS_SUPER_MAGIC:
+			if (vx_check(inode->i_xid, VX_IDENT))
+				goto fine;
+			vxwprintk(1, "xid=%d messing with the devpts.",
+				vx_current_xid());
+			goto error;
+	}
 fine:
 	retval = 0;
 error:
--- linux-2.6.11.11/fs/attr.c	2005-03-02 12:38:43 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/attr.c	2005-06-01 14:34:17 +0200
@@ -103,6 +148,8 @@ int inode_setattr(struct inode * inode, 
 			mode &= ~S_ISGID;
 		inode->i_mode = mode;
 	}
+	if (ia_valid & ATTR_ATTR_FLAG)
+		inode_setattr_flags(inode, attr->ia_attr_flags);
 	mark_inode_dirty(inode);
 out:
 	return error;
--- linux-2.6.11.11/fs/devpts/inode.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/devpts/inode.c	2005-06-01 14:34:17 +0200
@@ -20,8 +20,6 @@
 #include <linux/devpts_fs.h>
 #include <linux/xattr.h>
 
-#define DEVPTS_SUPER_MAGIC 0x1cd1
-
 extern struct xattr_handler devpts_xattr_security_handler;
 
 static struct xattr_handler *devpts_xattr_handlers[] = {
--- linux-2.6.11.11/fs/devpts/inode.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/devpts/inode.c	2005-06-01 14:34:17 +0200
@@ -31,6 +29,15 @@ static struct xattr_handler *devpts_xatt
 	NULL
 };
 
+static int devpts_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+	int ret = -EACCES;
+
+	if (vx_check(inode->i_xid, VX_IDENT))
+		ret = generic_permission(inode, mask, NULL);
+	return ret;
+}
+
 static struct inode_operations devpts_file_inode_operations = {
 #ifdef CONFIG_DEVPTS_FS_XATTR
 	.setxattr	= generic_setxattr,
--- linux-2.6.11.11/fs/devpts/inode.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/devpts/inode.c	2005-06-01 14:34:17 +0200
@@ -38,6 +45,7 @@ static struct inode_operations devpts_fi
 	.listxattr	= generic_listxattr,
 	.removexattr	= generic_removexattr,
 #endif
+	.permission	= devpts_permission,
 };
 
 static struct vfsmount *devpts_mnt;
--- linux-2.6.11.11/fs/devpts/inode.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/devpts/inode.c	2005-06-01 14:34:17 +0200
@@ -88,6 +96,68 @@ static int devpts_remount(struct super_b
 	return 0;
 }
 
+static int devpts_readdir(struct file * filp, void * dirent, filldir_t filldir)
+{
+	struct dentry *dentry = filp->f_dentry;
+	struct dentry *cursor = filp->private_data;
+	struct list_head *p, *q = &cursor->d_child;
+	ino_t ino;
+	int i = filp->f_pos;
+
+	switch (i) {
+		case 0:
+			ino = dentry->d_inode->i_ino;
+			if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
+				break;
+			filp->f_pos++;
+			i++;
+			/* fallthrough */
+		case 1:
+			ino = parent_ino(dentry);
+			if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
+				break;
+			filp->f_pos++;
+			i++;
+			/* fallthrough */
+		default:
+			spin_lock(&dcache_lock);
+			if (filp->f_pos == 2) {
+				list_del(q);
+				list_add(q, &dentry->d_subdirs);
+			}
+			for (p=q->next; p != &dentry->d_subdirs; p=p->next) {
+				struct dentry *next;
+				next = list_entry(p, struct dentry, d_child);
+				if (d_unhashed(next) || !next->d_inode)
+					continue;
+				if (!vx_check(next->d_inode->i_xid, VX_IDENT))
+					continue;
+
+				spin_unlock(&dcache_lock);
+				if (filldir(dirent, next->d_name.name,
+					next->d_name.len, filp->f_pos,
+					next->d_inode->i_ino, DT_CHR) < 0)
+					return 0;
+				spin_lock(&dcache_lock);
+				/* next is still alive */
+				list_del(q);
+				list_add(q, p);
+				p = q;
+				filp->f_pos++;
+			}
+			spin_unlock(&dcache_lock);
+	}
+	return 0;
+}
+
+static struct file_operations devpts_dir_operations = {
+	.open		= dcache_dir_open,
+	.release	= dcache_dir_close,
+	.llseek		= dcache_dir_lseek,
+	.read		= generic_read_dir,
+	.readdir	= devpts_readdir,
+};
+
 static struct super_operations devpts_sops = {
 	.statfs		= simple_statfs,
 	.remount_fs	= devpts_remount,
--- linux-2.6.11.11/fs/ext2/ialloc.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/ialloc.c	2005-06-01 14:34:17 +0200
@@ -579,7 +591,8 @@ got:
 	inode->i_blocks = 0;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	memset(ei->i_data, 0, sizeof(ei->i_data));
-	ei->i_flags = EXT2_I(dir)->i_flags & ~EXT2_BTREE_FL;
+	ei->i_flags = EXT2_I(dir)->i_flags &
+		~(EXT2_BTREE_FL|EXT2_IUNLINK_FL|EXT2_BARRIER_FL);
 	if (S_ISLNK(mode))
 		ei->i_flags &= ~(EXT2_IMMUTABLE_FL|EXT2_APPEND_FL);
 	/* dirsync is only applied to directories */
--- linux-2.6.11.11/fs/ext2/inode.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/inode.c	2005-06-01 14:34:17 +0200
@@ -52,6 +53,8 @@ static inline int ext2_inode_is_fast_sym
 		inode->i_blocks - ea_blocks == 0);
 }
 
+static void ext2_truncate_nocheck (struct inode * inode);
+
 /*
  * Called at the last iput() if i_nlink is zero.
  */
--- linux-2.6.11.11/fs/ext2/inode.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/inode.c	2005-06-01 14:34:17 +0200
@@ -65,7 +68,7 @@ void ext2_delete_inode (struct inode * i
 
 	inode->i_size = 0;
 	if (inode->i_blocks)
-		ext2_truncate (inode);
+		ext2_truncate_nocheck(inode);
 	ext2_free_inode (inode);
 
 	return;
--- linux-2.6.11.11/fs/ext2/inode.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/inode.c	2005-06-01 14:34:17 +0200
@@ -865,7 +868,7 @@ static void ext2_free_branches(struct in
 		ext2_free_data(inode, p, q);
 }
 
-void ext2_truncate (struct inode * inode)
+static void ext2_truncate_nocheck(struct inode * inode)
 {
 	__le32 *i_data = EXT2_I(inode)->i_data;
 	int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
--- linux-2.6.11.11/fs/ext2/inode.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/inode.c	2005-06-01 14:34:17 +0200
@@ -882,8 +885,6 @@ void ext2_truncate (struct inode * inode
 		return;
 	if (ext2_inode_is_fast_symlink(inode))
 		return;
-	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-		return;
 
 	ext2_discard_prealloc(inode);
 
--- linux-2.6.11.11/fs/ext2/inode.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/inode.c	2005-06-01 14:34:17 +0200
@@ -1005,17 +1006,28 @@ Egdp:
 	return ERR_PTR(-EIO);
 }
 
+void ext2_truncate (struct inode * inode)
+{
+	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+		return;
+	ext2_truncate_nocheck(inode);
+}
+
 void ext2_set_inode_flags(struct inode *inode)
 {
 	unsigned int flags = EXT2_I(inode)->i_flags;
 
-	inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
+	inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_IUNLINK|S_BARRIER|S_NOATIME|S_DIRSYNC);
 	if (flags & EXT2_SYNC_FL)
 		inode->i_flags |= S_SYNC;
 	if (flags & EXT2_APPEND_FL)
 		inode->i_flags |= S_APPEND;
 	if (flags & EXT2_IMMUTABLE_FL)
 		inode->i_flags |= S_IMMUTABLE;
+	if (flags & EXT2_IUNLINK_FL)
+		inode->i_flags |= S_IUNLINK;
+	if (flags & EXT2_BARRIER_FL)
+		inode->i_flags |= S_BARRIER;
 	if (flags & EXT2_NOATIME_FL)
 		inode->i_flags |= S_NOATIME;
 	if (flags & EXT2_DIRSYNC_FL)
--- linux-2.6.11.11/fs/ext2/ioctl.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/ext2/ioctl.c	2005-06-01 14:34:17 +0200
@@ -49,7 +49,9 @@ int ext2_ioctl (struct inode * inode, st
 		 *
 		 * This test looks nicer. Thanks to Pauline Middelink
 		 */
-		if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) {
+		if ((oldflags & EXT2_IMMUTABLE_FL) ||
+			((flags ^ oldflags) & (EXT2_APPEND_FL |
+			EXT2_IMMUTABLE_FL | EXT2_IUNLINK_FL))) {
 			if (!capable(CAP_LINUX_IMMUTABLE))
 				return -EPERM;
 		}
--- linux-2.6.11.11/fs/ext3/ialloc.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/ialloc.c	2005-06-01 14:34:17 +0200
@@ -566,7 +578,8 @@ got:
 	ei->i_dir_start_lookup = 0;
 	ei->i_disksize = 0;
 
-	ei->i_flags = EXT3_I(dir)->i_flags & ~EXT3_INDEX_FL;
+	ei->i_flags = EXT3_I(dir)->i_flags &
+		~(EXT3_INDEX_FL|EXT3_IUNLINK_FL|EXT3_BARRIER_FL);
 	if (S_ISLNK(mode))
 		ei->i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL);
 	/* dirsync only applies to directories */
--- linux-2.6.11.11/fs/ext3/inode.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/inode.c	2005-06-01 14:34:17 +0200
@@ -180,6 +181,8 @@ static int ext3_journal_test_restart(han
 	return ext3_journal_restart(handle, blocks_for_truncate(inode));
 }
 
+static void ext3_truncate_nocheck (struct inode *inode);
+
 /*
  * Called at the last iput() if i_nlink is zero.
  */
--- linux-2.6.11.11/fs/ext3/inode.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/inode.c	2005-06-01 14:34:17 +0200
@@ -203,7 +206,7 @@ void ext3_delete_inode (struct inode * i
 		handle->h_sync = 1;
 	inode->i_size = 0;
 	if (inode->i_blocks)
-		ext3_truncate(inode);
+		ext3_truncate_nocheck(inode);
 	/*
 	 * Kill off the orphan record which ext3_truncate created.
 	 * AKPM: I think this can be inside the above `if'.
--- linux-2.6.11.11/fs/ext3/inode.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/inode.c	2005-06-01 14:34:17 +0200
@@ -2050,7 +2053,7 @@ static void ext3_free_branches(handle_t 
  * ext3_truncate() run will find them and release them.
  */
 
-void ext3_truncate(struct inode * inode)
+void ext3_truncate_nocheck(struct inode * inode)
 {
 	handle_t *handle;
 	struct ext3_inode_info *ei = EXT3_I(inode);
--- linux-2.6.11.11/fs/ext3/inode.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/inode.c	2005-06-01 14:34:17 +0200
@@ -2071,8 +2074,6 @@ void ext3_truncate(struct inode * inode)
 		return;
 	if (ext3_inode_is_fast_symlink(inode))
 		return;
-	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-		return;
 
 	ext3_discard_reservation(inode);
 
--- linux-2.6.11.11/fs/ext3/inode.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/inode.c	2005-06-01 14:34:17 +0200
@@ -2390,17 +2391,28 @@ int ext3_get_inode_loc(struct inode *ino
 		!(EXT3_I(inode)->i_state & EXT3_STATE_XATTR));
 }
 
+void ext3_truncate(struct inode * inode)
+{
+	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+		return;
+	ext3_truncate_nocheck(inode);
+}
+
 void ext3_set_inode_flags(struct inode *inode)
 {
 	unsigned int flags = EXT3_I(inode)->i_flags;
 
-	inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
+	inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_IUNLINK|S_BARRIER|S_NOATIME|S_DIRSYNC);
 	if (flags & EXT3_SYNC_FL)
 		inode->i_flags |= S_SYNC;
 	if (flags & EXT3_APPEND_FL)
 		inode->i_flags |= S_APPEND;
 	if (flags & EXT3_IMMUTABLE_FL)
 		inode->i_flags |= S_IMMUTABLE;
+	if (flags & EXT3_IUNLINK_FL)
+		inode->i_flags |= S_IUNLINK;
+	if (flags & EXT3_BARRIER_FL)
+		inode->i_flags |= S_BARRIER;
 	if (flags & EXT3_NOATIME_FL)
 		inode->i_flags |= S_NOATIME;
 	if (flags & EXT3_DIRSYNC_FL)
--- linux-2.6.11.11/fs/ext3/inode.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/inode.c	2005-06-01 14:34:17 +0200
@@ -2791,6 +2858,12 @@ int ext3_setattr(struct dentry *dentry, 
 		ext3_journal_stop(handle);
 	}
 
+	if (ia_valid & ATTR_ATTR_FLAG) {
+		rc = ext3_setattr_flags(inode, attr->ia_attr_flags);
+		if (!error)
+			error = rc;
+	}
+
 	rc = inode_setattr(inode, attr);
 
 	/* If inode_setattr's call to ext3_truncate failed to get a
--- linux-2.6.11.11/fs/ext3/ioctl.c	2005-03-02 12:38:44 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/ext3/ioctl.c	2005-06-01 14:34:17 +0200
@@ -58,7 +59,9 @@ int ext3_ioctl (struct inode * inode, st
 		 *
 		 * This test looks nicer. Thanks to Pauline Middelink
 		 */
-		if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) {
+		if ((oldflags & EXT3_IMMUTABLE_FL) ||
+			((flags ^ oldflags) & (EXT3_APPEND_FL |
+			EXT3_IMMUTABLE_FL | EXT3_IUNLINK_FL))) {
 			if (!capable(CAP_LINUX_IMMUTABLE))
 				return -EPERM;
 		}
--- linux-2.6.11.11/fs/nfs/inode.c	2005-03-02 12:38:45 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/nfs/inode.c	2005-06-01 14:34:17 +0200
@@ -730,7 +738,12 @@ nfs_fhget(struct super_block *sb, struct
 
 out:
 	return inode;
-
+/*	FIXME
+fail_dlim:
+	make_bad_inode(inode);
+	iput(inode);
+	inode = NULL;
+*/
 out_no_inode:
 	printk("nfs_fhget: iget failed\n");
 	goto out;
--- linux-2.6.11.11/fs/reiserfs/inode.c	2005-03-02 12:38:45 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/reiserfs/inode.c	2005-06-01 14:34:17 +0200
@@ -2787,6 +2834,10 @@ int reiserfs_setattr(struct dentry *dent
 	}
 
     error = inode_change_ok(inode, attr) ;
+
+    if (!error && attr->ia_valid & ATTR_ATTR_FLAG)
+	reiserfs_setattr_flags(inode, attr->ia_attr_flags);
+
     if (!error) {
 	if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
 	    (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
--- linux-2.6.11.11/fs/reiserfs/ioctl.c	2005-03-02 12:38:45 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/reiserfs/ioctl.c	2005-06-01 14:34:17 +0200
@@ -22,7 +22,7 @@ static int reiserfs_unpack (struct inode
 int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
 		unsigned long arg)
 {
-	unsigned int flags;
+	unsigned int flags, oldflags;
 
 	switch (cmd) {
 	    case REISERFS_IOC_UNPACK:
--- linux-2.6.11.11/fs/reiserfs/ioctl.c	2005-03-02 12:38:45 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/reiserfs/ioctl.c	2005-06-01 14:34:17 +0200
@@ -38,6 +38,7 @@ int reiserfs_ioctl (struct inode * inode
 	case REISERFS_IOC_GETFLAGS:
 		flags = REISERFS_I(inode) -> i_attrs;
 		i_attrs_to_sd_attrs( inode, ( __u16 * ) &flags );
+		flags &= REISERFS_FL_USER_VISIBLE;
 		return put_user(flags, (int __user *) arg);
 	case REISERFS_IOC_SETFLAGS: {
 		if (IS_RDONLY(inode))
--- linux-2.6.11.11/fs/reiserfs/ioctl.c	2005-03-02 12:38:45 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/reiserfs/ioctl.c	2005-06-01 14:34:17 +0200
@@ -49,8 +50,12 @@ int reiserfs_ioctl (struct inode * inode
 		if (get_user(flags, (int __user *) arg))
 			return -EFAULT;
 
-		if ( ( ( flags ^ REISERFS_I(inode) -> i_attrs) & ( REISERFS_IMMUTABLE_FL | REISERFS_APPEND_FL)) &&
-		     !capable( CAP_LINUX_IMMUTABLE ) )
+		oldflags = REISERFS_I(inode) -> i_attrs;
+		if ( ( (oldflags & REISERFS_IMMUTABLE_FL) ||
+			( (flags ^ oldflags) &
+			(REISERFS_IMMUTABLE_FL | REISERFS_IUNLINK_FL |
+			 REISERFS_APPEND_FL) ) ) &&
+			!capable( CAP_LINUX_IMMUTABLE ) )
 			return -EPERM;
 			
 		if( ( flags & REISERFS_NOTAIL_FL ) &&
--- linux-2.6.11.11/fs/reiserfs/ioctl.c	2005-03-02 12:38:45 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/reiserfs/ioctl.c	2005-06-01 14:34:17 +0200
@@ -61,6 +66,9 @@ int reiserfs_ioctl (struct inode * inode
 				if( result )
 					return result;
 		}
+
+		flags = flags & REISERFS_FL_USER_MODIFYABLE;
+		flags |= oldflags & ~REISERFS_FL_USER_MODIFYABLE;
 		sd_attrs_to_i_attrs( flags, inode );
 		REISERFS_I(inode) -> i_attrs = flags;
 		inode->i_ctime = CURRENT_TIME_SEC;
--- linux-2.6.11.11/fs/super.c	2005-03-02 12:38:46 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/super.c	2005-06-01 14:34:17 +0200
@@ -826,6 +834,13 @@ do_kern_mount(const char *fstype, int fl
 	sb = type->get_sb(type, flags, name, data);
 	if (IS_ERR(sb))
 		goto out_free_secdata;
+
+	error = -EPERM;
+	if (!capable(CAP_SYS_ADMIN) && !sb->s_bdev &&
+		(sb->s_magic != PROC_SUPER_MAGIC) &&
+		(sb->s_magic != DEVPTS_SUPER_MAGIC))
+		goto out_sb;
+
  	error = security_sb_kern_mount(sb, secdata);
  	if (error)
  		goto out_sb;
--- linux-2.6.11.11/fs/sysfs/mount.c	2005-03-02 12:38:46 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/sysfs/mount.c	2005-06-01 14:34:17 +0200
@@ -11,8 +11,6 @@
 
 #include "sysfs.h"
 
-/* Random magic number */
-#define SYSFS_MAGIC 0x62656572
 
 struct vfsmount *sysfs_mount;
 struct super_block * sysfs_sb = NULL;
--- linux-2.6.11.11/fs/sysfs/mount.c	2005-03-02 12:38:46 +0100
+++ linux-2.6.11.11-vs2.0-rc3/fs/sysfs/mount.c	2005-06-01 14:34:17 +0200
@@ -37,7 +35,7 @@ static int sysfs_fill_super(struct super
 
 	sb->s_blocksize = PAGE_CACHE_SIZE;
 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-	sb->s_magic = SYSFS_MAGIC;
+	sb->s_magic = SYSFS_SUPER_MAGIC;
 	sb->s_op = &sysfs_ops;
 	sb->s_time_gran = 1;
 	sysfs_sb = sb;
--- linux-2.6.11.11/include/linux/devpts_fs.h	2004-08-14 12:55:59 +0200
+++ linux-2.6.11.11-vs2.0-rc3/include/linux/devpts_fs.h	2005-06-01 14:34:17 +0200
@@ -30,5 +30,7 @@ static inline void devpts_pty_kill(int n
 
 #endif
 
+#define DEVPTS_SUPER_MAGIC	0x00001cd1
+
 
 #endif /* _LINUX_DEVPTS_FS_H */
--- linux-2.6.11.11/include/linux/shmem_fs.h	2004-10-23 05:06:23 +0200
+++ linux-2.6.11.11-vs2.0-rc3/include/linux/shmem_fs.h	2005-06-01 14:34:17 +0200
@@ -8,6 +8,9 @@
 
 #define SHMEM_NR_DIRECT 16
 
+#define TMPFS_SUPER_MAGIC	0x01021994
+
+
 struct shmem_inode_info {
 	spinlock_t		lock;
 	unsigned long		flags;
--- linux-2.6.11.11/include/linux/sysfs.h	2005-03-02 12:38:53 +0100
+++ linux-2.6.11.11-vs2.0-rc3/include/linux/sysfs.h	2005-06-01 14:34:17 +0200
@@ -12,6 +12,8 @@
 
 #include <asm/atomic.h>
 
+#define SYSFS_SUPER_MAGIC	0x62656572
+
 struct kobject;
 struct module;
 
--- linux-2.6.11.11/include/linux/vserver/inode.h	1970-01-01 01:00:00 +0100
+++ linux-2.6.11.11-vs2.0-rc3/include/linux/vserver/inode.h	2005-06-01 14:34:17 +0200
@@ -0,0 +1,41 @@
+#ifndef _VX_INODE_H
+#define _VX_INODE_H
+
+
+#define IATTR_XID	0x01000000
+
+#define IATTR_ADMIN	0x00000001
+#define IATTR_WATCH	0x00000002
+#define IATTR_HIDE	0x00000004
+#define IATTR_FLAGS	0x00000007
+
+#define IATTR_BARRIER	0x00010000
+#define IATTR_IUNLINK	0x00020000
+#define IATTR_IMMUTABLE 0x00040000
+
+#ifdef	__KERNEL__
+
+#ifndef	CONFIG_VSERVER
+#warning config options missing
+#endif
+
+#ifdef	CONFIG_VSERVER_PROC_SECURE
+#define IATTR_PROC_DEFAULT	( IATTR_ADMIN | IATTR_HIDE )
+#define IATTR_PROC_SYMLINK	( IATTR_ADMIN )
+#else
+#define IATTR_PROC_DEFAULT	( IATTR_ADMIN )
+#define IATTR_PROC_SYMLINK	( IATTR_ADMIN )
+#endif
+
+#define vx_hide_check(c,m)	(((m) & IATTR_HIDE) ? vx_check(c,m) : 1)
+
+#endif	/* __KERNEL__ */
+
+/* inode ioctls */
+
+#define FIOC_GETXFLG	_IOR('x', 5, long)
+#define FIOC_SETXFLG	_IOW('x', 6, long)
+
+#else	/* _VX_INODE_H */
+#warning duplicate inclusion
+#endif	/* _VX_INODE_H */
--- linux-2.6.11.11/kernel/vserver/inode.c	1970-01-01 01:00:00 +0100
+++ linux-2.6.11.11-vs2.0-rc3/kernel/vserver/inode.c	2005-06-01 14:34:17 +0200
@@ -0,0 +1,365 @@
+/*
+ *  linux/kernel/vserver/inode.c
+ *
+ *  Virtual Server: File System Support
+ *
+ *  Copyright (C) 2004-2005  Herbert P�tzl
+ *
+ *  V0.01  separated from vcontext V0.05
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/vs_context.h>
+#include <linux/proc_fs.h>
+#include <linux/devpts_fs.h>
+#include <linux/namei.h>
+#include <linux/mount.h>
+#include <linux/parser.h>
+#include <linux/compat.h>
+#include <linux/vserver/inode.h>
+#include <linux/vserver/inode_cmd.h>
+#include <linux/vserver/xid.h>
+
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+
+static int __vc_get_iattr(struct inode *in, uint32_t *xid, uint32_t *flags, uint32_t *mask)
+{
+	struct proc_dir_entry *entry;
+
+	if (!in || !in->i_sb)
+		return -ESRCH;
+
+	*flags = IATTR_XID
+		| (IS_BARRIER(in) ? IATTR_BARRIER : 0)
+		| (IS_IUNLINK(in) ? IATTR_IUNLINK : 0)
+		| (IS_IMMUTABLE(in) ? IATTR_IMMUTABLE : 0);
+	*mask = IATTR_IUNLINK | IATTR_IMMUTABLE;
+
+	if (S_ISDIR(in->i_mode))
+		*mask |= IATTR_BARRIER;
+
+	if (in->i_sb->s_flags & MS_TAGXID) {
+		*xid = in->i_xid;
+		*mask |= IATTR_XID;
+	}
+
+	switch (in->i_sb->s_magic) {
+	case PROC_SUPER_MAGIC:
+		entry = PROC_I(in)->pde;
+
+		/* check for specific inodes? */
+		if (entry)
+			*mask |= IATTR_FLAGS;
+		if (entry)
+			*flags |= (entry->vx_flags & IATTR_FLAGS);
+		else
+			*flags |= (PROC_I(in)->vx_flags & IATTR_FLAGS);
+		break;
+
+	case DEVPTS_SUPER_MAGIC:
+		*xid = in->i_xid;
+		*mask |= IATTR_XID;
+		break;
+
+	default:
+		break;
+	}
+	return 0;
+}
+
+int vc_get_iattr(uint32_t id, void __user *data)
+{
+	struct nameidata nd;
+	struct vcmd_ctx_iattr_v1 vc_data = { .xid = -1 };
+	int ret;
+
+	if (!vx_check(0, VX_ADMIN))
+		return -ENOSYS;
+	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+
+	ret = user_path_walk_link(vc_data.name, &nd);
+	if (!ret) {
+		ret = __vc_get_iattr(nd.dentry->d_inode,
+			&vc_data.xid, &vc_data.flags, &vc_data.mask);
+		path_release(&nd);
+	}
+	if (ret)
+		return ret;
+
+	if (copy_to_user (data, &vc_data, sizeof(vc_data)))
+		ret = -EFAULT;
+	return ret;
+}
+
+#ifdef	CONFIG_COMPAT
+
+int vc_get_iattr_x32(uint32_t id, void __user *data)
+{
+	struct nameidata nd;
+	struct vcmd_ctx_iattr_v1_x32 vc_data = { .xid = -1 };
+	int ret;
+
+	if (!vx_check(0, VX_ADMIN))
+		return -ENOSYS;
+	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+
+	ret = user_path_walk_link(compat_ptr(vc_data.name_ptr), &nd);
+	if (!ret) {
+		ret = __vc_get_iattr(nd.dentry->d_inode,
+			&vc_data.xid, &vc_data.flags, &vc_data.mask);
+		path_release(&nd);
+	}
+	if (ret)
+		return ret;
+
+	if (copy_to_user (data, &vc_data, sizeof(vc_data)))
+		ret = -EFAULT;
+	return ret;
+}
+
+#endif	/* CONFIG_COMPAT */
+
+
+static int __vc_set_iattr(struct dentry *de, uint32_t *xid, uint32_t *flags, uint32_t *mask)
+{
+	struct inode *in = de->d_inode;
+	int error = 0, is_proc = 0, has_xid = 0;
+
+	if (!in || !in->i_sb)
+		return -ESRCH;
+
+	is_proc = (in->i_sb->s_magic == PROC_SUPER_MAGIC);
+	if ((*mask & IATTR_FLAGS) && !is_proc)
+		return -EINVAL;
+
+	has_xid = (in->i_sb->s_flags & MS_TAGXID) ||
+		(in->i_sb->s_magic == DEVPTS_SUPER_MAGIC);
+	if ((*mask & IATTR_XID) && !has_xid)
+		return -EINVAL;
+
+	down(&in->i_sem);
+	if (*mask & IATTR_XID)
+		in->i_xid = *xid;
+
+	if (*mask & IATTR_FLAGS) {
+		struct proc_dir_entry *entry = PROC_I(in)->pde;
+		unsigned int iflags = PROC_I(in)->vx_flags;
+
+		iflags = (iflags & ~(*mask & IATTR_FLAGS))
+			| (*flags & IATTR_FLAGS);
+		PROC_I(in)->vx_flags = iflags;
+		if (entry)
+			entry->vx_flags = iflags;
+	}
+
+	if (*mask & (IATTR_BARRIER | IATTR_IUNLINK | IATTR_IMMUTABLE)) {
+		struct iattr attr;
+
+		attr.ia_valid = ATTR_ATTR_FLAG;
+		attr.ia_attr_flags =
+			(IS_IMMUTABLE(in) ? ATTR_FLAG_IMMUTABLE : 0) |
+			(IS_IUNLINK(in) ? ATTR_FLAG_IUNLINK : 0) |
+			(IS_BARRIER(in) ? ATTR_FLAG_BARRIER : 0);
+
+		if (*mask & IATTR_IMMUTABLE) {
+			if (*flags & IATTR_IMMUTABLE)
+				attr.ia_attr_flags |= ATTR_FLAG_IMMUTABLE;
+			else
+				attr.ia_attr_flags &= ~ATTR_FLAG_IMMUTABLE;
+		}
+		if (*mask & IATTR_IUNLINK) {
+			if (*flags & IATTR_IUNLINK)
+				attr.ia_attr_flags |= ATTR_FLAG_IUNLINK;
+			else
+				attr.ia_attr_flags &= ~ATTR_FLAG_IUNLINK;
+		}
+		if (S_ISDIR(in->i_mode) && (*mask & IATTR_BARRIER)) {
+			if (*flags & IATTR_BARRIER)
+				attr.ia_attr_flags |= ATTR_FLAG_BARRIER;
+			else
+				attr.ia_attr_flags &= ~ATTR_FLAG_BARRIER;
+		}
+		if (in->i_op && in->i_op->setattr)
+			error = in->i_op->setattr(de, &attr);
+		else {
+			error = inode_change_ok(in, &attr);
+			if (!error)
+				error = inode_setattr(in, &attr);
+		}
+	}
+
+	mark_inode_dirty(in);
+	up(&in->i_sem);
+	return 0;
+}
+
+int vc_set_iattr(uint32_t id, void __user *data)
+{
+	struct nameidata nd;
+	struct vcmd_ctx_iattr_v1 vc_data;
+	int ret;
+
+	if (!capable(CAP_SYS_ADMIN) || !capable(CAP_LINUX_IMMUTABLE))
+		return -EPERM;
+	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+
+	ret = user_path_walk_link(vc_data.name, &nd);
+	if (!ret) {
+		ret = __vc_set_iattr(nd.dentry,
+			&vc_data.xid, &vc_data.flags, &vc_data.mask);
+		path_release(&nd);
+	}
+
+	if (copy_to_user (data, &vc_data, sizeof(vc_data)))
+		ret = -EFAULT;
+	return ret;
+}
+
+#ifdef	CONFIG_COMPAT
+
+int vc_set_iattr_x32(uint32_t id, void __user *data)
+{
+	struct nameidata nd;
+	struct vcmd_ctx_iattr_v1_x32 vc_data;
+	int ret;
+
+	if (!capable(CAP_SYS_ADMIN) || !capable(CAP_LINUX_IMMUTABLE))
+		return -EPERM;
+	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+
+	ret = user_path_walk_link(compat_ptr(vc_data.name_ptr), &nd);
+	if (!ret) {
+		ret = __vc_set_iattr(nd.dentry,
+			&vc_data.xid, &vc_data.flags, &vc_data.mask);
+		path_release(&nd);
+	}
+
+	if (copy_to_user (data, &vc_data, sizeof(vc_data)))
+		ret = -EFAULT;
+	return ret;
+}
+
+#endif	/* CONFIG_COMPAT */
+
+#ifdef	CONFIG_VSERVER_LEGACY
+
+#define PROC_DYNAMIC_FIRST 0xF0000000UL
+
+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)
+		return -ENOTTY;
+
+	entry = PROC_I(inode)->pde;
+	if (!entry)
+		return -ENOTTY;
+
+	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;
+}
+#endif
+
+
+int vx_parse_xid(char *string, xid_t *xid, int remove)
+{
+	static match_table_t tokens = {
+		{1, "xid=%u"},
+		{0, NULL}
+	};
+	substring_t args[MAX_OPT_ARGS];
+	int token, option = 0;
+
+	if (!string)
+		return 0;
+
+	token = match_token(string, tokens, args);
+	if (token && xid && !match_int(args, &option))
+		*xid = option;
+
+	vxdprintk(VXD_CBIT(xid, 7),
+		"vx_parse_xid(�%s�): %d:#%d",
+		string, token, option);
+
+	if (token && remove) {
+		char *p = strstr(string, "xid=");
+		char *q = p;
+
+		if (p) {
+			while (*q != '\0' && *q != ',')
+				q++;
+			while (*q)
+				*p++ = *q++;
+			while (*p)
+				*p++ = '\0';
+		}
+	}
+	return token;
+}
+
+void vx_propagate_xid(struct nameidata *nd, struct inode *inode)
+{
+	xid_t new_xid = 0;
+	struct vfsmount *mnt;
+	int propagate;
+
+	if (!nd)
+		return;
+	mnt = nd->mnt;
+	if (!mnt)
+		return;
+
+	propagate = (mnt->mnt_flags & MNT_XID);
+	if (propagate)
+		new_xid = mnt->mnt_xid;
+
+	vxdprintk(VXD_CBIT(xid, 7),
+		"vx_propagate_xid(%p[#%lu.%d]): %d,%d",
+		inode, inode->i_ino, inode->i_xid,
+		new_xid, (propagate)?1:0);
+
+	if (propagate)
+		inode->i_xid = new_xid;
+}
+
+#include <linux/module.h>
+
+EXPORT_SYMBOL_GPL(vx_propagate_xid);
+
--- linux-2.6.11.11/mm/shmem.c	2005-03-02 12:39:08 +0100
+++ linux-2.6.11.11-vs2.0-rc3/mm/shmem.c	2005-06-01 14:34:17 +0200
@@ -51,7 +51,6 @@
 #include <asm/pgtable.h>
 
 /* This magic number is used in glibc for posix shared memory */
-#define TMPFS_MAGIC	0x01021994
 
 #define ENTRIES_PER_PAGE (PAGE_CACHE_SIZE/sizeof(unsigned long))
 #define ENTRIES_PER_PAGEPAGE (ENTRIES_PER_PAGE*ENTRIES_PER_PAGE)
--- linux-2.6.11.11/mm/shmem.c	2005-03-02 12:39:08 +0100
+++ linux-2.6.11.11-vs2.0-rc3/mm/shmem.c	2005-06-01 14:34:17 +0200
@@ -1604,7 +1603,7 @@ static int shmem_statfs(struct super_blo
 {
 	struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
 
-	buf->f_type = TMPFS_MAGIC;
+	buf->f_type = TMPFS_SUPER_MAGIC;
 	buf->f_bsize = PAGE_CACHE_SIZE;
 	buf->f_namelen = NAME_MAX;
 	if (sbinfo) {
--- linux-2.6.11.11/mm/shmem.c	2005-03-02 12:39:08 +0100
+++ linux-2.6.11.11-vs2.0-rc3/mm/shmem.c	2005-06-01 14:34:17 +0200
@@ -2002,7 +2001,7 @@ static int shmem_fill_super(struct super
 	sb->s_maxbytes = SHMEM_MAX_BYTES;
 	sb->s_blocksize = PAGE_CACHE_SIZE;
 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-	sb->s_magic = TMPFS_MAGIC;
+	sb->s_magic = TMPFS_SUPER_MAGIC;
 	sb->s_op = &shmem_ops;
 	inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
 	if (!inode)