Skip to content
Open
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
1 change: 1 addition & 0 deletions doc/man/man3/seccomp_notify_addfd.3
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.so man3/seccomp_notify_alloc.3
12 changes: 11 additions & 1 deletion doc/man/man3/seccomp_notify_alloc.3
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
.SH NAME
.\" //////////////////////////////////////////////////////////////////////////
seccomp_notify_alloc, seccomp_notify_free, seccomp_notify_receive,
seccomp_notify_respond, seccomp_notify_id_valid, seccomp_notify_fd \- Manage seccomp notifications
seccomp_notify_respond, seccomp_notify_id_valid, seccomp_notify_fd, seccomp_notify_addfd \- Manage seccomp notifications
.\" //////////////////////////////////////////////////////////////////////////
.SH SYNOPSIS
.\" //////////////////////////////////////////////////////////////////////////
Expand All @@ -16,6 +16,7 @@ seccomp_notify_respond, seccomp_notify_id_valid, seccomp_notify_fd \- Manage sec
.BI "int seccomp_notify_respond(int " fd ", struct seccomp_notif_resp *" resp ")"
.BI "int seccomp_notify_id_valid(int " fd ", uint64_t " id ")"
.BI "int seccomp_notify_fd(const scmp_filter_ctx " ctx ")"
.BI "int seccomp_notify_addfd(int " fd ", struct seccomp_notif_addfd *" addfd ")"
.sp
Link with \fI\-lseccomp\fP.
.fi
Expand Down Expand Up @@ -54,6 +55,11 @@ race conditions.
The
.BR seccomp_notify_fd ()
returns the notification fd of a filter after it has been loaded.
.P
The
.BR seccomp_notify_addfd ()
function enables the caller to install a file descriptor into the target's file descriptor table.
The id field of the struct should be the same as the id from the request.
.\" //////////////////////////////////////////////////////////////////////////
.SH RETURN VALUE
.\" //////////////////////////////////////////////////////////////////////////
Expand All @@ -67,6 +73,10 @@ The
returns 0 if the id is valid, and -ENOENT if it is not.
.P
The
.BR seccomp_notify_addfd ()
returns the installed fd number on success, and one of error codes mentioned below on failure.
.P
The
.BR seccomp_notify_alloc (),
.BR seccomp_notify_receive (),
and
Expand Down
30 changes: 30 additions & 0 deletions include/seccomp.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,24 @@ struct seccomp_notif_resp {
__s32 error;
__u32 flags;
};

#endif

/* seccomp_notif_addfd and ADDFD_FLAG_SETFD was added in kernel v5.10 */
#ifndef SECCOMP_ADDFD_FLAG_SETFD
#define SECCOMP_ADDFD_FLAG_SETFD (1UL << 0)
struct seccomp_notif_addfd {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the struct seccomp_notif_addfd() definition inside of the #ifndef SECCOMP_ADDFD_FLAG_SETFD? Seems strange to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a fair question. The seccomp_notif_addfd struct is only used when SECCOMP_ADDFD_FLAG_SETFD is present and supported, so using the presence of SECCOMP_ADDFD_FLAG_SETFD to serve as a proxy for the definition of seccomp_notif_addfd seems like a reasonable thing to do.

I'm definitely open to other ideas and I'm sure @realsdx would be as well.

https://man7.org/linux/man-pages/man2/seccomp_unotify.2.html

__u64 id;
__u32 flags;
__u32 srcfd;
__u32 newfd;
__u32 newfd_flags;
};
#endif

/* Addfd and return it, atomically. ADDFD_FLAG_SEND was added in kernel 5.14 */
#ifndef SECCOMP_ADDFD_FLAG_SEND
#define SECCOMP_ADDFD_FLAG_SEND (1UL << 1)
#endif

/*
Expand Down Expand Up @@ -814,6 +832,18 @@ int seccomp_notify_id_valid(int fd, uint64_t id);
*/
int seccomp_notify_fd(const scmp_filter_ctx ctx);

/**
* Install a file descriptor into the target's process.
* @param fd the notification fd
* @param addfd the addfd structure
*
* This function enables the caller to install/add a fd into the
* target's fd table. Returns the installed fd number on success and,
* negative values on failure.
*
*/
int seccomp_notify_addfd(int fd, struct seccomp_notif_addfd *addfd);

