xref: /linux/tools/testing/selftests/lsm/lsm_get_self_attr_test.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
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