| ## Headerparser |
| |
| headerparser is a tool that assists in writing device system call descriptions for syzkaller. |
| |
| In order to make syzkaller smarter when it comes to fuzzing a device node, you can provide it with |
| information about the ioctl argument struct types it expects. |
| |
| However, in certain cases the number of argument struct types might be high, increasing the amount of manual |
| effort that goes into writing the description files for the struct types. |
| |
| In order to ease the effort of writing ioctl argument type description files, headerlib does a best-effort job at generating them for you. You will still need to manually select the appropriate syzkaller data type from the list of types [here](https://github.com/google/syzkaller/blob/master/docs/syscall_descriptions_syntax.md). |
| |
| ## Dependencies |
| Headerlib uses pycparser. You can install pycparser using pip. |
| |
| ```shell |
| $ pip install pycparser |
| ``` |
| |
| ## Using headerparser |
| ```shell |
| $ python headerparser.py --filenames=./test_headers/th_b.h |
| B { |
| B1 len|fileoff|flags|intN #(unsigned long) |
| B2 len|fileoff|flags|intN #(unsigned long) |
| } |
| struct_containing_union { |
| something len|fileoff|flags|int32 #(int) |
| a_union.a_char ptr[in|out, string]|ptr[in, filename] #(char*) |
| a_union.B_ptr ptr|buffer|array #(struct B*) |
| } |
| ``` |
| |
| You can copy paste the content underneath the `Structure Metadata` over to your syzkaller device description. |
| |
| ## Something breaks |
| Let us try parsing `test_headers/th_a.h` header file to generate argument structs. |
| |
| ```shell |
| $ python headerparser.py --filenames=./test_headers/th_a.h |
| ERROR:root:HeaderFilePreprocessorException: /tmp/tmpW8xzty/source.o:36:2: before: some_type |
| |
| $ python headerparser.py --filenames=./test_headers/th_a.h --debug |
| DEBUG:GlobalHierarchy:load_header_files : ['./test_headers/th_a.h'] |
| DEBUG:HeaderFilePreprocessor:HeaderFilePreprocessor._mktempfiles: sourcefile=/tmp/tmpbBQYhR/source.cobjectfile=/tmp/tmpbBQYhR/source.o |
| DEBUG:HeaderFilePreprocessor:HeaderFilePreprocessor.execute: cp ./test_headers/th_a.h /tmp/tmpbBQYhR |
| DEBUG:HeaderFilePreprocessor:HeaderFilePreprocessor.execute: gcc -I. -E -P -c /tmp/tmpbBQYhR/source.c > /tmp/tmpbBQYhR/source.o |
| ERROR:root:HeaderFilePreprocessorException: /tmp/tmpbBQYhR/source.o:36:2: before: some_type |
| ``` |
| |
| From the error message, we can see that the error occurs as pycparser is not aware of the type `some_type`. We can resolve this by making pycparser aware of the unknown type. In order to do this, we supply headerparser with a include file that contains C declarations and includes that can fix the parse error. |
| |
| ```shell |
| $ cat > include_file |
| typedef int some_type; |
| $ python headerparser.py --filenames=./test_headers/th_a.h --include=./include_file |
| A { |
| B_item ptr|buffer|array #(struct B*) |
| char_ptr ptr[in|out, string]|ptr[in, filename] #(char*) |
| an_unsigned_int len|fileoff|int32 #(unsigned int) |
| a_bool _Bool #(_Bool) |
| another_bool _Bool #(_Bool) |
| var some_type #(some_type) |
| } |
| ``` |