/**
* Generate seccomp Pseudo Filter Code (PFC) and export it to a file
* @param ctx the filter context
Expand Down
9 changes: 9 additions & 0 deletions src/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,15 @@ API int seccomp_notify_fd(const scmp_filter_ctx ctx)
return _rc_filter(sys_notify_fd());
}

/* NOTE - function header comment in include/seccomp.h */
API int seccomp_notify_addfd(int fd, struct seccomp_notif_addfd *addfd)
{
/* force a runtime api level detection */
_seccomp_api_update();

return _rc_filter(sys_notify_addfd(fd, addfd));
}

/* NOTE - function header comment in include/seccomp.h */
API int seccomp_export_pfc(const scmp_filter_ctx ctx, int fd)
{
Expand Down
8 changes: 8 additions & 0 deletions src/python/libseccomp.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ cdef extern from "seccomp.h":
int32_t error
uint32_t flags

cdef struct seccomp_notif_addfd:
uint64_t id
uint32_t flags
uint32_t srcfd
uint32_t newfd
uint32_t newfd_flags

scmp_version *seccomp_version()

unsigned int seccomp_api_get()
Expand Down Expand Up @@ -165,6 +172,7 @@ cdef extern from "seccomp.h":
void seccomp_notify_free(seccomp_notif *req, seccomp_notif_resp *resp)
int seccomp_notify_receive(int fd, seccomp_notif *req)
int seccomp_notify_respond(int fd, seccomp_notif_resp *resp)
int seccomp_notify_addfd(int fd, seccomp_notif_addfd *addfd)
int seccomp_notify_id_valid(int fd, uint64_t id)
int seccomp_notify_fd(scmp_filter_ctx ctx)

Expand Down
175 changes: 171 additions & 4 deletions src/python/seccomp.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,139 @@ cdef class NotificationResponse:
"""
self._flags = value

cdef class NotificationAddfd:
""" Python object representing a seccomp notification addfd structure.
"""
cdef uint64_t _id
cdef uint32_t _flags
cdef uint32_t _srcfd
cdef uint32_t _newfd
cdef uint32_t _newfd_flags

def __cinit__(self, notify, flags, srcfd, newfd = 0, newfd_flags = 0):
""" Initialize the notification addfd structure.

Arguments:
notify - a Notification object
srcfd - the source file descriptor
flags - notify addfd flags
newfd - 0 or desired file descriptor number in target
newfd_flags - new flags to set on the target file descriptor

Description:
Create a seccomp NotificationAddfd object.
"""
self._id = notify.id
self._flags = flags
self._srcfd = srcfd
self._newfd = newfd
self._newfd_flags = newfd_flags

@property
def id(self):
""" Get the seccomp notification request ID.

Description:
Get the seccomp notification request ID.
"""
return self._id

@id.setter
def id(self, value):
""" Set the seccomp notification request ID.

Arguments:
id - the seccomp notification request ID

Description:
Set the seccomp notification request ID.
"""
self._id = value

@property
def flags(self):
""" Get the seccomp notification addfd flags.

Description:
Get the seccomp notification addfd flags.
"""
return self._flags

@flags.setter
def flags(self, value):
""" Set the seccomp notification addfd flags.

Arguments:
flags - the notification addfd flags

Description:
Set the seccomp notification addfd flags.
"""
self._flags = value

@property
def srcfd(self):
""" Get the local file descriptor number.

Description:
Get the local file descriptor number.
"""
return self._srcfd

@srcfd.setter
def srcfd(self, value):
""" Set the local file descriptor number.

Arguments:
srcfd - the local file descriptor number

Description:
Set the local file descriptor number.
"""
self._srcfd = value

@property
def newfd(self):
""" Get the target file descriptor number.

Description:
Get the target file descriptor number.
"""
return self._newfd

@newfd.setter
def newfd(self, value):
""" Set the target file descriptor number.

Arguments:
newfd - the target file descriptor number

Description:
Set the target file descriptor number.
"""
self._newfd = value

@property
def newfd_flags(self):
""" Get the new flags to set on the target file descriptor.

Description:
Get the new flags to set on the target file descriptor.
"""
return self._newfd_flags

@newfd_flags.setter
def newfd_flags(self, value):
""" Set the new flags to set on the target file descriptor.

Arguments:
newfd_flags - the new flags to set on the target file descriptor

Description:
Set the new flags to set on the target file descriptor.
"""
self._newfd_flags = value

cdef class SyscallFilter:
""" Python object representing a seccomp syscall filter. """
cdef int _defaction
Expand Down Expand Up @@ -959,16 +1092,20 @@ cdef class SyscallFilter:
if rc != 0:
raise RuntimeError(str.format("Library error (errno = {0})", rc))

def receive_notify(self):
def receive_notify(self, fd = None):
""" Receive seccomp notifications.

Arguments:
fd - the notify file descriptor

Description:
Receive a seccomp notification from the system, requires the use of
the NOTIFY action.
"""
cdef libseccomp.seccomp_notif *req

fd = libseccomp.seccomp_notify_fd(self._ctx)
if fd is None:
fd = libseccomp.seccomp_notify_fd(self._ctx)
if fd < 0:
raise RuntimeError("Notifications not enabled/active")
rc = libseccomp.seccomp_notify_alloc(&req, NULL)
Expand All @@ -988,18 +1125,20 @@ cdef class SyscallFilter:
free(req)
return notify

def respond_notify(self, response):
def respond_notify(self, response, fd = None):
""" Send a seccomp notification response.

Arguments:
response - the response to send to the system
fd - the notify file descriptor

Description:
Respond to a seccomp notification.
"""
cdef libseccomp.seccomp_notif_resp *resp

fd = libseccomp.seccomp_notify_fd(self._ctx)
if fd is None:
fd = libseccomp.seccomp_notify_fd(self._ctx)
if fd < 0:
raise RuntimeError("Notifications not enabled/active")
rc = libseccomp.seccomp_notify_alloc(NULL, &resp)
Expand All @@ -1026,6 +1165,34 @@ cdef class SyscallFilter:
raise RuntimeError("Notifications not enabled/active")
return fd

def notify_addfd(self, addfd, fd = None):
"""Add a file descriptor to target

Arguments:
addfd - the addfd object
fd - the notify file descriptor

Description:
Add a file descriptor to the target process.
"""
if fd is None:
fd = libseccomp.seccomp_notify_fd(self._ctx)
if fd < 0:
raise RuntimeError("Notifications not enabled/active")

cdef libseccomp.seccomp_notif_addfd _addfd

_addfd.id = addfd.id
_addfd.flags = addfd.flags
_addfd.srcfd = addfd.srcfd
_addfd.newfd = addfd.newfd
_addfd.newfd_flags = addfd.newfd_flags

rc = libseccomp.seccomp_notify_addfd(fd, &_addfd)
if rc < 0:
raise RuntimeError(str.format("Library error (errno = {0})", rc))
return rc

def export_pfc(self, file):
""" Export the filter in PFC format.

Expand Down
23 changes: 23 additions & 0 deletions src/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -573,3 +573,26 @@ int sys_notify_id_valid(int fd, uint64_t id)
return -ENOENT;
return 0;
}

