github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/syz-cluster/pkg/api/api.go (about) 1 // Copyright 2024 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package api 5 6 import "time" 7 8 // The output passed to other workflow steps. 9 type TriageResult struct { 10 // If set, ignore the patch series completely. 11 SkipReason string `json:"skip_reason"` 12 // Fuzzing configuration to try (NULL if nothing). 13 Fuzz []*FuzzTask `json:"fuzz"` 14 } 15 16 // The data layout faclitates the simplicity of the workflow definition. 17 type FuzzTask struct { 18 Base BuildRequest `json:"base"` 19 Patched BuildRequest `json:"patched"` 20 FuzzConfig 21 } 22 23 const ( 24 FocusNet = "net" 25 FocusKVM = "kvm" 26 FocusIoUring = "io_uring" 27 FocusBPF = "bpf" 28 FocusFS = "fs" 29 ) 30 31 // FuzzConfig represents a set of parameters passed to the fuzz step. 32 // The triage step aggregates multiple KernelFuzzConfig to construct FuzzConfig. 33 type FuzzConfig struct { 34 Track string `json:"track"` // E.g. KASAN. 35 Focus []string `json:"focus"` 36 CorpusURLs []string `json:"corpus_urls"` 37 // Don't expect kernel coverage for the patched area. 38 SkipCoverCheck bool `json:"skip_cover_check"` 39 // Only report the bugs that match the regexp. 40 BugTitleRe string `json:"bug_title_re"` 41 } 42 43 // The triage step of the workflow will request these from controller. 44 type Tree struct { 45 Name string `json:"name"` // Primary key. 46 URL string `json:"URL"` 47 Branch string `json:"branch"` 48 EmailLists []string `json:"email_lists"` 49 } 50 51 // KernelFuzzConfig is a specific fuzzing assignment. 52 // Based on it, the triage step will construct FuzzTasks. 53 type KernelFuzzConfig struct { 54 EmailLists []string `json:"email_lists"` 55 Track string `json:"track"` // E.g. KASAN. 56 KernelConfig string `json:"kernel_config"` 57 Focus string `json:"focus"` 58 CorpusURL string `json:"corpus_url"` 59 SkipCoverCheck bool `json:"skip_cover_check"` 60 BugTitleRe string `json:"bug_title_re"` 61 } 62 63 // FuzzTriageTarget is a single record in the list of supported fuzz configs. 64 type FuzzTriageTarget struct { 65 EmailLists []string `json:"email_lists"` 66 Campaigns []*KernelFuzzConfig `json:"campaigns"` 67 } 68 69 type BuildRequest struct { 70 Arch string `json:"arch"` 71 TreeName string `json:"tree_name"` 72 TreeURL string `json:"tree_url"` 73 CommitHash string `json:"commit_hash"` 74 ConfigName string `json:"config_name"` // These are known to both the triage and build steps. 75 SeriesID string `json:"series_id"` 76 } 77 78 // BuildResult is returned from the build workflow step. 79 type BuildResult struct { 80 BuildID string `json:"build_id"` 81 Success bool `json:"success"` 82 } 83 84 type Build struct { 85 Arch string `json:"arch"` 86 TreeName string `json:"tree_name"` 87 TreeURL string `json:"tree_url"` 88 CommitHash string `json:"commit_hash"` 89 CommitDate time.Time `json:"commit_date"` 90 ConfigName string `json:"config_name"` 91 SeriesID string `json:"series_id"` 92 Compiler string `json:"compiler"` 93 BuildSuccess bool `json:"build_success"` 94 } 95 96 const ( 97 TestRunning string = "running" 98 TestPassed string = "passed" 99 TestSkipped string = "skipped" 100 TestFailed string = "failed" // TODO: drop it? only mark completion? 101 TestError string = "error" 102 ) 103 104 type TestResult struct { 105 SessionID string `json:"session_id"` 106 BaseBuildID string `json:"base_build_id"` 107 PatchedBuildID string `json:"patched_build_id"` 108 TestName string `json:"test_name"` 109 Result string `json:"result"` 110 Log []byte `json:"log"` 111 } 112 113 type BootResult struct { 114 Success bool `json:"success"` 115 } 116 117 // NewFinding is a kernel crash, boot error, etc. found during a test. 118 type NewFinding struct { 119 SessionID string `json:"session_id"` 120 TestName string `json:"test_name"` 121 Title string `json:"title"` 122 Report []byte `json:"report"` 123 Log []byte `json:"log"` 124 SyzRepro []byte `json:"syz_repro"` 125 SyzReproOpts []byte `json:"syz_repro_opts"` 126 CRepro []byte `json:"c_repro"` 127 } 128 129 type Series struct { 130 ID string `json:"id"` // Only included in the reply. 131 ExtID string `json:"ext_id"` 132 Title string `json:"title"` 133 AuthorEmail string `json:"author_email"` 134 Cc []string `json:"cc"` 135 Version int `json:"version"` 136 Link string `json:"link"` 137 SubjectTags []string `json:"subject_tags"` 138 PublishedAt time.Time `json:"published_at"` 139 Patches []SeriesPatch `json:"patches"` 140 } 141 142 func (s *Series) PatchBodies() [][]byte { 143 var ret [][]byte 144 for _, patch := range s.Patches { 145 ret = append(ret, patch.Body) 146 } 147 return ret 148 } 149 150 type SeriesPatch struct { 151 Seq int `json:"seq"` 152 Title string `json:"title"` 153 Link string `json:"link"` 154 Body []byte `json:"body"` 155 } 156 157 type NewSession struct { 158 ExtID string `json:"ext_id"` 159 Tags []string `json:"tags"` 160 } 161 162 type SessionReport struct { 163 ID string `json:"id"` 164 Moderation bool `json:"moderation"` 165 Series *Series `json:"series"` 166 Findings []*Finding `json:"findings"` 167 Link string `json:"link"` // URL to the web dashboard. 168 } 169 170 type Finding struct { 171 Title string `json:"title"` 172 Report string `json:"report"` 173 LogURL string `json:"log_url"` 174 Build BuildInfo `json:"build"` 175 LinkCRepro string `json:"c_repro"` 176 LinkSyzRepro string `json:"syz_repro"` 177 Invalidated bool `json:"invalidated"` 178 } 179 180 type BuildInfo struct { 181 TreeName string `json:"tree_name"` 182 TreeURL string `json:"tree_url"` 183 BaseCommit string `json:"base_commit"` 184 Arch string `json:"arch"` 185 Compiler string `json:"compiler"` 186 ConfigLink string `json:"config_link"` 187 } 188 189 // Let them stay here until we find a better place. 190 // The list is ordered by decreasing importance. 191 var DefaultTrees = []*Tree{ 192 { 193 Name: `bpf-next`, 194 URL: `https://kernel.googlesource.com/pub/scm/linux/kernel/git/bpf/bpf-next.git`, 195 Branch: `master`, 196 EmailLists: []string{`bpf@vger.kernel.org`}, 197 }, 198 { 199 Name: `bpf`, 200 URL: `https://kernel.googlesource.com/pub/scm/linux/kernel/git/bpf/bpf.git`, 201 Branch: `master`, 202 EmailLists: []string{`bpf@vger.kernel.org`}, 203 }, 204 { 205 Name: `nf-next`, 206 URL: `https://kernel.googlesource.com/pub/scm/linux/kernel/git/netfilter/nf-next.git`, 207 Branch: `main`, 208 EmailLists: []string{`netfilter-devel@vger.kernel.org`}, 209 }, 210 { 211 Name: `nf`, 212 URL: `https://kernel.googlesource.com/pub/scm/linux/kernel/git/netfilter/nf.git`, 213 Branch: `main`, 214 EmailLists: []string{`netfilter-devel@vger.kernel.org`}, 215 }, 216 { 217 Name: `net-next`, 218 URL: `https://kernel.googlesource.com/pub/scm/linux/kernel/git/netdev/net-next.git`, 219 Branch: `main`, 220 EmailLists: []string{`netdev@vger.kernel.org`}, 221 }, 222 { 223 Name: `net`, 224 URL: `https://kernel.googlesource.com/pub/scm/linux/kernel/git/netdev/net.git`, 225 Branch: `main`, 226 EmailLists: []string{`netdev@vger.kernel.org`}, 227 }, 228 { 229 Name: `kvm-next`, 230 URL: `https://kernel.googlesource.com/pub/scm/virt/kvm/kvm/`, 231 Branch: `next`, 232 EmailLists: []string{`kvm@vger.kernel.org`}, 233 }, 234 { 235 Name: `drm-next`, 236 URL: `https://gitlab.freedesktop.org/drm/kernel.git`, 237 Branch: `drm-next`, 238 EmailLists: []string{`dri-devel@lists.freedesktop.org`}, 239 }, 240 { 241 Name: `mm-new`, 242 URL: `https://kernel.googlesource.com/pub/scm/linux/kernel/git/akpm/mm.git`, 243 Branch: `mm-new`, 244 EmailLists: []string{`linux-mm@kvack.org`}, 245 }, 246 { 247 Name: `torvalds`, 248 URL: `https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux`, 249 Branch: `master`, 250 EmailLists: nil, // First fallback tree. 251 }, 252 { 253 Name: `linux-next`, 254 URL: `https://kernel.googlesource.com/pub/scm/linux/kernel/git/next/linux-next`, 255 Branch: `master`, 256 EmailLists: nil, // Second fallback tree. It's less stable, but more series can be applied. 257 }, 258 } 259 260 const ( 261 netCorpusURL = `https://storage.googleapis.com/syzkaller/corpus/ci-upstream-net-kasan-gce-corpus.db` 262 bpfCorpusURL = `https://storage.googleapis.com/syzkaller/corpus/ci-upstream-bpf-kasan-gce-corpus.db` 263 fsCorpusURL = `https://storage.googleapis.com/syzkaller/corpus/ci2-upstream-fs-corpus.db` 264 allCorpusURL = `https://storage.googleapis.com/syzkaller/corpus/ci-upstream-kasan-gce-root-corpus.db` 265 ) 266 267 const kasanTrack = "KASAN" 268 269 // The list is ordered by decreasing importance. 270 var FuzzTargets = []*FuzzTriageTarget{ 271 { 272 EmailLists: []string{`kvm@vger.kernel.org`}, 273 Campaigns: []*KernelFuzzConfig{ 274 { 275 Track: kasanTrack, 276 KernelConfig: `upstream-apparmor-kasan.config`, 277 Focus: FocusKVM, 278 CorpusURL: allCorpusURL, 279 }, 280 }, 281 }, 282 { 283 EmailLists: []string{`io-uring@vger.kernel.org`}, 284 Campaigns: []*KernelFuzzConfig{ 285 { 286 Track: kasanTrack, 287 KernelConfig: `upstream-apparmor-kasan.config`, 288 Focus: FocusIoUring, 289 CorpusURL: allCorpusURL, 290 }, 291 }, 292 }, 293 { 294 EmailLists: []string{`bpf@vger.kernel.org`}, 295 Campaigns: []*KernelFuzzConfig{ 296 { 297 Track: kasanTrack, 298 KernelConfig: `upstream-apparmor-kasan.config`, 299 Focus: FocusBPF, 300 CorpusURL: bpfCorpusURL, 301 }, 302 }, 303 }, 304 { 305 EmailLists: []string{ 306 `netdev@vger.kernel.org`, 307 `netfilter-devel@vger.kernel.org`, 308 `linux-wireless@vger.kernel.org`, 309 }, 310 Campaigns: []*KernelFuzzConfig{ 311 { 312 Track: kasanTrack, 313 KernelConfig: `upstream-apparmor-kasan.config`, 314 Focus: FocusNet, 315 CorpusURL: netCorpusURL, 316 }, 317 }, 318 }, 319 { 320 EmailLists: []string{ 321 `linux-fsdevel@vger.kernel.org`, 322 `linux-block@vger.kernel.org`, 323 `linux-unionfs@vger.kernel.org`, 324 `linux-ext4@vger.kernel.org`, 325 }, 326 Campaigns: []*KernelFuzzConfig{ 327 { 328 KernelConfig: `upstream-apparmor-kasan.config`, 329 Track: kasanTrack, 330 Focus: FocusFS, 331 CorpusURL: fsCorpusURL, 332 }, 333 }, 334 }, 335 { 336 EmailLists: []string{`linux-mm@kvack.org`}, 337 Campaigns: []*KernelFuzzConfig{ 338 { 339 KernelConfig: `upstream-apparmor-kasan.config`, 340 Track: kasanTrack, 341 CorpusURL: allCorpusURL, 342 // Not all mm/ code is instrumented with KCOV. 343 SkipCoverCheck: true, 344 }, 345 }, 346 }, 347 { 348 EmailLists: nil, // A fallback option. 349 Campaigns: []*KernelFuzzConfig{ 350 { 351 KernelConfig: `upstream-apparmor-kasan.config`, 352 Track: kasanTrack, 353 CorpusURL: allCorpusURL, 354 }, 355 }, 356 }, 357 }