aboutsummaryrefslogtreecommitdiffstats
path: root/prog/mutation.go
Commit message (Collapse)AuthorAgeFilesLines
* prog: add specialized mutation for KFuzzTest callsEthan Graham2025-09-221-17/+44
| | | | | | | | | | | | Internal kernel functions (and as a result KFuzzTest) have stricter contracts than system calls. For this reason, we must avoid mutating the following cases: - Length arguments not matching the length of the related buffer. - Strings not being null-terminated. Add special cases for KFuzzTest calls that avoids these situations. Signed-off-by: Ethan Graham <ethangraham@google.com>
* prog: pkg/compiler: docs: introduce the `no_squash` attributeAlexander Potapenko2025-09-091-0/+3
| | | | | | | | | | | | | | | | | The `no_squash` per-syscall attribute prevents the fuzzer from generating squashed arguments to a particular syscall. This is particularly helpful for pseudo-syscalls with elaborate arguments that are hard to reason about when they are squashed - e.g. for syz_kvm_add_vcpu() that takes a SYZOS program as an input. I've considered an alternative solution that prohibits ANY for all pseudo-syscalls. But there is a bunch of existing programs (both the tests and the repros) for syscalls like syz_mount_image() for which the benefit of not passing ANY is not immediately obvious. I therefore decided to go with an explicit attribute that can later be enforced for every pseudo-syscall at compile time.
* all: use min/max functionsDmitry Vyukov2025-01-171-21/+6
| | | | They are shorter, more readable, and don't require temp vars.
* prog: fix validation of DataMmapProgDmitry Vyukov2024-05-061-0/+3
| | | | | | | Allow to serialize/deserialize DataMmapProg and fix validation in debug mode. Fixes #4750
* prog: use optimized mutation parametersAleksandr Nogikh2024-04-021-9/+52
| | | | | | | | | These parameters have been selected by a local experiment. On syz-testbed, they seem to help syzkaller find +15% more different crash types per single run and +30% more crash types overall. Later we might want to choose these parameters during the actual run.
* prog: fix resource leak during replaceArg() of union fieldsAleksandr Nogikh2024-03-131-1/+0
| | | | | | | | | | | The replaced union field may contain resource references that must also be cleaned up. The bug was triggered via methods that patch conditional fields, so let's add stress tests for the conditional fields + resources combination. Reported-by: Paul Chaignon <paul.chaignon@gmail.com>
* Revert "prog: fix resource leak during replaceArg() of union fields"Aleksandr Nogikh2024-03-081-0/+1
| | | | This reverts commit 6387f6b7d487e2a77d753ad28c1074e39c17c3ca.
* prog: fix resource leak during replaceArg() of union fieldsAleksandr Nogikh2024-03-081-1/+0
| | | | | | | | | | | The replaced union field may contain resource references that must also be cleaned up. The bug was triggered via methods that patch conditional fields, so let's add stress tests for the conditional fields + resources combination. Reported-by: Paul Chaignon <paul.chaignon@gmail.com>
* prog: support conditional fieldsAleksandr Nogikh2024-02-191-1/+3
| | | | | | | | | | | | | 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.
* prog: swap array elements during mutationAleksandr Nogikh2024-02-081-1/+7
|
* 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.
* pkg/image: optimize image decompressionDmitry Vyukov2022-12-221-8/+0
| | | | | | | | | | | | | | | Benchmark results: name old time/op new time/op delta Decompress-8 24.7ms ± 1% 13.4ms ± 4% -45.81% (p=0.000 n=16+19) name old alloc/op new alloc/op delta Decompress-8 67.2MB ± 0% 0.0MB ± 1% -99.98% (p=0.000 n=18+20) name old allocs/op new allocs/op delta Decompress-8 188 ± 0% 167 ± 0% -11.17% (p=0.000 n=20+20) Test process memory consumption drops from 220MB to 80MB.
* pkg/image: make Decompress easier to useDmitry Vyukov2022-12-221-4/+2
| | | | | | | | | | Change DecompressWriter to DecompressCheck: checking validity of the image is the only useful use of DecompressWriter. Change Decompress to MustDecompress which does not return an error. We check validity during program deserialization, so all other uses already panic on errors. Also add dtor return value in preparation for subsequent changes.
* pkg/image: factor out from progDmitry Vyukov2022-12-221-6/+8
| | | | | | | Move image compression-related function to a separate package. In preperation for subsequent changes that make decompression more complex. Prog package is already large and complex. Also makes running compression tests/benchmarks much faster.
* prog: refactor HeatMapDmitry Vyukov2022-11-251-5/+3
| | | | | | Provide NumMutations method instead of Size. It allows HeatMap to choose number of mutations better (e.g. for completely empty/flat images w/o interesting data).
* prog: use randInt when mutating imagesDmitry Vyukov2022-11-231-1/+1
| | | | | | | The current Uint64 produces uniformly distributed integers. Guessing integers in the full 64-bit range is very inefficient. Use the randInt function we use in normal generation/mutation, it produces various more interesting values with higher probability.
* prog: don't decompress more than 1 image at a timeDmitry Vyukov2022-11-231-0/+8
|
* prog: move image mutation into a separate functionDmitry Vyukov2022-11-231-23/+26
|
* prog, pkg/compiler: add `BufferCompressed` buffer type & `compressed_image` ↵Hrutvik Kanabar2022-11-211-0/+28
| | | | | | | | | | | | | | | | | | | | | | | | 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/mgrconfig, prog, syz-fuzzer: manager-configurable syscall mutationHrutvik Kanabar2022-09-221-16/+25
| | | | | | | | | | | | | | | | | | Allow manager configuration to specify that certain syscalls should not be mutated. This is expected to be useful when mutating certain syscalls is unlikely to produce interesting executions. For example, mutating a `syz_mount_image` call will likely produce a corrupt image. Some implementation details: - Add a `no_mutate_syscalls` manager config entry, with the same format as `enable_syscalls`. Ensure this is parsed and stored in the config as a set of syscall IDs. - Send this set to fuzzers when they connect to their managers via RPC. Ensure each fuzzer stores a copy of the set. - When mutating arguments of a syscall, check first whether it has been specified as non-mutatable. - For all mutations not managed by a `syz-manager`, retain previous behaviour by ensuring that no syscalls are considered non-mutable.
* prog: generate very long file namesDmitry Vyukov2022-08-101-2/+7
| | | | | Generate very long file names once in a while to provoke bugs like: https://github.com/google/gvisor/commit/f857f268eceb1cdee0b2bdfa218c969c84033fcd
* prog: fix out-of-bounds access in any blob mutationDmitry Vyukov2022-06-201-4/+7
| | | | | | | | | | | | | | | | | If we grow any blob during mutation, we allocate a new address for it (so that it does not overlap with other data). To do this we call analyze after the mutation. However, after mutation the blob can grow out of bounds of the data area and analyze will cause out-of-bounds access during marking of existing allocations. Fix this by calling analyze before we mutate the blob. Also while we are here use the proper call for analyze. Currently we always analyze only the first call, which is wrong (probably a latent TODO from initial implementation). Fixes #3206
* pkg/csource: remove calls instead of skipping themAleksandr Nogikh2021-10-011-4/+4
| | | | | | | | | | | | | | | | | | Currently csource skips calls at the very last moment, which has an unpleasant consequence - if we make choice of enabled defines depend on the individual calls or call properties, we may end up with defined yet unused functions. The perfect solution would be to untie syz_emit_ethernet/syz_extract_tcp_res and NetInjection, and also to untie VhciInjection and syz_emit_vhci. For the time being, move these checks to the very beginning of csource processing, so that these calls could be removed before we construct our defines. Adjust pkg/csource/csource_test.go to better cover fault injection generation problems.
* pkg/compiler: add glob typeJoey Jiaojg2021-05-261-0/+6
| | | | | | | | | | | | | | | | | | | | * 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
* prog: fix UnionType mutation for when per-field dir is specifiedNecip Fazil Yildiran2020-08-141-2/+2
| | | | prog/TestMutateRandom used to fail due to this.
* prog: reduce number of allocations in MutateDmitry Vyukov2020-05-181-31/+29
| | | | Don't allocate 3 parallel slices.
* prog: introduce Field typeDmitry Vyukov2020-05-021-17/+7
| | | | | | | | | | | | | Remvoe FieldName from Type and add a separate Field type that holds field name. Use Field for struct fields, union options and syscalls arguments, only these really have names. Reduces size of sys/linux/gen/amd64.go from 5665583 to 5201321 (-8.2%). Allows to not create new type for squashed any pointer. But main advantages will follow, e.g. removing StructDesc, using TypeRef in Arg, etc. Update #1580
* prog: rename {PtrType,ArrayType}.Type to ElemDmitry Vyukov2020-05-011-1/+1
| | | | | | | Name "Type" is confusing when referring to pointer/array element type. Frequently there are too many Type/typ/typ1/t and typ.Type is not very informative. It _is_ a type, but what's usually more relevant is that it's an _element_ type. Let's leave type checking to compiler and give it a more meaningful name.
* prog: remove Dir from TypeDmitry Vyukov2020-05-011-14/+14
| | | | | | | | | | | | | | | | | | 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: reduce code nesting levelDmitry Vyukov2020-04-281-20/+20
|
* prog: rename target.SanitizeCall to NeutralizeDmitry Vyukov2020-03-171-3/+1
| | | | | | | | | | | | | 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: control program lengthDmitry Vyukov2020-03-131-16/+29
| | | | | | | | | | | | | | | | | | | We have _some_ limits on program length, but they are really soft. When we ask to generate a program with 10 calls, sometimes we get 100-150 calls. There are also no checks when we accept external programs from corpus/hub. Issue #1630 contains an example where this crashes VM (executor limit on number of 1000 resources is violated). Larger programs also harm the process overall (slower, consume more memory, lead to monster reproducers, etc). Add a set of measure for hard control over program length. Ensure that generated/mutated programs are not too long; drop too long programs coming from corpus/hub in manager; drop too long programs in hub. As a bonus ensure that mutation don't produce programs with 0 calls (which is currently possible and happens). Fixes #1630
* prog: remove use of unsafeDmitry Vyukov2020-02-091-11/+9
| | | | | | | | | | | Unsafe is, well, unsafe. Plus it fails under the new checkptr mode in go1.14. Remove use of unsafe. No statistically significant change in performance: name old time/op new time/op delta StoreLoadInt-8 21.2ns ± 5% 21.6ns ± 9% ~ (p=0.136 n=20+20)
* prog: reduce len mutation priorityDmitry Vyukov2020-01-181-1/+2
| | | | | Mutating LenType only produces "incorrect" results according to descriptions, we generally try to do it less often (there is infinite space of incorrect inputs).
* prog: increase array size during mutationDmitry Vyukov2020-01-071-2/+8
| | | | | | | | We have strict upper bound of array size 10. However, for netlink we frequently need lots of attributes in arrays. Add a mutation that increases array size by few elements without an upper bound (we should not grow them infinitely due to coverage feedback?).
* prog: don't mutate strings with enumerated valuesDmitry Vyukov2020-01-051-4/+8
| | | | | | | | | | 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, pkg/compiler: alignment for integer rangesPaul Chaignon2019-10-251-12/+45
| | | | | | | | | Enables the syntax intN[start:end, alignment] for integer ranges. For instance, int32[0:10, 2] represents even 32-bit numbers between 0 and 10 included. With this change, two NEED tags in syscall descriptions can be addressed. Signed-off-by: Paul Chaignon <paul.chaignon@orange.com>
* prog: mutate length of output buffersVeronica Radu2019-10-101-6/+26
| | | | Update #480
* prog: fix plain priority for integersVeronica Radu2019-10-021-1/+1
|
* prog: add insertionPoint param in generateCall funcVeronica Radu2019-09-231-1/+1
|
* prog: use type size when generating/mutating intsVeronica Radu2019-09-231-2/+4
| | | | Update #1381
* prog: implemented argument and call prioritiesVeronica Radu2019-09-041-36/+176
|
* prog: move all flag mutation logic into flags() (#1362)Andrey Konovalov2019-09-031-21/+1
| | | | | This makes it a bit easier to understand. Also fix an issue with using flag value as bit number.
* prog: add implementation for resource centricVeronica Radu2019-09-031-3/+4
|
* prog: add special mutation for binary flagsVeronica Radu2019-08-091-1/+25
|
* prog: fix crash in blob mutationDmitry Vyukov2019-07-261-1/+1
| | | | | | | | | | | If we deserialized a huge blob (larger than max blob size), then we can get a negative size in the "Insert random bytes" case at: if r := int(maxLen) - len(data); n > r { n = r } Don't insert bytes if data is already larger than maxLen.
* prog/mutation: Add internal commentsMarco Elver2019-06-071-7/+27
|
* prog: add concept of "special pointers"Dmitry Vyukov2018-08-301-1/+8
| | | | | | | | | | | | | | | | | Currently we only generate either valid user-space pointers or NULL. Extend NULL to a set of special pointers that we will use in programs. All targets now contain 3 special values: - NULL - 0xfffffffffffffff (invalid kernel pointer) - 0x999999999999999 (non-canonical address) Each target can add additional special pointers on top of this. Also generate NULL/special pointers for non-opt ptr's. This restriction was always too restrictive. We may want to generate them with very low probability, but we do want to generate them. Also change pointers to NULL/special during mutation (but still not in the opposite direction).
* prog: split and simplify MutateDmitry Vyukov2018-08-021-108/+135
| | | | Update #538
* prog: introduce debugValidateDmitry Vyukov2018-08-021-5/+1
| | | | | | Move debug validation into a separate function. Update #538