|
5 | 5 | "errors" |
6 | 6 | "fmt" |
7 | 7 | "io" |
| 8 | + "net" |
8 | 9 | "os" |
9 | 10 | "os/exec" |
10 | 11 | "path/filepath" |
@@ -172,6 +173,42 @@ func (p *setnsProcess) start() (retErr error) { |
172 | 173 | case procHooks: |
173 | 174 | // This shouldn't happen. |
174 | 175 | panic("unexpected procHooks in setns") |
| 176 | + case procSeccomp: |
| 177 | + if p.config.Config.Seccomp.ListenerPath == "" { |
| 178 | + return errors.New("listenerPath is not set") |
| 179 | + } |
| 180 | + |
| 181 | + seccompFd, err := recvSeccompFd(uintptr(p.pid()), uintptr(sync.Fd)) |
| 182 | + if err != nil { |
| 183 | + return err |
| 184 | + } |
| 185 | + defer unix.Close(seccompFd) |
| 186 | + |
| 187 | + bundle, annotations := utils.Annotations(p.config.Config.Labels) |
| 188 | + containerProcessState := &specs.ContainerProcessState{ |
| 189 | + Version: specs.Version, |
| 190 | + Fds: []string{specs.SeccompFdName}, |
| 191 | + Pid: p.cmd.Process.Pid, |
| 192 | + Metadata: p.config.Config.Seccomp.ListenerMetadata, |
| 193 | + State: specs.State{ |
| 194 | + Version: specs.Version, |
| 195 | + ID: p.config.ContainerId, |
| 196 | + Status: specs.StateRunning, |
| 197 | + Pid: p.initProcessPid, |
| 198 | + Bundle: bundle, |
| 199 | + Annotations: annotations, |
| 200 | + }, |
| 201 | + } |
| 202 | + if err := sendContainerProcessState(p.config.Config.Seccomp.ListenerPath, |
| 203 | + containerProcessState, seccompFd); err != nil { |
| 204 | + return err |
| 205 | + } |
| 206 | + |
| 207 | + // Sync with child. |
| 208 | + if err := writeSync(p.messageSockPair.parent, procSeccompDone); err != nil { |
| 209 | + return err |
| 210 | + } |
| 211 | + return nil |
175 | 212 | default: |
176 | 213 | return errors.New("invalid JSON payload from child") |
177 | 214 | } |
@@ -426,6 +463,41 @@ func (p *initProcess) start() (retErr error) { |
426 | 463 |
|
427 | 464 | ierr := parseSync(p.messageSockPair.parent, func(sync *syncT) error { |
428 | 465 | switch sync.Type { |
| 466 | + case procSeccomp: |
| 467 | + if p.config.Config.Seccomp.ListenerPath == "" { |
| 468 | + return errors.New("listenerPath is not set") |
| 469 | + } |
| 470 | + |
| 471 | + seccompFd, err := recvSeccompFd(uintptr(childPid), uintptr(sync.Fd)) |
| 472 | + if err != nil { |
| 473 | + return err |
| 474 | + } |
| 475 | + defer unix.Close(seccompFd) |
| 476 | + |
| 477 | + s, err := p.container.currentOCIState() |
| 478 | + if err != nil { |
| 479 | + return err |
| 480 | + } |
| 481 | + |
| 482 | + // initProcessStartTime hasn't been set yet. |
| 483 | + s.Pid = p.cmd.Process.Pid |
| 484 | + s.Status = specs.StateCreating |
| 485 | + containerProcessState := &specs.ContainerProcessState{ |
| 486 | + Version: specs.Version, |
| 487 | + Fds: []string{specs.SeccompFdName}, |
| 488 | + Pid: s.Pid, |
| 489 | + Metadata: p.config.Config.Seccomp.ListenerMetadata, |
| 490 | + State: *s, |
| 491 | + } |
| 492 | + if err := sendContainerProcessState(p.config.Config.Seccomp.ListenerPath, |
| 493 | + containerProcessState, seccompFd); err != nil { |
| 494 | + return err |
| 495 | + } |
| 496 | + |
| 497 | + // Sync with child. |
| 498 | + if err := writeSync(p.messageSockPair.parent, procSeccompDone); err != nil { |
| 499 | + return err |
| 500 | + } |
429 | 501 | case procReady: |
430 | 502 | // set rlimits, this has to be done here because we lose permissions |
431 | 503 | // to raise the limits once we enter a user-namespace |
@@ -486,7 +558,7 @@ func (p *initProcess) start() (retErr error) { |
486 | 558 |
|
487 | 559 | // Sync with child. |
488 | 560 | if err := writeSync(p.messageSockPair.parent, procRun); err != nil { |
489 | | - return fmt.Errorf("error writing syncT 'run': %w", err) |
| 561 | + return err |
490 | 562 | } |
491 | 563 | sentRun = true |
492 | 564 | case procHooks: |
@@ -518,7 +590,7 @@ func (p *initProcess) start() (retErr error) { |
518 | 590 | } |
519 | 591 | // Sync with child. |
520 | 592 | if err := writeSync(p.messageSockPair.parent, procResume); err != nil { |
521 | | - return fmt.Errorf("error writing syncT 'resume': %w", err) |
| 593 | + return err |
522 | 594 | } |
523 | 595 | sentResume = true |
524 | 596 | default: |
@@ -621,6 +693,46 @@ func (p *initProcess) forwardChildLogs() chan error { |
621 | 693 | return logs.ForwardLogs(p.logFilePair.parent) |
622 | 694 | } |
623 | 695 |
|
| 696 | +func recvSeccompFd(childPid, childFd uintptr) (int, error) { |
| 697 | + pidfd, _, errno := unix.Syscall(unix.SYS_PIDFD_OPEN, childPid, 0, 0) |
| 698 | + if errno != 0 { |
| 699 | + return -1, fmt.Errorf("performing SYS_PIDFD_OPEN syscall: %w", errno) |
| 700 | + } |
| 701 | + defer unix.Close(int(pidfd)) |
| 702 | + |
| 703 | + seccompFd, _, errno := unix.Syscall(unix.SYS_PIDFD_GETFD, pidfd, childFd, 0) |
| 704 | + if errno != 0 { |
| 705 | + return -1, fmt.Errorf("performing SYS_PIDFD_GETFD syscall: %w", errno) |
| 706 | + } |
| 707 | + |
| 708 | + return int(seccompFd), nil |
| 709 | +} |
| 710 | + |
| 711 | +func sendContainerProcessState(listenerPath string, state *specs.ContainerProcessState, fd int) error { |
| 712 | + conn, err := net.Dial("unix", listenerPath) |
| 713 | + if err != nil { |
| 714 | + return fmt.Errorf("failed to connect with seccomp agent specified in the seccomp profile: %w", err) |
| 715 | + } |
| 716 | + |
| 717 | + socket, err := conn.(*net.UnixConn).File() |
| 718 | + if err != nil { |
| 719 | + return fmt.Errorf("cannot get seccomp socket: %w", err) |
| 720 | + } |
| 721 | + defer socket.Close() |
| 722 | + |
| 723 | + b, err := json.Marshal(state) |
| 724 | + if err != nil { |
| 725 | + return fmt.Errorf("cannot marshall seccomp state: %w", err) |
| 726 | + } |
| 727 | + |
| 728 | + err = utils.SendFds(socket, b, fd) |
| 729 | + if err != nil { |
| 730 | + return fmt.Errorf("cannot send seccomp fd to %s: %w", listenerPath, err) |
| 731 | + } |
| 732 | + |
| 733 | + return nil |
| 734 | +} |
| 735 | + |
624 | 736 | func getPipeFds(pid int) ([]string, error) { |
625 | 737 | fds := make([]string, 3) |
626 | 738 |
|
|
0 commit comments