* 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