1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Linux Security Module infrastructure tests 4 * Tests for the lsm_get_self_attr system call 5 * 6 * Copyright © 2022 Casey Schaufler <casey@schaufler-ca.com> 7 */ 8 9 #define _GNU_SOURCE 10 #include <linux/lsm.h> 11 #include <fcntl.h> 12 #include <string.h> 13 #include <stdio.h> 14 #include <unistd.h> 15 #include <sys/types.h> 16 #include "../kselftest_harness.h" 17 #include "common.h" 18 19 static struct lsm_ctx *next_ctx(struct lsm_ctx *ctxp) 20 { 21 void *vp; 22 23 vp = (void *)ctxp + sizeof(*ctxp) + ctxp->ctx_len; 24 return (struct lsm_ctx *)vp; 25 } 26 27 TEST(size_null_lsm_get_self_attr) 28 { 29 const long page_size = sysconf(_SC_PAGESIZE); 30 struct lsm_ctx *ctx = calloc(page_size, 1); 31 32 ASSERT_NE(NULL, ctx); 33 errno = 0; 34 ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, NULL, 0)); 35 ASSERT_EQ(EINVAL, errno); 36 37 free(ctx); 38 } 39 40 TEST(ctx_null_lsm_get_self_attr) 41 { 42 const long page_size = sysconf(_SC_PAGESIZE); 43 __u32 size = page_size; 44 int rc; 45 46 rc = lsm_get_self_attr(LSM_ATTR_CURRENT, NULL, &size, 0); 47 48 if (attr_lsm_count()) { 49 ASSERT_NE(-1, rc); 50 ASSERT_NE(1, size); 51 } else { 52 ASSERT_EQ(-1, rc); 53 } 54 } 55 56 TEST(size_too_small_lsm_get_self_attr) 57 { 58 const long page_size = sysconf(_SC_PAGESIZE); 59 struct lsm_ctx *ctx = calloc(page_size, 1); 60 __u32 size = 1; 61 62 ASSERT_NE(NULL, ctx); 63 errno = 0; 64 ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, &size, 0)); 65 if (attr_lsm_count()) { 66 ASSERT_EQ(E2BIG, errno); 67 } else { 68 ASSERT_EQ(EOPNOTSUPP, errno); 69 } 70 ASSERT_NE(1, size); 71 72 free(ctx); 73 } 74 75 TEST(flags_zero_lsm_get_self_attr) 76 { 77 const long page_size = sysconf(_SC_PAGESIZE); 78 struct lsm_ctx *ctx = calloc(page_size, 1); 79 __u64 *syscall_lsms = calloc(page_size, 1); 80 __u32 size; 81 int lsmcount; 82 int i; 83 84 ASSERT_NE(NULL, ctx); 85 errno = 0; 86 size = page_size; 87 ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, &size, 88 LSM_FLAG_SINGLE)); 89 ASSERT_EQ(EINVAL, errno); 90 ASSERT_EQ(page_size, size); 91 92 lsmcount = syscall(__NR_lsm_list_modules, syscall_lsms, &size, 0); 93 ASSERT_LE(1, lsmcount); 94 ASSERT_NE(NULL, syscall_lsms); 95 96 for (i = 0; i < lsmcount; i++) { 97 errno = 0; 98 size = page_size; 99 ctx->id = syscall_lsms[i]; 100 101 if (syscall_lsms[i] == LSM_ID_SELINUX || 102 syscall_lsms[i] == LSM_ID_SMACK || 103 syscall_lsms[i] == LSM_ID_APPARMOR) { 104 ASSERT_EQ(1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, 105 &size, LSM_FLAG_SINGLE)); 106 } else { 107 ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, 108 &size, 109 LSM_FLAG_SINGLE)); 110 } 111 } 112 113 free(ctx); 114 } 115 116 TEST(flags_overset_lsm_get_self_attr) 117 { 118 const long page_size = sysconf(_SC_PAGESIZE); 119 struct lsm_ctx *ctx = calloc(page_size, 1); 120 __u32 size; 121 122 ASSERT_NE(NULL, ctx); 123 124 errno = 0; 125 size = page_size; 126 ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT | LSM_ATTR_PREV, ctx, 127 &size, 0)); 128 ASSERT_EQ(EOPNOTSUPP, errno); 129 130 errno = 0; 131 size = page_size; 132 ASSERT_EQ(-1, lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, &size, 133 LSM_FLAG_SINGLE | 134 (LSM_FLAG_SINGLE << 1))); 135 ASSERT_EQ(EINVAL, errno); 136 137 free(ctx); 138 } 139 140 TEST(basic_lsm_get_self_attr) 141 { 142 const long page_size = sysconf(_SC_PAGESIZE); 143 __u32 size = page_size; 144 struct lsm_ctx *ctx = calloc(page_size, 1); 145 struct lsm_ctx *tctx = NULL; 146 __u64 *syscall_lsms = calloc(page_size, 1); 147 char *attr = calloc(page_size, 1); 148 int cnt_current = 0; 149 int cnt_exec = 0; 150 int cnt_fscreate = 0; 151 int cnt_keycreate = 0; 152 int cnt_prev = 0; 153 int cnt_sockcreate = 0; 154 int lsmcount; 155 int count; 156 int i; 157 158 ASSERT_NE(NULL, ctx); 159 ASSERT_NE(NULL, syscall_lsms); 160 161 lsmcount = syscall(__NR_lsm_list_modules, syscall_lsms, &size, 0); 162 ASSERT_LE(1, lsmcount); 163 164 for (i = 0; i < lsmcount; i++) { 165 switch (syscall_lsms[i]) { 166 case LSM_ID_SELINUX: 167 cnt_current++; 168 cnt_exec++; 169 cnt_fscreate++; 170 cnt_keycreate++; 171 cnt_prev++; 172 cnt_sockcreate++; 173 break; 174 case LSM_ID_SMACK: 175 cnt_current++; 176 break; 177 case LSM_ID_APPARMOR: 178 cnt_current++; 179 cnt_exec++; 180 cnt_prev++; 181 break; 182 default: 183 break; 184 } 185 } 186 187 if (cnt_current) { 188 size = page_size; 189 count = lsm_get_self_attr(LSM_ATTR_CURRENT, ctx, &size, 0); 190 ASSERT_EQ(cnt_current, count); 191 tctx = ctx; 192 ASSERT_EQ(0, read_proc_attr("current", attr, page_size)); 193 ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); 194 for (i = 1; i < count; i++) { 195 tctx = next_ctx(tctx); 196 ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); 197 } 198 } 199 if (cnt_exec) { 200 size = page_size; 201 count = lsm_get_self_attr(LSM_ATTR_EXEC, ctx, &size, 0); 202 ASSERT_GE(cnt_exec, count); 203 if (count > 0) { 204 tctx = ctx; 205 if (read_proc_attr("exec", attr, page_size) == 0) 206 ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); 207 } 208 for (i = 1; i < count; i++) { 209 tctx = next_ctx(tctx); 210 ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); 211 } 212 } 213 if (cnt_fscreate) { 214 size = page_size; 215 count = lsm_get_self_attr(LSM_ATTR_FSCREATE, ctx, &size, 0); 216 ASSERT_GE(cnt_fscreate, count); 217 if (count > 0) { 218 tctx = ctx; 219 if (read_proc_attr("fscreate", attr, page_size) == 0) 220 ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); 221 } 222 for (i = 1; i < count; i++) { 223 tctx = next_ctx(tctx); 224 ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); 225 } 226 } 227 if (cnt_keycreate) { 228 size = page_size; 229 count = lsm_get_self_attr(LSM_ATTR_KEYCREATE, ctx, &size, 0); 230 ASSERT_GE(cnt_keycreate, count); 231 if (count > 0) { 232 tctx = ctx; 233 if (read_proc_attr("keycreate", attr, page_size) == 0) 234 ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); 235 } 236 for (i = 1; i < count; i++) { 237 tctx = next_ctx(tctx); 238 ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); 239 } 240 } 241 if (cnt_prev) { 242 size = page_size; 243 count = lsm_get_self_attr(LSM_ATTR_PREV, ctx, &size, 0); 244 ASSERT_GE(cnt_prev, count); 245 if (count > 0) { 246 tctx = ctx; 247 ASSERT_EQ(0, read_proc_attr("prev", attr, page_size)); 248 ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); 249 for (i = 1; i < count; i++) { 250 tctx = next_ctx(tctx); 251 ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); 252 } 253 } 254 } 255 if (cnt_sockcreate) { 256 size = page_size; 257 count = lsm_get_self_attr(LSM_ATTR_SOCKCREATE, ctx, &size, 0); 258 ASSERT_GE(cnt_sockcreate, count); 259 if (count > 0) { 260 tctx = ctx; 261 if (read_proc_attr("sockcreate", attr, page_size) == 0) 262 ASSERT_EQ(0, strcmp((char *)tctx->ctx, attr)); 263 } 264 for (i = 1; i < count; i++) { 265 tctx = next_ctx(tctx); 266 ASSERT_NE(0, strcmp((char *)tctx->ctx, attr)); 267 } 268 } 269 270 free(ctx); 271 free(attr); 272 free(syscall_lsms); 273 } 274 275 TEST_HARNESS_MAIN 276