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

RFE: user notification #147

Closed
wants to merge 3 commits into from
Closed
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 doc/man/man3/seccomp_api_get.3
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ syscall to load the seccomp filter into the kernel.
.TP
.B 3
The SCMP_FLTATR_CTL_LOG filter attribute and the SCMP_ACT_LOG action are supported.
.TP
.B 4
The SCMP_FLTATR_SPEC_ALLOW filter attribute is supported.
.TP
.B 5
The SCMP_FLTATR_NEW_LISTENER filter attribute and the SCMP_ACT_NEW_LISTENER
action are supported.
.\" //////////////////////////////////////////////////////////////////////////
.SH RETURN VALUE
.\" //////////////////////////////////////////////////////////////////////////
Expand Down
12 changes: 12 additions & 0 deletions doc/man/man3/seccomp_attr_set.3
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@ the
action. Defaults to off (
.I value
== 0).
.TP
.B SCMP_FLTATR_SPEC_ALLOW
A flag to disable Speculative Store Bypass mitigations for this filter.
Defaults to off (
.I value
== 0).
.TP
.B SCMP_FLTATR_NEW_LISTENER
Generate a userspace listener file descriptor when this filter is installed.
Defaults to off (
.I value
== 0).
.\" //////////////////////////////////////////////////////////////////////////
.SH RETURN VALUE
.\" //////////////////////////////////////////////////////////////////////////
Expand Down
105 changes: 105 additions & 0 deletions doc/man/man3/seccomp_notif_alloc.3
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
.TH "seccomp_notif_alloc" 3 "24 April 2019" "tycho@tycho.ws" "libseccomp Documentation"
.\" //////////////////////////////////////////////////////////////////////////
.SH NAME
.\" //////////////////////////////////////////////////////////////////////////
seccomp_notif_alloc, seccomp_notif_free, seccomp_notif_receive,
seccomp_notif_send_resp, seccomp_notif_id_valid, seccomp_notif_fd \- Manage seccomp notifications
.\" //////////////////////////////////////////////////////////////////////////
.SH SYNOPSIS
.\" //////////////////////////////////////////////////////////////////////////
.nf
.B #include <seccomp.h>
.sp
.BI "int seccomp_notif_alloc(struct seccomp_notif **" req ", struct seccomp_notif_resp **" resp ")"
.BI "void seccomp_notif_free(struct seccomp_notif *" req ", struct seccomp_notif_resp *" resp ")"
.BI "int seccomp_notif_receive(int " fd ", struct seccomp_notif *" req ")"
.BI "int seccomp_notif_send_resp(int " fd ", struct seccomp_notif_resp *" resp ")"
.BI "int seccomp_notif_id_valid(int " fd ", uint64_t " id ")"
.BI "int seccomp_notif_fd(const scmp_filter_ctx " ctx ")"
.sp
Link with \fI\-lseccomp\fP.
.fi
.\" //////////////////////////////////////////////////////////////////////////
.SH DESCRIPTION
.\" //////////////////////////////////////////////////////////////////////////
.P
The
.BR seccomp_notif_alloc ()
function dynamically allocates enough memory for a seccomp notification and
response. Note that one should always use these functions and not depend on the
structure sizes in headers, since the size can vary depending on the kernel
version. This function takes care to ask the kerenl how big each structure
should be, and allocates the right amount of memory. The
.BR seccomp_notif_free ()
function frees memory allocated by
.BR seccomp_notif_alloc ().
.P
The
.BR seccomp_notif_receive ()
function receives a notification from a seccomp notify fd (obtained from
.BR seccomp_notif_fd ()).
.P
The
.BR seccomp_notif_send_resp ()
function sends a response to a particular notification. The id field should be
the same as the id from the request, so that the kernel knows which request
this response corresponds to.
.P
The
.BR seccomp_notif_id_valid ()
function checks to see if the syscall from a particualr notification request is
still valid, i.e. if the task is still alive. See NOTES below for details on
race conditions.
.P
The
.BR seccomp_notif_fd ()
returns the notification fd of a filter after it has been loaded. Note that one
must set the
.BR SCMP_FLTATR_NEW_LISTENER
attribute and have loaded the filter, or this function returns an error.
.\" //////////////////////////////////////////////////////////////////////////
.SH RETURN VALUE
.\" //////////////////////////////////////////////////////////////////////////
.P
The
.BR seccomp_notif_alloc (),
.BR seccomp_notif_receive (),
and
.BR seccomp_notif_send_resp ()
functions all return 0 on success, -1 on failure.
.P
The
.BR seccomp_notif_id_valid ()
returns 0 if the id is valid, and -ENOENT if it is not.
.P
The
.BR seccomp_notif_fd ()
returns the notification fd of a filter that was loaded with the
.BR SCMP_FLTATR_NEW_LISTENER
attribute set.
.\" //////////////////////////////////////////////////////////////////////////
.SH NOTES
.\" //////////////////////////////////////////////////////////////////////////
.P
Care should be taken to avoid two different time of check/time of use errors.
First, after opening any resources relevant to the pid for a notification (e.g.
/proc/pid/mem for reading tracee memory to make policy decisions), applications
should call
.BR seccomp_notif_id_valid ()
to make sure that the resources the application has opened correspond to the
right pid, i.e. that the pid didn't die and a different task take its place.
.P
Second, the classic time of check/time of use issue with seccomp memory should
also be avoided: applications should copy any memory they wish to use to make
decisions from the tracee into its own address space before applying any policy
decisions, since a multi-threaded tracee may edit the memory at any time,
including after it's used to make a policy decision.
.P
A complete example of how to avoid these two races is available in the Linux
Kernel source tree a
.BR /samples/seccomp/user-trap.c.
.\" //////////////////////////////////////////////////////////////////////////
.SH AUTHOR
.\" //////////////////////////////////////////////////////////////////////////
Tycho Andersen <tycho@tycho.ws>
.\" //////////////////////////////////////////////////////////////////////////
1 change: 1 addition & 0 deletions doc/man/man3/seccomp_notif_fd.3
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.so man3/seccomp_notif_alloc.3
1 change: 1 addition & 0 deletions doc/man/man3/seccomp_notif_free.3
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.so man3/seccomp_notif_alloc.3
1 change: 1 addition & 0 deletions doc/man/man3/seccomp_notif_id_valid.3
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.so man3/seccomp_notif_alloc.3
1 change: 1 addition & 0 deletions doc/man/man3/seccomp_notif_receive.3
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.so man3/seccomp_notif_alloc.3
1 change: 1 addition & 0 deletions doc/man/man3/seccomp_notif_send_resp.3
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.so man3/seccomp_notif_alloc.3
110 changes: 110 additions & 0 deletions include/seccomp.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <inttypes.h>
#include <asm/unistd.h>
#include <linux/audit.h>
#include <linux/seccomp.h>
pcmoore marked this conversation as resolved.
Show resolved Hide resolved

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -65,6 +66,8 @@ enum scmp_filter_attr {
SCMP_FLTATR_CTL_TSYNC = 4, /**< sync threads on filter load */
SCMP_FLTATR_API_TSKIP = 5, /**< allow rules with a -1 syscall */
SCMP_FLTATR_CTL_LOG = 6, /**< log not-allowed actions */
SCMP_FLTATR_SPEC_ALLOW = 7, /**< disable SSB mitigation */
pcmoore marked this conversation as resolved.
Show resolved Hide resolved
pcmoore marked this conversation as resolved.
Show resolved Hide resolved
SCMP_FLTATR_NEW_LISTENER = 8, /**< returns a listener fd */
pcmoore marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

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

See my previous comment regarding attribute names (my apologies once again). Similar to the last one, this should probably be SCMP_FLTATR_CTL_<blah>.

_SCMP_FLTATR_MAX,
};

