diff options
46 files changed, 10240 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 000000000..52cbdeb9f --- /dev/null +++ b/AUTHORS @@ -0,0 +1,9 @@ +# This is the official list of the syzkaller project authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS file. See the latter for an explanation. + +# Names should be added to this file as +# Name or Organization +# Email addresses for individuals are tracked elsewhere to avoid spam. + +Google Inc. + diff --git a/CONTRIBUTORS b/CONTRIBUTORS new file mode 100644 index 000000000..529799d5b --- /dev/null +++ b/CONTRIBUTORS @@ -0,0 +1,8 @@ +# This is the official list of people who can contribute (and who have contributed) +# code to the syzkaller project repository. The AUTHORS file lists the copyright holders; +# this file lists people. For example, Google employees are listed here +# but not in AUTHORS, because Google holds the copyright. + +Google Inc. + Dmitry Vyukov + diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..dd5b3a58a --- /dev/null +++ b/LICENSE @@ -0,0 +1,174 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/README.md b/README.md new file mode 100644 index 000000000..f0f9fc8cf --- /dev/null +++ b/README.md @@ -0,0 +1,71 @@ +# syzkaller - linux syscall fuzzer + +```syzkaller``` is a distributed, unsupervised, coverage-guided Linux syscall fuzzer. +It is meant to be used with [KASAN](https://www.kernel.org/doc/Documentation/kasan.txt) (```CONFIG_KASAN=y```), +[KTSAN](https://github.com/google/ktsan) (```CONFIG_KTSAN=y```), +or [KUBSAN] (http://developerblog.redhat.com/2014/10/16/gcc-undefined-behavior-sanitizer-ubsan/) ([patch](https://lkml.org/lkml/2014/10/20/181)). + +Project [mailing list](https://groups.google.com/forum/#!forum/syzkaller). + +This is work-in-progress, some things may not work yet. + +## Usage + +Coverage support is not upstreamed yet, so you need to apply [this patch](https://codereview.appspot.com/267910043) +to gcc (tested on revision 227353) and [this patch](https://github.com/dvyukov/linux/commit/3506cff7ed260596a783c3766a852869cd913a5e) +to kernel. Then build kernel with ```CONFIG_KASAN``` or ```CONFIG_KTSAN``` and the new ```CONFIG_SANCOV```. + +Then, build ```syzkaller/master```, ```syzkaller/manager```, ```syzkaller/fuzzer``` and ```syzkaller/executor```. +The latter is build using ```make``` in the dir, the rest are build using ```go build```. + +Then, write manager config based on ```manager/example.cfg```. + +Then, start the master process as: + +```$ ./master -workdir=./workdir -addr=myhost.com:48342 -http=myhost.com:29855``` + +and start the manager process as: + +```$ ./manager -config my.cfg``` + +The manager process will wind up qemu virtual machines and start fuzzing in them. +If you open the HTTP address (in our case ```http://myhost.com:29855```), +you will see how corpus collection progresses. + +## Process Structure + +Master process is responsible for persistent corpus and crash storage. +It communicates with one or more manager processes via RPC. + +Manager process starts, monitors and restarts several VM instances (support for +physical machines is not implemented yet), and starts fuzzer process inside of the VMs. +Manager process also serves as a persistent proxy between fuzzer processes and the master process. +As opposed to fuzzer processes, it runs on a host with stable kernel which does not +experience white-noise fuzzer load. + +Fuzzer process runs inside of presumably unstable VMs (or physical machines under test). +Fuzzer guides fuzzing process itself (input generation, mutation, minimization, etc) +and sends inputs that trigger new coverage back to the manager process via RPC. +It also starts transient executor processes. + +Executor process executes a single input (a sequence of syscalls). +It accepts the program to execute from fuzzer process and sends results back. +It is designed to be as simple as possible (to not interfere with fuzzing process), +written in C++, compiled as static binary and uses shared memory for communication. + +## Syscall description + +syzkaller uses declarative description of syscalls to generate, mutate, minimize, +serialize and deserialize programs (sequences of syscalls). Below you can see +(hopefully self-explanatory) excerpt from the description: + +``` +open(file filename, flags flags[open_flags], mode flags[open_mode]) fd +read(fd fd, buf buffer[out], count len[buf]) len[buf] +close(fd fd) +open_mode = S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH +``` + +The description is contained in ```syzkaller/sys/sys.txt``` file. + +This is not an official Google product. diff --git a/cover/cover.go b/cover/cover.go new file mode 100644 index 000000000..c55f328e6 --- /dev/null +++ b/cover/cover.go @@ -0,0 +1,139 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +/* Package cover implements set operations on slices (arrays of coverage PCs). */ +package cover + +import ( + "sort" +) + +type Cover []uint32 + +func (a Cover) Len() int { return len(a) } +func (a Cover) Less(i, j int) bool { return a[i] < a[j] } +func (a Cover) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +const sent = ^uint32(0) + +func Copy(cov Cover) Cover { + return append(Cover{}, cov...) +} + +/* Canonicalize sorts and removes duplicates. */ +func Canonicalize(cov []uint32) Cover { + sort.Sort(Cover(cov)) + i := 0 + last := sent + for _, pc := range cov { + if pc != last { + last = pc + cov[i] = pc + i++ + } + } + return Cover(cov[:i]) +} + +func Difference(cov0, cov1 Cover) Cover { + return foreach(cov0, cov1, func(v0, v1 uint32) uint32 { + if v0 < v1 { + return v0 + } + return sent + }) +} + +func SymmetricDifference(cov0, cov1 Cover) Cover { + return foreach(cov0, cov1, func(v0, v1 uint32) uint32 { + if v0 < v1 { + return v0 + } + if v1 < v0 { + return v1 + } + return sent + }) +} + +func Union(cov0, cov1 Cover) Cover { + return foreach(cov0, cov1, func(v0, v1 uint32) uint32 { + if v0 <= v1 { + return v0 + } + return v1 + }) +} + +func Intersection(cov0, cov1 Cover) Cover { + return foreach(cov0, cov1, func(v0, v1 uint32) uint32 { + if v0 == v1 { + return v0 + } + return sent + }) +} + +func foreach(cov0, cov1 Cover, f func(uint32, uint32) uint32) Cover { + var res []uint32 + for i0, i1 := 0, 0; i0 < len(cov0) || i1 < len(cov1); { + v0, v1 := sent, sent + if i0 < len(cov0) { + v0 = cov0[i0] + } + if i1 < len(cov1) { + v1 = cov1[i1] + } + if v0 <= v1 { + i0++ + } + if v1 <= v0 { + i1++ + } + if v := f(v0, v1); v != sent { + res = append(res, v) + } + } + return res +} + +// Minimize returns a minimal set of inputs that give the same coverage as the full corpus. +func Minimize(corpus []Cover) []int { + inputs := make([]*minInput, len(corpus)) + for i, cov := range corpus { + inputs[i] = &minInput{ + idx: i, + cov: cov, + } + } + sort.Sort(minInputArray(inputs)) + var min []int + covered := make(map[uint32]struct{}) + for _, inp := range inputs { + hit := false + for _, pc := range inp.cov { + if !hit { + if _, ok := covered[pc]; !ok { + hit = true + min = append(min, inp.idx) + } + } + if hit { + covered[pc] = struct{}{} + } + } + } + return min +} + +type minInput struct { + idx int + cov Cover +} + +type minInputArray []*minInput + +// Inputs with larger coverage come first. +func (a minInputArray) Len() int { return len(a) } +func (a minInputArray) Less(i, j int) bool { return len(a[i].cov) > len(a[j].cov) } +func (a minInputArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] } diff --git a/cover/cover_test.go b/cover/cover_test.go new file mode 100644 index 000000000..73dc7581b --- /dev/null +++ b/cover/cover_test.go @@ -0,0 +1,205 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package cover + +import ( + "math/rand" + "reflect" + "sort" + "testing" + "time" +) + +func initTest(t *testing.T) (*rand.Rand, int) { + iters := 1000 + if testing.Short() { + iters = 100 + } + seed := int64(time.Now().UnixNano()) + rs := rand.NewSource(seed) + t.Logf("seed=%v", seed) + return rand.New(rs), iters +} + +type Test struct { + V0 Cover + V1 Cover + R Cover +} + +func runTest(t *testing.T, f func(Cover, Cover) Cover, sorted, symmetric bool, tests []Test) { + if symmetric { + for _, test := range tests { + tests = append(tests, Test{test.V1, test.V0, test.R}) + } + } + tests = append(tests, Test{Cover{}, Cover{}, Cover{}}) + for _, test := range tests { + if sorted { + if !sort.IsSorted(test.V0) { + t.Fatalf("input is not sorted: %+v", test.V0) + } + if !sort.IsSorted(test.V1) { + t.Fatalf("input is not sorted: %+v", test.V1) + } + } + if !sort.IsSorted(test.R) { + t.Fatalf("golden is not sorted: %+v", test.R) + } + res := f(test.V0, test.V1) + if !sort.IsSorted(res) { + t.Fatalf("output is not sorted: %+v", res) + } + if (len(res) != 0 || len(test.R) != 0) && !reflect.DeepEqual(res, test.R) { + t.Fatalf("f(%+v, %+v) = %+v (expect: %+v)", test.V0, test.V1, res, test.R) + } + } +} + +func TestCanonicalize(t *testing.T) { + runTest(t, func(c0, c1 Cover) Cover { return Canonicalize([]uint32(c0)) }, false, false, []Test{ + {Cover{1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 6}, Cover{}, Cover{1, 2, 3, 4, 5, 6}}, + {Cover{6, 2, 3, 4, 5, 1}, Cover{}, Cover{1, 2, 3, 4, 5, 6}}, + {Cover{6, 1, 2, 6, 3, 3, 4, 5, 1}, Cover{}, Cover{1, 2, 3, 4, 5, 6}}, + }) +} + +func TestDifference(t *testing.T) { + runTest(t, Difference, true, false, []Test{ + {Cover{1, 2, 3, 4, 5, 6}, Cover{}, Cover{1, 2, 3, 4, 5, 6}}, + {Cover{1, 2, 3, 4, 5, 6}, Cover{3}, Cover{1, 2, 4, 5, 6}}, + {Cover{1, 2, 3, 4, 5, 6}, Cover{1, 6}, Cover{2, 3, 4, 5}}, + {Cover{1, 2, 3, 4, 5, 6}, Cover{0, 10}, Cover{1, 2, 3, 4, 5, 6}}, + {Cover{1, 2, 3, 4, 5, 6}, Cover{0, 3, 6}, Cover{1, 2, 4, 5}}, + }) +} + +func TestSymmetricDifference(t *testing.T) { + runTest(t, SymmetricDifference, true, true, []Test{ + {Cover{1, 2, 3, 4, 5, 6}, Cover{}, Cover{1, 2, 3, 4, 5, 6}}, + {Cover{1, 2, 3, 4, 5, 6}, Cover{1, 2, 3, 4, 5, 6}, Cover{}}, + {Cover{1, 2, 3, 4, 5, 6}, Cover{2, 4, 6}, Cover{1, 3, 5}}, + {Cover{2, 4, 6}, Cover{1, 3, 5}, Cover{1, 2, 3, 4, 5, 6}}, + }) +} + +func TestUnion(t *testing.T) { + runTest(t, Union, true, true, []Test{ + {Cover{1, 2, 3, 4, 5, 6}, Cover{}, Cover{1, 2, 3, 4, 5, 6}}, + {Cover{1, 2, 3, 4, 5, 6}, Cover{1, 2, 3, 4, 5, 6}, Cover{1, 2, 3, 4, 5, 6}}, + {Cover{1, 3, 5}, Cover{2, 4, 6}, Cover{1, 2, 3, 4, 5, 6}}, + {Cover{1, 2, 3, 5}, Cover{2, 4, 5, 6}, Cover{1, 2, 3, 4, 5, 6}}, + }) +} + +func TestIntersection(t *testing.T) { + runTest(t, Intersection, true, true, []Test{ + {Cover{1, 2, 3, 4, 5, 6}, Cover{}, Cover{}}, + {Cover{1, 2, 3}, Cover{4, 5, 6}, Cover{}}, + {Cover{1, 2, 3}, Cover{2, 3, 5}, Cover{2, 3}}, + }) +} + +func TestMinimize(t *testing.T) { + tests := []struct { + inp []Cover + out []int + }{ + // Take all. + { + []Cover{ + {1, 2, 3}, + {4, 5, 6}, + {7, 8, 9}, + }, + []int{0, 1, 2}, + }, + // Take one. + { + []Cover{ + {1, 2, 3, 4, 5, 6, 7, 8, 9}, + {1}, + {2, 3, 4, 5}, + {6, 7, 8}, + }, + []int{0}, + }, + // Take two. + { + []Cover{ + {1, 2, 3, 4, 5, 6, 7, 8, 9}, + {1}, + {2, 3, 4, 5}, + {10}, + }, + []int{0, 3}, + }, + // Take another two. + { + []Cover{ + {1, 2, 3, 4}, + {1, 2}, + {3, 4, 5, 6, 7}, + {3, 7}, + }, + []int{2, 0}, + }, + // Take the largest one. + { + []Cover{ + {1, 2}, + {1, 2, 3, 4, 5}, + {3, 4, 5}, + }, + []int{1}, + }, + } + for _, test := range tests { + res := Minimize(test.inp) + if !reflect.DeepEqual(res, test.out) { + t.Logf("corpus:") + for _, in := range test.inp { + t.Logf(" %+v", in) + } + t.Fatalf("expect: %+v, got: %+v", test.out, res) + } + } +} + +func TestMinimizeRandom(t *testing.T) { + rnd, iters := initTest(t) + for i := 0; i < iters; i++ { + n := rnd.Intn(20) + cov := make([]Cover, n) + for i := range cov { + tmp := make(Cover, rnd.Intn(10)) + for j := range tmp { + tmp[j] = uint32(rnd.Intn(100)) + } + cov[i] = Canonicalize(tmp) + } + var total Cover + for _, c := range cov { + total = Union(total, c) + } + mini := Minimize(cov) + var minimized Cover + for _, idx := range mini { + minimized = Union(minimized, cov[idx]) + } + t.Logf("minimized %v -> %v", len(cov), len(mini)) + if !reflect.DeepEqual(total, minimized) { + t.Logf("corpus:") + for _, in := range cov { + t.Logf(" %+v", in) + } + t.Logf("minimized:") + for _, in := range cov { + t.Logf(" %+v", in) + } + + t.Fatalf("better luck next time") + } + } +} diff --git a/executor/Makefile b/executor/Makefile new file mode 100644 index 000000000..a84d06880 --- /dev/null +++ b/executor/Makefile @@ -0,0 +1,9 @@ +# Copyright 2015 syzkaller project authors. All rights reserved. +# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +executor: executor.cc syscalls.h + gcc executor.cc -o executor -lpthread -static -Wall -O1 -g + +format: executor.cc + clang-format --style=file -i executor.cc + diff --git a/executor/executor.cc b/executor/executor.cc new file mode 100644 index 000000000..e49303101 --- /dev/null +++ b/executor/executor.cc @@ -0,0 +1,478 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdarg.h> +#include <stddef.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <time.h> +#include <sys/types.h> +#include <sys/syscall.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <pthread.h> +#include "syscalls.h" + +const int kInFd = 3; +const int kOutFd = 4; +const int kMaxInput = 1 << 20; +const int kMaxOutput = 16 << 20; +const int kMaxArgs = 6; +const int kMaxThreads = 16; +const int kMaxCommands = 4 << 10; + +const uint64_t instr_eof = -1; +const uint64_t instr_copyin = -2; +const uint64_t instr_copyout = -3; + +const uint64_t arg_const = 0; +const uint64_t arg_result = 1; +const uint64_t arg_data = 2; + +// We use the default value instead of results of failed syscalls. +// -1 is an invalid fd and an invalid address and deterministic, +// so good enough for our purposes. +const uint64_t default_value = -1; + +bool flag_debug; +bool flag_cover; +bool flag_threaded; + +__attribute__((aligned(64 << 10))) char input_data[kMaxInput]; +__attribute__((aligned(64 << 10))) char output_data[kMaxOutput]; +uint32_t* output_pos; +int completed; + +struct res_t { + bool executed; + uint64_t val; +}; + +res_t results[kMaxCommands]; + +struct thread_t { + bool created; + int id; + pthread_t th; + int cover_fd; + uint32_t cover_data[16 << 10]; + uint64_t* copyout_pos; + bool ready; + bool done; + bool handled; + int call_n; + int call_index; + int call_num; + int num_args; + uint64_t args[kMaxArgs]; + uint64_t res; + int cover_size; +}; + +thread_t threads[kMaxThreads]; + +__attribute__((noreturn)) void fail(const char* msg, ...); +__attribute__((noreturn)) void error(const char* msg, ...); +void debug(const char* msg, ...); +uint64_t read_input(uint64_t** input_posp); +uint64_t read_arg(uint64_t** input_posp); +uint64_t read_result(uint64_t** input_posp); +void write_output(uint32_t v); +void copyin(char* addr, uint64_t val, uint64_t size); +uint64_t copyout(char* addr, uint64_t size); +thread_t* schedule_call(int n, int call_index, int call_num, uint64_t num_args, uint64_t* args, uint64_t* pos); +void execute_call(thread_t* th); +void handle_completion(thread_t* th); +void* worker_thread(void* arg); +uint64_t current_time_ms(); +void cover_init(thread_t* th); +void cover_reset(thread_t* th); +int cover_read(thread_t* th); + +int main() +{ + if (mmap(&input_data[0], kMaxInput, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, kInFd, 0) != &input_data[0]) + fail("mmap of input file failed"); + if (mmap(&output_data[0], kMaxOutput, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, kOutFd, 0) != &output_data[0]) + fail("mmap of output file failed"); + uint64_t* input_pos = (uint64_t*)&input_data[0]; + uint64_t flags = read_input(&input_pos); + flag_debug = flags & (1 << 0); + flag_cover = flags & (1 << 1); + flag_threaded = flags & (1 << 2); + output_pos = (uint32_t*)&output_data[0]; + write_output(0); // Number of executed syscalls (updated later). + + if (!flag_threaded) + cover_init(&threads[0]); + + int call_index = 0; + for (int n = 0;; n++) { + uint64_t call_num = read_input(&input_pos); + if (call_num == instr_eof) + break; + if (call_num == instr_copyin) { + char* addr = (char*)read_input(&input_pos); + uint64_t typ = read_input(&input_pos); + uint64_t size = read_input(&input_pos); + debug("copyin to %p\n", addr); + switch (typ) { + case arg_const: { + uint64_t arg = read_input(&input_pos); + copyin(addr, arg, size); + break; + } + case arg_result: { + uint64_t val = read_result(&input_pos); + copyin(addr, val, size); + break; + } + case arg_data: { + memcpy(addr, input_pos, size); + // Read out the data. + for (uint64_t i = 0; i < (size + 7) / 8; i++) + read_input(&input_pos); + break; + } + default: + fail("bad argument type %lu", typ); + } + continue; + } + if (call_num == instr_copyout) { + read_input(&input_pos); // addr + read_input(&input_pos); // size + // The copyout will happen when/if the call completes. + continue; + } + + // Normal syscall. + if (call_num >= sizeof(syscalls) / sizeof(syscalls[0])) + fail("invalid command number %lu", call_num); + uint64_t num_args = read_input(&input_pos); + if (num_args > kMaxArgs) + fail("command has bad number of arguments %lu", num_args); + uint64_t args[kMaxArgs] = {}; + for (uint64_t i = 0; i < num_args; i++) + args[i] = read_arg(&input_pos); + for (uint64_t i = num_args; i < 6; i++) + args[i] = 0; + thread_t* th = schedule_call(n, call_index++, call_num, num_args, args, input_pos); + + if (flag_threaded) { + // Wait for call completion. + uint64_t start = current_time_ms(); + while (!__atomic_load_n(&th->done, __ATOMIC_ACQUIRE) && (current_time_ms() - start) < 100) + usleep(10); + if (__atomic_load_n(&th->done, __ATOMIC_ACQUIRE)) + handle_completion(th); + // Check if any of previous calls have completed. + usleep(100); + for (int i = 0; i < kMaxThreads; i++) { + th = &threads[i]; + if (__atomic_load_n(&th->done, __ATOMIC_ACQUIRE) && !th->handled) + handle_completion(th); + } + } else { + // Execute directly. + if (th != &threads[0]) + fail("using non-main thread in non-thread mode"); + execute_call(th); + handle_completion(th); + } + } + + // TODO: handle hanged threads. + debug("exiting\n"); + return 0; +} + +thread_t* schedule_call(int n, int call_index, int call_num, uint64_t num_args, uint64_t* args, uint64_t* pos) +{ + // Find a spare thread to execute the call. + thread_t* th = 0; + for (int i = 0; i < kMaxThreads; i++) { + th = &threads[i]; + if (!th->created) { + th->created = true; + th->id = i; + th->done = true; + th->handled = true; + if (flag_threaded) { + if (pthread_create(&th->th, 0, worker_thread, th)) + fail("pthread_create failed"); + } + } + if (__atomic_load_n(&th->done, __ATOMIC_ACQUIRE)) { + if (!th->handled) + handle_completion(th); + break; + } + } + if (th == &threads[kMaxThreads]) + fail("out of threads"); + debug("scheduling call %d [%s] on thread %d\n", call_index, syscalls[call_num].name, th->id); + if (th->ready || !th->done || !th->handled) + fail("bad thread state in schedule: ready=%d done=%d handled=%d", + th->ready, th->done, th->handled); + th->copyout_pos = pos; + th->done = false; + th->handled = false; + th->call_n = n; + th->call_index = call_index; + th->call_num = call_num; + th->num_args = num_args; + for (int i = 0; i < kMaxArgs; i++) + th->args[i] = args[i]; + __atomic_store_n(&th->ready, true, __ATOMIC_RELEASE); + return th; +} + +void handle_completion(thread_t* th) +{ + debug("completion of call %d [%s] on thread %d\n", th->call_index, syscalls[th->call_num].name, th->id); + if (th->ready || !th->done || th->handled) + fail("bad thread state in completion: ready=%d done=%d handled=%d", + th->ready, th->done, th->handled); + if (th->res != (uint64_t)-1) { + results[th->call_n].executed = true; + results[th->call_n].val = th->res; + for (;;) { + th->call_n++; + uint64_t call_num = read_input(&th->copyout_pos); + if (call_num != instr_copyout) + break; + char* addr = (char*)read_input(&th->copyout_pos); + uint64_t size = read_input(&th->copyout_pos); + uint64_t val = copyout(addr, size); + results[th->call_n].executed = true; + results[th->call_n].val = val; + debug("copyout from %p\n", addr); + } + } + write_output(th->call_index); + write_output(th->call_num); + write_output(th->cover_size); + for (int i = 0; i < th->cover_size; i++) + write_output(th->cover_data[i]); + completed++; + __atomic_store_n((uint32_t*)&output_data[0], completed, __ATOMIC_RELEASE); + th->handled = true; +} + +void* worker_thread(void* arg) +{ + thread_t* th = (thread_t*)arg; + + cover_init(th); + for (;;) { + while (!__atomic_load_n(&th->ready, __ATOMIC_ACQUIRE)) + usleep(10); + execute_call(th); + } + return 0; +} + +void execute_call(thread_t* th) +{ + th->ready = false; + call_t* call = &syscalls[th->call_num]; + debug("#%d: %s(", th->id, call->name); + for (int i = 0; i < th->num_args; i++) { + if (i != 0) + debug(", "); + debug("0x%lx", th->args[i]); + } + debug(")\n"); + + if (kMaxArgs != 6) + fail("inconsistent number of arguments"); + + cover_reset(th); + th->res = syscall(call->sys_nr, th->args[0], th->args[1], th->args[2], th->args[3], th->args[4], th->args[5]); + int errno0 = errno; + th->cover_size = cover_read(th); + + if (th->res == (uint64_t)-1) + debug("#%d: %s = errno(%d)\n", th->id, call->name, errno0); + else + debug("#%d: %s = %lx\n", th->id, call->name, th->res); + __atomic_store_n(&th->done, true, __ATOMIC_RELEASE); +} + +void cover_init(thread_t* th) +{ + if (!flag_cover) + return; + debug("#%d: opening /proc/cover\n", th->id); + th->cover_fd = open("/proc/cover", O_RDWR); + if (th->cover_fd == -1) + fail("open of /proc/cover failed"); + char cmd[128]; + sprintf(cmd, "enable=%d", (int)(sizeof(th->cover_data) / sizeof(th->cover_data[0]))); + int n = write(th->cover_fd, cmd, strlen(cmd)); + if (n != (int)strlen(cmd)) + fail("cover enable write failed"); + debug("#%d: opened /proc/cover\n", th->id); +} + +void cover_reset(thread_t* th) +{ + if (!flag_cover) + return; + debug("#%d: resetting /proc/cover\n", th->id); + int n = write(th->cover_fd, "reset", sizeof("reset") - 1); + if (n != sizeof("reset") - 1) + fail("cover reset write failed"); +} + +int cover_read(thread_t* th) +{ + if (!flag_cover) + return 0; + int n = read(th->cover_fd, th->cover_data, sizeof(th->cover_data)); + if (n < 0 || n > (int)sizeof(th->cover_data) || (n % sizeof(th->cover_data[0])) != 0) + fail("cover read failed after %s (n=%d)", syscalls[th->call_num].name, n); + n /= sizeof(th->cover_data[0]); + debug("#%d: read /proc/cover = %d\n", th->id, n); + return n; +} + +void copyin(char* addr, uint64_t val, uint64_t size) +{ + switch (size) { + case 1: + *(uint8_t*)addr = val; + break; + case 2: + *(uint16_t*)addr = val; + break; + case 4: + *(uint32_t*)addr = val; + break; + case 8: + *(uint64_t*)addr = val; + break; + default: + fail("copyin: bad argument size %lu", size); + } +} + +uint64_t copyout(char* addr, uint64_t size) +{ + switch (size) { + case 1: + return *(uint8_t*)addr; + case 2: + return *(uint16_t*)addr; + case 4: + return *(uint32_t*)addr; + case 8: + return *(uint64_t*)addr; + default: + fail("copyout: bad argument size %lu", size); + } +} + +uint64_t read_arg(uint64_t** input_posp) +{ + uint64_t typ = read_input(input_posp); + uint64_t size = read_input(input_posp); + (void)size; + uint64_t arg = 0; + switch (typ) { + case arg_const: { + arg = read_input(input_posp); + break; + } + case arg_result: { + arg = read_result(input_posp); + break; + } + default: + fail("bad argument type %lu", typ); + } + return arg; +} + +uint64_t read_result(uint64_t** input_posp) +{ + uint64_t idx = read_input(input_posp); + uint64_t op_div = read_input(input_posp); + uint64_t op_add = read_input(input_posp); + if (idx >= kMaxCommands) + fail("command refers to bad result %ld", idx); + uint64_t arg = default_value; + if (results[idx].executed) { + arg = results[idx].val; + if (op_div != 0) + arg = arg / op_div; + arg += op_add; + } + return arg; +} + +uint64_t read_input(uint64_t** input_posp) +{ + uint64_t* input_pos = *input_posp; + if ((char*)input_pos >= input_data + kMaxInput) + fail("input command overflows input"); + *input_posp = input_pos + 1; + return *input_pos; +} + +void write_output(uint32_t v) +{ + if ((char*)output_pos >= output_data + kMaxOutput) + fail("output overflow"); + *output_pos++ = v; +} + +uint64_t current_time_ms() +{ + timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + fail("clock_gettime failed"); + return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; +} + +// logical error (e.g. invalid input program) +void fail(const char* msg, ...) +{ + int e = errno; + fflush(stdout); + va_list args; + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + fprintf(stderr, " (errno %d)\n", e); + exit(67); +} + +// kernel error (e.g. wrong syscall return value) +void error(const char* msg, ...) +{ + fflush(stdout); + va_list args; + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + fprintf(stderr, "\n"); + exit(68); +} + +void debug(const char* msg, ...) +{ + if (!flag_debug) + return; + va_list args; + va_start(args, msg); + vfprintf(stdout, msg, args); + va_end(args); + fflush(stdout); +} diff --git a/executor/syscalls.h b/executor/syscalls.h new file mode 100644 index 000000000..86dc26a4b --- /dev/null +++ b/executor/syscalls.h @@ -0,0 +1,307 @@ +// AUTOGENERATED FILE + +struct call_t { + const char* name; + int sys_nr; +}; + +call_t syscalls[] = { + {"open", __NR_open}, + {"openat", __NR_openat}, + {"creat", __NR_creat}, + {"close", __NR_close}, + {"read", __NR_read}, + {"pread64", __NR_pread64}, + {"readv", __NR_readv}, + {"preadv", __NR_preadv}, + {"write", __NR_write}, + {"pwrite64", __NR_pwrite64}, + {"writev", __NR_writev}, + {"pwritev", __NR_pwritev}, + {"lseek", __NR_lseek}, + {"dup", __NR_dup}, + {"dup2", __NR_dup2}, + {"dup3", __NR_dup3}, + {"pipe", __NR_pipe}, + {"pipe2", __NR_pipe2}, + {"tee", __NR_tee}, + {"splice", __NR_splice}, + {"vmsplice", __NR_vmsplice}, + {"sendfile", __NR_sendfile}, + {"stat", __NR_stat}, + {"lstat", __NR_lstat}, + {"fstat", __NR_fstat}, + {"poll", __NR_poll}, + {"ppoll", __NR_ppoll}, + {"select", __NR_select}, + {"pselect6", __NR_pselect6}, + {"epoll_create", __NR_epoll_create}, + {"epoll_create1", __NR_epoll_create1}, + {"epoll_ctl", __NR_epoll_ctl}, + {"epoll_wait", __NR_epoll_wait}, + {"epoll_pwait", __NR_epoll_pwait}, + {"signalfd", __NR_signalfd}, + {"signalfd4", __NR_signalfd4}, + {"eventfd", __NR_eventfd}, + {"eventfd2", __NR_eventfd2}, + {"timerfd_create", __NR_timerfd_create}, + {"timerfd_settime", __NR_timerfd_settime}, + {"timerfd_gettime", __NR_timerfd_gettime}, + {"mmap", __NR_mmap}, + {"munmap", __NR_munmap}, + {"mremap", __NR_mremap}, + {"remap_file_pages", __NR_remap_file_pages}, + {"mprotect", __NR_mprotect}, + {"msync", __NR_msync}, + {"madvise", __NR_madvise}, + {"fadvise64", __NR_fadvise64}, + {"readahead", __NR_readahead}, + {"mbind", __NR_mbind}, + {"move_pages", __NR_move_pages}, + {"migrate_pages", __NR_migrate_pages}, + {"set_mempolicy", __NR_set_mempolicy}, + {"get_mempolicy", __NR_get_mempolicy}, + {"mincore", __NR_mincore}, + {"mlock", __NR_mlock}, + {"munlock", __NR_munlock}, + {"mlockall", __NR_mlockall}, + {"munlockall", __NR_munlockall}, + {"unshare", __NR_unshare}, + {"kcmp", __NR_kcmp}, + {"futex", __NR_futex}, + {"set_robust_list", __NR_set_robust_list}, + {"get_robust_list", __NR_get_robust_list}, + {"restart_syscall", __NR_restart_syscall}, + {"socket", __NR_socket}, + {"socketpair", __NR_socketpair}, + {"accept", __NR_accept}, + {"accept4", __NR_accept4}, + {"bind", __NR_bind}, + {"listen", __NR_listen}, + {"connect", __NR_connect}, + {"shutdown", __NR_shutdown}, + {"sendto", __NR_sendto}, + {"sendmsg", __NR_sendmsg}, + {"sendmmsg", __NR_sendmmsg}, + {"recvfrom", __NR_recvfrom}, + {"recvmsg", __NR_recvmsg}, + {"recvmmsg", __NR_recvmmsg}, + {"getsockname", __NR_getsockname}, + {"getpeername", __NR_getpeername}, + {"getsockopt", __NR_getsockopt}, + {"setsockopt", __NR_setsockopt}, + {"ioctl", __NR_ioctl}, + {"fcntl$dupfd", __NR_fcntl}, + {"fcntl$getflags", __NR_fcntl}, + {"fcntl$setflags", __NR_fcntl}, + {"fcntl$setstatus", __NR_fcntl}, + {"fcntl$lock", __NR_fcntl}, + {"fcntl$getown", __NR_fcntl}, + {"fcntl$setown", __NR_fcntl}, + {"fcntl$getownex", __NR_fcntl}, + {"fcntl$setownex", __NR_fcntl}, + {"fcntl$setsig", __NR_fcntl}, + {"fcntl$setlease", __NR_fcntl}, + {"fcntl$notify", __NR_fcntl}, + {"fcntl$setpipe", __NR_fcntl}, + {"ptrace", __NR_ptrace}, + {"ptrace$peek", __NR_ptrace}, + {"ptrace$poke", __NR_ptrace}, + {"ptrace$peekuser", __NR_ptrace}, + {"ptrace$pokeuser", __NR_ptrace}, + {"ptrace$getregs", __NR_ptrace}, + {"ptrace$getregset", __NR_ptrace}, + {"ptrace$setregs", __NR_ptrace}, + {"ptrace$setregset", __NR_ptrace}, + {"ptrace$getsig", __NR_ptrace}, + {"ptrace$setsig", __NR_ptrace}, + {"ptrace$setopts", __NR_ptrace}, + {"ptrace$getenv", __NR_ptrace}, + {"ptrace$cont", __NR_ptrace}, + {"io_setup", __NR_io_setup}, + {"io_destroy", __NR_io_destroy}, + {"io_getevents", __NR_io_getevents}, + {"io_submit", __NR_io_submit}, + {"io_cancel", __NR_io_cancel}, + {"capget", __NR_capget}, + {"capset", __NR_capset}, + {"prctl", __NR_prctl}, + {"arch_prctl", __NR_arch_prctl}, + {"seccomp", __NR_seccomp}, + {"add_key", __NR_add_key}, + {"request_key", __NR_request_key}, + {"keyctl", __NR_keyctl}, + {"mq_open", __NR_mq_open}, + {"mq_timedsend", __NR_mq_timedsend}, + {"mq_timedreceive", __NR_mq_timedreceive}, + {"mq_notify", __NR_mq_notify}, + {"mq_getsetattr", __NR_mq_getsetattr}, + {"mq_unlink", __NR_mq_unlink}, + {"msgget", __NR_msgget}, + {"msgsnd", __NR_msgsnd}, + {"msgrcv", __NR_msgrcv}, + {"msgctl", __NR_msgctl}, + {"semget", __NR_semget}, + {"semop", __NR_semop}, + {"semtimedop", __NR_semtimedop}, + {"semctl", __NR_semctl}, + {"shmget", __NR_shmget}, + {"shmat", __NR_shmat}, + {"shmctl", __NR_shmctl}, + {"shmdt", __NR_shmdt}, + {"mknod", __NR_mknod}, + {"mknodat", __NR_mknodat}, + {"chmod", __NR_chmod}, + {"fchmod", __NR_fchmod}, + {"fchmodat", __NR_fchmodat}, + {"chown", __NR_chown}, + {"lchown", __NR_lchown}, + {"fchown", __NR_fchown}, + {"fchownat", __NR_fchownat}, + {"fallocate", __NR_fallocate}, + {"faccessat", __NR_faccessat}, + {"utime", __NR_utime}, + {"utimes", __NR_utimes}, + {"futimesat", __NR_futimesat}, + {"utimensat", __NR_utimensat}, + {"getgid", __NR_getgid}, + {"getegid", __NR_getegid}, + {"setuid", __NR_setuid}, + {"setgid", __NR_setgid}, + {"getuid", __NR_getuid}, + {"geteuid", __NR_geteuid}, + {"setpgid", __NR_setpgid}, + {"getpgid", __NR_getpgid}, + {"getpgrp", __NR_getpgrp}, + {"getpid", __NR_getpid}, + {"gettid", __NR_gettid}, + {"setreuid", __NR_setreuid}, + {"setregid", __NR_setregid}, + {"setresuid", __NR_setresuid}, + {"setresgid", __NR_setresgid}, + {"getresuid", __NR_getresuid}, + {"getresgid", __NR_getresgid}, + {"setfsuid", __NR_setfsuid}, + {"setfsgid", __NR_setfsgid}, + {"getgroups", __NR_getgroups}, + {"setgroups", __NR_setgroups}, + {"personality", __NR_personality}, + {"inotify_init", __NR_inotify_init}, + {"inotify_init1", __NR_inotify_init1}, + {"inotify_add_watch", __NR_inotify_add_watch}, + {"inotify_rm_watch", __NR_inotify_rm_watch}, + {"fanotify_init", __NR_fanotify_init}, + {"fanotify_mark", __NR_fanotify_mark}, + {"link", __NR_link}, + {"linkat", __NR_linkat}, + {"symlinkat", __NR_symlinkat}, + {"symlink", __NR_symlink}, + {"unlink", __NR_unlink}, + {"unlinkat", __NR_unlinkat}, + {"readlink", __NR_readlink}, + {"readlinkat", __NR_readlinkat}, + {"rename", __NR_rename}, + {"renameat", __NR_renameat}, + {"renameat2", __NR_renameat2}, + {"mkdir", __NR_mkdir}, + {"mkdirat", __NR_mkdirat}, + {"rmdir", __NR_rmdir}, + {"truncate", __NR_truncate}, + {"ftruncate", __NR_ftruncate}, + {"flock", __NR_flock}, + {"fsync", __NR_fsync}, + {"fdatasync", __NR_fdatasync}, + {"sync", __NR_sync}, + {"syncfs", __NR_syncfs}, + {"sync_file_range", __NR_sync_file_range}, + {"lookup_dcookie", __NR_lookup_dcookie}, + {"getdents", __NR_getdents}, + {"getdents64", __NR_getdents64}, + {"name_to_handle_at", __NR_name_to_handle_at}, + {"open_by_handle_at", __NR_open_by_handle_at}, + {"mount", __NR_mount}, + {"umount2", __NR_umount2}, + {"pivot_root", __NR_pivot_root}, + {"sysfs", __NR_sysfs}, + {"statfs", __NR_statfs}, + {"fstatfs", __NR_fstatfs}, + {"uselib", __NR_uselib}, + {"init_module", __NR_init_module}, + {"finit_module", __NR_finit_module}, + {"delete_module", __NR_delete_module}, + {"kexec_load", __NR_kexec_load}, + {"get_kernel_syms", __NR_get_kernel_syms}, + {"syslog", __NR_syslog}, + {"uname", __NR_uname}, + {"sysinfo", __NR_sysinfo}, + {"ustat", __NR_ustat}, + {"acct", __NR_acct}, + {"getrusage", __NR_getrusage}, + {"getrlimit", __NR_getrlimit}, + {"setrlimit", __NR_setrlimit}, + {"prlimit64", __NR_prlimit64}, + {"iopl", __NR_iopl}, + {"ioperm", __NR_ioperm}, + {"ioprio_get", __NR_ioprio_get}, + {"ioprio_set", __NR_ioprio_set}, + {"setns", __NR_setns}, + {"setxattr", __NR_setxattr}, + {"lsetxattr", __NR_lsetxattr}, + {"fsetxattr", __NR_fsetxattr}, + {"getxattr", __NR_getxattr}, + {"lgetxattr", __NR_lgetxattr}, + {"fgetxattr", __NR_fgetxattr}, + {"listxattr", __NR_listxattr}, + {"llistxattr", __NR_llistxattr}, + {"flistxattr", __NR_flistxattr}, + {"removexattr", __NR_removexattr}, + {"lremovexattr", __NR_lremovexattr}, + {"fremovexattr", __NR_fremovexattr}, + {"time", __NR_time}, + {"clock_gettime", __NR_clock_gettime}, + {"clock_settime", __NR_clock_settime}, + {"clock_adjtime", __NR_clock_adjtime}, + {"clock_getres", __NR_clock_getres}, + {"clock_nanosleep", __NR_clock_nanosleep}, + {"timer_create", __NR_timer_create}, + {"timer_gettime", __NR_timer_gettime}, + {"timer_getoverrun", __NR_timer_getoverrun}, + {"timer_settime", __NR_timer_settime}, + {"timer_delete", __NR_timer_delete}, + {"rt_sigaction", __NR_rt_sigaction}, + {"rt_sigprocmask", __NR_rt_sigprocmask}, + {"rt_sigreturn", __NR_rt_sigreturn}, + {"rt_sigpending", __NR_rt_sigpending}, + {"rt_sigtimedwait", __NR_rt_sigtimedwait}, + {"rt_sigsuspend", __NR_rt_sigsuspend}, + {"rt_sigqueueinfo", __NR_rt_sigqueueinfo}, + {"rt_tgsigqueueinfo", __NR_rt_tgsigqueueinfo}, + {"sigaltstack", __NR_sigaltstack}, + {"tgkill", __NR_tgkill}, + {"tkill", __NR_tkill}, + {"pause", __NR_pause}, + {"alarm", __NR_alarm}, + {"nanosleep", __NR_nanosleep}, + {"getitimer", __NR_getitimer}, + {"setitimer", __NR_setitimer}, + {"exit", __NR_exit}, + {"exit_group", __NR_exit_group}, + {"waitid", __NR_waitid}, + {"wait4", __NR_wait4}, + {"times", __NR_times}, + {"set_thread_area", __NR_set_thread_area}, + {"get_thread_area", __NR_get_thread_area}, + {"set_tid_address", __NR_set_tid_address}, + {"getpriority", __NR_getpriority}, + {"setpriority", __NR_setpriority}, + {"sched_getscheduler", __NR_sched_getscheduler}, + {"sched_setscheduler", __NR_sched_setscheduler}, + {"sched_rr_get_interval", __NR_sched_rr_get_interval}, + {"sched_getparam", __NR_sched_getparam}, + {"sched_setparam", __NR_sched_setparam}, + {"sched_getaffinity", __NR_sched_getaffinity}, + {"sched_setaffinity", __NR_sched_setaffinity}, + {"sched_getattr", __NR_sched_getattr}, + {"sched_setattr", __NR_sched_setattr}, + {"sched_yield", __NR_sched_yield}, +}; diff --git a/fuzzer/fuzzer.go b/fuzzer/fuzzer.go new file mode 100644 index 000000000..5cca527ad --- /dev/null +++ b/fuzzer/fuzzer.go @@ -0,0 +1,418 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package main + +// TODO: implement some form of smashing of new inputs. +// E.g. alter arguments while the program still gives the new coverage, +// i.e. aim at cracking new branches and triggering bugs in that new piece of code. + +import ( + "bytes" + "crypto/sha1" + "encoding/binary" + "flag" + "fmt" + "log" + "math/rand" + "net/rpc" + "os" + "runtime/debug" + "strconv" + "strings" + "sync" + "time" + + "github.com/google/syzkaller/cover" + "github.com/google/syzkaller/ipc" + "github.com/google/syzkaller/prog" + . "github.com/google/syzkaller/rpctype" + "github.com/google/syzkaller/sys" +) + +var ( + flagName = flag.String("name", "", "unique name for manager") + flagExecutor = flag.String("executor", "", "path to executor binary") + flagManager = flag.String("manager", "", "manager rpc address") + flagStrace = flag.Bool("strace", false, "run executor under strace") + flagParallel = flag.Int("parallel", 1, "run that many tests in parallel") + flagSaveProg = flag.Bool("saveprog", false, "save programs into local file before executing") + flagSyscalls = flag.String("calls", "", "comma-delimited list of enabled syscall IDs (empty string for all syscalls)") + flagV = flag.Int("v", 0, "verbosity") +) + +const ( + programLength = 30 +) + +type Sig [sha1.Size]byte + +func hash(data []byte) Sig { + return Sig(sha1.Sum(data)) +} + +type Input struct { + p *prog.Prog + call int + cover cover.Cover +} + +var ( + corpusCover []cover.Cover + maxCover []cover.Cover + flakes cover.Cover + corpus []Input + corpusHashes map[Sig]struct{} + triage []Input + manager *rpc.Client + + workerIn = make(chan *prog.Prog, 10) + workerOut = make(chan []Input, 10) +) + +func main() { + debug.SetGCPercent(50) + flag.Parse() + logf(0, "started") + + var calls []*sys.Call + if *flagSyscalls != "" { + for _, id := range strings.Split(*flagSyscalls, ",") { + n, err := strconv.ParseUint(id, 10, 64) + if err != nil || n >= uint64(len(sys.Calls)) { + panic(fmt.Sprintf("invalid syscall in -calls flag: '%v", id)) + } + calls = append(calls, sys.Calls[n]) + } + } + + corpusCover = make([]cover.Cover, sys.CallCount) + maxCover = make([]cover.Cover, sys.CallCount) + corpusHashes = make(map[Sig]struct{}) + + conn, err := rpc.Dial("tcp", *flagManager) + if err != nil { + panic(err) + } + manager = conn + a := &ManagerConnectArgs{*flagName} + r := &ManagerConnectRes{} + if err := manager.Call("Manager.Connect", a, r); err != nil { + panic(err) + } + + if *flagParallel <= 0 { + *flagParallel = 1 + } + flags := ipc.FlagCover + if *flagStrace { + flags |= ipc.FlagStrace + } + workerIn = make(chan *prog.Prog, *flagParallel+10) + workerOut = make(chan []Input, *flagParallel) + for i := 0; i < *flagParallel; i++ { + env, err := ipc.MakeEnv(*flagExecutor, 4*time.Second, flags) + if err != nil { + panic(err) + } + workerId := i + 1 + go func() { + for p := range workerIn { + workerOut <- execute(env, p, workerId) + } + }() + } + env, err := ipc.MakeEnv(*flagExecutor, 4*time.Second, flags) + if err != nil { + panic(err) + } + rs := rand.NewSource(time.Now().UnixNano()) + rnd := rand.New(rs) + var lastPoll time.Time + var lastPrint time.Time + secondTicker := time.NewTicker(100 * time.Millisecond).C + for i := 0; ; i++ { + if !*flagSaveProg && time.Since(lastPrint) > 10*time.Second { + // Keep-alive for manager. + logf(0, "#%v: alive", i) + lastPrint = time.Now() + } + if len(triage) != 0 { + last := len(triage) - 1 + inp := triage[last] + triage = triage[:last] + logf(1, "#%v: triaging : %s", i, inp.p) + triageInput(env, inp) + continue + } + if time.Since(lastPoll) > 10*time.Second { + a := &ManagerPollArgs{*flagName} + r := &ManagerPollRes{} + if err := manager.Call("Manager.Poll", a, r); err != nil { + panic(err) + } + for _, inp := range r.NewInputs { + addInput(inp) + } + for _, data := range r.Candidates { + p, err := prog.Deserialize(data) + if err != nil { + panic(err) + } + inputs := execute(env, p, 0) + for _, inp := range inputs { + call := inp.p.Calls[inp.call].Meta + maxCover[call.CallID] = cover.Union(maxCover[call.CallID], inp.cover) + triage = append(triage, inp) + } + } + if len(r.NewInputs) == 0 && len(r.Candidates) == 0 { + lastPoll = time.Now() + } + continue + } + // Parallel part. + pending := 0 + for ; ; i++ { + if !(!*flagSaveProg && time.Since(lastPrint) > 10*time.Second) && + !(len(triage) != 0) && + !(time.Since(lastPoll) > 10*time.Second) { + // No need to do any work above. + // Send new inputs to workers, if they need some. + for len(workerIn) < *flagParallel { + if len(corpus) == 0 || i%10 == 0 { + p := prog.Generate(rnd, programLength, calls) + logf(1, "#%v: generated: %s", i, p) + workerIn <- p + pending++ + p = p.Clone() + p.Mutate(rnd, programLength, calls) + logf(1, "#%v: mutated: %s", i, p) + workerIn <- p + pending++ + } else { + inp := corpus[rnd.Intn(len(corpus))] + p := inp.p.Clone() + p.Mutate(rs, programLength, calls) + logf(1, "#%v: mutated: %s <- %s", i, p, inp.p) + workerIn <- p + pending++ + } + } + } else if pending == 0 { + // Need to do some work above. + // Break if collected all pending results. + break + } + // Collect results. + select { + case inputs := <-workerOut: + pending-- + for _, inp := range inputs { + triage = append(triage, inp) + } + case <-secondTicker: + } + } + // Do this after the parallel section because workers access maxCover. + for _, inp := range triage { + call := inp.p.Calls[inp.call].Meta + maxCover[call.CallID] = cover.Union(maxCover[call.CallID], inp.cover) + } + } +} + +func addInput(inp RpcInput) { + p, err := prog.Deserialize(inp.Prog) + if err != nil { + panic(err) + } + if inp.CallIndex < 0 || inp.CallIndex >= len(p.Calls) { + panic("bad call index") + } + call := p.Calls[inp.CallIndex].Meta + sig := hash(inp.Prog) + if _, ok := corpusHashes[sig]; ok { + return + } + cov := cover.Canonicalize(inp.Cover) + diff := cover.Difference(cov, maxCover[call.CallID]) + diff = cover.Difference(diff, flakes) + if len(diff) == 0 { + return + } + inp1 := Input{p, inp.CallIndex, cov} + corpus = append(corpus, inp1) + corpusCover[call.CallID] = cover.Union(corpusCover[call.CallID], cov) + maxCover[call.CallID] = cover.Union(maxCover[call.CallID], cov) + corpusHashes[hash(inp.Prog)] = struct{}{} +} + +func triageInput(env *ipc.Env, inp Input) { + call := inp.p.Calls[inp.call].Meta + newCover := cover.Difference(inp.cover, corpusCover[call.CallID]) + newCover = cover.Difference(newCover, flakes) + if len(newCover) == 0 { + return + } + + if _, ok := corpusHashes[hash(inp.p.Serialize())]; ok { + return + } + + minCover := inp.cover + for i := 0; i < 3; i++ { + allCover := execute1(env, inp.p, 0) + if len(allCover[inp.call]) == 0 { + // The call was not executed. Happens sometimes, reason unknown. + continue + } + cov := allCover[inp.call] + diff := cover.SymmetricDifference(inp.cover, cov) + if len(diff) != 0 { + flakes = cover.Union(flakes, diff) + } + minCover = cover.Intersection(minCover, cov) + } + stableNewCover := cover.Intersection(newCover, minCover) + if len(stableNewCover) == 0 { + return + } + inp.p, inp.call = prog.Minimize(inp.p, inp.call, func(p1 *prog.Prog, call1 int) bool { + allCover := execute1(env, p1, 0) + if len(allCover[call1]) == 0 { + return false // The call was not executed. + } + cov := allCover[call1] + if len(cover.Intersection(stableNewCover, cov)) != len(stableNewCover) { + return false + } + minCover = cover.Intersection(minCover, cov) + return true + }) + inp.cover = minCover + corpusCover[call.CallID] = cover.Union(corpusCover[call.CallID], minCover) + corpus = append(corpus, inp) + data := inp.p.Serialize() + corpusHashes[hash(data)] = struct{}{} + + logf(2, "added new input for %v to corpus:\n%s", call.CallName, data) + + a := &NewManagerInputArgs{*flagName, RpcInput{call.CallName, inp.p.Serialize(), inp.call, []uint32(inp.cover)}} + if err := manager.Call("Manager.NewInput", a, nil); err != nil { + panic(err) + } +} + +func execute(env *ipc.Env, p *prog.Prog, workerId int) []Input { + allCover := execute1(env, p, workerId) + var inputs []Input + for i, cov := range allCover { + if len(cov) == 0 { + continue + } + c := p.Calls[i].Meta + diff := cover.Difference(cov, maxCover[c.CallID]) + diff = cover.Difference(diff, flakes) + if len(diff) != 0 { + p1 := p.Clone() + p1.TrimAfter(i) + inputs = append(inputs, Input{p1, i, cover.Copy(cov)}) + } + } + return inputs +} + +var logMu sync.Mutex + +func execute1(env *ipc.Env, p *prog.Prog, workerId int) []cover.Cover { + if *flagSaveProg { + f, err := os.Create(fmt.Sprintf("%v-%v.prog", *flagName, workerId)) + if err == nil { + f.Write(p.Serialize()) + f.Close() + } + } else { + // The following output helps to understand what program crashed kernel. + // It must not be intermixed. + logMu.Lock() + log.Printf("worker #%v: executing program:\n%s", workerId, p.Serialize()) + logMu.Unlock() + } + + try := 0 +retry: + exec := p.SerializeForExec() + if len(exec) > len(env.In) { + panic("program is too long") + } + copy(env.In, exec) + // Zero out the first word (ncmd), so that we don't have garbage there + // if executor crashes before writing non-garbage there. + for i := 0; i < 4; i++ { + env.Out[i] = 0 + } + output, strace, failed, hanged, err := env.Exec() + if err != nil { + if try > 10 { + panic(err) + } + try++ + debug.FreeOSMemory() + time.Sleep(time.Second) + goto retry + } + logf(4, "result failed=%v hanged=%v:\n%v\n", failed, hanged, string(output)) + if len(strace) != 0 { + logf(4, "strace:\n%s\n", strace) + } + r := bytes.NewReader(env.Out) + var ncmd uint32 + if err := binary.Read(r, binary.LittleEndian, &ncmd); err != nil { + panic(err) + } + cov := make([]cover.Cover, len(p.Calls)) + for i := uint32(0); i < ncmd; i++ { + var callIndex, callNum, coverSize, pc uint32 + if err := binary.Read(r, binary.LittleEndian, &callIndex); err != nil { + panic(err) + } + if err := binary.Read(r, binary.LittleEndian, &callNum); err != nil { + panic(err) + } + if err := binary.Read(r, binary.LittleEndian, &coverSize); err != nil { + panic(err) + } + if int(callIndex) > len(cov) { + panic(fmt.Sprintf("expect index %v, got %v", i, callIndex)) + } + c := p.Calls[callIndex] + if num := c.Meta.ID; uint32(num) != callNum { + logf(0, "ERROR: call %v: expect syscall %v, got %v, executed %v", callIndex, num, callNum, ncmd) + logf(0, "program:\n%s", p.Serialize()) + logf(0, "output:\n%s", output) + } + cover1 := make([]uint32, 0, coverSize) + for j := uint32(0); j < coverSize; j++ { + if err := binary.Read(r, binary.LittleEndian, &pc); err != nil { + panic(err) + } + cover1 = append(cover1, pc) + } + if *flagV >= 4 { + log.Printf("%v:", c.Meta.Name) + for _, pc := range cover1 { + log.Printf(" 0x%x", (1<<32-1)<<32|uint64(pc)) + } + log.Printf("\n") + } + cov[callIndex] = cover.Canonicalize(cover1) + } + return cov +} + +func logf(v int, msg string, args ...interface{}) { + if *flagV >= v { + log.Printf(msg, args...) + } +} diff --git a/ipc/ipc.go b/ipc/ipc.go new file mode 100644 index 000000000..81aee4970 --- /dev/null +++ b/ipc/ipc.go @@ -0,0 +1,222 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package ipc + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + "syscall" + "time" +) + +type Env struct { + In []byte + Out []byte + + inFile *os.File + outFile *os.File + bin []string + timeout time.Duration + flags uint64 +} + +const ( + FlagDebug = uint64(1) << iota // debug output from executor + FlagCover // collect coverage + FlagThreaded // use multiple threads to mitigate blocked syscalls + FlagStrace // run executor under strace +) + +func MakeEnv(bin string, timeout time.Duration, flags uint64) (*Env, error) { + inf, inmem, err := createMapping(1 << 20) + if err != nil { + return nil, err + } + outf, outmem, err := createMapping(16 << 20) + if err != nil { + closeMapping(inf, inmem) + return nil, err + } + for i := 0; i < 8; i++ { + inmem[i] = byte(flags >> (8 * uint(i))) + } + inmem = inmem[8:] + env := &Env{ + In: inmem, + Out: outmem, + inFile: inf, + outFile: outf, + bin: strings.Split(bin, " "), + timeout: timeout, + flags: flags, + } + if len(env.bin) == 0 { + return nil, fmt.Errorf("binary is empty string") + } + return env, nil +} + +func (env *Env) Close() error { + err1 := closeMapping(env.inFile, env.In) + err2 := closeMapping(env.outFile, env.Out) + switch { + case err1 != nil: + return err1 + case err2 != nil: + return err2 + default: + return nil + } +} + +func (env *Env) Exec() (output, strace []byte, failed, hanged bool, err0 error) { + dir, err := ioutil.TempDir("./", "syzkaller-testdir") + if err != nil { + err0 = fmt.Errorf("failed to create temp dir: %v", err) + return + } + defer os.RemoveAll(dir) + rp, wp, err := os.Pipe() + if err != nil { + err0 = fmt.Errorf("failed to create pipe: %v", err) + return + } + defer rp.Close() + defer wp.Close() + cmd := exec.Command(env.bin[0], env.bin[1:]...) + traceFile := "" + if env.flags&FlagStrace != 0 { + f, err := ioutil.TempFile("./", "syzkaller-strace") + if err != nil { + err0 = fmt.Errorf("failed to create temp file: %v", err) + return + } + f.Close() + defer os.Remove(f.Name()) + traceFile, _ = filepath.Abs(f.Name()) + args := []string{"-s", "8", "-o", traceFile} + args = append(args, env.bin...) + if env.flags&FlagThreaded != 0 { + args = append([]string{"-f"}, args...) + } + cmd = exec.Command("strace", args...) + } + cmd.ExtraFiles = append(cmd.ExtraFiles, env.inFile, env.outFile) + cmd.Env = []string{} + cmd.Dir = dir + cmd.Stdout = wp + cmd.Stderr = wp + if syscall.Getuid() == 0 { + // Running under root, more isolation is possible. + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true, Cloneflags: syscall.CLONE_NEWNS} + } else { + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} + } + if err := cmd.Start(); err != nil { + err0 = fmt.Errorf("failed to start executor binary: %v", err) + return + } + wp.Close() + done := make(chan bool) + hang := make(chan bool) + go func() { + t := time.NewTimer(env.timeout) + select { + case <-t.C: + // We started the process in its own process group and now kill the whole group. + // This solves a potential problem with strace: + // if we kill just strace, executor still runs and ReadAll below hangs. + syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) + syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) + syscall.Kill(cmd.Process.Pid, syscall.SIGKILL) + syscall.Kill(cmd.Process.Pid, syscall.SIGKILL) + hang <- true + case <-done: + t.Stop() + hang <- false + } + }() + output, err = ioutil.ReadAll(rp) + readErr := err + close(done) + if err = cmd.Wait(); <-hang && err != nil { + hanged = true + failed = true + } + if err != nil { + output = append(output, []byte(err.Error())...) + output = append(output, '\n') + } + if cmd.ProcessState != nil { + sys := cmd.ProcessState.Sys() + if ws, ok := sys.(syscall.WaitStatus); ok { + // Magic values returned by executor. + if ws.ExitStatus() == 67 { + err0 = fmt.Errorf("executor failed: %s", output) + return + } + if ws.ExitStatus() == 68 { + failed = true + } + } + } + if readErr != nil { + err0 = fmt.Errorf("failed to read executor output: %v", err) + return + } + if traceFile != "" { + strace, err = ioutil.ReadFile(traceFile) + if err != nil { + err0 = fmt.Errorf("failed to read strace output: %v", err) + return + } + } + return +} + +func createMapping(size int) (f *os.File, mem []byte, err error) { + f, err = ioutil.TempFile("./", "syzkaller-shm") + if err != nil { + return + } + if _, err = f.Write(make([]byte, size)); err != nil { + // if err = f.Truncate(int64(size)); err != nil { + f.Close() + os.Remove(f.Name()) + return + } + f.Close() + f, err = os.OpenFile(f.Name(), os.O_RDWR, 0) + if err != nil { + os.Remove(f.Name()) + return + } + mem, err = syscall.Mmap(int(f.Fd()), 0, size, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED) + if err != nil { + f.Close() + os.Remove(f.Name()) + return + } + return +} + +func closeMapping(f *os.File, mem []byte) error { + err1 := syscall.Munmap(mem) + err2 := f.Close() + err3 := os.Remove(f.Name()) + switch { + case err1 != nil: + return err1 + case err2 != nil: + return err2 + case err3 != nil: + return err3 + default: + return nil + } +} diff --git a/ipc/ipc_test.go b/ipc/ipc_test.go new file mode 100644 index 000000000..d017b7038 --- /dev/null +++ b/ipc/ipc_test.go @@ -0,0 +1,235 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package ipc + +import ( + "bufio" + "bytes" + "io/ioutil" + "math/rand" + "os" + "os/exec" + "strings" + "testing" + "time" + + "github.com/google/syzkaller/prog" +) + +func buildExecutor(t *testing.T) string { + return buildProgram(t, "../executor/executor.cc") +} + +func buildSource(t *testing.T, src []byte) string { + srcf, err := ioutil.TempFile("", "syzkaller") + if err != nil { + t.Fatalf("failed to create temp file: %v", err) + } + srcf.Close() + os.Remove(srcf.Name()) + name := srcf.Name() + ".c" + if err := ioutil.WriteFile(name, src, 0600); err != nil { + t.Fatalf("failed to write temp file: %v", err) + } + defer os.Remove(name) + return buildProgram(t, name) +} + +func buildProgram(t *testing.T, src string) string { + bin, err := ioutil.TempFile("", "syzkaller") + if err != nil { + t.Fatalf("failed to create temp file: %v", err) + } + bin.Close() + out, err := exec.Command("gcc", src, "-o", bin.Name(), "-lpthread", "-static", "-O1", "-g").CombinedOutput() + if err != nil { + os.Remove(bin.Name()) + data, _ := ioutil.ReadFile(src) + t.Fatalf("failed to build program:\n%s\n%s", data, out) + } + return bin.Name() +} + +func initTest(t *testing.T) (rand.Source, int) { + iters := 100 + if testing.Short() { + iters = 10 + } + seed := int64(time.Now().UnixNano()) + rs := rand.NewSource(seed) + t.Logf("seed=%v", seed) + return rs, iters +} + +func TestEmptyProg(t *testing.T) { + bin := buildExecutor(t) + defer os.Remove(bin) + + env, err := MakeEnv(bin, time.Second, 0) + if err != nil { + t.Fatalf("failed to create env: %v", err) + } + defer env.Close() + + p := new(prog.Prog) + data := p.SerializeForExec() + copy(env.In, data) + + output, strace, failed, hanged, err := env.Exec() + if err != nil { + t.Fatalf("failed to run executor: %v", err) + } + if len(output) != 0 { + t.Fatalf("output on empty program") + } + if len(strace) != 0 { + t.Fatalf("strace output when not stracing") + } + if failed || hanged { + t.Fatalf("empty program failed") + } +} + +func TestStrace(t *testing.T) { + bin := buildExecutor(t) + defer os.Remove(bin) + + env, err := MakeEnv(bin, time.Second, FlagStrace) + if err != nil { + t.Fatalf("failed to create env: %v", err) + } + defer env.Close() + + p := new(prog.Prog) + data := p.SerializeForExec() + copy(env.In, data) + + _, strace, failed, hanged, err := env.Exec() + if err != nil { + t.Fatalf("failed to run executor: %v", err) + } + if len(strace) == 0 { + t.Fatalf("no strace output") + } + if failed || hanged { + t.Fatalf("empty program failed") + } +} + +func TestExecute(t *testing.T) { + bin := buildExecutor(t) + defer os.Remove(bin) + + rs, iters := initTest(t) + flags := []uint64{0, FlagStrace, FlagThreaded, FlagStrace | FlagThreaded} + for _, flag := range flags { + env, err := MakeEnv(bin, time.Second, flag) + if err != nil { + t.Fatalf("failed to create env: %v", err) + } + defer env.Close() + + for i := 0; i < iters/len(flags); i++ { + p := prog.Generate(rs, 10, nil) + data := p.SerializeForExec() + copy(env.In, data) + + _, _, _, _, err := env.Exec() + if err != nil { + t.Fatalf("failed to run executor: %v", err) + } + } + } +} + +func TestCompare(t *testing.T) { + t.Skip("flaky") + + bin := buildExecutor(t) + defer os.Remove(bin) + + // Sequence of syscalls that statically linked libc produces on startup. + rawTracePrefix := []string{"execve", "uname", "brk", "brk", "arch_prctl", + "readlink", "brk", "brk", "access"} + executorTracePrefix := []string{"execve", "uname", "brk", "brk", "arch_prctl", + "set_tid_address", "set_robust_list", "futex", "rt_sigaction", "rt_sigaction", + "rt_sigprocmask", "getrlimit", "readlink", "brk", "brk", "access", "mmap", "mmap"} + // These calls produce non-deterministic results, ignore them. + nondet := []string{"getrusage", "msgget", "msgrcv", "msgsnd", "shmget", "semat", "io_setup", "getpgrp", + "getpid", "getpgid", "getppid", "setsid", "ppoll", "keyctl", "ioprio_get", + "move_pages", "kcmp"} + + env1, err := MakeEnv(bin, time.Second, FlagStrace) + if err != nil { + t.Fatalf("failed to create env: %v", err) + } + defer env1.Close() + + rs, iters := initTest(t) + for i := 0; i < iters; i++ { + p := prog.Generate(rs, 10, nil) + data := p.SerializeForExec() + copy(env1.In, data) + + _, strace1, _, _, err := env1.Exec() + if err != nil { + t.Fatalf("failed to run executor: %v", err) + } + + src := p.WriteCSource() + cprog := buildSource(t, src) + defer os.Remove(cprog) + + env2, err := MakeEnv(cprog, time.Second, FlagStrace) + if err != nil { + t.Fatalf("failed to create env: %v", err) + } + defer env2.Close() // yes, that's defer in a loop + + _, strace2, _, _, err := env2.Exec() + if err != nil { + t.Fatalf("failed to run c binary: %v", err) + } + stripPrefix := func(data []byte, prefix []string) string { + prefix0 := prefix + buf := new(bytes.Buffer) + s := bufio.NewScanner(bytes.NewReader(data)) + for s.Scan() { + if strings.HasPrefix(s.Text(), "--- SIG") { + // Signal parameters can contain pid and pc. + continue + } + if len(prefix) == 0 { + skip := false + for _, c := range nondet { + if strings.HasPrefix(s.Text(), c) { + skip = true + break + } + } + if skip { + continue + } + buf.WriteString(s.Text()) + buf.Write([]byte{'\n'}) + continue + } + if !strings.HasPrefix(s.Text(), prefix[0]) { + t.Fatalf("strace output does not start with expected prefix\ngot:\n%s\nexpect prefix: %+v\ncurrent call: %v", data, prefix0, prefix[0]) + } + prefix = prefix[1:] + } + if err := s.Err(); err != nil { + t.Fatalf("failed to scan strace output: %v", err) + } + return buf.String() + } + s1 := stripPrefix(strace1, executorTracePrefix) + s2 := stripPrefix(strace2, rawTracePrefix) + if s1 == "" || s1 != s2 { + t.Logf("program:\n%s\n", p.Serialize()) + t.Fatalf("strace output differs:\n%s\n\n\n%s\n", s1, s2) + } + } +} diff --git a/manager/cover.go b/manager/cover.go new file mode 100644 index 000000000..accc230f9 --- /dev/null +++ b/manager/cover.go @@ -0,0 +1,286 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package main + +import ( + "bufio" + "bytes" + "fmt" + "html/template" + "io" + "io/ioutil" + "os/exec" + "sort" + "strconv" + "strings" + "sync" +) + +type LineInfo struct { + file string + line int +} + +var ( + mu sync.Mutex + pcLines = make(map[uint32][]LineInfo) + parsedFiles = make(map[string][][]byte) + htmlReplacer = strings.NewReplacer(">", ">", "<", "<", "&", "&", "\t", " ") + sourcePrefix string +) + +func generateCoverHtml(w io.Writer, vmlinux string, cov []uint32) error { + mu.Lock() + defer mu.Unlock() + + info, err := covToLineInfo(vmlinux, cov) + if err != nil { + return err + } + files := fileSet(info) + for f := range files { + if _, ok := parsedFiles[f]; ok { + continue + } + if err := parseFile(f); err != nil { + return err + } + } + + var d templateData + for f, covered := range files { + lines := parsedFiles[f] + coverage := len(covered) + var buf bytes.Buffer + for i, ln := range lines { + if len(covered) > 0 && covered[0] == i+1 { + buf.Write([]byte("<span id='covered'>")) + buf.Write(ln) + buf.Write([]byte("</span>\n")) + covered = covered[1:] + } else { + buf.Write(ln) + buf.Write([]byte("\n")) + } + } + stripped := f + if len(stripped) > len(sourcePrefix) { + stripped = stripped[len(sourcePrefix):] + } + d.Files = append(d.Files, &templateFile{ + Name: stripped, + Body: template.HTML(buf.String()), + Coverage: coverage, + }) + } + + sort.Sort(templateFileArray(d.Files)) + if err := coverTemplate.Execute(w, d); err != nil { + return err + } + return nil +} + +func covToLineInfo(vmlinux string, cov []uint32) ([]LineInfo, error) { + var missing []uint32 + for _, pc := range cov { + if _, ok := pcLines[pc]; !ok { + missing = append(missing, pc) + } + } + if len(missing) > 0 { + if err := symbolize(vmlinux, missing); err != nil { + return nil, err + } + } + var info []LineInfo + for _, pc := range cov { + info = append(info, pcLines[pc]...) + } + return info, nil +} + +func fileSet(info []LineInfo) map[string][]int { + files := make(map[string]map[int]struct{}) + for _, li := range info { + if files[li.file] == nil { + files[li.file] = make(map[int]struct{}) + } + files[li.file][li.line] = struct{}{} + } + res := make(map[string][]int) + for f, lines := range files { + sorted := make([]int, 0, len(lines)) + for ln := range lines { + sorted = append(sorted, ln) + } + sort.Ints(sorted) + res[f] = sorted + } + return res +} + +func parseFile(fn string) error { + data, err := ioutil.ReadFile(fn) + if err != nil { + return err + } + var lines [][]byte + for { + idx := bytes.IndexByte(data, '\n') + if idx == -1 { + break + } + lines = append(lines, []byte(htmlReplacer.Replace(string(data[:idx])))) + data = data[idx+1:] + } + if len(data) != 0 { + lines = append(lines, data) + } + parsedFiles[fn] = lines + if sourcePrefix == "" { + sourcePrefix = fn + } else { + i := 0 + for ; i < len(sourcePrefix) && i < len(fn); i++ { + if sourcePrefix[i] != fn[i] { + break + } + } + sourcePrefix = sourcePrefix[:i] + } + return nil +} + +func symbolize(vmlinux string, cov []uint32) error { + cmd := exec.Command("addr2line", "-a", "-i", "-e", vmlinux) + stdin, err := cmd.StdinPipe() + if err != nil { + return err + } + defer stdin.Close() + stdout, err := cmd.StdoutPipe() + if err != nil { + return err + } + defer stdout.Close() + if err := cmd.Start(); err != nil { + return err + } + defer cmd.Wait() + go func() { + for _, pc := range cov { + fmt.Fprintf(stdin, "0xffffffff%x\n", pc-1) + } + stdin.Close() + }() + s := bufio.NewScanner(stdout) + var pc uint32 + for s.Scan() { + ln := s.Text() + if len(ln) > 3 && ln[0] == '0' && ln[1] == 'x' { + v, err := strconv.ParseUint(ln, 0, 64) + if err != nil { + return fmt.Errorf("failed to parse pc in addr2line output: %v", err) + } + pc = uint32(v) + 1 + continue + } + colon := strings.IndexByte(ln, ':') + if colon == -1 { + continue + } + file := ln[:colon] + line, err := strconv.Atoi(ln[colon+1:]) + if err != nil || pc == 0 || file == "" || file == "??" || line <= 0 { + continue + } + pcLines[pc] = append(pcLines[pc], LineInfo{file, line}) + } + if err := s.Err(); err != nil { + return err + } + return nil +} + +type templateData struct { + Files []*templateFile +} + +type templateFile struct { + Name string + Body template.HTML + Coverage int +} + +type templateFileArray []*templateFile + +func (a templateFileArray) Len() int { return len(a) } +func (a templateFileArray) Less(i, j int) bool { return a[i].Name < a[j].Name } +func (a templateFileArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +var coverTemplate = template.Must(template.New("").Parse( + ` +<!DOCTYPE html> +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <style> + body { + background: white; + } + #topbar { + background: black; + position: fixed; + top: 0; left: 0; right: 0; + height: 42px; + border-bottom: 1px solid rgb(70, 70, 70); + } + #nav { + float: left; + margin-left: 10px; + margin-top: 10px; + } + #content { + font-family: 'Courier New', Courier, monospace; + color: rgb(70, 70, 70); + margin-top: 50px; + } + #covered { + color: rgb(0, 0, 0); + font-weight: bold; + } + </style> + </head> + <body> + <div id="topbar"> + <div id="nav"> + <select id="files"> + {{range $i, $f := .Files}} + <option value="file{{$i}}">{{$f.Name}} ({{$f.Coverage}})</option> + {{end}} + </select> + </div> + </div> + <div id="content"> + {{range $i, $f := .Files}} + <pre class="file" id="file{{$i}}" {{if $i}}style="display: none"{{end}}>{{$f.Body}}</pre> + {{end}} + </div> + </body> + <script> + (function() { + var files = document.getElementById('files'); + var visible = document.getElementById('file0'); + files.addEventListener('change', onChange, false); + function onChange() { + visible.style.display = 'none'; + visible = document.getElementById(files.value); + visible.style.display = 'block'; + window.scrollTo(0, 0); + } + })(); + </script> +</html> +`)) diff --git a/manager/example.cfg b/manager/example.cfg new file mode 100644 index 000000000..216e09eeb --- /dev/null +++ b/manager/example.cfg @@ -0,0 +1,25 @@ +{ + "name": "my-qemu-asan", + "http": "myhost.com:56741", + "master": "myhost.com:48342", + "workdir": "/syzkaller/manager/workdir", + "vmlinux": "/linux/vmlinux", + "type": "qemu", + "count": 16, + "port": 23504, + "params": { + "kernel": "/linux/arch/x86/boot/bzImage", + "image": "/linux_image/wheezy.img", + "sshkey": "/linux_image/ssh/id_rsa", + "fuzzer": "/syzkaller/fuzzer/fuzzer", + "executor": "/syzkaller/executor/executor", + "port": 23505, + "cpu": 2, + "mem": 2048 + }, + "disable_syscalls": [ + "keyctl", + "add_key", + "request_key" + ] +} diff --git a/manager/html.go b/manager/html.go new file mode 100644 index 000000000..242492e38 --- /dev/null +++ b/manager/html.go @@ -0,0 +1,188 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package main + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "html/template" + "net/http" + "sort" + "strconv" + + "github.com/google/syzkaller/cover" + "github.com/google/syzkaller/prog" +) + +func (mgr *Manager) httpInfo(w http.ResponseWriter, r *http.Request) { + mgr.mu.Lock() + defer mgr.mu.Unlock() + + type CallCov struct { + count int + cov cover.Cover + } + calls := make(map[string]*CallCov) + for _, inp := range mgr.corpus { + if calls[inp.Call] == nil { + calls[inp.Call] = new(CallCov) + } + cc := calls[inp.Call] + cc.count++ + cc.cov = cover.Union(cc.cov, cover.Cover(inp.Cover)) + } + + data := &UIData{ + Name: mgr.cfg.Name, + MasterHttp: mgr.masterHttp, + MasterCorpusSize: len(mgr.masterCorpus), + CorpusSize: len(mgr.corpus), + } + + var cov cover.Cover + for c, cc := range calls { + cov = cover.Union(cov, cc.cov) + data.Calls = append(data.Calls, UICallType{c, cc.count, len(cc.cov)}) + } + sort.Sort(UICallTypeArray(data.Calls)) + data.CoverSize = len(cov) + + if err := htmlTemplate.Execute(w, data); err != nil { + http.Error(w, fmt.Sprintf("failed to execute template: %v", err), http.StatusInternalServerError) + } +} + +func (mgr *Manager) httpCorpus(w http.ResponseWriter, r *http.Request) { + mgr.mu.Lock() + defer mgr.mu.Unlock() + + var data []UIInput + call := r.FormValue("call") + for i, inp := range mgr.corpus { + if call != inp.Call { + continue + } + p, err := prog.Deserialize(inp.Prog) + if err != nil { + http.Error(w, fmt.Sprintf("failed to deserialize program: %v", err), http.StatusInternalServerError) + } + data = append(data, UIInput{ + Short: p.String(), + Full: string(inp.Prog), + Cover: len(inp.Cover), + N: i, + }) + } + sort.Sort(UIInputArray(data)) + + if err := corpusTemplate.Execute(w, data); err != nil { + http.Error(w, fmt.Sprintf("failed to execute template: %v", err), http.StatusInternalServerError) + } +} + +func (mgr *Manager) httpCover(w http.ResponseWriter, r *http.Request) { + mgr.mu.Lock() + defer mgr.mu.Unlock() + + var cov cover.Cover + call := r.FormValue("call") + if n, err := strconv.Atoi(call); err == nil && n < len(mgr.corpus) { + cov = mgr.corpus[n].Cover + } else { + for _, inp := range mgr.corpus { + if call == "" || call == inp.Call { + cov = cover.Union(cov, cover.Cover(inp.Cover)) + } + } + } + + if err := generateCoverHtml(w, mgr.cfg.Vmlinux, cov); err != nil { + http.Error(w, fmt.Sprintf("failed to generate coverage profile: %v", err), http.StatusInternalServerError) + } +} + +func (mgr *Manager) httpCurrentCorpus(w http.ResponseWriter, r *http.Request) { + mgr.mu.Lock() + defer mgr.mu.Unlock() + + mgr.minimizeCorpus() + var hashes []string + for _, inp := range mgr.corpus { + hash := hash(inp.Prog) + hashes = append(hashes, hex.EncodeToString(hash[:])) + } + data, err := json.Marshal(&hashes) + if err != nil { + http.Error(w, fmt.Sprintf("failed to marshal corpus: %v", err), http.StatusInternalServerError) + return + } + w.Write(data) +} + +type UIData struct { + Name string + MasterHttp string + MasterCorpusSize int + CorpusSize int + CoverSize int + Calls []UICallType +} + +type UICallType struct { + Name string + Inputs int + Cover int +} + +type UIInput struct { + Short string + Full string + Calls int + Cover int + N int +} + +type UICallTypeArray []UICallType + +func (a UICallTypeArray) Len() int { return len(a) } +func (a UICallTypeArray) Less(i, j int) bool { return a[i].Name < a[j].Name } +func (a UICallTypeArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +type UIInputArray []UIInput + +func (a UIInputArray) Len() int { return len(a) } +func (a UIInputArray) Less(i, j int) bool { return a[i].Cover > a[j].Cover } +func (a UIInputArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +var htmlTemplate = template.Must(template.New("").Parse(` +<!doctype html> +<html> +<head> + <title>syzkaller {{.Name}}</title> +</head> +<body> +Manager: {{.Name}} <a href='http://{{.MasterHttp}}'>[master]</a> <br> +Master corpus: {{.MasterCorpusSize}} <br> +Corpus: {{.CorpusSize}}<br> +<a href='/cover'>Cover: {{.CoverSize}}</a> <br> +<br> +{{range $c := $.Calls}} + {{$c.Name}} <a href='/corpus?call={{$c.Name}}'>inputs:{{$c.Inputs}}</a> <a href='/cover?call={{$c.Name}}'>cover:{{$c.Cover}}</a><br> +{{end}} +</body></html> +`)) + +var corpusTemplate = template.Must(template.New("").Parse(` +<!doctype html> +<html> +<head> + <title>syzkaller corpus</title> +</head> +<body> +{{range $c := $}} + <span title="{{$c.Full}}">{{$c.Short}}</span> <a href='/cover?call={{$c.N}}'>cover:{{$c.Cover}}</a> <br> +{{end}} +</body></html> +`)) diff --git a/manager/main.go b/manager/main.go new file mode 100644 index 000000000..f83338918 --- /dev/null +++ b/manager/main.go @@ -0,0 +1,139 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package main + +import ( + "encoding/json" + "flag" + "io/ioutil" + "log" + + "github.com/google/syzkaller/sys" + "github.com/google/syzkaller/vm" + _ "github.com/google/syzkaller/vm/local" + _ "github.com/google/syzkaller/vm/qemu" +) + +var ( + flagConfig = flag.String("config", "", "configuration file") + flagV = flag.Int("v", 0, "verbosity") +) + +type Config struct { + Name string + Http string + Master string + Workdir string + Vmlinux string + Type string + Count int + Port int + Nocover bool + Params map[string]interface{} + Enable_Syscalls []string + Disable_Syscalls []string +} + +func main() { + flag.Parse() + cfg, syscalls := parseConfig() + var instances []vm.Instance + for i := 0; i < cfg.Count; i++ { + params, err := json.Marshal(cfg.Params) + if err != nil { + fatalf("failed to marshal config params: %v", err) + } + inst, err := vm.Create(cfg.Type, cfg.Workdir, syscalls, cfg.Port, i, params) + if err != nil { + fatalf("failed to create an instance: %v", err) + } + instances = append(instances, inst) + } + RunManager(cfg, syscalls, instances) +} + +func parseConfig() (*Config, map[int]bool) { + if *flagConfig == "" { + fatalf("supply config file name in -config flag") + } + data, err := ioutil.ReadFile(*flagConfig) + if err != nil { + fatalf("failed to read config file: %v", err) + } + cfg := new(Config) + if err := json.Unmarshal(data, cfg); err != nil { + fatalf("failed to parse config file: %v", err) + } + if cfg.Name == "" { + fatalf("config param name is empty") + } + if cfg.Http == "" { + fatalf("config param http is empty") + } + if cfg.Master == "" { + fatalf("config param master is empty") + } + if cfg.Workdir == "" { + fatalf("config param workdir is empty") + } + if cfg.Vmlinux == "" { + fatalf("config param vmlinux is empty") + } + if cfg.Type == "" { + fatalf("config param type is empty") + } + if cfg.Count <= 0 || cfg.Count > 1000 { + fatalf("invalid config param count: %v, want (1, 1000]", cfg.Count) + } + + var syscalls map[int]bool + if len(cfg.Enable_Syscalls) != 0 || len(cfg.Disable_Syscalls) != 0 { + syscalls = make(map[int]bool) + if len(cfg.Enable_Syscalls) != 0 { + for _, c := range cfg.Enable_Syscalls { + n := 0 + for _, call := range sys.Calls { + if call.CallName == c { + syscalls[call.ID] = true + n++ + } + } + if n == 0 { + fatalf("unknown enabled syscall: %v", c) + } + } + } else { + for _, call := range sys.Calls { + syscalls[call.ID] = true + } + } + for _, c := range cfg.Disable_Syscalls { + n := 0 + for _, call := range sys.Calls { + if call.CallName == c { + delete(syscalls, call.ID) + n++ + } + } + if n == 0 { + fatalf("unknown disabled syscall: %v", c) + } + } + // They will be generated anyway. + syscalls[sys.CallMap["mmap"].ID] = true + syscalls[sys.CallMap["clock_gettime"].ID] = true + } + + return cfg, syscalls +} + +func logf(v int, msg string, args ...interface{}) { + if *flagV >= v { + log.Printf(msg, args...) + } +} + +func fatalf(msg string, args ...interface{}) { + log.Fatalf(msg, args...) +} diff --git a/manager/manager.go b/manager/manager.go new file mode 100644 index 000000000..0c6841db0 --- /dev/null +++ b/manager/manager.go @@ -0,0 +1,238 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package main + +import ( + "crypto/sha1" + "fmt" + "net" + "net/http" + "net/rpc" + "sync" + "time" + + "github.com/google/syzkaller/cover" + "github.com/google/syzkaller/prog" + . "github.com/google/syzkaller/rpctype" + "github.com/google/syzkaller/sys" + "github.com/google/syzkaller/vm" +) + +type Sig [sha1.Size]byte + +func hash(data []byte) Sig { + return Sig(sha1.Sum(data)) +} + +type Manager struct { + cfg *Config + master *rpc.Client + masterHttp string + instances []vm.Instance + + mu sync.Mutex + masterCorpus [][]byte // mirror of master corpus + masterHashes map[Sig]struct{} // hashes of master corpus + candidates [][]byte // new untriaged inputs from master + syscalls map[int]bool + + corpus []RpcInput + corpusCover []cover.Cover + + fuzzers map[string]*Fuzzer +} + +type Fuzzer struct { + name string + input int +} + +func RunManager(cfg *Config, syscalls map[int]bool, instances []vm.Instance) { + // Connect to master. + master, err := rpc.Dial("tcp", cfg.Master) + if err != nil { + fatalf("failed to dial mastger: %v", err) + } + a := &MasterConnectArgs{cfg.Name, cfg.Http} + r := &MasterConnectRes{} + if err := master.Call("Master.Connect", a, r); err != nil { + fatalf("failed to connect to master: %v", err) + } + logf(0, "connected to master at %v", cfg.Master) + + mgr := &Manager{ + cfg: cfg, + master: master, + masterHttp: r.Http, + instances: instances, + masterHashes: make(map[Sig]struct{}), + syscalls: syscalls, + corpusCover: make([]cover.Cover, sys.CallCount), + fuzzers: make(map[string]*Fuzzer), + } + + http.HandleFunc("/", mgr.httpInfo) + http.HandleFunc("/corpus", mgr.httpCorpus) + http.HandleFunc("/cover", mgr.httpCover) + http.HandleFunc("/current_corpus", mgr.httpCurrentCorpus) + go func() { + logf(0, "serving http on http://%v", cfg.Http) + panic(http.ListenAndServe(cfg.Http, nil)) + }() + + // Create RPC server for fuzzers. + rpcAddr := fmt.Sprintf("localhost:%v", cfg.Port) + ln, err := net.Listen("tcp", rpcAddr) + if err != nil { + fatalf("failed to listen on port %v: %v", cfg.Port, err) + } + s := rpc.NewServer() + s.Register(mgr) + go s.Accept(ln) + logf(0, "serving rpc on tcp://%v", rpcAddr) + + mgr.run() +} + +func (mgr *Manager) run() { + mgr.pollMaster() + for _, inst := range mgr.instances { + go inst.Run() + } + pollTicker := time.NewTicker(10 * time.Second).C + for { + select { + case <-pollTicker: + mgr.mu.Lock() + mgr.pollMaster() + mgr.mu.Unlock() + } + } +} + +func (mgr *Manager) pollMaster() { + for { + a := &MasterPollArgs{mgr.cfg.Name} + r := &MasterPollRes{} + if err := mgr.master.Call("Master.PollInputs", a, r); err != nil { + fatalf("failed to poll master: %v", err) + } + logf(3, "polling master, got %v inputs", len(r.Inputs)) + if len(r.Inputs) == 0 { + break + } + nextProg: + for _, prg := range r.Inputs { + p, err := prog.Deserialize(prg) + if err != nil { + logf(0, "failed to deserialize master program: %v", err) + continue + } + if mgr.syscalls != nil { + for _, c := range p.Calls { + if !mgr.syscalls[c.Meta.ID] { + continue nextProg + } + } + } + sig := hash(prg) + if _, ok := mgr.masterHashes[sig]; ok { + continue + } + mgr.masterHashes[sig] = struct{}{} + mgr.masterCorpus = append(mgr.masterCorpus, prg) + mgr.candidates = append(mgr.candidates, prg) + } + } +} + +func (mgr *Manager) minimizeCorpus() { + if len(mgr.corpus) == 0 { + return + } + // First, sort corpus per call. + type Call struct { + inputs []RpcInput + cov []cover.Cover + } + calls := make(map[string]Call) + for _, inp := range mgr.corpus { + c := calls[inp.Call] + c.inputs = append(c.inputs, inp) + c.cov = append(c.cov, inp.Cover) + calls[inp.Call] = c + } + // Now minimize and build new corpus. + var newCorpus []RpcInput + for _, c := range calls { + for _, idx := range cover.Minimize(c.cov) { + newCorpus = append(newCorpus, c.inputs[idx]) + } + } + logf(1, "minimized corpus: %v -> %v", len(mgr.corpus), len(newCorpus)) + mgr.corpus = newCorpus +} + +func (mgr *Manager) Connect(a *ManagerConnectArgs, r *ManagerConnectRes) error { + logf(1, "fuzzer %v connected", a.Name) + mgr.mu.Lock() + defer mgr.mu.Unlock() + + mgr.minimizeCorpus() + mgr.fuzzers[a.Name] = &Fuzzer{ + name: a.Name, + input: 0, + } + return nil +} + +func (mgr *Manager) NewInput(a *NewManagerInputArgs, r *int) error { + logf(2, "new input from fuzzer %v", a.Name) + mgr.mu.Lock() + defer mgr.mu.Unlock() + + call := sys.CallID[a.Call] + if len(cover.Difference(a.Cover, mgr.corpusCover[call])) == 0 { + return nil + } + mgr.corpusCover[call] = cover.Union(mgr.corpusCover[call], a.Cover) + mgr.corpus = append(mgr.corpus, a.RpcInput) + + sig := hash(a.Prog) + if _, ok := mgr.masterHashes[sig]; !ok { + mgr.masterHashes[sig] = struct{}{} + mgr.masterCorpus = append(mgr.masterCorpus, a.Prog) + + a1 := &NewMasterInputArgs{mgr.cfg.Name, a.Prog} + if err := mgr.master.Call("Master.NewInput", a1, nil); err != nil { + fatalf("call Master.NewInput failed: %v", err) + } + } + + return nil +} + +func (mgr *Manager) Poll(a *ManagerPollArgs, r *ManagerPollRes) error { + logf(2, "poll from %v", a.Name) + mgr.mu.Lock() + defer mgr.mu.Unlock() + + f := mgr.fuzzers[a.Name] + if f == nil { + fatalf("fuzzer %v is not connected", a.Name) + } + + for i := 0; i < 100 && f.input < len(mgr.corpus); i++ { + r.NewInputs = append(r.NewInputs, mgr.corpus[f.input]) + f.input++ + } + + for i := 0; i < 10 && len(mgr.candidates) > 0; i++ { + last := len(mgr.candidates) - 1 + r.Candidates = append(r.Candidates, mgr.candidates[last]) + mgr.candidates = mgr.candidates[:last] + } + + return nil +} diff --git a/master/html.go b/master/html.go new file mode 100644 index 000000000..bb7ac1bd7 --- /dev/null +++ b/master/html.go @@ -0,0 +1,94 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package main + +import ( + "encoding/json" + "fmt" + "html/template" + "io/ioutil" + "net/http" +) + +func (m *Master) httpInfo(w http.ResponseWriter, r *http.Request) { + m.mu.Lock() + defer m.mu.Unlock() + + data := &UIData{ + CorpusLen: len(m.corpus.m), + } + for _, mgr := range m.managers { + data.Managers = append(data.Managers, UIManager{ + Name: mgr.name, + Http: mgr.http, + }) + } + if err := htmlTemplate.Execute(w, data); err != nil { + http.Error(w, fmt.Sprintf("failed to execute template: %v", err), http.StatusInternalServerError) + } +} + +func (m *Master) httpMinimize(w http.ResponseWriter, r *http.Request) { + m.mu.Lock() + defer m.mu.Unlock() + + corpus := make(map[string]bool) + for _, mgr := range m.managers { + resp, err := http.Get("http://" + mgr.http + "/current_corpus") + if err != nil { + http.Error(w, fmt.Sprintf("failed to query corpus from %v: %v", mgr.name, err), http.StatusInternalServerError) + return + } + defer resp.Body.Close() + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + http.Error(w, fmt.Sprintf("failed to query corpus from %v: %v", mgr.name, err), http.StatusInternalServerError) + return + } + var hashes []string + err = json.Unmarshal(data, &hashes) + if err != nil || len(hashes) == 0 { + http.Error(w, fmt.Sprintf("failed to parse corpus from %v: %v", mgr.name, err), http.StatusInternalServerError) + return + } + for _, hash := range hashes { + corpus[hash] = true + } + } + orig := len(m.corpus.m) + m.corpus.minimize(corpus) + fmt.Printf("minimized: %v -> %v -> %v\n", orig, len(corpus), len(m.corpus.m)) + for _, mgr := range m.managers { + mgr.input = 0 + } +} + +type UIData struct { + CorpusLen int + Managers []UIManager +} + +type UIManager struct { + Name string + Http string +} + +var htmlTemplate = template.Must(template.New("").Parse(` +<!doctype html> +<html> +<head> + <title>syzkaller master</title> +</head> +<body> +Corpus: {{.CorpusLen}} <br> +{{if .Managers}} + Managers:<br> + {{range $mgr := $.Managers}} + <a href='http://{{$mgr.Http}}'>{{$mgr.Name}}</a><br> + {{end}} +{{else}} + No managers connected<br> +{{end}} +</body></html> +`)) diff --git a/master/master.go b/master/master.go new file mode 100644 index 000000000..c1a427732 --- /dev/null +++ b/master/master.go @@ -0,0 +1,170 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package main + +import ( + "flag" + "fmt" + "log" + "net" + "net/http" + "net/rpc" + "path/filepath" + "sync" + "time" + + "github.com/google/syzkaller/prog" + . "github.com/google/syzkaller/rpctype" +) + +var ( + flagWorkdir = flag.String("workdir", "", "dir with persistent artifacts") + flagAddr = flag.String("addr", "", "RPC listen address to connect managers") + flagHTTP = flag.String("http", "", "HTTP server listen address") + flagV = flag.Int("v", 0, "verbosity") +) + +// Master manages persistent fuzzer state (input corpus and crashers). +type Master struct { + mu sync.Mutex + managers map[string]*Manager + corpus *PersistentSet + crashers *PersistentSet + startTime time.Time + lastInput time.Time +} + +type Manager struct { + name string + http string + input int +} + +func main() { + flag.Parse() + if *flagWorkdir == "" { + fatalf("-workdir is not set") + } + if *flagAddr == "" { + fatalf("-addr is not set") + } + if *flagHTTP == "" { + fatalf("-http is not set") + } + ln, err := net.Listen("tcp", *flagAddr) + if err != nil { + fatalf("failed to listen: %v", err) + } + + m := &Master{} + m.managers = make(map[string]*Manager) + m.startTime = time.Now() + m.lastInput = time.Now() + logf(0, "loading corpus...") + m.corpus = newPersistentSet(filepath.Join(*flagWorkdir, "corpus"), func(data []byte) bool { + if _, err := prog.Deserialize(data); err != nil { + logf(0, "deleting broken program: %v\n%s", err, data) + return false + } + return true + }) + m.crashers = newPersistentSet(filepath.Join(*flagWorkdir, "crashers"), nil) + + http.HandleFunc("/", m.httpInfo) + http.HandleFunc("/minimize", m.httpMinimize) + go func() { + logf(0, "serving http on http://%v", *flagHTTP) + panic(http.ListenAndServe(*flagHTTP, nil)) + }() + + logf(0, "serving rpc on tcp://%v", *flagAddr) + s := rpc.NewServer() + s.Register(m) + go s.Accept(ln) + + m.loop() +} + +func (m *Master) loop() { + for range time.NewTicker(1 * time.Second).C { + } +} + +// Connect attaches new manager to master. +func (m *Master) Connect(a *MasterConnectArgs, r *MasterConnectRes) error { + logf(1, "connect from %v (http://%v)", a.Name, a.Http) + m.mu.Lock() + defer m.mu.Unlock() + + mgr := &Manager{ + name: a.Name, + http: a.Http, + } + m.managers[a.Name] = mgr + r.Http = *flagHTTP + return nil +} + +// NewInput saves new interesting input on master. +func (m *Master) NewInput(a *NewMasterInputArgs, r *int) error { + p, err := prog.Deserialize(a.Prog) + if err != nil { + logf(0, "bogus new input from %v: %v\n%s\n", a.Name, err, a.Prog) + return fmt.Errorf("the program is bogus: %v", err) + } + m.mu.Lock() + defer m.mu.Unlock() + + if !m.corpus.add(a.Prog) { + return nil + } + m.lastInput = time.Now() + logf(1, "new input from %v: %s", a.Name, p) + return nil +} + +type NewCrasherArgs struct { + Name string + Text []byte + Suppression []byte + Prog []byte +} + +// NewCrasher saves new crasher input on master. +func (m *Master) NewCrasher(a *NewCrasherArgs, r *int) error { + logf(0, "new crasher from %v", a.Name) + m.mu.Lock() + defer m.mu.Unlock() + + if !m.crashers.add(a.Text) { + return nil // Already have this. + } + return nil +} + +func (m *Master) PollInputs(a *MasterPollArgs, r *MasterPollRes) error { + logf(2, "poll from %v", a.Name) + m.mu.Lock() + defer m.mu.Unlock() + + mgr := m.managers[a.Name] + if mgr == nil { + return fmt.Errorf("manager is not connected") + } + for i := 0; i < 100 && mgr.input < len(m.corpus.a); i++ { + r.Inputs = append(r.Inputs, m.corpus.a[mgr.input]) + mgr.input++ + } + return nil +} + +func logf(v int, msg string, args ...interface{}) { + if *flagV >= v { + log.Printf(msg, args...) + } +} + +func fatalf(msg string, args ...interface{}) { + log.Fatalf(msg, args...) +} diff --git a/master/persistent.go b/master/persistent.go new file mode 100644 index 000000000..12f4bbdc8 --- /dev/null +++ b/master/persistent.go @@ -0,0 +1,129 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package main + +import ( + "crypto/sha1" + "encoding/hex" + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" +) + +type Sig [sha1.Size]byte + +// PersistentSet is a set of binary blobs with a persistent mirror on disk. +type PersistentSet struct { + dir string + m map[Sig][]byte + a [][]byte +} + +func hash(data []byte) Sig { + return Sig(sha1.Sum(data)) +} + +func newPersistentSet(dir string, verify func(data []byte) bool) *PersistentSet { + ps := &PersistentSet{ + dir: dir, + m: make(map[Sig][]byte), + } + os.MkdirAll(dir, 0770) + filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if err != nil { + log.Fatalf("error during dir walk: %v\n", err) + } + if info.IsDir() { + return nil + } + data, err := ioutil.ReadFile(path) + if err != nil { + log.Fatalf("error during file read: %v\n", err) + return nil + } + sig := hash(data) + if _, ok := ps.m[sig]; ok { + return nil + } + name := info.Name() + if len(data) == 0 { + // This can happen is master runs on machine-under-test, + // and it has crashed midway. + log.Printf("removing empty file %v", name) + os.Remove(path) + return nil + } + const hexLen = 2 * sha1.Size + if len(name) > hexLen+1 && isHexString(name[:hexLen]) && name[hexLen] == '.' { + return nil // description file + } + if len(name) != hexLen || !isHexString(name) { + log.Fatalf("unknown file in persistent dir %v: %v", dir, name) + } + if verify != nil && !verify(data) { + os.Remove(path) + return nil + } + if name != hex.EncodeToString(sig[:]) { + log.Printf("bad hash in persistent dir %v for file %v, expect %v", dir, name, hex.EncodeToString(sig[:])) + if err := ioutil.WriteFile(filepath.Join(ps.dir, hex.EncodeToString(sig[:])), data, 0660); err != nil { + log.Fatalf("failed to write file: %v", err) + } + os.Remove(path) + } + ps.m[sig] = data + ps.a = append(ps.a, data) + return nil + }) + return ps +} + +func isHexString(s string) bool { + for _, v := range []byte(s) { + if v >= '0' && v <= '9' || v >= 'a' && v <= 'f' { + continue + } + return false + } + return true +} + +func (ps *PersistentSet) add(data []byte) bool { + sig := hash(data) + if _, ok := ps.m[sig]; ok { + return false + } + data = append([]byte{}, data...) + ps.m[sig] = data + ps.a = append(ps.a, data) + fname := filepath.Join(ps.dir, hex.EncodeToString(sig[:])) + if err := ioutil.WriteFile(fname, data, 0660); err != nil { + log.Fatalf("failed to write file: %v", err) + } + return true +} + +// addDescription creates a complementary to data file on disk. +func (ps *PersistentSet) addDescription(data []byte, desc []byte, typ string) { + sig := hash(data) + fname := filepath.Join(ps.dir, fmt.Sprintf("%v.%v", hex.EncodeToString(sig[:]), typ)) + if err := ioutil.WriteFile(fname, desc, 0660); err != nil { + log.Fatalf("failed to write file: %v", err) + } +} + +func (ps *PersistentSet) minimize(set map[string]bool) { + ps.a = nil + for sig, data := range ps.m { + s := hex.EncodeToString(sig[:]) + if set[s] { + ps.a = append(ps.a, data) + } else { + delete(ps.m, sig) + os.Remove(filepath.Join(ps.dir, s)) + } + } +} diff --git a/prog/analysis.go b/prog/analysis.go new file mode 100644 index 000000000..9a19d8264 --- /dev/null +++ b/prog/analysis.go @@ -0,0 +1,245 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// Conservative resource-related analysis of programs. +// The analysis figures out what files descriptors are [potentially] opened +// at a particular point in program, what pages are [potentially] mapped, +// what files were already referenced in calls, etc. + +package prog + +import ( + "fmt" + + "github.com/google/syzkaller/sys" +) + +const ( + maxPages = 4 << 10 +) + +type state struct { + enabledCalls []*sys.Call + files map[string]bool + resources map[sys.ResourceKind]map[sys.ResourceSubkind][]*Arg + strings map[string]bool + pages [maxPages]bool +} + +// analyze analyzes the program p up to but not including call c. +func analyze(enabledCalls []*sys.Call, p *Prog, c *Call) *state { + s := newState(enabledCalls) + for _, c1 := range p.Calls { + if c1 == c { + break + } + s.analyze(c1) + } + return s +} + +func newState(enabledCalls []*sys.Call) *state { + s := &state{ + enabledCalls: enabledCalls, + files: make(map[string]bool), + resources: make(map[sys.ResourceKind]map[sys.ResourceSubkind][]*Arg), + strings: make(map[string]bool), + } + if len(s.enabledCalls) == 0 { + s.enabledCalls = sys.Calls + } + return s +} + +func (s *state) analyze(c *Call) { + foreachArgArray(&c.Args, c.Ret, func(arg, base *Arg, _ *[]*Arg) { + switch typ := arg.Type.(type) { + case sys.FilenameType: + if arg.Kind == ArgData && arg.Dir != DirOut { + s.files[string(arg.Data)] = true + } + case sys.ResourceType: + if arg.Dir != DirIn { + if s.resources[typ.Kind] == nil { + s.resources[typ.Kind] = make(map[sys.ResourceSubkind][]*Arg) + } + s.resources[typ.Kind][typ.Subkind] = append(s.resources[typ.Kind][typ.Subkind], arg) + } + case sys.BufferType: + if typ.Kind == sys.BufferString && arg.Kind == ArgData && len(arg.Data) != 0 { + s.strings[string(arg.Data)] = true + } + } + }) + switch c.Meta.Name { + case "mmap": + // Filter out only very wrong arguments. + length := c.Args[1] + if length.AddrPage == 0 && length.AddrOffset == 0 { + break + } + if flags, fd := c.Args[4], c.Args[3]; flags.Val&MAP_ANONYMOUS == 0 && fd.Kind == ArgConst && fd.Val == sys.InvalidFD { + break + } + s.addressable(c.Args[0], length, true) + case "munmap": + s.addressable(c.Args[0], c.Args[1], false) + case "mremap": + s.addressable(c.Args[4], c.Args[2], true) + } +} + +func (s *state) addressable(addr, size *Arg, ok bool) { + if addr.Kind != ArgPointer || size.Kind != ArgPageSize { + panic("mmap/munmap/mremap args are not pages") + } + n := size.AddrPage + if size.AddrOffset != 0 { + n++ + } + if addr.AddrPage+n > uintptr(len(s.pages)) { + panic(fmt.Sprintf("address is out of bounds: page=%v len=%v (%v, %v) bound=%v", addr.AddrPage, n, size.AddrPage, size.AddrOffset, len(s.pages))) + } + for i := uintptr(0); i < n; i++ { + s.pages[addr.AddrPage+i] = ok + } +} + +func foreachArgArray(args *[]*Arg, ret *Arg, f func(arg, base *Arg, parent *[]*Arg)) { + var rec func(arg, base *Arg, parent *[]*Arg) + rec = func(arg, base *Arg, parent *[]*Arg) { + f(arg, base, parent) + for _, arg1 := range arg.Inner { + parent1 := parent + if _, ok := arg.Type.(sys.StructType); ok { + parent1 = &arg.Inner + } + rec(arg1, base, parent1) + } + if arg.Kind == ArgPointer && arg.Res != nil { + rec(arg.Res, arg, parent) + } + } + for _, arg := range *args { + rec(arg, nil, args) + } + if ret != nil { + rec(ret, nil, nil) + } +} + +func foreachArg(c *Call, f func(arg, base *Arg, parent *[]*Arg)) { + foreachArgArray(&c.Args, nil, f) +} + +func referencedArgs(args []*Arg, ret *Arg) (res []*Arg) { + f := func(arg, _ *Arg, _ *[]*Arg) { + for arg1 := range arg.Uses { + if arg1.Kind != ArgResult { + panic("use references not ArgResult") + } + res = append(res, arg1) + } + } + foreachArgArray(&args, ret, f) + return +} + +func assignTypeAndDir(c *Call) { + var rec func(arg *Arg, typ sys.Type, dir ArgDir) + rec = func(arg *Arg, typ sys.Type, dir ArgDir) { + if arg.Call != nil && arg.Call != c { + panic(fmt.Sprintf("different call is already assigned: %p %p %v %v", arg.Call, c, arg.Call.Meta.Name, c.Meta.Name)) + } + arg.Call = c + if arg.Type != nil && arg.Type.Name() != typ.Name() { + panic("different type is already assigned") + } + arg.Type = typ + switch arg.Kind { + case ArgPointer: + arg.Dir = DirIn + switch typ1 := typ.(type) { + case sys.FilenameType: + rec(arg.Res, typ, dir) + case sys.PtrType: + if arg.Res != nil { + rec(arg.Res, typ1.Type, ArgDir(typ1.Dir)) + } + } + case ArgGroup: + arg.Dir = dir + switch typ1 := typ.(type) { + case sys.StructType: + for i, arg1 := range arg.Inner { + rec(arg1, typ1.Fields[i], dir) + } + case sys.ArrayType: + for _, arg1 := range arg.Inner { + rec(arg1, typ1.Type, dir) + } + } + default: + arg.Dir = dir + } + } + for i, arg := range c.Args { + rec(arg, c.Meta.Args[i], DirIn) + } + if c.Ret == nil { + c.Ret = returnArg() + c.Ret.Call = c + c.Ret.Type = c.Meta.Ret + c.Ret.Dir = DirOut + } +} + +func sanitizeCall(c *Call) { + switch c.Meta.Name { + case "mmap": + // Add MAP_FIXED flag, otherwise it produces non-deterministic results. + addr := c.Args[0] + if addr.Kind != ArgPointer { + panic("mmap address is not ArgPointer") + } + length := c.Args[1] + if length.Kind != ArgPageSize { + panic("mmap length is not ArgPageSize") + } + flags := c.Args[3] + if flags.Kind != ArgConst { + panic("mmap flag arg is not const") + } + flags.Val |= MAP_FIXED + case "mremap": + // Add MREMAP_FIXED flag, otherwise it produces non-deterministic results. + flags := c.Args[3] + if flags.Kind != ArgConst { + panic("mremap flag arg is not const") + } + if flags.Val&MREMAP_MAYMOVE != 0 { + flags.Val |= MREMAP_FIXED + } + case "mknod": + mode := c.Args[1] + if mode.Kind != ArgConst { + panic("mknod mode is not const") + } + // Char and block devices read/write io ports, kernel memory and do other nasty things. + if mode.Val != S_IFREG && mode.Val != S_IFIFO && mode.Val != S_IFSOCK { + mode.Val = S_IFIFO + } + case "syslog": + cmd := c.Args[0] + // These disable console output, but we need it. + if cmd.Val == SYSLOG_ACTION_CONSOLE_OFF || cmd.Val == SYSLOG_ACTION_CONSOLE_ON { + cmd.Val = SYSLOG_ACTION_SIZE_UNREAD + } + case "exit", "exit_group": + code := c.Args[0] + // These codes are reserved by executor. + if code.Val%128 == 67 || code.Val%128 == 68 { + code.Val = 1 + } + } +} diff --git a/prog/clone.go b/prog/clone.go new file mode 100644 index 000000000..dd8e6e4db --- /dev/null +++ b/prog/clone.go @@ -0,0 +1,49 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package prog + +func (p *Prog) Clone() *Prog { + p1 := new(Prog) + newargs := make(map[*Arg]*Arg) + for _, c := range p.Calls { + c1 := new(Call) + c1.Meta = c.Meta + c1.Ret = c.Ret.clone(c1, newargs) + for _, arg := range c.Args { + c1.Args = append(c1.Args, arg.clone(c1, newargs)) + } + p1.Calls = append(p1.Calls, c1) + } + if err := p1.validate(); err != nil { + panic(err) + } + return p1 +} + +func (arg *Arg) clone(c *Call, newargs map[*Arg]*Arg) *Arg { + arg1 := new(Arg) + *arg1 = *arg + arg1.Call = c + arg1.Data = append([]byte{}, arg.Data...) + switch arg.Kind { + case ArgPointer: + if arg.Res != nil { + arg1.Res = arg.Res.clone(c, newargs) + } + case ArgResult: + r := newargs[arg.Res] + arg1.Res = r + if r.Uses == nil { + r.Uses = make(map[*Arg]bool) + } + r.Uses[arg1] = true + } + arg1.Inner = nil + for _, arg2 := range arg.Inner { + arg1.Inner = append(arg1.Inner, arg2.clone(c, newargs)) + } + arg1.Uses = nil // filled when we clone the referent + newargs[arg] = arg1 + return arg1 +} diff --git a/prog/consts.go b/prog/consts.go new file mode 100644 index 000000000..a83952d0e --- /dev/null +++ b/prog/consts.go @@ -0,0 +1,598 @@ +// AUTOGENERATED FILE +package prog + +const ( + ADDR_COMPAT_LAYOUT = 2097152 + ADDR_LIMIT_32BIT = 8388608 + ADDR_LIMIT_3GB = 134217728 + ADDR_NO_RANDOMIZE = 262144 + AF_APPLETALK = 5 + AF_ATMPVC = 8 + AF_AX25 = 3 + AF_INET = 2 + AF_INET6 = 10 + AF_IPX = 4 + AF_LOCAL = 1 + AF_NETLINK = 16 + AF_PACKET = 17 + AF_X25 = 9 + ARCH_GET_FS = 4099 + ARCH_GET_GS = 4100 + ARCH_SET_FS = 4098 + ARCH_SET_GS = 4097 + AT_EACCESS = 512 + AT_EMPTY_PATH = 4096 + AT_FDCWD = 18446744073709551516 + AT_REMOVEDIR = 512 + AT_SYMLINK_FOLLOW = 1024 + AT_SYMLINK_NOFOLLOW = 256 + CLOCK_BOOTTIME = 7 + CLOCK_MONOTONIC = 1 + CLOCK_MONOTONIC_COARSE = 6 + CLOCK_MONOTONIC_RAW = 4 + CLOCK_PROCESS_CPUTIME_ID = 2 + CLOCK_REALTIME = 0 + CLOCK_REALTIME_COARSE = 5 + CLOCK_THREAD_CPUTIME_ID = 3 + CLONE_CHILD_CLEARTID = 2097152 + CLONE_CHILD_SETTID = 16777216 + CLONE_FILES = 1024 + CLONE_FS = 512 + CLONE_IO = 2147483648 + CLONE_NEWIPC = 134217728 + CLONE_NEWNET = 1073741824 + CLONE_NEWNS = 131072 + CLONE_NEWPID = 536870912 + CLONE_NEWUTS = 67108864 + CLONE_PARENT = 32768 + CLONE_PARENT_SETTID = 1048576 + CLONE_PTRACE = 8192 + CLONE_SETTLS = 524288 + CLONE_SIGHAND = 2048 + CLONE_SYSVSEM = 262144 + CLONE_THREAD = 65536 + CLONE_UNTRACED = 8388608 + CLONE_VFORK = 16384 + CLONE_VM = 256 + DN_ACCESS = 1 + DN_ATTRIB = 32 + DN_CREATE = 4 + DN_DELETE = 8 + DN_MODIFY = 2 + DN_MULTISHOT = 2147483648 + DN_RENAME = 16 + EFD_CLOEXEC = 524288 + EFD_NONBLOCK = 2048 + EFD_SEMAPHORE = 1 + EPOLLERR = 8 + EPOLLET = 2147483648 + EPOLLHUP = 16 + EPOLLIN = 1 + EPOLLONESHOT = 1073741824 + EPOLLOUT = 4 + EPOLLPRI = 2 + EPOLLRDHUP = 8192 + EPOLL_CLOEXEC = 524288 + EPOLL_CTL_ADD = 1 + EPOLL_CTL_DEL = 2 + EPOLL_CTL_MOD = 3 + FALLOC_FL_KEEP_SIZE = 1 + FALLOC_FL_PUNCH_HOLE = 2 + FAN_ACCESS = 1 + FAN_ACCESS_PERM = 131072 + FAN_CLASS_CONTENT = 4 + FAN_CLASS_NOTIF = 0 + FAN_CLASS_PRE_CONTENT = 8 + FAN_CLOEXEC = 1 + FAN_CLOSE_NOWRITE = 16 + FAN_CLOSE_WRITE = 8 + FAN_EVENT_ON_CHILD = 134217728 + FAN_MARK_ADD = 1 + FAN_MARK_DONT_FOLLOW = 4 + FAN_MARK_FLUSH = 128 + FAN_MARK_IGNORED_MASK = 32 + FAN_MARK_IGNORED_SURV_MODIFY = 64 + FAN_MARK_MOUNT = 16 + FAN_MARK_ONLYDIR = 8 + FAN_MARK_REMOVE = 2 + FAN_MODIFY = 2 + FAN_NONBLOCK = 2 + FAN_ONDIR = 1073741824 + FAN_OPEN = 32 + FAN_OPEN_PERM = 65536 + FAN_UNLIMITED_MARKS = 32 + FAN_UNLIMITED_QUEUE = 16 + FD_CLOEXEC = 1 + FUTEX_CMP_REQUEUE = 4 + FUTEX_REQUEUE = 3 + FUTEX_WAIT = 0 + FUTEX_WAIT_BITSET = 9 + FUTEX_WAKE = 1 + F_DUPFD = 0 + F_DUPFD_CLOEXEC = 1030 + F_GETFD = 1 + F_GETFL = 3 + F_GETLEASE = 1025 + F_GETLK = 5 + F_GETOWN = 9 + F_GETOWN_EX = 16 + F_GETPIPE_SZ = 1032 + F_GETSIG = 11 + F_NOTIFY = 1026 + F_OWNER_PGRP = 2 + F_OWNER_PID = 1 + F_OWNER_TID = 0 + F_RDLCK = 0 + F_SETFD = 2 + F_SETFL = 4 + F_SETLEASE = 1024 + F_SETLK = 6 + F_SETLKW = 7 + F_SETOWN = 8 + F_SETOWN_EX = 15 + F_SETPIPE_SZ = 1031 + F_SETSIG = 10 + F_UNLCK = 2 + F_WRLCK = 1 + GETALL = 13 + GETNCNT = 14 + GETPID = 11 + GETVAL = 12 + GETZCNT = 15 + IN_ACCESS = 1 + IN_ATTRIB = 4 + IN_CLOEXEC = 524288 + IN_CLOSE_NOWRITE = 16 + IN_CLOSE_WRITE = 8 + IN_CREATE = 256 + IN_DELETE = 512 + IN_DELETE_SELF = 1024 + IN_DONT_FOLLOW = 33554432 + IN_EXCL_UNLINK = 67108864 + IN_MASK_ADD = 536870912 + IN_MODIFY = 2 + IN_MOVED_FROM = 64 + IN_MOVED_TO = 128 + IN_MOVE_SELF = 2048 + IN_NONBLOCK = 2048 + IN_ONESHOT = 2147483648 + IN_ONLYDIR = 16777216 + IN_OPEN = 32 + IOCB_CMD_FDSYNC = 3 + IOCB_CMD_FSYNC = 2 + IOCB_CMD_NOOP = 6 + IOCB_CMD_POLL = 5 + IOCB_CMD_PREAD = 0 + IOCB_CMD_PREADV = 7 + IOCB_CMD_PREADX = 4 + IOCB_CMD_PWRITE = 1 + IOCB_CMD_PWRITEV = 8 + IOCB_FLAG_RESFD = 1 + IOPRIO_WHO_PGRP = 2 + IOPRIO_WHO_PROCESS = 1 + IOPRIO_WHO_USER = 3 + IPC_CREAT = 512 + IPC_EXCL = 1024 + IPC_INFO = 3 + IPC_NOWAIT = 2048 + IPC_RMID = 0 + IPC_SET = 1 + IPC_STAT = 2 + ITIMER_PROF = 2 + ITIMER_REAL = 0 + ITIMER_VIRTUAL = 1 + KCMP_FILE = 0 + KCMP_FILES = 2 + KCMP_FS = 3 + KCMP_IO = 5 + KCMP_SIGHAND = 4 + KCMP_SYSVSEM = 6 + KCMP_VM = 1 + KEXEC_ARCH_386 = 196608 + KEXEC_ARCH_ARM = 2621440 + KEXEC_ARCH_IA_64 = 3276800 + KEXEC_ARCH_MIPS = 524288 + KEXEC_ARCH_MIPS_LE = 655360 + KEXEC_ARCH_PPC = 1310720 + KEXEC_ARCH_PPC64 = 1376256 + KEXEC_ARCH_S390 = 1441792 + KEXEC_ARCH_SH = 2752512 + KEXEC_ARCH_X86_64 = 4063232 + KEXEC_ON_CRASH = 1 + KEXEC_PRESERVE_CONTEXT = 2 + KEYCTL_ASSUME_AUTHORITY = 16 + KEYCTL_CHOWN = 4 + KEYCTL_CLEAR = 7 + KEYCTL_DESCRIBE = 6 + KEYCTL_GET_KEYRING_ID = 0 + KEYCTL_GET_PERSISTENT = 22 + KEYCTL_GET_SECURITY = 17 + KEYCTL_INSTANTIATE = 12 + KEYCTL_INSTANTIATE_IOV = 20 + KEYCTL_INVALIDATE = 21 + KEYCTL_JOIN_SESSION_KEYRING = 1 + KEYCTL_LINK = 8 + KEYCTL_NEGATE = 13 + KEYCTL_READ = 11 + KEYCTL_REJECT = 19 + KEYCTL_REVOKE = 3 + KEYCTL_SEARCH = 10 + KEYCTL_SESSION_TO_PARENT = 18 + KEYCTL_SETPERM = 5 + KEYCTL_SET_REQKEY_KEYRING = 14 + KEYCTL_SET_TIMEOUT = 15 + KEYCTL_UNLINK = 9 + KEYCTL_UPDATE = 2 + KEY_REQKEY_DEFL_DEFAULT = 0 + KEY_REQKEY_DEFL_GROUP_KEYRING = 6 + KEY_REQKEY_DEFL_NO_CHANGE = 18446744073709551615 + KEY_REQKEY_DEFL_PROCESS_KEYRING = 2 + KEY_REQKEY_DEFL_REQUESTOR_KEYRING = 7 + KEY_REQKEY_DEFL_SESSION_KEYRING = 3 + KEY_REQKEY_DEFL_THREAD_KEYRING = 1 + KEY_REQKEY_DEFL_USER_KEYRING = 4 + KEY_REQKEY_DEFL_USER_SESSION_KEYRING = 5 + KEY_SPEC_GROUP_KEYRING = 18446744073709551610 + KEY_SPEC_PROCESS_KEYRING = 18446744073709551614 + KEY_SPEC_REQKEY_AUTH_KEY = 18446744073709551609 + KEY_SPEC_REQUESTOR_KEYRING = 18446744073709551608 + KEY_SPEC_SESSION_KEYRING = 18446744073709551613 + KEY_SPEC_THREAD_KEYRING = 18446744073709551615 + KEY_SPEC_USER_KEYRING = 18446744073709551612 + KEY_SPEC_USER_SESSION_KEYRING = 18446744073709551611 + LOCK_EX = 2 + LOCK_NB = 4 + LOCK_SH = 1 + LOCK_UN = 8 + MADV_DODUMP = 17 + MADV_DOFORK = 11 + MADV_DONTDUMP = 16 + MADV_DONTFORK = 10 + MADV_DONTNEED = 4 + MADV_HUGEPAGE = 14 + MADV_HWPOISON = 100 + MADV_MERGEABLE = 12 + MADV_NOHUGEPAGE = 15 + MADV_NORMAL = 0 + MADV_RANDOM = 1 + MADV_REMOVE = 9 + MADV_SEQUENTIAL = 2 + MADV_SOFT_OFFLINE = 101 + MADV_UNMERGEABLE = 13 + MADV_WILLNEED = 3 + MAP_32BIT = 64 + MAP_ANONYMOUS = 32 + MAP_DENYWRITE = 2048 + MAP_EXECUTABLE = 4096 + MAP_FILE = 0 + MAP_FIXED = 16 + MAP_GROWSDOWN = 256 + MAP_HUGETLB = 262144 + MAP_LOCKED = 8192 + MAP_NONBLOCK = 65536 + MAP_NORESERVE = 16384 + MAP_POPULATE = 32768 + MAP_PRIVATE = 2 + MAP_SHARED = 1 + MAP_STACK = 131072 + MAP_UNINITIALIZED = 67108864 + MCL_CURRENT = 1 + MCL_FUTURE = 2 + MMAP_PAGE_ZERO = 1048576 + MNT_DETACH = 2 + MNT_EXPIRE = 4 + MNT_FORCE = 1 + MODULE_INIT_IGNORE_MODVERSIONS = 1 + MODULE_INIT_IGNORE_VERMAGIC = 2 + MPOL_BIND = 2 + MPOL_DEFAULT = 0 + MPOL_F_ADDR = 2 + MPOL_F_MEMS_ALLOWED = 4 + MPOL_F_NODE = 1 + MPOL_F_RELATIVE_NODES = 16384 + MPOL_F_STATIC_NODES = 32768 + MPOL_INTERLEAVE = 3 + MPOL_MF_MOVE = 2 + MPOL_MF_MOVE_ALL = 4 + MPOL_MF_STRICT = 1 + MPOL_PREFERRED = 1 + MREMAP_FIXED = 2 + MREMAP_MAYMOVE = 1 + MSG_CMSG_CLOEXEC = 1073741824 + MSG_CONFIRM = 2048 + MSG_DONTROUTE = 4 + MSG_DONTWAIT = 64 + MSG_EOR = 128 + MSG_ERRQUEUE = 8192 + MSG_EXCEPT = 8192 + MSG_INFO = 12 + MSG_MORE = 32768 + MSG_NOERROR = 4096 + MSG_NOSIGNAL = 16384 + MSG_OOB = 1 + MSG_PEEK = 2 + MSG_STAT = 11 + MSG_TRUNC = 32 + MSG_WAITALL = 256 + MSG_WAITFORONE = 65536 + MS_ASYNC = 1 + MS_BIND = 4096 + MS_DIRSYNC = 128 + MS_INVALIDATE = 2 + MS_MANDLOCK = 64 + MS_MOVE = 8192 + MS_NOATIME = 1024 + MS_NODEV = 4 + MS_NODIRATIME = 2048 + MS_NOEXEC = 8 + MS_NOSUID = 2 + MS_RDONLY = 1 + MS_RELATIME = 2097152 + MS_REMOUNT = 32 + MS_SILENT = 32768 + MS_STRICTATIME = 16777216 + MS_SYNC = 4 + MS_SYNCHRONOUS = 16 + NT_386_IOPERM = 513 + NT_386_TLS = 512 + NT_AUXV = 6 + NT_PRFPREG = 2 + NT_PRPSINFO = 3 + NT_PRSTATUS = 1 + NT_TASKSTRUCT = 4 + NT_X86_XSTATE = 514 + O_APPEND = 1024 + O_ASYNC = 8192 + O_CLOEXEC = 524288 + O_CREAT = 64 + O_DIRECT = 16384 + O_DIRECTORY = 65536 + O_DSYNC = 4096 + O_EXCL = 128 + O_LARGEFILE = 0 + O_NOATIME = 262144 + O_NOCTTY = 256 + O_NOFOLLOW = 131072 + O_NONBLOCK = 2048 + O_PATH = 2097152 + O_RDONLY = 0 + O_RDWR = 2 + O_SYNC = 1052672 + O_TRUNC = 512 + O_WRONLY = 1 + POSIX_FADV_DONTNEED = 4 + POSIX_FADV_NOREUSE = 5 + POSIX_FADV_NORMAL = 0 + POSIX_FADV_RANDOM = 1 + POSIX_FADV_SEQUENTIAL = 2 + POSIX_FADV_WILLNEED = 3 + PRIO_PGRP = 1 + PRIO_PROCESS = 0 + PRIO_USER = 2 + PROT_EXEC = 4 + PROT_READ = 1 + PROT_WRITE = 2 + PR_CAPBSET_DROP = 24 + PR_CAPBSET_READ = 23 + PR_GET_CHILD_SUBREAPER = 37 + PR_GET_DUMPABLE = 3 + PR_GET_ENDIAN = 19 + PR_GET_FPEMU = 9 + PR_GET_FPEXC = 11 + PR_GET_KEEPCAPS = 7 + PR_GET_NAME = 16 + PR_GET_NO_NEW_PRIVS = 39 + PR_GET_PDEATHSIG = 2 + PR_GET_SECCOMP = 21 + PR_GET_SECUREBITS = 27 + PR_GET_TID_ADDRESS = 40 + PR_GET_TIMERSLACK = 30 + PR_GET_TIMING = 13 + PR_GET_TSC = 25 + PR_GET_UNALIGN = 5 + PR_MCE_KILL = 33 + PR_MCE_KILL_GET = 34 + PR_SET_CHILD_SUBREAPER = 36 + PR_SET_DUMPABLE = 4 + PR_SET_ENDIAN = 20 + PR_SET_FPEMU = 10 + PR_SET_FPEXC = 12 + PR_SET_KEEPCAPS = 8 + PR_SET_MM = 35 + PR_SET_NAME = 15 + PR_SET_NO_NEW_PRIVS = 38 + PR_SET_PDEATHSIG = 1 + PR_SET_PTRACER = 1499557217 + PR_SET_SECCOMP = 22 + PR_SET_SECUREBITS = 28 + PR_SET_TIMERSLACK = 29 + PR_SET_TIMING = 14 + PR_SET_TSC = 26 + PR_SET_UNALIGN = 6 + PR_TASK_PERF_EVENTS_DISABLE = 31 + PR_TASK_PERF_EVENTS_ENABLE = 32 + PTRACE_ATTACH = 16 + PTRACE_CONT = 7 + PTRACE_DETACH = 17 + PTRACE_GETEVENTMSG = 16897 + PTRACE_GETFPREGS = 14 + PTRACE_GETREGS = 12 + PTRACE_GETREGSET = 16900 + PTRACE_GETSIGINFO = 16898 + PTRACE_INTERRUPT = 16903 + PTRACE_KILL = 8 + PTRACE_LISTEN = 16904 + PTRACE_O_EXITKILL = 1048576 + PTRACE_O_TRACECLONE = 8 + PTRACE_O_TRACEEXEC = 16 + PTRACE_O_TRACEEXIT = 64 + PTRACE_O_TRACEFORK = 2 + PTRACE_O_TRACESYSGOOD = 1 + PTRACE_O_TRACEVFORK = 4 + PTRACE_O_TRACEVFORKDONE = 32 + PTRACE_PEEKDATA = 2 + PTRACE_PEEKTEXT = 1 + PTRACE_PEEKUSER = 3 + PTRACE_POKEDATA = 5 + PTRACE_POKETEXT = 4 + PTRACE_POKEUSER = 6 + PTRACE_SEIZE = 16902 + PTRACE_SETFPREGS = 15 + PTRACE_SETOPTIONS = 16896 + PTRACE_SETREGS = 13 + PTRACE_SETREGSET = 16901 + PTRACE_SETSIGINFO = 16899 + PTRACE_SINGLESTEP = 9 + PTRACE_SYSCALL = 24 + PTRACE_SYSEMU = 31 + PTRACE_SYSEMU_SINGLESTEP = 32 + PTRACE_TRACEME = 0 + P_ALL = 0 + P_PGID = 2 + P_PID = 1 + READ_IMPLIES_EXEC = 4194304 + RENAME_EXCHANGE = 2 + RENAME_NOREPLACE = 1 + RENAME_WHITEOUT = 4 + RLIMIT_AS = 9 + RLIMIT_CORE = 4 + RLIMIT_CPU = 0 + RLIMIT_DATA = 2 + RLIMIT_FSIZE = 1 + RLIMIT_LOCKS = 10 + RLIMIT_MEMLOCK = 8 + RLIMIT_MSGQUEUE = 12 + RLIMIT_NICE = 13 + RLIMIT_NOFILE = 7 + RLIMIT_NPROC = 6 + RLIMIT_RSS = 5 + RLIMIT_RTPRIO = 14 + RLIMIT_RTTIME = 15 + RLIMIT_SIGPENDING = 11 + RLIMIT_STACK = 3 + RUSAGE_CHILDREN = 18446744073709551615 + RUSAGE_SELF = 0 + RUSAGE_THREAD = 1 + SA_NOCLDSTOP = 1 + SA_NOCLDWAIT = 2 + SA_NODEFER = 1073741824 + SA_ONSTACK = 134217728 + SA_RESETHAND = 2147483648 + SA_RESTART = 268435456 + SA_SIGINFO = 4 + SCHED_BATCH = 3 + SCHED_DEADLINE = 6 + SCHED_FIFO = 1 + SCHED_FLAG_RESET_ON_FORK = 1 + SCHED_IDLE = 5 + SCHED_OTHER = 0 + SCHED_RR = 2 + SECCOMP_FILTER_FLAG_TSYNC = 1 + SECCOMP_SET_MODE_FILTER = 1 + SECCOMP_SET_MODE_STRICT = 0 + SEEK_CUR = 1 + SEEK_DATA = 3 + SEEK_END = 2 + SEEK_HOLE = 4 + SEEK_SET = 0 + SEM_INFO = 19 + SEM_STAT = 18 + SEM_UNDO = 4096 + SETALL = 17 + SETVAL = 16 + SFD_CLOEXEC = 524288 + SFD_NONBLOCK = 2048 + SHM_HUGETLB = 2048 + SHM_INFO = 14 + SHM_LOCK = 11 + SHM_NORESERVE = 4096 + SHM_RDONLY = 4096 + SHM_REMAP = 16384 + SHM_RND = 8192 + SHM_STAT = 13 + SHM_UNLOCK = 12 + SHORT_INODE = 16777216 + SHUT_RD = 0 + SHUT_WR = 1 + SIGEV_NONE = 1 + SIGEV_SIGNAL = 0 + SIGEV_THREAD = 2 + SIG_BLOCK = 0 + SIG_SETMASK = 2 + SIG_UNBLOCK = 1 + SOCK_CLOEXEC = 524288 + SOCK_DGRAM = 2 + SOCK_NONBLOCK = 2048 + SOCK_PACKET = 10 + SOCK_RAW = 3 + SOCK_RDM = 4 + SOCK_SEQPACKET = 5 + SOCK_STREAM = 1 + SPLICE_F_GIFT = 8 + SPLICE_F_MORE = 4 + SPLICE_F_MOVE = 1 + SPLICE_F_NONBLOCK = 2 + STICKY_TIMEOUTS = 67108864 + SYNC_FILE_RANGE_WAIT_AFTER = 4 + SYNC_FILE_RANGE_WAIT_BEFORE = 1 + SYNC_FILE_RANGE_WRITE = 2 + SYSLOG_ACTION_CLEAR = 5 + SYSLOG_ACTION_CLOSE = 0 + SYSLOG_ACTION_CONSOLE_LEVEL = 8 + SYSLOG_ACTION_CONSOLE_OFF = 6 + SYSLOG_ACTION_CONSOLE_ON = 7 + SYSLOG_ACTION_OPEN = 1 + SYSLOG_ACTION_READ = 2 + SYSLOG_ACTION_READ_ALL = 3 + SYSLOG_ACTION_READ_CLEAR = 4 + SYSLOG_ACTION_SIZE_BUFFER = 10 + SYSLOG_ACTION_SIZE_UNREAD = 9 + SYZ_PER_BSD = 6 + SYZ_PER_HPUX = 16 + SYZ_PER_IRIX32 = 9 + SYZ_PER_IRIX64 = 11 + SYZ_PER_IRIXN32 = 10 + SYZ_PER_ISCR4 = 5 + SYZ_PER_LINUX = 0 + SYZ_PER_LINUX32 = 8 + SYZ_PER_OSF4 = 15 + SYZ_PER_OSR5 = 3 + SYZ_PER_RISCOS = 12 + SYZ_PER_SOLARIS = 13 + SYZ_PER_SVR3 = 2 + SYZ_PER_SVR4 = 1 + SYZ_PER_UW7 = 14 + SYZ_PER_WYSEV386 = 4 + SYZ_PER_XENIX = 7 + S_IFBLK = 24576 + S_IFCHR = 8192 + S_IFIFO = 4096 + S_IFREG = 32768 + S_IFSOCK = 49152 + S_IRGRP = 32 + S_IROTH = 4 + S_IRUSR = 256 + S_IWGRP = 16 + S_IWOTH = 2 + S_IWUSR = 128 + S_IXGRP = 8 + S_IXOTH = 1 + S_IXUSR = 64 + TFD_CLOEXEC = 524288 + TFD_NONBLOCK = 2048 + TFD_TIMER_ABSTIME = 1 + TIMER_ABSTIME = 1 + UMOUNT_NOFOLLOW = 8 + WCONTINUED = 8 + WEXITED = 4 + WHOLE_SECONDS = 33554432 + WNOHANG = 1 + WNOWAIT = 16777216 + WSTOPPED = 2 + WUNTRACED = 2 + XATTR_CREATE = 1 + XATTR_REPLACE = 2 + __WALL = 1073741824 + __WCLONE = 2147483648 + __WNOTHREAD = 536870912 +) diff --git a/prog/encoding.go b/prog/encoding.go new file mode 100644 index 000000000..6a74d3dd0 --- /dev/null +++ b/prog/encoding.go @@ -0,0 +1,411 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package prog + +import ( + "bufio" + "bytes" + "encoding/hex" + "fmt" + "io" + "strconv" + + "github.com/google/syzkaller/sys" +) + +// String generates a very compact program description (mostly for debug output). +func (p *Prog) String() string { + buf := new(bytes.Buffer) + for i, c := range p.Calls { + if i != 0 { + fmt.Fprintf(buf, "-") + } + fmt.Fprintf(buf, "%v", c.Meta.Name) + } + return buf.String() +} + +func (p *Prog) Serialize() []byte { + /* + if err := p.validate(); err != nil { + panic("serializing invalid program") + } + */ + buf := new(bytes.Buffer) + vars := make(map[*Arg]int) + varSeq := 0 + for _, c := range p.Calls { + if len(c.Ret.Uses) != 0 { + fmt.Fprintf(buf, "r%v = ", varSeq) + vars[c.Ret] = varSeq + varSeq++ + } + fmt.Fprintf(buf, "%v(", c.Meta.Name) + for i, a := range c.Args { + if i != 0 { + fmt.Fprintf(buf, ", ") + } + a.serialize(buf, vars, &varSeq) + } + fmt.Fprintf(buf, ")\n") + } + return buf.Bytes() +} + +func (a *Arg) serialize(buf io.Writer, vars map[*Arg]int, varSeq *int) { + if a == nil { + fmt.Fprintf(buf, "nil") + return + } + if len(a.Uses) != 0 { + fmt.Fprintf(buf, "[r%v=]", *varSeq) + vars[a] = *varSeq + *varSeq++ + } + switch a.Kind { + case ArgConst: + fmt.Fprintf(buf, "0x%x", a.Val) + case ArgResult: + id, ok := vars[a.Res] + if !ok { + panic("no result") + } + fmt.Fprintf(buf, "r%v", id) + if a.OpDiv != 0 { + fmt.Fprintf(buf, "/%v", a.OpDiv) + } + if a.OpAdd != 0 { + fmt.Fprintf(buf, "+%v", a.OpAdd) + } + case ArgPointer: + fmt.Fprintf(buf, "&%v=", serializeAddr(a, true)) + a.Res.serialize(buf, vars, varSeq) + case ArgPageSize: + fmt.Fprintf(buf, "%v", serializeAddr(a, false)) + case ArgData: + fmt.Fprintf(buf, "\"%v\"", hex.EncodeToString(a.Data)) + case ArgGroup: + fmt.Fprintf(buf, "{") + for i, a1 := range a.Inner { + if i != 0 { + fmt.Fprintf(buf, ", ") + } + a1.serialize(buf, vars, varSeq) + } + fmt.Fprintf(buf, "}") + default: + panic("unknown arg kind") + } +} + +func Deserialize(data []byte) (prog *Prog, err error) { + prog = new(Prog) + p := &parser{r: bufio.NewScanner(bytes.NewReader(data))} + vars := make(map[string]*Arg) + for p.Scan() { + if p.EOF() { + continue + } + name := p.Ident() + r := "" + if p.Char() == '=' { + r = name + p.Parse('=') + name = p.Ident() + + } + meta := sys.CallMap[name] + if meta == nil { + return nil, fmt.Errorf("unknown syscall %v", name) + } + c := &Call{Meta: meta} + prog.Calls = append(prog.Calls, c) + p.Parse('(') + for i := 0; p.Char() != ')'; i++ { + arg, err := parseArg(p, vars) + if err != nil { + return nil, err + } + c.Args = append(c.Args, arg) + if p.Char() != ')' { + p.Parse(',') + } + } + p.Parse(')') + if !p.EOF() { + return nil, fmt.Errorf("tailing data (line #%v)", p.l) + } + if len(c.Args) != len(meta.Args) { + return nil, fmt.Errorf("wrong call arg count: %v, want %v", len(c.Args), len(meta.Args)) + } + assignTypeAndDir(c) + if r != "" { + vars[r] = c.Ret + } + } + if p.Err() != nil { + return nil, err + } + if err := prog.validate(); err != nil { + return nil, err + } + return +} + +func parseArg(p *parser, vars map[string]*Arg) (*Arg, error) { + r := "" + if p.Char() == '[' { + p.Parse('[') + r = p.Ident() + p.Parse('=') + p.Parse(']') + } + var arg *Arg + switch p.Char() { + case '0': + val := p.Ident() + v, err := strconv.ParseUint(val, 0, 64) + if err != nil { + return nil, fmt.Errorf("wrong arg value '%v': %v", val, err) + } + arg = constArg(uintptr(v)) + case 'r': + id := p.Ident() + v, ok := vars[id] + if !ok || v == nil { + return nil, fmt.Errorf("result %v references unknown variable (vars=%+v)", id, vars) + } + arg = resultArg(v) + if p.Char() == '/' { + p.Parse('/') + op := p.Ident() + v, err := strconv.ParseUint(op, 0, 64) + if err != nil { + return nil, fmt.Errorf("wrong result div op: '%v'", op) + } + arg.OpDiv = uintptr(v) + } + if p.Char() == '+' { + p.Parse('+') + op := p.Ident() + v, err := strconv.ParseUint(op, 0, 64) + if err != nil { + return nil, fmt.Errorf("wrong result add op: '%v'", op) + } + arg.OpAdd = uintptr(v) + } + case '&': + p.Parse('&') + page, off, err := parseAddr(p, true) + if err != nil { + return nil, err + } + p.Parse('=') + inner, err := parseArg(p, vars) + if err != nil { + return nil, err + } + arg = pointerArg(page, off, inner) + case '(': + page, off, err := parseAddr(p, false) + if err != nil { + return nil, err + } + arg = pageSizeArg(page, off) + case '"': + p.Parse('"') + val := "" + if p.Char() != '"' { + val = p.Ident() + } + p.Parse('"') + data, err := hex.DecodeString(val) + if err != nil { + return nil, fmt.Errorf("data arg has bad value '%v'", val) + } + arg = dataArg(data) + case '{': + p.Parse('{') + var inner []*Arg + for p.Char() != '}' { + arg, err := parseArg(p, vars) + if err != nil { + return nil, err + } + inner = append(inner, arg) + if p.Char() != '}' { + p.Parse(',') + } + } + p.Parse('}') + arg = groupArg(inner) + case 'n': + p.Parse('n') + p.Parse('i') + p.Parse('l') + if r != "" { + return nil, fmt.Errorf("named nil argument") + } + default: + return nil, fmt.Errorf("failed to parse argument at %v (line #%v/%v: %v)", int(p.Char()), p.l, p.i, p.s) + } + if r != "" { + vars[r] = arg + } + return arg, nil +} + +const ( + encodingAddrBase = 0x7f0000000000 + encodingPageSize = 4 << 10 +) + +func serializeAddr(a *Arg, base bool) string { + page := a.AddrPage * encodingPageSize + if base { + page += encodingAddrBase + } + soff := "" + if off := a.AddrOffset; off != 0 { + sign := "+" + if off < 0 { + sign = "-" + off = -off + page += encodingPageSize + } + soff = fmt.Sprintf("%v0x%x", sign, off) + } + return fmt.Sprintf("(0x%x%v)", page, soff) +} + +func parseAddr(p *parser, base bool) (uintptr, int, error) { + p.Parse('(') + pstr := p.Ident() + page, err := strconv.ParseUint(pstr, 0, 64) + if err != nil { + return 0, 0, fmt.Errorf("failed to parse addr page: '%v'", pstr) + } + if page%encodingPageSize != 0 { + return 0, 0, fmt.Errorf("address base is not page size aligned: '%v'", pstr) + } + if base { + if page < encodingAddrBase { + return 0, 0, fmt.Errorf("address without base offset: '%v'", pstr) + } + page -= encodingAddrBase + } + var off int64 + if p.Char() == '+' || p.Char() == '-' { + minus := false + if p.Char() == '-' { + minus = true + p.Parse('-') + } else { + p.Parse('+') + } + ostr := p.Ident() + off, err = strconv.ParseInt(ostr, 0, 64) + if err != nil { + return 0, 0, fmt.Errorf("failed to parse addr offset: '%v'", ostr) + } + if minus { + page -= encodingPageSize + off = -off + } + } + p.Parse(')') + page /= encodingPageSize + return uintptr(page), int(off), nil +} + +type parser struct { + r *bufio.Scanner + s string + i int + l int + e error +} + +func (p *parser) Scan() bool { + if p.e != nil { + return false + } + if !p.r.Scan() { + p.e = p.r.Err() + return false + } + p.s = p.r.Text() + p.i = 0 + p.l++ + return true +} + +func (p *parser) Err() error { + return p.e +} + +func (p *parser) Str() string { + return p.s +} + +func (p *parser) EOF() bool { + return p.i == len(p.s) +} + +func (p *parser) Char() byte { + if p.e != nil { + return 0 + } + if p.EOF() { + p.failf("unexpected eof") + return 0 + } + return p.s[p.i] +} + +func (p *parser) Parse(ch byte) { + if p.e != nil { + return + } + if p.EOF() { + p.failf("want %s, got EOF", string(ch)) + return + } + if p.s[p.i] != ch { + p.failf("want '%v', got '%v'", string(ch), string(p.s[p.i])) + return + } + p.i++ + p.SkipWs() +} + +func (p *parser) SkipWs() { + for p.i < len(p.s) && (p.s[p.i] == ' ' || p.s[p.i] == '\t') { + p.i++ + } +} + +func (p *parser) Ident() string { + i := p.i + for p.i < len(p.s) && + (p.s[p.i] >= 'a' && p.s[p.i] <= 'z' || + p.s[p.i] >= 'A' && p.s[p.i] <= 'Z' || + p.s[p.i] >= '0' && p.s[p.i] <= '9' || + p.s[p.i] == '_' || p.s[p.i] == '$') { + p.i++ + } + if i == p.i { + p.failf("failed to parse identifier at pos %v", i) + return "" + } + if ch := p.s[i]; ch >= '0' && ch <= '9' { + } + s := p.s[i:p.i] + p.SkipWs() + return s +} + +func (p *parser) failf(msg string, args ...interface{}) { + p.e = fmt.Errorf("%v\nline #%v: %v", fmt.Sprintf(msg, args...), p.l, p.s) +} diff --git a/prog/encodingc.go b/prog/encodingc.go new file mode 100644 index 000000000..c84acc918 --- /dev/null +++ b/prog/encodingc.go @@ -0,0 +1,114 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package prog + +import ( + "bytes" + "fmt" + "io" + "unsafe" + + "github.com/google/syzkaller/sys" +) + +func (p *Prog) WriteCSource() []byte { + exec := p.SerializeForExec() + buf := new(bytes.Buffer) + writeCSource(buf, exec) + return buf.Bytes() +} + +func writeCSource(w io.Writer, exec []byte) { + fmt.Fprintf(w, `// autogenerated by syzkaller (http://github.com/google/syzkaller) +#include <syscall.h> +#include <string.h> +#include <stdint.h> + +int main() +{ +`) + read := func() uintptr { + if len(exec) < 8 { + panic("exec program overflow") + } + v := *(*uint64)(unsafe.Pointer(&exec[0])) + exec = exec[8:] + return uintptr(v) + } + resultRef := func() string { + arg := read() + res := fmt.Sprintf("r%v", arg) + if opDiv := read(); opDiv != 0 { + res = fmt.Sprintf("%v/%v", res, opDiv) + } + if opAdd := read(); opAdd != 0 { + res = fmt.Sprintf("%v+%v", res, opAdd) + } + return res + } + lastCall := 0 + for n := 0; ; n++ { + switch instr := read(); instr { + case instrEOF: + fmt.Fprintf(w, "\treturn 0;\n}\n") + return + case instrCopyin: + addr := read() + typ := read() + size := read() + switch typ { + case execArgConst: + arg := read() + fmt.Fprintf(w, "\t*(uint%v_t*)0x%x = 0x%x;\n", size*8, addr, arg) + case execArgResult: + fmt.Fprintf(w, "\t*(uint%v_t*)0x%x = %v;\n", size*8, addr, resultRef()) + case execArgData: + data := exec[:size] + exec = exec[(size+7)/8*8:] + var esc []byte + for _, v := range data { + hex := func(v byte) byte { + if v < 10 { + return '0' + v + } + return 'a' + v - 10 + } + esc = append(esc, '\\', 'x', hex(v>>4), hex(v<<4>>4)) + } + fmt.Fprintf(w, "\tmemcpy((void*)0x%x, \"%s\", %v);\n", addr, esc, size) + default: + panic("bad argument type") + } + case instrCopyout: + addr := read() + size := read() + fmt.Fprintf(w, "\tlong r%v = -1;\n", n) + fmt.Fprintf(w, "\tif (r%v != -1)\n", lastCall) + fmt.Fprintf(w, "\t\tr%v = *(uint%v_t*)0x%x;\n", n, size*8, addr) + default: + // Normal syscall. + meta := sys.Calls[instr] + fmt.Fprintf(w, "\tlong r%v = syscall(SYS_%v", n, meta.CallName) + nargs := read() + for i := uintptr(0); i < nargs; i++ { + typ := read() + size := read() + _ = size + switch typ { + case execArgConst: + fmt.Fprintf(w, ", 0x%xul", read()) + case execArgResult: + fmt.Fprintf(w, ", %v", resultRef()) + default: + panic("unknown arg type") + } + } + for i := nargs; i < 6; i++ { + fmt.Fprintf(w, ", 0") + } + fmt.Fprintf(w, ");\n") + lastCall = n + } + } +} diff --git a/prog/encodingexec.go b/prog/encodingexec.go new file mode 100644 index 000000000..90b8ef7ea --- /dev/null +++ b/prog/encodingexec.go @@ -0,0 +1,172 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// This file does serialization of programs for executor binary. +// The format aims at simple parsing: binary and irreversible. + +package prog + +const ( + instrEOF = ^uintptr(iota) + instrCopyin + instrCopyout +) + +const ( + execArgConst = uintptr(iota) + execArgResult + execArgData +) + +const ( + ptrSize = 8 + pageSize = 4 << 10 + dataOffset = 512 << 20 +) + +func (p *Prog) SerializeForExec() []byte { + if err := p.validate(); err != nil { + panic("serializing invalid program") + } + var instrSeq uintptr + w := &execContext{args: make(map[*Arg]*argInfo)} + for _, c := range p.Calls { + // Calculate arg offsets within structs. + foreachArg(c, func(arg, base *Arg, _ *[]*Arg) { + if base == nil || arg.Kind == ArgGroup { + return + } + if w.args[base] == nil { + w.args[base] = &argInfo{} + } + w.args[arg] = &argInfo{Offset: w.args[base].CurSize} + w.args[base].CurSize += arg.Size(arg.Type) + }) + // Generate copyin instructions that fill in data into pointer arguments. + foreachArg(c, func(arg, _ *Arg, _ *[]*Arg) { + if arg.Kind == ArgPointer && arg.Res != nil { + var rec func(*Arg) + rec = func(arg1 *Arg) { + if arg1.Kind == ArgGroup { + for _, arg2 := range arg1.Inner { + rec(arg2) + } + return + } + if arg1.Dir == DirOut || arg1.Kind == ArgData && len(arg1.Data) == 0 { + return + } + w.write(instrCopyin) + w.write(physicalAddr(arg) + w.args[arg1].Offset) + w.writeArg(arg1) + instrSeq++ + } + rec(arg.Res) + } + }) + // Generate the call itself. + w.write(uintptr(c.Meta.ID)) + w.write(uintptr(len(c.Args))) + for _, arg := range c.Args { + w.writeArg(arg) + } + w.args[c.Ret] = &argInfo{Idx: instrSeq} + instrSeq++ + // Generate copyout instructions that persist interesting return values. + foreachArg(c, func(arg, base *Arg, _ *[]*Arg) { + if len(arg.Uses) == 0 { + return + } + switch arg.Kind { + case ArgReturn: + // Idx is already assigned above. + case ArgConst, ArgResult: + // Create a separate copyout instruction that has own Idx. + if base.Kind != ArgPointer { + panic("arg base is not a pointer") + } + info := w.args[arg] + info.Idx = instrSeq + instrSeq++ + w.write(instrCopyout) + w.write(physicalAddr(base) + info.Offset) + w.write(arg.Size(arg.Type)) + default: + panic("bad arg kind in copyout") + } + }) + } + w.write(instrEOF) + return w.buf +} + +func physicalAddr(arg *Arg) uintptr { + if arg.Kind != ArgPointer { + panic("physicalAddr: bad arg kind") + } + addr := arg.AddrPage*pageSize + dataOffset + if arg.AddrOffset >= 0 { + addr += uintptr(arg.AddrOffset) + } else { + addr += pageSize - uintptr(-arg.AddrOffset) + } + return addr +} + +type execContext struct { + buf []byte + args map[*Arg]*argInfo +} + +type argInfo struct { + Offset uintptr // from base pointer + CurSize uintptr + Idx uintptr // instruction index +} + +func (w *execContext) write(v uintptr) { + w.buf = append(w.buf, byte(v>>0), byte(v>>8), byte(v>>16), byte(v>>24), byte(v>>32), byte(v>>40), byte(v>>48), byte(v>>56)) +} + +func (w *execContext) writeArg(arg *Arg) { + switch arg.Kind { + case ArgConst: + w.write(execArgConst) + w.write(arg.Size(arg.Type)) + w.write(arg.Val) + case ArgResult: + w.write(execArgResult) + w.write(arg.Size(arg.Type)) + w.write(w.args[arg.Res].Idx) + w.write(arg.OpDiv) + w.write(arg.OpAdd) + case ArgPointer: + w.write(execArgConst) + w.write(arg.Size(arg.Type)) + w.write(physicalAddr(arg)) + case ArgPageSize: + w.write(execArgConst) + w.write(arg.Size(arg.Type)) + w.write(arg.AddrPage * pageSize) + case ArgData: + w.write(execArgData) + w.write(uintptr(len(arg.Data))) + for i := 0; i < len(arg.Data); i += 8 { + var v uintptr + for j := 0; j < 8; j++ { + if i+j >= len(arg.Data) { + break + } + v |= uintptr(arg.Data[i+j]) << uint(j*8) + } + w.write(v) + } + case ArgGroup: + // Squash groups. + for _, arg1 := range arg.Inner { + w.writeArg(arg1) + } + default: + panic("unknown arg type") + } +} diff --git a/prog/generation.go b/prog/generation.go new file mode 100644 index 000000000..43e527aa0 --- /dev/null +++ b/prog/generation.go @@ -0,0 +1,29 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package prog + +import ( + "math/rand" + + "github.com/google/syzkaller/sys" +) + +// Generate generates a random program of length ~ncalls. +// calls is a set of allowed syscalls, if nil all syscalls are used. +func Generate(rs rand.Source, ncalls int, enabledCalls []*sys.Call) *Prog { + p := new(Prog) + r := newRand(rs) + s := newState(enabledCalls) + for len(p.Calls) < ncalls { + calls := r.generateCall(s) + for _, c := range calls { + s.analyze(c) + p.Calls = append(p.Calls, c) + } + } + if err := p.validate(); err != nil { + panic(err) + } + return p +} diff --git a/prog/mutation.go b/prog/mutation.go new file mode 100644 index 000000000..6d84f198f --- /dev/null +++ b/prog/mutation.go @@ -0,0 +1,377 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package prog + +import ( + "fmt" + "math/rand" + + "github.com/google/syzkaller/sys" +) + +func (p *Prog) Mutate(rs rand.Source, ncalls int, enabledCalls []*sys.Call) { + r := newRand(rs) + for stop := false; !stop; stop = r.bin() { + r.choose( + 10, func() { + // Insert a new call. + if len(p.Calls) >= ncalls { + return + } + idx := r.Intn(len(p.Calls) + 1) + var c *Call + if idx < len(p.Calls) { + c = p.Calls[idx] + } + s := analyze(enabledCalls, p, c) + calls := r.generateCall(s) + p.insertBefore(c, calls) + }, + 10, func() { + // Change args of a call. + if len(p.Calls) == 0 { + return + } + c := p.Calls[r.Intn(len(p.Calls))] + if len(c.Args) == 0 { + return + } + s := analyze(enabledCalls, p, c) + for stop := false; !stop; stop = r.bin() { + args, bases, parents := mutationArgs(c) + idx := r.Intn(len(args)) + arg, base, parent := args[idx], bases[idx], parents[idx] + var baseSize uintptr + if base != nil { + if base.Kind != ArgPointer || base.Res == nil { + panic("bad base arg") + } + baseSize = base.Res.Size(base.Res.Type) + } + var size *Arg + switch a := arg.Type.(type) { + case sys.IntType, sys.FlagsType, sys.FileoffType, sys.ResourceType, sys.VmaType: + arg1, size1, calls1 := r.generateArg(s, arg.Type, arg.Dir, nil) + replaceArg(p, arg, arg1, calls1) + size = size1 + case sys.BufferType: + switch a.Kind { + case sys.BufferBlob: + var data []byte + switch arg.Kind { + case ArgData: + data = append([]byte{}, arg.Data...) + case ArgConst: + // 0 is OK for optional args. + if arg.Val != 0 { + panic(fmt.Sprintf("BufferType has non-zero const value: %v", arg.Val)) + } + default: + panic(fmt.Sprintf("bad arg kind for BufferType: %v", arg.Kind)) + } + arg.Data = mutateData(r, data) + case sys.BufferString: + if r.bin() { + arg.Data = mutateData(r, append([]byte{}, arg.Data...)) + } else { + arg.Data = r.randString(s) + } + case sys.BufferSockaddr: + arg.Data = r.sockaddr(s) + default: + panic("unknown buffer kind") + } + size = constArg(uintptr(len(arg.Data))) + case sys.FilenameType: + filename := r.filename(s) + arg.Data = []byte(filename) + case sys.ArrayType: + count := r.rand(6) + if count > uintptr(len(arg.Inner)) { + var calls []*Call + for count > uintptr(len(arg.Inner)) { + arg1, _, calls1 := r.generateArg(s, a.Type, arg.Dir, nil) + arg.Inner = append(arg.Inner, arg1) + for _, c1 := range calls1 { + calls = append(calls, c1) + s.analyze(c1) + } + } + for _, c1 := range calls { + assignTypeAndDir(c1) + sanitizeCall(c1) + } + assignTypeAndDir(c) + sanitizeCall(c) + p.insertBefore(c, calls) + } else if count < uintptr(len(arg.Inner)) { + removed := arg.Inner[count:] + arg.Inner = arg.Inner[:count] + + foreachArgArray(&removed, nil, func(arg, _ *Arg, _ *[]*Arg) { + if arg.Kind == ArgResult { + if _, ok := arg.Res.Uses[arg]; !ok { + panic("broken tree") + } + delete(arg.Res.Uses, arg) + } + }) + + for _, arg := range referencedArgs(removed, nil) { + c1 := arg.Call + s := analyze(enabledCalls, p, c1) + arg1, _, calls1 := r.generateArg(s, arg.Type, arg.Dir, nil) + replaceArg(p, arg, arg1, calls1) + } + } + // TODO: swap elements of the array + size = constArg(count) + case sys.PtrType: + // TODO: we don't know size for out args + size := uintptr(1) + if arg.Res != nil { + size = arg.Res.Size(arg.Res.Type) + } + arg1, calls1 := r.addr(s, size, arg.Res) + replaceArg(p, arg, arg1, calls1) + case sys.StructType: + switch a.Name() { + case "timespec", "timeval": + arg1, _, calls1 := r.generateArg(s, arg.Type, arg.Dir, nil) + replaceArg(p, arg.Inner[0], arg1.Inner[0], calls1) + replaceArg(p, arg.Inner[1], arg1.Inner[1], nil) + default: + panic("bad arg returned by mutationArgs: StructType") + } + case sys.LenType: + panic("bad arg returned by mutationArgs: LenType") + default: + panic(fmt.Sprintf("bad arg returned by mutationArgs: %#v, type=%#v", *arg, arg.Type)) + } + + // Update associated size argument if there is one. + if size != nil { + name := arg.Type.Name() + if name == "" && base != nil { + name = base.Type.Name() + } + for _, arg1 := range *parent { + if sz, ok := arg1.Type.(sys.LenType); ok && sz.Buf == name { + if arg1.Kind != ArgConst && arg1.Kind != ArgPageSize { + panic(fmt.Sprintf("size arg is not const: %#v", *arg1)) + } + arg1.Val = size.Val + arg1.AddrPage = size.AddrPage + arg1.AddrOffset = size.AddrOffset + } + } + } + + // Update base pointer if size has increased. + if base != nil && baseSize < base.Res.Size(base.Res.Type) { + arg1, calls1 := r.addr(s, base.Res.Size(base.Res.Type), base.Res) + for _, c := range calls1 { + assignTypeAndDir(c) + sanitizeCall(c) + } + p.insertBefore(c, calls1) + arg.AddrPage = arg1.AddrPage + arg.AddrOffset = arg1.AddrOffset + } + } + }, + 1, func() { + // Remove a random call. + if len(p.Calls) == 0 { + return + } + idx := r.Intn(len(p.Calls)) + c := p.Calls[idx] + copy(p.Calls[idx:], p.Calls[idx+1:]) + p.Calls = p.Calls[:len(p.Calls)-1] + + foreachArg(c, func(arg, _ *Arg, _ *[]*Arg) { + if arg.Kind == ArgResult { + if _, ok := arg.Res.Uses[arg]; !ok { + panic("broken tree") + } + delete(arg.Res.Uses, arg) + } + }) + + for _, arg := range referencedArgs(c.Args, c.Ret) { + c1 := arg.Call + s := analyze(enabledCalls, p, c1) + arg1, _, calls1 := r.generateArg(s, arg.Type, arg.Dir, nil) + replaceArg(p, arg, arg1, calls1) + } + }, + ) + } + for _, c := range p.Calls { + assignTypeAndDir(c) + sanitizeCall(c) + } + if err := p.validate(); err != nil { + panic(err) + } +} + +// Minimize minimizes program p into an equivalent program using the equivalence +// predicate pred. It iteratively generates simpler programs and asks pred +// whether it is equal to the orginal program or not. If it is equivalent then +// the simplification attempt is committed and the process continues. +func Minimize(p0 *Prog, callIndex0 int, pred func(*Prog, int) bool) (*Prog, int) { + if callIndex0 < 0 || callIndex0 >= len(p0.Calls) { + panic("bad call index") + } + name0 := p0.Calls[callIndex0].Meta.Name + // Try to remove all calls except the last one one-by-one. + for i := len(p0.Calls) - 1; i >= 0; i-- { + if i == callIndex0 { + continue + } + callIndex := callIndex0 + if i < callIndex { + callIndex-- + } + c := p0.Calls[i] + p := p0.Clone() + c = p.Calls[i] + copy(p.Calls[i:], p.Calls[i+1:]) + p.Calls = p.Calls[:len(p.Calls)-1] + for _, arg := range referencedArgs(c.Args, c.Ret) { + arg1 := constArg(arg.Type.Default()) + replaceArg(p, arg, arg1, nil) + } + foreachArg(c, func(arg, _ *Arg, _ *[]*Arg) { + if arg.Kind == ArgResult { + delete(arg.Res.Uses, arg) + } + }) + if !pred(p, callIndex) { + continue + } + p0 = p + callIndex0 = callIndex + } + // TODO: simplify individual arguments: + // - replace constants with 0 + // - reset bits in constants + // - remove offsets from addresses + // - replace file descriptors with -1 + // etc + if callIndex0 < 0 || callIndex0 >= len(p0.Calls) || name0 != p0.Calls[callIndex0].Meta.Name { + panic(fmt.Sprintf("bad call index after minimizatoin: ncalls=%v index=%v call=%v/%v", + len(p0.Calls), callIndex0, name0, p0.Calls[callIndex0].Meta.Name)) + } + return p0, callIndex0 +} + +func (p *Prog) TrimAfter(idx int) { + if idx < 0 || idx >= len(p.Calls) { + panic("trimming non-existing call") + } + for i := len(p.Calls) - 1; i > idx; i-- { + c := p.Calls[i] + foreachArg(c, func(arg, _ *Arg, _ *[]*Arg) { + if arg.Kind == ArgResult { + delete(arg.Res.Uses, arg) + } + }) + } + p.Calls = p.Calls[:idx+1] +} + +func mutationArgs(c *Call) (args, bases []*Arg, parents []*[]*Arg) { + foreachArg(c, func(arg, base *Arg, parent *[]*Arg) { + switch arg.Type.(type) { + case sys.StructType: + switch arg.Type.Name() { + default: + // For structs only individual fields are updated. + return + case "timespec", "timeval": + // These special structs are mutated as a whole. + } + case sys.LenType: + // Size is updated when the size-of arg change. + return + } + if arg.Dir == DirOut { + return + } + if base != nil { + if _, ok := base.Type.(sys.StructType); ok && (base.Type.Name() == "timespec" || base.Type.Name() == "timeval") { + // These special structs are mutated as a whole. + return + } + } + args = append(args, arg) + bases = append(bases, base) + parents = append(parents, parent) + }) + return +} + +func mutateData(r *randGen, data []byte) []byte { + for stop := false; !stop; stop = r.bin() { + r.choose( + 1, func() { + data = append(data, byte(r.rand(256))) + }, + 1, func() { + if len(data) == 0 { + return + } + data[r.Intn(len(data))] = byte(r.rand(256)) + }, + 1, func() { + if len(data) == 0 { + return + } + byt := r.Intn(len(data)) + bit := r.Intn(8) + data[byt] ^= 1 << uint(bit) + }, + 1, func() { + if len(data) == 0 { + return + } + i := r.Intn(len(data)) + copy(data[i:], data[i+1:]) + data = data[:len(data)-1] + }, + ) + } + return data +} + +func replaceArg(p *Prog, arg, arg1 *Arg, calls []*Call) { + if arg.Kind != ArgConst && arg.Kind != ArgResult && arg.Kind != ArgPointer { + panic(fmt.Sprintf("replaceArg: bad arg kind %v", arg.Kind)) + } + if arg1.Kind != ArgConst && arg1.Kind != ArgResult && arg1.Kind != ArgPointer { + panic(fmt.Sprintf("replaceArg: bad arg1 kind %v", arg1.Kind)) + } + if arg.Kind == ArgResult { + delete(arg.Res.Uses, arg) + } + for _, c := range calls { + assignTypeAndDir(c) + sanitizeCall(c) + } + c := arg.Call + p.insertBefore(c, calls) + // Somewhat hacky, but safe and preserves references to arg. + uses := arg.Uses + *arg = *arg1 + arg.Uses = uses + if arg.Kind == ArgResult { + delete(arg.Res.Uses, arg1) + arg.Res.Uses[arg] = true + } + assignTypeAndDir(c) + sanitizeCall(c) +} diff --git a/prog/mutation_test.go b/prog/mutation_test.go new file mode 100644 index 000000000..c788baf3d --- /dev/null +++ b/prog/mutation_test.go @@ -0,0 +1,268 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package prog + +import ( + "bytes" + "fmt" + "testing" +) + +func TestClone(t *testing.T) { + rs, iters := initTest(t) + for i := 0; i < iters; i++ { + p := Generate(rs, 10, nil) + p1 := p.Clone() + data := p.Serialize() + data1 := p1.Serialize() + if !bytes.Equal(data, data1) { + t.Fatalf("program changed after clone\noriginal:\n%s\n\nnew:\n%s\n", data, data1) + } + } +} + +func TestMutate(t *testing.T) { + rs, iters := initTest(t) +next: + for i := 0; i < iters; i++ { + p := Generate(rs, 10, nil) + data0 := p.Serialize() + p1 := p.Clone() + // There is a chance that mutation will produce the same program. + // So we check that at least 1 out of 10 mutations actually change the program. + for try := 0; try < 10; try++ { + p1.Mutate(rs, 10, nil) + data := p.Serialize() + if !bytes.Equal(data0, data) { + t.Fatalf("program changed after clone/mutate\noriginal:\n%s\n\nnew:\n%s\n", data0, data) + } + data1 := p1.Serialize() + if !bytes.Equal(data, data1) { + continue next + } + } + t.Fatalf("mutation does not change program") + } +} + +func TestMutateTable(t *testing.T) { + if testing.Short() { + t.Skip("skipping in short mode") + } + tests := [][2]string{ + // Insert calls. + { + "mmap(&(0x7f0000000000)=nil, (0x1000), 0x3, 0x32, 0xffffffffffffffff, 0x0)\n" + + "pipe2(&(0x7f0000000000)={0x0, 0x0}, 0x0)\n", + + "mmap(&(0x7f0000000000)=nil, (0x1000), 0x3, 0x32, 0xffffffffffffffff, 0x0)\n" + + "sched_yield()\n" + + "pipe2(&(0x7f0000000000)={0x0, 0x0}, 0x0)\n", + }, + // Remove calls and update args. + { + "r0 = open(&(0x7f0000001000)=\"2e2f66696c653000\", 0x22c0, 0x1)\n" + + "sched_yield()\n" + + "read(r0, &(0x7f0000000000)=0x0, 0x1)\n" + + "sched_yield()\n", + + "sched_yield()\n" + + "read(0xffffffffffffffff, &(0x7f0000000000)=0x0, 0x1)\n" + + "sched_yield()\n", + }, + // Mutate flags. + { + "r0 = open(&(0x7f0000001000)=\"2e2f66696c653000\", 0x22c0, 0x1)\n" + + "sched_yield()\n" + + "read(r0, &(0x7f0000000000)=0x0, 0x1)\n" + + "sched_yield()\n", + + "r0 = open(&(0x7f0000001000)=\"2e2f66696c653000\", 0x22c0, 0x2)\n" + + "sched_yield()\n" + + "read(r0, &(0x7f0000000000)=0x0, 0x1)\n" + + "sched_yield()\n", + }, + // Mutate data (delete byte and update size). + { + "r0 = open(&(0x7f0000001000)=\"2e2f66696c653000\", 0x22c0, 0x1)\n" + + "write(r0, &(0x7f0000000000)=\"11223344\", 0x4)\n", + + "r0 = open(&(0x7f0000001000)=\"2e2f66696c653000\", 0x22c0, 0x1)\n" + + "write(r0, &(0x7f0000000000)=\"112244\", 0x3)\n", + }, + // Mutate data (insert byte and update size). + { + "r0 = open(&(0x7f0000001000)=\"2e2f66696c653000\", 0x22c0, 0x1)\n" + + "write(r0, &(0x7f0000000000)=\"1122\", 0x2)\n", + + "r0 = open(&(0x7f0000001000)=\"2e2f66696c653000\", 0x22c0, 0x1)\n" + + "write(r0, &(0x7f0000000000)=\"112255\", 0x3)\n", + }, + // Mutate data (change byte). + { + "r0 = open(&(0x7f0000001000)=\"2e2f66696c653000\", 0x22c0, 0x1)\n" + + "write(r0, &(0x7f0000000000)=\"1122\", 0x2)\n", + + "r0 = open(&(0x7f0000001000)=\"2e2f66696c653000\", 0x22c0, 0x1)\n" + + "write(r0, &(0x7f0000000000)=\"1155\", 0x2)\n", + }, + // Change filename. + { + "open(&(0x7f0000001000)=\"2e2f66696c653000\", 0x22c0, 0x1)\n" + + "r0 = open(&(0x7f0000001000)=\"2e2f66696c653000\", 0x22c0, 0x1)\n" + + "write(r0, &(0x7f0000000000)=\"\", 0x0)\n", + + "open(&(0x7f0000001000)=\"2e2f66696c653000\", 0x22c0, 0x1)\n" + + "r0 = open(&(0x7f0000001000)=\"2e2f66696c653100\", 0x22c0, 0x1)\n" + + "write(r0, &(0x7f0000000000)=\"\", 0x0)\n", + }, + // Extend an array. + { + "r0 = open(&(0x7f0000001000)=\"2e2f66696c653000\", 0x22c0, 0x1)\n" + + "readv(r0, &(0x7f0000000000)={{&(0x7f0000001000)=nil, 0x1}, {&(0x7f0000002000)=nil, 0x2}}, 0x2)\n", + + "mmap(&(0x7f0000000000)=nil, (0x1000), 0x3, 0x32, 0xffffffffffffffff, 0x0)\n" + + "r0 = open(&(0x7f0000001000)=\"2e2f66696c653000\", 0x22c0, 0x1)\n" + + "readv(r0, &(0x7f0000000000)={{&(0x7f0000001000)=nil, 0x1}, {&(0x7f0000002000)=nil, 0x2}, {&(0x7f0000000000)=nil, 0x3}}, 0x3)\n", + }, + } + rs, _ := initTest(t) +nextTest: + for ti, test := range tests { + p, err := Deserialize([]byte(test[0])) + if err != nil { + t.Fatalf("failed to deserialize original program: %v", err) + } + for i := 0; i < 1e6; i++ { + p1 := p.Clone() + p1.Mutate(rs, 30, nil) + data1 := p1.Serialize() + if string(data1) == test[1] { + t.Logf("test #%v: success on iter %v", ti, i) + continue nextTest + } + _ = fmt.Printf + } + t.Fatalf("failed to achieve mutation goal\noriginal:\n%s\n\ngoal:\n%s\n", test[0], test[1]) + } +} + +func TestMinimize(t *testing.T) { + tests := []struct { + orig string + callIndex int + pred func(*Prog, int) bool + result string + }{ + // Predicate always returns false, so must get the same program. + { + "mmap(&(0x7f0000000000)=nil, (0x1000), 0x3, 0x32, 0xffffffffffffffff, 0x0)\n" + + "sched_yield()\n" + + "pipe2(&(0x7f0000000000)={0x0, 0x0}, 0x0)\n", + 2, + func(p *Prog, callIndex int) bool { + if len(p.Calls) == 0 { + t.Fatalf("got an empty program") + } + if p.Calls[len(p.Calls)-1].Meta.Name != "pipe2" { + t.Fatalf("last call is removed") + } + return false + }, + "mmap(&(0x7f0000000000)=nil, (0x1000), 0x3, 0x32, 0xffffffffffffffff, 0x0)\n" + + "sched_yield()\n" + + "pipe2(&(0x7f0000000000)={0x0, 0x0}, 0x0)\n", + }, + // Remove a call. + { + "mmap(&(0x7f0000000000)=nil, (0x1000), 0x3, 0x32, 0xffffffffffffffff, 0x0)\n" + + "sched_yield()\n" + + "pipe2(&(0x7f0000000000)={0x0, 0x0}, 0x0)\n", + 2, + func(p *Prog, callIndex int) bool { + // Aim at removal of sched_yield. + return len(p.Calls) == 2 && p.Calls[0].Meta.Name == "mmap" && p.Calls[1].Meta.Name == "pipe2" + }, + "mmap(&(0x7f0000000000)=nil, (0x1000), 0x3, 0x32, 0xffffffffffffffff, 0x0)\n" + + "pipe2(&(0x7f0000000000)={0x0, 0x0}, 0x0)\n", + }, + // Remove two dependent calls. + { + "mmap(&(0x7f0000000000)=nil, (0x1000), 0x3, 0x32, 0xffffffffffffffff, 0x0)\n" + + "pipe2(&(0x7f0000000000)={0x0, 0x0}, 0x0)\n" + + "sched_yield()\n", + 2, + func(p *Prog, callIndex int) bool { + // Aim at removal of pipe2 and then mmap. + if len(p.Calls) == 2 && p.Calls[0].Meta.Name == "mmap" && p.Calls[1].Meta.Name == "sched_yield" { + return true + } + if len(p.Calls) == 1 && p.Calls[0].Meta.Name == "sched_yield" { + return true + } + return false + }, + "sched_yield()\n", + }, + // Remove a call and replace results. + { + "mmap(&(0x7f0000000000)=nil, (0x1000), 0x3, 0x32, 0xffffffffffffffff, 0x0)\n" + + "pipe2(&(0x7f0000000000)={[r0=]0x0, 0x0}, 0x0)\n" + + "write(r0, &(0x7f0000000000)=\"1155\", 0x2)\n" + + "sched_yield()\n", + 3, + func(p *Prog, callIndex int) bool { + return p.String() == "mmap-write-sched_yield" + }, + "mmap(&(0x7f0000000000)=nil, (0x1000), 0x3, 0x32, 0xffffffffffffffff, 0x0)\n" + + "write(0xffffffffffffffff, &(0x7f0000000000)=\"1155\", 0x2)\n" + + "sched_yield()\n", + }, + // Remove a call and replace results. + { + "mmap(&(0x7f0000000000)=nil, (0x1000), 0x3, 0x32, 0xffffffffffffffff, 0x0)\n" + + "r0=open(&(0x7f0000000000)=\"1155\", 0x0, 0x0)\n" + + "write(r0, &(0x7f0000000000)=\"1155\", 0x2)\n" + + "sched_yield()\n", + 3, + func(p *Prog, callIndex int) bool { + return p.String() == "mmap-write-sched_yield" + }, + "mmap(&(0x7f0000000000)=nil, (0x1000), 0x3, 0x32, 0xffffffffffffffff, 0x0)\n" + + "write(0xffffffffffffffff, &(0x7f0000000000)=\"1155\", 0x2)\n" + + "sched_yield()\n", + }, + } + for ti, test := range tests { + p, err := Deserialize([]byte(test.orig)) + if err != nil { + t.Fatalf("failed to deserialize original program: %v", err) + } + p1, _ := Minimize(p, test.callIndex, test.pred) + res := p1.Serialize() + if string(res) != test.result { + t.Fatalf("minimization produced wrong result #%v\norig:\n%v\nexpect:\n%v\ngot:\n%v\n", + ti, test.orig, test.result, string(res)) + } + } +} + +func TestMinimizeRandom(t *testing.T) { + rs, iters := initTest(t) + for i := 0; i < iters; i++ { + p := Generate(rs, 10, nil) + Minimize(p, len(p.Calls)-1, func(p1 *Prog, callIndex int) bool { + if err := p1.validate(); err != nil { + t.Fatalf("invalid program: %v", err) + } + return false + }) + Minimize(p, len(p.Calls)-1, func(p1 *Prog, callIndex int) bool { + if err := p1.validate(); err != nil { + t.Fatalf("invalid program: %v", err) + } + return true + }) + } +} diff --git a/prog/prog.go b/prog/prog.go new file mode 100644 index 000000000..019873d99 --- /dev/null +++ b/prog/prog.go @@ -0,0 +1,143 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package prog + +import ( + "github.com/google/syzkaller/sys" +) + +type Prog struct { + Calls []*Call +} + +type Call struct { + Meta *sys.Call + Args []*Arg + Ret *Arg +} + +type Arg struct { + Call *Call + Type sys.Type + Kind ArgKind + Dir ArgDir + Val uintptr // value of ArgConst + AddrPage uintptr // page index for ArgPointer address, page count for ArgPageSize + AddrOffset int // page offset for ArgPointer address + Data []byte // data of ArgData + Inner []*Arg // subargs of ArgGroup + Res *Arg // target of ArgResult, pointee for ArgPointer + Uses map[*Arg]bool // this arg is used by those ArgResult args + OpDiv uintptr // divide result for ArgResult (executed before OpAdd) + OpAdd uintptr // add to result for ArgResult +} + +type ArgKind int + +const ( + ArgConst ArgKind = iota + ArgResult + ArgPointer // even if these are always constant (for reproducibility), we use a separate type because they are represented in an abstract (base+page+offset) form + ArgPageSize // same as ArgPointer but base is not added, so it represents "lengths" in pages + ArgData + ArgGroup // logical group of args (struct or array) + ArgReturn // fake value denoting syscall return value +) + +type ArgDir sys.Dir + +const ( + DirIn = ArgDir(sys.DirIn) + DirOut = ArgDir(sys.DirOut) + DirInOut = ArgDir(sys.DirInOut) +) + +func (a *Arg) Size(typ sys.Type) uintptr { + switch typ1 := typ.(type) { + case sys.IntType: + return typ1.TypeSize + case sys.LenType: + return typ1.TypeSize + case sys.FlagsType: + return typ1.TypeSize + case sys.FileoffType: + return typ1.TypeSize + case sys.ResourceType: + return typ1.Size() + case sys.VmaType: + return ptrSize + case sys.FilenameType: + return uintptr(len(a.Data)) + case sys.PtrType: + return ptrSize + case sys.StructType: + var size uintptr + for i, f := range typ1.Fields { + size += a.Inner[i].Size(f) + } + return size + case sys.ArrayType: + if len(a.Inner) == 0 { + return 0 + } + return uintptr(len(a.Inner)) * a.Inner[0].Size(typ1.Type) + case sys.BufferType: + return uintptr(len(a.Data)) + default: + panic("unknown arg type") + } +} + +func constArg(v uintptr) *Arg { + return &Arg{Kind: ArgConst, Val: v} +} + +func resultArg(r *Arg) *Arg { + arg := &Arg{Kind: ArgResult, Res: r} + if r.Uses == nil { + r.Uses = make(map[*Arg]bool) + } + if r.Uses[arg] { + panic("already used") + } + r.Uses[arg] = true + return arg +} + +func dataArg(data []byte) *Arg { + return &Arg{Kind: ArgData, Data: append([]byte{}, data...)} +} + +func pointerArg(page uintptr, off int, obj *Arg) *Arg { + return &Arg{Kind: ArgPointer, AddrPage: page, AddrOffset: off, Res: obj} +} + +func pageSizeArg(npages uintptr, off int) *Arg { + return &Arg{Kind: ArgPageSize, AddrPage: npages, AddrOffset: off} +} + +func groupArg(inner []*Arg) *Arg { + return &Arg{Kind: ArgGroup, Inner: inner} +} + +func returnArg() *Arg { + return &Arg{Kind: ArgReturn, Dir: DirOut} +} + +func (p *Prog) insertBefore(c *Call, calls []*Call) { + idx := 0 + for ; idx < len(p.Calls); idx++ { + if p.Calls[idx] == c { + break + } + } + var newCalls []*Call + newCalls = append(newCalls, p.Calls[:idx]...) + newCalls = append(newCalls, calls...) + if idx < len(p.Calls) { + newCalls = append(newCalls, p.Calls[idx]) + newCalls = append(newCalls, p.Calls[idx+1:]...) + } + p.Calls = newCalls +} diff --git a/prog/prog_test.go b/prog/prog_test.go new file mode 100644 index 000000000..e4c956c74 --- /dev/null +++ b/prog/prog_test.go @@ -0,0 +1,77 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package prog + +import ( + "bytes" + "fmt" + "math/rand" + "testing" + "time" +) + +func initTest(t *testing.T) (rand.Source, int) { + iters := 10000 + if testing.Short() { + iters = 100 + } + seed := int64(time.Now().UnixNano()) + rs := rand.NewSource(seed) + t.Logf("seed=%v", seed) + return rs, iters +} + +func TestGeneration(t *testing.T) { + rs, iters := initTest(t) + for i := 0; i < iters; i++ { + p := Generate(rs, 20, nil) + hasGettime, hasSelect := false, false + for _, c := range p.Calls { + if c.Meta.Name == "clock_gettime" { + hasGettime = true + } + if c.Meta.Name == "select" { + hasSelect = true + } + } + if hasGettime && hasSelect { + fmt.Printf("%s\n\n", p.WriteCSource()) + } + } +} + +func TestSerialize(t *testing.T) { + rs, iters := initTest(t) + for i := 0; i < iters; i++ { + p := Generate(rs, 10, nil) + data := p.Serialize() + p1, err := Deserialize(data) + if err != nil { + t.Fatalf("failed to deserialize program: %v\n%s", err, data) + } + data1 := p1.Serialize() + if len(p.Calls) != len(p1.Calls) { + t.Fatalf("different number of calls") + } + if !bytes.Equal(data, data1) { + t.Fatalf("program changed after serialize/deserialize\noriginal:\n%s\n\nnew:\n%s\n", data, data1) + } + } +} + +func TestSerializeForExec(t *testing.T) { + rs, iters := initTest(t) + for i := 0; i < iters; i++ { + p := Generate(rs, 10, nil) + p.SerializeForExec() + } +} + +func TestSerializeC(t *testing.T) { + rs, iters := initTest(t) + for i := 0; i < iters; i++ { + p := Generate(rs, 10, nil) + p.WriteCSource() + } +} diff --git a/prog/rand.go b/prog/rand.go new file mode 100644 index 000000000..18c79bb9d --- /dev/null +++ b/prog/rand.go @@ -0,0 +1,638 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package prog + +import ( + "bytes" + "encoding/binary" + "fmt" + "math/rand" + + "github.com/google/syzkaller/sys" +) + +type randGen struct { + *rand.Rand + createDepth int +} + +func newRand(rs rand.Source) *randGen { + return &randGen{rand.New(rs), 0} +} + +func (r *randGen) rand(n int) uintptr { + return uintptr(r.Intn(n)) +} + +func (r *randGen) bin() bool { + return r.Intn(2) == 0 +} + +func (r *randGen) oneOf(n int) bool { + return r.Intn(n) == 0 +} + +func (r *randGen) rand64() uintptr { + v := uintptr(r.Int63()) + if r.bin() { + v |= 1 << 63 + } + return v +} + +func (r *randGen) randInt() uintptr { + v := r.rand64() + r.choose( + 100, func() { v %= 10 }, + 10, func() { v %= 256 }, + 10, func() { v %= 4 << 10 }, + 10, func() { v %= 64 << 10 }, + 1, func() { v %= 1 << 31 }, + 1, func() {}, + ) + r.choose( + 10, func() {}, + 1, func() { v = uintptr(-int(v)) }, + ) + return v +} + +func (r *randGen) randBufLen() (n uintptr) { + r.choose( + 1, func() { n = 0 }, + 50, func() { n = r.rand(256) }, + 5, func() { n = 4 << 10 }, + ) + return +} + +func (r *randGen) randPageCount() (n uintptr) { + r.choose( + 100, func() { n = r.rand(4) + 1 }, + 5, func() { n = r.rand(20) + 1 }, + 1, func() { n = (r.rand(3) + 1) * 1024 }, + ) + return +} + +func (r *randGen) flags(vv []uintptr) uintptr { + var v uintptr + r.choose( + 10, func() { v = 0 }, + 10, func() { v = vv[r.rand(len(vv))] }, + 90, func() { + for stop := false; !stop; stop = r.bin() { + v |= vv[r.rand(len(vv))] + } + }, + 1, func() { v = r.rand64() }, + ) + return v +} + +func (r *randGen) filename(s *state) string { + // TODO: support procfs and sysfs + dir := "." + if r.oneOf(5) && len(s.files) != 0 { + files := make([]string, 0, len(s.files)) + for f := range s.files { + files = append(files, f) + } + dir = files[r.Intn(len(files))] + if len(dir) > 0 && dir[len(dir)-1] == 0 { + dir = dir[:len(dir)-1] + } + } + if len(s.files) == 0 || r.oneOf(10) { + // Generate a new name. + for i := 0; ; i++ { + f := fmt.Sprintf("%v/file%v\x00", dir, i) + if !s.files[f] { + return f + } + } + } + files := make([]string, 0, len(s.files)) + for f := range s.files { + files = append(files, f) + } + return files[r.Intn(len(files))] +} + +var sockFamilies = []uint16{AF_LOCAL, AF_INET, AF_INET6, AF_IPX, AF_NETLINK, AF_X25, AF_AX25, AF_ATMPVC, AF_APPLETALK, AF_PACKET} + +func (r *randGen) sockaddr(s *state) []byte { + fa := sockFamilies[r.Intn(len(sockFamilies))] + port := 13269 + uint16(r.Intn(20)) + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, fa) // this is actually host byte order + switch fa { + case AF_LOCAL: + buf.WriteString(r.filename(s)) + case AF_INET: + binary.Write(buf, binary.BigEndian, port) + binary.Write(buf, binary.BigEndian, uint32(127<<24+0<<16+0<<8+1)) + case AF_INET6: + binary.Write(buf, binary.BigEndian, port) + binary.Write(buf, binary.BigEndian, uint32(r.Int63())) // flow info + binary.Write(buf, binary.BigEndian, uint64(0)) // addr: loopback + binary.Write(buf, binary.BigEndian, uint64(1)) // addr: loopback + binary.Write(buf, binary.BigEndian, uint32(r.Int63())) // scope id + case AF_IPX: + case AF_NETLINK: + case AF_X25: + case AF_AX25: + case AF_ATMPVC: + case AF_APPLETALK: + case AF_PACKET: + binary.Write(buf, binary.BigEndian, uint16(0)) // Physical-layer protocol + binary.Write(buf, binary.BigEndian, uint32(0)) // Interface number + binary.Write(buf, binary.BigEndian, uint16(0)) // ARP hardware type + binary.Write(buf, binary.BigEndian, uint8(0)) // Packet type + binary.Write(buf, binary.BigEndian, uint8(0)) // Length of address + binary.Write(buf, binary.BigEndian, uint64(0)) // Physical-layer address + default: + panic("unknown socket domain") + } + if r.oneOf(2) { + buf.Write(make([]byte, 128-len(buf.Bytes()))) + } + data := buf.Bytes() + if r.oneOf(100) { + data = data[:r.Intn(len(data))] + } + return data +} + +func (r *randGen) randString(s *state) []byte { + if len(s.strings) != 0 && r.bin() { + // Return an existing string. + strings := make([]string, 0, len(s.strings)) + for s := range s.strings { + strings = append(strings, s) + } + return []byte(strings[r.Intn(len(strings))]) + } + dict := []string{"user", "keyring", "trusted", "system", "security", "selinux", + "posix_acl_access", "mime_type", "md5sum", "nodev", "self", "sysfs", "rootfs", + "ramfs", "bdev", "proc", "cgroup", "cpuset", "tmpfs", "devtmpfs", "debugfs", + "securityfs", "sockfs", "pipefs", "anon_inodefs", "devpts", "ext3", "ext2", + "ext4", "hugetlbfs", "vfat", "ecryptfs", "fuseblk", "fuse", "fusectl", "pstore", + "mqueue", "rpc_pipefs", "nfs", "nfs4", "nfsd", "binfmt_misc", "autofs", "xfs", + "jfs", "msdos", "ntfs", "minix", "hfs", "hfsplus", "qnx4", "ufs", "btrfs"} + punct := []byte{'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '+', '\\', + '/', ':', '.', ',', '-', '\'', '[', ']', '{', '}'} + buf := new(bytes.Buffer) + for !r.oneOf(4) { + r.choose( + 10, func() { buf.WriteString(dict[r.Intn(len(dict))]) }, + 10, func() { buf.Write([]byte{punct[r.Intn(len(punct))]}) }, + 1, func() { buf.Write([]byte{byte(r.Intn(256))}) }, + ) + } + if !r.oneOf(100) { + buf.Write([]byte{0}) + } + return buf.Bytes() +} + +func (r *randGen) timespec(s *state, usec bool) (arg *Arg, calls []*Call) { + // We need to generate timespec/timeval that are either (1) definitely in the past, + // or (2) definitely in unreachable fututre, or (3) few ms ahead of now. + // Note timespec/timeval can be absolute or relative to now. + r.choose( + 1, func() { + // now for relative, past for absolute + arg = groupArg([]*Arg{constArg(0), constArg(0)}) + }, + 1, func() { + // few ms ahead for relative, past for absolute + nsec := uintptr(10 * 1e6) + if usec { + nsec /= 1e3 + } + arg = groupArg([]*Arg{constArg(0), constArg(nsec)}) + }, + 1, func() { + // unreachable fututre for both relative and absolute + arg = groupArg([]*Arg{constArg(2e9), constArg(0)}) + }, + 1, func() { + // few ms ahead for absolute + tp := groupArg([]*Arg{constArg(0), constArg(0)}) + var tpaddr *Arg + tpaddr, calls = r.addr(s, 2*ptrSize, tp) + gettime := &Call{ + Meta: sys.CallMap["clock_gettime"], + Args: []*Arg{ + constArg(CLOCK_REALTIME), + tpaddr, + }, + } + calls = append(calls, gettime) + sec := resultArg(tp.Inner[0]) + nsec := resultArg(tp.Inner[1]) + if usec { + nsec.OpDiv = 1e3 + nsec.OpAdd = 10 * 1e3 + } else { + nsec.OpAdd = 10 * 1e6 + } + arg = groupArg([]*Arg{sec, nsec}) + }, + ) + return +} + +func (r *randGen) addr1(s *state, size uintptr, data *Arg) (*Arg, []*Call) { + npages := (size + pageSize - 1) / pageSize + if r.oneOf(10) { + return r.randPageAddr(s, npages, data), nil + } + for i := uintptr(0); i < maxPages-npages; i++ { + free := true + for j := uintptr(0); j < npages; j++ { + if s.pages[i+j] { + free = false + break + } + } + if !free { + continue + } + c := &Call{ + Meta: sys.CallMap["mmap"], + Args: []*Arg{ + pointerArg(i, 0, nil), + pageSizeArg(npages, 0), + constArg(PROT_READ | PROT_WRITE), + constArg(MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED), + constArg(sys.InvalidFD), + constArg(0), + }, + } + return pointerArg(i, 0, data), []*Call{c} + } + return r.randPageAddr(s, npages, data), nil +} + +func (r *randGen) addr(s *state, size uintptr, data *Arg) (*Arg, []*Call) { + arg, calls := r.addr1(s, size, data) + if arg.Kind != ArgPointer { + panic("bad") + } + // Patch offset of the address. + r.choose( + 1, func() {}, + 1, func() { arg.AddrOffset = -int(size) }, + 1, func() { + if size > 0 { + arg.AddrOffset = -r.Intn(int(size)) + } + }, + 1, func() { arg.AddrOffset = r.Intn(pageSize) }, + ) + return arg, calls +} + +func (r *randGen) randPageAddr(s *state, npages uintptr, data *Arg) *Arg { + var starts []uintptr + for i := uintptr(0); i < maxPages-npages; i++ { + busy := true + for j := uintptr(0); j < npages; j++ { + if !s.pages[i+j] { + busy = false + break + } + } + // TODO: it does not need to be completely busy, + // for example, mmap addr arg can be new memory. + if !busy { + continue + } + starts = append(starts, i) + } + if len(starts) != 0 { + return pointerArg(starts[r.rand(len(starts))], 0, data) + } else { + return pointerArg(r.rand(int(maxPages-npages)), 0, data) + } +} + +func (r *randGen) createResource(s *state, res sys.ResourceType) (arg *Arg, calls []*Call) { + if r.createDepth > 2 { + special := res.SpecialValues() + return constArg(special[r.Intn(len(special))]), nil + } + r.createDepth++ + defer func() { r.createDepth-- }() + + sk := res.Subkind + if r.oneOf(50) { + // Spoof resource subkind. + all := res.SubKinds() + sk = all[r.Intn(len(all))] + } + // Find calls that produce the necessary resources. + var metas []*sys.Call + // Recurse into arguments to see if there is an out/inout arg of necessary type. + var checkArg func(typ sys.Type, dir ArgDir) bool + checkArg = func(typ sys.Type, dir ArgDir) bool { + if resarg, ok := typ.(sys.ResourceType); ok && dir != DirIn && resarg.Kind == res.Kind && + (resarg.Subkind == sk || resarg.Subkind == sys.ResAny || sk == sys.ResAny) { + return true + } + switch typ1 := typ.(type) { + case sys.ArrayType: + if checkArg(typ1.Type, dir) { + return true + } + case sys.StructType: + for _, fld := range typ1.Fields { + if checkArg(fld, dir) { + return true + } + } + case sys.PtrType: + if checkArg(typ1.Type, ArgDir(typ1.Dir)) { + return true + } + } + return false + } + for _, meta := range s.enabledCalls { + ok := false + for _, arg := range meta.Args { + if checkArg(arg, DirIn) { + ok = true + break + } + } + if !ok && meta.Ret != nil && checkArg(meta.Ret, DirOut) { + ok = true + } + if ok { + metas = append(metas, meta) + } + } + if len(metas) == 0 { + if len(s.enabledCalls) != len(sys.Calls) { + // We used only a subset of all syscalls, + // so we legitimately may not be able to create the resource. + return constArg(res.Default()), nil + } + panic(fmt.Sprintf("can't create resource %v/%v", res.Kind, sk)) + } + + // Now we have a set of candidate calls that can create the necessary resource. + for i := 0; i < 1e3; i++ { + // Generate one of them. + meta := metas[r.Intn(len(metas))] + calls := r.generateParticularCall(s, meta) + assignTypeAndDir(calls[len(calls)-1]) + s1 := newState(s.enabledCalls) + s1.analyze(calls[len(calls)-1]) + // Now see if we have what we want. + var allres []*Arg + for sk1, ress := range s1.resources[res.Kind] { + if sk1 == sys.ResAny || sk == sys.ResAny || sk1 == sk { + allres = append(allres, ress...) + } + } + if len(allres) != 0 { + // Bingo! + arg := resultArg(allres[r.Intn(len(allres))]) + return arg, calls + } + switch meta.Name { + case "getgroups": + // Returns groups in an array. + default: + panic(fmt.Sprintf("unexpected call failed to create a resource %v/%v: %v", res.Kind, sk, meta.Name)) + } + // Discard unsuccessful calls. + for _, c := range calls { + foreachArg(c, func(arg, _ *Arg, _ *[]*Arg) { + if arg.Kind == ArgResult { + delete(arg.Res.Uses, arg) + } + }) + } + } + // Generally we can loop several times, e.g. when we choose a call that returns + // the resource in an array, but then generateArg generated that array of zero length. + // But we must succeed eventually. + panic("failed to create a resource") +} + +func (r *randGen) choose(args ...interface{}) { + if len(args) == 0 || len(args)%2 != 0 { + panic("bad number of args to choose") + } + n := len(args) / 2 + weights := make([]int, n) + funcs := make([]func(), n) + total := 0 + for i := 0; i < n; i++ { + weights[i] = total + args[i*2].(int) + funcs[i] = args[i*2+1].(func()) + total = weights[i] + } + x := r.Intn(total) + for i, w := range weights { + if x < w { + funcs[i]() + return + } + } + panic("choose is broken") +} + +func (r *randGen) generateCall(s *state) []*Call { + meta := s.enabledCalls[r.rand(len(s.enabledCalls))] + return r.generateParticularCall(s, meta) +} + +func (r *randGen) generateParticularCall(s *state, meta *sys.Call) (calls []*Call) { + c := &Call{Meta: meta} + c.Args, calls = r.generateArgs(s, meta.Args, DirIn) + calls = append(calls, c) + for _, c1 := range calls { + assignTypeAndDir(c1) + sanitizeCall(c1) + } + return calls +} + +func (r *randGen) generateArgs(s *state, types []sys.Type, dir ArgDir) ([]*Arg, []*Call) { + var calls []*Call + args := make([]*Arg, len(types)) + sizes := make(map[string]*Arg) + // Pass 1: generate all args except size arguments. + for i, typ := range types { + if _, ok := typ.(sys.LenType); ok { + continue + } + arg, size, calls1 := r.generateArg(s, typ, dir, sizes) + args[i] = arg + calls = append(calls, calls1...) + if size != nil { + sizes[typ.Name()] = size + } + } + // Pass 2: fill in size arguments. + for i, typ := range types { + if a, ok := typ.(sys.LenType); ok { + size := sizes[a.Buf] + if size == nil { + panic(fmt.Sprintf("no size for %v[%v] (%+v)", a.Name(), a.Buf, sizes)) + } + args[i] = size + } + } + return args, calls +} + +func (r *randGen) generateArg(s *state, typ sys.Type, dir ArgDir, sizes map[string]*Arg) (arg, size *Arg, calls []*Call) { + if dir == DirOut { + // No need to generate something interesting for output scalar arguments. + // But we still need to generate the argument itself so that it can be referenced + // in subsequent calls. For the same reason we do generate pointer/array/struct + // output arguments (their elements can be referenced in subsequent calls). + switch typ.(type) { + case sys.IntType, sys.FlagsType, sys.FileoffType, sys.ResourceType: + return constArg(0), nil, nil + } + } + + if typ.Optional() && r.oneOf(10) { + if _, ok := typ.(sys.BufferType); ok { + panic("impossible") // parent PtrType must be Optional instead + } + return constArg(typ.Default()), constArg(0), nil + } + + switch a := typ.(type) { + case sys.ResourceType: + r.choose( + 1, func() { + special := a.SpecialValues() + arg = constArg(special[r.Intn(len(special))]) + }, + 90, func() { + // Get an existing resource. + if ress := s.resources[a.Kind]; ress != nil { + allres := ress[a.Subkind] + allres = append(allres, ress[sys.ResAny]...) + if a.Subkind == sys.ResAny || r.oneOf(10) { + for _, v := range ress { + allres = append(allres, v...) + } + } + if len(allres) != 0 { + // TODO: negative PIDs mean process group, + // we should be able to negate an existing PID. + arg = resultArg(allres[r.Intn(len(allres))]) + } + } + if arg == nil { + arg, calls = r.createResource(s, a) + } + }, + 10, func() { + // Create a new resource. + arg, calls = r.createResource(s, a) + }, + ) + return arg, nil, calls + case sys.FileoffType: + // TODO: can do better + var arg *Arg + r.choose( + 90, func() { arg = constArg(0) }, + 10, func() { arg = constArg(r.rand(100)) }, + 1, func() { arg = constArg(r.randInt()) }, + ) + return arg, nil, nil + case sys.BufferType: + switch a.Kind { + case sys.BufferBlob: + sz := r.randBufLen() + if dir == DirOut { + return nil, constArg(sz), nil + } + data := make([]byte, sz) + for i := range data { + data[i] = byte(r.Intn(256)) + } + return dataArg(data), constArg(sz), nil + case sys.BufferString: + data := r.randString(s) + return dataArg(data), constArg(uintptr(len(data))), nil + case sys.BufferSockaddr: + data := r.sockaddr(s) + if dir == DirOut { + return nil, constArg(uintptr(len(data))), nil + } + return dataArg(data), constArg(uintptr(len(data))), nil + default: + panic("unknown buffer kind") + } + case sys.VmaType: + npages := r.randPageCount() + arg := r.randPageAddr(s, npages, nil) + return arg, pageSizeArg(npages, 0), nil + case sys.FlagsType: + return constArg(r.flags(a.Vals)), nil, nil + case sys.IntType: + v := r.randInt() + if a.Limit != 0 && !r.oneOf(100) { + v %= a.Limit + } + return constArg(v), nil, nil + case sys.FilenameType: + filename := r.filename(s) + return dataArg([]byte(filename)), nil, nil + case sys.ArrayType: + count := r.rand(6) + var inner []*Arg + var calls []*Call + for i := uintptr(0); i < count; i++ { + arg1, _, calls1 := r.generateArg(s, a.Type, dir, nil) + inner = append(inner, arg1) + calls = append(calls, calls1...) + } + return groupArg(inner), constArg(count), calls + case sys.StructType: + if dir != DirOut && (a.Name() == "timespec" || a.Name() == "timeval") { + usec := a.Name() == "timeval" + arg, calls = r.timespec(s, usec) + return arg, nil, calls + } + args, calls := r.generateArgs(s, a.Fields, dir) + return groupArg(args), nil, calls + case sys.PtrType: + inner, size, calls := r.generateArg(s, a.Type, ArgDir(a.Dir), sizes) + if ArgDir(a.Dir) == DirOut && inner == nil { + // No data, but we should have got size. + arg, calls1 := r.addr(s, size.Val, nil) + calls = append(calls, calls1...) + return arg, size, calls + } + if size == nil { + size = constArg(inner.Size(a.Type)) + } + arg, calls1 := r.addr(s, inner.Size(a.Type), inner) + calls = append(calls, calls1...) + return arg, size, calls + case sys.LenType: + if sizes == nil || sizes[a.Buf] == nil { + fmt.Printf("name=%v buf=%v sizes=%+v\n", a.Name(), a.Buf, sizes) + panic("me no generate len") + } + return sizes[a.Name()], nil, nil + default: + panic("unknown argument type") + } +} diff --git a/prog/validation.go b/prog/validation.go new file mode 100644 index 000000000..097848bed --- /dev/null +++ b/prog/validation.go @@ -0,0 +1,168 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package prog + +import ( + "fmt" + + "github.com/google/syzkaller/sys" +) + +type validCtx struct { + args map[*Arg]bool + uses map[*Arg]*Arg +} + +func (p *Prog) validate() error { + ctx := &validCtx{make(map[*Arg]bool), make(map[*Arg]*Arg)} + for _, c := range p.Calls { + if err := c.validate(ctx); err != nil { + + fmt.Printf("PROGRAM:\n") + for _, c := range p.Calls { + fmt.Printf(" %v: %+v %p\n", c.Meta.Name, c.Args, c.Ret) + } + + return err + } + } + for u, orig := range ctx.uses { + if !ctx.args[u] { + return fmt.Errorf("use of %+v referes to an out-of-tree arg\narg: %#v", *orig, u) + } + } + return nil +} + +func (c *Call) validate(ctx *validCtx) error { + if len(c.Args) != len(c.Meta.Args) { + return fmt.Errorf("syscall %v: wrong number of arguments, want %v, got %v", c.Meta.Name, len(c.Meta.Args), len(c.Args)) + } + var checkArg func(arg *Arg, typ sys.Type) error + checkArg = func(arg *Arg, typ sys.Type) error { + if arg == nil { + return fmt.Errorf("syscall %v: nil arg", c.Meta.Name) + } + if arg.Call != c { + return fmt.Errorf("syscall %v: arg has wrong call, call=%p, arg=%+v", c.Meta.Name, c, *arg) + } + if ctx.args[arg] { + return fmt.Errorf("syscall %v: arg is referenced several times in the tree", c.Meta.Name) + } + ctx.args[arg] = true + for u := range arg.Uses { + ctx.uses[u] = arg + } + if arg.Type == nil { + return fmt.Errorf("syscall %v: no type", c.Meta.Name) + } + if arg.Type.Name() != typ.Name() { + return fmt.Errorf("syscall %v: arg '%v' type mismatch", c.Meta.Name, typ.Name()) + } + if arg.Dir == DirOut { + if arg.Val != 0 || arg.AddrPage != 0 || arg.AddrOffset != 0 || len(arg.Data) != 0 { + return fmt.Errorf("syscall %v: output arg '%v' has data", c.Meta.Name, typ.Name()) + } + } + switch arg.Type.(type) { + case sys.ResourceType: + switch arg.Kind { + case ArgResult: + case ArgReturn: + case ArgConst: + if arg.Dir == DirOut && arg.Val != 0 { + return fmt.Errorf("syscall %v: out resource arg '%v' has bad const value %v", c.Meta.Name, typ.Name(), arg.Val) + } + default: + return fmt.Errorf("syscall %v: fd arg '%v' has bad kind %v", c.Meta.Name, typ.Name(), arg.Kind) + } + case sys.FilenameType: + switch arg.Kind { + case ArgData: + default: + return fmt.Errorf("syscall %v: filename arg '%v' has bad kind %v", c.Meta.Name, typ.Name(), arg.Kind) + } + } + switch arg.Kind { + case ArgConst: + case ArgResult: + if arg.Res == nil { + return fmt.Errorf("syscall %v: result arg '%v' has no reference", c.Meta.Name, typ.Name()) + } + if !ctx.args[arg.Res] { + return fmt.Errorf("syscall %v: result arg '%v' references out-of-tree result: %p%+v -> %v %p%+v", + c.Meta.Name, typ.Name(), arg, arg, arg.Res.Call.Meta.Name, arg.Res, arg.Res) + } + if _, ok := arg.Res.Uses[arg]; !ok { + return fmt.Errorf("syscall %v: result arg '%v' has broken link (%+v)", c.Meta.Name, typ.Name(), arg.Res.Uses) + } + case ArgPointer: + if arg.Dir != DirIn { + return fmt.Errorf("syscall %v: pointer arg '%v' has output direction", c.Meta.Name, typ.Name()) + } + switch typ1 := typ.(type) { + case sys.VmaType: + if arg.Res != nil { + return fmt.Errorf("syscall %v: vma arg '%v' has data", c.Meta.Name, typ.Name()) + } + case sys.PtrType: + if arg.Res != nil { + if err := checkArg(arg.Res, typ1.Type); err != nil { + return err + } + } + default: + return fmt.Errorf("syscall %v: pointer arg '%v' has bad meta type %+v", c.Meta.Name, typ.Name(), typ) + } + case ArgPageSize: + case ArgData: + case ArgGroup: + switch typ1 := typ.(type) { + case sys.StructType: + if len(arg.Inner) != len(typ1.Fields) { + return fmt.Errorf("syscall %v: struct arg '%v' has wrong number of fields, want %v, got %v", c.Meta.Name, typ.Name(), len(typ1.Fields), len(arg.Inner)) + } + for i, arg1 := range arg.Inner { + if err := checkArg(arg1, typ1.Fields[i]); err != nil { + return err + } + } + case sys.ArrayType: + for _, arg1 := range arg.Inner { + if err := checkArg(arg1, typ1.Type); err != nil { + return err + } + } + default: + return fmt.Errorf("syscall %v: group arg '%v' has bad underlying type %+v", c.Meta.Name, typ.Name(), typ) + } + case ArgReturn: + default: + return fmt.Errorf("syscall %v: unknown arg '%v' kind", c.Meta.Name, typ.Name()) + } + return nil + } + for i, arg := range c.Args { + if c.Ret.Kind != ArgReturn { + return fmt.Errorf("syscall %v: arg '%v' has wrong return kind", c.Meta.Name, arg.Type.Name()) + } + if err := checkArg(arg, c.Meta.Args[i]); err != nil { + return err + } + } + if c.Ret == nil { + return fmt.Errorf("syscall %v: return value is absent", c.Meta.Name) + } + if c.Ret.Kind != ArgReturn { + return fmt.Errorf("syscall %v: return value has wrong kind %v", c.Meta.Name, c.Ret.Kind) + } + if c.Meta.Ret != nil { + if err := checkArg(c.Ret, c.Meta.Ret); err != nil { + return err + } + } else if c.Ret.Type != nil { + return fmt.Errorf("syscall %v: return value has spurious type: %+v", c.Meta.Name, c.Ret.Type) + } + return nil +} diff --git a/rpctype/rpctype.go b/rpctype/rpctype.go new file mode 100644 index 000000000..a74c78e6e --- /dev/null +++ b/rpctype/rpctype.go @@ -0,0 +1,56 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// Package rpctype contains types of message passed via net/rpc connections +// between various parts of the system. +package rpctype + +type RpcInput struct { + Call string + Prog []byte + CallIndex int + Cover []uint32 +} + +type MasterConnectArgs struct { + Name string + Http string +} + +type MasterConnectRes struct { + Http string +} + +type NewMasterInputArgs struct { + Name string + Prog []byte +} + +type MasterPollArgs struct { + Name string +} + +type MasterPollRes struct { + Inputs [][]byte +} + +type ManagerConnectArgs struct { + Name string +} + +type ManagerConnectRes struct { +} + +type NewManagerInputArgs struct { + Name string + RpcInput +} + +type ManagerPollArgs struct { + Name string +} + +type ManagerPollRes struct { + Candidates [][]byte + NewInputs []RpcInput +} diff --git a/sys/decl.go b/sys/decl.go new file mode 100644 index 000000000..31f7febc3 --- /dev/null +++ b/sys/decl.go @@ -0,0 +1,270 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +//go:generate go install github.com/google/syzkaller/sysgen +//go:generate sysgen sys.txt + +package sys + +type Call struct { + ID int + CallID int + Name string + CallName string + Args []Type + Ret Type +} + +type Type interface { + Name() string + Optional() bool + Default() uintptr +} + +type TypeCommon struct { + TypeName string + IsOptional bool +} + +func (t TypeCommon) Name() string { + return t.TypeName +} + +func (t TypeCommon) Optional() bool { + return t.IsOptional +} + +func (t TypeCommon) Default() uintptr { + return 0 +} + +type ( + ResourceKind int + ResourceSubkind int +) + +const ( + ResFD ResourceKind = iota + ResIOCtx + ResIPC + ResKey + ResInotifyDesc + ResPid + ResUid + ResGid + ResTimerid +) + +const ( + ResAny ResourceSubkind = iota + FdFile + FdSock + FdPipe + FdSignal + FdEvent + FdTimer + FdEpoll + FdDir + FdMq + FdInotify + FdFanotify + + IPCMsq + IPCSem + IPCShm +) + +const ( + InvalidFD = ^uintptr(0) + BogusFD = uintptr(100000 - 1) +) + +type ResourceType struct { + TypeCommon + Kind ResourceKind + Subkind ResourceSubkind +} + +func (t ResourceType) Default() uintptr { + switch t.Kind { + case ResFD: + return InvalidFD + case ResIOCtx: + return 0 + case ResIPC: + return 0 + case ResKey: + return 0 + case ResInotifyDesc: + return 0 + case ResPid: + return 0 + case ResUid: + return 0 + case ResGid: + return 0 + case ResTimerid: + return 0 + default: + panic("unknown resource type") + } +} + +func (t ResourceType) SpecialValues() []uintptr { + switch t.Kind { + case ResFD: + return []uintptr{InvalidFD, BogusFD} + case ResIOCtx: + return []uintptr{0} + case ResIPC: + return []uintptr{0, ^uintptr(0)} + case ResKey: + return []uintptr{0} + case ResInotifyDesc: + return []uintptr{0} + case ResPid: + return []uintptr{0, ^uintptr(0)} + case ResUid: + return []uintptr{0, ^uintptr(0)} + case ResGid: + return []uintptr{0, ^uintptr(0)} + case ResTimerid: + return []uintptr{0} + default: + panic("unknown resource kind") + } +} + +func (t ResourceType) Size() uintptr { + switch t.Kind { + case ResFD: + return 4 + case ResIOCtx: + return 8 + case ResIPC: + return 4 + case ResKey: + return 4 + case ResInotifyDesc: + return 4 + case ResPid: + return 4 + case ResUid: + return 4 + case ResGid: + return 4 + case ResTimerid: + return 4 + default: + panic("unknown resource kind") + } +} + +func (t ResourceType) SubKinds() []ResourceSubkind { + switch t.Kind { + case ResFD: + return []ResourceSubkind{FdFile, FdSock, FdPipe, FdSignal, FdEvent, FdTimer, FdEpoll, FdDir, FdMq, FdInotify, FdFanotify} + case ResIPC: + return []ResourceSubkind{IPCMsq, IPCSem, IPCShm} + case ResIOCtx, ResKey, ResInotifyDesc, ResPid, ResUid, ResGid, ResTimerid: + return []ResourceSubkind{ResAny} + default: + panic("unknown resource kind") + } +} + +type FileoffType struct { + TypeCommon + TypeSize uintptr + File string +} + +type AddrType struct { + TypeCommon +} + +type BufferKind int + +const ( + BufferBlob BufferKind = iota + BufferString + BufferSockaddr +) + +type BufferType struct { + TypeCommon + Kind BufferKind +} + +type VmaType struct { + TypeCommon +} + +type LenType struct { + TypeCommon + TypeSize uintptr + Buf string +} + +type FlagsType struct { + TypeCommon + TypeSize uintptr + Vals []uintptr +} + +type IntType struct { + TypeCommon + TypeSize uintptr + Limit uintptr +} + +type FilenameType struct { + TypeCommon +} + +type ArrayType struct { + TypeCommon + Type Type +} + +type PtrType struct { + TypeCommon + Type Type + Dir Dir +} + +type StructType struct { + TypeCommon + Fields []Type +} + +type Dir int + +const ( + DirIn Dir = iota + DirOut + DirInOut +) + +var ( + CallCount int + CallMap = make(map[string]*Call) + CallID = make(map[string]int) +) + +func init() { + for _, c := range Calls { + if CallMap[c.Name] != nil { + println(c.Name) + panic("duplicate syscall") + } + id, ok := CallID[c.CallName] + if !ok { + id = len(CallID) + CallID[c.CallName] = id + } + c.CallID = id + CallMap[c.Name] = c + } + CallCount = len(CallID) +} diff --git a/sys/sys.go b/sys/sys.go new file mode 100644 index 000000000..a5cca6c36 --- /dev/null +++ b/sys/sys.go @@ -0,0 +1,303 @@ +// AUTOGENERATED FILE +package sys + +var Calls = []*Call{ + &Call{ID: 0, Name: "open", CallName: "open", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2, 1024, 8192, 524288, 64, 16384, 65536, 128, 0, 262144, 256, 131072, 2048, 2097152, 1052672, 512}}, FlagsType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 0, Vals: []uintptr{256, 128, 64, 32, 16, 8, 4, 2, 1}}}}, + &Call{ID: 1, Name: "openat", CallName: "openat", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2, 1024, 8192, 524288, 64, 16384, 65536, 128, 0, 262144, 256, 131072, 2048, 2097152, 1052672, 512}}, FlagsType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 0, Vals: []uintptr{256, 128, 64, 32, 16, 8, 4, 2, 1}}}}, + &Call{ID: 2, Name: "creat", CallName: "creat", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}}}, FlagsType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 0, Vals: []uintptr{256, 128, 64, 32, 16, 8, 4, 2, 1}}}}, + &Call{ID: 3, Name: "close", CallName: "close", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}}}, + &Call{ID: 4, Name: "read", CallName: "read", Ret: LenType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Buf: "buf", TypeSize: 0}, Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "count", IsOptional: false}, Buf: "buf", TypeSize: 0}}}, + &Call{ID: 5, Name: "pread64", CallName: "pread64", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "count", IsOptional: false}, Buf: "buf", TypeSize: 0}, FileoffType{TypeCommon: TypeCommon{TypeName: "pos", IsOptional: false}, File: "fd", TypeSize: 0}}}, + &Call{ID: 6, Name: "readv", CallName: "readv", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "vec", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_out", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "vlen", IsOptional: false}, Buf: "vec", TypeSize: 0}}}, + &Call{ID: 7, Name: "preadv", CallName: "preadv", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "vec", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_out", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "vlen", IsOptional: false}, Buf: "vec", TypeSize: 0}, FileoffType{TypeCommon: TypeCommon{TypeName: "off", IsOptional: false}, File: "fd", TypeSize: 0}}}, + &Call{ID: 8, Name: "write", CallName: "write", Ret: LenType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Buf: "buf", TypeSize: 0}, Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "count", IsOptional: false}, Buf: "buf", TypeSize: 0}}}, + &Call{ID: 9, Name: "pwrite64", CallName: "pwrite64", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "count", IsOptional: false}, Buf: "buf", TypeSize: 0}, FileoffType{TypeCommon: TypeCommon{TypeName: "pos", IsOptional: false}, File: "fd", TypeSize: 0}}}, + &Call{ID: 10, Name: "writev", CallName: "writev", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "vec", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_in", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "vlen", IsOptional: false}, Buf: "vec", TypeSize: 0}}}, + &Call{ID: 11, Name: "pwritev", CallName: "pwritev", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "vec", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_in", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "vlen", IsOptional: false}, Buf: "vec", TypeSize: 0}, FileoffType{TypeCommon: TypeCommon{TypeName: "off", IsOptional: false}, File: "fd", TypeSize: 0}}}, + &Call{ID: 12, Name: "lseek", CallName: "lseek", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FileoffType{TypeCommon: TypeCommon{TypeName: "offset", IsOptional: false}, File: "fd", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "whence", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2, 3, 4}}}}, + &Call{ID: 13, Name: "dup", CallName: "dup", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "oldfd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}}}, + &Call{ID: 14, Name: "dup2", CallName: "dup2", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "oldfd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, ResourceType{TypeCommon: TypeCommon{TypeName: "newfd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}}}, + &Call{ID: 15, Name: "dup3", CallName: "dup3", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "oldfd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, ResourceType{TypeCommon: TypeCommon{TypeName: "newfd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{524288}}}}, + &Call{ID: 16, Name: "pipe", CallName: "pipe", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "pipefd", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "pipefd", IsOptional: false}, Fields: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "rfd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, ResourceType{TypeCommon: TypeCommon{TypeName: "wfd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}}}, Dir: DirOut}}}, + &Call{ID: 17, Name: "pipe2", CallName: "pipe2", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "pipefd", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "pipefd", IsOptional: false}, Fields: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "rfd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, ResourceType{TypeCommon: TypeCommon{TypeName: "wfd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}}}, Dir: DirOut}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2048, 524288}}}}, + &Call{ID: 18, Name: "tee", CallName: "tee", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fdin", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, ResourceType{TypeCommon: TypeCommon{TypeName: "fdout", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, IntType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, TypeSize: 8}, FlagsType{TypeCommon: TypeCommon{TypeName: "f", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 4, 8}}}}, + &Call{ID: 19, Name: "splice", CallName: "splice", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fdin", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FileoffType{TypeCommon: TypeCommon{TypeName: "offin", IsOptional: false}, File: "fdin", TypeSize: 0}, ResourceType{TypeCommon: TypeCommon{TypeName: "fdout", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FileoffType{TypeCommon: TypeCommon{TypeName: "offout", IsOptional: false}, File: "fdout", TypeSize: 0}, IntType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, TypeSize: 8}, FlagsType{TypeCommon: TypeCommon{TypeName: "f", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 4, 8}}}}, + &Call{ID: 20, Name: "vmsplice", CallName: "vmsplice", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "vec", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_in", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "vlen", IsOptional: false}, Buf: "vec", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "f", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 4, 8}}}}, + &Call{ID: 21, Name: "sendfile", CallName: "sendfile", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fdout", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, ResourceType{TypeCommon: TypeCommon{TypeName: "fdin", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "off", IsOptional: true}, Type: FileoffType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, File: "fdin", TypeSize: 8}, Dir: DirInOut}, IntType{TypeCommon: TypeCommon{TypeName: "count", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 22, Name: "stat", CallName: "stat", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "statbuf", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "stat", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "dev", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "ino", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "nlink", IsOptional: false}, TypeSize: 2}, ResourceType{TypeCommon: TypeCommon{TypeName: "uid", IsOptional: false}, Kind: ResUid}, ResourceType{TypeCommon: TypeCommon{TypeName: "gid", IsOptional: false}, Kind: ResGid}, IntType{TypeCommon: TypeCommon{TypeName: "rdev", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "blksize", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "blocks", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "atime", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "ansec", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "mtime", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "mnsec", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "ctime", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "cnsec", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 4}}}, Dir: DirOut}}}, + &Call{ID: 23, Name: "lstat", CallName: "lstat", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "statbuf", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "stat", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "dev", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "ino", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "nlink", IsOptional: false}, TypeSize: 2}, ResourceType{TypeCommon: TypeCommon{TypeName: "uid", IsOptional: false}, Kind: ResUid}, ResourceType{TypeCommon: TypeCommon{TypeName: "gid", IsOptional: false}, Kind: ResGid}, IntType{TypeCommon: TypeCommon{TypeName: "rdev", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "blksize", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "blocks", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "atime", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "ansec", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "mtime", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "mnsec", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "ctime", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "cnsec", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 4}}}, Dir: DirOut}}}, + &Call{ID: 24, Name: "fstat", CallName: "fstat", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "statbuf", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "stat", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "dev", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "ino", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "nlink", IsOptional: false}, TypeSize: 2}, ResourceType{TypeCommon: TypeCommon{TypeName: "uid", IsOptional: false}, Kind: ResUid}, ResourceType{TypeCommon: TypeCommon{TypeName: "gid", IsOptional: false}, Kind: ResGid}, IntType{TypeCommon: TypeCommon{TypeName: "rdev", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "blksize", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "blocks", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "atime", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "ansec", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "mtime", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "mnsec", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "ctime", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "cnsec", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 4}}}, Dir: DirOut}}}, + &Call{ID: 25, Name: "poll", CallName: "poll", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "fds", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "pollfd", IsOptional: false}, Fields: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, IntType{TypeCommon: TypeCommon{TypeName: "events", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "revents", IsOptional: false}, TypeSize: 2}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "nfds", IsOptional: false}, Buf: "fds", TypeSize: 0}, IntType{TypeCommon: TypeCommon{TypeName: "timeout", IsOptional: false}, TypeSize: 4}}}, + &Call{ID: 26, Name: "ppoll", CallName: "ppoll", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "fds", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "pollfd", IsOptional: false}, Fields: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, IntType{TypeCommon: TypeCommon{TypeName: "events", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "revents", IsOptional: false}, TypeSize: 2}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "nfds", IsOptional: false}, Buf: "fds", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "tsp", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "sigmask", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigset", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "sigmask", TypeSize: 0}}}, + &Call{ID: 27, Name: "select", CallName: "select", Args: []Type{LenType{TypeCommon: TypeCommon{TypeName: "n", IsOptional: false}, Buf: "inp", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "inp", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "fd_set", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask7", IsOptional: false}, TypeSize: 8}}}, Dir: DirInOut}, PtrType{TypeCommon: TypeCommon{TypeName: "outp", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "fd_set", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask7", IsOptional: false}, TypeSize: 8}}}, Dir: DirInOut}, PtrType{TypeCommon: TypeCommon{TypeName: "exp", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "fd_set", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask7", IsOptional: false}, TypeSize: 8}}}, Dir: DirInOut}, PtrType{TypeCommon: TypeCommon{TypeName: "tvp", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}, Dir: DirInOut}}}, + &Call{ID: 28, Name: "pselect6", CallName: "pselect6", Args: []Type{LenType{TypeCommon: TypeCommon{TypeName: "n", IsOptional: false}, Buf: "inp", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "inp", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "fd_set", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask7", IsOptional: false}, TypeSize: 8}}}, Dir: DirInOut}, PtrType{TypeCommon: TypeCommon{TypeName: "outp", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "fd_set", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask7", IsOptional: false}, TypeSize: 8}}}, Dir: DirInOut}, PtrType{TypeCommon: TypeCommon{TypeName: "exp", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "fd_set", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mask7", IsOptional: false}, TypeSize: 8}}}, Dir: DirInOut}, PtrType{TypeCommon: TypeCommon{TypeName: "tvp", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, Dir: DirInOut}, PtrType{TypeCommon: TypeCommon{TypeName: "sig", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigset_size", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "ss", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigset", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, TypeSize: 8}}}, Dir: DirInOut}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "ss", TypeSize: 8}}}, Dir: DirIn}}}, + &Call{ID: 29, Name: "epoll_create", CallName: "epoll_create", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: FdEpoll}, Args: []Type{IntType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, TypeSize: 4}}}, + &Call{ID: 30, Name: "epoll_create1", CallName: "epoll_create1", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: FdEpoll}, Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{524288}}}}, + &Call{ID: 31, Name: "epoll_ctl", CallName: "epoll_ctl", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "epfd", IsOptional: false}, Kind: ResFD, Subkind: FdEpoll}, FlagsType{TypeCommon: TypeCommon{TypeName: "op", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 3, 2}}, ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "ev", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "epoll_event", IsOptional: false}, Fields: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "ev", IsOptional: false}, TypeSize: 4, Vals: []uintptr{1, 4, 8192, 2, 8, 16, 2147483648, 1073741824}}, IntType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}}}, + &Call{ID: 32, Name: "epoll_wait", CallName: "epoll_wait", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "epfd", IsOptional: false}, Kind: ResFD, Subkind: FdEpoll}, PtrType{TypeCommon: TypeCommon{TypeName: "events", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "epoll_event", IsOptional: false}, Fields: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "ev", IsOptional: false}, TypeSize: 4, Vals: []uintptr{1, 4, 8192, 2, 8, 16, 2147483648, 1073741824}}, IntType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, TypeSize: 8}}}}, Dir: DirOut}, LenType{TypeCommon: TypeCommon{TypeName: "maxevents", IsOptional: false}, Buf: "events", TypeSize: 0}, IntType{TypeCommon: TypeCommon{TypeName: "timeout", IsOptional: false}, TypeSize: 4}}}, + &Call{ID: 33, Name: "epoll_pwait", CallName: "epoll_pwait", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "epfd", IsOptional: false}, Kind: ResFD, Subkind: FdEpoll}, PtrType{TypeCommon: TypeCommon{TypeName: "events", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "epoll_event", IsOptional: false}, Fields: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "ev", IsOptional: false}, TypeSize: 4, Vals: []uintptr{1, 4, 8192, 2, 8, 16, 2147483648, 1073741824}}, IntType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, TypeSize: 8}}}}, Dir: DirOut}, LenType{TypeCommon: TypeCommon{TypeName: "maxevents", IsOptional: false}, Buf: "events", TypeSize: 0}, IntType{TypeCommon: TypeCommon{TypeName: "timeout", IsOptional: false}, TypeSize: 4}, PtrType{TypeCommon: TypeCommon{TypeName: "sigmask", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigset", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "sigmask", TypeSize: 0}}}, + &Call{ID: 34, Name: "signalfd", CallName: "signalfd", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: FdSignal}, Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigset", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "mask", TypeSize: 0}}}, + &Call{ID: 35, Name: "signalfd4", CallName: "signalfd4", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: FdSignal}, Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigset", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "mask", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2048, 524288}}}}, + &Call{ID: 36, Name: "eventfd", CallName: "eventfd", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: FdEvent}, Args: []Type{IntType{TypeCommon: TypeCommon{TypeName: "initval", IsOptional: false}, TypeSize: 4}}}, + &Call{ID: 37, Name: "eventfd2", CallName: "eventfd2", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: FdEvent}, Args: []Type{IntType{TypeCommon: TypeCommon{TypeName: "initval", IsOptional: false}, TypeSize: 4}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{524288, 2048, 1}}}}, + &Call{ID: 38, Name: "timerfd_create", CallName: "timerfd_create", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: FdTimer}, Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "clockid", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 5, 1, 6, 4, 7, 2, 3}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2048, 524288}}}}, + &Call{ID: 39, Name: "timerfd_settime", CallName: "timerfd_settime", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdTimer}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1}}, PtrType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "itimerspec", IsOptional: false}, Fields: []Type{StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "itimerspec", IsOptional: false}, Fields: []Type{StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}}}, Dir: DirOut}}}, + &Call{ID: 40, Name: "timerfd_gettime", CallName: "timerfd_gettime", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdTimer}, PtrType{TypeCommon: TypeCommon{TypeName: "cur", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "itimerspec", IsOptional: false}, Fields: []Type{StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}}}, Dir: DirOut}}}, + &Call{ID: 41, Name: "mmap", CallName: "mmap", Ret: VmaType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}}, Args: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "prot", IsOptional: false}, TypeSize: 0, Vals: []uintptr{4, 1, 2}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 64, 32, 2048, 4096, 0, 16, 256, 262144, 8192, 65536, 16384, 32768, 131072, 67108864}}, ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: true}, Kind: ResFD, Subkind: FdFile}, FileoffType{TypeCommon: TypeCommon{TypeName: "offset", IsOptional: false}, File: "fd", TypeSize: 0}}}, + &Call{ID: 42, Name: "munmap", CallName: "munmap", Args: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 0}}}, + &Call{ID: 43, Name: "mremap", CallName: "mremap", Ret: VmaType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}}, Args: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 0}, LenType{TypeCommon: TypeCommon{TypeName: "newlen", IsOptional: false}, Buf: "newaddr", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2}}, VmaType{TypeCommon: TypeCommon{TypeName: "newaddr", IsOptional: false}}}}, + &Call{ID: 44, Name: "remap_file_pages", CallName: "remap_file_pages", Args: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "addr", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "prot", IsOptional: false}, TypeSize: 0, Vals: []uintptr{4, 1, 2}}, IntType{TypeCommon: TypeCommon{TypeName: "pgoff", IsOptional: false}, TypeSize: 8}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 64, 32, 2048, 4096, 0, 16, 256, 262144, 8192, 65536, 16384, 32768, 131072, 67108864}}}}, + &Call{ID: 45, Name: "mprotect", CallName: "mprotect", Args: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "prot", IsOptional: false}, TypeSize: 0, Vals: []uintptr{4, 1, 2}}}}, + &Call{ID: 46, Name: "msync", CallName: "msync", Args: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "f", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 4, 2}}}}, + &Call{ID: 47, Name: "madvise", CallName: "madvise", Args: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "advice", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2, 3, 4, 9, 10, 11, 100, 101, 12, 13, 14, 15, 16, 17}}}}, + &Call{ID: 48, Name: "fadvise64", CallName: "fadvise64", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FileoffType{TypeCommon: TypeCommon{TypeName: "offset", IsOptional: false}, File: "fd", TypeSize: 0}, IntType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, TypeSize: 8}, FlagsType{TypeCommon: TypeCommon{TypeName: "advice", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 2, 1, 5, 3, 4}}}}, + &Call{ID: 49, Name: "readahead", CallName: "readahead", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, IntType{TypeCommon: TypeCommon{TypeName: "off", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "count", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 50, Name: "mbind", CallName: "mbind", Args: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 2, 3, 1, 32768, 16384}}, PtrType{TypeCommon: TypeCommon{TypeName: "nodemask", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 8}, Dir: DirIn}, IntType{TypeCommon: TypeCommon{TypeName: "maxnode", IsOptional: false}, TypeSize: 8}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 4}}}}, + &Call{ID: 51, Name: "move_pages", CallName: "move_pages", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, LenType{TypeCommon: TypeCommon{TypeName: "nr", IsOptional: false}, Buf: "pages", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "pages", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: VmaType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "nodes", IsOptional: true}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 4}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "status", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 4}}, Dir: DirOut}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2, 4}}}}, + &Call{ID: 52, Name: "migrate_pages", CallName: "migrate_pages", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "maxnode", IsOptional: false}, TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 8}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 8}, Dir: DirIn}}}, + &Call{ID: 53, Name: "set_mempolicy", CallName: "set_mempolicy", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 2, 3, 1, 32768, 16384}}, PtrType{TypeCommon: TypeCommon{TypeName: "nodemask", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 8}, Dir: DirIn}, IntType{TypeCommon: TypeCommon{TypeName: "maxnode", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 54, Name: "get_mempolicy", CallName: "get_mempolicy", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 4}, Dir: DirOut}, PtrType{TypeCommon: TypeCommon{TypeName: "nodemask", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 8}, Dir: DirOut}, IntType{TypeCommon: TypeCommon{TypeName: "maxnode", IsOptional: false}, TypeSize: 8}, VmaType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 4, 2, 1}}}}, + &Call{ID: 55, Name: "mincore", CallName: "mincore", Args: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "addr", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "vec", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "vec", IsOptional: false}, Kind: BufferBlob}}}}, + &Call{ID: 56, Name: "mlock", CallName: "mlock", Args: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "addr", TypeSize: 0}}}, + &Call{ID: 57, Name: "munlock", CallName: "munlock", Args: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "addr", TypeSize: 0}}}, + &Call{ID: 58, Name: "mlockall", CallName: "mlockall", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2}}}}, + &Call{ID: 59, Name: "munlockall", CallName: "munlockall", Args: []Type{}}, + &Call{ID: 60, Name: "unshare", CallName: "unshare", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2097152, 16777216, 1024, 512, 2147483648, 134217728, 1073741824, 131072, 536870912, 67108864, 32768, 1048576, 8192, 524288, 2048, 262144, 65536, 8388608, 16384, 256}}}}, + &Call{ID: 61, Name: "kcmp", CallName: "kcmp", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid1", IsOptional: false}, Kind: ResPid}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid2", IsOptional: false}, Kind: ResPid}, FlagsType{TypeCommon: TypeCommon{TypeName: "type", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 2, 3, 5, 4, 6, 1}}, ResourceType{TypeCommon: TypeCommon{TypeName: "fd1", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, ResourceType{TypeCommon: TypeCommon{TypeName: "fd2", IsOptional: false}, Kind: ResFD, Subkind: ResAny}}}, + &Call{ID: 62, Name: "futex", CallName: "futex", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 4}, Dir: DirIn}, FlagsType{TypeCommon: TypeCommon{TypeName: "op", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 9, 1, 3, 4}}, IntType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "timeout", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "addr2", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 4}, Dir: DirIn}, IntType{TypeCommon: TypeCommon{TypeName: "val3", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 63, Name: "set_robust_list", CallName: "set_robust_list", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "head", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "robust_list", IsOptional: false}, Fields: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "next", IsOptional: false}}, IntType{TypeCommon: TypeCommon{TypeName: "off", IsOptional: false}, TypeSize: 8}, VmaType{TypeCommon: TypeCommon{TypeName: "pend", IsOptional: false}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "head", TypeSize: 0}}}, + &Call{ID: 64, Name: "get_robust_list", CallName: "get_robust_list", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, PtrType{TypeCommon: TypeCommon{TypeName: "head", IsOptional: false}, Type: PtrType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "robust_list", IsOptional: false}, Fields: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "next", IsOptional: false}}, IntType{TypeCommon: TypeCommon{TypeName: "off", IsOptional: false}, TypeSize: 8}, VmaType{TypeCommon: TypeCommon{TypeName: "pend", IsOptional: false}}}}, Dir: DirOut}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Type: LenType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Buf: "head", TypeSize: 8}, Dir: DirInOut}}}, + &Call{ID: 65, Name: "restart_syscall", CallName: "restart_syscall", Args: []Type{}}, + &Call{ID: 66, Name: "socket", CallName: "socket", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "domain", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 10, 4, 16, 9, 3, 8, 5, 17}}, FlagsType{TypeCommon: TypeCommon{TypeName: "type", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 5, 3, 4, 10, 2048, 524288}}, IntType{TypeCommon: TypeCommon{TypeName: "proto", IsOptional: false}, TypeSize: 1}}}, + &Call{ID: 67, Name: "socketpair", CallName: "socketpair", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "domain", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 10, 4, 16, 9, 3, 8, 5, 17}}, FlagsType{TypeCommon: TypeCommon{TypeName: "type", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 5, 3, 4, 10, 2048, 524288}}, IntType{TypeCommon: TypeCommon{TypeName: "proto", IsOptional: false}, TypeSize: 1}, PtrType{TypeCommon: TypeCommon{TypeName: "fds", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "pipefd", IsOptional: false}, Fields: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "rfd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, ResourceType{TypeCommon: TypeCommon{TypeName: "wfd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}}}, Dir: DirOut}}}, + &Call{ID: 68, Name: "accept", CallName: "accept", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, PtrType{TypeCommon: TypeCommon{TypeName: "peer", IsOptional: true}, Type: BufferType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: BufferSockaddr}, Dir: DirOut}, PtrType{TypeCommon: TypeCommon{TypeName: "peerlen", IsOptional: false}, Type: LenType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Buf: "peer", TypeSize: 4}, Dir: DirInOut}}}, + &Call{ID: 69, Name: "accept4", CallName: "accept4", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, PtrType{TypeCommon: TypeCommon{TypeName: "peer", IsOptional: true}, Type: BufferType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: BufferSockaddr}, Dir: DirOut}, PtrType{TypeCommon: TypeCommon{TypeName: "peerlen", IsOptional: false}, Type: LenType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Buf: "peer", TypeSize: 4}, Dir: DirInOut}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2048, 524288}}}}, + &Call{ID: 70, Name: "bind", CallName: "bind", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Type: BufferType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: BufferSockaddr}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "addrlen", IsOptional: false}, Buf: "addr", TypeSize: 0}}}, + &Call{ID: 71, Name: "listen", CallName: "listen", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, IntType{TypeCommon: TypeCommon{TypeName: "backlog", IsOptional: false}, TypeSize: 4}}}, + &Call{ID: 72, Name: "connect", CallName: "connect", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Type: BufferType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: BufferSockaddr}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "addrlen", IsOptional: false}, Buf: "addr", TypeSize: 0}}}, + &Call{ID: 73, Name: "shutdown", CallName: "shutdown", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, FlagsType{TypeCommon: TypeCommon{TypeName: "how", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1}}}}, + &Call{ID: 74, Name: "sendto", CallName: "sendto", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "buf", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "f", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2048, 4, 64, 128, 32768, 16384, 1}}, PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: true}, Type: BufferType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: BufferSockaddr}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "addrlen", IsOptional: false}, Buf: "addr", TypeSize: 0}}}, + &Call{ID: 75, Name: "sendmsg", CallName: "sendmsg", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, PtrType{TypeCommon: TypeCommon{TypeName: "msg", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "send_msghdr", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Type: BufferType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: BufferSockaddr}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "addrlen", IsOptional: false}, Buf: "addr", TypeSize: 4}, PtrType{TypeCommon: TypeCommon{TypeName: "vec", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_in", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "vlen", IsOptional: false}, Buf: "vec", TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "ctrl", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "cmsghdr", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "level", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "type", IsOptional: false}, TypeSize: 4}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "ctrllen", IsOptional: false}, Buf: "ctrl", TypeSize: 8}, FlagsType{TypeCommon: TypeCommon{TypeName: "f", IsOptional: false}, TypeSize: 4, Vals: []uintptr{2048, 4, 64, 128, 32768, 16384, 1}}, IntType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, TypeSize: 4}}}, Dir: DirIn}, FlagsType{TypeCommon: TypeCommon{TypeName: "f", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2048, 4, 64, 128, 32768, 16384, 1}}}}, + &Call{ID: 76, Name: "sendmmsg", CallName: "sendmmsg", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, PtrType{TypeCommon: TypeCommon{TypeName: "mmsg", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "send_msghdr", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Type: BufferType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: BufferSockaddr}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "addrlen", IsOptional: false}, Buf: "addr", TypeSize: 4}, PtrType{TypeCommon: TypeCommon{TypeName: "vec", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_in", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "vlen", IsOptional: false}, Buf: "vec", TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "ctrl", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "cmsghdr", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "level", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "type", IsOptional: false}, TypeSize: 4}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "ctrllen", IsOptional: false}, Buf: "ctrl", TypeSize: 8}, FlagsType{TypeCommon: TypeCommon{TypeName: "f", IsOptional: false}, TypeSize: 4, Vals: []uintptr{2048, 4, 64, 128, 32768, 16384, 1}}, IntType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, TypeSize: 4}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "vlen", IsOptional: false}, Buf: "mmsg", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "f", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2048, 4, 64, 128, 32768, 16384, 1}}}}, + &Call{ID: 77, Name: "recvfrom", CallName: "recvfrom", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "buf", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "f", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1073741824, 64, 8192, 1, 2, 32, 256, 65536}}, PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: true}, Type: BufferType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: BufferSockaddr}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "addrlen", IsOptional: false}, Buf: "addr", TypeSize: 0}}}, + &Call{ID: 78, Name: "recvmsg", CallName: "recvmsg", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, PtrType{TypeCommon: TypeCommon{TypeName: "msg", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "recv_msghdr", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Type: BufferType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: BufferSockaddr}, Dir: DirOut}, LenType{TypeCommon: TypeCommon{TypeName: "addrlen", IsOptional: false}, Buf: "addr", TypeSize: 4}, PtrType{TypeCommon: TypeCommon{TypeName: "vec", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_out", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "vlen", IsOptional: false}, Buf: "vec", TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "ctrl", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "ctrl", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "ctrllen", IsOptional: false}, Buf: "ctrl", TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "f", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, TypeSize: 4}}}, Dir: DirIn}, FlagsType{TypeCommon: TypeCommon{TypeName: "f", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1073741824, 64, 8192, 1, 2, 32, 256, 65536}}}}, + &Call{ID: 79, Name: "recvmmsg", CallName: "recvmmsg", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, PtrType{TypeCommon: TypeCommon{TypeName: "mmsg", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "recv_msghdr", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Type: BufferType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: BufferSockaddr}, Dir: DirOut}, LenType{TypeCommon: TypeCommon{TypeName: "addrlen", IsOptional: false}, Buf: "addr", TypeSize: 4}, PtrType{TypeCommon: TypeCommon{TypeName: "vec", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_out", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "vlen", IsOptional: false}, Buf: "vec", TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "ctrl", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "ctrl", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "ctrllen", IsOptional: false}, Buf: "ctrl", TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "f", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, TypeSize: 4}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "vlen", IsOptional: false}, Buf: "mmsg", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "f", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1073741824, 64, 8192, 1, 2, 32, 256, 65536}}}}, + &Call{ID: 80, Name: "getsockname", CallName: "getsockname", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Type: BufferType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: BufferSockaddr}, Dir: DirOut}, PtrType{TypeCommon: TypeCommon{TypeName: "addrlen", IsOptional: false}, Type: LenType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Buf: "addr", TypeSize: 4}, Dir: DirInOut}}}, + &Call{ID: 81, Name: "getpeername", CallName: "getpeername", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, PtrType{TypeCommon: TypeCommon{TypeName: "peer", IsOptional: false}, Type: BufferType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: BufferSockaddr}, Dir: DirOut}, PtrType{TypeCommon: TypeCommon{TypeName: "peerlen", IsOptional: false}, Type: LenType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Buf: "peer", TypeSize: 4}, Dir: DirInOut}}}, + &Call{ID: 82, Name: "getsockopt", CallName: "getsockopt", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, IntType{TypeCommon: TypeCommon{TypeName: "level", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "optname", IsOptional: false}, TypeSize: 4}, PtrType{TypeCommon: TypeCommon{TypeName: "optval", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "ioctl_arg", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "a0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a7", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}, PtrType{TypeCommon: TypeCommon{TypeName: "optlen", IsOptional: false}, Type: LenType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Buf: "optval", TypeSize: 4}, Dir: DirInOut}}}, + &Call{ID: 83, Name: "setsockopt", CallName: "setsockopt", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdSock}, IntType{TypeCommon: TypeCommon{TypeName: "level", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "optname", IsOptional: false}, TypeSize: 4}, PtrType{TypeCommon: TypeCommon{TypeName: "optval", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "ioctl_arg", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "a0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a7", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "optlen", IsOptional: false}, Buf: "optval", TypeSize: 0}}}, + &Call{ID: 84, Name: "ioctl", CallName: "ioctl", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, IntType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 4}, PtrType{TypeCommon: TypeCommon{TypeName: "arg", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "ioctl_arg", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "a0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a7", IsOptional: false}, TypeSize: 8}}}, Dir: DirInOut}}}, + &Call{ID: 85, Name: "fcntl$dupfd", CallName: "fcntl", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1030}}, ResourceType{TypeCommon: TypeCommon{TypeName: "arg", IsOptional: false}, Kind: ResFD, Subkind: ResAny}}}, + &Call{ID: 86, Name: "fcntl$getflags", CallName: "fcntl", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 3, 11, 1025, 1032}}}}, + &Call{ID: 87, Name: "fcntl$setflags", CallName: "fcntl", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1}}}}, + &Call{ID: 88, Name: "fcntl$setstatus", CallName: "fcntl", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 0, Vals: []uintptr{4}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1024, 8192, 16384, 262144, 2048}}}}, + &Call{ID: 89, Name: "fcntl$lock", CallName: "fcntl", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 0, Vals: []uintptr{6, 7, 5}}, PtrType{TypeCommon: TypeCommon{TypeName: "lock", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "flock", IsOptional: false}, Fields: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "type", IsOptional: false}, TypeSize: 2, Vals: []uintptr{0, 1, 2}}, FlagsType{TypeCommon: TypeCommon{TypeName: "whence", IsOptional: false}, TypeSize: 2, Vals: []uintptr{0, 1, 2, 3, 4}}, IntType{TypeCommon: TypeCommon{TypeName: "start", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, TypeSize: 8}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}}}, Dir: DirIn}}}, + &Call{ID: 90, Name: "fcntl$getown", CallName: "fcntl", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResPid}, Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 0, Vals: []uintptr{9}}}}, + &Call{ID: 91, Name: "fcntl$setown", CallName: "fcntl", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 0, Vals: []uintptr{8}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}}}, + &Call{ID: 92, Name: "fcntl$getownex", CallName: "fcntl", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 0, Vals: []uintptr{16}}, PtrType{TypeCommon: TypeCommon{TypeName: "arg", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "f_owner_ex", IsOptional: false}, Fields: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "type", IsOptional: false}, TypeSize: 4, Vals: []uintptr{0, 1, 2}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}}}, Dir: DirOut}}}, + &Call{ID: 93, Name: "fcntl$setownex", CallName: "fcntl", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 0, Vals: []uintptr{15}}, PtrType{TypeCommon: TypeCommon{TypeName: "arg", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "f_owner_ex", IsOptional: false}, Fields: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "type", IsOptional: false}, TypeSize: 4, Vals: []uintptr{0, 1, 2}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}}}, Dir: DirIn}}}, + &Call{ID: 94, Name: "fcntl$setsig", CallName: "fcntl", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 0, Vals: []uintptr{10}}, IntType{TypeCommon: TypeCommon{TypeName: "sig", IsOptional: false}, TypeSize: 4, Limit: 130}}}, + &Call{ID: 95, Name: "fcntl$setlease", CallName: "fcntl", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1024}}, FlagsType{TypeCommon: TypeCommon{TypeName: "typ", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2}}}}, + &Call{ID: 96, Name: "fcntl$notify", CallName: "fcntl", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2147483648, 1, 2, 4, 8, 16, 32}}, FlagsType{TypeCommon: TypeCommon{TypeName: "typ", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2147483648, 1, 2, 4, 8, 16, 32}}}}, + &Call{ID: 97, Name: "fcntl$setpipe", CallName: "fcntl", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1031}}, IntType{TypeCommon: TypeCommon{TypeName: "sz", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 98, Name: "ptrace", CallName: "ptrace", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "req", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 16904, 8, 16903, 16, 17}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}}}, + &Call{ID: 99, Name: "ptrace$peek", CallName: "ptrace", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "req", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 8}, Dir: DirOut}}}, + &Call{ID: 100, Name: "ptrace$poke", CallName: "ptrace", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "req", IsOptional: false}, TypeSize: 0, Vals: []uintptr{4, 5}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 8}, Dir: DirOut}, IntType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 101, Name: "ptrace$peekuser", CallName: "ptrace", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "req", IsOptional: false}, TypeSize: 0, Vals: []uintptr{3}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 102, Name: "ptrace$pokeuser", CallName: "ptrace", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "req", IsOptional: false}, TypeSize: 0, Vals: []uintptr{3}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 103, Name: "ptrace$getregs", CallName: "ptrace", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "req", IsOptional: false}, TypeSize: 0, Vals: []uintptr{12, 14}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "ignored", IsOptional: false}, TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, Kind: BufferBlob}}}}, + &Call{ID: 104, Name: "ptrace$getregset", CallName: "ptrace", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "req", IsOptional: false}, TypeSize: 0, Vals: []uintptr{16900}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, FlagsType{TypeCommon: TypeCommon{TypeName: "what", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 3, 4, 6, 512, 513, 514}}, PtrType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_out", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}, Dir: DirIn}}}, + &Call{ID: 105, Name: "ptrace$setregs", CallName: "ptrace", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "req", IsOptional: false}, TypeSize: 0, Vals: []uintptr{13, 15}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "ignored", IsOptional: false}, TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, Kind: BufferBlob}}}}, + &Call{ID: 106, Name: "ptrace$setregset", CallName: "ptrace", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "req", IsOptional: false}, TypeSize: 0, Vals: []uintptr{16901}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, FlagsType{TypeCommon: TypeCommon{TypeName: "what", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 3, 4, 6, 512, 513, 514}}, PtrType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_in", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}, Dir: DirIn}}}, + &Call{ID: 107, Name: "ptrace$getsig", CallName: "ptrace", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "req", IsOptional: false}, TypeSize: 0, Vals: []uintptr{16898}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "ignored", IsOptional: false}, TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "siginfo", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "signo", IsOptional: false}, TypeSize: 4, Limit: 130}, IntType{TypeCommon: TypeCommon{TypeName: "errno", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "code", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "pad3", IsOptional: false}, TypeSize: 4}}}, Dir: DirOut}}}, + &Call{ID: 108, Name: "ptrace$setsig", CallName: "ptrace", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "req", IsOptional: false}, TypeSize: 0, Vals: []uintptr{16899}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "ignored", IsOptional: false}, TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "siginfo", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "signo", IsOptional: false}, TypeSize: 4, Limit: 130}, IntType{TypeCommon: TypeCommon{TypeName: "errno", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "code", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "pad3", IsOptional: false}, TypeSize: 4}}}, Dir: DirIn}}}, + &Call{ID: 109, Name: "ptrace$setopts", CallName: "ptrace", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "req", IsOptional: false}, TypeSize: 0, Vals: []uintptr{16896, 16902}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "ignored", IsOptional: false}, TypeSize: 8}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1048576, 8, 16, 64, 2, 1, 4, 32}}}}, + &Call{ID: 110, Name: "ptrace$getenv", CallName: "ptrace", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "req", IsOptional: false}, TypeSize: 0, Vals: []uintptr{16897}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "ignored", IsOptional: false}, TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 8}, Dir: DirOut}}}, + &Call{ID: 111, Name: "ptrace$cont", CallName: "ptrace", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "req", IsOptional: false}, TypeSize: 0, Vals: []uintptr{7, 24, 9, 31, 32}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "ignored", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 112, Name: "io_setup", CallName: "io_setup", Args: []Type{IntType{TypeCommon: TypeCommon{TypeName: "n", IsOptional: false}, TypeSize: 4}, PtrType{TypeCommon: TypeCommon{TypeName: "ctx", IsOptional: false}, Type: ResourceType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: ResIOCtx}, Dir: DirOut}}}, + &Call{ID: 113, Name: "io_destroy", CallName: "io_destroy", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "ctx", IsOptional: false}, Kind: ResIOCtx}}}, + &Call{ID: 114, Name: "io_getevents", CallName: "io_getevents", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "ctx", IsOptional: false}, Kind: ResIOCtx}, IntType{TypeCommon: TypeCommon{TypeName: "min_nr", IsOptional: false}, TypeSize: 8}, LenType{TypeCommon: TypeCommon{TypeName: "nr", IsOptional: false}, Buf: "events", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "events", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "io_event", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "obj", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "res", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "res2", IsOptional: false}, TypeSize: 4}}}}, Dir: DirOut}, PtrType{TypeCommon: TypeCommon{TypeName: "timeout", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}}}, + &Call{ID: 115, Name: "io_submit", CallName: "io_submit", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "ctx", IsOptional: false}, Kind: ResIOCtx}, LenType{TypeCommon: TypeCommon{TypeName: "nr", IsOptional: false}, Buf: "iocbpp", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "iocbpp", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: PtrType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iocb", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "key", IsOptional: false}, TypeSize: 8}, FlagsType{TypeCommon: TypeCommon{TypeName: "op", IsOptional: false}, TypeSize: 2, Vals: []uintptr{0, 1, 2, 3, 4, 5, 6, 7, 8}}, IntType{TypeCommon: TypeCommon{TypeName: "prio", IsOptional: false}, TypeSize: 2}, ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Dir: DirInOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "nbytes", IsOptional: false}, Buf: "buf", TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "offset", IsOptional: false}, TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "reserv", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigevent", IsOptional: false}, Fields: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}}, IntType{TypeCommon: TypeCommon{TypeName: "signo", IsOptional: false}, TypeSize: 4, Limit: 130}, FlagsType{TypeCommon: TypeCommon{TypeName: "notify", IsOptional: false}, TypeSize: 4, Vals: []uintptr{1, 0, 2}}, IntType{TypeCommon: TypeCommon{TypeName: "pad0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad7", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 4, Vals: []uintptr{1}}, ResourceType{TypeCommon: TypeCommon{TypeName: "resfd", IsOptional: false}, Kind: ResFD, Subkind: FdEvent}}}, Dir: DirIn}}, Dir: DirIn}}}, + &Call{ID: 116, Name: "io_cancel", CallName: "io_cancel", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "ctx", IsOptional: false}, Kind: ResIOCtx}, PtrType{TypeCommon: TypeCommon{TypeName: "iocb", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iocb", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "key", IsOptional: false}, TypeSize: 8}, FlagsType{TypeCommon: TypeCommon{TypeName: "op", IsOptional: false}, TypeSize: 2, Vals: []uintptr{0, 1, 2, 3, 4, 5, 6, 7, 8}}, IntType{TypeCommon: TypeCommon{TypeName: "prio", IsOptional: false}, TypeSize: 2}, ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Dir: DirInOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "nbytes", IsOptional: false}, Buf: "buf", TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "offset", IsOptional: false}, TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "reserv", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigevent", IsOptional: false}, Fields: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}}, IntType{TypeCommon: TypeCommon{TypeName: "signo", IsOptional: false}, TypeSize: 4, Limit: 130}, FlagsType{TypeCommon: TypeCommon{TypeName: "notify", IsOptional: false}, TypeSize: 4, Vals: []uintptr{1, 0, 2}}, IntType{TypeCommon: TypeCommon{TypeName: "pad0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad7", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 4, Vals: []uintptr{1}}, ResourceType{TypeCommon: TypeCommon{TypeName: "resfd", IsOptional: false}, Kind: ResFD, Subkind: FdEvent}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "res", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "io_event", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "obj", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "res", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "res2", IsOptional: false}, TypeSize: 4}}}, Dir: DirOut}}}, + &Call{ID: 117, Name: "capget", CallName: "capget", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "hdr", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "cap_header", IsOptional: false}, Fields: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "var", IsOptional: false}, TypeSize: 4, Vals: []uintptr{429392688, 537333798, 537396514}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "cap_data", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "eff0", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "perm0", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "inher0", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "eff1", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "perm1", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "inher1", IsOptional: false}, TypeSize: 4}}}, Dir: DirIn}}}, + &Call{ID: 118, Name: "capset", CallName: "capset", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "hdr", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "cap_header", IsOptional: false}, Fields: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "var", IsOptional: false}, TypeSize: 4, Vals: []uintptr{429392688, 537333798, 537396514}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "cap_data", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "eff0", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "perm0", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "inher0", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "eff1", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "perm1", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "inher1", IsOptional: false}, TypeSize: 4}}}, Dir: DirIn}}}, + &Call{ID: 119, Name: "prctl", CallName: "prctl", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "option", IsOptional: false}, TypeSize: 0, Vals: []uintptr{23, 24, 36, 37, 4, 3, 20, 19, 10, 9, 12, 11, 8, 7, 15, 16, 38, 39, 1, 2, 1499557217, 22, 21, 28, 27, 40, 29, 30, 14, 13, 31, 32, 26, 25, 6, 5, 33, 34, 35}}, IntType{TypeCommon: TypeCommon{TypeName: "arg2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "arg3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "arg4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "arg5", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 120, Name: "arch_prctl", CallName: "arch_prctl", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "code", IsOptional: false}, TypeSize: 0, Vals: []uintptr{4098, 4099, 4097, 4100}}, PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "ioctl_arg", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "a0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "a7", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}}}, + &Call{ID: 121, Name: "seccomp", CallName: "seccomp", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "op", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1}}, PtrType{TypeCommon: TypeCommon{TypeName: "prog", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sock_fprog", IsOptional: false}, Fields: []Type{LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "filter", TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "filter", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sock_filter", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "code", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "jt", IsOptional: false}, TypeSize: 1}, IntType{TypeCommon: TypeCommon{TypeName: "kf", IsOptional: false}, TypeSize: 1}, IntType{TypeCommon: TypeCommon{TypeName: "k", IsOptional: false}, TypeSize: 4}}}}, Dir: DirIn}}}, Dir: DirIn}}}, + &Call{ID: 122, Name: "add_key", CallName: "add_key", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResKey}, Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "type", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "type", IsOptional: false}, Kind: BufferString}}, PtrType{TypeCommon: TypeCommon{TypeName: "desc", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "desc", IsOptional: false}, Kind: BufferString}}, PtrType{TypeCommon: TypeCommon{TypeName: "payload", IsOptional: true}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "payload", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "paylen", IsOptional: false}, Buf: "payload", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "keyring", IsOptional: false}, TypeSize: 0, Vals: []uintptr{18446744073709551615, 18446744073709551614, 18446744073709551613, 18446744073709551612, 18446744073709551611}}}}, + &Call{ID: 123, Name: "request_key", CallName: "request_key", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResKey}, Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "type", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "type", IsOptional: false}, Kind: BufferString}}, PtrType{TypeCommon: TypeCommon{TypeName: "desc", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "desc", IsOptional: false}, Kind: BufferString}}, PtrType{TypeCommon: TypeCommon{TypeName: "callout", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "callout", IsOptional: false}, Kind: BufferString}}, FlagsType{TypeCommon: TypeCommon{TypeName: "keyring", IsOptional: false}, TypeSize: 0, Vals: []uintptr{18446744073709551615, 18446744073709551614, 18446744073709551613, 18446744073709551612, 18446744073709551611}}}}, + &Call{ID: 124, Name: "keyctl", CallName: "keyctl", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "code", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}, ResourceType{TypeCommon: TypeCommon{TypeName: "key", IsOptional: false}, Kind: ResKey}, PtrType{TypeCommon: TypeCommon{TypeName: "arg2", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "arg2", IsOptional: false}, Kind: BufferString}}, IntType{TypeCommon: TypeCommon{TypeName: "arg3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "arg4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "arg5", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 125, Name: "mq_open", CallName: "mq_open", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: FdMq}, Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Kind: BufferString}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2, 2048, 64, 128, 64}}, FlagsType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 0, Vals: []uintptr{256, 128, 64, 32, 16, 8, 4, 2, 1}}, PtrType{TypeCommon: TypeCommon{TypeName: "attr", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "mq_attr", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "maxmsg", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "msgsize", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "curmsg", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "res0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "res1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "res2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "res3", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}}}, + &Call{ID: 126, Name: "mq_timedsend", CallName: "mq_timedsend", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "mqd", IsOptional: false}, Kind: ResFD, Subkind: FdMq}, PtrType{TypeCommon: TypeCommon{TypeName: "msg", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "msg", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "msglen", IsOptional: false}, Buf: "msg", TypeSize: 0}, IntType{TypeCommon: TypeCommon{TypeName: "prio", IsOptional: false}, TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "timeout", IsOptional: true}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}}}, + &Call{ID: 127, Name: "mq_timedreceive", CallName: "mq_timedreceive", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "mqd", IsOptional: false}, Kind: ResFD, Subkind: FdMq}, PtrType{TypeCommon: TypeCommon{TypeName: "msg", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "msg", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "msglen", IsOptional: false}, Buf: "msg", TypeSize: 0}, IntType{TypeCommon: TypeCommon{TypeName: "prio", IsOptional: false}, TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "timeout", IsOptional: true}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}}}, + &Call{ID: 128, Name: "mq_notify", CallName: "mq_notify", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "mqd", IsOptional: false}, Kind: ResFD, Subkind: FdMq}, PtrType{TypeCommon: TypeCommon{TypeName: "notif", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigevent", IsOptional: false}, Fields: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}}, IntType{TypeCommon: TypeCommon{TypeName: "signo", IsOptional: false}, TypeSize: 4, Limit: 130}, FlagsType{TypeCommon: TypeCommon{TypeName: "notify", IsOptional: false}, TypeSize: 4, Vals: []uintptr{1, 0, 2}}, IntType{TypeCommon: TypeCommon{TypeName: "pad0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad7", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}}}, + &Call{ID: 129, Name: "mq_getsetattr", CallName: "mq_getsetattr", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "mqd", IsOptional: false}, Kind: ResFD, Subkind: FdMq}, PtrType{TypeCommon: TypeCommon{TypeName: "attr", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "mq_attr", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "maxmsg", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "msgsize", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "curmsg", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "res0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "res1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "res2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "res3", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "oldattr", IsOptional: true}, Type: StructType{TypeCommon: TypeCommon{TypeName: "mq_attr", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "maxmsg", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "msgsize", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "curmsg", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "res0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "res1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "res2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "res3", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}}}, + &Call{ID: 130, Name: "mq_unlink", CallName: "mq_unlink", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Kind: BufferString}}}}, + &Call{ID: 131, Name: "msgget", CallName: "msgget", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResIPC, Subkind: IPCMsq}, Args: []Type{IntType{TypeCommon: TypeCommon{TypeName: "key", IsOptional: false}, TypeSize: 4}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{512, 1024, 256, 128, 64, 32, 16, 8, 4, 2, 1}}}}, + &Call{ID: 132, Name: "msgsnd", CallName: "msgsnd", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "msqid", IsOptional: false}, Kind: ResIPC, Subkind: IPCMsq}, PtrType{TypeCommon: TypeCommon{TypeName: "msgp", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "msgp", IsOptional: false}, Kind: BufferBlob}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2048, 8192, 4096}}}}, + &Call{ID: 133, Name: "msgrcv", CallName: "msgrcv", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "msqid", IsOptional: false}, Kind: ResIPC, Subkind: IPCMsq}, PtrType{TypeCommon: TypeCommon{TypeName: "msgp", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "msgp", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "sz", IsOptional: false}, Buf: "msgp", TypeSize: 0}, IntType{TypeCommon: TypeCommon{TypeName: "typ", IsOptional: false}, TypeSize: 8}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2048, 8192, 4096}}}}, + &Call{ID: 134, Name: "msgctl", CallName: "msgctl", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "msqid", IsOptional: false}, Kind: ResIPC, Subkind: IPCMsq}, FlagsType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2, 1, 0, 3, 12, 11}}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "msqid_ds", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "key", IsOptional: false}, TypeSize: 4}, ResourceType{TypeCommon: TypeCommon{TypeName: "uid", IsOptional: false}, Kind: ResUid}, ResourceType{TypeCommon: TypeCommon{TypeName: "gid", IsOptional: false}, Kind: ResGid}, ResourceType{TypeCommon: TypeCommon{TypeName: "cuid", IsOptional: false}, Kind: ResUid}, ResourceType{TypeCommon: TypeCommon{TypeName: "cgid", IsOptional: false}, Kind: ResGid}, IntType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "seq", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "stime", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "rtime", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "ctime", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "cbytes", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "qnum", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "qbytes", IsOptional: false}, TypeSize: 8}, ResourceType{TypeCommon: TypeCommon{TypeName: "lspid", IsOptional: false}, Kind: ResPid}, ResourceType{TypeCommon: TypeCommon{TypeName: "lrpid", IsOptional: false}, Kind: ResPid}}}, Dir: DirInOut}}}, + &Call{ID: 135, Name: "semget", CallName: "semget", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResIPC, Subkind: IPCSem}, Args: []Type{IntType{TypeCommon: TypeCommon{TypeName: "key", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "nsems", IsOptional: false}, TypeSize: 8}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{512, 1024, 256, 128, 64, 32, 16, 8, 4, 2, 1}}}}, + &Call{ID: 136, Name: "semop", CallName: "semop", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "semid", IsOptional: false}, Kind: ResIPC, Subkind: IPCSem}, PtrType{TypeCommon: TypeCommon{TypeName: "ops", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sembuf", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "num", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "op", IsOptional: false}, TypeSize: 2}, FlagsType{TypeCommon: TypeCommon{TypeName: "flg", IsOptional: false}, TypeSize: 8, Vals: []uintptr{2048, 4096}}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "nops", IsOptional: false}, Buf: "ops", TypeSize: 0}}}, + &Call{ID: 137, Name: "semtimedop", CallName: "semtimedop", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "semid", IsOptional: false}, Kind: ResIPC, Subkind: IPCSem}, PtrType{TypeCommon: TypeCommon{TypeName: "ops", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sembuf", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "num", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "op", IsOptional: false}, TypeSize: 2}, FlagsType{TypeCommon: TypeCommon{TypeName: "flg", IsOptional: false}, TypeSize: 8, Vals: []uintptr{2048, 4096}}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "nops", IsOptional: false}, Buf: "ops", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "timeout", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}}}, + &Call{ID: 138, Name: "semctl", CallName: "semctl", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "semid", IsOptional: false}, Kind: ResIPC, Subkind: IPCSem}, IntType{TypeCommon: TypeCommon{TypeName: "semnum", IsOptional: false}, TypeSize: 8}, FlagsType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2, 1, 0, 3, 19, 18, 13, 14, 11, 12, 15, 17, 16}}, PtrType{TypeCommon: TypeCommon{TypeName: "arg", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "semid_ds", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "key", IsOptional: false}, TypeSize: 4}, ResourceType{TypeCommon: TypeCommon{TypeName: "uid", IsOptional: false}, Kind: ResUid}, ResourceType{TypeCommon: TypeCommon{TypeName: "gid", IsOptional: false}, Kind: ResGid}, ResourceType{TypeCommon: TypeCommon{TypeName: "cuid", IsOptional: false}, Kind: ResUid}, ResourceType{TypeCommon: TypeCommon{TypeName: "cgid", IsOptional: false}, Kind: ResGid}, IntType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "seq", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "otime", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "ctime", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsems", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}}}, + &Call{ID: 139, Name: "shmget", CallName: "shmget", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResIPC, Subkind: IPCShm}, Args: []Type{IntType{TypeCommon: TypeCommon{TypeName: "key", IsOptional: false}, TypeSize: 4}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "unused", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{512, 1024, 2048, 4096, 256, 128, 64, 32, 16, 8, 4, 2, 1}}, VmaType{TypeCommon: TypeCommon{TypeName: "unused", IsOptional: false}}}}, + &Call{ID: 140, Name: "shmat", CallName: "shmat", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "shmid", IsOptional: false}, Kind: ResIPC, Subkind: IPCShm}, VmaType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{8192, 4096, 16384}}}}, + &Call{ID: 141, Name: "shmctl", CallName: "shmctl", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "shmid", IsOptional: false}, Kind: ResIPC, Subkind: IPCShm}, FlagsType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2, 1, 0, 3, 14, 13, 11, 12}}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "shmid_ds", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "key", IsOptional: false}, TypeSize: 4}, ResourceType{TypeCommon: TypeCommon{TypeName: "uid", IsOptional: false}, Kind: ResUid}, ResourceType{TypeCommon: TypeCommon{TypeName: "gid", IsOptional: false}, Kind: ResGid}, ResourceType{TypeCommon: TypeCommon{TypeName: "cuid", IsOptional: false}, Kind: ResUid}, ResourceType{TypeCommon: TypeCommon{TypeName: "cgid", IsOptional: false}, Kind: ResGid}, IntType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "seq", IsOptional: false}, TypeSize: 2}, IntType{TypeCommon: TypeCommon{TypeName: "segsz", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "atime", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "atime", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "dtime", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "ctime", IsOptional: false}, TypeSize: 8}, ResourceType{TypeCommon: TypeCommon{TypeName: "cpid", IsOptional: false}, Kind: ResPid}, ResourceType{TypeCommon: TypeCommon{TypeName: "lpid", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "nattch", IsOptional: false}, TypeSize: 8}}}, Dir: DirInOut}}}, + &Call{ID: 142, Name: "shmdt", CallName: "shmdt", Args: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}}}}, + &Call{ID: 143, Name: "mknod", CallName: "mknod", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}}}, FlagsType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 0, Vals: []uintptr{32768, 8192, 24576, 4096, 49152, 256, 128, 64, 32, 16, 8, 4, 2, 1}}, IntType{TypeCommon: TypeCommon{TypeName: "dev", IsOptional: false}, TypeSize: 4}}}, + &Call{ID: 144, Name: "mknodat", CallName: "mknodat", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "dirfd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}}}, FlagsType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 0, Vals: []uintptr{32768, 8192, 24576, 4096, 49152, 256, 128, 64, 32, 16, 8, 4, 2, 1}}, IntType{TypeCommon: TypeCommon{TypeName: "dev", IsOptional: false}, TypeSize: 4}}}, + &Call{ID: 145, Name: "chmod", CallName: "chmod", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}}}, FlagsType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 0, Vals: []uintptr{256, 128, 64, 32, 16, 8, 4, 2, 1}}}}, + &Call{ID: 146, Name: "fchmod", CallName: "fchmod", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 0, Vals: []uintptr{256, 128, 64, 32, 16, 8, 4, 2, 1}}}}, + &Call{ID: 147, Name: "fchmodat", CallName: "fchmodat", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "dirfd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}}}, FlagsType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 0, Vals: []uintptr{256, 128, 64, 32, 16, 8, 4, 2, 1}}}}, + &Call{ID: 148, Name: "chown", CallName: "chown", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}}}, ResourceType{TypeCommon: TypeCommon{TypeName: "uid", IsOptional: false}, Kind: ResUid}, ResourceType{TypeCommon: TypeCommon{TypeName: "gid", IsOptional: false}, Kind: ResGid}}}, + &Call{ID: 149, Name: "lchown", CallName: "lchown", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}}}, ResourceType{TypeCommon: TypeCommon{TypeName: "uid", IsOptional: false}, Kind: ResUid}, ResourceType{TypeCommon: TypeCommon{TypeName: "gid", IsOptional: false}, Kind: ResGid}}}, + &Call{ID: 150, Name: "fchown", CallName: "fchown", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, ResourceType{TypeCommon: TypeCommon{TypeName: "uid", IsOptional: false}, Kind: ResUid}, ResourceType{TypeCommon: TypeCommon{TypeName: "gid", IsOptional: false}, Kind: ResGid}}}, + &Call{ID: 151, Name: "fchownat", CallName: "fchownat", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "dirfd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}}}, ResourceType{TypeCommon: TypeCommon{TypeName: "uid", IsOptional: false}, Kind: ResUid}, ResourceType{TypeCommon: TypeCommon{TypeName: "gid", IsOptional: false}, Kind: ResGid}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{4096, 256}}}}, + &Call{ID: 152, Name: "fallocate", CallName: "fallocate", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2}}, IntType{TypeCommon: TypeCommon{TypeName: "off", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 153, Name: "faccessat", CallName: "faccessat", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "dirfd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "pathname", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "pathname", IsOptional: false}}}, FlagsType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 0, Vals: []uintptr{256, 128, 64, 32, 16, 8, 4, 2, 1}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{512, 256}}}}, + &Call{ID: 154, Name: "utime", CallName: "utime", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "filename", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "filename", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "times", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "utimbuf", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "actime", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "modtime", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}}}, + &Call{ID: 155, Name: "utimes", CallName: "utimes", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "filename", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "filename", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "times", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "itimerval", IsOptional: false}, Fields: []Type{StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}, StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}}}, Dir: DirIn}}}, + &Call{ID: 156, Name: "futimesat", CallName: "futimesat", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "dir", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "pathname", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "pathname", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "times", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "itimerval", IsOptional: false}, Fields: []Type{StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}, StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}}}, Dir: DirIn}}}, + &Call{ID: 157, Name: "utimensat", CallName: "utimensat", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "dir", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "pathname", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "pathname", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "times", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "itimerval", IsOptional: false}, Fields: []Type{StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}, StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}}}, Dir: DirIn}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 256}}}}, + &Call{ID: 158, Name: "getgid", CallName: "getgid", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResGid}, Args: []Type{}}, + &Call{ID: 159, Name: "getegid", CallName: "getegid", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResGid}, Args: []Type{}}, + &Call{ID: 160, Name: "setuid", CallName: "setuid", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "uid", IsOptional: false}, Kind: ResUid}}}, + &Call{ID: 161, Name: "setgid", CallName: "setgid", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "gid", IsOptional: false}, Kind: ResGid}}}, + &Call{ID: 162, Name: "getuid", CallName: "getuid", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResUid}, Args: []Type{}}, + &Call{ID: 163, Name: "geteuid", CallName: "geteuid", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResUid}, Args: []Type{}}, + &Call{ID: 164, Name: "setpgid", CallName: "setpgid", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, ResourceType{TypeCommon: TypeCommon{TypeName: "pgid", IsOptional: false}, Kind: ResPid}}}, + &Call{ID: 165, Name: "getpgid", CallName: "getpgid", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResPid}, Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}}}, + &Call{ID: 166, Name: "getpgrp", CallName: "getpgrp", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResPid}, Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}}}, + &Call{ID: 167, Name: "getpid", CallName: "getpid", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResPid}, Args: []Type{}}, + &Call{ID: 168, Name: "gettid", CallName: "gettid", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResPid}, Args: []Type{}}, + &Call{ID: 169, Name: "setreuid", CallName: "setreuid", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "ruid", IsOptional: false}, Kind: ResUid}, ResourceType{TypeCommon: TypeCommon{TypeName: "euid", IsOptional: false}, Kind: ResUid}}}, + &Call{ID: 170, Name: "setregid", CallName: "setregid", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "rgid", IsOptional: false}, Kind: ResGid}, ResourceType{TypeCommon: TypeCommon{TypeName: "egid", IsOptional: false}, Kind: ResGid}}}, + &Call{ID: 171, Name: "setresuid", CallName: "setresuid", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "ruid", IsOptional: false}, Kind: ResUid}, ResourceType{TypeCommon: TypeCommon{TypeName: "euid", IsOptional: false}, Kind: ResUid}, ResourceType{TypeCommon: TypeCommon{TypeName: "suid", IsOptional: false}, Kind: ResUid}}}, + &Call{ID: 172, Name: "setresgid", CallName: "setresgid", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "rgid", IsOptional: false}, Kind: ResGid}, ResourceType{TypeCommon: TypeCommon{TypeName: "egid", IsOptional: false}, Kind: ResGid}, ResourceType{TypeCommon: TypeCommon{TypeName: "sgid", IsOptional: false}, Kind: ResGid}}}, + &Call{ID: 173, Name: "getresuid", CallName: "getresuid", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "ruid", IsOptional: false}, Type: ResourceType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: ResUid}, Dir: DirOut}, PtrType{TypeCommon: TypeCommon{TypeName: "euid", IsOptional: false}, Type: ResourceType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: ResUid}, Dir: DirOut}, PtrType{TypeCommon: TypeCommon{TypeName: "suid", IsOptional: false}, Type: ResourceType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: ResUid}, Dir: DirOut}}}, + &Call{ID: 174, Name: "getresgid", CallName: "getresgid", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "rgid", IsOptional: false}, Type: ResourceType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: ResGid}, Dir: DirOut}, PtrType{TypeCommon: TypeCommon{TypeName: "egid", IsOptional: false}, Type: ResourceType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: ResGid}, Dir: DirOut}, PtrType{TypeCommon: TypeCommon{TypeName: "sgid", IsOptional: false}, Type: ResourceType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: ResGid}, Dir: DirOut}}}, + &Call{ID: 175, Name: "setfsuid", CallName: "setfsuid", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fsuid", IsOptional: false}, Kind: ResUid}}}, + &Call{ID: 176, Name: "setfsgid", CallName: "setfsgid", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fsgid", IsOptional: false}, Kind: ResGid}}}, + &Call{ID: 177, Name: "getgroups", CallName: "getgroups", Args: []Type{LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "list", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "list", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: ResourceType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: ResGid}}, Dir: DirInOut}}}, + &Call{ID: 178, Name: "setgroups", CallName: "setgroups", Args: []Type{LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "list", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "list", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: ResourceType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: ResGid}}, Dir: DirIn}}}, + &Call{ID: 179, Name: "personality", CallName: "personality", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "persona", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 262144, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728}}}}, + &Call{ID: 180, Name: "inotify_init", CallName: "inotify_init", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: FdInotify}, Args: []Type{}}, + &Call{ID: 181, Name: "inotify_init1", CallName: "inotify_init1", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: FdInotify}, Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2048, 524288}}}}, + &Call{ID: 182, Name: "inotify_add_watch", CallName: "inotify_add_watch", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResInotifyDesc}, Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdInotify}, PtrType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}}}, FlagsType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 4, 8, 16, 256, 512, 1024, 2, 2048, 64, 128, 32, 33554432, 67108864, 536870912, 2147483648, 16777216}}}}, + &Call{ID: 183, Name: "inotify_rm_watch", CallName: "inotify_rm_watch", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdInotify}, ResourceType{TypeCommon: TypeCommon{TypeName: "wd", IsOptional: false}, Kind: ResInotifyDesc}}}, + &Call{ID: 184, Name: "fanotify_init", CallName: "fanotify_init", Ret: ResourceType{TypeCommon: TypeCommon{TypeName: "ret", IsOptional: false}, Kind: ResFD, Subkind: FdFanotify}, Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{8, 4, 0, 1, 2, 16, 32}}, FlagsType{TypeCommon: TypeCommon{TypeName: "events", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2, 0, 524288, 1024, 4096, 262144, 2048, 1052672}}}}, + &Call{ID: 185, Name: "fanotify_mark", CallName: "fanotify_mark", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdFanotify}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 128, 4, 8, 16, 32, 64}}, FlagsType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 8, 16, 32, 65536, 131072, 1073741824, 134217728}}, ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}}}, + &Call{ID: 186, Name: "link", CallName: "link", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}}}}}, + &Call{ID: 187, Name: "linkat", CallName: "linkat", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "oldfd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: false}}}, ResourceType{TypeCommon: TypeCommon{TypeName: "newfd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{4096, 1024}}}}, + &Call{ID: 188, Name: "symlinkat", CallName: "symlinkat", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: false}}}, ResourceType{TypeCommon: TypeCommon{TypeName: "newfd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}}}}}, + &Call{ID: 189, Name: "symlink", CallName: "symlink", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}}}}}, + &Call{ID: 190, Name: "unlink", CallName: "unlink", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}}}, + &Call{ID: 191, Name: "unlinkat", CallName: "unlinkat", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 512}}}}, + &Call{ID: 192, Name: "readlink", CallName: "readlink", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "siz", IsOptional: false}, Buf: "buf", TypeSize: 0}}}, + &Call{ID: 193, Name: "readlinkat", CallName: "readlinkat", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "siz", IsOptional: false}, Buf: "buf", TypeSize: 0}}}, + &Call{ID: 194, Name: "rename", CallName: "rename", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}}}}}, + &Call{ID: 195, Name: "renameat", CallName: "renameat", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "oldfd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: false}}}, ResourceType{TypeCommon: TypeCommon{TypeName: "newfd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}}}}}, + &Call{ID: 196, Name: "renameat2", CallName: "renameat2", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "oldfd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: false}}}, ResourceType{TypeCommon: TypeCommon{TypeName: "newfd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2, 1, 4}}}}, + &Call{ID: 197, Name: "mkdir", CallName: "mkdir", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}, FlagsType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 0, Vals: []uintptr{256, 128, 64, 32, 16, 8, 4, 2, 1}}}}, + &Call{ID: 198, Name: "mkdirat", CallName: "mkdirat", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}, FlagsType{TypeCommon: TypeCommon{TypeName: "mode", IsOptional: false}, TypeSize: 0, Vals: []uintptr{256, 128, 64, 32, 16, 8, 4, 2, 1}}}}, + &Call{ID: 199, Name: "rmdir", CallName: "rmdir", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}}}, + &Call{ID: 200, Name: "truncate", CallName: "truncate", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}}}, IntType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 201, Name: "ftruncate", CallName: "ftruncate", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, IntType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 202, Name: "flock", CallName: "flock", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "op", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 8, 4}}}}, + &Call{ID: 203, Name: "fsync", CallName: "fsync", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}}}, + &Call{ID: 204, Name: "fdatasync", CallName: "fdatasync", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}}}, + &Call{ID: 205, Name: "sync", CallName: "sync", Args: []Type{}}, + &Call{ID: 206, Name: "syncfs", CallName: "syncfs", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}}}, + &Call{ID: 207, Name: "sync_file_range", CallName: "sync_file_range", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, IntType{TypeCommon: TypeCommon{TypeName: "off", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nbytes", IsOptional: false}, TypeSize: 8}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 4}}}}, + &Call{ID: 208, Name: "lookup_dcookie", CallName: "lookup_dcookie", Args: []Type{IntType{TypeCommon: TypeCommon{TypeName: "cookie", IsOptional: false}, TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "buf", TypeSize: 0}}}, + &Call{ID: 209, Name: "getdents", CallName: "getdents", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "ent", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "ent", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "count", IsOptional: false}, Buf: "ent", TypeSize: 0}}}, + &Call{ID: 210, Name: "getdents64", CallName: "getdents64", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "ent", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "ent", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "count", IsOptional: false}, Buf: "ent", TypeSize: 0}}}, + &Call{ID: 211, Name: "name_to_handle_at", CallName: "name_to_handle_at", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: FdDir}, PtrType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "file", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "handle", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "file_handle", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "bytes", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "type", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "handl0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl7", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl8", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl9", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl10", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl11", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl12", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl13", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl14", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl15", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "mnt", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 4}, Dir: DirOut}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{4096, 1024, 18446744073709551516}}}}, + &Call{ID: 212, Name: "open_by_handle_at", CallName: "open_by_handle_at", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "mountdirfd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "handle", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "file_handle", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "bytes", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "type", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "handl0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl7", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl8", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl9", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl10", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl11", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl12", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl13", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl14", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "handl15", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2, 1024, 8192, 524288, 64, 16384, 65536, 128, 0, 262144, 256, 131072, 2048, 2097152, 1052672, 512}}}}, + &Call{ID: 213, Name: "mount", CallName: "mount", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "src", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "src", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "dst", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "dst", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "type", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "type", IsOptional: false}, Kind: BufferString}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{4096, 128, 64, 8192, 1024, 4, 2048, 8, 2, 1, 2097152, 32, 32768, 16777216, 16}}, PtrType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "data", IsOptional: false}, Kind: BufferBlob}}}}, + &Call{ID: 214, Name: "umount2", CallName: "umount2", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 4, 8}}}}, + &Call{ID: 215, Name: "pivot_root", CallName: "pivot_root", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "new_root", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "new_root", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "put_old", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "put_old", IsOptional: false}}}}}, + &Call{ID: 216, Name: "sysfs", CallName: "sysfs", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "option", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 3}}, IntType{TypeCommon: TypeCommon{TypeName: "arg1", IsOptional: false}, TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "arg2", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "arg2", IsOptional: false}, Kind: BufferString}}}}, + &Call{ID: 217, Name: "statfs", CallName: "statfs", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Kind: BufferBlob}}}}, + &Call{ID: 218, Name: "fstatfs", CallName: "fstatfs", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Kind: BufferBlob}}}}, + &Call{ID: 219, Name: "uselib", CallName: "uselib", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "lib", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "lib", IsOptional: false}}}}}, + &Call{ID: 220, Name: "init_module", CallName: "init_module", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "mod", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "mod", IsOptional: false}, Kind: BufferString}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "mod", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "args", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "args", IsOptional: false}, Kind: BufferString}}}}, + &Call{ID: 221, Name: "finit_module", CallName: "finit_module", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "args", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "args", IsOptional: false}, Kind: BufferString}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2}}}}, + &Call{ID: 222, Name: "delete_module", CallName: "delete_module", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Kind: BufferString}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{2048, 512}}}}, + &Call{ID: 223, Name: "kexec_load", CallName: "kexec_load", Args: []Type{IntType{TypeCommon: TypeCommon{TypeName: "entry", IsOptional: false}, TypeSize: 8}, LenType{TypeCommon: TypeCommon{TypeName: "nr_segments", IsOptional: false}, Buf: "segments", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "segments", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "kexec_segment", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "sz", IsOptional: false}, Buf: "buf", TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "mem", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "memsz", IsOptional: false}, TypeSize: 8}}}}, Dir: DirIn}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 196608, 4063232, 1310720, 1376256, 3276800, 2621440, 1441792, 2752512, 524288, 655360}}}}, + &Call{ID: 224, Name: "get_kernel_syms", CallName: "get_kernel_syms", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "table", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "table", IsOptional: false}, Kind: BufferBlob}}}}, + &Call{ID: 225, Name: "syslog", CallName: "syslog", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "cmd", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2, 3, 4, 5, 7, 9, 10}}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: true}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "buf", TypeSize: 0}}}, + &Call{ID: 226, Name: "uname", CallName: "uname", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Kind: BufferBlob}}}}, + &Call{ID: 227, Name: "sysinfo", CallName: "sysinfo", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "info", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "info", IsOptional: false}, Kind: BufferBlob}}}}, + &Call{ID: 228, Name: "ustat", CallName: "ustat", Args: []Type{IntType{TypeCommon: TypeCommon{TypeName: "dev", IsOptional: false}, TypeSize: 8}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "ustat", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "free", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "inode", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nampac0", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "nampac1", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "nampac2", IsOptional: false}, TypeSize: 4}}}, Dir: DirOut}}}, + &Call{ID: 229, Name: "acct", CallName: "acct", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "filename", IsOptional: true}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "filename", IsOptional: false}}}}}, + &Call{ID: 230, Name: "getrusage", CallName: "getrusage", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "who", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 18446744073709551615, 1}}, PtrType{TypeCommon: TypeCommon{TypeName: "usage", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "rusage", IsOptional: false}, Fields: []Type{StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}, StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}, IntType{TypeCommon: TypeCommon{TypeName: "maxrss", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "ixrss", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "idrss", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "isrss", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "minflt", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "majflt", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nswap", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "inblock", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "oublock", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "msgsnd", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "msgrcv", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "signals", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nvcsw", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nivcsw", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}}}, + &Call{ID: 231, Name: "getrlimit", CallName: "getrlimit", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "res", IsOptional: false}, TypeSize: 0, Vals: []uintptr{9, 4, 0, 2, 1, 10, 8, 12, 13, 7, 6, 5, 14, 15, 11, 3}}, PtrType{TypeCommon: TypeCommon{TypeName: "rlim", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "rlimit", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "soft", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "hard", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}}}, + &Call{ID: 232, Name: "setrlimit", CallName: "setrlimit", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "res", IsOptional: false}, TypeSize: 0, Vals: []uintptr{9, 4, 0, 2, 1, 10, 8, 12, 13, 7, 6, 5, 14, 15, 11, 3}}, PtrType{TypeCommon: TypeCommon{TypeName: "rlim", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "rlimit", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "soft", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "hard", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}}}, + &Call{ID: 233, Name: "prlimit64", CallName: "prlimit64", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, FlagsType{TypeCommon: TypeCommon{TypeName: "res", IsOptional: false}, TypeSize: 0, Vals: []uintptr{9, 4, 0, 2, 1, 10, 8, 12, 13, 7, 6, 5, 14, 15, 11, 3}}, PtrType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: true}, Type: StructType{TypeCommon: TypeCommon{TypeName: "rlimit", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "soft", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "hard", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: true}, Type: StructType{TypeCommon: TypeCommon{TypeName: "rlimit", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "soft", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "hard", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}}}, + &Call{ID: 234, Name: "iopl", CallName: "iopl", Args: []Type{IntType{TypeCommon: TypeCommon{TypeName: "level", IsOptional: false}, TypeSize: 1}}}, + &Call{ID: 235, Name: "ioperm", CallName: "ioperm", Args: []Type{IntType{TypeCommon: TypeCommon{TypeName: "from", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "num", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "on", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 236, Name: "ioprio_get", CallName: "ioprio_get", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "which", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 3}}, ResourceType{TypeCommon: TypeCommon{TypeName: "who", IsOptional: false}, Kind: ResPid}}}, + &Call{ID: 237, Name: "ioprio_set", CallName: "ioprio_set", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "which", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 3}}, ResourceType{TypeCommon: TypeCommon{TypeName: "who", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "prio", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 238, Name: "setns", CallName: "setns", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, FlagsType{TypeCommon: TypeCommon{TypeName: "type", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 134217728, 1073741824, 67108864}}}}, + &Call{ID: 239, Name: "setxattr", CallName: "setxattr", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Kind: BufferString}}, PtrType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Kind: BufferString}}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "val", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2}}}}, + &Call{ID: 240, Name: "lsetxattr", CallName: "lsetxattr", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Kind: BufferString}}, PtrType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Kind: BufferString}}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "val", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2}}}}, + &Call{ID: 241, Name: "fsetxattr", CallName: "fsetxattr", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Kind: BufferString}}, PtrType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Kind: BufferString}}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "val", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2}}}}, + &Call{ID: 242, Name: "getxattr", CallName: "getxattr", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Kind: BufferString}}, PtrType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "val", TypeSize: 0}}}, + &Call{ID: 243, Name: "lgetxattr", CallName: "lgetxattr", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Kind: BufferString}}, PtrType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "val", TypeSize: 0}}}, + &Call{ID: 244, Name: "fgetxattr", CallName: "fgetxattr", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Kind: BufferString}}, PtrType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "val", TypeSize: 0}}}, + &Call{ID: 245, Name: "listxattr", CallName: "listxattr", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "list", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "list", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "list", TypeSize: 0}}}, + &Call{ID: 246, Name: "llistxattr", CallName: "llistxattr", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "list", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "list", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "list", TypeSize: 0}}}, + &Call{ID: 247, Name: "flistxattr", CallName: "flistxattr", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "list", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "list", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "list", TypeSize: 0}}}, + &Call{ID: 248, Name: "removexattr", CallName: "removexattr", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Kind: BufferString}}}}, + &Call{ID: 249, Name: "lremovexattr", CallName: "lremovexattr", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}, Dir: DirIn, Type: FilenameType{TypeCommon: TypeCommon{TypeName: "path", IsOptional: false}}}, PtrType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Kind: BufferString}}}}, + &Call{ID: 250, Name: "fremovexattr", CallName: "fremovexattr", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "fd", IsOptional: false}, Kind: ResFD, Subkind: ResAny}, PtrType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Dir: DirIn, Type: BufferType{TypeCommon: TypeCommon{TypeName: "name", IsOptional: false}, Kind: BufferString}}}}, + &Call{ID: 251, Name: "time", CallName: "time", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "t", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 8}, Dir: DirOut}}}, + &Call{ID: 252, Name: "clock_gettime", CallName: "clock_gettime", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "id", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 5, 1, 6, 4, 7, 2, 3}}, PtrType{TypeCommon: TypeCommon{TypeName: "tp", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}}}, + &Call{ID: 253, Name: "clock_settime", CallName: "clock_settime", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "id", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 5, 1, 6, 4, 7, 2, 3}}, PtrType{TypeCommon: TypeCommon{TypeName: "tp", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}}}, + &Call{ID: 254, Name: "clock_adjtime", CallName: "clock_adjtime", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "id", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 5, 1, 6, 4, 7, 2, 3}}, PtrType{TypeCommon: TypeCommon{TypeName: "tx", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timex", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "stuff0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff7", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff8", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff9", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff10", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff11", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff12", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff13", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff14", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff15", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff16", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff17", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff18", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff19", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff20", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff21", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff22", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff23", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff24", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stuff25", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}}}, + &Call{ID: 255, Name: "clock_getres", CallName: "clock_getres", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "id", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 5, 1, 6, 4, 7, 2, 3}}, PtrType{TypeCommon: TypeCommon{TypeName: "tp", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}}}, + &Call{ID: 256, Name: "clock_nanosleep", CallName: "clock_nanosleep", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "id", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 5, 1, 6, 4, 7, 2, 3}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1}}, PtrType{TypeCommon: TypeCommon{TypeName: "rqtp", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "rmtp", IsOptional: true}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}}}, + &Call{ID: 257, Name: "timer_create", CallName: "timer_create", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "id", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 5, 1, 6, 4, 7, 2, 3}}, PtrType{TypeCommon: TypeCommon{TypeName: "ev", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigevent", IsOptional: false}, Fields: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "val", IsOptional: false}}, IntType{TypeCommon: TypeCommon{TypeName: "signo", IsOptional: false}, TypeSize: 4, Limit: 130}, FlagsType{TypeCommon: TypeCommon{TypeName: "notify", IsOptional: false}, TypeSize: 4, Vals: []uintptr{1, 0, 2}}, IntType{TypeCommon: TypeCommon{TypeName: "pad0", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad1", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad2", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad3", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad4", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad5", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad6", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "pad7", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "timerid", IsOptional: false}, Type: ResourceType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Kind: ResTimerid}, Dir: DirOut}}}, + &Call{ID: 258, Name: "timer_gettime", CallName: "timer_gettime", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "timerid", IsOptional: false}, Kind: ResTimerid}, PtrType{TypeCommon: TypeCommon{TypeName: "setting", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "itimerspec", IsOptional: false}, Fields: []Type{StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}}}, Dir: DirOut}}}, + &Call{ID: 259, Name: "timer_getoverrun", CallName: "timer_getoverrun", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "timerid", IsOptional: false}, Kind: ResTimerid}}}, + &Call{ID: 260, Name: "timer_settime", CallName: "timer_settime", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "timerid", IsOptional: false}, Kind: ResTimerid}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1}}, PtrType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "itimerspec", IsOptional: false}, Fields: []Type{StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: true}, Type: StructType{TypeCommon: TypeCommon{TypeName: "itimerspec", IsOptional: false}, Fields: []Type{StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}}}, Dir: DirOut}}}, + &Call{ID: 261, Name: "timer_delete", CallName: "timer_delete", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "timerid", IsOptional: false}, Kind: ResTimerid}}}, + &Call{ID: 262, Name: "rt_sigaction", CallName: "rt_sigaction", Args: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sig", IsOptional: false}, TypeSize: 4, Limit: 130}, PtrType{TypeCommon: TypeCommon{TypeName: "act", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigaction", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "handler", IsOptional: false}, TypeSize: 8}, StructType{TypeCommon: TypeCommon{TypeName: "sigset", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, TypeSize: 8}}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 8, Vals: []uintptr{1, 2, 1073741824, 134217728, 2147483648, 268435456, 4}}, IntType{TypeCommon: TypeCommon{TypeName: "restor", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "oact", IsOptional: true}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigaction", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "handler", IsOptional: false}, TypeSize: 8}, StructType{TypeCommon: TypeCommon{TypeName: "sigset", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, TypeSize: 8}}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 8, Vals: []uintptr{1, 2, 1073741824, 134217728, 2147483648, 268435456, 4}}, IntType{TypeCommon: TypeCommon{TypeName: "restor", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}, LenType{TypeCommon: TypeCommon{TypeName: "sigsetsize", IsOptional: false}, Buf: "fake", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "fake", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigset", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}}}, + &Call{ID: 263, Name: "rt_sigprocmask", CallName: "rt_sigprocmask", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "how", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2}}, PtrType{TypeCommon: TypeCommon{TypeName: "nset", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigset", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "oset", IsOptional: true}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigset", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}, LenType{TypeCommon: TypeCommon{TypeName: "sigsetsize", IsOptional: false}, Buf: "nset", TypeSize: 0}}}, + &Call{ID: 264, Name: "rt_sigreturn", CallName: "rt_sigreturn", Args: []Type{}}, + &Call{ID: 265, Name: "rt_sigpending", CallName: "rt_sigpending", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "set", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigset", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}, LenType{TypeCommon: TypeCommon{TypeName: "sigsetsize", IsOptional: false}, Buf: "set", TypeSize: 0}}}, + &Call{ID: 266, Name: "rt_sigtimedwait", CallName: "rt_sigtimedwait", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "these", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigset", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "info", IsOptional: true}, Type: StructType{TypeCommon: TypeCommon{TypeName: "siginfo", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "signo", IsOptional: false}, TypeSize: 4, Limit: 130}, IntType{TypeCommon: TypeCommon{TypeName: "errno", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "code", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "pad3", IsOptional: false}, TypeSize: 4}}}, Dir: DirOut}, PtrType{TypeCommon: TypeCommon{TypeName: "ts", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "sigsetsize", IsOptional: false}, Buf: "these", TypeSize: 0}}}, + &Call{ID: 267, Name: "rt_sigsuspend", CallName: "rt_sigsuspend", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sigset", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "sigsetsize", IsOptional: false}, Buf: "new", TypeSize: 0}}}, + &Call{ID: 268, Name: "rt_sigqueueinfo", CallName: "rt_sigqueueinfo", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "sig", IsOptional: false}, TypeSize: 4, Limit: 130}, PtrType{TypeCommon: TypeCommon{TypeName: "info", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "siginfo", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "signo", IsOptional: false}, TypeSize: 4, Limit: 130}, IntType{TypeCommon: TypeCommon{TypeName: "errno", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "code", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "pad3", IsOptional: false}, TypeSize: 4}}}, Dir: DirIn}}}, + &Call{ID: 269, Name: "rt_tgsigqueueinfo", CallName: "rt_tgsigqueueinfo", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "gid", IsOptional: false}, Kind: ResPid}, ResourceType{TypeCommon: TypeCommon{TypeName: "tid", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "sig", IsOptional: false}, TypeSize: 4, Limit: 130}, PtrType{TypeCommon: TypeCommon{TypeName: "info", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "siginfo", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "signo", IsOptional: false}, TypeSize: 4, Limit: 130}, IntType{TypeCommon: TypeCommon{TypeName: "errno", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "code", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "pad3", IsOptional: false}, TypeSize: 4}}}, Dir: DirIn}}}, + &Call{ID: 270, Name: "sigaltstack", CallName: "sigaltstack", Args: []Type{VmaType{TypeCommon: TypeCommon{TypeName: "ss", IsOptional: false}}, PtrType{TypeCommon: TypeCommon{TypeName: "oss", IsOptional: true}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 8}, Dir: DirOut}}}, + &Call{ID: 271, Name: "tgkill", CallName: "tgkill", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "gid", IsOptional: false}, Kind: ResPid}, ResourceType{TypeCommon: TypeCommon{TypeName: "tid", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "sig", IsOptional: false}, TypeSize: 4, Limit: 130}}}, + &Call{ID: 272, Name: "tkill", CallName: "tkill", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "tid", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "sig", IsOptional: false}, TypeSize: 4, Limit: 130}}}, + &Call{ID: 273, Name: "pause", CallName: "pause", Args: []Type{}}, + &Call{ID: 274, Name: "alarm", CallName: "alarm", Args: []Type{IntType{TypeCommon: TypeCommon{TypeName: "seconds", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 275, Name: "nanosleep", CallName: "nanosleep", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "req", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "rem", IsOptional: true}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}}}, + &Call{ID: 276, Name: "getitimer", CallName: "getitimer", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "which", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2}}, PtrType{TypeCommon: TypeCommon{TypeName: "cur", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "itimerval", IsOptional: false}, Fields: []Type{StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}, StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}}}, Dir: DirOut}}}, + &Call{ID: 277, Name: "setitimer", CallName: "setitimer", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "which", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2}}, PtrType{TypeCommon: TypeCommon{TypeName: "new", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "itimerval", IsOptional: false}, Fields: []Type{StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}, StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}}}, Dir: DirIn}, PtrType{TypeCommon: TypeCommon{TypeName: "old", IsOptional: true}, Type: StructType{TypeCommon: TypeCommon{TypeName: "itimerval", IsOptional: false}, Fields: []Type{StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}, StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}}}, Dir: DirOut}}}, + &Call{ID: 278, Name: "exit", CallName: "exit", Args: []Type{IntType{TypeCommon: TypeCommon{TypeName: "code", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 279, Name: "exit_group", CallName: "exit_group", Args: []Type{IntType{TypeCommon: TypeCommon{TypeName: "code", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 280, Name: "waitid", CallName: "waitid", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "which", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 0}}, ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, PtrType{TypeCommon: TypeCommon{TypeName: "infop", IsOptional: true}, Type: StructType{TypeCommon: TypeCommon{TypeName: "siginfo", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "signo", IsOptional: false}, TypeSize: 4, Limit: 130}, IntType{TypeCommon: TypeCommon{TypeName: "errno", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "code", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "pad3", IsOptional: false}, TypeSize: 4}}}, Dir: DirOut}, FlagsType{TypeCommon: TypeCommon{TypeName: "options", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 8, 4, 2, 8, 1, 16777216, 2147483648, 1073741824, 536870912}}, PtrType{TypeCommon: TypeCommon{TypeName: "ru", IsOptional: true}, Type: StructType{TypeCommon: TypeCommon{TypeName: "rusage", IsOptional: false}, Fields: []Type{StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}, StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}, IntType{TypeCommon: TypeCommon{TypeName: "maxrss", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "ixrss", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "idrss", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "isrss", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "minflt", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "majflt", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nswap", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "inblock", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "oublock", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "msgsnd", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "msgrcv", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "signals", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nvcsw", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nivcsw", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}}}, + &Call{ID: 281, Name: "wait4", CallName: "wait4", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, PtrType{TypeCommon: TypeCommon{TypeName: "status", IsOptional: true}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 4}, Dir: DirOut}, FlagsType{TypeCommon: TypeCommon{TypeName: "options", IsOptional: false}, TypeSize: 0, Vals: []uintptr{1, 2, 8, 4, 2, 8, 1, 16777216, 2147483648, 1073741824, 536870912}}, PtrType{TypeCommon: TypeCommon{TypeName: "ru", IsOptional: true}, Type: StructType{TypeCommon: TypeCommon{TypeName: "rusage", IsOptional: false}, Fields: []Type{StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}, StructType{TypeCommon: TypeCommon{TypeName: "timeval", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "usec", IsOptional: false}, TypeSize: 8}}}, IntType{TypeCommon: TypeCommon{TypeName: "maxrss", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "ixrss", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "idrss", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "isrss", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "minflt", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "majflt", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nswap", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "inblock", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "oublock", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "msgsnd", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "msgrcv", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "signals", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nvcsw", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nivcsw", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}}}, + &Call{ID: 282, Name: "times", CallName: "times", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "tms", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "utime", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "stime", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "cutime", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "cstime", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}}}, + &Call{ID: 283, Name: "set_thread_area", CallName: "set_thread_area", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "info", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "user_desc", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "entry", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "base", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "limit", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 1}}}, Dir: DirIn}}}, + &Call{ID: 284, Name: "get_thread_area", CallName: "get_thread_area", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "info", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "user_desc", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "entry", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "base", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "limit", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 1}}}, Dir: DirIn}}}, + &Call{ID: 285, Name: "set_tid_address", CallName: "set_tid_address", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "tidptr", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 4}, Dir: DirOut}}}, + &Call{ID: 286, Name: "getpriority", CallName: "getpriority", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "which", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2}}, ResourceType{TypeCommon: TypeCommon{TypeName: "who", IsOptional: false}, Kind: ResPid}}}, + &Call{ID: 287, Name: "setpriority", CallName: "setpriority", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "which", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2}}, ResourceType{TypeCommon: TypeCommon{TypeName: "who", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "prio", IsOptional: false}, TypeSize: 8}}}, + &Call{ID: 288, Name: "sched_getscheduler", CallName: "sched_getscheduler", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}}}, + &Call{ID: 289, Name: "sched_setscheduler", CallName: "sched_setscheduler", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, FlagsType{TypeCommon: TypeCommon{TypeName: "policy", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 3, 5, 1, 2, 6}}, PtrType{TypeCommon: TypeCommon{TypeName: "prio", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 4}, Dir: DirIn}}}, + &Call{ID: 290, Name: "sched_rr_get_interval", CallName: "sched_rr_get_interval", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, PtrType{TypeCommon: TypeCommon{TypeName: "tp", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "timespec", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "sec", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "nsec", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}}}, + &Call{ID: 291, Name: "sched_getparam", CallName: "sched_getparam", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, PtrType{TypeCommon: TypeCommon{TypeName: "prio", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 4}, Dir: DirOut}}}, + &Call{ID: 292, Name: "sched_setparam", CallName: "sched_setparam", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, PtrType{TypeCommon: TypeCommon{TypeName: "prio", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 4}, Dir: DirIn}}}, + &Call{ID: 293, Name: "sched_getaffinity", CallName: "sched_getaffinity", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, LenType{TypeCommon: TypeCommon{TypeName: "cpusetsize", IsOptional: false}, Buf: "mask", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 8}, Dir: DirOut}}}, + &Call{ID: 294, Name: "sched_setaffinity", CallName: "sched_setaffinity", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, LenType{TypeCommon: TypeCommon{TypeName: "cpusetsize", IsOptional: false}, Buf: "mask", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "mask", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 8}, Dir: DirIn}}}, + &Call{ID: 295, Name: "sched_getattr", CallName: "sched_getattr", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, PtrType{TypeCommon: TypeCommon{TypeName: "attr", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sched_attr", IsOptional: false}, Fields: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, TypeSize: 4, Vals: []uintptr{48}}, FlagsType{TypeCommon: TypeCommon{TypeName: "policy", IsOptional: false}, TypeSize: 4, Vals: []uintptr{0, 3, 5, 1, 2, 6}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 8, Vals: []uintptr{0, 1}}, IntType{TypeCommon: TypeCommon{TypeName: "nice", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "prio", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "runtime", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "deadlin", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "period", IsOptional: false}, TypeSize: 8}}}, Dir: DirOut}, LenType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, Buf: "attr", TypeSize: 0}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0}}}}, + &Call{ID: 296, Name: "sched_setattr", CallName: "sched_setattr", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, PtrType{TypeCommon: TypeCommon{TypeName: "attr", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "sched_attr", IsOptional: false}, Fields: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "size", IsOptional: false}, TypeSize: 4, Vals: []uintptr{48}}, FlagsType{TypeCommon: TypeCommon{TypeName: "policy", IsOptional: false}, TypeSize: 4, Vals: []uintptr{0, 3, 5, 1, 2, 6}}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 8, Vals: []uintptr{0, 1}}, IntType{TypeCommon: TypeCommon{TypeName: "nice", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "prio", IsOptional: false}, TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "runtime", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "deadlin", IsOptional: false}, TypeSize: 8}, IntType{TypeCommon: TypeCommon{TypeName: "period", IsOptional: false}, TypeSize: 8}}}, Dir: DirIn}, FlagsType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0}}}}, + &Call{ID: 297, Name: "sched_yield", CallName: "sched_yield", Args: []Type{}}, +} diff --git a/sys/sys.txt b/sys/sys.txt new file mode 100644 index 000000000..88e0ed6cd --- /dev/null +++ b/sys/sys.txt @@ -0,0 +1,1134 @@ +# Description of syscall arguments. + +# A syscall is described as: +# syscallname "(" [arg ["," arg]*] ")" [type] +# arg = argname type +# argname = identifier +# type = typename [ "[" type-options "]" ] +# typename = "fd" | "fileoff" | "buffer" | "vma" , "len" | "flags" | "filename" | "ptr" | "array" | "intN" | "intptr" +# type-options = [type-opt ["," type-opt]] +# common type-options include: +# "opt" - the argument is optional (like mmap fd argument, or accept peer argument) +# rest of the type-options are type-specific: +# "fd": file descriptor, type-options: kind of fd (file/sock/pipe/rand) (optional) +# "fileoff": offset within a file, type-options: argname of the file +# "buffer": a pointer to a memory buffer (like read/write buffer argument), type-options: direction (in/out/inout) +# "string": a pointer to a memory buffer, similar to buffer[in] +# "vma": a pointer to a set of pages (used as input for mmap/munmap/mremap/madvise) +# "len": length of buffer/vma/arrayptr (for array it is number of elements), type-options: argname of the object +# "flags": a set of flags, type-options: reference to flags description +# "filename": a file/link/dir name +# "ptr": a pointer to an object, type-options: type of the object; direction (in/out/inout) +# "array": a variable-length array, type-options: type of elements +# "intN"/"intptr": an integer without a particular meaning +# flags/len/flags also have trailing underlying type type-option when used in structs/pointers. +# +# Flags are described as: +# flagname = const ["," const] +# +# Structs are described as: +# structname struct "{" "\n" (fieldname type "\n")+ "}" + +include <sys/types.h> +include <sys/socket.h> +include <sys/select.h> +include <sys/ptrace.h> +include <sys/fanotify.h> +include <sys/inotify.h> +include <sys/resource.h> +include <sys/stat.h> +include <sys/xattr.h> +include <sys/mman.h> +include <sys/time.h> +include <sys/ipc.h> +include <sys/shm.h> +include <sys/msg.h> +include <sys/sem.h> +include <sys/prctl.h> +include <sys/mount.h> +include <sys/epoll.h> +include <sys/signalfd.h> +include <sys/eventfd.h> +include <sys/timerfd.h> +include <sys/personality.h> +include <sys/wait.h> +include <sys/user.h> + +include <linux/futex.h> +include <linux/aio_abi.h> +include <linux/kexec.h> +include <linux/seccomp.h> +include <linux/elf.h> + +include <asm/prctl.h> + +include <fcntl.h> +include <sched.h> +include <mqueue.h> +include <time.h> +include <numaif.h> + + + + +open(file filename, flags flags[open_flags], mode flags[open_mode]) fd +openat(fd fd[dir], file filename, flags flags[open_flags], mode flags[open_mode]) fd +creat(file filename, mode flags[open_mode]) fd +close(fd fd) +read(fd fd, buf buffer[out], count len[buf]) len[buf] +pread64(fd fd, buf buffer[out], count len[buf], pos fileoff[fd]) +readv(fd fd, vec ptr[in, array[iovec_out]], vlen len[vec]) +preadv(fd fd, vec ptr[in, array[iovec_out]], vlen len[vec], off fileoff[fd]) +write(fd fd, buf buffer[in], count len[buf]) len[buf] +pwrite64(fd fd, buf buffer[in], count len[buf], pos fileoff[fd]) +writev(fd fd, vec ptr[in, array[iovec_in]], vlen len[vec]) +pwritev(fd fd, vec ptr[in, array[iovec_in]], vlen len[vec], off fileoff[fd]) +lseek(fd fd, offset fileoff[fd], whence flags[seek_whence]) + +dup(oldfd fd) fd +dup2(oldfd fd, newfd fd) fd +dup3(oldfd fd, newfd fd, flags flags[dup_flags]) fd + +pipe(pipefd ptr[out, pipefd]) +pipe2(pipefd ptr[out, pipefd], flags flags[pipe_flags]) + +tee(fdin fd, fdout fd, len int64, f flags[splice_flags]) +splice(fdin fd, offin fileoff[fdin], fdout fd, offout fileoff[fdout], len int64, f flags[splice_flags]) +vmsplice(fd fd, vec ptr[in, array[iovec_in]], vlen len[vec], f flags[splice_flags]) +sendfile(fdout fd, fdin fd, off ptr[inout, fileoff[fdin, int64], opt], count int64) + +stat(file filename, statbuf ptr[out, stat]) +lstat(file filename, statbuf ptr[out, stat]) +fstat(fd fd, statbuf ptr[out, stat]) + +poll(fds ptr[in, array[pollfd]], nfds len[fds], timeout int32) +ppoll(fds ptr[in, array[pollfd]], nfds len[fds], tsp ptr[in, timespec], sigmask ptr[in, sigset], size len[sigmask]) +select(n len[inp], inp ptr[inout, fd_set], outp ptr[inout, fd_set], exp ptr[inout, fd_set], tvp ptr[inout, timeval]) +pselect6(n len[inp], inp ptr[inout, fd_set], outp ptr[inout, fd_set], exp ptr[inout, fd_set], tvp ptr[inout, timespec], sig ptr[in, sigset_size]) + +epoll_create(size int32) fd[epoll] +epoll_create1(flags flags[epoll_flags]) fd[epoll] +epoll_ctl(epfd fd[epoll], op flags[epoll_op], fd fd, ev ptr[in, epoll_event]) +epoll_wait(epfd fd[epoll], events ptr[out, array[epoll_event]], maxevents len[events], timeout int32) +epoll_pwait(epfd fd[epoll], events ptr[out, array[epoll_event]], maxevents len[events], timeout int32, sigmask ptr[in, sigset], size len[sigmask]) + +signalfd(fd fd, mask ptr[in, sigset], size len[mask]) fd[signal] +signalfd4(fd fd, mask ptr[in, sigset], size len[mask], flags flags[signalfd_flags]) fd[signal] +eventfd(initval int32) fd[event] +eventfd2(initval int32, flags flags[eventfd_flags]) fd[event] +timerfd_create(clockid flags[clock_type], flags flags[timerfd_create_flags]) fd[timer] +timerfd_settime(fd fd[timer], flags flags[timerfd_settime_flags], new ptr[in, itimerspec], old ptr[out, itimerspec]) +timerfd_gettime(fd fd[timer], cur ptr[out, itimerspec]) + +mmap(addr vma, len len[addr], prot flags[mmap_prot], flags flags[mmap_flags], fd fd[file, opt], offset fileoff[fd]) vma +munmap(addr vma, len len[addr]) +mremap(addr vma, len len[addr], newlen len[newaddr], flags flags[mremap_flags], newaddr vma) vma +remap_file_pages(addr vma, size len[addr], prot flags[mmap_prot], pgoff intptr, flags flags[mmap_flags]) +mprotect(addr vma, len len[addr], prot flags[mmap_prot]) +msync(addr vma, len len[addr], f flags[msync_flags]) +madvise(addr vma, len len[addr], advice flags[madvise_flags]) +fadvise64(fd fd, offset fileoff[fd], len intptr, advice flags[fadvise_flags]) +readahead(fd fd, off intptr, count intptr) +mbind(addr vma, len len[addr], mode flags[mbind_mode], nodemask ptr[in, int64], maxnode intptr, flags flags[mbind_flags]) +move_pages(pid pid, nr len[pages], pages ptr[in, array[vma]], nodes ptr[in, array[int32], opt], status ptr[out, array[int32]], flags flags[move_pages_flags]) +migrate_pages(pid pid, maxnode intptr, old ptr[in, int64], new ptr[in, int64]) +set_mempolicy(mode flags[mbind_mode], nodemask ptr[in, int64], maxnode intptr) +get_mempolicy(mode ptr[out, int32], nodemask ptr[out, int64], maxnode intptr, addr vma, flags flags[mempolicy_flags]) +mincore(addr vma, size len[addr], vec buffer[out]) +mlock(addr vma, size len[addr]) +munlock(addr vma, size len[addr]) +mlockall(flags flags[mlockall_flags]) +munlockall() +unshare(flags flags[clone_flags]) +kcmp(pid1 pid, pid2 pid, type flags[kcmp_flags], fd1 fd, fd2 fd) + +futex(addr ptr[in, int32], op flags[futex_op], val intptr, timeout ptr[in, timespec], addr2 ptr[in, int32], val3 intptr) +set_robust_list(head ptr[in, robust_list], len len[head]) +get_robust_list(pid pid, head ptr[in, ptr[out, robust_list]], len ptr[inout, len[head, intptr]]) +restart_syscall() + +socket(domain flags[socket_domain], type flags[socket_type], proto int8) fd[sock] +socketpair(domain flags[socket_domain], type flags[socket_type], proto int8, fds ptr[out, pipefd]) +accept(fd fd[sock], peer ptr[out, sockaddr, opt], peerlen ptr[inout, len[peer, int32]]) fd[sock] +accept4(fd fd[sock], peer ptr[out, sockaddr, opt], peerlen ptr[inout, len[peer, int32]], flags flags[accept_flags]) fd[sock] +# TODO: must not bind to port 0, that will result in a random port which is not reproducible +bind(fd fd[sock], addr ptr[in, sockaddr], addrlen len[addr]) +listen(fd fd[sock], backlog int32) +connect(fd fd[sock], addr ptr[in, sockaddr], addrlen len[addr]) +shutdown(fd fd[sock], how flags[shutdown_flags]) +sendto(fd fd[sock], buf buffer[in], len len[buf], f flags[send_flags], addr ptr[in, sockaddr, opt], addrlen len[addr]) +sendmsg(fd fd[sock], msg ptr[in, send_msghdr], f flags[send_flags]) +sendmmsg(fd fd[sock], mmsg ptr[in, array[send_msghdr]], vlen len[mmsg], f flags[send_flags]) +recvfrom(fd fd[sock], buf buffer[out], len len[buf], f flags[recv_flags], addr ptr[in, sockaddr, opt], addrlen len[addr]) +recvmsg(fd fd[sock], msg ptr[in, recv_msghdr], f flags[recv_flags]) +recvmmsg(fd fd[sock], mmsg ptr[in, array[recv_msghdr]], vlen len[mmsg], f flags[recv_flags]) +getsockname(fd fd[sock], addr ptr[out, sockaddr], addrlen ptr[inout, len[addr, int32]]) +getpeername(fd fd[sock], peer ptr[out, sockaddr], peerlen ptr[inout, len[peer, int32]]) +# TODO: describe level/optname +getsockopt(fd fd[sock], level int32, optname int32, optval ptr[out, ioctl_arg], optlen ptr[inout, len[optval, int32]]) +setsockopt(fd fd[sock], level int32, optname int32, optval ptr[in, ioctl_arg], optlen len[optval]) + +# Almighty! +ioctl(fd fd, cmd int32, arg ptr[inout, ioctl_arg]) + +fcntl$dupfd(fd fd, cmd flags[fcntl_dupfd], arg fd) fd +fcntl$getflags(fd fd, cmd flags[fcntl_getflags]) +fcntl$setflags(fd fd, cmd flags[fcntl_setflags], flags flags[fcntl_flags]) +fcntl$setstatus(fd fd, cmd flags[fcntl_setstatus], flags flags[fcntl_status]) +fcntl$lock(fd fd, cmd flags[fcntl_lock], lock ptr[in, flock]) +fcntl$getown(fd fd, cmd flags[fcntl_getown]) pid +fcntl$setown(fd fd, cmd flags[fcntl_setown], pid pid) +fcntl$getownex(fd fd, cmd flags[fcntl_getownex], arg ptr[out, f_owner_ex]) +fcntl$setownex(fd fd, cmd flags[fcntl_setownex], arg ptr[in, f_owner_ex]) +fcntl$setsig(fd fd, cmd flags[fcntl_setsig], sig signalno) +fcntl$setlease(fd fd, cmd flags[fcntl_setlease], typ flags[flock_type]) +fcntl$notify(fd fd, cmd flags[fcntl_notify], typ flags[fcntl_notify]) +fcntl$setpipe(fd fd, cmd flags[fcntl_setpipe], sz intptr) + +ptrace(req flags[ptrace_req], pid pid) +ptrace$peek(req flags[ptrace_req_peek], pid pid, addr ptr[out, intptr]) +ptrace$poke(req flags[ptrace_req_poke], pid pid, addr ptr[out, intptr], data intptr) +ptrace$peekuser(req flags[ptrace_req_peekuser], pid pid, addr intptr) +ptrace$pokeuser(req flags[ptrace_req_peekuser], pid pid, addr intptr, data intptr) +ptrace$getregs(req flags[ptrace_req_getregs], pid pid, ignored intptr, data buffer[out]) +ptrace$getregset(req flags[ptrace_req_getregset], pid pid, what flags[pthread_regset], data ptr[in, iovec_out]) +ptrace$setregs(req flags[ptrace_req_setregs], pid pid, ignored intptr, data buffer[in]) +ptrace$setregset(req flags[ptrace_req_setregset], pid pid, what flags[pthread_regset], data ptr[in, iovec_in]) +ptrace$getsig(req flags[ptrace_req_getsig], pid pid, ignored intptr, data ptr[out, siginfo]) +ptrace$setsig(req flags[ptrace_req_setsig], pid pid, ignored intptr, data ptr[in, siginfo]) +ptrace$setopts(req flags[ptrace_req_setopts], pid pid, ignored intptr, flags flags[ptrace_options]) +ptrace$getenv(req flags[ptrace_req_getenv], pid pid, ignored intptr, data ptr[out, intptr]) +ptrace$cont(req flags[ptrace_req_cont], pid pid, ignored intptr, data intptr) + +io_setup(n int32, ctx ptr[out, io_ctx]) +io_destroy(ctx io_ctx) +io_getevents(ctx io_ctx, min_nr intptr, nr len[events], events ptr[out, array[io_event]], timeout ptr[in, timespec]) +io_submit(ctx io_ctx, nr len[iocbpp], iocbpp ptr[in, array[ptr[in, iocb]]]) +# TODO: iocb should be the same pointer passed to io_submit, so the pointer itself should be a resource +io_cancel(ctx io_ctx, iocb ptr[in, iocb], res ptr[out, io_event]) + +capget(hdr ptr[in, cap_header], data ptr[in, cap_data]) +capset(hdr ptr[in, cap_header], data ptr[in, cap_data]) + +# TODO: in some cases args are pointers and other interesting values +prctl(option flags[prctl_code], arg2 intptr, arg3 intptr, arg4 intptr, arg5 intptr) +arch_prctl(code flags[arch_prctl_code], addr ptr[in, ioctl_arg]) +seccomp(op flags[seccomp_op], flags flags[seccomp_flags], prog ptr[in, sock_fprog]) + +add_key(type string, desc string, payload buffer[in, opt], paylen len[payload], keyring flags[keyring_type]) key +request_key(type string, desc string, callout string, keyring flags[keyring_type]) key +# TODO: there must be something interesting in args (see security/keys/keyctl.c) +# arg2 is usually a key, but not always +keyctl(code flags[keyctl_code], key key, arg2 string, arg3 intptr, arg4 intptr, arg5 intptr) + +mq_open(name string, flags flags[mq_open_flags], mode flags[open_mode], attr ptr[in, mq_attr]) fd[mq] +mq_timedsend(mqd fd[mq], msg buffer[in], msglen len[msg], prio intptr, timeout ptr[in, timespec, opt]) +mq_timedreceive(mqd fd[mq], msg buffer[out], msglen len[msg], prio intptr, timeout ptr[in, timespec, opt]) +mq_notify(mqd fd[mq], notif ptr[in, sigevent]) +mq_getsetattr(mqd fd[mq], attr ptr[in, mq_attr], oldattr ptr[out, mq_attr, opt]) +mq_unlink(name string) + +msgget(key int32, flags flags[msgget_flags]) ipc[msq] +msgsnd(msqid ipc[msq], msgp buffer[in], flags flags[msg_flags]) +msgrcv(msqid ipc[msq], msgp buffer[out], sz len[msgp], typ intptr, flags flags[msg_flags]) +msgctl(msqid ipc[msq], cmd flags[msgctl_cmd], buf ptr[inout, msqid_ds]) + +semget(key int32, nsems intptr, flags flags[semget_flags]) ipc[sem] +semop(semid ipc[sem], ops ptr[in, array[sembuf]], nops len[ops]) +semtimedop(semid ipc[sem], ops ptr[in, array[sembuf]], nops len[ops], timeout ptr[in, timespec]) +semctl(semid ipc[sem], semnum intptr, cmd flags[semctl_cmd], arg ptr[in, semid_ds]) + +# The unused arg is unused by syscall (does not exist at all), +# but it helps to generate sane size values. +shmget(key int32, size len[unused], flags flags[shmget_flags], unused vma) ipc[shm] +shmat(shmid ipc[shm], addr vma, flags flags[shmat_flags]) +shmctl(shmid ipc[shm], cmd flags[shmctl_cmd], buf ptr[inout, shmid_ds]) +shmdt(addr vma) + +mknod(file filename, mode flags[mknod_mode], dev int32) +mknodat(dirfd fd[dir], file filename, mode flags[mknod_mode], dev int32) +chmod(file filename, mode flags[open_mode]) +fchmod(fd fd, mode flags[open_mode]) +fchmodat(dirfd fd[dir], file filename, mode flags[open_mode]) +chown(file filename, uid uid, gid gid) +lchown(file filename, uid uid, gid gid) +fchown(fd fd, uid uid, gid gid) +fchownat(dirfd fd[dir], file filename, uid uid, gid gid, flags flags[fchownat_flags]) +fallocate(fd fd, mode flags[fallocate_mode], off intptr, len intptr) +faccessat(dirfd fd[dir], pathname filename, mode flags[open_mode], flags flags[faccessat_flags]) +utime(filename filename, times ptr[in, utimbuf]) +utimes(filename filename, times ptr[in, itimerval]) +futimesat(dir fd[dir], pathname filename, times ptr[in, itimerval]) +utimensat(dir fd[dir], pathname filename, times ptr[in, itimerval], flags flags[utimensat_flags]) + +getgid() gid +getegid() gid +setuid(uid uid) +setgid(gid gid) +getuid() uid +geteuid() uid +setpgid(pid pid, pgid pid) +getpgid(pid pid) pid +getpgrp(pid pid) pid +getpid() pid +gettid() pid +setreuid(ruid uid, euid uid) +setregid(rgid gid, egid gid) +setresuid(ruid uid, euid uid, suid uid) +setresgid(rgid gid, egid gid, sgid gid) +getresuid(ruid ptr[out, uid], euid ptr[out, uid], suid ptr[out, uid]) +getresgid(rgid ptr[out, gid], egid ptr[out, gid], sgid ptr[out, gid]) +setfsuid(fsuid uid) +setfsgid(fsgid gid) +getgroups(size len[list], list ptr[inout, array[gid]]) +setgroups(size len[list], list ptr[in, array[gid]]) +personality(persona flags[personality_flags]) +# Don't mess with parent (fuzzer). If we ptrace attach to it, it will hang. +# If we setrlimit for parent, it will misbehave. Killing - the same. Nothing good. +#getppid() pid +#getsid(pid pid) pid +#setsid() pid + +inotify_init() fd[inotify] +inotify_init1(flags flags[inotify_flags]) fd[inotify] +inotify_add_watch(fd fd[inotify], file filename, mask flags[inotify_mask]) inotifydesc +inotify_rm_watch(fd fd[inotify], wd inotifydesc) +fanotify_init(flags flags[fanotify_flags], events flags[fanotify_events]) fd[fanotify] +fanotify_mark(fd fd[fanotify], flags flags[fanotify_mark], mask flags[fanotify_mask], fd fd[dir], path filename) + +link(old filename, new filename) +linkat(oldfd fd[dir], old filename, newfd fd[dir], new filename, flags flags[linkat_flags]) +symlinkat(old filename, newfd fd[dir], new filename) +symlink(old filename, new filename) +unlink(path filename) +unlinkat(fd fd[dir], path filename, flags flags[unlinkat_flags]) +readlink(path filename, buf buffer[out], siz len[buf]) +readlinkat(fd fd[dir], path filename, buf buffer[out], siz len[buf]) +rename(old filename, new filename) +renameat(oldfd fd[dir], old filename, newfd fd[dir], new filename) +renameat2(oldfd fd[dir], old filename, newfd fd[dir], new filename, flags flags[renameat2_flags]) +mkdir(path filename, mode flags[open_mode]) +mkdirat(fd fd[dir], path filename, mode flags[open_mode]) +rmdir(path filename) +truncate(file filename, len intptr) +ftruncate(fd fd, len intptr) +flock(fd fd, op flags[flock_op]) +fsync(fd fd) +fdatasync(fd fd) +sync() +syncfs(fd fd) +sync_file_range(fd fd, off intptr, nbytes intptr, flags flags[sync_file_flags]) +lookup_dcookie(cookie int64, buf buffer[out], len len[buf]) +getdents(fd fd[dir], ent buffer[out], count len[ent]) +getdents64(fd fd[dir], ent buffer[out], count len[ent]) +name_to_handle_at(fd fd[dir], file filename, handle ptr[in, file_handle], mnt ptr[out, int32], flags flags[name_to_handle_at_flags]) +open_by_handle_at(mountdirfd fd, handle ptr[in, file_handle], flags flags[open_flags]) + +mount(src filename, dst filename, type string, flags flags[mount_flags], data buffer[in]) +umount2(path filename, flags flags[umount_flags]) +pivot_root(new_root filename, put_old filename) + +# TODO: arg1 is a string for option=1 +sysfs(option flags[sysfs_opt], arg1 intptr, arg2 string) +statfs(path filename, buf buffer[out]) +fstatfs(fd fd, buf buffer[out]) + +uselib(lib filename) +init_module(mod string, len len[mod], args string) +finit_module(fd fd, args string, flags flags[finit_module_flags]) +delete_module(name string, flags flags[delete_module_flags]) +kexec_load(entry intptr, nr_segments len[segments], segments ptr[in, array[kexec_segment]], flags flags[kexec_load_flags]) +get_kernel_syms(table buffer[out]) +syslog(cmd flags[syslog_cmd], buf buffer[out, opt], len len[buf]) +uname(buf buffer[out]) +sysinfo(info buffer[out]) +ustat(dev intptr, buf ptr[out, ustat]) +acct(filename filename[opt]) + +getrusage(who flags[rusage_who], usage ptr[out, rusage]) +getrlimit(res flags[rlimit_type], rlim ptr[out, rlimit]) +setrlimit(res flags[rlimit_type], rlim ptr[in, rlimit]) +prlimit64(pid pid, res flags[rlimit_type], new ptr[in, rlimit, opt], old ptr[out, rlimit, opt]) + +iopl(level int8) +ioperm(from intptr, num intptr, on intptr) +# TODO: who can be group or user +ioprio_get(which flags[ioprio_which], who pid) +ioprio_set(which flags[ioprio_which], who pid, prio intptr) +setns(fd fd, type flags[ns_type]) + +setxattr(path filename, name string, val string, size len[val], flags flags[setxattr_flags]) +lsetxattr(path filename, name string, val string, size len[val], flags flags[setxattr_flags]) +fsetxattr(fd fd, name string, val string, size len[val], flags flags[setxattr_flags]) +getxattr(path filename, name string, val buffer[out], size len[val]) +lgetxattr(path filename, name string, val buffer[out], size len[val]) +fgetxattr(fd fd, name string, val buffer[out], size len[val]) +listxattr(path filename, list buffer[out], size len[list]) +llistxattr(path filename, list buffer[out], size len[list]) +flistxattr(fd fd, list buffer[out], size len[list]) +removexattr(path filename, name string) +lremovexattr(path filename, name string) +fremovexattr(fd fd, name string) + +time(t ptr[out, intptr]) +clock_gettime(id flags[clock_id], tp ptr[out, timespec]) +clock_settime(id flags[clock_id], tp ptr[in, timespec]) +clock_adjtime(id flags[clock_id], tx ptr[in, timex]) +clock_getres(id flags[clock_id], tp ptr[out, timespec]) +clock_nanosleep(id flags[clock_id], flags flags[timer_flags], rqtp ptr[in, timespec], rmtp ptr[out, timespec, opt]) +timer_create(id flags[clock_id], ev ptr[in, sigevent], timerid ptr[out, timerid]) +timer_gettime(timerid timerid, setting ptr[out, itimerspec]) +timer_getoverrun(timerid timerid) +timer_settime(timerid timerid, flags flags[timer_flags], new ptr[in, itimerspec], old ptr[out, itimerspec, opt]) +timer_delete(timerid timerid) +rt_sigaction(sig signalno, act ptr[in, sigaction], oact ptr[out, sigaction, opt], sigsetsize len[fake], fake ptr[out, sigset]) +rt_sigprocmask(how flags[sigprocmask_how], nset ptr[in, sigset], oset ptr[out, sigset, opt], sigsetsize len[nset]) +rt_sigreturn() +rt_sigpending(set ptr[out, sigset], sigsetsize len[set]) +rt_sigtimedwait(these ptr[in, sigset], info ptr[out, siginfo, opt], ts ptr[in, timespec], sigsetsize len[these]) +rt_sigsuspend(new ptr[in, sigset], sigsetsize len[new]) +rt_sigqueueinfo(pid pid, sig signalno, info ptr[in, siginfo]) +rt_tgsigqueueinfo(gid pid, tid pid, sig signalno, info ptr[in, siginfo]) +sigaltstack(ss vma, oss ptr[out, intptr, opt]) +tgkill(gid pid, tid pid, sig signalno) +tkill(tid pid, sig signalno) +pause() +alarm(seconds intptr) +nanosleep(req ptr[in, timespec], rem ptr[out, timespec, opt]) +getitimer(which flags[getitimer_which], cur ptr[out, itimerval]) +setitimer(which flags[getitimer_which], new ptr[in, itimerval], old ptr[out, itimerval, opt]) +exit(code intptr) +exit_group(code intptr) +waitid(which flags[waitid_which], pid pid, infop ptr[out, siginfo, opt], options flags[wait_options], ru ptr[out, rusage, opt]) +wait4(pid pid, status ptr[out, int32, opt], options flags[wait_options], ru ptr[out, rusage, opt]) +times(buf ptr[out, tms]) +# Can send signals to all processes (pid=-1). +#kill(pid pid, sig signalno) + +set_thread_area(info ptr[in, user_desc]) +get_thread_area(info ptr[in, user_desc]) +set_tid_address(tidptr ptr[out, int32]) +getpriority(which flags[priority_which], who pid) +setpriority(which flags[priority_which], who pid, prio intptr) +sched_getscheduler(pid pid) +sched_setscheduler(pid pid, policy flags[sched_policy], prio ptr[in, int32]) +sched_rr_get_interval(pid pid, tp ptr[out, timespec]) +sched_getparam(pid pid, prio ptr[out, int32]) +sched_setparam(pid pid, prio ptr[in, int32]) +sched_getaffinity(pid pid, cpusetsize len[mask], mask ptr[out, int64]) +sched_setaffinity(pid pid, cpusetsize len[mask], mask ptr[in, int64]) +sched_getattr(pid pid, attr ptr[out, sched_attr], size len[attr], flags flags[sched_attr_flags]) +sched_setattr(pid pid, attr ptr[in, sched_attr], flags flags[sched_attr_flags]) +sched_yield() + + + + +# TODO: need something better +ioctl_arg { + a0 intptr + a1 intptr + a2 intptr + a3 intptr + a4 intptr + a5 intptr + a6 intptr + a7 intptr +} + +pipefd { + rfd fd + wfd fd +} + +iovec_in { + addr buffer[in] + len len[addr, intptr] +} + +iovec_out { + addr buffer[out] + len len[addr, intptr] +} + +stat { + dev int16 + pad int16 + ino int32 + mode int16 + nlink int16 + uid uid + gid gid + rdev int16 + pad int16 + size int32 + blksize int32 + blocks int32 + atime int32 + ansec int32 + mtime int32 + mnsec int32 + ctime int32 + cnsec int32 + pad int32 + pad int32 +} + +pollfd { + fd fd + events int16 + revents int16 +} + +send_msghdr { + addr ptr[in, sockaddr] + addrlen len[addr, int32] + vec ptr[in, array[iovec_in]] + vlen len[vec, intptr] + ctrl ptr[in, cmsghdr] + ctrllen len[ctrl, intptr] + f flags[send_flags, int32] + len int32 +} + +recv_msghdr { + addr ptr[out, sockaddr] + addrlen len[addr, int32] + vec ptr[in, array[iovec_out]] + vlen len[vec, intptr] + ctrl buffer[out] + ctrllen len[ctrl, intptr] + f int32 + len int32 +} + +cmsghdr { + len intptr + level int32 + type int32 +# TODO: this is followed by an embed array of aux data, and len is length of the whole message +} + +sigset { + mask int64 +} + +sigset_size { + ss ptr[inout, sigset] + len len[ss, intptr] +} + +# prog knowns about this struct type +timespec { + sec intptr + nsec intptr +} + +# prog knowns about this struct type +timeval { + sec intptr + usec intptr +} + +itimerspec { + interv timespec + value timespec +} + +itimerval { + interv timeval + value timeval +} + +utimbuf { + actime intptr + modtime intptr +} + +io_event { + data int64 + obj int64 + res int64 + res2 int32 +} + +iocb { + data int64 + key int64 + op flags[lio_opcode, int16] + prio int16 + fd fd +# TODO: in 32-bit mode buf/reserv are still 64 bits + buf buffer[inout] + nbytes len[buf, int64] + offset int64 + reserv ptr[in, sigevent] + flags flags[iocb_flags, int32] + resfd fd[event] +} + +sigevent { + val vma + signo signalno + notify flags[sigev_notify, int32] + pad0 int64 + pad1 int64 + pad2 int64 + pad3 int64 + pad4 int64 + pad5 int64 + pad6 int64 + pad7 int64 +# TODO: this is actually +# TODO: function pointer needs special support +# union { +# int _pad[SIGEV_PAD_SIZE]; +# int _tid; +# struct { +# void (*_function)(sigval_t); +# void *_attribute;/* really pthread_attr_t */ +# } _sigev_thread; +# } _sigev_un; +} + +cap_header { + var flags[cap_version, int32] + pid pid +} + +cap_data { + eff0 int32 + perm0 int32 + inher0 int32 + eff1 int32 + perm1 int32 + inher1 int32 +} + +epoll_event { + ev flags[epoll_ev, int32] + pad int32 + data int64 +} + +# fd_set needs to be a separate type +fd_set { + mask0 int64 + mask1 int64 + mask2 int64 + mask3 int64 + mask4 int64 + mask5 int64 + mask6 int64 + mask7 int64 +} + +ipc_perm { + key int32 + uid uid + gid gid + cuid uid + cgid gid + mode int16 + seq int16 +} + +msqid_ds { + key int32 + uid uid + gid gid + cuid uid + cgid gid + mode int16 + seq int16 + stime intptr + rtime intptr + ctime intptr + cbytes intptr + qnum intptr + qbytes intptr + lspid pid + lrpid pid +} + +shmid_ds { + key int32 + uid uid + gid gid + cuid uid + cgid gid + mode int16 + seq int16 + segsz intptr + atime intptr + atime intptr + dtime intptr + ctime intptr + cpid pid + lpid pid + nattch intptr +} + +semid_ds { + key int32 + uid uid + gid gid + cuid uid + cgid gid + mode int16 + seq int16 + otime intptr + ctime intptr + nsems intptr +} + +sembuf { + num int16 + op int16 + flg flags[semop_flags, int64] +} + +sock_fprog { + len len[filter, intptr] + filter ptr[in, array[sock_filter]] +} + +sock_filter { + code int16 + jt int8 + kf int8 + k int32 +} + +file_handle { + bytes int32 + type int32 +# TODO: again embed array of variable length (bytes is the length) + handl0 int64 + handl1 int64 + handl2 int64 + handl3 int64 + handl4 int64 + handl5 int64 + handl6 int64 + handl7 int64 + handl8 int64 + handl9 int64 + handl10 int64 + handl11 int64 + handl12 int64 + handl13 int64 + handl14 int64 + handl15 int64 +} + +mq_attr { + flags intptr + maxmsg intptr + msgsize intptr + curmsg intptr + res0 intptr + res1 intptr + res2 intptr + res3 intptr +} + +kexec_segment { + buf buffer[in] + sz len[buf, intptr] +# TODO: this is address in kernel + mem intptr + memsz intptr +} + +robust_list { + next vma + off intptr + pend vma +} + +rusage { + utime timeval + stime timeval + maxrss intptr + ixrss intptr + idrss intptr + isrss intptr + minflt intptr + majflt intptr + nswap intptr + inblock intptr + oublock intptr + msgsnd intptr + msgrcv intptr + signals intptr + nvcsw intptr + nivcsw intptr +} + +rlimit { + soft intptr + hard intptr +} + +sigaction { +# TODO: function pointers need special support + handler intptr + mask sigset + flags flags[sigaction_flags, intptr] + restor intptr +} + +tms { + utime intptr + stime intptr + cutime intptr + cstime intptr +} + +siginfo { + signo signalno + errno int32 + code int32 + pad3 int32 +# actual size is 128 bytes +} + +timex { + stuff0 intptr + stuff1 intptr + stuff2 intptr + stuff3 intptr + stuff4 intptr + stuff5 intptr + stuff6 intptr + stuff7 intptr + stuff8 intptr + stuff9 intptr + stuff10 intptr + stuff11 intptr + stuff12 intptr + stuff13 intptr + stuff14 intptr + stuff15 intptr + stuff16 intptr + stuff17 intptr + stuff18 intptr + stuff19 intptr + stuff20 intptr + stuff21 intptr + stuff22 intptr + stuff23 intptr + stuff24 intptr + stuff25 intptr +} + +ustat { + free int32 + inode intptr + nampac0 int32 + nampac1 int32 + nampac2 int32 +} + +user_desc { + entry int32 + base int32 + limit int32 + flags int8 +} + +sched_attr { + size flags[sched_attr_size, int32] + policy flags[sched_policy, int32] + flags flags[sched_attr_flags2, int64] + nice int32 + prio int32 + runtime int64 + deadlin int64 + period int64 +} + +flock { + type flags[flock_type, int16] + whence flags[seek_whence, int16] + start intptr + len intptr + pid pid +} + + +f_owner_ex { + type flags[f_owner_type, int32] + pid pid +} + + + + +open_flags = O_RDONLY, O_WRONLY, O_RDWR, O_APPEND, O_ASYNC, O_CLOEXEC, O_CREAT, O_DIRECT, O_DIRECTORY, O_EXCL, O_LARGEFILE, O_NOATIME, O_NOCTTY, O_NOFOLLOW, O_NONBLOCK, O_PATH, O_SYNC, O_TRUNC +open_mode = S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH +madvise_flags = MADV_NORMAL, MADV_RANDOM, MADV_SEQUENTIAL, MADV_WILLNEED, MADV_DONTNEED, MADV_REMOVE, MADV_DONTFORK, MADV_DOFORK, MADV_HWPOISON, MADV_SOFT_OFFLINE, MADV_MERGEABLE, MADV_UNMERGEABLE, MADV_HUGEPAGE, MADV_NOHUGEPAGE, MADV_DONTDUMP, MADV_DODUMP +fadvise_flags = POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL, POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, POSIX_FADV_DONTNEED +move_pages_flags = MPOL_MF_MOVE, MPOL_MF_MOVE_ALL +msync_flags = MS_ASYNC, MS_SYNC, MS_INVALIDATE +mmap_prot = PROT_EXEC, PROT_READ, PROT_WRITE +mmap_flags = MAP_SHARED, MAP_PRIVATE, MAP_32BIT, MAP_ANONYMOUS, MAP_DENYWRITE, MAP_EXECUTABLE, MAP_FILE, MAP_FIXED, MAP_GROWSDOWN, MAP_HUGETLB, MAP_LOCKED, MAP_NONBLOCK, MAP_NORESERVE, MAP_POPULATE, MAP_STACK, MAP_UNINITIALIZED +mremap_flags = MREMAP_MAYMOVE, MREMAP_FIXED +mbind_mode = MPOL_DEFAULT, MPOL_BIND, MPOL_INTERLEAVE, MPOL_PREFERRED, MPOL_F_STATIC_NODES, MPOL_F_RELATIVE_NODES +mbind_flags = MPOL_MF_STRICT, MPOL_MF_MOVE, MPOL_MF_MOVE_ALL +pipe_flags = O_NONBLOCK, O_CLOEXEC +mlockall_flags = MCL_CURRENT, MCL_FUTURE +dup_flags = O_CLOEXEC +splice_flags = SPLICE_F_MOVE, SPLICE_F_NONBLOCK, SPLICE_F_MORE, SPLICE_F_GIFT +seek_whence = SEEK_SET, SEEK_CUR, SEEK_END, SEEK_DATA, SEEK_HOLE +socket_domain = AF_LOCAL, AF_INET, AF_INET6, AF_IPX, AF_NETLINK, AF_X25, AF_AX25, AF_ATMPVC, AF_APPLETALK, AF_PACKET +socket_type = SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET, SOCK_RAW, SOCK_RDM, SOCK_PACKET, SOCK_NONBLOCK, SOCK_CLOEXEC +accept_flags = SOCK_NONBLOCK, SOCK_CLOEXEC +shutdown_flags = SHUT_RD, SHUT_WR +send_flags = MSG_CONFIRM, MSG_DONTROUTE, MSG_DONTWAIT, MSG_EOR, MSG_MORE, MSG_NOSIGNAL, MSG_OOB +recv_flags = MSG_CMSG_CLOEXEC, MSG_DONTWAIT, MSG_ERRQUEUE, MSG_OOB, MSG_PEEK, MSG_TRUNC, MSG_WAITALL, MSG_WAITFORONE +fcntl_commands = F_DUPFD, F_DUPFD_CLOEXEC, F_GETFD, F_SETFD, F_GETFL, F_SETFL, F_SETLK, F_SETLKW, F_GETLK, F_GETOWN, F_SETOWN, F_GETOWN_EX, F_SETOWN_EX, F_GETSIG, F_SETSIG, F_SETLEASE, F_GETLEASE, F_NOTIFY, F_SETPIPE_SZ, F_GETPIPE_SZ +signalfd_flags = SFD_NONBLOCK, SFD_CLOEXEC +eventfd_flags = EFD_CLOEXEC, EFD_NONBLOCK, EFD_SEMAPHORE +timerfd_create_flags = TFD_NONBLOCK, TFD_CLOEXEC +timerfd_settime_flags = TFD_TIMER_ABSTIME +clock_type = CLOCK_REALTIME, CLOCK_REALTIME_COARSE, CLOCK_MONOTONIC, CLOCK_MONOTONIC_COARSE, CLOCK_MONOTONIC_RAW, CLOCK_BOOTTIME, CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID +lio_opcode = IOCB_CMD_PREAD, IOCB_CMD_PWRITE, IOCB_CMD_FSYNC, IOCB_CMD_FDSYNC, IOCB_CMD_PREADX, IOCB_CMD_POLL, IOCB_CMD_NOOP, IOCB_CMD_PREADV, IOCB_CMD_PWRITEV +iocb_flags = IOCB_FLAG_RESFD +sigev_notify = SIGEV_NONE, SIGEV_SIGNAL, SIGEV_THREAD +cap_version = 0x19980330, 0x20071026, 0x20080522 +prctl_code = PR_CAPBSET_READ, PR_CAPBSET_DROP, PR_SET_CHILD_SUBREAPER, PR_GET_CHILD_SUBREAPER, PR_SET_DUMPABLE, PR_GET_DUMPABLE, PR_SET_ENDIAN, PR_GET_ENDIAN, PR_SET_FPEMU, PR_GET_FPEMU, PR_SET_FPEXC, PR_GET_FPEXC, PR_SET_KEEPCAPS, PR_GET_KEEPCAPS, PR_SET_NAME, PR_GET_NAME, PR_SET_NO_NEW_PRIVS, PR_GET_NO_NEW_PRIVS, PR_SET_PDEATHSIG, PR_GET_PDEATHSIG, PR_SET_PTRACER, PR_SET_SECCOMP, PR_GET_SECCOMP, PR_SET_SECUREBITS, PR_GET_SECUREBITS, PR_GET_TID_ADDRESS, PR_SET_TIMERSLACK, PR_GET_TIMERSLACK, PR_SET_TIMING, PR_GET_TIMING, PR_TASK_PERF_EVENTS_DISABLE, PR_TASK_PERF_EVENTS_ENABLE, PR_SET_TSC, PR_GET_TSC, PR_SET_UNALIGN, PR_GET_UNALIGN, PR_MCE_KILL, PR_MCE_KILL_GET, PR_SET_MM +arch_prctl_code = ARCH_SET_FS, ARCH_GET_FS, ARCH_SET_GS, ARCH_GET_GS +keyctl_code = KEYCTL_GET_KEYRING_ID, KEYCTL_JOIN_SESSION_KEYRING, KEYCTL_UPDATE, KEYCTL_REVOKE, KEYCTL_CHOWN, KEYCTL_SETPERM, KEYCTL_DESCRIBE, KEYCTL_CLEAR, KEYCTL_LINK, KEYCTL_UNLINK, KEYCTL_SEARCH, KEYCTL_READ, KEYCTL_INSTANTIATE, KEYCTL_NEGATE, KEYCTL_SET_REQKEY_KEYRING, KEYCTL_SET_TIMEOUT, KEYCTL_ASSUME_AUTHORITY +epoll_flags = EPOLL_CLOEXEC +epoll_op = EPOLL_CTL_ADD, EPOLL_CTL_MOD, EPOLL_CTL_DEL +epoll_ev = EPOLLIN, EPOLLOUT, EPOLLRDHUP, EPOLLPRI, EPOLLERR, EPOLLHUP, EPOLLET, EPOLLONESHOT +msgget_flags = IPC_CREAT, IPC_EXCL, S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH +msg_flags = IPC_NOWAIT, MSG_EXCEPT, MSG_NOERROR +msgctl_cmd = IPC_STAT, IPC_SET, IPC_RMID, IPC_INFO, MSG_INFO, MSG_STAT +semget_flags = IPC_CREAT, IPC_EXCL, S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH +semop_flags = IPC_NOWAIT, SEM_UNDO +semctl_cmd = IPC_STAT, IPC_SET, IPC_RMID, IPC_INFO, SEM_INFO, SEM_STAT, GETALL, GETNCNT, GETPID, GETVAL, GETZCNT, SETALL, SETVAL +shmget_flags = IPC_CREAT, IPC_EXCL, SHM_HUGETLB, SHM_NORESERVE, S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH +shmat_flags = SHM_RND, SHM_RDONLY, SHM_REMAP +shmctl_cmd = IPC_STAT, IPC_SET, IPC_RMID, IPC_INFO, SHM_INFO, SHM_STAT, SHM_LOCK, SHM_UNLOCK +mknod_mode = S_IFREG, S_IFCHR, S_IFBLK, S_IFIFO, S_IFSOCK, S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH +fchownat_flags = AT_EMPTY_PATH, AT_SYMLINK_NOFOLLOW +fallocate_mode = 0, FALLOC_FL_KEEP_SIZE, FALLOC_FL_PUNCH_HOLE +linkat_flags = AT_EMPTY_PATH, AT_SYMLINK_FOLLOW +unlinkat_flags = 0, AT_REMOVEDIR +renameat2_flags = RENAME_EXCHANGE, RENAME_NOREPLACE, RENAME_WHITEOUT +flock_op = LOCK_SH, LOCK_EX, LOCK_UN, LOCK_NB +seccomp_op = SECCOMP_SET_MODE_STRICT, SECCOMP_SET_MODE_FILTER +seccomp_flags = 0, SECCOMP_FILTER_FLAG_TSYNC +name_to_handle_at_flags = AT_EMPTY_PATH, AT_SYMLINK_FOLLOW, AT_FDCWD +mq_open_flags = O_RDONLY, O_WRONLY, O_RDWR, O_NONBLOCK, O_CREAT, O_EXCL, O_CREAT +mount_flags = MS_BIND, MS_DIRSYNC, MS_MANDLOCK, MS_MOVE, MS_NOATIME, MS_NODEV, MS_NODIRATIME, MS_NOEXEC, MS_NOSUID, MS_RDONLY, MS_RELATIME, MS_REMOUNT, MS_SILENT, MS_STRICTATIME, MS_SYNCHRONOUS +umount_flags = MNT_FORCE, MNT_DETACH, MNT_EXPIRE, UMOUNT_NOFOLLOW +finit_module_flags = MODULE_INIT_IGNORE_MODVERSIONS, MODULE_INIT_IGNORE_VERMAGIC +delete_module_flags = O_NONBLOCK, O_TRUNC +kexec_load_flags = KEXEC_ON_CRASH, KEXEC_PRESERVE_CONTEXT, KEXEC_ARCH_386, KEXEC_ARCH_X86_64, KEXEC_ARCH_PPC, KEXEC_ARCH_PPC64, KEXEC_ARCH_IA_64, KEXEC_ARCH_ARM, KEXEC_ARCH_S390, KEXEC_ARCH_SH, KEXEC_ARCH_MIPS, KEXEC_ARCH_MIPS_LE +keyring_type = KEY_SPEC_THREAD_KEYRING, KEY_SPEC_PROCESS_KEYRING, KEY_SPEC_SESSION_KEYRING, KEY_SPEC_USER_KEYRING, KEY_SPEC_USER_SESSION_KEYRING +inotify_flags = IN_NONBLOCK, IN_CLOEXEC +inotify_mask = IN_ACCESS, IN_ATTRIB, IN_CLOSE_WRITE, IN_CLOSE_NOWRITE, IN_CREATE, IN_DELETE, IN_DELETE_SELF, IN_MODIFY, IN_MOVE_SELF, IN_MOVED_FROM, IN_MOVED_TO, IN_OPEN, IN_DONT_FOLLOW, IN_EXCL_UNLINK, IN_MASK_ADD, IN_ONESHOT, IN_ONLYDIR +fanotify_flags = FAN_CLASS_PRE_CONTENT, FAN_CLASS_CONTENT, FAN_CLASS_NOTIF, FAN_CLOEXEC, FAN_NONBLOCK, FAN_UNLIMITED_QUEUE, FAN_UNLIMITED_MARKS +fanotify_events = O_RDONLY, O_WRONLY, O_RDWR, O_LARGEFILE, O_CLOEXEC, O_APPEND, O_DSYNC, O_NOATIME, O_NONBLOCK, O_SYNC +fanotify_mark = FAN_MARK_ADD, FAN_MARK_REMOVE, FAN_MARK_FLUSH, FAN_MARK_DONT_FOLLOW, FAN_MARK_ONLYDIR, FAN_MARK_MOUNT, FAN_MARK_IGNORED_MASK, FAN_MARK_IGNORED_SURV_MODIFY +fanotify_mask = FAN_ACCESS, FAN_MODIFY, FAN_CLOSE_WRITE, FAN_CLOSE_NOWRITE, FAN_OPEN, FAN_OPEN_PERM, FAN_ACCESS_PERM, FAN_ONDIR, FAN_EVENT_ON_CHILD +faccessat_flags = AT_EACCESS, AT_SYMLINK_NOFOLLOW +clone_flags = CLONE_CHILD_CLEARTID, CLONE_CHILD_SETTID, CLONE_FILES, CLONE_FS, CLONE_IO, CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWNS, CLONE_NEWPID, CLONE_NEWUTS, CLONE_PARENT, CLONE_PARENT_SETTID, CLONE_PTRACE, CLONE_SETTLS, CLONE_SIGHAND, CLONE_SYSVSEM, CLONE_THREAD, CLONE_UNTRACED, CLONE_VFORK, CLONE_VM +futex_op = FUTEX_WAIT, FUTEX_WAIT_BITSET, FUTEX_WAKE, FUTEX_REQUEUE, FUTEX_CMP_REQUEUE +sync_file_flags = SYNC_FILE_RANGE_WAIT_BEFORE, SYNC_FILE_RANGE_WRITE, SYNC_FILE_RANGE_WAIT_AFTER +kcmp_flags = KCMP_FILE, KCMP_FILES, KCMP_FS, KCMP_IO, KCMP_SIGHAND, KCMP_SYSVSEM, KCMP_VM +rusage_who = RUSAGE_SELF, RUSAGE_CHILDREN, RUSAGE_THREAD +rlimit_type = RLIMIT_AS, RLIMIT_CORE, RLIMIT_CPU, RLIMIT_DATA, RLIMIT_FSIZE, RLIMIT_LOCKS, RLIMIT_MEMLOCK, RLIMIT_MSGQUEUE, RLIMIT_NICE, RLIMIT_NOFILE, RLIMIT_NPROC, RLIMIT_RSS, RLIMIT_RTPRIO, RLIMIT_RTTIME, RLIMIT_SIGPENDING, RLIMIT_STACK +# The ones that disable console output are intentionally omitted. +syslog_cmd = SYSLOG_ACTION_CLOSE, SYSLOG_ACTION_OPEN, SYSLOG_ACTION_READ, SYSLOG_ACTION_READ_ALL, SYSLOG_ACTION_READ_CLEAR, SYSLOG_ACTION_CLEAR, SYSLOG_ACTION_CONSOLE_ON, SYSLOG_ACTION_SIZE_UNREAD, SYSLOG_ACTION_SIZE_BUFFER +ioprio_which = IOPRIO_WHO_PROCESS, IOPRIO_WHO_PGRP, IOPRIO_WHO_USER +setxattr_flags = XATTR_CREATE, XATTR_REPLACE +ns_type = 0, CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWUTS +personality_flags = SYZ_PER_LINUX, SYZ_PER_SVR4, SYZ_PER_SVR3, SYZ_PER_OSR5, SYZ_PER_WYSEV386, SYZ_PER_ISCR4, SYZ_PER_BSD, SYZ_PER_XENIX, SYZ_PER_LINUX32, SYZ_PER_IRIX32, SYZ_PER_IRIXN32, SYZ_PER_IRIX64, SYZ_PER_RISCOS, SYZ_PER_SOLARIS, SYZ_PER_UW7, SYZ_PER_OSF4, SYZ_PER_HPUX, ADDR_NO_RANDOMIZE, MMAP_PAGE_ZERO, ADDR_COMPAT_LAYOUT, READ_IMPLIES_EXEC, ADDR_LIMIT_32BIT, SHORT_INODE, WHOLE_SECONDS, STICKY_TIMEOUTS, ADDR_LIMIT_3GB +sysfs_opt = 1, 2, 3 +clock_id = CLOCK_REALTIME, CLOCK_REALTIME_COARSE, CLOCK_MONOTONIC, CLOCK_MONOTONIC_COARSE, CLOCK_MONOTONIC_RAW, CLOCK_BOOTTIME, CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID +sigprocmask_how = SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK +getitimer_which = ITIMER_REAL, ITIMER_VIRTUAL, ITIMER_PROF +wait_options = WNOHANG, WUNTRACED, WCONTINUED, WEXITED, WSTOPPED, WCONTINUED, WNOHANG, WNOWAIT, __WCLONE, __WALL, __WNOTHREAD +waitid_which = P_PID, P_PGID, P_ALL +sigaction_flags = SA_NOCLDSTOP,SA_NOCLDWAIT, SA_NODEFER, SA_ONSTACK, SA_RESETHAND, SA_RESTART, SA_SIGINFO +timer_flags = 0, TIMER_ABSTIME +utimensat_flags = 0, AT_SYMLINK_NOFOLLOW +priority_which = PRIO_PROCESS, PRIO_PGRP, PRIO_USER +sched_policy = SCHED_OTHER, SCHED_BATCH, SCHED_IDLE, SCHED_FIFO, SCHED_RR, SCHED_DEADLINE +sched_attr_flags = 0 +sched_attr_flags2 = 0, SCHED_FLAG_RESET_ON_FORK +sched_attr_size = 48 +mempolicy_flags = 0, MPOL_F_MEMS_ALLOWED, MPOL_F_ADDR, MPOL_F_NODE +ptrace_req = PTRACE_TRACEME, PTRACE_LISTEN, PTRACE_KILL, PTRACE_INTERRUPT, PTRACE_ATTACH, PTRACE_DETACH +ptrace_req_peek = PTRACE_PEEKTEXT, PTRACE_PEEKDATA +ptrace_req_poke = PTRACE_POKETEXT, PTRACE_POKEDATA +ptrace_req_peekuser = PTRACE_PEEKUSER +ptrace_req_pokeuser = PTRACE_POKEUSER +ptrace_req_getregs = PTRACE_GETREGS, PTRACE_GETFPREGS +ptrace_req_getregset = PTRACE_GETREGSET +ptrace_req_setregs = PTRACE_SETREGS, PTRACE_SETFPREGS +ptrace_req_setregset = PTRACE_SETREGSET +ptrace_req_getsig = PTRACE_GETSIGINFO +ptrace_req_setsig = PTRACE_SETSIGINFO +ptrace_req_setopts = PTRACE_SETOPTIONS, PTRACE_SEIZE +ptrace_req_getenv = PTRACE_GETEVENTMSG +ptrace_req_cont = PTRACE_CONT, PTRACE_SYSCALL, PTRACE_SINGLESTEP, PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP +pthread_regset = NT_PRSTATUS, NT_PRFPREG, NT_PRPSINFO, NT_TASKSTRUCT, NT_AUXV, NT_386_TLS, NT_386_IOPERM, NT_X86_XSTATE +ptrace_options = PTRACE_O_EXITKILL, PTRACE_O_TRACECLONE, PTRACE_O_TRACEEXEC, PTRACE_O_TRACEEXIT, PTRACE_O_TRACEFORK, PTRACE_O_TRACESYSGOOD, PTRACE_O_TRACEVFORK, PTRACE_O_TRACEVFORKDONE +fcntl_dupfd = F_DUPFD, F_DUPFD_CLOEXEC +fcntl_getflags = F_GETFD, F_GETFL, F_GETSIG, F_GETLEASE, F_GETPIPE_SZ +fcntl_setflags = F_SETFD +fcntl_setstatus = F_SETFL +fcntl_lock = F_SETLK, F_SETLKW, F_GETLK +fcntl_getown = F_GETOWN +fcntl_setown = F_SETOWN +fcntl_getownex = F_GETOWN_EX +fcntl_setownex = F_SETOWN_EX +fcntl_setsig = F_SETSIG +fcntl_setlease = F_SETLEASE +fcntl_setpipe = F_SETPIPE_SZ +fcntl_flags = FD_CLOEXEC +fcntl_status = O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, O_NONBLOCK +flock_type = F_RDLCK, F_WRLCK, F_UNLCK +f_owner_type = F_OWNER_TID, F_OWNER_PID, F_OWNER_PGRP +fcntl_notify = DN_MULTISHOT, DN_ACCESS, DN_MODIFY, DN_CREATE, DN_DELETE, DN_RENAME, DN_ATTRIB + + + + +# Values that are not available with outdated headers. +define MAP_UNINITIALIZED 0x4000000 +define MADV_SOFT_OFFLINE 101 +define MPOL_F_STATIC_NODES (1 << 15) +define MPOL_F_RELATIVE_NODES (1 << 14) +define PTRACE_SYSEMU 31 +define PTRACE_SYSEMU_SINGLESTEP 32 +define KCMP_FILE 0 +define KCMP_VM 1 +define KCMP_FILES 2 +define KCMP_FS 3 +define KCMP_SIGHAND 4 +define KCMP_IO 5 +define KCMP_SYSVSEM 6 +define KEY_SPEC_THREAD_KEYRING -1 +define KEY_SPEC_PROCESS_KEYRING -2 +define KEY_SPEC_SESSION_KEYRING -3 +define KEY_SPEC_USER_KEYRING -4 +define KEY_SPEC_USER_SESSION_KEYRING -5 +define KEY_SPEC_GROUP_KEYRING -6 +define KEY_SPEC_REQKEY_AUTH_KEY -7 +define KEY_SPEC_REQUESTOR_KEYRING -8 +define KEY_REQKEY_DEFL_NO_CHANGE -1 +define KEY_REQKEY_DEFL_DEFAULT 0 +define KEY_REQKEY_DEFL_THREAD_KEYRING 1 +define KEY_REQKEY_DEFL_PROCESS_KEYRING 2 +define KEY_REQKEY_DEFL_SESSION_KEYRING 3 +define KEY_REQKEY_DEFL_USER_KEYRING 4 +define KEY_REQKEY_DEFL_USER_SESSION_KEYRING 5 +define KEY_REQKEY_DEFL_GROUP_KEYRING 6 +define KEY_REQKEY_DEFL_REQUESTOR_KEYRING 7 +define KEYCTL_GET_KEYRING_ID 0 +define KEYCTL_JOIN_SESSION_KEYRING 1 +define KEYCTL_UPDATE 2 +define KEYCTL_REVOKE 3 +define KEYCTL_CHOWN 4 +define KEYCTL_SETPERM 5 +define KEYCTL_DESCRIBE 6 +define KEYCTL_CLEAR 7 +define KEYCTL_LINK 8 +define KEYCTL_UNLINK 9 +define KEYCTL_SEARCH 10 +define KEYCTL_READ 11 +define KEYCTL_INSTANTIATE 12 +define KEYCTL_NEGATE 13 +define KEYCTL_SET_REQKEY_KEYRING 14 +define KEYCTL_SET_TIMEOUT 15 +define KEYCTL_ASSUME_AUTHORITY 16 +define KEYCTL_GET_SECURITY 17 +define KEYCTL_SESSION_TO_PARENT 18 +define KEYCTL_REJECT 19 +define KEYCTL_INSTANTIATE_IOV 20 +define KEYCTL_INVALIDATE 21 +define KEYCTL_GET_PERSISTENT 22 +define RENAME_NOREPLACE (1 << 0) +define RENAME_EXCHANGE (1 << 1) +define RENAME_WHITEOUT (1 << 2) +define IOCB_CMD_PREADX 4 +define IOCB_CMD_POLL 5 +define IOPRIO_WHO_PROCESS 1 +define IOPRIO_WHO_PGRP 2 +define IOPRIO_WHO_USER 3 +define MODULE_INIT_IGNORE_MODVERSIONS 1 +define MODULE_INIT_IGNORE_VERMAGIC 2 +define SYSLOG_ACTION_CLOSE 0 +define SYSLOG_ACTION_OPEN 1 +define SYSLOG_ACTION_READ 2 +define SYSLOG_ACTION_READ_ALL 3 +define SYSLOG_ACTION_READ_CLEAR 4 +define SYSLOG_ACTION_CLEAR 5 +define SYSLOG_ACTION_CONSOLE_OFF 6 +define SYSLOG_ACTION_CONSOLE_ON 7 +define SYSLOG_ACTION_CONSOLE_LEVEL 8 +define SYSLOG_ACTION_SIZE_UNREAD 9 +define SYSLOG_ACTION_SIZE_BUFFER 10 +define SYZ_PER_LINUX 0x0000 +define SYZ_PER_SVR4 0x0001 +define SYZ_PER_SVR3 0x0002 +define SYZ_PER_OSR5 0x0003 +define SYZ_PER_WYSEV386 0x0004 +define SYZ_PER_ISCR4 0x0005 +define SYZ_PER_BSD 0x0006 +define SYZ_PER_XENIX 0x0007 +define SYZ_PER_LINUX32 0x0008 +define SYZ_PER_IRIX32 0x0009 +define SYZ_PER_IRIXN32 0x000a +define SYZ_PER_IRIX64 0x000b +define SYZ_PER_RISCOS 0x000c +define SYZ_PER_SOLARIS 0x000d +define SYZ_PER_UW7 0x000e +define SYZ_PER_OSF4 0x000f +define SYZ_PER_HPUX 0x0010 +define SCHED_DEADLINE 6 +define SCHED_FLAG_RESET_ON_FORK 1 + +# Not yet implemented syscalls +#define __NR_clone 56 +#define __NR_fork 57 +#define __NR_vfork 58 +#define __NR_execve 59 +#define __NR_getcwd 79 +#define __NR_chdir 80 +#define __NR_fchdir 81 +#define __NR_umask 95 +#define __NR_vhangup 153 +#define __NR_modify_ldt 154 +#define __NR__sysctl 156 +#define __NR_adjtimex 159 +#define __NR_chroot 161 +#define __NR_swapon 167 +#define __NR_swapoff 168 +#define __NR_quotactl 179 +#define __NR_nfsservctl 180 +#define __NR_perf_event_open 298 +#define __NR_getcpu 309 +#define __NR_process_vm_readv 310 +#define __NR_process_vm_writev 311 + + + + +# Probably no sense in calling there. +# Also affect system-wide state, so not reproducble anyway. +#define __NR_gettimeofday 96 +#define __NR_settimeofday 164 +#define __NR_reboot 169 +#define __NR_sethostname 170 +#define __NR_setdomainname 171 +#define __NR_sched_get_priority_max 146 +#define __NR_sched_get_priority_min 147 + diff --git a/sysgen/parser.go b/sysgen/parser.go new file mode 100644 index 000000000..92c27c58a --- /dev/null +++ b/sysgen/parser.go @@ -0,0 +1,92 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package main + +import ( + "bufio" + "fmt" + "io" + "os" +) + +type Parser struct { + r *bufio.Scanner + s string + i int + l int +} + +func NewParser(r io.Reader) *Parser { + return &Parser{r: bufio.NewScanner(r)} +} + +func (p *Parser) Scan() bool { + if !p.r.Scan() { + if err := p.r.Err(); err != nil { + failf("failed to read input file: %v", err) + } + return false + } + p.s = p.r.Text() + p.i = 0 + p.l++ + return true +} + +func (p *Parser) Str() string { + return p.s +} + +func (p *Parser) EOF() bool { + return p.i == len(p.s) +} + +func (p *Parser) Char() byte { + if p.EOF() { + p.failf("unexpected eof") + } + return p.s[p.i] +} + +func (p *Parser) Parse(ch byte) { + if p.EOF() { + p.failf("want %s, got EOF", string(ch)) + } + if p.s[p.i] != ch { + p.failf("want '%v', got '%v'", string(ch), string(p.s[p.i])) + } + p.i++ + p.SkipWs() +} + +func (p *Parser) SkipWs() { + for p.i < len(p.s) && (p.s[p.i] == ' ' || p.s[p.i] == '\t') { + p.i++ + } +} + +func (p *Parser) Ident() string { + i := p.i + for p.i < len(p.s) && + (p.s[p.i] >= 'a' && p.s[p.i] <= 'z' || + p.s[p.i] >= 'A' && p.s[p.i] <= 'Z' || + p.s[p.i] >= '0' && p.s[p.i] <= '9' || + p.s[p.i] == '_' || p.s[p.i] == '$') { // $ is for n-way syscalls (like ptrace$peek) + p.i++ + } + if i == p.i { + p.failf("failed to parse identifier at pos %v", i) + } + if ch := p.s[i]; ch >= '0' && ch <= '9' { + // p.failf("identifier starts with a digit at pos %v", i) + } + s := p.s[i:p.i] + p.SkipWs() + return s +} + +func (p *Parser) failf(msg string, args ...interface{}) { + fmt.Fprintf(os.Stderr, "line #%v: %v\n", p.l, p.s) + failf(msg, args...) +} diff --git a/sysgen/sysgen.go b/sysgen/sysgen.go new file mode 100644 index 000000000..e8a3c62a1 --- /dev/null +++ b/sysgen/sysgen.go @@ -0,0 +1,649 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package main + +import ( + "bufio" + "bytes" + "fmt" + "go/format" + "io" + "io/ioutil" + "os" + "os/exec" + "sort" + "strconv" + "strings" +) + +func main() { + if len(os.Args) != 2 { + failf("usage: gen input_file") + } + inf, err := os.Open(os.Args[1]) + if err != nil { + failf("failed to open input file: %v", err) + } + defer inf.Close() + + includes, defines, syscalls, structs, unnamed, flags := parse(bufio.NewReader(inf)) + intFlags, flagVals := compileFlags(includes, defines, flags) + + out := new(bytes.Buffer) + generate(syscalls, structs, unnamed, intFlags, out) + writeSource("sys.go", out.Bytes()) + + out = new(bytes.Buffer) + generateConsts(flagVals, out) + writeSource("../prog/consts.go", out.Bytes()) + + out = new(bytes.Buffer) + generateHeader(syscalls, out) + writeFile("../executor/syscalls.h", out.Bytes()) +} + +type Syscall struct { + Name string + CallName string + Args [][]string + Ret []string +} + +type Struct struct { + Name string + Flds [][]string +} + +type Flag struct { + Name string + Values []string +} + +func generate(syscalls []Syscall, structs map[string]Struct, unnamed map[string][]string, flags map[string][]string, out io.Writer) { + fmt.Fprintf(out, "// AUTOGENERATED FILE\n") + fmt.Fprintf(out, "package sys\n\n") + + fmt.Fprintf(out, "var Calls = []*Call {\n") + for i, s := range syscalls { + fmt.Fprintf(out, "&Call{ID: %v, Name: \"%v\", CallName: \"%v\"", i, s.Name, s.CallName) + if len(s.Ret) != 0 { + fmt.Fprintf(out, ", Ret: ") + generateArg("ret", s.Ret[0], s.Ret[1:], structs, unnamed, flags, false, out) + } + fmt.Fprintf(out, ", Args: []Type{") + for i, a := range s.Args { + if i != 0 { + fmt.Fprintf(out, ", ") + } + generateArg(a[0], a[1], a[2:], structs, unnamed, flags, false, out) + } + fmt.Fprintf(out, "}},\n") + } + fmt.Fprintf(out, "}\n") +} + +func generateArg(name, typ string, a []string, structs map[string]Struct, unnamed map[string][]string, flags map[string][]string, isField bool, out io.Writer) { + name = "\"" + name + "\"" + opt := false + for i, v := range a { + if v == "opt" { + opt = true + copy(a[i:], a[i+1:]) + a = a[:len(a)-1] + break + } + } + common := func() string { + return fmt.Sprintf("TypeCommon: TypeCommon{TypeName: %v, IsOptional: %v}", name, opt) + } + switch typ { + case "fd": + if len(a) == 0 { + a = append(a, "") + } + if want := 1; len(a) != want { + failf("wrong number of arguments for %v arg %v want %v, got %v", typ, name, want, len(a)) + } + fmt.Fprintf(out, "ResourceType{%v, Kind: ResFD, Subkind: %v}", common(), fmtFdKind(a[0])) + case "io_ctx": + if want := 0; len(a) != want { + failf("wrong number of arguments for %v arg %v want %v, got %v", typ, name, want, len(a)) + } + fmt.Fprintf(out, "ResourceType{%v, Kind: ResIOCtx}", common()) + case "ipc": + if want := 1; len(a) != want { + failf("wrong number of arguments for %v arg %v want %v, got %v", typ, name, want, len(a)) + } + fmt.Fprintf(out, "ResourceType{%v, Kind: ResIPC, Subkind: %v}", common(), fmtIPCKind(a[0])) + case "key": + if want := 0; len(a) != want { + failf("wrong number of arguments for %v arg %v want %v, got %v", typ, name, want, len(a)) + } + fmt.Fprintf(out, "ResourceType{%v, Kind: ResKey}", common()) + case "inotifydesc": + if want := 0; len(a) != want { + failf("wrong number of arguments for %v arg %v want %v, got %v", typ, name, want, len(a)) + } + fmt.Fprintf(out, "ResourceType{%v, Kind: ResInotifyDesc}", common()) + case "timerid": + if want := 0; len(a) != want { + failf("wrong number of arguments for %v arg %v want %v, got %v", typ, name, want, len(a)) + } + fmt.Fprintf(out, "ResourceType{%v, Kind: ResTimerid}", common()) + case "pid": + if want := 0; len(a) != want { + failf("wrong number of arguments for %v arg %v want %v, got %v", typ, name, want, len(a)) + } + fmt.Fprintf(out, "ResourceType{%v, Kind: ResPid}", common()) + case "uid": + if want := 0; len(a) != want { + failf("wrong number of arguments for %v arg %v want %v, got %v", typ, name, want, len(a)) + } + fmt.Fprintf(out, "ResourceType{%v, Kind: ResUid}", common()) + case "gid": + if want := 0; len(a) != want { + failf("wrong number of arguments for %v arg %v want %v, got %v", typ, name, want, len(a)) + } + fmt.Fprintf(out, "ResourceType{%v, Kind: ResGid}", common()) + case "fileoff": + var size uint64 + if isField { + if want := 2; len(a) != want { + failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + } + size = typeToSize(a[1]) + } else { + if want := 1; len(a) != want { + failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + } + } + fmt.Fprintf(out, "FileoffType{%v, File: \"%v\", TypeSize: %v}", common(), a[0], size) + case "buffer": + if want := 1; len(a) != want { + failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + } + commonHdr := common() + opt = false + fmt.Fprintf(out, "PtrType{%v, Dir: %v, Type: BufferType{%v, Kind: BufferBlob}}", commonHdr, fmtDir(a[0]), common()) + case "string": + if want := 0; len(a) != want { + failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + } + commonHdr := common() + opt = false + fmt.Fprintf(out, "PtrType{%v, Dir: %v, Type: BufferType{%v, Kind: BufferString}}", commonHdr, fmtDir("in"), common()) + case "sockaddr": + if want := 0; len(a) != want { + failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + } + fmt.Fprintf(out, "BufferType{%v, Kind: BufferSockaddr}", common()) + case "vma": + if want := 0; len(a) != want { + failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + } + fmt.Fprintf(out, "VmaType{%v}", common()) + case "len": + var size uint64 + if isField { + if want := 2; len(a) != want { + failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + } + size = typeToSize(a[1]) + } else { + if want := 1; len(a) != want { + failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + } + } + fmt.Fprintf(out, "LenType{%v, Buf: \"%v\", TypeSize: %v}", common(), a[0], size) + case "flags": + var size uint64 + if isField { + if want := 2; len(a) != want { + failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + } + size = typeToSize(a[1]) + } else { + if want := 1; len(a) != want { + failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + } + } + vals := flags[a[0]] + if len(vals) == 0 { + failf("unknown flag %v", a[0]) + } + fmt.Fprintf(out, "FlagsType{%v, TypeSize: %v, Vals: []uintptr{%v}}", common(), size, strings.Join(vals, ",")) + case "int8", "int16", "int32", "int64", "intptr": + if want := 0; len(a) != want { + failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + } + fmt.Fprintf(out, "IntType{%v, TypeSize: %v}", common(), typeToSize(typ)) + case "signalno": + if want := 0; len(a) != want { + failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + } + fmt.Fprintf(out, "IntType{%v, TypeSize: 4, Limit: 130}", common()) + case "filename": + if want := 0; len(a) != want { + failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + } + commonHdr := common() + opt = false + fmt.Fprintf(out, "PtrType{%v, Dir: DirIn, Type: FilenameType{%v}}", commonHdr, common()) + case "array": + if want := 1; len(a) != want { + failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + } + fmt.Fprintf(out, "ArrayType{%v, Type: %v}", common(), generateType(a[0], structs, unnamed, flags)) + case "ptr": + if want := 2; len(a) != want { + failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a)) + } + fmt.Fprintf(out, "PtrType{%v, Type: %v, Dir: %v}", common(), generateType(a[1], structs, unnamed, flags), fmtDir(a[0])) + default: + if strings.HasPrefix(typ, "unnamed") { + if inner, ok := unnamed[typ]; ok { + generateArg("", inner[0], inner[1:], structs, unnamed, flags, isField, out) + return + } + failf("unknown unnamed type '%v'", typ) + } + if str, ok := structs[typ]; ok { + fmt.Fprintf(out, "StructType{TypeCommon: TypeCommon{TypeName: \"%v\", IsOptional: %v}, Fields: []Type{", str.Name, false) + for i, a := range str.Flds { + if i != 0 { + fmt.Fprintf(out, ", ") + } + generateArg(a[0], a[1], a[2:], structs, unnamed, flags, true, out) + } + fmt.Fprintf(out, "}}") + return + } + failf("unknown arg type \"%v\" for %v", typ, name) + } +} + +func generateType(typ string, structs map[string]Struct, unnamed map[string][]string, flags map[string][]string) string { + buf := new(bytes.Buffer) + generateArg("", typ, nil, structs, unnamed, flags, true, buf) + return buf.String() +} + +func fmtFdKind(s string) string { + switch s { + case "": + return "ResAny" + case "file": + return "FdFile" + case "sock": + return "FdSock" + case "pipe": + return "FdPipe" + case "signal": + return "FdSignal" + case "event": + return "FdEvent" + case "timer": + return "FdTimer" + case "epoll": + return "FdEpoll" + case "dir": + return "FdDir" + case "mq": + return "FdMq" + case "inotify": + return "FdInotify" + case "fanotify": + return "FdFanotify" + default: + failf("bad fd type %v", s) + return "" + } +} + +func fmtIPCKind(s string) string { + switch s { + case "msq": + return "IPCMsq" + case "sem": + return "IPCSem" + case "shm": + return "IPCShm" + default: + failf("bad ipc type %v", s) + return "" + } +} + +func fmtDir(s string) string { + switch s { + case "in": + return "DirIn" + case "out": + return "DirOut" + case "inout": + return "DirInOut" + default: + failf("bad direction %v", s) + return "" + } +} + +func typeToSize(typ string) uint64 { + switch typ { + case "int8", "int16", "int32", "int64", "intptr": + default: + failf("unknown type %v", typ) + } + sz := int64(64) // TODO: assume that pointer is 8 bytes for now + if typ != "intptr" { + sz, _ = strconv.ParseInt(typ[3:], 10, 64) + } + return uint64(sz / 8) +} + +type F struct { + name string + val string +} + +type FlagArray []F + +func (a FlagArray) Len() int { return len(a) } +func (a FlagArray) Less(i, j int) bool { return a[i].name < a[j].name } +func (a FlagArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +func generateConsts(flags map[string]string, out io.Writer) { + var ff []F + for k, v := range flags { + ff = append(ff, F{k, v}) + } + sort.Sort(FlagArray(ff)) + + fmt.Fprintf(out, "// AUTOGENERATED FILE\n") + fmt.Fprintf(out, "package prog\n\n") + fmt.Fprintf(out, "const (\n") + for _, f := range ff { + fmt.Fprintf(out, " %v = %v\n", f.name, f.val) + } + fmt.Fprintf(out, ")\n") +} + +func generateHeader(syscalls []Syscall, out io.Writer) { + fmt.Fprint(out, `// AUTOGENERATED FILE + +struct call_t { + const char* name; + int sys_nr; +}; + +call_t syscalls[] = { +`) + for _, s := range syscalls { + fmt.Fprintf(out, "\t{\"%v\", __NR_%v},\n", s.Name, s.CallName) + } + fmt.Fprintf(out, "};\n") +} + +func compileFlags(includes []string, defines map[string]string, flags []Flag) (map[string][]string, map[string]string) { + vals := make(map[string]string) + for _, f := range flags { + for _, v := range f.Values { + vals[v] = "" + } + } + for k := range defines { + vals[k] = "" + } + valArray := make([]string, 0, len(vals)) + for k := range vals { + valArray = append(valArray, k) + } + flagVals := fetchValues(valArray, includes, defines) + for i, f := range valArray { + vals[f] = flagVals[i] + } + res := make(map[string][]string) + for _, f := range flags { + var arr []string + for _, v := range f.Values { + arr = append(arr, vals[v]) + } + if res[f.Name] != nil { + failf("flag %v is defined multiple times", f.Name) + } + res[f.Name] = arr + } + ids := make(map[string]string) + for k, v := range vals { + if isIdentifier(k) { + ids[k] = v + } + } + return res, ids +} + +func fetchValues(vals []string, includes []string, defines map[string]string) []string { + includeText := "" + for _, inc := range includes { + includeText += fmt.Sprintf("#include <%v>\n", inc) + } + definesText := "" + for k, v := range defines { + definesText += fmt.Sprintf("#ifndef %v\n#define %v %v\n#endif\n", k, k, v) + } + src := strings.Replace(fetchSrc, "[[INCLUDES]]", includeText, 1) + src = strings.Replace(src, "[[DEFAULTS]]", definesText, 1) + src = strings.Replace(src, "[[VALS]]", strings.Join(vals, ","), 1) + bin, err := ioutil.TempFile("", "") + if err != nil { + failf("failed to create temp file: %v", err) + } + bin.Close() + defer os.Remove(bin.Name()) + + cmd := exec.Command("gcc", "-x", "c", "-", "-o", bin.Name()) + cmd.Stdin = strings.NewReader(src) + out, err := cmd.CombinedOutput() + if err != nil { + failf("failed to run gcc: %v\n%v", err, string(out)) + } + + out, err = exec.Command(bin.Name()).CombinedOutput() + if err != nil { + failf("failed to flags binary: %v\n%v", err, string(out)) + } + + flagVals := strings.Split(string(out), " ") + if len(flagVals) != len(vals) { + failf("fetched wrong number of values") + } + for _, v := range flagVals { + _, err := strconv.ParseUint(v, 10, 64) + if err != nil { + failf("failed to parse value: %v (%v)", err, v) + } + } + return flagVals +} + +func isIdentifier(s string) bool { + for i, c := range s { + if c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || i > 0 && (c >= '0' && c <= '9') { + continue + } + return false + } + return true +} + +func parse(in io.Reader) (includes []string, defines map[string]string, syscalls []Syscall, structs map[string]Struct, unnamed map[string][]string, flags []Flag) { + p := NewParser(in) + defines = make(map[string]string) + structs = make(map[string]Struct) + unnamed = make(map[string][]string) + var str *Struct + for p.Scan() { + if p.EOF() || p.Char() == '#' { + continue + } + if str != nil { + // Parsing a struct. + if p.Char() == '}' { + p.Parse('}') + if _, ok := structs[str.Name]; ok { + failf("%v struct is defined multiple times", str.Name) + } + structs[str.Name] = *str + str = nil + } else { + p.SkipWs() + fld := []string{p.Ident()} + fld = append(fld, parseType(p, unnamed)...) + str.Flds = append(str.Flds, fld) + } + } else { + name := p.Ident() + if name == "include" { + p.Parse('<') + var include []byte + for { + ch := p.Char() + if ch == '>' { + break + } + p.Parse(ch) + include = append(include, ch) + } + p.Parse('>') + includes = append(includes, string(include)) + } else if name == "define" { + key := p.Ident() + var val []byte + for !p.EOF() { + ch := p.Char() + p.Parse(ch) + val = append(val, ch) + } + if defines[key] != "" { + failf("%v define is defined multiple times", key) + } + defines[key] = string(val) + } else { + switch p.Char() { + case '(': + // syscall + p.Parse('(') + var args [][]string + for p.Char() != ')' { + arg := []string{p.Ident()} + arg = append(arg, parseType(p, unnamed)...) + args = append(args, arg) + if p.Char() != ')' { + p.Parse(',') + } + } + p.Parse(')') + var ret []string + if !p.EOF() { + ret = parseType(p, unnamed) + } + callName := name + if idx := strings.IndexByte(callName, '$'); idx != -1 { + callName = callName[:idx] + } + syscalls = append(syscalls, Syscall{name, callName, args, ret}) + case '=': + // flag + p.Parse('=') + vals := []string{p.Ident()} + for !p.EOF() { + p.Parse(',') + vals = append(vals, p.Ident()) + } + flags = append(flags, Flag{name, vals}) + case '{': + p.Parse('{') + str = &Struct{Name: name} + default: + failf("bad line (%v)", p.Str()) + } + } + } + if !p.EOF() { + failf("trailing data (%v)", p.Str()) + } + } + return +} + +func parseType(p *Parser, unnamed map[string][]string) []string { + return parseType1(p, unnamed, p.Ident()) +} + +var unnamedSeq int + +func parseType1(p *Parser, unnamed map[string][]string, name string) []string { + typ := []string{name} + if !p.EOF() && p.Char() == '[' { + p.Parse('[') + for { + id := p.Ident() + if p.Char() == '[' { + inner := parseType1(p, unnamed, id) + id = fmt.Sprintf("unnamed%v", unnamedSeq) + unnamedSeq++ + unnamed[id] = inner + } + typ = append(typ, id) + if p.Char() == ']' { + break + } + p.Parse(',') + } + p.Parse(']') + } + return typ +} + +func writeSource(file string, data []byte) { + src, err := format.Source(data) + if err != nil { + fmt.Printf("%s\n", data) + failf("failed to format output: %v", err) + } + writeFile(file, src) +} + +func writeFile(file string, data []byte) { + outf, err := os.Create(file) + if err != nil { + failf("failed to create output file: %v", err) + } + defer outf.Close() + outf.Write(data) +} + +func failf(msg string, args ...interface{}) { + fmt.Fprintf(os.Stderr, msg+"\n", args...) + os.Exit(1) +} + +var fetchSrc = ` +#define _GNU_SOURCE +#include <stdio.h> +[[INCLUDES]] + +[[DEFAULTS]] + +int main() { + int i; + unsigned long vals[] = {[[VALS]]}; + for (i = 0; i < sizeof(vals)/sizeof(vals[0]); i++) { + if (i != 0) + printf(" "); + printf("%lu", vals[i]); + } + return 0; +} +` diff --git a/tools/execlog/execlog.go b/tools/execlog/execlog.go new file mode 100644 index 000000000..5d39bb955 --- /dev/null +++ b/tools/execlog/execlog.go @@ -0,0 +1,83 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// execlog executes all programs from a log (for non-reproducible crashes). +package main + +import ( + "bufio" + "flag" + "log" + "os" + "strings" + "sync/atomic" + "time" + + "github.com/google/syzkaller/ipc" + "github.com/google/syzkaller/prog" +) + +var ( + flagExecutor = flag.String("executor", "", "path to executor binary") + flagLog = flag.String("log", "", "comma-delimited list of log files to execute") +) + +func main() { + flag.Parse() + var progs [][]byte + for _, fn := range strings.Split(*flagLog, ",") { + logf, err := os.Open(fn) + if err != nil { + log.Fatalf("failed to open log file: %v", err) + } + log.Printf("parsing log %v", fn) + s := bufio.NewScanner(logf) + var cur []byte + var last *prog.Prog + for s.Scan() { + ln := s.Text() + tmp := append(cur, ln...) + tmp = append(tmp, '\n') + p, err := prog.Deserialize(tmp) + if err == nil { + cur = tmp + last = p + continue + } + if last != nil { + progs = append(progs, last.SerializeForExec()) + last = nil + cur = cur[:0] + } + } + if last != nil { + progs = append(progs, last.SerializeForExec()) + } + } + log.Printf("parsed %v programs", len(progs)) + if len(progs) == 0 { + return + } + + var pos uint32 + for p := 0; p < 16; p++ { + go func() { + env, err := ipc.MakeEnv(*flagExecutor, 5*time.Second, 0) + if err != nil { + log.Fatalf("failed to create ipc env: %v", err) + } + for { + idx := int(atomic.AddUint32(&pos, 1) - 1) + if idx%1000 == 0 { + log.Printf("executing %v\n", idx) + } + copy(env.In, progs[idx%len(progs)]) + _, _, _, _, err := env.Exec() + if err != nil { + log.Printf("failed to execute program: %v", err) + } + } + }() + } + select {} +} diff --git a/tools/execprog/execprog.go b/tools/execprog/execprog.go new file mode 100644 index 000000000..9ffe39119 --- /dev/null +++ b/tools/execprog/execprog.go @@ -0,0 +1,62 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "os" + "time" + + "github.com/google/syzkaller/ipc" + "github.com/google/syzkaller/prog" +) + +var ( + flagExecutor = flag.String("executor", "", "path to executor binary") + flagProg = flag.String("prog", "", "file with a program to execute") + flagThreaded = flag.Bool("threaded", false, "use threaded mode in executor") + flagDebug = flag.Bool("debug", true, "debug output from executor") + flagStrace = flag.Bool("strace", false, "run executor under strace") + flagCover = flag.Bool("cover", false, "collect coverage") +) + +func main() { + flag.Parse() + data, err := ioutil.ReadFile(*flagProg) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to read prog file: %v\n", err) + os.Exit(1) + } + p, err := prog.Deserialize(data) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to deserialize the program: %v\n", err) + os.Exit(1) + } + var flags uint64 + if *flagThreaded { + flags |= ipc.FlagThreaded + } + if *flagDebug { + flags |= ipc.FlagDebug + } + if *flagStrace { + flags |= ipc.FlagStrace + } + if *flagCover { + flags |= ipc.FlagCover + } + env, err := ipc.MakeEnv(*flagExecutor, 3*time.Second, flags) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to create execution environment: %v\n", err) + os.Exit(1) + } + copy(env.In, p.SerializeForExec()) + output, strace, failed, hanged, err := env.Exec() + fmt.Printf("result: failed=%v hanged=%v err=%v\n\n%s", failed, hanged, err, output) + if *flagStrace { + fmt.Printf("strace output:\n%s", strace) + } +} diff --git a/tools/prog2c/prog2c.go b/tools/prog2c/prog2c.go new file mode 100644 index 000000000..9b8e58efa --- /dev/null +++ b/tools/prog2c/prog2c.go @@ -0,0 +1,31 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "io/ioutil" + "os" + + "github.com/google/syzkaller/prog" +) + +func main() { + if len(os.Args) != 2 { + fmt.Fprintf(os.Stderr, "usage: prog2c prog_file\n") + os.Exit(1) + } + data, err := ioutil.ReadFile(os.Args[1]) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to read prog file: %v\n", err) + os.Exit(1) + } + p, err := prog.Deserialize(data) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to deserialize the program: %v\n", err) + os.Exit(1) + } + src := p.WriteCSource() + os.Stdout.Write(src) +} diff --git a/tools/stress/stress.go b/tools/stress/stress.go new file mode 100644 index 000000000..5b84e81b4 --- /dev/null +++ b/tools/stress/stress.go @@ -0,0 +1,104 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "log" + "math/rand" + "os" + "path/filepath" + "regexp" + "time" + + "github.com/google/syzkaller/ipc" + "github.com/google/syzkaller/prog" +) + +var ( + flagCorpus = flag.String("corpus", "", "corpus directory") + flagExecutor = flag.String("executor", "", "path to executor binary") + flagOutput = flag.Bool("output", false, "print executor output to console") + flagDebug = flag.Bool("debug", false, "executor debug output") + + failedRe = regexp.MustCompile("runtime error: |panic: ") +) + +func main() { + flag.Parse() + corpus := readCorpus() + flags := ipc.FlagThreaded + if *flagDebug { + flags |= ipc.FlagDebug + } + env, err := ipc.MakeEnv(*flagExecutor, 5*time.Second, flags) + if err != nil { + failf("failed to create execution environment: %v", err) + } + rs := rand.NewSource(time.Now().UnixNano()) + rnd := rand.New(rs) + for i := 0; ; i++ { + var p *prog.Prog + if len(corpus) == 0 || i%10 != 0 { + p = prog.Generate(rs, 50, nil) + execute(env, p) + p.Mutate(rs, 50, nil) + execute(env, p) + } else { + p = corpus[rnd.Intn(len(corpus))].Clone() + p.Mutate(rs, 50, nil) + execute(env, p) + } + } +} + +func execute(env *ipc.Env, p *prog.Prog) { + if *flagExecutor == "" { + return + } + copy(env.In, p.SerializeForExec()) + output, _, _, _, err := env.Exec() + if err != nil { + fmt.Printf("failed to execute executor: %v\n", err) + } + failed := failedRe.Match(output) + if failed { + fmt.Printf("PROGRAM:\n%s\n", p.Serialize()) + } + if failed || *flagOutput { + os.Stdout.Write(output) + } +} + +func readCorpus() []*prog.Prog { + if *flagCorpus == "" { + return nil + } + files, err := ioutil.ReadDir(*flagCorpus) + if err != nil { + failf("failed to read corpus dir: %v", err) + } + var progs []*prog.Prog + for _, f := range files { + if f.IsDir() { + continue + } + data, err := ioutil.ReadFile(filepath.Join(*flagCorpus, f.Name())) + if err != nil { + failf("failed to read corpus file: %v", err) + } + p, err := prog.Deserialize(data) + if err != nil { + failf("failed to deserialize corpus program: %v", err) + } + progs = append(progs, p) + } + return progs +} + +func failf(msg string, args ...interface{}) { + log.Fatalf(msg, args...) +} diff --git a/vm/local/local.go b/vm/local/local.go new file mode 100644 index 000000000..3966771d0 --- /dev/null +++ b/vm/local/local.go @@ -0,0 +1,117 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package qemu + +import ( + "bytes" + "encoding/json" + "fmt" + "log" + "os" + "os/exec" + "syscall" + "time" + + "github.com/google/syzkaller/vm" +) + +func init() { + vm.Register("local", ctor) +} + +type local struct { + params + workdir string + syscalls map[int]bool + id int + mgrPort int +} + +type params struct { + Fuzzer string + Executor string + Parallel int +} + +func ctor(workdir string, syscalls map[int]bool, port, index int, paramsData []byte) (vm.Instance, error) { + p := new(params) + if err := json.Unmarshal(paramsData, p); err != nil { + return nil, fmt.Errorf("failed to unmarshal local params: %v", err) + } + if _, err := os.Stat(p.Fuzzer); err != nil { + return nil, fmt.Errorf("fuzzer binary '%v' does not exist: %v", p.Fuzzer, err) + } + if _, err := os.Stat(p.Executor); err != nil { + return nil, fmt.Errorf("executor binary '%v' does not exist: %v", p.Executor, err) + } + if p.Parallel == 0 { + p.Parallel = 1 + } + if p.Parallel <= 0 || p.Parallel > 100 { + return nil, fmt.Errorf("bad parallel param: %v, want [1-100]", p.Parallel) + } + + os.MkdirAll(workdir, 0770) + + // Disable annoying segfault dmesg messages, fuzzer is going to crash a lot. + etrace, err := os.Open("/proc/sys/debug/exception-trace") + if err == nil { + etrace.Write([]byte{'0'}) + etrace.Close() + } + + // Don't write executor core files. + syscall.Setrlimit(syscall.RLIMIT_CORE, &syscall.Rlimit{0, 0}) + + loc := &local{ + params: *p, + workdir: workdir, + syscalls: syscalls, + id: index, + mgrPort: port, + } + return loc, nil +} + +func (loc *local) Run() { + name := fmt.Sprintf("local-%v", loc.id) + log.Printf("%v: started\n", name) + for run := 0; ; run++ { + cmd := exec.Command(loc.Fuzzer, "-name", name, "-saveprog", "-executor", loc.Executor, + "-manager", fmt.Sprintf("localhost:%v", loc.mgrPort), "-parallel", fmt.Sprintf("%v", loc.Parallel)) + if len(loc.syscalls) != 0 { + buf := new(bytes.Buffer) + for c := range loc.syscalls { + fmt.Fprintf(buf, ",%v", c) + } + cmd.Args = append(cmd.Args, "-calls="+buf.String()[1:]) + } + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Dir = loc.workdir + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} + if err := cmd.Start(); err != nil { + log.Printf("failed to start fuzzer binary: %v", err) + time.Sleep(10 * time.Second) + continue + } + pid := cmd.Process.Pid + done := make(chan bool) + go func() { + select { + case <-done: + case <-time.After(time.Hour): + log.Printf("%v: running for long enough, restarting", name) + syscall.Kill(-pid, syscall.SIGKILL) + syscall.Kill(-pid, syscall.SIGKILL) + syscall.Kill(pid, syscall.SIGKILL) + syscall.Kill(pid, syscall.SIGKILL) + } + }() + err := cmd.Wait() + close(done) + log.Printf("fuzzer binary exited: %v", err) + time.Sleep(10 * time.Second) + } +} diff --git a/vm/qemu/qemu.go b/vm/qemu/qemu.go new file mode 100644 index 000000000..08719b0e9 --- /dev/null +++ b/vm/qemu/qemu.go @@ -0,0 +1,478 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package qemu + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "log" + "net" + "os" + "os/exec" + "path/filepath" + "regexp" + "strconv" + "sync" + "time" + + "github.com/google/syzkaller/vm" +) + +const hostAddr = "10.0.2.10" +const logOutput = false + +func init() { + vm.Register("qemu", ctor) +} + +type qemu struct { + params + workdir string + crashdir string + callsFlag string + id int + mgrPort int +} + +type params struct { + Qemu string + Kernel string + Image string + Sshkey string + Fuzzer string + Executor string + Port int + Cpu int + Mem int + Parallel int +} + +func ctor(workdir string, syscalls map[int]bool, port, index int, paramsData []byte) (vm.Instance, error) { + p := new(params) + if err := json.Unmarshal(paramsData, p); err != nil { + return nil, fmt.Errorf("failed to unmarshal qemu params: %v", err) + } + if _, err := os.Stat(p.Image); err != nil { + return nil, fmt.Errorf("image file '%v' does not exist: %v", p.Image, err) + } + if _, err := os.Stat(p.Kernel); err != nil { + return nil, fmt.Errorf("kernel file '%v' does not exist: %v", p.Kernel, err) + } + if _, err := os.Stat(p.Sshkey); err != nil { + return nil, fmt.Errorf("ssh key '%v' does not exist: %v", p.Sshkey, err) + } + if _, err := os.Stat(p.Fuzzer); err != nil { + return nil, fmt.Errorf("fuzzer binary '%v' does not exist: %v", p.Fuzzer, err) + } + if _, err := os.Stat(p.Executor); err != nil { + return nil, fmt.Errorf("executor binary '%v' does not exist: %v", p.Executor, err) + } + if p.Qemu == "" { + p.Qemu = "qemu-system-x86_64" + } + if p.Port <= 1024 || p.Port >= 64<<10 { + return nil, fmt.Errorf("bad qemu port: %v, want (1024-65536)", p.Port) + } + p.Port += index + if p.Cpu <= 0 || p.Cpu > 1024 { + return nil, fmt.Errorf("bad qemu cpu: %v, want [1-1024]", p.Cpu) + } + if p.Mem < 128 || p.Mem > 1048576 { + return nil, fmt.Errorf("bad qemu mem: %v, want [128-1048576]", p.Mem) + } + if p.Parallel == 0 { + p.Parallel = 1 + } + if p.Parallel <= 0 || p.Parallel > 100 { + return nil, fmt.Errorf("bad parallel param: %v, want [1-100]", p.Parallel) + } + + crashdir := filepath.Join(workdir, "crashes") + os.MkdirAll(crashdir, 0770) + + workdir = filepath.Join(workdir, "qemu") + os.MkdirAll(workdir, 0770) + + q := &qemu{ + params: *p, + workdir: workdir, + crashdir: crashdir, + id: index, + mgrPort: port, + } + + if len(syscalls) != 0 { + buf := new(bytes.Buffer) + for c := range syscalls { + fmt.Fprintf(buf, ",%v", c) + } + q.callsFlag = "-calls=" + buf.String()[1:] + } + + return q, nil +} + +func (q *qemu) Run() { + log.Printf("qemu/%v: started\n", q.id) + imagename := filepath.Join(q.workdir, fmt.Sprintf("image%v", q.id)) + for run := 0; ; run++ { + logname := filepath.Join(q.workdir, fmt.Sprintf("log%v-%v-%v", q.id, run, time.Now().Unix())) + var logf *os.File + if logOutput { + var err error + logf, err = os.Create(logname) + if err != nil { + log.Printf("failed to create log file: %v", err) + time.Sleep(10 * time.Second) + continue + } + } + rpipe, wpipe, err := os.Pipe() + if err != nil { + log.Printf("failed to create pipe: %v", err) + if logf != nil { + logf.Close() + } + time.Sleep(10 * time.Second) + continue + } + os.Remove(imagename) + if err := copyFile(q.Image, imagename); err != nil { + log.Printf("failed to copy image file: %v", err) + if logf != nil { + logf.Close() + } + rpipe.Close() + wpipe.Close() + time.Sleep(10 * time.Second) + continue + } + inst := &Instance{ + id: q.id, + crashdir: q.crashdir, + params: q.params, + name: fmt.Sprintf("qemu/%v-%v", q.id, run), + image: imagename, + callsFlag: q.callsFlag, + log: logf, + rpipe: rpipe, + wpipe: wpipe, + mgrPort: q.mgrPort, + cmds: make(map[*Command]bool), + } + inst.Run() + inst.Shutdown() + time.Sleep(10 * time.Second) + } +} + +type Instance struct { + params + sync.Mutex + id int + crashdir string + name string + image string + callsFlag string + log *os.File + rpipe *os.File + wpipe *os.File + mgrPort int + cmds map[*Command]bool + qemu *Command +} + +type Command struct { + sync.Mutex + cmd *exec.Cmd + done chan struct{} + failed bool + out []byte + outpos int +} + +func (inst *Instance) Run() { + var outputMu sync.Mutex + var output []byte + go func() { + var buf [64 << 10]byte + for { + n, err := inst.rpipe.Read(buf[:]) + if n != 0 { + outputMu.Lock() + output = append(output, buf[:n]...) + outputMu.Unlock() + if inst.log != nil { + inst.log.Write(buf[:n]) + } + } + if err != nil { + break + } + } + }() + + // Start the instance. + // TODO: ignores inst.Cpu + inst.qemu = inst.CreateCommand(inst.Qemu, + "-hda", inst.image, + "-m", strconv.Itoa(inst.Mem), + "-net", "nic", + "-net", fmt.Sprintf("user,host=%v,hostfwd=tcp::%v-:22", hostAddr, inst.Port), + "-nographic", + "-kernel", inst.Kernel, + "-append", "console=ttyS0 root=/dev/sda debug earlyprintk=serial slub_debug=UZ", + "-enable-kvm", + "-numa", "node,nodeid=0,cpus=0-1", "-numa", "node,nodeid=1,cpus=2-3", + "-smp", "sockets=2,cores=2,threads=1", + "-usb", "-usbdevice", "mouse", "-usbdevice", "tablet", + ) + // Wait for ssh server. + time.Sleep(10 * time.Second) + start := time.Now() + for { + c, err := net.DialTimeout("tcp", fmt.Sprintf("localhost:%v", inst.Port), 3*time.Second) + if err == nil { + c.SetDeadline(time.Now().Add(3 * time.Second)) + var tmp [1]byte + n, err := c.Read(tmp[:]) + c.Close() + if err == nil && n > 0 { + // ssh is up and responding. + break + } + c.Close() + time.Sleep(3 * time.Second) + } + if inst.qemu.Exited() { + output = append(output, "qemu stopped\n"...) + inst.SaveCrasher(output) + inst.Logf("qemu stopped") + return + } + if time.Since(start) > 10*time.Minute { + outputMu.Lock() + output = append(output, "ssh server did not start\n"...) + inst.SaveCrasher(output) + outputMu.Unlock() + inst.Logf("ssh server did not start") + return + } + } + inst.Logf("started vm") + + // Copy the binaries into the instance. + if !inst.CreateSCPCommand(inst.Fuzzer, "/syzkaller_fuzzer").Wait(1*time.Minute) || + !inst.CreateSCPCommand(inst.Executor, "/syzkaller_executor").Wait(1*time.Minute) { + inst.Logf("failed to scp binaries into the instance") + return + } + + // Disable annoying segfault dmesg messages, fuzzer is going to crash a lot. + inst.CreateSSHCommand("echo -n 0 > /proc/sys/debug/exception-trace").Wait(10 * time.Second) + + // Run the binary. + cmd := inst.CreateSSHCommand(fmt.Sprintf("/syzkaller_fuzzer -name %v -executor /syzkaller_executor -manager %v:%v -parallel %v %v", + inst.name, hostAddr, inst.mgrPort, inst.Parallel, inst.callsFlag)) + + deadline := start.Add(time.Hour) + lastOutput := time.Now() + lastOutputLen := 0 + matchPos := 0 + crashRe := regexp.MustCompile("\\[ cut here \\]|Kernel panic| BUG: | WARNING: | INFO: |unable to handle kernel NULL pointer dereference|general protection fault") + const contextSize = 64 << 10 + for range time.NewTicker(5 * time.Second).C { + outputMu.Lock() + if lastOutputLen != len(output) { + lastOutput = time.Now() + } + if loc := crashRe.FindAllIndex(output[matchPos:], -1); len(loc) != 0 { + // Give it some time to finish writing the error message. + outputMu.Unlock() + time.Sleep(5 * time.Second) + outputMu.Lock() + loc = crashRe.FindAllIndex(output[matchPos:], -1) + start := loc[0][0] - contextSize + if start < 0 { + start = 0 + } + end := loc[len(loc)-1][1] + contextSize + if end > len(output) { + end = len(output) + } + inst.SaveCrasher(output[start:end]) + } + if len(output) > 2*contextSize { + copy(output, output[len(output)-contextSize:]) + output = output[:contextSize] + } + matchPos = len(output) - 128 + if matchPos < 0 { + matchPos = 0 + } + lastOutputLen = len(output) + outputMu.Unlock() + + if time.Since(lastOutput) > 3*time.Minute { + time.Sleep(time.Second) + outputMu.Lock() + output = append(output, "no output from fuzzer, restarting\n"...) + inst.SaveCrasher(output) + outputMu.Unlock() + inst.Logf("no output from fuzzer, restarting") + cmd.cmd.Process.Kill() + cmd.cmd.Process.Kill() + return + } + if cmd.Exited() { + time.Sleep(time.Second) + outputMu.Lock() + output = append(output, "fuzzer binary stopped or lost connection\n"...) + inst.SaveCrasher(output) + inst.Logf("fuzzer binary stopped or lost connection") + outputMu.Unlock() + return + } + if time.Now().After(deadline) { + inst.Logf("running for long enough, restarting") + cmd.cmd.Process.Kill() + cmd.cmd.Process.Kill() + return + } + } +} + +func (inst *Instance) SaveCrasher(output []byte) { + ioutil.WriteFile(filepath.Join(inst.crashdir, fmt.Sprintf("crash%v-%v", inst.id, time.Now().UnixNano())), output, 0660) +} + +func (inst *Instance) Shutdown() { + defer func() { + os.Remove(inst.image) + inst.rpipe.Close() + inst.wpipe.Close() + if inst.log != nil { + inst.log.Close() + } + }() + if inst.qemu.cmd == nil { + // CreateCommand should have been failed very early. + return + } + for try := 0; try < 10; try++ { + inst.qemu.cmd.Process.Kill() + time.Sleep(time.Second) + inst.Lock() + n := len(inst.cmds) + inst.Unlock() + if n == 0 { + return + } + } + inst.Logf("hanged processes after kill") + inst.Lock() + for cmd := range inst.cmds { + cmd.cmd.Process.Kill() + cmd.cmd.Process.Kill() + } + inst.Unlock() + time.Sleep(3 * time.Second) +} + +func (inst *Instance) CreateCommand(args ...string) *Command { + if inst.log != nil { + fmt.Fprintf(inst.log, "executing command: %v\n", args) + } + cmd := &Command{} + cmd.done = make(chan struct{}) + cmd.cmd = exec.Command(args[0], args[1:]...) + cmd.cmd.Stdout = inst.wpipe + cmd.cmd.Stderr = inst.wpipe + if err := cmd.cmd.Start(); err != nil { + inst.Logf("failed to start command '%v': %v\n", args, err) + cmd.failed = true + close(cmd.done) + return cmd + } + inst.Lock() + inst.cmds[cmd] = true + inst.Unlock() + go func() { + err := cmd.cmd.Wait() + inst.Lock() + delete(inst.cmds, cmd) + inst.Unlock() + if inst.log != nil { + fmt.Fprintf(inst.log, "command '%v' exited: %v\n", args, err) + } + cmd.failed = err != nil + close(cmd.done) + }() + return cmd +} + +func (inst *Instance) CreateSSHCommand(args ...string) *Command { + args1 := []string{"ssh", "-i", inst.Sshkey, "-p", strconv.Itoa(inst.Port), + "-o", "ConnectionAttempts=10", "-o", "ConnectTimeout=10", + "-o", "BatchMode=yes", "-o", "UserKnownHostsFile=/dev/null", + "-o", "StrictHostKeyChecking=no", "root@localhost"} + return inst.CreateCommand(append(args1, args...)...) +} + +func (inst *Instance) CreateSCPCommand(from, to string) *Command { + return inst.CreateCommand("scp", "-i", inst.Sshkey, "-P", strconv.Itoa(inst.Port), + "-o", "ConnectionAttempts=10", "-o", "ConnectTimeout=10", + "-o", "BatchMode=yes", "-o", "UserKnownHostsFile=/dev/null", + "-o", "StrictHostKeyChecking=no", + from, "root@localhost:"+to) +} + +func (inst *Instance) Logf(str string, args ...interface{}) { + fmt.Fprintf(inst.wpipe, str+"\n", args...) + log.Printf("%v: "+str, append([]interface{}{inst.name}, args...)...) +} + +func (cmd *Command) Wait(max time.Duration) bool { + select { + case <-cmd.done: + return !cmd.failed + case <-time.After(max): + return false + } +} + +func (cmd *Command) Exited() bool { + select { + case <-cmd.done: + return true + default: + return false + } +} + +var copySem sync.Mutex + +func copyFile(oldfn, newfn string) error { + copySem.Lock() + defer copySem.Unlock() + + oldf, err := os.Open(oldfn) + if err != nil { + return err + } + defer oldf.Close() + newf, err := os.Create(newfn) + if err != nil { + return err + } + defer newf.Close() + _, err = io.Copy(newf, oldf) + if err != nil { + return err + } + return nil +} diff --git a/vm/vm.go b/vm/vm.go new file mode 100644 index 000000000..b9eded0c8 --- /dev/null +++ b/vm/vm.go @@ -0,0 +1,28 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package vm + +import ( + "fmt" +) + +type Instance interface { + Run() +} + +type ctorFunc func(workdir string, syscalls map[int]bool, port, index int, params []byte) (Instance, error) + +var ctors = make(map[string]ctorFunc) + +func Register(typ string, ctor ctorFunc) { + ctors[typ] = ctor +} + +func Create(typ string, workdir string, syscalls map[int]bool, port, index int, params []byte) (Instance, error) { + ctor := ctors[typ] + if ctor == nil { + return nil, fmt.Errorf("unknown instance type '%v'", typ) + } + return ctor(workdir, syscalls, port, index, params) +} |
