summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Moore <paul@paul-moore.com>2020-04-02 20:25:00 -0400
committerPaul Moore <paul@paul-moore.com>2020-06-16 11:21:28 -0400
commit7e02b9ef56e5547f4abfb7308ad8f611d7abe8be (patch)
tree65c8091fd251af877d580cb39a284e4aa8f489b6
parentd0713af4184b9a0fb510c14b4f04d4d64be22bf6 (diff)
downloadlibseccomp-7e02b9ef56e5547f4abfb7308ad8f611d7abe8be.tar.gz
api: filter the return codes we send to userspace
This is one part of including error codes in our API promise, it helps ensure we don't accidentally send an undocumented error code to the caller. Acked-by: Tom Hromatka <tom.hromatka@oracle.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
-rw-r--r--src/api.c153
1 files changed, 101 insertions, 52 deletions
diff --git a/src/api.c b/src/api.c
index 961c3f8..ba8fa5d 100644
--- a/src/api.c
+++ b/src/api.c
@@ -49,6 +49,51 @@ const struct scmp_version library_version = {
unsigned int seccomp_api_level = 0;
/**
+ * Filter the error codes we send back to callers
+ * @param err the error code
+ *
+ * We consider error codes part of our API so we want to make sure we don't
+ * accidentally send an undocumented error code to our callers. This function
+ * helps with that.
+ *
+ */
+static int _rc_filter(int err)
+{
+ /* pass through success values */
+ if (err >= 0)
+ return err;
+
+ /* filter the error codes */
+ switch (err) {
+ case -EACCES:
+ /* NOTE: operation is not permitted by libseccomp */
+ case -ECANCELED:
+ /* NOTE: kernel level error that is beyond the control of
+ * libseccomp */
+ case -EDOM:
+ /* NOTE: failure due to arch/ABI */
+ case -EEXIST:
+ /* NOTE: operation failed due to existing rule or filter */
+ case -EINVAL:
+ /* NOTE: invalid input to the libseccomp API */
+ case -ENOENT:
+ /* NOTE: no matching entry found */
+ case -ENOMEM:
+ /* NOTE: unable to allocate enough memory to perform the
+ * requested operation */
+ case -EOPNOTSUPP:
+ /* NOTE: operation is not supported */
+ case -ESRCH:
+ /* NOTE: operation failed due to multi-threading */
+ return err;
+ default:
+ /* NOTE: this is the default "internal libseccomp error"
+ * error code, it is our catch-all */
+ return -EFAULT;
+ }
+}
+
+/**
* Validate a filter context
* @param ctx the filter context
*
@@ -182,11 +227,11 @@ API int seccomp_api_set(unsigned int level)
sys_set_seccomp_action(SCMP_ACT_NOTIFY, true);
break;
default:
- return -EINVAL;
+ return _rc_filter(-EINVAL);
}
seccomp_api_level = level;
- return 0;
+ return _rc_filter(0);
}
/* NOTE - function header comment in include/seccomp.h */
@@ -208,9 +253,9 @@ API int seccomp_reset(scmp_filter_ctx ctx, uint32_t def_action)
/* use a NULL filter collection here since we are resetting it */
if (ctx == NULL || db_col_action_valid(NULL, def_action) < 0)
- return -EINVAL;
+ return _rc_filter(-EINVAL);
- return db_col_reset(col, def_action);
+ return _rc_filter(db_col_reset(col, def_action));
}
/* NOTE - function header comment in include/seccomp.h */
@@ -226,15 +271,15 @@ API int seccomp_merge(scmp_filter_ctx ctx_dst, scmp_filter_ctx ctx_src)
struct db_filter_col *col_src = (struct db_filter_col *)ctx_src;
if (db_col_valid(col_dst) || db_col_valid(col_src))
- return -EINVAL;
+ return _rc_filter(-EINVAL);
/* NOTE: only the default action, NNP, and TSYNC settings must match */
if ((col_dst->attr.act_default != col_src->attr.act_default) ||
(col_dst->attr.nnp_enable != col_src->attr.nnp_enable) ||
(col_dst->attr.tsync_enable != col_src->attr.tsync_enable))
- return -EINVAL;
+ return _rc_filter(-EINVAL);
- return db_col_merge(col_dst, col_src);
+ return _rc_filter(db_col_merge(col_dst, col_src));
}
/* NOTE - function header comment in include/seccomp.h */
@@ -267,9 +312,9 @@ API int seccomp_arch_exist(const scmp_filter_ctx ctx, uint32_t arch_token)
arch_token = arch_def_native->token;
if (arch_valid(arch_token))
- return -EINVAL;
+ return _rc_filter(-EINVAL);
- return (db_col_arch_exist(col, arch_token) ? 0 : -EEXIST);
+ return _rc_filter((db_col_arch_exist(col, arch_token) ? 0 : -EEXIST));
}
/* NOTE - function header comment in include/seccomp.h */
@@ -283,11 +328,11 @@ API int seccomp_arch_add(scmp_filter_ctx ctx, uint32_t arch_token)
arch = arch_def_lookup(arch_token);
if (arch == NULL)
- return -EINVAL;
+ return _rc_filter(-EINVAL);
if (db_col_arch_exist(col, arch_token))
- return -EEXIST;
+ return _rc_filter(-EEXIST);
- return db_col_db_new(col, arch);
+ return _rc_filter(db_col_db_new(col, arch));
}
/* NOTE - function header comment in include/seccomp.h */
@@ -299,11 +344,11 @@ API int seccomp_arch_remove(scmp_filter_ctx ctx, uint32_t arch_token)
arch_token = arch_def_native->token;
if (arch_valid(arch_token))
- return -EINVAL;
+ return _rc_filter(-EINVAL);
if (db_col_arch_exist(col, arch_token) != -EEXIST)
- return -EEXIST;
+ return _rc_filter(-EEXIST);
- return db_col_db_remove(col, arch_token);
+ return _rc_filter(db_col_db_remove(col, arch_token));
}
/* NOTE - function header comment in include/seccomp.h */
@@ -312,10 +357,10 @@ API int seccomp_load(const scmp_filter_ctx ctx)
struct db_filter_col *col;
if (_ctx_valid(ctx))
- return -EINVAL;
+ return _rc_filter(-EINVAL);
col = (struct db_filter_col *)ctx;
- return sys_filter_load(col);
+ return _rc_filter(sys_filter_load(col));
}
/* NOTE - function header comment in include/seccomp.h */
@@ -323,9 +368,10 @@ API int seccomp_attr_get(const scmp_filter_ctx ctx,
enum scmp_filter_attr attr, uint32_t *value)
{
if (_ctx_valid(ctx))
- return -EINVAL;
+ return _rc_filter(-EINVAL);
- return db_col_attr_get((const struct db_filter_col *)ctx, attr, value);
+ return _rc_filter(db_col_attr_get((const struct db_filter_col *)ctx,
+ attr, value));
}
/* NOTE - function header comment in include/seccomp.h */
@@ -333,9 +379,10 @@ API int seccomp_attr_set(scmp_filter_ctx ctx,
enum scmp_filter_attr attr, uint32_t value)
{
if (_ctx_valid(ctx))
- return -EINVAL;
+ return _rc_filter(-EINVAL);
- return db_col_attr_set((struct db_filter_col *)ctx, attr, value);
+ return _rc_filter(db_col_attr_set((struct db_filter_col *)ctx,
+ attr, value));
}
/* NOTE - function header comment in include/seccomp.h */
@@ -423,9 +470,9 @@ API int seccomp_syscall_priority(scmp_filter_ctx ctx,
struct db_filter_col *col = (struct db_filter_col *)ctx;
if (db_col_valid(col) || _syscall_valid(col, syscall))
- return -EINVAL;
+ return _rc_filter(-EINVAL);
- return db_col_syscall_priority(col, syscall, priority);
+ return _rc_filter(db_col_syscall_priority(col, syscall, priority));
}
/* NOTE - function header comment in include/seccomp.h */
@@ -438,20 +485,21 @@ API int seccomp_rule_add_array(scmp_filter_ctx ctx,
struct db_filter_col *col = (struct db_filter_col *)ctx;
if (arg_cnt > ARG_COUNT_MAX)
- return -EINVAL;
+ return _rc_filter(-EINVAL);
if (arg_cnt > 0 && arg_array == NULL)
- return -EINVAL;
+ return _rc_filter(-EINVAL);
if (db_col_valid(col) || _syscall_valid(col, syscall))
- return -EINVAL;
+ return _rc_filter(-EINVAL);
rc = db_col_action_valid(col, action);
if (rc < 0)
- return rc;
+ return _rc_filter(rc);
if (action == col->attr.act_default)
- return -EACCES;
+ return _rc_filter(-EACCES);
- return db_col_rule_add(col, 0, action, syscall, arg_cnt, arg_array);
+ return _rc_filter(db_col_rule_add(col, 0, action,
+ syscall, arg_cnt, arg_array));
}
/* NOTE - function header comment in include/seccomp.h */
@@ -466,7 +514,7 @@ API int seccomp_rule_add(scmp_filter_ctx ctx,
/* arg_cnt is unsigned, so no need to check the lower bound */
if (arg_cnt > ARG_COUNT_MAX)
- return -EINVAL;
+ return _rc_filter(-EINVAL);
va_start(arg_list, arg_cnt);
for (iter = 0; iter < arg_cnt; ++iter)
@@ -474,7 +522,7 @@ API int seccomp_rule_add(scmp_filter_ctx ctx,
rc = seccomp_rule_add_array(ctx, action, syscall, arg_cnt, arg_array);
va_end(arg_list);
- return rc;
+ return _rc_filter(rc);
}
/* NOTE - function header comment in include/seccomp.h */
@@ -487,23 +535,24 @@ API int seccomp_rule_add_exact_array(scmp_filter_ctx ctx,
struct db_filter_col *col = (struct db_filter_col *)ctx;
if (arg_cnt > ARG_COUNT_MAX)
- return -EINVAL;
+ return _rc_filter(-EINVAL);
if (arg_cnt > 0 && arg_array == NULL)
- return -EINVAL;
+ return _rc_filter(-EINVAL);
if (db_col_valid(col) || _syscall_valid(col, syscall))
- return -EINVAL;
+ return _rc_filter(-EINVAL);
rc = db_col_action_valid(col, action);
if (rc < 0)
- return rc;
+ return _rc_filter(rc);
if (action == col->attr.act_default)
- return -EACCES;
+ return _rc_filter(-EACCES);
if (col->filter_cnt > 1)
- return -EOPNOTSUPP;
+ return _rc_filter(-EOPNOTSUPP);
- return db_col_rule_add(col, 1, action, syscall, arg_cnt, arg_array);
+ return _rc_filter(db_col_rule_add(col, 1, action,
+ syscall, arg_cnt, arg_array));
}
/* NOTE - function header comment in include/seccomp.h */
@@ -518,7 +567,7 @@ API int seccomp_rule_add_exact(scmp_filter_ctx ctx,
/* arg_cnt is unsigned, so no need to check the lower bound */
if (arg_cnt > ARG_COUNT_MAX)
- return -EINVAL;
+ return _rc_filter(-EINVAL);
va_start(arg_list, arg_cnt);
for (iter = 0; iter < arg_cnt; ++iter)
@@ -527,7 +576,7 @@ API int seccomp_rule_add_exact(scmp_filter_ctx ctx,
action, syscall, arg_cnt, arg_array);
va_end(arg_list);
- return rc;
+ return _rc_filter(rc);
}
/* NOTE - function header comment in include/seccomp.h */
@@ -537,7 +586,7 @@ API int seccomp_notify_alloc(struct seccomp_notif **req,
/* force a runtime api level detection */
_seccomp_api_update();
- return sys_notify_alloc(req, resp);
+ return _rc_filter(sys_notify_alloc(req, resp));
}
/* NOTE - function header comment in include/seccomp.h */
@@ -553,13 +602,13 @@ API void seccomp_notify_free(struct seccomp_notif *req,
/* NOTE - function header comment in include/seccomp.h */
API int seccomp_notify_receive(int fd, struct seccomp_notif *req)
{
- return sys_notify_receive(fd, req);
+ return _rc_filter(sys_notify_receive(fd, req));
}
/* NOTE - function header comment in include/seccomp.h */
API int seccomp_notify_respond(int fd, struct seccomp_notif_resp *resp)
{
- return sys_notify_respond(fd, resp);
+ return _rc_filter(sys_notify_respond(fd, resp));
}
/* NOTE - function header comment in include/seccomp.h */
@@ -568,7 +617,7 @@ API int seccomp_notify_id_valid(int fd, uint64_t id)
/* force a runtime api level detection */
_seccomp_api_update();
- return sys_notify_id_valid(fd, id);
+ return _rc_filter(sys_notify_id_valid(fd, id));
}
/* NOTE - function header comment in include/seccomp.h */
@@ -580,19 +629,19 @@ API int seccomp_notify_fd(const scmp_filter_ctx ctx)
_seccomp_api_update();
if (_ctx_valid(ctx))
- return -EINVAL;
+ return _rc_filter(-EINVAL);
col = (struct db_filter_col *)ctx;
- return col->notify_fd;
+ return _rc_filter(col->notify_fd);
}
/* NOTE - function header comment in include/seccomp.h */
API int seccomp_export_pfc(const scmp_filter_ctx ctx, int fd)
{
if (_ctx_valid(ctx))
- return -EINVAL;
+ return _rc_filter(-EINVAL);
- return gen_pfc_generate((struct db_filter_col *)ctx, fd);
+ return _rc_filter(gen_pfc_generate((struct db_filter_col *)ctx, fd));
}
/* NOTE - function header comment in include/seccomp.h */
@@ -602,15 +651,15 @@ API int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd)
struct bpf_program *program;
if (_ctx_valid(ctx))
- return -EINVAL;
+ return _rc_filter(-EINVAL);
program = gen_bpf_generate((struct db_filter_col *)ctx);
if (program == NULL)
- return -ENOMEM;
+ return _rc_filter(-ENOMEM);
rc = write(fd, program->blks, BPF_PGM_SIZE(program));
gen_bpf_release(program);
if (rc < 0)
- return -ECANCELED;
+ return _rc_filter(-ECANCELED);
- return 0;
+ return _rc_filter(0);
}