|
1 | 1 | package main |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "errors" |
4 | 5 | "fmt" |
5 | 6 | "os" |
6 | 7 | "runtime" |
@@ -51,11 +52,14 @@ var generateFlags = []cli.Flag{ |
51 | 52 | cli.StringSliceFlag{Name: "gidmappings", Usage: "add GIDMappings e.g HostID:ContainerID:Size"}, |
52 | 53 | cli.StringSliceFlag{Name: "sysctl", Usage: "add sysctl settings e.g net.ipv4.forward=1"}, |
53 | 54 | cli.StringFlag{Name: "apparmor", Usage: "specifies the the apparmor profile for the container"}, |
54 | | - cli.StringFlag{Name: "seccomp-default", Usage: "specifies the the defaultaction of Seccomp syscall restrictions"}, |
55 | | - cli.StringSliceFlag{Name: "seccomp-arch", Usage: "specifies Additional architectures permitted to be used for system calls"}, |
56 | | - cli.StringSliceFlag{Name: "seccomp-syscalls", Usage: "specifies Additional architectures permitted to be used for system calls, e.g Name:Action:Arg1_index/Arg1_value/Arg1_valuetwo/Arg1_op, Arg2_index/Arg2_value/Arg2_valuetwo/Arg2_op "}, |
57 | | - cli.StringSliceFlag{Name: "seccomp-allow", Usage: "specifies syscalls to be added to allowed"}, |
58 | | - cli.StringSliceFlag{Name: "seccomp-errno", Usage: "specifies syscalls to be added to list that returns an error"}, |
| 55 | + cli.BoolFlag{Name: "seccomp-only", Usage: "specifies to export just a seccomp configuration file"}, |
| 56 | + cli.StringFlag{Name: "seccomp-arch", Value: "amd64,x86,x32", Usage: "specifies additional architectures permitted to be used for system calls"}, |
| 57 | + cli.StringFlag{Name: "seccomp-default", Value: "errno", Usage: "specifies default action to be used for system calls"}, |
| 58 | + cli.StringFlag{Name: "seccomp-allow", Usage: "specifies syscalls to respond with allow"}, |
| 59 | + cli.StringFlag{Name: "seccomp-trap", Usage: "specifies syscalls to respond with trap"}, |
| 60 | + cli.StringFlag{Name: "seccomp-errno", Usage: "specifies syscalls to respond with errno"}, |
| 61 | + cli.StringFlag{Name: "seccomp-trace", Usage: "specifies syscalls to respond with trace"}, |
| 62 | + cli.StringFlag{Name: "seccomp-kill", Usage: "specifies syscalls to respond with kill"}, |
59 | 63 | cli.StringFlag{Name: "template", Usage: "base template to use for creating the configuration"}, |
60 | 64 | cli.StringSliceFlag{Name: "label", Usage: "add annotations to the configuration e.g. key=value"}, |
61 | 65 | } |
@@ -86,11 +90,13 @@ var generateCommand = cli.Command{ |
86 | 90 | return err |
87 | 91 | } |
88 | 92 |
|
| 93 | + var exportOpts generate.ExportOptions |
| 94 | + exportOpts.Seccomp = context.Bool("seccomp-only") |
| 95 | + |
89 | 96 | if context.IsSet("output") { |
90 | | - output := context.String("output") |
91 | | - err = specgen.SaveToFile(output) |
| 97 | + err = specgen.SaveToFile(context.String("output"), exportOpts) |
92 | 98 | } else { |
93 | | - err = specgen.Save(os.Stdout) |
| 99 | + err = specgen.Save(os.Stdout, exportOpts) |
94 | 100 | } |
95 | 101 | if err != nil { |
96 | 102 | return err |
@@ -319,61 +325,262 @@ func setupSpec(g *generate.Generator, context *cli.Context) error { |
319 | 325 | g.AddLinuxGIDMapping(hid, cid, size) |
320 | 326 | } |
321 | 327 |
|
322 | | - var sd string |
323 | | - var sa, ss []string |
| 328 | + err := addSeccomp(g, context) |
| 329 | + return err |
| 330 | +} |
324 | 331 |
|
325 | | - if context.IsSet("seccomp-default") { |
326 | | - sd = context.String("seccomp-default") |
| 332 | +func setupLinuxNamespaces(context *cli.Context, g *generate.Generator, needsNewUser bool) { |
| 333 | + for _, nsName := range generate.Namespaces { |
| 334 | + if !context.IsSet(nsName) && !(needsNewUser && nsName == "user") { |
| 335 | + continue |
| 336 | + } |
| 337 | + nsPath := context.String(nsName) |
| 338 | + if nsPath == "host" { |
| 339 | + g.RemoveLinuxNamespace(nsName) |
| 340 | + continue |
| 341 | + } |
| 342 | + g.AddOrReplaceLinuxNamespace(nsName, nsPath) |
327 | 343 | } |
| 344 | +} |
328 | 345 |
|
329 | | - if context.IsSet("seccomp-arch") { |
330 | | - sa = context.StringSlice("seccomp-arch") |
| 346 | +func parseIDMapping(idms string) (uint32, uint32, uint32, error) { |
| 347 | + idm := strings.Split(idms, ":") |
| 348 | + if len(idm) != 3 { |
| 349 | + return 0, 0, 0, fmt.Errorf("idmappings error: %s", idms) |
331 | 350 | } |
332 | 351 |
|
333 | | - if context.IsSet("seccomp-syscalls") { |
334 | | - ss = context.StringSlice("seccomp-syscalls") |
| 352 | + hid, err := strconv.Atoi(idm[0]) |
| 353 | + if err != nil { |
| 354 | + return 0, 0, 0, err |
335 | 355 | } |
336 | 356 |
|
337 | | - if sd == "" && len(sa) == 0 && len(ss) == 0 { |
338 | | - return nil |
| 357 | + cid, err := strconv.Atoi(idm[1]) |
| 358 | + if err != nil { |
| 359 | + return 0, 0, 0, err |
339 | 360 | } |
340 | 361 |
|
| 362 | + size, err := strconv.Atoi(idm[2]) |
| 363 | + if err != nil { |
| 364 | + return 0, 0, 0, err |
| 365 | + } |
| 366 | + |
| 367 | + return uint32(hid), uint32(cid), uint32(size), nil |
| 368 | +} |
| 369 | + |
| 370 | +func parseHook(s string) (string, []string) { |
| 371 | + parts := strings.Split(s, ":") |
| 372 | + args := []string{} |
| 373 | + path := parts[0] |
| 374 | + if len(parts) > 1 { |
| 375 | + args = parts[1:] |
| 376 | + } |
| 377 | + return path, args |
| 378 | +} |
| 379 | + |
| 380 | +func parseTmpfsMount(s string) (string, []string, error) { |
| 381 | + var dest string |
| 382 | + var options []string |
| 383 | + var err error |
| 384 | + |
| 385 | + parts := strings.Split(s, ":") |
| 386 | + if len(parts) == 2 { |
| 387 | + dest = parts[0] |
| 388 | + options = strings.Split(parts[1], ",") |
| 389 | + } else if len(parts) == 1 { |
| 390 | + dest = parts[0] |
| 391 | + options = []string{"rw", "noexec", "nosuid", "nodev", "size=65536k"} |
| 392 | + } else { |
| 393 | + err = fmt.Errorf("invalid value for --tmpfs") |
| 394 | + } |
| 395 | + |
| 396 | + return dest, options, err |
| 397 | +} |
| 398 | + |
| 399 | +func parseBindMount(s string) (string, string, string, error) { |
| 400 | + var source, dest string |
| 401 | + options := "ro" |
| 402 | + |
| 403 | + bparts := strings.SplitN(s, ":", 3) |
| 404 | + switch len(bparts) { |
| 405 | + case 2: |
| 406 | + source, dest = bparts[0], bparts[1] |
| 407 | + case 3: |
| 408 | + source, dest, options = bparts[0], bparts[1], bparts[2] |
| 409 | + default: |
| 410 | + return source, dest, options, fmt.Errorf("--bind should have format src:dest:[options]") |
| 411 | + } |
| 412 | + |
| 413 | + return source, dest, options, nil |
| 414 | +} |
| 415 | + |
| 416 | +func addSeccomp(g *generate.Generator, context *cli.Context) error { |
| 417 | + |
341 | 418 | // Set the DefaultAction of seccomp |
342 | | - if context.IsSet("seccomp-default") { |
343 | | - if err := g.SetLinuxSeccompDefault(sd); err != nil { |
344 | | - return err |
345 | | - } |
| 419 | + seccompDefault := context.String("seccomp-default") |
| 420 | + err := g.SetDefaultSeccompAction(seccompDefault) |
| 421 | + if err != nil { |
| 422 | + return err |
346 | 423 | } |
347 | 424 |
|
348 | 425 | // Add the additional architectures permitted to be used for system calls |
349 | | - if context.IsSet("seccomp-arch") { |
350 | | - for _, arch := range sa { |
351 | | - if err := g.AddLinuxSeccompArch(arch); err != nil { |
352 | | - return err |
| 426 | + seccompArch := context.String("seccomp-arch") |
| 427 | + architectureArgs := strings.Split(seccompArch, ",") |
| 428 | + err = g.SetSeccompArchitectures(architectureArgs) |
| 429 | + if err != nil { |
| 430 | + return err |
| 431 | + } |
| 432 | + |
| 433 | + if context.IsSet("seccomp-kill") { |
| 434 | + seccompKill := context.String("seccomp-kill") |
| 435 | + killArgs := strings.Split(seccompKill, ",") |
| 436 | + setSyscallArgsSlice := [][]string{} |
| 437 | + for _, killArg := range killArgs { |
| 438 | + comparisonArgs := strings.Split(killArg, ":") |
| 439 | + if len(comparisonArgs) == 5 { |
| 440 | + setSyscallArgs := []string{"kill", |
| 441 | + comparisonArgs[0], |
| 442 | + comparisonArgs[1], |
| 443 | + comparisonArgs[2], |
| 444 | + comparisonArgs[3], |
| 445 | + comparisonArgs[4], |
| 446 | + } |
| 447 | + setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs) |
| 448 | + } else if len(comparisonArgs) == 1 { |
| 449 | + setSyscallArgs := []string{"kill", comparisonArgs[0]} |
| 450 | + setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs) |
| 451 | + } else { |
| 452 | + return errors.New("Invalid syscall argument formatting") |
| 453 | + } |
| 454 | + |
| 455 | + for _, r := range setSyscallArgsSlice { |
| 456 | + err := g.SetSyscallAction(r) |
| 457 | + if err != nil { |
| 458 | + return err |
| 459 | + } |
353 | 460 | } |
354 | 461 | } |
355 | 462 | } |
| 463 | + if context.IsSet("seccomp-trace") { |
| 464 | + seccompTrace := context.String("seccomp-trace") |
| 465 | + traceArgs := strings.Split(seccompTrace, ",") |
| 466 | + setSyscallArgsSlice := [][]string{} |
| 467 | + for _, traceArg := range traceArgs { |
| 468 | + comparisonArgs := strings.Split(traceArg, ":") |
| 469 | + if len(comparisonArgs) == 5 { |
| 470 | + setSyscallArgs := []string{"trace", |
| 471 | + comparisonArgs[0], |
| 472 | + comparisonArgs[1], |
| 473 | + comparisonArgs[2], |
| 474 | + comparisonArgs[3], |
| 475 | + comparisonArgs[4], |
| 476 | + } |
| 477 | + setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs) |
| 478 | + } else if len(comparisonArgs) == 1 { |
| 479 | + setSyscallArgs := []string{"trace", comparisonArgs[0]} |
| 480 | + setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs) |
| 481 | + } else { |
| 482 | + return errors.New("Invalid syscall argument formatting") |
| 483 | + } |
356 | 484 |
|
357 | | - // Set syscall restrict in Seccomp |
358 | | - if context.IsSet("seccomp-syscalls") { |
359 | | - for _, syscall := range ss { |
360 | | - if err := g.AddLinuxSeccompSyscall(syscall); err != nil { |
361 | | - return err |
| 485 | + for _, r := range setSyscallArgsSlice { |
| 486 | + err := g.SetSyscallAction(r) |
| 487 | + if err != nil { |
| 488 | + return err |
| 489 | + } |
362 | 490 | } |
363 | 491 | } |
364 | 492 | } |
365 | 493 |
|
366 | | - if context.IsSet("seccomp-allow") { |
367 | | - seccompAllows := context.StringSlice("seccomp-allow") |
368 | | - for _, s := range seccompAllows { |
369 | | - g.AddLinuxSeccompSyscallAllow(s) |
| 494 | + if context.IsSet("seccomp-errno") { |
| 495 | + seccompErrno := context.String("seccomp-errno") |
| 496 | + errnoArg := strings.Split(seccompErrno, ",") |
| 497 | + setSyscallArgsSlice := [][]string{} |
| 498 | + for _, errnoArg := range errnoArg { |
| 499 | + comparisonArgs := strings.Split(errnoArg, ":") |
| 500 | + if len(comparisonArgs) == 5 { |
| 501 | + setSyscallArgs := []string{"errno", |
| 502 | + comparisonArgs[0], |
| 503 | + comparisonArgs[1], |
| 504 | + comparisonArgs[2], |
| 505 | + comparisonArgs[3], |
| 506 | + comparisonArgs[4], |
| 507 | + } |
| 508 | + setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs) |
| 509 | + } else if len(comparisonArgs) == 1 { |
| 510 | + setSyscallArgs := []string{"errno", comparisonArgs[0]} |
| 511 | + setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs) |
| 512 | + } else { |
| 513 | + return errors.New("Invalid syscall argument formatting") |
| 514 | + } |
| 515 | + |
| 516 | + for _, r := range setSyscallArgsSlice { |
| 517 | + err := g.SetSyscallAction(r) |
| 518 | + if err != nil { |
| 519 | + return err |
| 520 | + } |
| 521 | + } |
370 | 522 | } |
371 | 523 | } |
372 | 524 |
|
373 | | - if context.IsSet("seccomp-errno") { |
374 | | - seccompErrnos := context.StringSlice("seccomp-errno") |
375 | | - for _, s := range seccompErrnos { |
376 | | - g.AddLinuxSeccompSyscallErrno(s) |
| 525 | + if context.IsSet("seccomp-trap") { |
| 526 | + seccompTrap := context.String("seccomp-trap") |
| 527 | + trapArg := strings.Split(seccompTrap, ",") |
| 528 | + setSyscallArgsSlice := [][]string{} |
| 529 | + for _, trapArg := range trapArg { |
| 530 | + comparisonArgs := strings.Split(trapArg, ":") |
| 531 | + if len(comparisonArgs) == 5 { |
| 532 | + setSyscallArgs := []string{"trap", |
| 533 | + comparisonArgs[0], |
| 534 | + comparisonArgs[1], |
| 535 | + comparisonArgs[2], |
| 536 | + comparisonArgs[3], |
| 537 | + comparisonArgs[4], |
| 538 | + } |
| 539 | + setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs) |
| 540 | + } else if len(comparisonArgs) == 1 { |
| 541 | + setSyscallArgs := []string{"trap", comparisonArgs[0]} |
| 542 | + setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs) |
| 543 | + } else { |
| 544 | + return errors.New("Invalid syscall argument formatting") |
| 545 | + } |
| 546 | + |
| 547 | + for _, r := range setSyscallArgsSlice { |
| 548 | + err := g.SetSyscallAction(r) |
| 549 | + if err != nil { |
| 550 | + return err |
| 551 | + } |
| 552 | + } |
| 553 | + } |
| 554 | + } |
| 555 | + |
| 556 | + if context.IsSet("seccomp-allow") { |
| 557 | + seccompAllow := context.String("seccomp-allow") |
| 558 | + allowArg := strings.Split(seccompAllow, ",") |
| 559 | + setSyscallArgsSlice := [][]string{} |
| 560 | + for _, allowArg := range allowArg { |
| 561 | + comparisonArgs := strings.Split(allowArg, ":") |
| 562 | + if len(comparisonArgs) == 5 { |
| 563 | + setSyscallArgs := []string{"allow", |
| 564 | + comparisonArgs[0], |
| 565 | + comparisonArgs[1], |
| 566 | + comparisonArgs[2], |
| 567 | + comparisonArgs[3], |
| 568 | + comparisonArgs[4], |
| 569 | + } |
| 570 | + setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs) |
| 571 | + } else if len(comparisonArgs) == 1 { |
| 572 | + setSyscallArgs := []string{"allow", comparisonArgs[0]} |
| 573 | + setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs) |
| 574 | + } else { |
| 575 | + return errors.New("Invalid syscall argument formatting") |
| 576 | + } |
| 577 | + |
| 578 | + for _, r := range setSyscallArgsSlice { |
| 579 | + err := g.SetSyscallAction(r) |
| 580 | + if err != nil { |
| 581 | + return err |
| 582 | + } |
| 583 | + } |
377 | 584 | } |
378 | 585 | } |
379 | 586 |
|
|
0 commit comments