/**
* Install a file descriptor into the target's process.
* @param fd the notification fd
* @param addfd the addfd structure
*
* Install a file descriptor into the target's process. Returns the
* installed fd number on success, negative values on failure.
*
*/
int sys_notify_addfd(int fd, struct seccomp_notif_addfd *addfd)
{
int rc;
if (state.sup_user_notif <= 0)
return -EOPNOTSUPP;

rc = ioctl(fd, SECCOMP_IOCTL_NOTIF_ADDFD, addfd);
if (rc < 0 && errno == EINVAL)
return -EOPNOTSUPP;
if (rc < 0)
return -ECANCELED;
return rc;
}
7 changes: 7 additions & 0 deletions src/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,12 @@ struct seccomp_notif_sizes {

#endif /* SECCOMP_IOCTL_NOTIF_ID_VALID */

/* SECCOMP_IOCTL_NOTIF_ADDFD was added in kernel v5.10 */
#ifndef SECCOMP_IOCTL_NOTIF_ADDFD
#define SECCOMP_IOCTL_NOTIF_ADDFD SECCOMP_IOW(3, \
struct seccomp_notif_addfd)
#endif

/* non-public ioctl number for backwards compat (see system.c) */
#define SECCOMP_IOCTL_NOTIF_ID_VALID_WRONG_DIR SECCOMP_IOR(2, __u64)

Expand All @@ -202,4 +208,5 @@ int sys_notify_alloc(struct seccomp_notif **req,
int sys_notify_receive(int fd, struct seccomp_notif *req);
int sys_notify_respond(int fd, struct seccomp_notif_resp *resp);
int sys_notify_id_valid(int fd, uint64_t id);
int sys_notify_addfd(int fd, struct seccomp_notif_addfd *addfd);
#endif
1 change: 1 addition & 0 deletions tests/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,4 @@ util.pyc
60-sim-precompute
61-sim-transactions
62-sim-arch_transactions
63-live-notify_addfd
Loading
Loading