diff --git a/src/api.c b/src/api.c index 413cc81a..b002ec64 100644 --- a/src/api.c +++ b/src/api.c @@ -755,6 +755,9 @@ API int seccomp_export_pfc(const scmp_filter_ctx ctx, int fd) API int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd) { int rc; + ssize_t n; + size_t len; + const char *buf; struct db_filter_col *col; struct bpf_program *program; @@ -766,9 +769,22 @@ API int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd) if (rc < 0) return _rc_filter(rc); program = col->prgm_bpf; - rc = write(fd, program->blks, BPF_PGM_SIZE(program)); - if (rc < 0) - return _rc_filter_sys(col, -errno); + + /* handle short writes and EINTR */ + buf = (const char *)program->blks; + len = BPF_PGM_SIZE(program); + while (len > 0) { + n = write(fd, buf, len); + if (n < 0) { + if (errno == EINTR) + continue; + return _rc_filter_sys(col, -errno); + } + if (n == 0) + return _rc_filter_sys(col, -EIO); + buf += n; + len -= n; + } return 0; } diff --git a/tests/11-basic-basic_errors.c b/tests/11-basic-basic_errors.c index dcfa7c28..365b87c1 100644 --- a/tests/11-basic-basic_errors.c +++ b/tests/11-basic-basic_errors.c @@ -19,7 +19,9 @@ * along with this library; if not, see . */ +#define _GNU_SOURCE #include +#include #include #include @@ -32,6 +34,8 @@ int main(int argc, char *argv[]) unsigned int api; struct seccomp_notif *req = NULL; struct seccomp_notif_resp *resp = NULL; + int pipefd[2]; + int i; /* get the api level */ api = seccomp_api_get(); @@ -179,6 +183,29 @@ int main(int argc, char *argv[]) seccomp_release(ctx); ctx = NULL; + /* seccomp_export_bpf short write */ + ctx = seccomp_init(SCMP_ACT_ALLOW); + if (ctx == NULL) + return -1; + for (i = 0; i < 1024; i++) { + rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(1), SCMP_SYS(write), 1, + SCMP_A0(SCMP_CMP_EQ, i)); + if (rc != 0) + return -1; + } + if (pipe2(pipefd, O_NONBLOCK) < 0) + return -1; + /* a pipe smaller than the filter only takes a part of it */ + if (fcntl(pipefd[1], F_SETPIPE_SZ, getpagesize()) < 0) + return -1; + rc = seccomp_export_bpf(ctx, pipefd[1]); + if (rc != -ECANCELED) + return -1; + close(pipefd[0]); + close(pipefd[1]); + seccomp_release(ctx); + ctx = NULL; + /* seccomp_export_bpf_mem errors */ char buf[1024]; size_t buf_len = sizeof(buf);