|
29 | 29 | #include <linux/msg.h>
|
30 | 30 | #include <linux/overflow.h>
|
31 | 31 | #include <linux/perf_event.h>
|
| 32 | +#include <linux/fs.h> |
32 | 33 | #include <net/flow.h>
|
33 | 34 | #include <net/sock.h>
|
34 | 35 |
|
@@ -239,6 +240,7 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
|
239 | 240 | lsm_set_blob_size(&needed->lbs_tun_dev, &blob_sizes.lbs_tun_dev);
|
240 | 241 | lsm_set_blob_size(&needed->lbs_xattr_count,
|
241 | 242 | &blob_sizes.lbs_xattr_count);
|
| 243 | + lsm_set_blob_size(&needed->lbs_bdev, &blob_sizes.lbs_bdev); |
242 | 244 | }
|
243 | 245 |
|
244 | 246 | /* Prepare LSM for initialization. */
|
@@ -419,6 +421,7 @@ static void __init ordered_lsm_init(void)
|
419 | 421 | init_debug("task blob size = %d\n", blob_sizes.lbs_task);
|
420 | 422 | init_debug("tun device blob size = %d\n", blob_sizes.lbs_tun_dev);
|
421 | 423 | init_debug("xattr slots = %d\n", blob_sizes.lbs_xattr_count);
|
| 424 | + init_debug("bdev blob size = %d\n", blob_sizes.lbs_bdev); |
422 | 425 |
|
423 | 426 | /*
|
424 | 427 | * Create any kmem_caches needed for blobs
|
@@ -758,6 +761,28 @@ static int lsm_msg_msg_alloc(struct msg_msg *mp)
|
758 | 761 | GFP_KERNEL);
|
759 | 762 | }
|
760 | 763 |
|
| 764 | +/** |
| 765 | + * lsm_bdev_alloc - allocate a composite block_device blob |
| 766 | + * @bdev: the block_device that needs a blob |
| 767 | + * |
| 768 | + * Allocate the block_device blob for all the modules |
| 769 | + * |
| 770 | + * Returns 0, or -ENOMEM if memory can't be allocated. |
| 771 | + */ |
| 772 | +static int lsm_bdev_alloc(struct block_device *bdev) |
| 773 | +{ |
| 774 | + if (blob_sizes.lbs_bdev == 0) { |
| 775 | + bdev->bd_security = NULL; |
| 776 | + return 0; |
| 777 | + } |
| 778 | + |
| 779 | + bdev->bd_security = kzalloc(blob_sizes.lbs_bdev, GFP_KERNEL); |
| 780 | + if (!bdev->bd_security) |
| 781 | + return -ENOMEM; |
| 782 | + |
| 783 | + return 0; |
| 784 | +} |
| 785 | + |
761 | 786 | /**
|
762 | 787 | * lsm_early_task - during initialization allocate a composite task blob
|
763 | 788 | * @task: the task that needs a blob
|
@@ -5658,6 +5683,84 @@ int security_locked_down(enum lockdown_reason what)
|
5658 | 5683 | }
|
5659 | 5684 | EXPORT_SYMBOL(security_locked_down);
|
5660 | 5685 |
|
| 5686 | +/** |
| 5687 | + * security_bdev_alloc() - Allocate a block device LSM blob |
| 5688 | + * @bdev: block device |
| 5689 | + * |
| 5690 | + * Allocate and attach a security structure to @bdev->bd_security. The |
| 5691 | + * security field is initialized to NULL when the bdev structure is |
| 5692 | + * allocated. |
| 5693 | + * |
| 5694 | + * Return: Return 0 if operation was successful. |
| 5695 | + */ |
| 5696 | +int security_bdev_alloc(struct block_device *bdev) |
| 5697 | +{ |
| 5698 | + int rc = 0; |
| 5699 | + |
| 5700 | + rc = lsm_bdev_alloc(bdev); |
| 5701 | + if (unlikely(rc)) |
| 5702 | + return rc; |
| 5703 | + |
| 5704 | + rc = call_int_hook(bdev_alloc_security, bdev); |
| 5705 | + if (unlikely(rc)) |
| 5706 | + security_bdev_free(bdev); |
| 5707 | + |
| 5708 | + return rc; |
| 5709 | +} |
| 5710 | +EXPORT_SYMBOL(security_bdev_alloc); |
| 5711 | + |
| 5712 | +/** |
| 5713 | + * security_bdev_free() - Free a block device's LSM blob |
| 5714 | + * @bdev: block device |
| 5715 | + * |
| 5716 | + * Deallocate the bdev security structure and set @bdev->bd_security to NULL. |
| 5717 | + */ |
| 5718 | +void security_bdev_free(struct block_device *bdev) |
| 5719 | +{ |
| 5720 | + if (!bdev->bd_security) |
| 5721 | + return; |
| 5722 | + |
| 5723 | + call_void_hook(bdev_free_security, bdev); |
| 5724 | + |
| 5725 | + kfree(bdev->bd_security); |
| 5726 | + bdev->bd_security = NULL; |
| 5727 | +} |
| 5728 | +EXPORT_SYMBOL(security_bdev_free); |
| 5729 | + |
| 5730 | +/** |
| 5731 | + * security_bdev_setintegrity() - Set the device's integrity data |
| 5732 | + * @bdev: block device |
| 5733 | + * @type: type of integrity, e.g. hash digest, signature, etc |
| 5734 | + * @value: the integrity value |
| 5735 | + * @size: size of the integrity value |
| 5736 | + * |
| 5737 | + * Register a verified integrity measurement of a bdev with LSMs. |
| 5738 | + * LSMs should free the previously saved data if @value is NULL. |
| 5739 | + * Please note that the new hook should be invoked every time the security |
| 5740 | + * information is updated to keep these data current. For example, in dm-verity, |
| 5741 | + * if the mapping table is reloaded and configured to use a different dm-verity |
| 5742 | + * target with a new roothash and signing information, the previously stored data |
| 5743 | + * in the LSM blob will become obsolete. It is crucial to re-invoke the hook to |
| 5744 | + * refresh these data and ensure they are up to date. This necessity arises from |
| 5745 | + * the design of device-mapper, where a device-mapper device is first created, and |
| 5746 | + * then targets are subsequently loaded into it. These targets can be modified |
| 5747 | + * multiple times during the device's lifetime. Therefore, while the LSM blob is |
| 5748 | + * allocated during the creation of the block device, its actual contents are |
| 5749 | + * not initialized at this stage and can change substantially over time. This |
| 5750 | + * includes alterations from data that the LSMs 'trusts' to those they do not, |
| 5751 | + * making it essential to handle these changes correctly. Failure to address |
| 5752 | + * this dynamic aspect could potentially allow for bypassing LSM checks. |
| 5753 | + * |
| 5754 | + * Return: Returns 0 on success, negative values on failure. |
| 5755 | + */ |
| 5756 | +int security_bdev_setintegrity(struct block_device *bdev, |
| 5757 | + enum lsm_integrity_type type, const void *value, |
| 5758 | + size_t size) |
| 5759 | +{ |
| 5760 | + return call_int_hook(bdev_setintegrity, bdev, type, value, size); |
| 5761 | +} |
| 5762 | +EXPORT_SYMBOL(security_bdev_setintegrity); |
| 5763 | + |
5661 | 5764 | #ifdef CONFIG_PERF_EVENTS
|
5662 | 5765 | /**
|
5663 | 5766 | * security_perf_event_open() - Check if a perf event open is allowed
|
|
0 commit comments