aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/tomoyo/common.c')
-rw-r--r--security/tomoyo/common.c431
1 files changed, 259 insertions, 172 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index bdf1ed7ca45b..811adb5e9fea 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -9,53 +9,74 @@
9#include <linux/uaccess.h> 9#include <linux/uaccess.h>
10#include <linux/slab.h> 10#include <linux/slab.h>
11#include <linux/security.h> 11#include <linux/security.h>
12#include <linux/hardirq.h>
13#include "common.h" 12#include "common.h"
14 13
14static struct tomoyo_profile tomoyo_default_profile = {
15 .learning = &tomoyo_default_profile.preference,
16 .permissive = &tomoyo_default_profile.preference,
17 .enforcing = &tomoyo_default_profile.preference,
18 .preference.enforcing_verbose = true,
19 .preference.learning_max_entry = 2048,
20 .preference.learning_verbose = false,
21 .preference.permissive_verbose = true
22};
23
24/* Profile version. Currently only 20090903 is defined. */
25static unsigned int tomoyo_profile_version;
26
27/* Profile table. Memory is allocated as needed. */
28static struct tomoyo_profile *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES];
29
15/* String table for functionality that takes 4 modes. */ 30/* String table for functionality that takes 4 modes. */
16static const char *tomoyo_mode_4[4] = { 31static const char *tomoyo_mode_4[4] = {
17 "disabled", "learning", "permissive", "enforcing" 32 "disabled", "learning", "permissive", "enforcing"
18}; 33};
19/* String table for functionality that takes 2 modes. */
20static const char *tomoyo_mode_2[4] = {
21 "disabled", "enabled", "enabled", "enabled"
22};
23 34
24/* 35/* String table for /sys/kernel/security/tomoyo/profile */
25 * tomoyo_control_array is a static data which contains 36static const char *tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX
26 * 37 + TOMOYO_MAX_MAC_CATEGORY_INDEX] = {
27 * (1) functionality name used by /sys/kernel/security/tomoyo/profile . 38 [TOMOYO_MAC_FILE_EXECUTE] = "file::execute",
28 * (2) initial values for "struct tomoyo_profile". 39 [TOMOYO_MAC_FILE_OPEN] = "file::open",
29 * (3) max values for "struct tomoyo_profile". 40 [TOMOYO_MAC_FILE_CREATE] = "file::create",
30 */ 41 [TOMOYO_MAC_FILE_UNLINK] = "file::unlink",
31static struct { 42 [TOMOYO_MAC_FILE_MKDIR] = "file::mkdir",
32 const char *keyword; 43 [TOMOYO_MAC_FILE_RMDIR] = "file::rmdir",
33 unsigned int current_value; 44 [TOMOYO_MAC_FILE_MKFIFO] = "file::mkfifo",
34 const unsigned int max_value; 45 [TOMOYO_MAC_FILE_MKSOCK] = "file::mksock",
35} tomoyo_control_array[TOMOYO_MAX_CONTROL_INDEX] = { 46 [TOMOYO_MAC_FILE_TRUNCATE] = "file::truncate",
36 [TOMOYO_MAC_FOR_FILE] = { "MAC_FOR_FILE", 0, 3 }, 47 [TOMOYO_MAC_FILE_SYMLINK] = "file::symlink",
37 [TOMOYO_MAX_ACCEPT_ENTRY] = { "MAX_ACCEPT_ENTRY", 2048, INT_MAX }, 48 [TOMOYO_MAC_FILE_REWRITE] = "file::rewrite",
38 [TOMOYO_VERBOSE] = { "TOMOYO_VERBOSE", 1, 1 }, 49 [TOMOYO_MAC_FILE_MKBLOCK] = "file::mkblock",
50 [TOMOYO_MAC_FILE_MKCHAR] = "file::mkchar",
51 [TOMOYO_MAC_FILE_LINK] = "file::link",
52 [TOMOYO_MAC_FILE_RENAME] = "file::rename",
53 [TOMOYO_MAC_FILE_CHMOD] = "file::chmod",
54 [TOMOYO_MAC_FILE_CHOWN] = "file::chown",
55 [TOMOYO_MAC_FILE_CHGRP] = "file::chgrp",
56 [TOMOYO_MAC_FILE_IOCTL] = "file::ioctl",
57 [TOMOYO_MAC_FILE_CHROOT] = "file::chroot",
58 [TOMOYO_MAC_FILE_MOUNT] = "file::mount",
59 [TOMOYO_MAC_FILE_UMOUNT] = "file::umount",
60 [TOMOYO_MAC_FILE_PIVOT_ROOT] = "file::pivot_root",
61 [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file",
39}; 62};
40 63
41/*
42 * tomoyo_profile is a structure which is used for holding the mode of access
43 * controls. TOMOYO has 4 modes: disabled, learning, permissive, enforcing.
44 * An administrator can define up to 256 profiles.
45 * The ->profile of "struct tomoyo_domain_info" is used for remembering
46 * the profile's number (0 - 255) assigned to that domain.
47 */
48static struct tomoyo_profile {
49 unsigned int value[TOMOYO_MAX_CONTROL_INDEX];
50 const struct tomoyo_path_info *comment;
51} *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES];
52
53/* Permit policy management by non-root user? */ 64/* Permit policy management by non-root user? */
54static bool tomoyo_manage_by_non_root; 65static bool tomoyo_manage_by_non_root;
55 66
56/* Utility functions. */ 67/* Utility functions. */
57 68
58/** 69/**
70 * tomoyo_yesno - Return "yes" or "no".
71 *
72 * @value: Bool value.
73 */
74static const char *tomoyo_yesno(const unsigned int value)
75{
76 return value ? "yes" : "no";
77}
78
79/**
59 * tomoyo_print_name_union - Print a tomoyo_name_union. 80 * tomoyo_print_name_union - Print a tomoyo_name_union.
60 * 81 *
61 * @head: Pointer to "struct tomoyo_io_buffer". 82 * @head: Pointer to "struct tomoyo_io_buffer".
@@ -154,80 +175,62 @@ bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
154} 175}
155 176
156/** 177/**
157 * tomoyo_check_flags - Check mode for specified functionality.
158 *
159 * @domain: Pointer to "struct tomoyo_domain_info".
160 * @index: The functionality to check mode.
161 *
162 * TOMOYO checks only process context.
163 * This code disables TOMOYO's enforcement in case the function is called from
164 * interrupt context.
165 */
166unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
167 const u8 index)
168{
169 const u8 profile = domain->profile;
170
171 if (WARN_ON(in_interrupt()))
172 return 0;
173 return tomoyo_policy_loaded && index < TOMOYO_MAX_CONTROL_INDEX
174#if TOMOYO_MAX_PROFILES != 256
175 && profile < TOMOYO_MAX_PROFILES
176#endif
177 && tomoyo_profile_ptr[profile] ?
178 tomoyo_profile_ptr[profile]->value[index] : 0;
179}
180
181/**
182 * tomoyo_verbose_mode - Check whether TOMOYO is verbose mode.
183 *
184 * @domain: Pointer to "struct tomoyo_domain_info".
185 *
186 * Returns true if domain policy violation warning should be printed to
187 * console.
188 */
189bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain)
190{
191 return tomoyo_check_flags(domain, TOMOYO_VERBOSE) != 0;
192}
193
194/**
195 * tomoyo_find_or_assign_new_profile - Create a new profile. 178 * tomoyo_find_or_assign_new_profile - Create a new profile.
196 * 179 *
197 * @profile: Profile number to create. 180 * @profile: Profile number to create.
198 * 181 *
199 * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise. 182 * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise.
200 */ 183 */
201static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned 184static struct tomoyo_profile *tomoyo_find_or_assign_new_profile
202 int profile) 185(const unsigned int profile)
203{ 186{
204 struct tomoyo_profile *ptr = NULL; 187 struct tomoyo_profile *ptr;
205 int i; 188 struct tomoyo_profile *entry;
206
207 if (profile >= TOMOYO_MAX_PROFILES) 189 if (profile >= TOMOYO_MAX_PROFILES)
208 return NULL; 190 return NULL;
209 if (mutex_lock_interruptible(&tomoyo_policy_lock))
210 return NULL;
211 ptr = tomoyo_profile_ptr[profile]; 191 ptr = tomoyo_profile_ptr[profile];
212 if (ptr) 192 if (ptr)
213 goto ok; 193 return ptr;
214 ptr = kmalloc(sizeof(*ptr), GFP_NOFS); 194 entry = kzalloc(sizeof(*entry), GFP_NOFS);
215 if (!tomoyo_memory_ok(ptr)) { 195 if (mutex_lock_interruptible(&tomoyo_policy_lock))
216 kfree(ptr); 196 goto out;
217 ptr = NULL; 197 ptr = tomoyo_profile_ptr[profile];
218 goto ok; 198 if (!ptr && tomoyo_memory_ok(entry)) {
199 ptr = entry;
200 ptr->learning = &tomoyo_default_profile.preference;
201 ptr->permissive = &tomoyo_default_profile.preference;
202 ptr->enforcing = &tomoyo_default_profile.preference;
203 ptr->default_config = TOMOYO_CONFIG_DISABLED;
204 memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT,
205 sizeof(ptr->config));
206 mb(); /* Avoid out-of-order execution. */
207 tomoyo_profile_ptr[profile] = ptr;
208 entry = NULL;
219 } 209 }
220 for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++)
221 ptr->value[i] = tomoyo_control_array[i].current_value;
222 mb(); /* Avoid out-of-order execution. */
223 tomoyo_profile_ptr[profile] = ptr;
224 ok:
225 mutex_unlock(&tomoyo_policy_lock); 210 mutex_unlock(&tomoyo_policy_lock);
211 out:
212 kfree(entry);
226 return ptr; 213 return ptr;
227} 214}
228 215
229/** 216/**
230 * tomoyo_write_profile - Write to profile table. 217 * tomoyo_profile - Find a profile.
218 *
219 * @profile: Profile number to find.
220 *
221 * Returns pointer to "struct tomoyo_profile".
222 */
223struct tomoyo_profile *tomoyo_profile(const u8 profile)
224{
225 struct tomoyo_profile *ptr = tomoyo_profile_ptr[profile];
226 if (!tomoyo_policy_loaded)
227 return &tomoyo_default_profile;
228 BUG_ON(!ptr);
229 return ptr;
230}
231
232/**
233 * tomoyo_write_profile - Write profile table.
231 * 234 *
232 * @head: Pointer to "struct tomoyo_io_buffer". 235 * @head: Pointer to "struct tomoyo_io_buffer".
233 * 236 *
@@ -237,64 +240,116 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
237{ 240{
238 char *data = head->write_buf; 241 char *data = head->write_buf;
239 unsigned int i; 242 unsigned int i;
240 unsigned int value; 243 int value;
244 int mode;
245 u8 config;
246 bool use_default = false;
241 char *cp; 247 char *cp;
242 struct tomoyo_profile *profile; 248 struct tomoyo_profile *profile;
243 unsigned long num; 249 if (sscanf(data, "PROFILE_VERSION=%u", &tomoyo_profile_version) == 1)
244 250 return 0;
245 cp = strchr(data, '-'); 251 i = simple_strtoul(data, &cp, 10);
246 if (cp) 252 if (data == cp) {
247 *cp = '\0'; 253 profile = &tomoyo_default_profile;
248 if (strict_strtoul(data, 10, &num)) 254 } else {
249 return -EINVAL; 255 if (*cp != '-')
250 if (cp) 256 return -EINVAL;
251 data = cp + 1; 257 data = cp + 1;
252 profile = tomoyo_find_or_assign_new_profile(num); 258 profile = tomoyo_find_or_assign_new_profile(i);
253 if (!profile) 259 if (!profile)
254 return -EINVAL; 260 return -EINVAL;
261 }
255 cp = strchr(data, '='); 262 cp = strchr(data, '=');
256 if (!cp) 263 if (!cp)
257 return -EINVAL; 264 return -EINVAL;
258 *cp = '\0'; 265 *cp++ = '\0';
266 if (profile != &tomoyo_default_profile)
267 use_default = strstr(cp, "use_default") != NULL;
268 if (strstr(cp, "verbose=yes"))
269 value = 1;
270 else if (strstr(cp, "verbose=no"))
271 value = 0;
272 else
273 value = -1;
274 if (!strcmp(data, "PREFERENCE::enforcing")) {
275 if (use_default) {
276 profile->enforcing = &tomoyo_default_profile.preference;
277 return 0;
278 }
279 profile->enforcing = &profile->preference;
280 if (value >= 0)
281 profile->preference.enforcing_verbose = value;
282 return 0;
283 }
284 if (!strcmp(data, "PREFERENCE::permissive")) {
285 if (use_default) {
286 profile->permissive = &tomoyo_default_profile.preference;
287 return 0;
288 }
289 profile->permissive = &profile->preference;
290 if (value >= 0)
291 profile->preference.permissive_verbose = value;
292 return 0;
293 }
294 if (!strcmp(data, "PREFERENCE::learning")) {
295 char *cp2;
296 if (use_default) {
297 profile->learning = &tomoyo_default_profile.preference;
298 return 0;
299 }
300 profile->learning = &profile->preference;
301 if (value >= 0)
302 profile->preference.learning_verbose = value;
303 cp2 = strstr(cp, "max_entry=");
304 if (cp2)
305 sscanf(cp2 + 10, "%u",
306 &profile->preference.learning_max_entry);
307 return 0;
308 }
309 if (profile == &tomoyo_default_profile)
310 return -EINVAL;
259 if (!strcmp(data, "COMMENT")) { 311 if (!strcmp(data, "COMMENT")) {
260 const struct tomoyo_path_info *old_comment = profile->comment; 312 const struct tomoyo_path_info *old_comment = profile->comment;
261 profile->comment = tomoyo_get_name(cp + 1); 313 profile->comment = tomoyo_get_name(cp);
262 tomoyo_put_name(old_comment); 314 tomoyo_put_name(old_comment);
263 return 0; 315 return 0;
264 } 316 }
265 for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) { 317 if (!strcmp(data, "CONFIG")) {
266 if (strcmp(data, tomoyo_control_array[i].keyword)) 318 i = TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX;
267 continue; 319 config = profile->default_config;
268 if (sscanf(cp + 1, "%u", &value) != 1) { 320 } else if (tomoyo_str_starts(&data, "CONFIG::")) {
269 int j; 321 config = 0;
270 const char **modes; 322 for (i = 0; i < TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX; i++) {
271 switch (i) { 323 if (strcmp(data, tomoyo_mac_keywords[i]))
272 case TOMOYO_VERBOSE: 324 continue;
273 modes = tomoyo_mode_2; 325 config = profile->config[i];
274 break; 326 break;
275 default:
276 modes = tomoyo_mode_4;
277 break;
278 }
279 for (j = 0; j < 4; j++) {
280 if (strcmp(cp + 1, modes[j]))
281 continue;
282 value = j;
283 break;
284 }
285 if (j == 4)
286 return -EINVAL;
287 } else if (value > tomoyo_control_array[i].max_value) {
288 value = tomoyo_control_array[i].max_value;
289 } 327 }
290 profile->value[i] = value; 328 if (i == TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX)
291 return 0; 329 return -EINVAL;
330 } else {
331 return -EINVAL;
292 } 332 }
293 return -EINVAL; 333 if (use_default) {
334 config = TOMOYO_CONFIG_USE_DEFAULT;
335 } else {
336 for (mode = 3; mode >= 0; mode--)
337 if (strstr(cp, tomoyo_mode_4[mode]))
338 /*
339 * Update lower 3 bits in order to distinguish
340 * 'config' from 'TOMOYO_CONFIG_USE_DEAFULT'.
341 */
342 config = (config & ~7) | mode;
343 }
344 if (i < TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX)
345 profile->config[i] = config;
346 else if (config != TOMOYO_CONFIG_USE_DEFAULT)
347 profile->default_config = config;
348 return 0;
294} 349}
295 350
296/** 351/**
297 * tomoyo_read_profile - Read from profile table. 352 * tomoyo_read_profile - Read profile table.
298 * 353 *
299 * @head: Pointer to "struct tomoyo_io_buffer". 354 * @head: Pointer to "struct tomoyo_io_buffer".
300 * 355 *
@@ -302,53 +357,82 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
302 */ 357 */
303static int tomoyo_read_profile(struct tomoyo_io_buffer *head) 358static int tomoyo_read_profile(struct tomoyo_io_buffer *head)
304{ 359{
305 static const int total = TOMOYO_MAX_CONTROL_INDEX + 1; 360 int index;
306 int step;
307
308 if (head->read_eof) 361 if (head->read_eof)
309 return 0; 362 return 0;
310 for (step = head->read_step; step < TOMOYO_MAX_PROFILES * total; 363 if (head->read_bit)
311 step++) { 364 goto body;
312 const u8 index = step / total; 365 tomoyo_io_printf(head, "PROFILE_VERSION=%s\n", "20090903");
313 u8 type = step % total; 366 tomoyo_io_printf(head, "PREFERENCE::learning={ verbose=%s "
367 "max_entry=%u }\n",
368 tomoyo_yesno(tomoyo_default_profile.preference.
369 learning_verbose),
370 tomoyo_default_profile.preference.learning_max_entry);
371 tomoyo_io_printf(head, "PREFERENCE::permissive={ verbose=%s }\n",
372 tomoyo_yesno(tomoyo_default_profile.preference.
373 permissive_verbose));
374 tomoyo_io_printf(head, "PREFERENCE::enforcing={ verbose=%s }\n",
375 tomoyo_yesno(tomoyo_default_profile.preference.
376 enforcing_verbose));
377 head->read_bit = 1;
378 body:
379 for (index = head->read_step; index < TOMOYO_MAX_PROFILES; index++) {
380 bool done;
381 u8 config;
382 int i;
383 int pos;
314 const struct tomoyo_profile *profile 384 const struct tomoyo_profile *profile
315 = tomoyo_profile_ptr[index]; 385 = tomoyo_profile_ptr[index];
316 head->read_step = step; 386 const struct tomoyo_path_info *comment;
387 head->read_step = index;
317 if (!profile) 388 if (!profile)
318 continue; 389 continue;
319 if (!type) { /* Print profile' comment tag. */ 390 pos = head->read_avail;
320 if (!tomoyo_io_printf(head, "%u-COMMENT=%s\n", 391 comment = profile->comment;
321 index, profile->comment ? 392 done = tomoyo_io_printf(head, "%u-COMMENT=%s\n", index,
322 profile->comment->name : "")) 393 comment ? comment->name : "");
323 break; 394 if (!done)
324 continue; 395 goto out;
325 } 396 config = profile->default_config;
326 type--; 397 if (!tomoyo_io_printf(head, "%u-CONFIG={ mode=%s }\n", index,
327 if (type < TOMOYO_MAX_CONTROL_INDEX) { 398 tomoyo_mode_4[config & 3]))
328 const unsigned int value = profile->value[type]; 399 goto out;
329 const char **modes = NULL; 400 for (i = 0; i < TOMOYO_MAX_MAC_INDEX +
330 const char *keyword 401 TOMOYO_MAX_MAC_CATEGORY_INDEX; i++) {
331 = tomoyo_control_array[type].keyword; 402 config = profile->config[i];
332 switch (tomoyo_control_array[type].max_value) { 403 if (config == TOMOYO_CONFIG_USE_DEFAULT)
333 case 3: 404 continue;
334 modes = tomoyo_mode_4; 405 if (!tomoyo_io_printf(head,
335 break; 406 "%u-CONFIG::%s={ mode=%s }\n",
336 case 1: 407 index, tomoyo_mac_keywords[i],
337 modes = tomoyo_mode_2; 408 tomoyo_mode_4[config & 3]))
338 break; 409 goto out;
339 }
340 if (modes) {
341 if (!tomoyo_io_printf(head, "%u-%s=%s\n", index,
342 keyword, modes[value]))
343 break;
344 } else {
345 if (!tomoyo_io_printf(head, "%u-%s=%u\n", index,
346 keyword, value))
347 break;
348 }
349 } 410 }
411 if (profile->learning != &tomoyo_default_profile.preference &&
412 !tomoyo_io_printf(head, "%u-PREFERENCE::learning={ "
413 "verbose=%s max_entry=%u }\n", index,
414 tomoyo_yesno(profile->preference.
415 learning_verbose),
416 profile->preference.learning_max_entry))
417 goto out;
418 if (profile->permissive != &tomoyo_default_profile.preference
419 && !tomoyo_io_printf(head, "%u-PREFERENCE::permissive={ "
420 "verbose=%s }\n", index,
421 tomoyo_yesno(profile->preference.
422 permissive_verbose)))
423 goto out;
424 if (profile->enforcing != &tomoyo_default_profile.preference &&
425 !tomoyo_io_printf(head, "%u-PREFERENCE::enforcing={ "
426 "verbose=%s }\n", index,
427 tomoyo_yesno(profile->preference.
428 enforcing_verbose)))
429 goto out;
430 continue;
431 out:
432 head->read_avail = pos;
433 break;
350 } 434 }
351 if (step == TOMOYO_MAX_PROFILES * total) 435 if (index == TOMOYO_MAX_PROFILES)
352 head->read_eof = true; 436 head->read_eof = true;
353 return 0; 437 return 0;
354} 438}
@@ -1595,7 +1679,7 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head)
1595static int tomoyo_read_version(struct tomoyo_io_buffer *head) 1679static int tomoyo_read_version(struct tomoyo_io_buffer *head)
1596{ 1680{
1597 if (!head->read_eof) { 1681 if (!head->read_eof) {
1598 tomoyo_io_printf(head, "2.2.0"); 1682 tomoyo_io_printf(head, "2.3.0-pre");
1599 head->read_eof = true; 1683 head->read_eof = true;
1600 } 1684 }
1601 return 0; 1685 return 0;
@@ -1915,6 +1999,9 @@ void tomoyo_check_profile(void)
1915 profile, domain->domainname->name); 1999 profile, domain->domainname->name);
1916 } 2000 }
1917 tomoyo_read_unlock(idx); 2001 tomoyo_read_unlock(idx);
1918 printk(KERN_INFO "TOMOYO: 2.2.0 2009/04/01\n"); 2002 if (tomoyo_profile_version != 20090903)
2003 panic("Profile version %u is not supported.\n",
2004 tomoyo_profile_version);
2005 printk(KERN_INFO "TOMOYO: 2.3.0-pre 2010/06/03\n");
1919 printk(KERN_INFO "Mandatory Access Control activated.\n"); 2006 printk(KERN_INFO "Mandatory Access Control activated.\n");
1920} 2007}