3 |
* |
* |
4 |
* Copyright (C) 2005-2010 NTT DATA CORPORATION |
* Copyright (C) 2005-2010 NTT DATA CORPORATION |
5 |
* |
* |
6 |
* Version: 1.8.0-pre 2010/10/22 |
* Version: 1.8.0-rc 2010/11/09 |
7 |
|
*/ |
8 |
|
|
9 |
|
#include "internal.h" |
10 |
|
|
11 |
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) |
12 |
|
|
13 |
|
/** |
14 |
|
* __wait_event_interruptible_timeout - Sleep until a condition gets true or a timeout elapses. |
15 |
* |
* |
16 |
* This file is applicable to both 2.4.30 and 2.6.11 and later. |
* @wq: The waitqueue to wait on. |
17 |
* See README.ccs for ChangeLog. |
* @condition: A C expression for the event to wait for. |
18 |
|
* @ret: Timeout, in jiffies. |
19 |
|
* |
20 |
|
* Returns 0 if the @timeout elapsed, -ERESTARTSYS if it was interrupted by a |
21 |
|
* signal, and the remaining jiffies otherwise if the condition evaluated to |
22 |
|
* true before the timeout elapsed. |
23 |
|
* |
24 |
|
* This is for compatibility with older kernels. |
25 |
|
*/ |
26 |
|
#define __wait_event_interruptible_timeout(wq, condition, ret) \ |
27 |
|
do { \ |
28 |
|
wait_queue_t __wait; \ |
29 |
|
init_waitqueue_entry(&__wait, current); \ |
30 |
|
\ |
31 |
|
add_wait_queue(&wq, &__wait); \ |
32 |
|
for (;;) { \ |
33 |
|
set_current_state(TASK_INTERRUPTIBLE); \ |
34 |
|
if (condition) \ |
35 |
|
break; \ |
36 |
|
if (!signal_pending(current)) { \ |
37 |
|
ret = schedule_timeout(ret); \ |
38 |
|
if (!ret) \ |
39 |
|
break; \ |
40 |
|
continue; \ |
41 |
|
} \ |
42 |
|
ret = -ERESTARTSYS; \ |
43 |
|
break; \ |
44 |
|
} \ |
45 |
|
current->state = TASK_RUNNING; \ |
46 |
|
remove_wait_queue(&wq, &__wait); \ |
47 |
|
} while (0) |
48 |
|
|
49 |
|
/** |
50 |
|
* wait_event_interruptible_timeout - Sleep until a condition gets true or a timeout elapses. |
51 |
|
* |
52 |
|
* @wq: The waitqueue to wait on. |
53 |
|
* @condition: A C expression for the event to wait for. |
54 |
|
* @timeout: Timeout, in jiffies. |
55 |
|
* |
56 |
|
* Returns 0 if the @timeout elapsed, -ERESTARTSYS if it was interrupted by a |
57 |
|
* signal, and the remaining jiffies otherwise if the condition evaluated to |
58 |
|
* true before the timeout elapsed. |
59 |
|
* |
60 |
|
* This is for compatibility with older kernels. |
61 |
|
*/ |
62 |
|
#define wait_event_interruptible_timeout(wq, condition, timeout) \ |
63 |
|
({ \ |
64 |
|
long __ret = timeout; \ |
65 |
|
if (!(condition)) \ |
66 |
|
__wait_event_interruptible_timeout(wq, condition, __ret); \ |
67 |
|
__ret; \ |
68 |
|
}) |
69 |
|
|
70 |
|
#endif |
71 |
|
|
72 |
|
/** |
73 |
|
* list_for_each_cookie - iterate over a list with cookie. |
74 |
* |
* |
75 |
|
* @pos: Pointer to "struct list_head". |
76 |
|
* @head: Pointer to "struct list_head". |
77 |
*/ |
*/ |
78 |
|
#define list_for_each_cookie(pos, head) \ |
79 |
|
for (pos = pos ? pos : srcu_dereference((head)->next, &ccs_ss); \ |
80 |
|
pos != (head); pos = srcu_dereference(pos->next, &ccs_ss)) |
81 |
|
|
|
#include "internal.h" |
|
82 |
|
|
83 |
/* Profile version. Currently only 20100903 is defined. */ |
/* Profile version. Currently only 20100903 is defined. */ |
84 |
static unsigned int ccs_profile_version; |
static unsigned int ccs_profile_version; |
283 |
__attribute__ ((format(printf, 3, 4))); |
__attribute__ ((format(printf, 3, 4))); |
284 |
|
|
285 |
/** |
/** |
286 |
* ccs_addprintf - snprint()-like-strncat(). |
* ccs_addprintf - strncat()-like-snprintf(). |
287 |
* |
* |
288 |
* @buffer: Buffer to write to. Must be '\0'-terminated. |
* @buffer: Buffer to write to. Must be '\0'-terminated. |
289 |
* @len: Size of @buffer. |
* @len: Size of @buffer. |
349 |
* @head: Pointer to "struct ccs_io_buffer". |
* @head: Pointer to "struct ccs_io_buffer". |
350 |
* @string: String to print. |
* @string: String to print. |
351 |
* |
* |
352 |
|
* Returns nothing. |
353 |
|
* |
354 |
* Note that @string has to be kept valid until @head is kfree()d. |
* Note that @string has to be kept valid until @head is kfree()d. |
355 |
* This means that char[] allocated on stack memory cannot be passed to |
* This means that char[] allocated on stack memory cannot be passed to |
356 |
* this function. Use ccs_io_printf() for char[] allocated on stack memory. |
* this function. Use ccs_io_printf() for char[] allocated on stack memory. |
|
* |
|
|
* Returns nothing. |
|
357 |
*/ |
*/ |
358 |
static void ccs_set_string(struct ccs_io_buffer *head, const char *string) |
static void ccs_set_string(struct ccs_io_buffer *head, const char *string) |
359 |
{ |
{ |
488 |
panic("Profile version %u is not supported.\n", |
panic("Profile version %u is not supported.\n", |
489 |
ccs_profile_version); |
ccs_profile_version); |
490 |
} |
} |
491 |
printk(KERN_INFO "CCSecurity: 1.8.0-pre 2010/10/22\n"); |
printk(KERN_INFO "CCSecurity: 1.8.0-rc 2010/11/09\n"); |
492 |
printk(KERN_INFO "Mandatory Access Control activated.\n"); |
printk(KERN_INFO "Mandatory Access Control activated.\n"); |
493 |
} |
} |
494 |
|
|
686 |
* ccs_read_profile - Read profile table. |
* ccs_read_profile - Read profile table. |
687 |
* |
* |
688 |
* @head: Pointer to "struct ccs_io_buffer". |
* @head: Pointer to "struct ccs_io_buffer". |
689 |
|
* |
690 |
|
* Returns nothing. |
691 |
*/ |
*/ |
692 |
static void ccs_read_profile(struct ccs_io_buffer *head) |
static void ccs_read_profile(struct ccs_io_buffer *head) |
693 |
{ |
{ |
770 |
* @a: Pointer to "struct ccs_acl_head". |
* @a: Pointer to "struct ccs_acl_head". |
771 |
* @b: Pointer to "struct ccs_acl_head". |
* @b: Pointer to "struct ccs_acl_head". |
772 |
* |
* |
773 |
* Returns true if @a and @b are duplicated, false otherwise. |
* Returns true if @a == @b, false otherwise. |
774 |
*/ |
*/ |
775 |
static bool ccs_same_manager(const struct ccs_acl_head *a, |
static bool ccs_same_manager(const struct ccs_acl_head *a, |
776 |
const struct ccs_acl_head *b) |
const struct ccs_acl_head *b) |
832 |
* |
* |
833 |
* @head: Pointer to "struct ccs_io_buffer". |
* @head: Pointer to "struct ccs_io_buffer". |
834 |
* |
* |
835 |
|
* Returns nothing. |
836 |
|
* |
837 |
* Caller holds ccs_read_lock(). |
* Caller holds ccs_read_lock(). |
838 |
*/ |
*/ |
839 |
static void ccs_read_manager(struct ccs_io_buffer *head) |
static void ccs_read_manager(struct ccs_io_buffer *head) |
967 |
* @a: Pointer to "struct ccs_acl_info". |
* @a: Pointer to "struct ccs_acl_info". |
968 |
* @b: Pointer to "struct ccs_acl_info". |
* @b: Pointer to "struct ccs_acl_info". |
969 |
* |
* |
970 |
* Returns true if @a and @b are duplicated, false otherwise. |
* Returns true if @a == @b, false otherwise. |
971 |
*/ |
*/ |
972 |
static bool ccs_same_handler_acl(const struct ccs_acl_info *a, |
static bool ccs_same_handler_acl(const struct ccs_acl_info *a, |
973 |
const struct ccs_acl_info *b) |
const struct ccs_acl_info *b) |
983 |
* @a: Pointer to "struct ccs_acl_info". |
* @a: Pointer to "struct ccs_acl_info". |
984 |
* @b: Pointer to "struct ccs_acl_info". |
* @b: Pointer to "struct ccs_acl_info". |
985 |
* |
* |
986 |
* Returns true if @a and @b are duplicated, false otherwise. |
* Returns true if @a == @b, false otherwise. |
987 |
*/ |
*/ |
988 |
static bool ccs_same_task_acl(const struct ccs_acl_info *a, |
static bool ccs_same_task_acl(const struct ccs_acl_info *a, |
989 |
const struct ccs_acl_info *b) |
const struct ccs_acl_info *b) |
1349 |
ccs_yesno(cond->grant_log == |
ccs_yesno(cond->grant_log == |
1350 |
CCS_GRANTLOG_YES)); |
CCS_GRANTLOG_YES)); |
1351 |
if (cond->transit) { |
if (cond->transit) { |
1352 |
ccs_set_string(head, " auto_domain_transitition=\""); |
ccs_set_string(head, " auto_domain_transition=\""); |
1353 |
ccs_set_string(head, cond->transit->name); |
ccs_set_string(head, cond->transit->name); |
1354 |
ccs_set_string(head, "\""); |
ccs_set_string(head, "\""); |
1355 |
} |
} |
1592 |
* @domain: Pointer to "struct ccs_domain_info". |
* @domain: Pointer to "struct ccs_domain_info". |
1593 |
* @index: Index number. |
* @index: Index number. |
1594 |
* |
* |
|
* Caller holds ccs_read_lock(). |
|
|
* |
|
1595 |
* Returns true on success, false otherwise. |
* Returns true on success, false otherwise. |
1596 |
|
* |
1597 |
|
* Caller holds ccs_read_lock(). |
1598 |
*/ |
*/ |
1599 |
static bool ccs_read_domain2(struct ccs_io_buffer *head, |
static bool ccs_read_domain2(struct ccs_io_buffer *head, |
1600 |
struct ccs_domain_info *domain, |
struct ccs_domain_info *domain, |
1615 |
* |
* |
1616 |
* @head: Pointer to "struct ccs_io_buffer". |
* @head: Pointer to "struct ccs_io_buffer". |
1617 |
* |
* |
1618 |
|
* Returns nothing. |
1619 |
|
* |
1620 |
* Caller holds ccs_read_lock(). |
* Caller holds ccs_read_lock(). |
1621 |
*/ |
*/ |
1622 |
static void ccs_read_domain(struct ccs_io_buffer *head) |
static void ccs_read_domain(struct ccs_io_buffer *head) |
1703 |
* |
* |
1704 |
* @head: Pointer to "struct ccs_io_buffer". |
* @head: Pointer to "struct ccs_io_buffer". |
1705 |
* |
* |
1706 |
|
* Returns nothing. |
1707 |
|
* |
1708 |
* This is equivalent to doing |
* This is equivalent to doing |
1709 |
* |
* |
1710 |
* grep -A 1 '^<kernel>' /proc/ccs/domain_policy | |
* grep -A 1 '^<kernel>' /proc/ccs/domain_policy | |
1733 |
} |
} |
1734 |
|
|
1735 |
/** |
/** |
1736 |
* ccs_write_pid: Specify PID to obtain domainname. |
* ccs_write_pid - Specify PID to obtain domainname. |
1737 |
* |
* |
1738 |
* @head: Pointer to "struct ccs_io_buffer". |
* @head: Pointer to "struct ccs_io_buffer". |
1739 |
* |
* |
1990 |
* |
* |
1991 |
* @head: Pointer to "struct ccs_io_buffer". |
* @head: Pointer to "struct ccs_io_buffer". |
1992 |
* |
* |
1993 |
|
* Returns nothing. |
1994 |
|
* |
1995 |
* Caller holds ccs_read_lock(). |
* Caller holds ccs_read_lock(). |
1996 |
*/ |
*/ |
1997 |
static void ccs_read_exception(struct ccs_io_buffer *head) |
static void ccs_read_exception(struct ccs_io_buffer *head) |
2026 |
/* Wait queue for userspace -> kernel notification. */ |
/* Wait queue for userspace -> kernel notification. */ |
2027 |
static DECLARE_WAIT_QUEUE_HEAD(ccs_answer_wait); |
static DECLARE_WAIT_QUEUE_HEAD(ccs_answer_wait); |
2028 |
|
|
|
/* Lock for manipulating ccs_query_list. */ |
|
|
static DEFINE_SPINLOCK(ccs_query_list_lock); |
|
|
|
|
2029 |
/* Structure for query. */ |
/* Structure for query. */ |
2030 |
struct ccs_query { |
struct ccs_query { |
2031 |
struct list_head list; |
struct list_head list; |
2040 |
/* The list for "struct ccs_query". */ |
/* The list for "struct ccs_query". */ |
2041 |
static LIST_HEAD(ccs_query_list); |
static LIST_HEAD(ccs_query_list); |
2042 |
|
|
2043 |
|
/* Lock for manipulating ccs_query_list. */ |
2044 |
|
static DEFINE_SPINLOCK(ccs_query_list_lock); |
2045 |
|
|
2046 |
/* Number of "struct file" referring /proc/ccs/query interface. */ |
/* Number of "struct file" referring /proc/ccs/query interface. */ |
2047 |
static atomic_t ccs_query_observers = ATOMIC_INIT(0); |
static atomic_t ccs_query_observers = ATOMIC_INIT(0); |
2048 |
|
|
2144 |
va_start(args, fmt); |
va_start(args, fmt); |
2145 |
len = vsnprintf((char *) &len, 1, fmt, args) + 1; |
len = vsnprintf((char *) &len, 1, fmt, args) + 1; |
2146 |
va_end(args); |
va_end(args); |
2147 |
/* Write /proc/ccs/grant_log or /proc/ccs/reject_log . */ |
/* Write /proc/ccs/grant_log or /proc/ccs/reject_log. */ |
2148 |
va_start(args, fmt); |
va_start(args, fmt); |
2149 |
ccs_write_log2(r, len, fmt, args); |
ccs_write_log2(r, len, fmt, args); |
2150 |
va_end(args); |
va_end(args); |
2371 |
} |
} |
2372 |
|
|
2373 |
/** |
/** |
2374 |
* ccs_read_version: Get version. |
* ccs_read_version - Get version. |
2375 |
* |
* |
2376 |
* @head: Pointer to "struct ccs_io_buffer". |
* @head: Pointer to "struct ccs_io_buffer". |
2377 |
* |
* |
2539 |
* @type: Type of interface. |
* @type: Type of interface. |
2540 |
* @file: Pointer to "struct file". |
* @file: Pointer to "struct file". |
2541 |
* |
* |
2542 |
* Associates policy handler and returns 0 on success, -ENOMEM otherwise. |
* Returns 0 on success, negative value otherwise. |
2543 |
*/ |
*/ |
2544 |
int ccs_open_control(const u8 type, struct file *file) |
int ccs_open_control(const u8 type, struct file *file) |
2545 |
{ |
{ |
2638 |
} |
} |
2639 |
} |
} |
2640 |
/* |
/* |
2641 |
* If the file is /proc/ccs/query , increment the observer counter. |
* If the file is /proc/ccs/query, increment the observer counter. |
2642 |
* The obserber counter is used by ccs_supervisor() to see if |
* The obserber counter is used by ccs_supervisor() to see if |
2643 |
* there is some process monitoring /proc/ccs/query. |
* there is some process monitoring /proc/ccs/query. |
2644 |
*/ |
*/ |
2663 |
* Waits for read readiness. |
* Waits for read readiness. |
2664 |
* /proc/ccs/query is handled by /usr/sbin/ccs-queryd and |
* /proc/ccs/query is handled by /usr/sbin/ccs-queryd and |
2665 |
* /proc/ccs/grant_log and /proc/ccs/reject_log are handled by |
* /proc/ccs/grant_log and /proc/ccs/reject_log are handled by |
2666 |
* /usr/sbin/ccs-auditd . |
* /usr/sbin/ccs-auditd. |
2667 |
*/ |
*/ |
2668 |
int ccs_poll_control(struct file *file, poll_table *wait) |
int ccs_poll_control(struct file *file, poll_table *wait) |
2669 |
{ |
{ |
2788 |
* |
* |
2789 |
* @file: Pointer to "struct file". |
* @file: Pointer to "struct file". |
2790 |
* |
* |
2791 |
* Releases memory and returns 0. |
* Returns 0. |
2792 |
*/ |
*/ |
2793 |
int ccs_close_control(struct file *file) |
int ccs_close_control(struct file *file) |
2794 |
{ |
{ |
2796 |
const bool is_write = head->write_buf != NULL; |
const bool is_write = head->write_buf != NULL; |
2797 |
const u8 type = head->type; |
const u8 type = head->type; |
2798 |
/* |
/* |
2799 |
* If the file is /proc/ccs/query , decrement the observer counter. |
* If the file is /proc/ccs/query, decrement the observer counter. |
2800 |
*/ |
*/ |
2801 |
if (type == CCS_QUERY) { |
if (type == CCS_QUERY) { |
2802 |
if (atomic_dec_and_test(&ccs_query_observers)) |
if (atomic_dec_and_test(&ccs_query_observers)) |