[PATCH 3/4] seclvl update

From: Chris Wright (chrisw@private)
Date: Fri Feb 13 2004 - 15:05:07 PST

  • Next message: Chris Wright: "[PATCH 4/4] seclvl update"

    * 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