Skip to content

Commit

Permalink
seccomp: custom annotation to load raw bpf
Browse files Browse the repository at this point in the history
Add an annotation `run.oci.seccomp_bpf_data` to ignore the seccomp
section in the OCI configuration file and use the specified file as
the raw data to the `seccomp(SECCOMP_SET_MODE_FILTER)` syscall.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
  • Loading branch information
giuseppe committed Feb 11, 2021
1 parent 8ba7d9a commit a140be8
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 4 deletions.
11 changes: 11 additions & 0 deletions crun.1
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,17 @@ are available on the \fB\fCld.so(8)\fR man page.
If the annotation \fB\fCrun.oci.seccomp\_fail\_unknown\_syscall\fR is present, then crun
will fail when an unknown syscall is encountered in the seccomp configuration.

.SH \fB\fCrun.oci.seccomp\_bpf\_data=PATH\fR
.PP
If the annotation \fB\fCrun.oci.seccomp\_bpf\_data\fR is present, then crun
ignores the seccomp section in the OCI configuration file and use the specified data
as the raw data to the \fB\fCseccomp(SECCOMP\_SET\_MODE\_FILTER)\fR syscall.
The data must be encoded in base64.

.PP
It is an experimental feature, and the annotation will be removed once
it is supported in the OCI runtime specs.

.SH \fB\fCrun.oci.keep\_original\_groups=1\fR
.PP
If the annotation \fB\fCrun.oci.keep\_original\_groups\fR is present, then crun
Expand Down
10 changes: 10 additions & 0 deletions crun.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,16 @@ are available on the `ld.so(8)` man page.
If the annotation `run.oci.seccomp_fail_unknown_syscall` is present, then crun
will fail when an unknown syscall is encountered in the seccomp configuration.

## `run.oci.seccomp_bpf_data=PATH`

If the annotation `run.oci.seccomp_bpf_data` is present, then crun
ignores the seccomp section in the OCI configuration file and use the specified data
as the raw data to the `seccomp(SECCOMP_SET_MODE_FILTER)` syscall.
The data must be encoded in base64.

It is an experimental feature, and the annotation will be removed once
it is supported in the OCI runtime specs.

## `run.oci.keep_original_groups=1`

If the annotation `run.oci.keep_original_groups` is present, then crun
Expand Down
32 changes: 28 additions & 4 deletions src/libcrun/container.c
Original file line number Diff line number Diff line change
Expand Up @@ -1839,7 +1839,7 @@ libcrun_container_run_internal (libcrun_container_t *container, libcrun_context_
if (UNLIKELY (ret < 0))
return ret;

if (def->linux && def->linux->seccomp)
if (def->linux && (def->linux->seccomp || find_annotation (container, "run.oci.seccomp_bpf_data")))
{
ret = open_seccomp_output (context->id, &seccomp_fd, false, context->state_root, err);
if (UNLIKELY (ret < 0))
Expand Down Expand Up @@ -1949,9 +1949,33 @@ libcrun_container_run_internal (libcrun_container_t *container, libcrun_context_
if (annotation && strcmp (annotation, "0") != 0)
seccomp_gen_options = LIBCRUN_SECCOMP_FAIL_UNKNOWN_SYSCALL;

ret = libcrun_generate_seccomp (container, seccomp_fd, seccomp_gen_options, err);
if (UNLIKELY (ret < 0))
return cleanup_watch (context, pid, sync_socket, terminal_fd, err);
if ((annotation = find_annotation (container, "run.oci.seccomp_bpf_data")) != NULL)
{
cleanup_free char *bpf_data = NULL;
size_t size = 0;
size_t in_size;
int consumed;

in_size = strlen (annotation);
bpf_data = xmalloc (in_size + 1);

consumed = base64_decode (annotation, in_size, bpf_data, in_size, &size);
if (UNLIKELY (consumed != (int) in_size))
return crun_make_error (err, 0, "invalid seccomp BPF data");

ret = safe_write (seccomp_fd, bpf_data, (ssize_t) size);
if (UNLIKELY (ret < 0))
{
crun_make_error (err, 0, "write to seccomp fd");
return cleanup_watch (context, pid, sync_socket, terminal_fd, err);
}
}
else
{
ret = libcrun_generate_seccomp (container, seccomp_fd, seccomp_gen_options, err);
if (UNLIKELY (ret < 0))
return cleanup_watch (context, pid, sync_socket, terminal_fd, err);
}
close_and_reset (&seccomp_fd);
}

Expand Down
57 changes: 57 additions & 0 deletions src/libcrun/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1993,3 +1993,60 @@ append_paths (char **out, libcrun_error_t *err, ...)
(*out)[copied] = '\0';
return 0;
}

/* Adapted from mailutils 0.6.91 (distributed under LGPL 2.0+) */
static int
b64_input (char c)
{
const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int i;

for (i = 0; i < 64; i++)
{
if (table[i] == c)
return i;
}
return -1;
}

int
base64_decode (const char *iptr, size_t isize, char *optr, size_t osize, size_t *nbytes)
{
int i = 0, tmp = 0, pad = 0;
size_t consumed = 0;
unsigned char data[4];

*nbytes = 0;
while (consumed < isize && (*nbytes) + 3 < osize)
{
while ((i < 4) && (consumed < isize))
{
tmp = b64_input (*iptr++);
consumed++;
if (tmp != -1)
data[i++] = tmp;
else if (*(iptr - 1) == '=')
{
data[i++] = '\0';
pad++;
}
}

/* I have a entire block of data 32 bits get the output data. */
if (i == 4)
{
*optr++ = (data[0] << 2) | ((data[1] & 0x30) >> 4);
*optr++ = ((data[1] & 0xf) << 4) | ((data[2] & 0x3c) >> 2);
*optr++ = ((data[2] & 0x3) << 6) | data[3];
(*nbytes) += 3 - pad;
}
else
{
/* I did not get all the data. */
consumed -= i;
return consumed;
}
i = 0;
}
return consumed;
}
2 changes: 2 additions & 0 deletions src/libcrun/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,4 +251,6 @@ int append_paths (char **out, libcrun_error_t *err, ...);

LIBCRUN_PUBLIC int libcrun_str2sig (const char *name);

int base64_decode (const char *iptr, size_t isize, char *optr, size_t osize, size_t *nbytes);

#endif

0 comments on commit a140be8

Please sign in to comment.