Home | History | Annotate | Download | only in docs
      1 ## Headerparser
      2 
      3 headerparser is a tool that assists in writing device system call descriptions for syzkaller.
      4 
      5 In order to make syzkaller smarter when it comes to fuzzing a device node, you can provide it with
      6 information about the ioctl argument struct types it expects.
      7 
      8 However, in certain cases the number of argument struct types might be high, increasing the amount of manual
      9 effort that goes into writing the description files for the struct types.
     10 
     11 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).
     12 
     13 ## Dependencies
     14 Headerlib uses pycparser. You can install pycparser using pip.
     15 
     16 ```shell
     17 $ pip install pycparser
     18 ```
     19 
     20 ## Using headerparser
     21 ```shell
     22 $ python headerparser.py --filenames=./test_headers/th_b.h
     23 B {
     24           B1     len|fileoff|flags|intN     #(unsigned long)
     25           B2     len|fileoff|flags|intN     #(unsigned long)
     26 }
     27 struct_containing_union {
     28           something          len|fileoff|flags|int32                   #(int)
     29           a_union.a_char     ptr[in|out, string]|ptr[in, filename]     #(char*)
     30           a_union.B_ptr      ptr|buffer|array                          #(struct B*)
     31 }
     32 ```
     33 
     34 You can copy paste the content underneath the `Structure Metadata` over to your syzkaller device description.
     35 
     36 ## Something breaks
     37 Let us try parsing `test_headers/th_a.h` header file to generate argument structs.
     38 
     39 ```shell
     40 $ python headerparser.py --filenames=./test_headers/th_a.h
     41 ERROR:root:HeaderFilePreprocessorException: /tmp/tmpW8xzty/source.o:36:2: before: some_type
     42 
     43 $ python headerparser.py --filenames=./test_headers/th_a.h --debug
     44 DEBUG:GlobalHierarchy:load_header_files : ['./test_headers/th_a.h']
     45 DEBUG:HeaderFilePreprocessor:HeaderFilePreprocessor._mktempfiles: sourcefile=/tmp/tmpbBQYhR/source.cobjectfile=/tmp/tmpbBQYhR/source.o
     46 DEBUG:HeaderFilePreprocessor:HeaderFilePreprocessor.execute: cp ./test_headers/th_a.h /tmp/tmpbBQYhR
     47 DEBUG:HeaderFilePreprocessor:HeaderFilePreprocessor.execute: gcc -I. -E -P -c /tmp/tmpbBQYhR/source.c > /tmp/tmpbBQYhR/source.o
     48 ERROR:root:HeaderFilePreprocessorException: /tmp/tmpbBQYhR/source.o:36:2: before: some_type
     49 ```
     50 
     51 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.
     52 
     53 ```shell
     54 $ cat > include_file
     55 typedef int some_type;
     56 $ python headerparser.py --filenames=./test_headers/th_a.h --include=./include_file
     57 A {
     58           B_item              ptr|buffer|array                          #(struct B*)
     59           char_ptr            ptr[in|out, string]|ptr[in, filename]     #(char*)
     60           an_unsigned_int     len|fileoff|int32                         #(unsigned int)
     61           a_bool              _Bool                                     #(_Bool)
     62           another_bool        _Bool                                     #(_Bool)
     63           var                 some_type                                 #(some_type)
     64 }
     65 ```
     66