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
next_ctx(struct lsm_ctx * ctxp)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
TEST(size_null_lsm_get_self_attr)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
TEST(ctx_null_lsm_get_self_attr)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
TEST(size_too_small_lsm_get_self_attr)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
TEST(flags_zero_lsm_get_self_attr)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
TEST(flags_overset_lsm_get_self_attr)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
TEST(basic_lsm_get_self_attr)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