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
19static 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
27TEST(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
40TEST(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
56TEST(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
75TEST(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
116TEST(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
140TEST(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
275TEST_HARNESS_MAIN
276