• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************/
2 /*                                                                            */
3 /* Copyright (c) Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>, 2009      */
4 /*                                                                            */
5 /* This program is free software;  you can redistribute it and/or modify      */
6 /* it under the terms of the GNU General Public License as published by       */
7 /* the Free Software Foundation; either version 2 of the License, or          */
8 /* (at your option) any later version.                                        */
9 /*                                                                            */
10 /* This program is distributed in the hope that it will be useful,            */
11 /* but WITHOUT ANY WARRANTY;  without even the implied warranty of            */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See                  */
13 /* the GNU General Public License for more details.                           */
14 /*                                                                            */
15 /* You should have received a copy of the GNU General Public License          */
16 /* along with this program;  if not, write to the Free Software               */
17 /* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA    */
18 /*                                                                            */
19 /******************************************************************************/
20 /*
21  * include.h
22  *
23  * Common functions for testing TOMOYO Linux's kernel.
24  *
25  * Copyright (C) 2005-2010  NTT DATA CORPORATION
26  */
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <linux/kdev_t.h>
30 #include <linux/unistd.h>
31 #include <pty.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sys/socket.h>
36 #include <sys/stat.h>
37 #include <sys/syscall.h>
38 #include <sys/time.h>
39 #include <sys/timex.h>
40 #include <sys/types.h>
41 #include <sys/un.h>
42 #include <sys/wait.h>
43 #include <time.h>
44 #include <unistd.h>
45 #include <utime.h>
46 #include <sched.h>
47 #include <stdarg.h>
48 #include <sys/mount.h>
49 #include <arpa/inet.h>
50 #include <net/if.h>
51 #include <linux/ip.h>
52 #include <err.h>
53 #include "test.h"
54 
55 /*
56  * Some architectures like mips n32 don't have __NR_uselib defined in the
57  * system headers.
58  */
59 #ifdef __NR_uselib
uselib(const char * library)60 static inline int uselib(const char *library)
61 {
62 	return syscall(__NR_uselib, library);
63 }
64 #else
uselib(const char * library)65 static inline int uselib(const char *library)
66 {
67 	errno = ENOSYS;
68 	return -1;
69 }
70 #endif
71 
72 /* Is there an architecture without __NR_pivot_root defined? */
73 #ifdef __NR_pivot_root
pivot_root(const char * new_root,const char * put_old)74 static inline int pivot_root(const char *new_root, const char *put_old)
75 {
76 	return syscall(__NR_pivot_root, new_root, put_old);
77 }
78 #else
pivot_root(const char * new_root,const char * put_old)79 static inline int pivot_root(const char *new_root, const char *put_old)
80 {
81 	errno = ENOSYS;
82 	return -1;
83 }
84 #endif
85 
86 /* The sysctl() wrapper is dead and newer arches omit it now. */
write_sysctl(const char * path,const char * value)87 static inline int write_sysctl(const char *path, const char *value)
88 {
89 	FILE *fp = fopen(path, "w");
90 	if (!fp)
91 		return 1;
92 	fputs(value, fp);
93 	fclose(fp);
94 	return 0;
95 }
96 
read_sysctl(const char * path,char * value,int len)97 static inline int read_sysctl(const char *path, char *value, int len)
98 {
99 	char scratch[100];
100 	FILE *fp = fopen(path, "r");
101 	if (!fp)
102 		return 1;
103 	if (!value) {
104 		value = scratch;
105 		len = sizeof(scratch);
106 	}
107 	if (fgets(value, len, fp))
108 		/* ignore */;
109 	fclose(fp);
110 	return 0;
111 }
112 
113 /* Should be a fairly benign path to bang on. */
114 #define TEST_SYSCTL_PATH "/proc/sys/net/ipv4/ip_local_port_range"
115 
116 #define proc_policy_dir              "/sys/kernel/security/tomoyo/"
117 #define proc_policy_domain_policy    "/sys/kernel/security/tomoyo/domain_policy"
118 #define proc_policy_exception_policy "/sys/kernel/security/tomoyo/exception_policy"
119 #define proc_policy_profile          "/sys/kernel/security/tomoyo/profile"
120 #define proc_policy_manager          "/sys/kernel/security/tomoyo/manager"
121 #define proc_policy_query            "/sys/kernel/security/tomoyo/query"
122 #define proc_policy_grant_log        "/sys/kernel/security/tomoyo/grant_log"
123 #define proc_policy_reject_log       "/sys/kernel/security/tomoyo/reject_log"
124 #define proc_policy_domain_status    "/sys/kernel/security/tomoyo/.domain_status"
125 #define proc_policy_process_status   "/sys/kernel/security/tomoyo/.process_status"
126 #define proc_policy_self_domain      "/sys/kernel/security/tomoyo/self_domain"
127 
128 static FILE *profile_fp = NULL;
129 static FILE *domain_fp = NULL;
130 static FILE *exception_fp = NULL;
131 static char self_domain[4096] = "";
132 static pid_t pid = 0;
133 
clear_status(void)134 static void clear_status(void)
135 {
136 	static const char *keywords[] = {
137 		"file::execute",
138 		"file::open",
139 		"file::create",
140 		"file::unlink",
141 		"file::mkdir",
142 		"file::rmdir",
143 		"file::mkfifo",
144 		"file::mksock",
145 		"file::truncate",
146 		"file::symlink",
147 		"file::rewrite",
148 		"file::mkblock",
149 		"file::mkchar",
150 		"file::link",
151 		"file::rename",
152 		"file::chmod",
153 		"file::chown",
154 		"file::chgrp",
155 		"file::ioctl",
156 		"file::chroot",
157 		"file::mount",
158 		"file::umount",
159 		"file::pivot_root",
160 		NULL
161 	};
162 	int i;
163 	FILE *fp = fopen(proc_policy_profile, "r");
164 	static char buffer[4096];
165 	if (!fp) {
166 		fprintf(stderr, "Can't open %s\n", proc_policy_profile);
167 		exit(1);
168 	}
169 	for (i = 0; keywords[i]; i++)
170 		fprintf(profile_fp,
171 			"255-CONFIG::%s={ mode=disabled }\n",
172 			keywords[i]);
173 	while (memset(buffer, 0, sizeof(buffer)),
174 	       fgets(buffer, sizeof(buffer) - 10, fp)) {
175 		const char *mode;
176 		char *cp = strchr(buffer, '=');
177 		if (!cp)
178 			continue;
179 		*cp = '\0';
180 		mode = cp + 1;
181 		cp = strchr(buffer, '-');
182 		if (!cp)
183 			continue;
184 		*cp++ = '\0';
185 		if (strcmp(buffer, "0"))
186 			continue;
187 		fprintf(profile_fp, "255-%s", cp);
188 		if (!strcmp(cp, "COMMENT"))
189 			mode = "Profile for kernel test\n";
190 		else
191 			mode = "{ mode=disabled verbose=no }\n";
192 		fprintf(profile_fp, "255-%s=%s", cp, mode);
193 	}
194 	fprintf(profile_fp, "255-PREFERENCE::learning= verbose=no\n");
195 	fprintf(profile_fp, "255-PREFERENCE::enforcing= verbose=no\n");
196 	fprintf(profile_fp, "255-PREFERENCE::permissive= verbose=no\n");
197 	fprintf(profile_fp, "255-PREFERENCE::disabled= verbose=no\n");
198 	fprintf(profile_fp, "255-PREFERENCE::learning= max_entry=2048\n");
199 	fflush(profile_fp);
200 	fclose(fp);
201 }
202 
tomoyo_test_init(void)203 static void tomoyo_test_init(void)
204 {
205 	pid = getpid();
206 	if (access(proc_policy_dir, F_OK)) {
207 		fprintf(stderr, "You can't use this program for this kernel."
208 			"\n");
209 		exit(1);
210 	}
211 	profile_fp = fopen(proc_policy_profile, "w");
212 	if (!profile_fp) {
213 		fprintf(stderr, "Can't open %s .\n", proc_policy_profile);
214 		exit(1);
215 	}
216 	setlinebuf(profile_fp);
217 	domain_fp = fopen(proc_policy_domain_policy, "w");
218 	if (!domain_fp) {
219 		fprintf(stderr, "Can't open %s .\n",
220 			proc_policy_domain_policy);
221 		exit(1);
222 	}
223 	setlinebuf(domain_fp);
224 	exception_fp = fopen(proc_policy_exception_policy, "w");
225 	if (!exception_fp) {
226 		fprintf(stderr, "Can't open %s .\n",
227 			proc_policy_exception_policy);
228 		exit(1);
229 	}
230 	setlinebuf(exception_fp);
231 	if (fputc('\n', profile_fp) != '\n' || fflush(profile_fp)) {
232 		fprintf(stderr, "You need to register this program to %s to "
233 			"run this program.\n", proc_policy_manager);
234 		exit(1);
235 	}
236 	clear_status();
237 	{
238 		FILE *fp = fopen(proc_policy_self_domain, "r");
239 		memset(self_domain, 0, sizeof(self_domain));
240 		if (!fp || !fgets(self_domain, sizeof(self_domain) - 1, fp) ||
241 		    fclose(fp)) {
242 			fprintf(stderr, "Can't open %s .\n",
243 				proc_policy_self_domain);
244 			exit(1);
245 		}
246 	}
247 	fprintf(domain_fp, "select pid=%u\n", pid);
248 	fprintf(domain_fp, "use_profile 255\n");
249 	fprintf(domain_fp, "allow_read/write /sys/kernel/security/tomoyo/domain_policy\n");
250 	fprintf(domain_fp, "allow_truncate /sys/kernel/security/tomoyo/domain_policy\n");
251 	fprintf(domain_fp, "allow_read/write /sys/kernel/security/tomoyo/exception_policy\n");
252 	fprintf(domain_fp, "allow_truncate /sys/kernel/security/tomoyo/exception_policy\n");
253 	fprintf(domain_fp, "allow_read/write /sys/kernel/security/tomoyo/profile\n");
254 	fprintf(domain_fp, "allow_truncate /sys/kernel/security/tomoyo/profile\n");
255 }
256 
257 static void BUG(const char *fmt, ...)
258 	__attribute__ ((format(printf, 1, 2)));
259 
BUG(const char * fmt,...)260 static void BUG(const char *fmt, ...)
261 {
262 	va_list args;
263 	printf("BUG: ");
264 	va_start(args, fmt);
265 	vprintf(fmt, args);
266 	va_end(args);
267 	putchar('\n');
268 	fflush(stdout);
269 	while (1)
270 		sleep(100);
271 }
272 
write_domain_policy(const char * policy,int is_delete)273 int write_domain_policy(const char *policy, int is_delete)
274 {
275 	FILE *fp = fopen(proc_policy_domain_policy, "r");
276 	char buffer[8192];
277 	int domain_found = 0;
278 	int policy_found = 0;
279 	memset(buffer, 0, sizeof(buffer));
280 	if (!fp) {
281 		BUG("Can't read %s", proc_policy_domain_policy);
282 		return 0;
283 	}
284 	if (is_delete)
285 		fprintf(domain_fp, "delete ");
286 	fprintf(domain_fp, "%s\n", policy);
287 	while (fgets(buffer, sizeof(buffer) - 1, fp)) {
288 		char *cp = strchr(buffer, '\n');
289 		if (cp)
290 			*cp = '\0';
291 		if (!strncmp(buffer, "<kernel>", 8))
292 			domain_found = !strcmp(self_domain, buffer);
293 		if (!domain_found)
294 			continue;
295 		/* printf("<%s>\n", buffer); */
296 		if (strcmp(buffer, policy))
297 			continue;
298 		policy_found = 1;
299 		break;
300 	}
301 	fclose(fp);
302 	if (policy_found == is_delete) {
303 		BUG("Can't %s %s", is_delete ? "delete" : "append",
304 		    policy);
305 		return 0;
306 	}
307 	errno = 0;
308 	return 1;
309 
310 }
311 
write_exception_policy(const char * policy,int is_delete)312 int write_exception_policy(const char *policy, int is_delete)
313 {
314 	FILE *fp = fopen(proc_policy_exception_policy, "r");
315 	char buffer[8192];
316 	int policy_found = 0;
317 	memset(buffer, 0, sizeof(buffer));
318 	if (!fp) {
319 		BUG("Can't read %s", proc_policy_exception_policy);
320 		return 0;
321 	}
322 	if (is_delete)
323 		fprintf(exception_fp, "delete ");
324 	fprintf(exception_fp, "%s\n", policy);
325 	while (fgets(buffer, sizeof(buffer) - 1, fp)) {
326 		char *cp = strchr(buffer, '\n');
327 		if (cp)
328 			*cp = '\0';
329 		if (strcmp(buffer, policy))
330 			continue;
331 		policy_found = 1;
332 		break;
333 	}
334 	fclose(fp);
335 	if (policy_found == is_delete) {
336 		BUG("Can't %s %s", is_delete ? "delete" : "append",
337 		    policy);
338 		return 0;
339 	}
340 	errno = 0;
341 	return 1;
342 
343 }
344 
set_profile(const int mode,const char * name)345 int set_profile(const int mode, const char *name)
346 {
347 	static const char *modes[4] = { "disabled", "learning", "permissive",
348 					"enforcing" };
349 	FILE *fp = fopen(proc_policy_profile, "r");
350 	char buffer[8192];
351 	int policy_found = 0;
352 	const int len = strlen(name);
353 	if (!fp) {
354 		BUG("Can't read %s", proc_policy_profile);
355 		return 0;
356 	}
357 	fprintf(profile_fp, "255-CONFIG::%s=%s\n", name, modes[mode]);
358 	while (memset(buffer, 0, sizeof(buffer)),
359 	       fgets(buffer, sizeof(buffer) - 1, fp)) {
360 		char *cp = strchr(buffer, '\n');
361 		if (cp)
362 			*cp = '\0';
363 		if (strncmp(buffer, "255-CONFIG::", 12) ||
364 		    strncmp(buffer + 12, name, len) ||
365 		    buffer[12 + len] != '=')
366 			continue;
367 		if (strstr(buffer + 13 + len, modes[mode]))
368 			policy_found = 1;
369 		break;
370 	}
371 	fclose(fp);
372 	if (!policy_found) {
373 		BUG("Can't change profile to 255-CONFIG::%s=%s",
374 		    name, modes[mode]);
375 		return 0;
376 	}
377 	errno = 0;
378 	return 1;
379 }
380