1 /******************************************************************************/ 2 /* */ 3 /* Copyright (c) Tetsuo Handa <penguin-kernel (at) 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 60 static inline int uselib(const char *library) 61 { 62 return syscall(__NR_uselib, library); 63 } 64 #else 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 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 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. */ 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 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 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 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 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 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 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 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