1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2026 Christian Brauner <brauner@kernel.org> */ 3 4 /* 5 * BPF LSM block device integrity tracker for dm-verity. 6 * 7 * Tracks block devices in a hashmap keyed by bd_dev. When dm-verity 8 * calls security_bdev_setintegrity() during verity_preresume(), the 9 * setintegrity hook records the roothash and signature-validity data. 10 * The free hook cleans up when the device goes away. The alloc hook 11 * counts allocations for test validation. 12 * 13 * The sleepable hooks exercise bpf_copy_from_user() to verify that 14 * the sleepable classification actually permits sleepable helpers. 15 */ 16 17 #include "vmlinux.h" 18 #include <bpf/bpf_helpers.h> 19 #include <bpf/bpf_tracing.h> 20 21 struct verity_info { 22 __u8 has_roothash; /* LSM_INT_DMVERITY_ROOTHASH seen */ 23 __u8 sig_valid; /* LSM_INT_DMVERITY_SIG_VALID value (non-NULL = valid) */ 24 __u32 setintegrity_cnt; /* total setintegrity calls for this dev */ 25 }; 26 27 struct { 28 __uint(type, BPF_MAP_TYPE_HASH); 29 __uint(max_entries, 64); 30 __type(key, __u32); /* dev_t from bdev->bd_dev */ 31 __type(value, struct verity_info); 32 } verity_devices SEC(".maps"); 33 34 /* Global counters exposed to userspace via skeleton bss. */ 35 int alloc_count; 36 37 char _license[] SEC("license") = "GPL"; 38 39 SEC("lsm.s/bdev_setintegrity") 40 int BPF_PROG(bdev_setintegrity, struct block_device *bdev, 41 enum lsm_integrity_type type, const void *value, size_t size) 42 { 43 struct verity_info zero = {}; 44 struct verity_info *info; 45 __u32 dev; 46 char buf; 47 48 /* 49 * Exercise a sleepable helper to confirm the verifier 50 * allows it in this sleepable hook. 51 */ 52 (void)bpf_copy_from_user(&buf, sizeof(buf), NULL); 53 54 dev = bdev->bd_dev; 55 56 info = bpf_map_lookup_elem(&verity_devices, &dev); 57 if (!info) { 58 bpf_map_update_elem(&verity_devices, &dev, &zero, BPF_NOEXIST); 59 info = bpf_map_lookup_elem(&verity_devices, &dev); 60 if (!info) 61 return 0; 62 } 63 64 if (type == LSM_INT_DMVERITY_ROOTHASH) 65 info->has_roothash = 1; 66 else if (type == LSM_INT_DMVERITY_SIG_VALID) 67 info->sig_valid = (value != NULL); 68 69 __sync_fetch_and_add(&info->setintegrity_cnt, 1); 70 71 return 0; 72 } 73 74 SEC("lsm/bdev_free_security") 75 void BPF_PROG(bdev_free_security, struct block_device *bdev) 76 { 77 __u32 dev = bdev->bd_dev; 78 79 bpf_map_delete_elem(&verity_devices, &dev); 80 } 81 82 SEC("lsm.s/bdev_alloc_security") 83 int BPF_PROG(bdev_alloc_security, struct block_device *bdev) 84 { 85 char buf; 86 87 /* 88 * Exercise a sleepable helper to confirm the verifier 89 * allows it in this sleepable hook. 90 */ 91 (void)bpf_copy_from_user(&buf, sizeof(buf), NULL); 92 93 __sync_fetch_and_add(&alloc_count, 1); 94 95 return 0; 96 } 97