* remove racey is_mounted. replace with bd_claiming the device, holding it while open, and bd_releasing on close. this will still not work with things like loopback file mounts. but should get partitions, etc. right. --- lsm-2.6/security/seclvl.c~seclvl.fix03 2004-02-12 18:47:55.000000000 -0800 +++ lsm-2.6/security/seclvl.c 2004-02-12 20:03:05.000000000 -0800 @@ -535,49 +535,61 @@ return 0; } -static int is_mounted(struct inode *inode) +/* claim the blockdev to exclude mounters, release on file close */ +static int seclvl_bd_claim(struct inode *inode) { - struct super_block *sb; - if (S_ISBLK(inode->i_mode)) { - struct block_device *bdev = inode->i_bdev; - sb = get_super(bdev); - if (sb) { - drop_super(sb); - return 1; + int holder; + struct block_device *bdev = NULL; + dev_t dev = inode->i_rdev; + bdev = open_by_devnum(dev, FMODE_WRITE, BDEV_RAW); + if (bdev) { + if (bd_claim(bdev, &holder)) { + blkdev_put(bdev, BDEV_RAW); + return -EPERM; } + /* claimed, mark it to release on close */ + inode->i_security = current; } return 0; } +/* release the blockdev if you claimed it */ +static void seclvl_bd_release(struct inode *inode) +{ + if (inode && S_ISBLK(inode->i_mode) && inode->i_security == current) { + struct block_device *bdev = inode->i_bdev; + if (bdev) { + bd_release(bdev); + blkdev_put(bdev, BDEV_RAW); + inode->i_security = NULL; + } + } +} + /** * Security for writes to block devices is regulated by this seclvl - * function. + * function. Deny all writes to block devices in seclvl 2. In + * seclvl 1, we only deny writes to *mounted* block devices. */ static int seclvl_inode_permission(struct inode *inode, int mask, struct nameidata *nd) { - /* - * For now deny all writes to block devices in seclvl 1 & 2. - * We really want to only do that in 2. In seclvl 1, we only - * want to deny write to *mounted* block devices. - */ - if (current->pid == 1) - return 0; - if (S_ISBLK(inode->i_mode) && (mask & MAY_WRITE)) { + if (current->pid !=1 && S_ISBLK(inode->i_mode) && (mask & MAY_WRITE)) { switch (seclvl) { case 2: seclvl_printk(1, KERN_WARNING, "Write to block device " "denied in secure level [%d]\n", seclvl); return -EPERM; case 1: - if (is_mounted(inode)) { - seclvl_printk(1, KERN_WARNING, "Write to " - "mounted block device denied " - "in secure level [%d]\n", seclvl); + if (seclvl_bd_claim(inode)) { + seclvl_printk(1, KERN_WARNING, + "Write to mounted block device " + "denied in secure level [%d]\n", + seclvl); return -EPERM; } - } /* switch seclvl */ - } /* If attempting to write to block device */ + } + } return 0; } @@ -600,6 +612,18 @@ return 0; } +/* release busied block devices */ +static void seclvl_file_free_security(struct file *filp) +{ + struct dentry *dentry = filp->f_dentry; + struct inode *inode = NULL; + + if (dentry) { + inode = dentry->d_inode; + seclvl_bd_release(inode); + } +} + /** * Cannot unmount in secure level 2 */ @@ -638,6 +662,7 @@ .bprm_set_security = seclvl_bprm_set_security, .inode_permission = seclvl_inode_permission, .inode_setattr = seclvl_inode_setattr, + .file_free_security = seclvl_file_free_security, .settime = seclvl_settime, .sb_umount = seclvl_umount, .task_reparent_to_init = seclvl_task_reparent_to_init,
This archive was generated by hypermail 2b30 : Fri Feb 13 2004 - 15:05:56 PST