diff -NurpP --minimal linux-2.6.19.1-vs2.1.1.6/fs/block_dev.c linux-2.6.19.1-vs2.1.1.6.2/fs/block_dev.c
--- linux-2.6.19.1-vs2.1.1.6/fs/block_dev.c	2006-12-11 23:59:46 +0100
+++ linux-2.6.19.1-vs2.1.1.6.2/fs/block_dev.c	2006-12-13 22:24:06 +0100
@@ -377,6 +377,7 @@ struct block_device *bdget(dev_t dev)
 		bdev->bd_invalidated = 0;
 		inode->i_mode = S_IFBLK;
 		inode->i_rdev = dev;
+		inode->i_mdev = dev;
 		inode->i_bdev = bdev;
 		inode->i_data.a_ops = &def_blk_aops;
 		mapping_set_gfp_mask(&inode->i_data, GFP_USER);
@@ -426,8 +427,7 @@ static struct block_device *bd_acquire(s
 	}
 	spin_unlock(&bdev_lock);
 
-	mdev = inode->i_rdev;
-	if (!vs_map_blkdev(&mdev, DATTR_OPEN))
+	if (!vs_map_blkdev(inode->i_rdev, &mdev, DATTR_OPEN))
 		return NULL;
 	inode->i_mdev = mdev;
 
diff -NurpP --minimal linux-2.6.19.1-vs2.1.1.6/fs/char_dev.c linux-2.6.19.1-vs2.1.1.6.2/fs/char_dev.c
--- linux-2.6.19.1-vs2.1.1.6/fs/char_dev.c	2006-12-12 00:12:09 +0100
+++ linux-2.6.19.1-vs2.1.1.6.2/fs/char_dev.c	2006-12-13 22:23:14 +0100
@@ -369,10 +369,10 @@ int chrdev_open(struct inode * inode, st
 	if (!p) {
 		struct kobject *kobj;
 		int idx;
-		dev_t mdev = inode->i_rdev;
+		dev_t mdev;
 
 		spin_unlock(&cdev_lock);
-		if (!vs_map_chrdev(&mdev, DATTR_OPEN))
+		if (!vs_map_chrdev(inode->i_rdev, &mdev, DATTR_OPEN))
 			return -EPERM;
 		inode->i_mdev = mdev;
 
diff -NurpP --minimal linux-2.6.19.1-vs2.1.1.6/fs/namei.c linux-2.6.19.1-vs2.1.1.6.2/fs/namei.c
--- linux-2.6.19.1-vs2.1.1.6/fs/namei.c	2006-11-30 19:41:35 +0100
+++ linux-2.6.19.1-vs2.1.1.6.2/fs/namei.c	2006-12-13 23:11:56 +0100
@@ -37,6 +37,7 @@
 #include <linux/vs_base.h>
 #include <linux/vs_tag.h>
 #include <linux/vs_cowbl.h>
+#include <linux/vs_device.h>
 #include <asm/namei.h>
 #include <asm/uaccess.h>
 
@@ -1931,9 +1932,20 @@ int vfs_mknod(struct inode *dir, struct 
 	if (error)
 		return error;
 
-	if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD))
+	if (!(S_ISCHR(mode) || S_ISBLK(mode)))
+		goto okay;
+
+	if (!capable(CAP_MKNOD))
 		return -EPERM;
 
+	if (vx_check(0, VS_ADMIN|VS_WATCH))
+		goto okay;
+
+	if (S_ISCHR(mode) && !vs_chrdev_perm(dev, DATTR_CREATE))
+		return -EPERM;
+	if (S_ISBLK(mode) && !vs_blkdev_perm(dev, DATTR_CREATE))
+		return -EPERM;
+okay:
 	if (!dir->i_op || !dir->i_op->mknod)
 		return -EPERM;
 
diff -NurpP --minimal linux-2.6.19.1-vs2.1.1.6/include/linux/vs_device.h linux-2.6.19.1-vs2.1.1.6.2/include/linux/vs_device.h
--- linux-2.6.19.1-vs2.1.1.6/include/linux/vs_device.h	2006-12-11 23:58:22 +0100
+++ linux-2.6.19.1-vs2.1.1.6.2/include/linux/vs_device.h	2006-12-13 23:01:59 +0100
@@ -6,19 +6,38 @@
 #include "vserver/debug.h"
 
 
-int vs_map_device(struct vx_info *, dev_t *, umode_t);
+#ifdef CONFIG_VSERVER_DEVICE
 
-#define	vs_map_chrdev(d,p) \
-	((vs_map_device(current_vx_info(), d, S_IFCHR) & (p)) == (p))
-#define	vs_map_blkdev(d,p) \
-	((vs_map_device(current_vx_info(), d, S_IFBLK) & (p)) == (p))
+int vs_map_device(struct vx_info *, dev_t, dev_t *, umode_t);
 
-int vs_device_permission(struct vx_info *, dev_t, umode_t, int);
+#define vs_device_perm(v,d,m,p) \
+	((vs_map_device(current_vx_info(), d, NULL, m) & (p)) == (p))
 
-#define	vs_chrdev_permission(d,p) \
-	vs_device_permission(current_vx_info(), d, S_IFCHR, p)
-#define	vs_blkdev_permission(d,p) \
-	vs_device_permission(current_vx_info(), d, S_IFBLK, p)
+#else
+
+static inline
+int vs_map_device(struct vx_info *vxi,
+	dev_t device, dev_t *target, umode_t mode)
+{
+	if (target)
+		*target = device;
+	return ~0;
+}
+
+#define vs_device_perm(v,d,m,p) ((p) == (p))
+
+#endif
+
+
+#define vs_map_chrdev(d,t,p) \
+	((vs_map_device(current_vx_info(), d, t, S_IFCHR) & (p)) == (p))
+#define vs_map_blkdev(d,t,p) \
+	((vs_map_device(current_vx_info(), d, t, S_IFBLK) & (p)) == (p))
+
+#define vs_chrdev_perm(d,p) \
+	vs_device_perm(current_vx_info(), d, S_IFCHR, p)
+#define vs_blkdev_perm(d,p) \
+	vs_device_perm(current_vx_info(), d, S_IFBLK, p)
 
 
 #else
diff -NurpP --minimal linux-2.6.19.1-vs2.1.1.6/kernel/vserver/device.c linux-2.6.19.1-vs2.1.1.6.2/kernel/vserver/device.c
--- linux-2.6.19.1-vs2.1.1.6/kernel/vserver/device.c	2006-12-13 07:51:16 +0100
+++ linux-2.6.19.1-vs2.1.1.6.2/kernel/vserver/device.c	2006-12-13 22:52:49 +0100
@@ -115,11 +115,13 @@ static inline int __lookup_mapping(struc
 			!((vdm->flags ^ mode) & S_IFMT))
 			goto found;
 	}
