xref: /aosp_15_r20/external/bcc/tools/inject_example.txt (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard WorkerSome examples for inject
2*387f9dfdSAndroid Build Coastguard Worker
3*387f9dfdSAndroid Build Coastguard Workerinject guarantees the appropriate erroneous return of the specified injection
4*387f9dfdSAndroid Build Coastguard Workermode (kmalloc,bio,etc) given a call chain and an optional set of predicates. You
5*387f9dfdSAndroid Build Coastguard Workercan also optionally print out the generated BPF program for
6*387f9dfdSAndroid Build Coastguard Workermodification/debugging purposes.
7*387f9dfdSAndroid Build Coastguard Worker
8*387f9dfdSAndroid Build Coastguard WorkerAs a simple example, let's say you wanted to fail all mounts. As of 4.17 we can
9*387f9dfdSAndroid Build Coastguard Workerfail syscalls directly, so let's do that:
10*387f9dfdSAndroid Build Coastguard Worker
11*387f9dfdSAndroid Build Coastguard Worker# ./inject.py kmalloc -v 'SyS_mount()'
12*387f9dfdSAndroid Build Coastguard Worker
13*387f9dfdSAndroid Build Coastguard WorkerThe first argument indicates the mode (or what to fail). Appropriate headers are
14*387f9dfdSAndroid Build Coastguard Workerspecified, if necessary. The verbosity flag prints the generated program. Note
15*387f9dfdSAndroid Build Coastguard Workerthat some syscalls will be available as 'SyS_xyz' and some will be available as
16*387f9dfdSAndroid Build Coastguard Worker'sys_xyz'. This is largely dependent on the number of arguments each syscall
17*387f9dfdSAndroid Build Coastguard Workertakes.
18*387f9dfdSAndroid Build Coastguard Worker
19*387f9dfdSAndroid Build Coastguard WorkerTrying to mount various filesystems will fail and report an inability to
20*387f9dfdSAndroid Build Coastguard Workerallocate memory, as expected.
21*387f9dfdSAndroid Build Coastguard Worker
22*387f9dfdSAndroid Build Coastguard WorkerWhenever a predicate is missing, an implicit "(true)" is inserted. The example
23*387f9dfdSAndroid Build Coastguard Workerabove can be explicitly written as:
24*387f9dfdSAndroid Build Coastguard Worker
25*387f9dfdSAndroid Build Coastguard Worker# ./inject.py kmalloc -v '(true) => SyS_mount()(true)'
26*387f9dfdSAndroid Build Coastguard Worker
27*387f9dfdSAndroid Build Coastguard WorkerThe "(true)" without an associated function is a predicate for the error
28*387f9dfdSAndroid Build Coastguard Workerinjection mechanism of the current mode. In the case of kmalloc, the predicate
29*387f9dfdSAndroid Build Coastguard Workerwould have access to the arguments of:
30*387f9dfdSAndroid Build Coastguard Worker
31*387f9dfdSAndroid Build Coastguard Worker	should_failslab(struct kmem_cache *s, gfp_t gfpflags)
32*387f9dfdSAndroid Build Coastguard Worker
33*387f9dfdSAndroid Build Coastguard WorkerOther modes work similarly.
34*387f9dfdSAndroid Build Coastguard Worker"bio" has access to the arguments of:
35*387f9dfdSAndroid Build Coastguard Worker
36*387f9dfdSAndroid Build Coastguard Worker	should_fail_bio(struct bio *bio)
37*387f9dfdSAndroid Build Coastguard Worker
38*387f9dfdSAndroid Build Coastguard Worker"alloc_page" has access to the arguments of:
39*387f9dfdSAndroid Build Coastguard Worker
40*387f9dfdSAndroid Build Coastguard Worker	should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
41*387f9dfdSAndroid Build Coastguard Worker
42*387f9dfdSAndroid Build Coastguard WorkerWe also note that it's unnecessary to state the arguments of the function if you
43*387f9dfdSAndroid Build Coastguard Workerhave no intention to reference them in the associated predicate.
44*387f9dfdSAndroid Build Coastguard Worker
45*387f9dfdSAndroid Build Coastguard WorkerNow let's say we want to be a bit more specific; suppose you want to fail
46*387f9dfdSAndroid Build Coastguard Workerkmalloc() from mount_subtree() when called from btrfs_mount(). This will fail
47*387f9dfdSAndroid Build Coastguard Workeronly btrfs mounts:
48*387f9dfdSAndroid Build Coastguard Worker
49*387f9dfdSAndroid Build Coastguard Worker# ./inject.py kmalloc -v 'mount_subtree() => btrfs_mount()'
50*387f9dfdSAndroid Build Coastguard Worker
51*387f9dfdSAndroid Build Coastguard WorkerAttempting to mount btrfs filesystem during the execution of this command will
52*387f9dfdSAndroid Build Coastguard Workeryield an error, but other filesystems will be fine.
53*387f9dfdSAndroid Build Coastguard Worker
54*387f9dfdSAndroid Build Coastguard WorkerNext, lets say we want to hit one of the BUG_ONs in fs/btrfs. As of 4.16-rc3,
55*387f9dfdSAndroid Build Coastguard Workerthere is a BUG_ON in btrfs_prepare_close_one_device() at fs/btrfs/volumes.c:1002
56*387f9dfdSAndroid Build Coastguard Worker
57*387f9dfdSAndroid Build Coastguard WorkerTo hit this, we can use the following:
58*387f9dfdSAndroid Build Coastguard Worker
59*387f9dfdSAndroid Build Coastguard Worker# ./inject.py kmalloc -v 'btrfs_alloc_device() => btrfs_close_devices()'
60*387f9dfdSAndroid Build Coastguard Worker
61*387f9dfdSAndroid Build Coastguard WorkerWhile the script was executing, I mounted and unmounted btrfs, causing a
62*387f9dfdSAndroid Build Coastguard Workersegfault on umount(since that satisfied the call path indicated). A look at
63*387f9dfdSAndroid Build Coastguard Workerdmesg will confirm that the erroneous return value injected by the script
64*387f9dfdSAndroid Build Coastguard Workertripped the BUG_ON, causing a segfault down the line.
65*387f9dfdSAndroid Build Coastguard Worker
66*387f9dfdSAndroid Build Coastguard WorkerIn general, it's worth noting that the required specificity of the call chain is
67*387f9dfdSAndroid Build Coastguard Workerdependent on how much granularity you need. The example above might have
68*387f9dfdSAndroid Build Coastguard Workerperformed as expected without the intermediate btrfs_alloc_device, but might
69*387f9dfdSAndroid Build Coastguard Workerhave also done something unexpected(an earlier kmalloc could have failed before
70*387f9dfdSAndroid Build Coastguard Workerthe one we were targeting).
71*387f9dfdSAndroid Build Coastguard Worker
72*387f9dfdSAndroid Build Coastguard WorkerFor hot paths, the approach outlined above isn't enough. If a path is traversed
73*387f9dfdSAndroid Build Coastguard Workervery often, we can distinguish distinct calls with function arguments. Let's say
74*387f9dfdSAndroid Build Coastguard Workerwe want to fail the dentry allocation of a file creatively named 'bananas'. We
75*387f9dfdSAndroid Build Coastguard Workercan do the following:
76*387f9dfdSAndroid Build Coastguard Worker
77*387f9dfdSAndroid Build Coastguard Worker# ./inject.py kmalloc -v 'd_alloc_parallel(struct dentry *parent, const struct
78*387f9dfdSAndroid Build Coastguard Workerqstr *name)(STRCMP(name->name, 'bananas'))'
79*387f9dfdSAndroid Build Coastguard Worker
80*387f9dfdSAndroid Build Coastguard WorkerWhile this script is executing, any operation that would cause a dentry
81*387f9dfdSAndroid Build Coastguard Workerallocation where the name is 'bananas' fails, as expected.
82*387f9dfdSAndroid Build Coastguard Worker
83*387f9dfdSAndroid Build Coastguard WorkerHere, since we're referencing a function argument in our predicate, we need to
84*387f9dfdSAndroid Build Coastguard Workerprovide the function signature up to the argument we're using.
85*387f9dfdSAndroid Build Coastguard Worker
86*387f9dfdSAndroid Build Coastguard WorkerTo note, STRCMP is a workaround for some rewriter issues. It will take input of
87*387f9dfdSAndroid Build Coastguard Workerthe form (x->...->z, 'literal'), and generate some equivalent code that the
88*387f9dfdSAndroid Build Coastguard Workerverifier is more friendly about. It's not horribly robust, but works for the
89*387f9dfdSAndroid Build Coastguard Workerpurposes of making string comparisons a bit easier.
90*387f9dfdSAndroid Build Coastguard Worker
91*387f9dfdSAndroid Build Coastguard WorkerFinally, we briefly demonstrate how to inject bio failures. The mechanism is
92*387f9dfdSAndroid Build Coastguard Workeridentical, so any information from above will apply.
93*387f9dfdSAndroid Build Coastguard Worker
94*387f9dfdSAndroid Build Coastguard WorkerLet's say we want to fail bio requests when the request is to some specific
95*387f9dfdSAndroid Build Coastguard Workersector. An example use case would be to fail superblock writes in btrfs. For
96*387f9dfdSAndroid Build Coastguard Workerbtrfs, we know that there must be a superblock at 65536 bytes, or sector 128.
97*387f9dfdSAndroid Build Coastguard WorkerThis allows us to run the following:
98*387f9dfdSAndroid Build Coastguard Worker
99*387f9dfdSAndroid Build Coastguard Worker# ./inject.py bio -v -I 'linux/blkdev.h'  '(({struct gendisk *d = bio->bi_disk;
100*387f9dfdSAndroid Build Coastguard Workerstruct disk_part_tbl *tbl = d->part_tbl; struct hd_struct **parts = (void *)tbl +
101*387f9dfdSAndroid Build Coastguard Workersizeof(struct disk_part_tbl); struct hd_struct **partp = parts + bio->bi_partno;
102*387f9dfdSAndroid Build Coastguard Workerstruct hd_struct *p = *partp; dev_t disk = p->__dev.devt; disk ==
103*387f9dfdSAndroid Build Coastguard WorkerMKDEV(254,16);}) && bio->bi_iter.bi_sector == 128)'
104*387f9dfdSAndroid Build Coastguard Worker
105*387f9dfdSAndroid Build Coastguard WorkerThe predicate in the command above has two parts. The first is a compound
106*387f9dfdSAndroid Build Coastguard Workerstatement which shortens to "only if the system is btrfs", but is long due
107*387f9dfdSAndroid Build Coastguard Workerto rewriter/verifier shenanigans. The major/minor information can be found
108*387f9dfdSAndroid Build Coastguard Workerhowever; I used Python. The second part simply checks the starting
109*387f9dfdSAndroid Build Coastguard Workeraddress of bi_iter. While executing, this script effectively fails superblock
110*387f9dfdSAndroid Build Coastguard Workerwrites to the superblock at sector 128 without affecting other filesystems.
111*387f9dfdSAndroid Build Coastguard Worker
112*387f9dfdSAndroid Build Coastguard WorkerAs an extension to the above, one could easily fail all btrfs superblock writes
113*387f9dfdSAndroid Build Coastguard Worker(we only fail the primary) by calculating the sector number of the mirrors and
114*387f9dfdSAndroid Build Coastguard Workeramending the predicate accordingly.
115*387f9dfdSAndroid Build Coastguard Worker
116*387f9dfdSAndroid Build Coastguard WorkerInject also provides a probability option; this allows you to fail the
117*387f9dfdSAndroid Build Coastguard Workerpath+predicates some percentage of the time. For example, let's say we want to
118*387f9dfdSAndroid Build Coastguard Workerfail our mounts half the time:
119*387f9dfdSAndroid Build Coastguard Worker
120*387f9dfdSAndroid Build Coastguard Worker# ./inject.py kmalloc -v -P 0.01 'SyS_mount()'
121*387f9dfdSAndroid Build Coastguard Worker
122*387f9dfdSAndroid Build Coastguard WorkerUSAGE message:
123*387f9dfdSAndroid Build Coastguard Workerusage: inject.py [-h] [-I header] [-P probability] [-v] [-c COUNT]
124*387f9dfdSAndroid Build Coastguard Worker                 {kmalloc,bio,alloc_page} spec
125*387f9dfdSAndroid Build Coastguard Worker
126*387f9dfdSAndroid Build Coastguard WorkerFail specified kernel functionality when call chain and predicates are met
127*387f9dfdSAndroid Build Coastguard Worker
128*387f9dfdSAndroid Build Coastguard Workerpositional arguments:
129*387f9dfdSAndroid Build Coastguard Worker  {kmalloc,bio,alloc_page}
130*387f9dfdSAndroid Build Coastguard Worker                        indicate which base kernel function to fail
131*387f9dfdSAndroid Build Coastguard Worker  spec                  specify call chain
132*387f9dfdSAndroid Build Coastguard Worker
133*387f9dfdSAndroid Build Coastguard Workeroptional arguments:
134*387f9dfdSAndroid Build Coastguard Worker  -h, --help            show this help message and exit
135*387f9dfdSAndroid Build Coastguard Worker  -I header, --include header
136*387f9dfdSAndroid Build Coastguard Worker                        additional header files to include in the BPF program
137*387f9dfdSAndroid Build Coastguard Worker  -P probability, --probability probability
138*387f9dfdSAndroid Build Coastguard Worker                        probability that this call chain will fail
139*387f9dfdSAndroid Build Coastguard Worker  -v, --verbose         print BPF program
140*387f9dfdSAndroid Build Coastguard Worker  -c COUNT, --count COUNT
141*387f9dfdSAndroid Build Coastguard Worker                        Number of fails before bypassing the override
142*387f9dfdSAndroid Build Coastguard Worker
143*387f9dfdSAndroid Build Coastguard WorkerEXAMPLES:
144*387f9dfdSAndroid Build Coastguard Worker# ./inject.py kmalloc -v 'SyS_mount()'
145*387f9dfdSAndroid Build Coastguard Worker    Fails all calls to syscall mount
146*387f9dfdSAndroid Build Coastguard Worker# ./inject.py kmalloc -v '(true) => SyS_mount()(true)'
147*387f9dfdSAndroid Build Coastguard Worker    Explicit rewriting of above
148*387f9dfdSAndroid Build Coastguard Worker# ./inject.py kmalloc -v 'mount_subtree() => btrfs_mount()'
149*387f9dfdSAndroid Build Coastguard Worker    Fails btrfs mounts only
150*387f9dfdSAndroid Build Coastguard Worker# ./inject.py kmalloc -v 'd_alloc_parallel(struct dentry *parent, const struct \
151*387f9dfdSAndroid Build Coastguard Worker    qstr *name)(STRCMP(name->name, 'bananas'))'
152*387f9dfdSAndroid Build Coastguard Worker    Fails dentry allocations of files named 'bananas'
153*387f9dfdSAndroid Build Coastguard Worker# ./inject.py kmalloc -v -P 0.01 'SyS_mount()'
154*387f9dfdSAndroid Build Coastguard Worker    Fails calls to syscall mount with 1% probability
155