diff -NurBP --minimal linux-2.4.19-ctx14/Documentation/Configure.help linux-2.4.19-ctx14-vroot/Documentation/Configure.help --- linux-2.4.19-ctx14/Documentation/Configure.help Sat Aug 3 02:39:42 2002 +++ linux-2.4.19-ctx14-vroot/Documentation/Configure.help Sun Nov 10 23:41:56 2002 @@ -490,6 +490,11 @@ Most users will answer N here. +Virtual Root device support +CONFIG_BLK_DEV_VROOT + Saying Y here will allow you to use quota/fs ioctls on a shared + partition within a virtual server without compromising security. + Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL) CONFIG_BLK_DEV_UMEM Saying Y here will include support for the MM5415 family of diff -NurBP --minimal linux-2.4.19-ctx14/drivers/block/Config.in linux-2.4.19-ctx14-vroot/drivers/block/Config.in --- linux-2.4.19-ctx14/drivers/block/Config.in Sat Aug 3 02:39:43 2002 +++ linux-2.4.19-ctx14-vroot/drivers/block/Config.in Sun Nov 10 23:41:56 2002 @@ -40,6 +40,7 @@ dep_tristate 'Micro Memory MM5415 Battery Backed RAM support' CONFIG_BLK_DEV_UMEM $CONFIG_PCI $CONFIG_EXPERIMENTAL tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP +tristate 'Virtual Root device support' CONFIG_BLK_DEV_VROOT dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET tristate 'RAM disk support' CONFIG_BLK_DEV_RAM diff -NurBP --minimal linux-2.4.19-ctx14/drivers/block/Makefile linux-2.4.19-ctx14-vroot/drivers/block/Makefile --- linux-2.4.19-ctx14/drivers/block/Makefile Sat Aug 3 02:39:43 2002 +++ linux-2.4.19-ctx14-vroot/drivers/block/Makefile Sun Nov 10 23:41:56 2002 @@ -31,6 +31,7 @@ obj-$(CONFIG_BLK_DEV_DAC960) += DAC960.o obj-$(CONFIG_BLK_DEV_UMEM) += umem.o obj-$(CONFIG_BLK_DEV_NBD) += nbd.o +obj-$(CONFIG_BLK_DEV_VROOT) += vroot.o subdir-$(CONFIG_PARIDE) += paride diff -NurBP --minimal linux-2.4.19-ctx14/drivers/block/vroot.c linux-2.4.19-ctx14-vroot/drivers/block/vroot.c --- linux-2.4.19-ctx14/drivers/block/vroot.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.19-ctx14-vroot/drivers/block/vroot.c Sun Nov 10 23:41:57 2002 @@ -0,0 +1,334 @@ +/* + * linux/drivers/block/vroot.c + * + * Written by Herbert Pötzl, 9/11/2002 + * + * based on the loop.c code by Theodore Ts'o. + * + * Copyright 2002 by Herbert Pötzl. Redistribution of this file is + * permitted under the GNU General Public License. + * + */ + +#define MAJOR_NR VROOT_MAJOR + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "vroot.h" + +static int max_vroot = 4; +static struct vroot_device *vroot_dev; +static devfs_handle_t devfs_handle; /* For the directory */ + +#ifdef MODULE +typedef kdev_t (*vroot_get_dev_f)(int dev); + +extern int register_vroot_get_dev(vroot_get_dev_f); +extern int unregister_vroot_get_dev(vroot_get_dev_f); + +static kdev_t _vroot_get_dev(int dev) +#else + kdev_t vroot_get_dev(int dev) +#endif +{ + struct vroot_device *vr; + + if (dev >= max_vroot) + return NODEV; + + vr = &vroot_dev[dev]; + if (vr->vr_state != Vr_bound) + return NODEV; + printk(KERN_INFO "vroot[%d]_get_dev: dev(%d,%d)\n", + dev, MAJOR(vr->vr_device), MINOR(vr->vr_device)); + return vr->vr_device; +} + +static int vroot_set_dev( + struct vroot_device *vr, + struct file *vr_file, + kdev_t dev, + unsigned int arg) +{ + struct file *file; + struct inode *inode; + int error; + + MOD_INC_USE_COUNT; + + error = -EBUSY; + if (vr->vr_state != Vr_unbound) + goto out; + + error = -EBADF; + file = fget(arg); + if (!file) + goto out; + + error = -EINVAL; + inode = file->f_dentry->d_inode; + + if (S_ISBLK(inode->i_mode)) { + vr->vr_device = inode->i_rdev; + if (vr->vr_device == dev) { + error = -EBUSY; + goto out_fput; + } + } else + goto out_fput; + + printk(KERN_INFO "vroot[%d]_set_dev: dev(%d,%d)\n", + vr->vr_number, + MAJOR(inode->i_rdev), MINOR(inode->i_rdev)); + + vr->vr_state = Vr_bound; + fput(file); + return 0; + out_fput: + fput(file); + out: + MOD_DEC_USE_COUNT; + return error; +} + +static int vroot_clr_dev( + struct vroot_device *vr, + struct file *vr_file, + kdev_t dev) +{ + if (vr->vr_state != Vr_bound) + return -ENXIO; + if (vr->vr_refcnt > 1) /* we needed one fd for the ioctl */ + return -EBUSY; + + printk(KERN_INFO "vroot[%d]_clr_dev: dev(%d,%d)\n", + vr->vr_number, + MAJOR(vr->vr_device), MINOR(vr->vr_device)); + + vr->vr_state = Vr_unbound; + vr->vr_device = NODEV; + MOD_DEC_USE_COUNT; + return 0; +} + +static int vroot_make_request( + request_queue_t *q, + int rw, + struct buffer_head *rbh) +{ + if (!buffer_locked(rbh)) + BUG(); + + if (MINOR(rbh->b_rdev) >= max_vroot) + goto out; + + printk(KERN_WARNING "vroot[%d]_make_request: denied.\n", + MINOR(rbh->b_rdev)); + out: + buffer_IO_error(rbh); + return 0; +} + +static int vr_ioctl( + struct inode * inode, + struct file * file, + unsigned int cmd, + unsigned long arg) +{ + struct vroot_device *vr; + int dev, err; + + if (!inode) + return -EINVAL; + if (MAJOR(inode->i_rdev) != MAJOR_NR) { + printk(KERN_WARNING "vr_ioctl: pseudo-major != %d\n", + MAJOR_NR); + return -ENODEV; + } + dev = MINOR(inode->i_rdev); + if (dev >= max_vroot) + return -ENODEV; + vr = &vroot_dev[dev]; + down(&vr->vr_ctl_mutex); + switch (cmd) { + case VROOT_SET_DEV: + err = vroot_set_dev(vr, file, inode->i_rdev, arg); + break; + case VROOT_CLR_DEV: + err = vroot_clr_dev(vr, file, inode->i_rdev); + break; + case VROOT_INC_USE: + MOD_INC_USE_COUNT; + err = 0; + break; + case VROOT_DEC_USE: + MOD_DEC_USE_COUNT; + err = 0; + break; + default: + err = -EINVAL; + break; + } + up(&vr->vr_ctl_mutex); + return err; +} + +static int vr_open( + struct inode *inode, + struct file *file) +{ + struct vroot_device *vr; + int dev; //, type; + + if (!inode) + return -EINVAL; + if (MAJOR(inode->i_rdev) != MAJOR_NR) { + printk(KERN_WARNING "vr_open: pseudo-major != %d\n", MAJOR_NR); + return -ENODEV; + } + dev = MINOR(inode->i_rdev); + if (dev >= max_vroot) + return -ENODEV; + + vr = &vroot_dev[dev]; + MOD_INC_USE_COUNT; + down(&vr->vr_ctl_mutex); + + vr->vr_refcnt++; + up(&vr->vr_ctl_mutex); + return 0; +} + +static int vr_release( + struct inode *inode, + struct file *file) +{ + struct vroot_device *vr; + int dev; // , type; + + if (!inode) + return 0; + if (MAJOR(inode->i_rdev) != MAJOR_NR) { + printk(KERN_WARNING "vr_release: pseudo-major != %d\n", + MAJOR_NR); + return 0; + } + dev = MINOR(inode->i_rdev); + if (dev >= max_vroot) + return 0; + + vr = &vroot_dev[dev]; + down(&vr->vr_ctl_mutex); + + vr->vr_refcnt--; + up(&vr->vr_ctl_mutex); + MOD_DEC_USE_COUNT; + return 0; +} + +static struct block_device_operations vr_fops = { + owner: THIS_MODULE, + open: vr_open, + release: vr_release, + ioctl: vr_ioctl, +}; + +/* + * And now the modules code and kernel interface. + */ +MODULE_PARM(max_vroot, "i"); +MODULE_PARM_DESC(max_vroot, "Maximum number of vroot devices (1-256)"); +MODULE_LICENSE("GPL"); + +MODULE_AUTHOR ("Herbert Pötzl"); +MODULE_DESCRIPTION ("Virtual Root Device Mapper"); + + +int __init vroot_init(void) +{ + int i; + + if ((max_vroot < 1) || (max_vroot > 256)) { + printk(KERN_WARNING "vroot: invalid max_vroot (must be between" + " 1 and 256), using default (4)\n"); + max_vroot = 4; + } + + if (devfs_register_blkdev(MAJOR_NR, "vroot", &vr_fops)) { + printk(KERN_WARNING "Unable to get major number %d for vroot" + " device\n", MAJOR_NR); + return -EIO; + } + + devfs_handle = devfs_mk_dir(NULL, "vroot", NULL); + devfs_register_series(devfs_handle, "%u", max_vroot, + DEVFS_FL_DEFAULT, MAJOR_NR, 0, + S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP, + &vr_fops, NULL); + + vroot_dev = kmalloc(max_vroot * sizeof(struct vroot_device), GFP_KERNEL); + if (!vroot_dev) + return -ENOMEM; + + blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), vroot_make_request); + + for (i = 0; i < max_vroot; i++) { + struct vroot_device *vr = &vroot_dev[i]; + memset(vr, 0, sizeof(struct vroot_device)); + init_MUTEX(&vr->vr_ctl_mutex); + vr->vr_number = i; + vr->vr_state = Vr_unbound; + } + + for (i = 0; i < max_vroot; i++) + register_disk(NULL, MKDEV(MAJOR_NR, i), 1, &vr_fops, 0); + +#ifdef MODULE + register_vroot_get_dev(_vroot_get_dev); +#endif + printk(KERN_INFO "vroot: loaded (max %d devices)\n", max_vroot); + return 0; +} + +void vroot_exit(void) +{ +#ifdef MODULE + unregister_vroot_get_dev(_vroot_get_dev); +#endif + devfs_unregister(devfs_handle); + if (devfs_unregister_blkdev(MAJOR_NR, "vroot")) + printk(KERN_WARNING "vroot: cannot unregister blkdev\n"); + + kfree(vroot_dev); +} + +module_init(vroot_init); +module_exit(vroot_exit); + +#ifndef MODULE +static int __init max_vroot_setup(char *str) +{ + max_vroot = simple_strtol(str, NULL, 0); + return 1; +} + +__setup("max_vroot=", max_vroot_setup); +#endif diff -NurBP --minimal linux-2.4.19-ctx14/drivers/block/vroot.h linux-2.4.19-ctx14-vroot/drivers/block/vroot.h --- linux-2.4.19-ctx14/drivers/block/vroot.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.19-ctx14-vroot/drivers/block/vroot.h Sun Nov 10 23:41:57 2002 @@ -0,0 +1,43 @@ +#ifndef _LINUX_VROOT_H +#define _LINUX_VROOT_H + +#include + +/* + * linux/drivers/block/vroot.h + * + * Written by Herbert Pötzl, 9/11/2002 + * + * Copyright 2002 by Herbert Pötzl. Redistribution of this file is + * permitted under the GNU General Public License. + */ + +#ifdef __KERNEL__ + +/* Possible states of device */ +enum { + Vr_unbound, + Vr_bound, +}; + +struct vroot_device { + int vr_number; + int vr_refcnt; + + struct semaphore vr_ctl_mutex; + kdev_t vr_device; + int vr_state; +}; + +#endif /* __KERNEL__ */ + +/* + * IOCTL commands --- we will commandeer 0x56 ('V') + */ + +#define VROOT_SET_DEV 0x5600 +#define VROOT_CLR_DEV 0x5601 +#define VROOT_INC_USE 0x56FE +#define VROOT_DEC_USE 0x56FF + +#endif diff -NurBP --minimal linux-2.4.19-ctx14/fs/Makefile linux-2.4.19-ctx14-vroot/fs/Makefile --- linux-2.4.19-ctx14/fs/Makefile Mon Feb 25 20:38:07 2002 +++ linux-2.4.19-ctx14-vroot/fs/Makefile Sun Nov 10 23:41:57 2002 @@ -7,7 +7,7 @@ O_TARGET := fs.o -export-objs := filesystems.o open.o dcache.o buffer.o +export-objs := filesystems.o open.o dcache.o dquot.o buffer.o mod-subdirs := nls obj-y := open.o read_write.o devices.o file_table.o buffer.o \ diff -NurBP --minimal linux-2.4.19-ctx14/fs/dquot.c linux-2.4.19-ctx14-vroot/fs/dquot.c --- linux-2.4.19-ctx14/fs/dquot.c Sat Aug 3 02:39:45 2002 +++ linux-2.4.19-ctx14-vroot/fs/dquot.c Sun Nov 10 23:41:57 2002 @@ -48,6 +48,9 @@ * (C) Copyright 1994 - 1997 Marco van Wieringen */ +#include +#include + #include #include #include @@ -1373,6 +1376,52 @@ return error; } + +#if defined(CONFIG_BLK_DEV_VROOT) || defined(CONFIG_BLK_DEV_VROOT_MODULE) +#if defined(CONFIG_BLK_DEV_VROOT_MODULE) + +static rwlock_t dquot_vroot_lock = RW_LOCK_UNLOCKED; + +typedef kdev_t (*vroot_get_dev_f)(int dev); + +static vroot_get_dev_f vroot_get_dev = NULL; + +int register_vroot_get_dev(vroot_get_dev_f func) +{ + int ret = -EBUSY; + + write_lock(&dquot_vroot_lock); + if (!vroot_get_dev) { + vroot_get_dev = func; + ret = 0; + } + write_unlock(&dquot_vroot_lock); + return ret; +} + +int unregister_vroot_get_dev(vroot_get_dev_f func) +{ + int ret = -EINVAL; + + write_lock(&dquot_vroot_lock); + if (vroot_get_dev == func) { + vroot_get_dev = NULL; + ret = 0; + } + write_unlock(&dquot_vroot_lock); + return ret; +} + +EXPORT_SYMBOL(register_vroot_get_dev); +EXPORT_SYMBOL(unregister_vroot_get_dev); + +#else /* CONFIG_BLK_DEV_VROOT */ + +extern kdev_t vroot_get_dev(int dev); + +#endif +#endif + /* * This is the system call interface. This communicates with * the user-level programs. Currently this only supports diskquota @@ -1403,11 +1452,13 @@ case Q_GETQUOTA: if (((type == USRQUOTA && current->euid != id) || (type == GRPQUOTA && !in_egroup_p(id))) && - !capable(CAP_SYS_ADMIN)) + !(capable(CAP_SYS_ADMIN) || + (current->euid == 0 && capable(CAP_QUOTACTL)))) goto out; break; default: - if (!capable(CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_ADMIN) && + !(current->euid == 0 && capable(CAP_QUOTACTL))) goto out; } @@ -1425,6 +1476,21 @@ mode = nd.dentry->d_inode->i_mode; path_release(&nd); +#if defined(CONFIG_BLK_DEV_VROOT) || defined(CONFIG_BLK_DEV_VROOT_MODULE) + if (MAJOR(dev) == VROOT_MAJOR) { + ret = -ENODEV; +#ifdef CONFIG_BLK_DEV_VROOT_MODULE + read_lock(&dquot_vroot_lock); + dev = (vroot_get_dev) ? + vroot_get_dev(MINOR(dev)) : NODEV; + read_unlock(&dquot_vroot_lock); +#else + dev = vroot_get_dev(MINOR(dev)); +#endif + if (dev == NODEV) + goto out; + } +#endif ret = -ENOTBLK; if (!S_ISBLK(mode)) goto out; diff -NurBP --minimal linux-2.4.19-ctx14/include/linux/capability.h linux-2.4.19-ctx14-vroot/include/linux/capability.h --- linux-2.4.19-ctx14/include/linux/capability.h Mon Oct 28 15:13:05 2002 +++ linux-2.4.19-ctx14-vroot/include/linux/capability.h Sun Nov 10 23:41:57 2002 @@ -284,6 +284,10 @@ #define CAP_OPENDEV 29 +/* Allow quotactl */ + +#define CAP_QUOTACTL 30 + #ifdef __KERNEL__ /* * Bounding set diff -NurBP --minimal linux-2.4.19-ctx14/include/linux/major.h linux-2.4.19-ctx14-vroot/include/linux/major.h --- linux-2.4.19-ctx14/include/linux/major.h Sat Aug 3 02:39:45 2002 +++ linux-2.4.19-ctx14-vroot/include/linux/major.h Sun Nov 10 23:41:57 2002 @@ -24,6 +24,7 @@ #define PTY_SLAVE_MAJOR 3 #define HD_MAJOR IDE0_MAJOR #define TTY_MAJOR 4 +#define VROOT_MAJOR 4 #define TTYAUX_MAJOR 5 #define LP_MAJOR 6 #define VCS_MAJOR 7