Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

incusd/seccomp: Add support for pidfd threads #623

Merged
merged 1 commit into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions cmd/incusd/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,7 @@ func (d *Daemon) init() error {

if canUsePidFds() && d.os.LXCFeatures["pidfd"] {
d.os.PidFds = true
d.os.PidFdsThread = canUseThreadPidFds()
}

if d.os.PidFds {
Expand All @@ -923,6 +924,12 @@ func (d *Daemon) init() error {
logger.Info(" - pidfds: no")
}

if d.os.PidFdsThread {
logger.Info(" - pidfds for threads: yes")
} else {
logger.Info(" - pidfds for threads: no")
}

if canUseCoreScheduling() {
d.os.CoreScheduling = true
logger.Info(" - core scheduling: yes")
Expand Down
11 changes: 10 additions & 1 deletion cmd/incusd/main_checkfeature.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ __ro_after_init bool close_range_aware = false;
__ro_after_init bool tiocgptpeer_aware = false;
__ro_after_init bool netnsid_aware = false;
__ro_after_init bool pidfd_aware = false;
__ro_after_init bool pidfd_thread_aware = false;
__ro_after_init bool pidfd_setns_aware = false;
__ro_after_init bool uevent_aware = false;
__ro_after_init bool binfmt_aware = false;
Expand Down Expand Up @@ -419,7 +420,7 @@ static void is_seccomp_notify_aware(void)

static int is_pidfd_aware(void)
{
__do_close int pidfd = -EBADF;
__do_close int pidfd = -EBADF, pidfd_thread = -EBADF;
int ret;

pidfd = incus_pidfd_open(getpid(), 0);
Expand All @@ -442,6 +443,10 @@ static int is_pidfd_aware(void)
if (ret)
return -errno;

pidfd_thread = incus_pidfd_open(getpid(), PIDFD_THREAD);
if (pidfd_thread >= 0)
pidfd_thread_aware = true;

pidfd_aware = true;
return move_fd(pidfd);
}
Expand Down Expand Up @@ -707,6 +712,10 @@ func canUsePidFds() bool {
return bool(C.pidfd_aware)
}

func canUseThreadPidFds() bool {
return bool(C.pidfd_thread_aware)
}

// We're only using this during daemon startup to give an indication whether
// the underlying kernel has the necessary infrastructure to support idmapped
// mounts. This check does not give any indication whether the relevant
Expand Down
34 changes: 22 additions & 12 deletions internal/server/seccomp/seccomp.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,8 @@ static inline int bpf(int cmd, union bpf_attr *attr, size_t size)
static int handle_bpf_syscall(pid_t pid_target, int notify_fd, int mem_fd,
int tgid, struct seccomp_notify_proxy_msg *msg,
struct seccomp_notif *req, struct seccomp_notif_resp *resp,
int *bpf_cmd, int *bpf_prog_type, int *bpf_attach_type)
int *bpf_cmd, int *bpf_prog_type, int *bpf_attach_type,
unsigned int flags)
{
__do_close int pidfd = -EBADF, bpf_target_fd = -EBADF, bpf_attach_fd = -EBADF,
bpf_prog_fd = -EBADF;
Expand Down Expand Up @@ -307,7 +308,10 @@ static int handle_bpf_syscall(pid_t pid_target, int notify_fd, int mem_fd,

*bpf_prog_type = attr.prog_type;

pidfd = incus_pidfd_open(tgid, 0);
if (flags & PIDFD_THREAD)
pidfd = incus_pidfd_open(pid_target, PIDFD_THREAD);
else
pidfd = incus_pidfd_open(tgid, 0);
if (pidfd < 0)
return -errno;

Expand Down Expand Up @@ -383,7 +387,7 @@ static int handle_bpf_syscall(pid_t pid_target, int notify_fd, int mem_fd,
if (bpf_attach_fd < 0)
return -errno;

if (tgid != pid_target) {
if (!(flags & PIDFD_THREAD) && tgid != pid_target) {
// Make sure that the file descriptor table is shared
// so we can be sure that we're talking about the same
// open files.
Expand Down Expand Up @@ -416,7 +420,7 @@ static int handle_bpf_syscall(pid_t pid_target, int notify_fd, int mem_fd,
if (bpf_attach_fd < 0)
return -errno;

if (tgid != pid_target) {
if (!(flags & PIDFD_THREAD) && tgid != pid_target) {
// Make sure that the file descriptor table is shared
// so we can be sure that we're talking about the same
// open files.
Expand Down Expand Up @@ -2259,7 +2263,8 @@ func (s *Server) HandleBpfSyscall(c Instance, siov *Iovec) int {
}

defer logger.Debug("Handling bpf syscall", ctx)
var bpfCmd, bpfProgType, bpfAttachType C.int
var bpfCmd, bpfProgType, bpfAttachType, tgid C.int
var flags C.uint

if util.IsFalseOrEmpty(c.ExpandedConfig()["security.syscalls.intercept.bpf.devices"]) {
ctx["syscall_continue"] = "true"
Expand All @@ -2268,12 +2273,17 @@ func (s *Server) HandleBpfSyscall(c Instance, siov *Iovec) int {
return 0
}

tgid, err := FindTGID(siov.procFd)
if err != nil || tgid == -1 {
ctx["syscall_continue"] = "true"
ctx["syscall_handler_reason"] = "Could not find thread group leader ID"
C.seccomp_notify_update_response(siov.resp, 0, C.uint32_t(seccompUserNotifFlagContinue))
return 0
if s.s.OS.PidFdsThread {
flags |= C.PIDFD_THREAD
tgid = -1
} else {
tgid, err := FindTGID(siov.procFd)
if err != nil || tgid == -1 {
ctx["syscall_continue"] = "true"
ctx["syscall_handler_reason"] = "Could not find thread group leader ID"
C.seccomp_notify_update_response(siov.resp, 0, C.uint32_t(seccompUserNotifFlagContinue))
return 0
}
}

// Locking to a thread shouldn't be necessary but it still makes me
Expand All @@ -2289,7 +2299,7 @@ func (s *Server) HandleBpfSyscall(c Instance, siov *Iovec) int {
siov.resp,
&bpfCmd,
&bpfProgType,
&bpfAttachType)
&bpfAttachType, flags)
runtime.UnlockOSThread()
ctx["bpf_cmd"] = fmt.Sprintf("%d", bpfCmd)
ctx["bpf_prog_type"] = fmt.Sprintf("%d", bpfProgType)
Expand Down
1 change: 1 addition & 0 deletions internal/server/sys/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ type OS struct {
NativeTerminals bool // NativeTerminals indicates support for TIOGPTPEER ioctl.
NetnsGetifaddrs bool // NetnsGetifaddrs indicates support for NETLINK_GET_STRICT_CHK.
PidFds bool // PidFds indicates support for PID fds.
PidFdsThread bool // PidFds indicates support for thread PID fds.
PidFdSetns bool // PidFdSetns indicates support for setns through PID fds.
SeccompListenerAddfd bool // SeccompListenerAddfd indicates support for passing new FD to process through seccomp notify.
SeccompListener bool // SeccompListener indicates support for seccomp notify.
Expand Down
4 changes: 4 additions & 0 deletions shared/cgo/process_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
#include "memory_utils.h"
#include "syscall_numbers.h"

#ifndef PIDFD_THREAD
#define PIDFD_THREAD O_EXCL
#endif

static inline int incus_pidfd_open(pid_t pid, unsigned int flags)
{
return syscall(__NR_pidfd_open, pid, flags);
Expand Down
Loading