• Home
  • History
  • Annotate
  • 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 "test.h"
47  #include <sched.h>
48  #include <stdarg.h>
49  #include <sys/mount.h>
50  #include <arpa/inet.h>
51  #include <net/if.h>
52  #include <linux/ip.h>
53  #include <err.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