aboutsummaryrefslogtreecommitdiffstats
path: root/prog/hints.go
Commit message (Collapse)AuthorAgeFilesLines
* all: use min/max functionsDmitry Vyukov2025-01-171-8/+2
| | | | They are shorter, more readable, and don't require temp vars.
* pkg/fuzzer: display hints job infoAleksandr Nogikh2024-09-021-0/+10
| | | | This will let us gain even more insight into what the fuzzer is doing.
* prog: restricts hints to at most 10 attempts per single kernel PCDmitry Vyukov2024-07-221-13/+58
| | | | | | | | | We are getting too many generated candidates, the fuzzer may not keep up with them at all (hints jobs keep growing infinitely). If a hint indeed came from the input w/o transformation, then we should guess it on the first attempt (or at least after few attempts). If it did not come from the input, or came with a non-trivial transformation, then any number of attempts won't help. So limit the total number of attempts (until the next restart).
* prog: stop mutating crashing imagesDmitry Vyukov2024-07-051-2/+3
|
* prog: don't keep uncompressed images in memory during hintsDmitry Vyukov2024-07-051-2/+8
| | | | | | Unmap the image for the duration of the execution. Execution can take a while and uncompressed images are large, since hints jobs are executed round-robin, we can have thousands of them running.
* prog: reduce amount of hint replacementsDmitry Vyukov2024-07-021-4/+23
| | | | | | | | | | | | | | | | | | | | Several optimizations to reduce amount of hint replacements: 1. Don't mutate int's that are <= 8 bits. 2. Don't mutate data that is <= 3 bytes. 3. Restrict mutation of len only value >10 and < 1<<20. Values <= 10 we can produce during normal mutation. Values > 1<<20 are presumably not length of something and we have logic to produce various large bogus lengths. 4. Include all small ints <= 16 into specialInts and remove 31, 32, 63 (don't remember where they come from). 5. Don't produce other known flags (and combinations) for flags. And a larger part computes groups of related arguments so that we don't try to produce known ioctl's from other known ioctl's, and similarly for socket/socketpair/setsockopt/etc. See comments in Target.initRelatedFields for details. Update #477
* pkg/fuzzer: deflake comparisonsAleksandr Nogikh2024-05-151-0/+14
| | | | | | Do two exec hints to only leave stable comparison argument pairs. In local experiments, it allows to reduce their count by 30-40% (on average).
* prog: enable MutateWithHints() abortionAleksandr Nogikh2024-03-141-13/+27
| | | | | The call may potentially generate a very large number of possible mutations. Add a way to abort the process.
* prog: support conditional fieldsAleksandr Nogikh2024-02-191-0/+7
| | | | | | | | | | | | | pkg/compiler restructures conditional fields in structures into unions, so we only have to implement the support for unions. Semantics is as follows: If a union has conditions, syzkaller picks the first field whose condition matches. Since we require the last union field to have no conditions, we can always construct an object. Changes from this commit aim at ensuring that the selected union fields always follow the rule above.
* all: tools/syz-env make generate resultTaras Madan2023-02-241-12/+17
|
* pkg/image: treat empty compressed image as valid imageDmitry Vyukov2022-12-221-3/+0
| | | | | | | | When we decompress images for mutation or hints, we always specially check for empty compressed data (I assume it can apper after minimization). Treat it as correct compressed and return empty decompressed data. This removes the need in special handling in users.
* prog: mutate compressed images with hintsDmitry Vyukov2022-12-221-11/+52
| | | | | | | | | | | | | | | | | | | | | | Images are very large so the generic algorithm for data arguments can produce too many mutants. For images we consider only 4/8-byte aligned ints. This is enough to handle all magic numbers and checksums. We also ignore 0 and ^uint64(0) source bytes, because there are too many of these in lots of images. With this change the fuzzer was able to get past magic checks in all of the following functions with our fake images: - in fs/befs/super.c befs_check_sb()  - in fs/freevxfs/vxfs_super.c vxfs_fill_super()  - in fs/hpfs/super.c hpfs_fill_super()  - in fs/omfs/inode.c omfs_fill_super()  - in fs/qnx6/inode.c qnx6_check_first_superblock()  - in fs/ufs/super.c ufs_fill_super() And even successfully mounted sysv filesystem and triggered "sleeping function called from invalid context in __getblk_gfp" when opening a file in the mounted filesystem.
* prog, pkg/compiler: add `BufferCompressed` buffer type & `compressed_image` ↵Hrutvik Kanabar2022-11-211-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | builtin Create the `BufferCompressed` kind of `BufferType`, which will be used to represent compressed data. Create the corresponding `compressed_image` syzlang builtin, which is backed by `BufferCompressed`. For now, no syscalls use this feature - this will be introduced in future commits. We have to be careful to decompress the data before mutating, and re-compress before storing. We make sure that any deserialised `BufferCompressed` data is valid too. `BufferCompressed` arguments are mutated using a generic heatmap. In future, we could add variants of `BufferCompressed` or populate the `BufferType` sub-kind, using it to choose different kinds of heatmap for different uncompressed data formats. Various operations on compressed data must be forbidden, so we check for `BufferCompressed` in key places. We also have to ensure `compressed_image` can only be used in syscalls that are marked `no_{generate,minimize}`. Therefore, we add a generic compiler check which allows type descriptions to require attributes on the syscalls which use them.
* pkg/compiler: add glob typeJoey Jiaojg2021-05-261-1/+1
| | | | | | | | | | | | | | | | | | | | * all: add new typename dirname The current way to check files under sysfs or proc is: - define a string to represent each file - open the file - pass the fd to write / read / close The issues above are: - Need to know what file present on target device - Need to write openat for each file With dirname added, which will open one file in the directory randomly and then pass the fd to write/read/close. * all: use typename glob to match filename Fixes #481
* all: fix comments formatDmitry Vyukov2020-07-121-1/+1
| | | | | | | Fix capitalization, dots at the end and two spaces after a period. Update #1876
* .golangci.yml: enable godot checkerDmitry Vyukov2020-06-051-3/+2
| | | | | A good one. Lots of fixed comments are contributed by episodic contributors. So it's good to catch these earlier.
* prog: remove Dir from TypeDmitry Vyukov2020-05-011-1/+1
| | | | | | | | | | | | | | | | | | Having Dir is Type is handy, but forces us to duplicate lots of types. E.g. if a struct is referenced as both in and out, then we need to have 2 copies and 2 copies of structs/types it includes. If also prevents us from having the struct type as struct identity (because we can have up to 3 of them). Revert to the old way we used to do it: propagate Dir as we walk syscall arguments. This moves lots of dir passing from pkg/compiler to prog package. Now Arg contains the dir, so once we build the tree, we can use dirs as before. Reduces size of sys/linux/gen/amd64.go from 6058336 to 5661150 (-6.6%). Update #1580
* prog: rename target.SanitizeCall to NeutralizeDmitry Vyukov2020-03-171-1/+6
| | | | | | | | | | | | | We will need a wrapper for target.SanitizeCall that will do more than just calling the target-provided function. To avoid confusion and potential mistakes, give the target function and prog function different names. Prog package will continue to call this "sanitize", which will include target's "neutralize" + more. Also refactor API a bit: we need a helper function that sanitizes the whole program because that's needed most of the time. Fixes #477 Fixes #502
* prog: don't mutate strings with enumerated valuesDmitry Vyukov2020-01-051-1/+9
| | | | | | | | | | Strings with enumerated values are frequently file names or have complete enumeration of relevant values. Mutating complete enumeration if not very profitable. Mutating file names leads to escaping paths and fuzzer messing with things it is not supposed to mess with as in: r0 = openat$apparmor_task_exec(0xffffffffffffff9c, &(0x7f0000000440)='/proc/self//exe\x00', 0x3, 0x0)
* prog: add size checks for const arguments during hints mutationVeronica Radu2019-10-031-3/+21
| | | | Update #507
* prog: don't produce the same program when mutating with hintsDmitry Vyukov2019-01-031-0/+3
| | | | | No point in producing the same program as result of mutation with hints. So don't do it.
* prog: remove several sources of non-determinismDmitry Vyukov2019-01-031-11/+23
| | | | | | | | | | | | | | Non-determinism is bad: - it leads to flaky coverage reports - it makes test failures non-reproducible Remove 4 sources of non-determinism related to maps: - file name generation - string generation - resource generation - hints generation All a test that ensures all main operations are fully deterministic.
* prog: introduce debugValidateDmitry Vyukov2018-08-021-5/+1
| | | | | | Move debug validation into a separate function. Update #538
* prog: sanitize calls after hints mutationDmitry Vyukov2018-07-121-0/+1
| | | | | | | | Hints mutation could produce unsanitized calls. Sanitize calls after hints mutation. Also sanitize on load (in validate), because bad programs can already be in corpuses. And it's just the right thing to do because sanitization rules can change over time.
* prog: don't generate filenames that escape sandboxDmitry Vyukov2018-07-081-1/+6
| | | | | | All files that fuzzer works with must be in the working dir. Using "/" is known to cause problems when fuzzer removes files there or mounts something.
* prog: dedup mutation codeDmitry Vyukov2018-05-071-7/+10
| | | | Update #538
* gometalinter: some fixes for unparamDmitry Vyukov2018-05-031-2/+2
| | | | | | But we still can't enable it as there are more [uninteresting] warnings. Update #538
* prog: support big-endian during hints matchingDmitry Vyukov2018-04-011-25/+36
| | | | | | | | | | | | Use big-endian match/replace for both blobs and ints. Sometimes we have unmarked blobs (no little/big-endian info); for ANYBLOBs we intentionally lose all marking; but even for marked ints we may need this too. Consider that kernel code does not convert the data (i.e. not ntohs(pkt->proto) == ETH_P_BATMAN), but instead converts the constant (i.e. pkt->proto == htons(ETH_P_BATMAN)). In such case we will see dynamic operand that does not match what we have in the program.
* prog: reduce nesting level in shrinkExpandDmitry Vyukov2018-03-311-16/+17
|
* prog: extend a TODO about big-endian hintsDmitry Vyukov2018-02-271-0/+4
|
* prog: add arbitrary mutation of complex structsDmitry Vyukov2018-02-251-0/+1
| | | | | | Squash complex structs into flat byte array and mutate this array with generic blob mutations. This allows to mutate what we currently consider as paddings and add/remove paddings from structs, etc.
* prog: mutate len fields based on hintsDmitry Vyukov2018-02-191-5/+0
| | | | | With the new address allocation logic, the reason to not touch len has gone.
* prog: rework address allocationDmitry Vyukov2018-02-191-3/+0
| | | | | | | | | | | | 1. mmap all memory always, without explicit mmap calls in the program. This makes lots of things much easier and removes lots of code. Makes mmap not a special syscall and allows to fuzz without mmap enabled. 2. Change address assignment algorithm. Current algorithm allocates unmapped addresses too frequently and allows collisions between arguments of a single syscall. The new algorithm analyzes actual allocations in the program and places new arguments at unused locations.
* prog: rework foreachArgDmitry Vyukov2018-02-191-3/+4
| | | | | | | | Make Foreach* callback accept the arg and a context struct that can contain lots of aux info. This (1) removes lots of unuser base/parent args, (2) provides foundation for stopping recursion, (3) allows to merge foreachSubargOffset.
* prog: don't serialize output data argsDmitry Vyukov2017-12-171-11/+9
| | | | | | | | Fixes #188 We now will write just ""/1000 to denote a 1000-byte output buffer. Also we now don't store 1000-byte buffer in memory just to denote size. Old format is still parsed.
* prog: speedup and simplify hints codeDmitry Vyukov2017-12-081-74/+46
| | | | | | | | | | | | | Clone program only once. Preallocate slices in clone. Remove the clone full mode. Always mutate args in place. Allocate replacers map lazily. Don't allocate res map at all (calculate valus on the go). Remove sliceToUint64, pad. benchmark old ns/op new ns/op delta BenchmarkHints 122100048 7466013 -93.89%
* prog: fix a data raceDmitry Vyukov2017-12-081-4/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The race initially showed up on the new benchmark (see race report below). The race indicated a wrong call passed to replaceArg, as the result we sanitized the wrong call and left the new call un-sanitized. Fix this. Add test that exposes this. Run benchmarks in race mode during presubmit (benchmarks have higher chances of uncovering races than tests). WARNING: DATA RACE Write at 0x00c42000d3f0 by goroutine 18: github.com/google/syzkaller/sys/linux.(*arch).sanitizeCall() sys/linux/init.go:155 +0x256 github.com/google/syzkaller/sys/linux.(*arch).(github.com/google/syzkaller/sys/linux.sanitizeCall)-fm() sys/linux/init.go:42 +0x4b github.com/google/syzkaller/prog.(*Prog).replaceArg() prog/prog.go:357 +0x239 github.com/google/syzkaller/prog.generateHints.func2() prog/hints.go:105 +0x124 github.com/google/syzkaller/prog.checkConstArg() prog/hints.go:128 +0xf3 github.com/google/syzkaller/prog.generateHints() prog/hints.go:120 +0x495 github.com/google/syzkaller/prog.(*Prog).MutateWithHints.func1() prog/hints.go:72 +0x67 github.com/google/syzkaller/prog.foreachSubargImpl.func1() prog/analysis.go:86 +0x9f github.com/google/syzkaller/prog.foreachSubargImpl() prog/analysis.go:104 +0xc8 github.com/google/syzkaller/prog.foreachArgArray() prog/analysis.go:113 +0x89 github.com/google/syzkaller/prog.foreachArg() prog/analysis.go:121 +0x50 github.com/google/syzkaller/prog.(*Prog).MutateWithHints() prog/hints.go:71 +0x18e github.com/google/syzkaller/prog.BenchmarkHints.func1() prog/hints_test.go:477 +0x77 testing.(*B).RunParallel.func1() testing/benchmark.go:626 +0x156 Previous read at 0x00c42000d3f0 by goroutine 17: github.com/google/syzkaller/prog.clone() prog/clone.go:38 +0xbaa github.com/google/syzkaller/prog.(*Prog).cloneImpl() prog/clone.go:21 +0x17f github.com/google/syzkaller/prog.generateHints() prog/hints.go:95 +0xd0 github.com/google/syzkaller/prog.(*Prog).MutateWithHints.func1() prog/hints.go:72 +0x67 github.com/google/syzkaller/prog.foreachSubargImpl.func1() prog/analysis.go:86 +0x9f github.com/google/syzkaller/prog.foreachSubargImpl() prog/analysis.go:104 +0xc8 github.com/google/syzkaller/prog.foreachArgArray() prog/analysis.go:113 +0x89 github.com/google/syzkaller/prog.foreachArg() prog/analysis.go:121 +0x50 github.com/google/syzkaller/prog.(*Prog).MutateWithHints() prog/hints.go:71 +0x18e github.com/google/syzkaller/prog.BenchmarkHints.func1() prog/hints_test.go:477 +0x77 testing.(*B).RunParallel.func1() testing/benchmark.go:626 +0x156
* prog: fix hints of data argsDmitry Vyukov2017-12-081-8/+22
| | | | | | | | | | | | Hints for data args don't work. We do all the work, but at the final stage we patch arg in the _old_ program, not in the _new_ one. So programs passed to the callback are all the same and don't contain any mutations. Tests did not catch this because they work right before that point (don't test the actual interface function MutateWithHints). Fix that and add a test that catches this.
* prog: export MakeData/UnionArg as we do for other arg typesDmitry Vyukov2017-11-221-1/+1
| | | | Target code can use these to generate special structs.
* syz-fuzzer: generates hints only for the call that gave new coverageDmitry Vyukov2017-10-231-8/+7
| | | | | | During smashing we know what call gave new coverage, so we can concentrate just on it. This helps to reduce amount of hints generated (we have too many of them).
* prog: add a TODO for hintsDmitry Vyukov2017-10-231-0/+2
|
* prog: fix bugs in hints generationDmitry Vyukov2017-10-231-4/+18
| | | | Add a random hints test and fix bugs it uncovers.
* prog: remove default target and all global stateDmitry Vyukov2017-09-151-1/+1
| | | | | | Now each prog function accepts the desired target explicitly. No global, implicit state involved. This is much cleaner and allows cross-OS/arch testing, etc.
* prog: remove special knowledge about "mmap" syscallDmitry Vyukov2017-09-151-11/+2
| | | | Abstract "mmap" away as it can be called differently on another OS.
* prog, sys: move types to progDmitry Vyukov2017-09-051-4/+2
| | | | | | | | | | | Large overhaul moves syscalls and arg types from sys to prog. Sys package now depends on prog and contains only generated descriptions of syscalls. Introduce prog.Target type that encapsulates all targer properties, like syscall list, ptr/page size, etc. Also moves OS-dependent pieces like mmap call generation from prog to sys. Update #191
* prog: dot-import sysDmitry Vyukov2017-09-051-2/+2
| | | | In preparation for moving sys types to prog to reduce later diffs.
* hints: add new mutations and testsVictor Chibotaru2017-09-011-15/+141
|
* ipc, prog, fuzzer, execprog: add hints generation codeVictor Chibotaru2017-08-301-1/+48
| | | | | | | | | | | | | | | | | | | | | | A hint is basically a tuple consisting of a pointer to an argument in one of the syscalls of a program and a value, which should be assigned to that argument. A simplified version of hints workflow looks like this: 1. Fuzzer launches a program and collects all the comparisons' data for every syscall in the program. 2. Next it tries to match the obtained comparison operands' values vs. the input arguments' values. 3. For every such match the fuzzer mutates the program by replacing the pointed argument with the saved value. 4. If a valid program is obtained, then fuzzer launches it and checks if new coverage is obtained. This commit includes: 1. All the code related to hints generation, parsing and mutations. 2. Fuzzer functions to launch the process. 3. Some new stats gathered by fuzzer and manager, related to hints. 4. An updated version of execprog to test the hints process.
* executor, ipc: modify the IO between KCOV<->executor<->fuzzerVictor Chibotaru2017-08-301-0/+50
Now executor is able to read comparisons data from KCOV and write them to fuzzer.