Expand Down Expand Up @@ -318,6 +321,10 @@ struct scmp_arg_cmp {
* Throw a SIGSYS signal
*/
#define SCMP_ACT_TRAP 0x00030000U
/**
* Notifies userspace
*/
#define SCMP_ACT_USER_NOTIF 0x7fc00000U
/**
* Return the specified error code
*/
Expand All @@ -335,6 +342,46 @@ struct scmp_arg_cmp {
*/
#define SCMP_ACT_ALLOW 0x7fff0000U

/*
* User notification bits. It's a little unfortunate that we don't export
* system.h, so we end up having to define all these structures again.
* SECCOMP_RET_USER_NOTIF was added in kernel 5.0.
*/
Copy link
Member

Choose a reason for hiding this comment

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

We generally don't include commentary like this in the libseccomp header file :)

I think it's both appropriate and a good idea to add a one-liner about user notification first appearing in Linux v5.0 but I would leave it at that.

Copy link
Member

Choose a reason for hiding this comment

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

I probably wasn't clear enough about this previously, but this is what I was thinking for a comment:

/* User notification bits was added in Linux v5.0 */

#ifndef SECCOMP_RET_USER_NOTIF
#define SECCOMP_RET_USER_NOTIF 0x7fc00000U

struct seccomp_notif_sizes {
__u16 seccomp_notif;
__u16 seccomp_notif_resp;
__u16 seccomp_data;
};

struct seccomp_notif {
__u64 id;
__u32 pid;
__u32 flags;
struct seccomp_data data;
};

struct seccomp_notif_resp {
__u64 id;
__s64 val;
__s32 error;
__u32 flags;
};
#define SECCOMP_IOC_MAGIC '!'
#define SECCOMP_IO(nr) _IO(SECCOMP_IOC_MAGIC, nr)
#define SECCOMP_IOR(nr, type) _IOR(SECCOMP_IOC_MAGIC, nr, type)
#define SECCOMP_IOW(nr, type) _IOW(SECCOMP_IOC_MAGIC, nr, type)
#define SECCOMP_IOWR(nr, type) _IOWR(SECCOMP_IOC_MAGIC, nr, type)

/* Flags for seccomp notification fd ioctl. */
#define SECCOMP_IOCTL_NOTIF_RECV SECCOMP_IOWR(0, struct seccomp_notif)
#define SECCOMP_IOCTL_NOTIF_SEND SECCOMP_IOWR(1, \
struct seccomp_notif_resp)
#define SECCOMP_IOCTL_NOTIF_ID_VALID SECCOMP_IOR(2, __u64)
#endif

Copy link
Member

Choose a reason for hiding this comment

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

Everything in this chunk needs to be documented in a manpage.

/*
* functions
*/
Expand Down Expand Up @@ -367,6 +414,8 @@ const struct scmp_version *seccomp_version(void);
* 3 : support for the SCMP_FLTATR_CTL_LOG filter attribute
* support for the SCMP_ACT_LOG action
* support for the SCMP_ACT_KILL_PROCESS action
* 4 : support for the SCMP_FLTATR_SPEC_ALLOW filter attrbute
pcmoore marked this conversation as resolved.
Show resolved Hide resolved
* 5 : support for the SCMP_FLTATR_NEW_LISTENER filter attribute
*
*/
unsigned int seccomp_api_get(void);
Expand Down Expand Up @@ -693,6 +742,67 @@ int seccomp_export_pfc(const scmp_filter_ctx ctx, int fd);
*/
int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd);

