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 #include #include +#include #include #include @@ -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)