blob: 3b77817a49e794a3f4c218ec47fd2cf34176f387 [file] [log] [blame]
Howard McLauchlanef4154b2018-03-16 16:50:26 -07001Some examples for inject
2
3inject guarantees the appropriate erroneous return of the specified injection
4mode(kmalloc,bio,etc) given a call chain and an optional set of predicates. You
5can also optionally print out the generated BPF program for
6modification/debugging purposes.
7
8For example, suppose you want to fail kmalloc() from mount_subtree() when called
9from btrfs_mount():
10
11# ./inject.py kmalloc -I 'linux/mm.h' -I 'linux/fs.h' -v '(true)<-
12mount_subtree(struct vfsmount *mnt, const char *name) (true) <-
13btrfs_mount(struct file_system_type *fs_type, int flags, const char
14*device_name, void *data)'
15
16The first argument indicates the mode(or what to fail). Appropriate headers
17are specified. The verbosity flag prints the generated program.
18
19Note that btrfs_mount() has no accompanying predicate. In such cases the program
20defaults to (true).
21
22Next, lets say we want to hit one of the BUG_ONs in fs/btrfs. As of 4.16-rc3,
23there is a BUG_ON in btrfs_prepare_close_one_device() at fs/btrfs/volumes.c:1002
24
25To hit this, we can use the following:
26
27# ./inject.py kmalloc -v -I 'linux/mm.h' '(true)<- btrfs_alloc_device(struct
28btrfs_fs_info *fs_info, const u64 *ded, const u8 *uuid)(true)<-
29btrfs_close_devices(struct btrfs_fs_devices *fs_devices)(true)'
30
31While the script was executing, I mounted and unmounted btrfs, causing a
32segfault on umount(since that satisfied the call path indicated). A look at
33dmesg will confirm we successfully hit that BUG_ON and caused a panic.
34
35In general, it's worth noting that the required specificity of the call chain is
36dependent on how much granularity you need. The example above might have
37performed as expected without the intermediate btrfs_alloc_device, but might
38have also done something unexpected(an earlier kmalloc could have failed before
39the one we were targetting).
40
41For hot paths, the approach outlined above isn't enough. If a path is traversed
42very often, we can distinguish distinct calls with function arguments. Let's say
43we want to fail the dentry allocation of a file creatively named 'bananas'. We
44can do the following:
45
46# ./inject.py kmalloc -v -I 'linux/fs.h' '(true) <- d_alloc_parallel(struct
47dentry *parent, const struct qstr *name, wait_queue_head_t *wq)
48(STRCMP(name->name, 'bananas'))'
49
50While this script is executing, any operation that would cause a dentry
51allocation where the name is 'bananas' fails, as expected.
52
53To note, STRCMP is a workaround for some rewriter issues. It will take input of
54the form (x->...->z, 'literal'), and generate some equivalent code that the
55verifier is more friendly about. It's not horribly robust, but works for the
56purposes of making string comparisons a bit easier.
57
58Finally, we briefly demonstrate how to inject bio failures. The mechanism is
59identical, so any information from above will apply.
60
61Let's say we want to fail bio requests when the request is to some specific
62sector. An example use case would be to fail superblock writes in btrfs. For
63btrfs, we know that there must be a superblock at 65536 bytes, or sector 128.
64This allows us to run the following:
65
66# ./inject.py bio -v -I 'linux/blkdev.h' '(({struct gendisk *d = bio->bi_disk;
67struct disk_part_tbl *tbl = d->part_tbl; struct hd_struct **parts = (void *)tbl +
68sizeof(struct disk_part_tbl); struct hd_struct **partp = parts + bio->bi_partno;
69struct hd_struct *p = *partp; dev_t disk = p->__dev.devt; disk ==
70MKDEV(254,16);}) && bio->bi_iter.bi_sector == 128)'
71
72The predicate in the command above has two parts. The first is a compound
73statement which shortens to "only if the system is btrfs", but is long due
74to rewriter/verifier shenanigans. The major/minor information can be found
75however; I used Python. The second part simply checks the starting
76address of bi_iter. While executing, this script effectively fails superblock
77writes to the superblock at sector 128 without affecting other filesystems.
78
79As an extension to the above, one could easily fail all btrfs superblock writes
80(we only fail the primary) by calculating the sector number of the mirrors and
81amending the predicate accordingly.