-	ret = 0;
+
+	/* compatible default for now */
 	if (target)
 		*target = device;
 	if (flags)
-		*flags = DATTR_OPEN|DATTR_CREATE;
+		*flags = DATTR_OPEN;
+	ret = 0;
 	goto out;
 found:
 	if (target)
@@ -134,41 +136,24 @@ out:
 
 
 
-int vs_map_device(struct vx_info *vxi, dev_t *device, umode_t mode)
+int vs_map_device(struct vx_info *vxi,
+	dev_t device, dev_t *target, umode_t mode)
 {
-	dev_t target = ~0;
-	int ret, flags = 0;
-
-	if (!vxi && 0)
-		return DATTR_MASK;
+	int ret, flags = DATTR_MASK;
 
-	ret = __lookup_mapping(vxi, *device, &target, &flags, mode);
+	if (!vxi) {
+		if (target)
+			*target = device;
+		goto out;
+	}
+	ret = __lookup_mapping(vxi, device, target, &flags, mode);
 	printk("��� mapping device: %08x target: %08x flags: %04x mode: %04x mapped=%d\n",
-		*device, target, flags, mode, ret);
-
-	*device = target;
+		device, target ? *target : 0, flags, mode, ret);
+out:
 	return (flags & DATTR_MASK);
 }
 
 
-int vs_device_permission(struct vx_info *vxi,
-	dev_t device, umode_t mode, int perm)
-{
-	int ret, flags = 0;
-
-	if (!vxi && 0)
-		return -1;
-
-	ret = __lookup_mapping(vxi, device, NULL, &flags, mode);
-	printk("��� device perm: %08x flags/perm: %04x/%04x mode: %04x mapped=%d\n",
-		device, flags, perm, mode, ret);
-	
-	if ((flags & perm) != perm)
-		return 0;
-	return flags;
-}
-
-
 
 int do_set_mapping(struct vx_info *vxi,
 	dev_t device, dev_t target, int flags, umode_t mode)