/**
* Allocate a pair of notification request/response structures.
* @param req the request location
* @param resp the response location
*
* This function allocates a pair of request/response structure by computing
* the correct sized based on the currently running kernel. It returns zero on
* success, and negative values on failure.
*/
int seccomp_notif_alloc(struct seccomp_notif **req,
struct seccomp_notif_resp **resp);

Copy link
Member

Choose a reason for hiding this comment

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

All of these new APIs need to be documented in one or more manpages.

/**
* Free a pair of notification request/response structures.
* @param req the request location
* @param resp the response location
*/
void seccomp_notif_free(struct seccomp_notif *req,
struct seccomp_notif_resp *resp);
/**
* Receive a notification from a seccomp notification fd.
* @param fd the notification fd
* @param req the request buffer to save into
*
* Blocks waiting for a notification on this fd. This function is thread safe
* (synchronization is performed in the kernel). Returns zero on success,
* negative values on error.
*/
int seccomp_notif_receive(int fd, struct seccomp_notif *req);

/**
* Send a notification response to a seccomp notification fd.
* @param fd the notification fd
* @param resp the response buffer to use
*
* Sends a notification response on this fd. This function is thread safe
* (synchronization is performed in the kernel). Returns zero on success,
* negative values on error.
*/
int seccomp_notif_send_resp(int fd, struct seccomp_notif_resp *resp);

/**
* Check if a notification id is still valid.
* @param fd the notification fd
* @param id the id to test
*
* Checks to see if a notification id is still valid. Returns 0 on success, and
* negative values on failure.
*/
int seccomp_notif_id_valid(int fd, uint64_t id);

/**
* Return the notification fd from a filter that has already been loaded.
* @param ctx the filter context
*
* This returns the listener fd that was generated when the seccomp policy was
* loaded. This is only valid after seccomp_load() with
* SCMP_FLTATR_NEW_LISTENER set.
*/
int seccomp_notif_fd(const scmp_filter_ctx ctx);

/*
* pseudo syscall definitions
*/
Expand Down
Loading