| 320 | |
| 321 | |
| 322 | Try<Nothing> parseSyscalls( |
| 323 | const JSON::Object& json, |
| 324 | ContainerSeccompProfile* profile) |
| 325 | { |
| 326 | Result<JSON::Array> syscalls = json.at<JSON::Array>("syscalls"); |
| 327 | if (!syscalls.isSome()) { |
| 328 | return Error( |
| 329 | "Cannot determine 'syscalls' for the Seccomp configuration: " + |
| 330 | (syscalls.isError() ? syscalls.error() : "Not found")); |
| 331 | } |
| 332 | |
| 333 | // Each item in `syscalls` section defines a seccomp filter for a subset |
| 334 | // of system calls. |
| 335 | foreach (const JSON::Value& item, syscalls->values) { |
| 336 | if (!item.is<JSON::Object>()) { |
| 337 | return Error("'syscalls' contains a non-object item"); |
| 338 | } |
| 339 | |
| 340 | ContainerSeccompProfile::Syscall syscall; |
| 341 | |
| 342 | // Both `includes` and `excludes` sections define rules for filtering out |
| 343 | // this seccomp filter. We omit this seccomp rule in two cases: |
| 344 | // 1. `excludes` rule is matched. |
| 345 | // 2. `includes` rule is not matched. |
| 346 | // Currently, we support filtering by Linux capabilities and by CPU |
| 347 | // architecture. We do filtering by CPU architecture here, while we postpone |
| 348 | // filtering by Linux capabilities until starting a container via the Linux |
| 349 | // launcher. We can't filter by Linux capabilities here, because the list of |
| 350 | // capabilities is unknown at the moment the `linux/seccomp` isolator parses |
| 351 | // the seccomp profile. |
| 352 | |
| 353 | // Parse `includes` section. |
| 354 | const auto includes = item.as<JSON::Object>().at<JSON::Object>("includes"); |
| 355 | if (!includes.isSome()) { |
| 356 | return Error( |
| 357 | "Cannot determine 'includes' field for 'syscalls' item: " + |
| 358 | (includes.isError() ? includes.error() : "Not found")); |
| 359 | } |
| 360 | |
| 361 | bool architectureMatched = false; |
| 362 | const auto includesFilter = |
| 363 | parseSyscallFilter(includes.get(), &architectureMatched); |
| 364 | |
| 365 | if (includesFilter.isError()) { |
| 366 | return Error(includesFilter.error()); |
| 367 | } |
| 368 | |
| 369 | if (includes->values.count("arches") && !architectureMatched) { |
| 370 | continue; |
| 371 | } |
| 372 | |
| 373 | if (includes->values.count("caps")) { |
| 374 | syscall.mutable_includes()->CopyFrom(includesFilter.get()); |
| 375 | } |
| 376 | |
| 377 | // Parse `excludes` section. |
| 378 | const auto excludes = item.as<JSON::Object>().at<JSON::Object>("excludes"); |
| 379 | if (!excludes.isSome()) { |