// SPDX-License-Identifier: GPL-2.0 /* * Linux Security Module infrastructure tests * Tests for the lsm_get_self_attr system call * * Copyright © 2022 Casey Schaufler */ #define _GNU_SOURCE #include #include #include #include #include #include #include "../kselftest_harness.h" #include "common.h" static struct lsm_ctx *next_ctx(struct lsm_ctx *ctxp) { void *vp; vp = (void *)ctxp + sizeof(*ctxp) + ctxp->ctx_len; return (struct lsm_ctx *)vp; } TEST(size_null_lsm_get_self_attr) { const long page_size = sysconf(_SC_PAGESIZE); struct lsm_ctx *ctx = calloc(page_size, 1); ASSERT_NE(NULL, ctx); errno = 0; ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, NULL, 0)); ASSERT_EQ(EINVAL, errno); free(ctx); } TEST(ctx_null_lsm_get_self_attr) { const long page_size = sysconf(_SC_PAGESIZE); size_t size = page_size; int rc; rc = lsm_get_self_attr(LSM_ATTR_CURRENT, NULL, &size, 0); if (attr_lsm_count()) { ASSERT_NE(-1, rc); ASSERT_NE(1, size); } else { ASSERT_EQ(-1, rc); } } TEST(size_too_small_lsm_get_self_attr) { const long page_size = sysconf(_SC_PAGESIZE); struct lsm_ctx *ctx = calloc(page_size, 1); size_t size = 1; ASSERT_NE(NULL, ctx); errno = 0; ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, &size, 0)); if (attr_lsm_count()) { ASSERT_EQ(E2BIG, errno); } else { ASSERT_EQ(EOPNOTSUPP, errno); } ASSERT_NE(1, size); free(ctx); } TEST(flags_zero_lsm_get_self_attr) { const long page_size = sysconf(_SC_PAGESIZE); struct lsm_ctx *ctx = calloc(page_size, 1); __u64 *syscall_lsms = calloc(page_size, 1); size_t size; int lsmcount; int i; ASSERT_NE(NULL, ctx); errno = 0; size = page_size; ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, &size, LSM_FLAG_SINGLE)); ASSERT_EQ(EINVAL, errno); ASSERT_EQ(page_size, size); lsmcount = syscall(__NR_lsm_list_modules, syscall_lsms, &size, 0); ASSERT_LE(1, lsmcount); ASSERT_NE(NULL, syscall_lsms); for (i = 0; i < lsmcount; i++) { errno = 0; size = page_size; ctx->id = syscall_lsms[i]; if (syscall_lsms[i] == LSM_ID_SELINUX || syscall_lsms[i] == LSM_ID_SMACK || syscall_lsms[i] == LSM_ID_APPARMOR) { ASSERT_EQ(1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, &size, LSM_FLAG_SINGLE)); } else { ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, &size, LSM_FLAG_SINGLE)); } } free(ctx); } TEST(flags_overset_lsm_get_self_attr) { const long page_size = sysconf(_SC_PAGESIZE); struct lsm_ctx *ctx = calloc(page_size, 1); size_t size; ASSERT_NE(NULL, ctx); errno = 0; size = page_size; ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT | LSM_ATTR_PREV, ctx, &size, 0)); ASSERT_EQ(EOPNOTSUPP, errno); errno = 0; size = page_size; ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, &size, LSM_FLAG_SINGLE | (LSM_FLAG_SINGLE << 1))); ASSERT_EQ(EINVAL, errno); free(ctx); } TEST(basic_lsm_get_self_attr) { const long page_size = sysconf(_SC_PAGESIZE); size_t size = page_size; struct lsm_ctx *ctx = calloc(page_size, 1); struct lsm_ctx *tctx = NULL; __u64 *syscall_lsms = calloc(page_size, 1); char *attr = calloc(page_size, 1); int cnt_current = 0; int cnt_exec = 0; int cnt_fscreate = 0; int cnt_keycreate = 0; int cnt_prev = 0; int cnt_sockcreate = 0; int lsmcount; int count; int i; ASSERT_NE(NULL, ctx); ASSERT_NE(NULL, syscall_lsms); lsmcount = syscall(__NR_lsm_list_modules, syscall_lsms, &size, 0); ASSERT_LE(1, lsmcount); for (i = 0; i < lsmcount; i++) { switch (syscall_lsms[i]) { case LSM_ID_SELINUX: cnt_current++; cnt_exec++; cnt_fscreate++; cnt_keycreate++; cnt_prev++; cnt_sockcreate++; break; case LSM_ID_SMACK: cnt_current++; break; case LSM_ID_APPARMOR: cnt_current++; cnt_exec++; cnt_prev++; break; default: break; } } if (cnt_current) { size = page_size; count = lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, &size, 0); ASSERT_EQ(cnt_current, count); tctx = ctx; ASSERT_EQ(0, read_proc_attr("current", attr, page_size)); ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); for (i = 1; i < count; i++) { tctx = next_ctx(tctx); ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); } } if (cnt_exec) { size = page_size; count = lsm_get_self_attr(LSM_ATTR_EXEC, ctx, &size, 0); ASSERT_GE(cnt_exec, count); if (count > 0) { tctx = ctx; if (read_proc_attr("exec", attr, page_size) == 0) ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); } for (i = 1; i < count; i++) { tctx = next_ctx(tctx); ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); } } if (cnt_fscreate) { size = page_size; count = lsm_get_self_attr(LSM_ATTR_FSCREATE, ctx, &size, 0); ASSERT_GE(cnt_fscreate, count); if (count > 0) { tctx = ctx; if (read_proc_attr("fscreate", attr, page_size) == 0) ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); } for (i = 1; i < count; i++) { tctx = next_ctx(tctx); ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); } } if (cnt_keycreate) { size = page_size; count = lsm_get_self_attr(LSM_ATTR_KEYCREATE, ctx, &size, 0); ASSERT_GE(cnt_keycreate, count); if (count > 0) { tctx = ctx; if (read_proc_attr("keycreate", attr, page_size) == 0) ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); } for (i = 1; i < count; i++) { tctx = next_ctx(tctx); ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); } } if (cnt_prev) { size = page_size; count = lsm_get_self_attr(LSM_ATTR_PREV, ctx, &size, 0); ASSERT_GE(cnt_prev, count); if (count > 0) { tctx = ctx; ASSERT_EQ(0, read_proc_attr("prev", attr, page_size)); ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); for (i = 1; i < count; i++) { tctx = next_ctx(tctx); ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); } } } if (cnt_sockcreate) { size = page_size; count = lsm_get_self_attr(LSM_ATTR_SOCKCREATE, ctx, &size, 0); ASSERT_GE(cnt_sockcreate, count); if (count > 0) { tctx = ctx; if (read_proc_attr("sockcreate", attr, page_size) == 0) ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); } for (i = 1; i < count; i++) { tctx = next_ctx(tctx); ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); } } free(ctx); free(attr); free(syscall_lsms); } TEST_HARNESS_MAIN