forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add /sys/kernel/security/tomoyo/audit interface. This interface generates audit logs in the form of domain policy so that /usr/sbin/tomoyo-auditd can reuse audit logs for appending to /sys/kernel/security/tomoyo/domain_policy interface. Signed-off-by: Tetsuo Handa <[email protected]> Signed-off-by: James Morris <[email protected]>
- Loading branch information
Tetsuo Handa
authored and
James Morris
committed
Jun 28, 2011
1 parent
d5ca172
commit eadd99c
Showing
9 changed files
with
557 additions
and
235 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
obj-y = common.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o | ||
obj-y = audit.o common.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,300 @@ | ||
/* | ||
* security/tomoyo/audit.c | ||
* | ||
* Pathname restriction functions. | ||
* | ||
* Copyright (C) 2005-2010 NTT DATA CORPORATION | ||
*/ | ||
|
||
#include "common.h" | ||
#include <linux/slab.h> | ||
|
||
/** | ||
* tomoyo_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss. | ||
* | ||
* @time: Seconds since 1970/01/01 00:00:00. | ||
* @stamp: Pointer to "struct tomoyo_time". | ||
* | ||
* Returns nothing. | ||
* | ||
* This function does not handle Y2038 problem. | ||
*/ | ||
static void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp) | ||
{ | ||
static const u16 tomoyo_eom[2][12] = { | ||
{ 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, | ||
{ 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } | ||
}; | ||
u16 y; | ||
u8 m; | ||
bool r; | ||
stamp->sec = time % 60; | ||
time /= 60; | ||
stamp->min = time % 60; | ||
time /= 60; | ||
stamp->hour = time % 24; | ||
time /= 24; | ||
for (y = 1970; ; y++) { | ||
const unsigned short days = (y & 3) ? 365 : 366; | ||
if (time < days) | ||
break; | ||
time -= days; | ||
} | ||
r = (y & 3) == 0; | ||
for (m = 0; m < 11 && time >= tomoyo_eom[r][m]; m++) | ||
; | ||
if (m) | ||
time -= tomoyo_eom[r][m - 1]; | ||
stamp->year = y; | ||
stamp->month = ++m; | ||
stamp->day = ++time; | ||
} | ||
|
||
/** | ||
* tomoyo_print_header - Get header line of audit log. | ||
* | ||
* @r: Pointer to "struct tomoyo_request_info". | ||
* | ||
* Returns string representation. | ||
* | ||
* This function uses kmalloc(), so caller must kfree() if this function | ||
* didn't return NULL. | ||
*/ | ||
static char *tomoyo_print_header(struct tomoyo_request_info *r) | ||
{ | ||
struct tomoyo_time stamp; | ||
const pid_t gpid = task_pid_nr(current); | ||
static const int tomoyo_buffer_len = 4096; | ||
char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); | ||
pid_t ppid; | ||
if (!buffer) | ||
return NULL; | ||
{ | ||
struct timeval tv; | ||
do_gettimeofday(&tv); | ||
tomoyo_convert_time(tv.tv_sec, &stamp); | ||
} | ||
rcu_read_lock(); | ||
ppid = task_tgid_vnr(current->real_parent); | ||
rcu_read_unlock(); | ||
snprintf(buffer, tomoyo_buffer_len - 1, | ||
"#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s " | ||
"granted=%s (global-pid=%u) task={ pid=%u ppid=%u " | ||
"uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u " | ||
"fsuid=%u fsgid=%u }", | ||
stamp.year, stamp.month, stamp.day, stamp.hour, | ||
stamp.min, stamp.sec, r->profile, tomoyo_mode[r->mode], | ||
tomoyo_yesno(r->granted), gpid, task_tgid_vnr(current), ppid, | ||
current_uid(), current_gid(), current_euid(), current_egid(), | ||
current_suid(), current_sgid(), current_fsuid(), | ||
current_fsgid()); | ||
return buffer; | ||
} | ||
|
||
/** | ||
* tomoyo_init_log - Allocate buffer for audit logs. | ||
* | ||
* @r: Pointer to "struct tomoyo_request_info". | ||
* @len: Buffer size needed for @fmt and @args. | ||
* @fmt: The printf()'s format string. | ||
* @args: va_list structure for @fmt. | ||
* | ||
* Returns pointer to allocated memory. | ||
* | ||
* This function uses kzalloc(), so caller must kfree() if this function | ||
* didn't return NULL. | ||
*/ | ||
char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, | ||
va_list args) | ||
{ | ||
char *buf = NULL; | ||
const char *header = NULL; | ||
int pos; | ||
const char *domainname = tomoyo_domain()->domainname->name; | ||
header = tomoyo_print_header(r); | ||
if (!header) | ||
return NULL; | ||
/* +10 is for '\n' etc. and '\0'. */ | ||
len += strlen(domainname) + strlen(header) + 10; | ||
len = tomoyo_round2(len); | ||
buf = kzalloc(len, GFP_NOFS); | ||
if (!buf) | ||
goto out; | ||
len--; | ||
pos = snprintf(buf, len, "%s", header); | ||
pos += snprintf(buf + pos, len - pos, "\n%s\n", domainname); | ||
vsnprintf(buf + pos, len - pos, fmt, args); | ||
out: | ||
kfree(header); | ||
return buf; | ||
} | ||
|
||
/* Wait queue for /sys/kernel/security/tomoyo/audit. */ | ||
static DECLARE_WAIT_QUEUE_HEAD(tomoyo_log_wait); | ||
|
||
/* Structure for audit log. */ | ||
struct tomoyo_log { | ||
struct list_head list; | ||
char *log; | ||
int size; | ||
}; | ||
|
||
/* The list for "struct tomoyo_log". */ | ||
static LIST_HEAD(tomoyo_log); | ||
|
||
/* Lock for "struct list_head tomoyo_log". */ | ||
static DEFINE_SPINLOCK(tomoyo_log_lock); | ||
|
||
/* Length of "stuct list_head tomoyo_log". */ | ||
static unsigned int tomoyo_log_count; | ||
|
||
/** | ||
* tomoyo_get_audit - Get audit mode. | ||
* | ||
* @profile: Profile number. | ||
* @index: Index number of functionality. | ||
* @is_granted: True if granted log, false otherwise. | ||
* | ||
* Returns true if this request should be audited, false otherwise. | ||
*/ | ||
static bool tomoyo_get_audit(const u8 profile, const u8 index, | ||
const bool is_granted) | ||
{ | ||
u8 mode; | ||
const u8 category = TOMOYO_MAC_CATEGORY_FILE + TOMOYO_MAX_MAC_INDEX; | ||
struct tomoyo_profile *p; | ||
if (!tomoyo_policy_loaded) | ||
return false; | ||
p = tomoyo_profile(profile); | ||
if (tomoyo_log_count >= p->pref[TOMOYO_PREF_MAX_AUDIT_LOG]) | ||
return false; | ||
mode = p->config[index]; | ||
if (mode == TOMOYO_CONFIG_USE_DEFAULT) | ||
mode = p->config[category]; | ||
if (mode == TOMOYO_CONFIG_USE_DEFAULT) | ||
mode = p->default_config; | ||
if (is_granted) | ||
return mode & TOMOYO_CONFIG_WANT_GRANT_LOG; | ||
return mode & TOMOYO_CONFIG_WANT_REJECT_LOG; | ||
} | ||
|
||
/** | ||
* tomoyo_write_log2 - Write an audit log. | ||
* | ||
* @r: Pointer to "struct tomoyo_request_info". | ||
* @len: Buffer size needed for @fmt and @args. | ||
* @fmt: The printf()'s format string. | ||
* @args: va_list structure for @fmt. | ||
* | ||
* Returns nothing. | ||
*/ | ||
void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt, | ||
va_list args) | ||
{ | ||
char *buf; | ||
struct tomoyo_log *entry; | ||
bool quota_exceeded = false; | ||
if (!tomoyo_get_audit(r->profile, r->type, r->granted)) | ||
goto out; | ||
buf = tomoyo_init_log(r, len, fmt, args); | ||
if (!buf) | ||
goto out; | ||
entry = kzalloc(sizeof(*entry), GFP_NOFS); | ||
if (!entry) { | ||
kfree(buf); | ||
goto out; | ||
} | ||
entry->log = buf; | ||
len = tomoyo_round2(strlen(buf) + 1); | ||
/* | ||
* The entry->size is used for memory quota checks. | ||
* Don't go beyond strlen(entry->log). | ||
*/ | ||
entry->size = len + tomoyo_round2(sizeof(*entry)); | ||
spin_lock(&tomoyo_log_lock); | ||
if (tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT] && | ||
tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] + entry->size >= | ||
tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT]) { | ||
quota_exceeded = true; | ||
} else { | ||
tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] += entry->size; | ||
list_add_tail(&entry->list, &tomoyo_log); | ||
tomoyo_log_count++; | ||
} | ||
spin_unlock(&tomoyo_log_lock); | ||
if (quota_exceeded) { | ||
kfree(buf); | ||
kfree(entry); | ||
goto out; | ||
} | ||
wake_up(&tomoyo_log_wait); | ||
out: | ||
return; | ||
} | ||
|
||
/** | ||
* tomoyo_write_log - Write an audit log. | ||
* | ||
* @r: Pointer to "struct tomoyo_request_info". | ||
* @fmt: The printf()'s format string, followed by parameters. | ||
* | ||
* Returns nothing. | ||
*/ | ||
void tomoyo_write_log(struct tomoyo_request_info *r, const char *fmt, ...) | ||
{ | ||
va_list args; | ||
int len; | ||
va_start(args, fmt); | ||
len = vsnprintf((char *) &len, 1, fmt, args) + 1; | ||
va_end(args); | ||
va_start(args, fmt); | ||
tomoyo_write_log2(r, len, fmt, args); | ||
va_end(args); | ||
} | ||
|
||
/** | ||
* tomoyo_read_log - Read an audit log. | ||
* | ||
* @head: Pointer to "struct tomoyo_io_buffer". | ||
* | ||
* Returns nothing. | ||
*/ | ||
void tomoyo_read_log(struct tomoyo_io_buffer *head) | ||
{ | ||
struct tomoyo_log *ptr = NULL; | ||
if (head->r.w_pos) | ||
return; | ||
kfree(head->read_buf); | ||
head->read_buf = NULL; | ||
spin_lock(&tomoyo_log_lock); | ||
if (!list_empty(&tomoyo_log)) { | ||
ptr = list_entry(tomoyo_log.next, typeof(*ptr), list); | ||
list_del(&ptr->list); | ||
tomoyo_log_count--; | ||
tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] -= ptr->size; | ||
} | ||
spin_unlock(&tomoyo_log_lock); | ||
if (ptr) { | ||
head->read_buf = ptr->log; | ||
head->r.w[head->r.w_pos++] = head->read_buf; | ||
kfree(ptr); | ||
} | ||
} | ||
|
||
/** | ||
* tomoyo_poll_log - Wait for an audit log. | ||
* | ||
* @file: Pointer to "struct file". | ||
* @wait: Pointer to "poll_table". | ||
* | ||
* Returns POLLIN | POLLRDNORM when ready to read an audit log. | ||
*/ | ||
int tomoyo_poll_log(struct file *file, poll_table *wait) | ||
{ | ||
if (tomoyo_log_count) | ||
return POLLIN | POLLRDNORM; | ||
poll_wait(file, &tomoyo_log_wait, wait); | ||
if (tomoyo_log_count) | ||
return POLLIN | POLLRDNORM; | ||
return 0; | ||
} |
Oops, something went wrong.