/*
* security/tomoyo/audit.c
*
- * Pathname restriction functions.
- *
- * Copyright (C) 2005-2010 NTT DATA CORPORATION
+ * Copyright (C) 2005-2011 NTT DATA CORPORATION
*/
#include "common.h"
#include <linux/slab.h>
+/**
+ * tomoyo_print_bprm - Print "struct linux_binprm" for auditing.
+ *
+ * @bprm: Pointer to "struct linux_binprm".
+ * @dump: Pointer to "struct tomoyo_page_dump".
+ *
+ * Returns the contents of @bprm on success, NULL otherwise.
+ *
+ * This function uses kzalloc(), so caller must kfree() if this function
+ * didn't return NULL.
+ */
+static char *tomoyo_print_bprm(struct linux_binprm *bprm,
+ struct tomoyo_page_dump *dump)
+{
+ static const int tomoyo_buffer_len = 4096 * 2;
+ char *buffer = kzalloc(tomoyo_buffer_len, GFP_NOFS);
+ char *cp;
+ char *last_start;
+ int len;
+ unsigned long pos = bprm->p;
+ int offset = pos % PAGE_SIZE;
+ int argv_count = bprm->argc;
+ int envp_count = bprm->envc;
+ bool truncated = false;
+ if (!buffer)
+ return NULL;
+ len = snprintf(buffer, tomoyo_buffer_len - 1, "argv[]={ ");
+ cp = buffer + len;
+ if (!argv_count) {
+ memmove(cp, "} envp[]={ ", 11);
+ cp += 11;
+ }
+ last_start = cp;
+ while (argv_count || envp_count) {
+ if (!tomoyo_dump_page(bprm, pos, dump))
+ goto out;
+ pos += PAGE_SIZE - offset;
+ /* Read. */
+ while (offset < PAGE_SIZE) {
+ const char *kaddr = dump->data;
+ const unsigned char c = kaddr[offset++];
+ if (cp == last_start)
+ *cp++ = '"';
+ if (cp >= buffer + tomoyo_buffer_len - 32) {
+ /* Reserve some room for "..." string. */
+ truncated = true;
+ } else if (c == '\\') {
+ *cp++ = '\\';
+ *cp++ = '\\';
+ } else if (c > ' ' && c < 127) {
+ *cp++ = c;
+ } else if (!c) {
+ *cp++ = '"';
+ *cp++ = ' ';
+ last_start = cp;
+ } else {
+ *cp++ = '\\';
+ *cp++ = (c >> 6) + '0';
+ *cp++ = ((c >> 3) & 7) + '0';
+ *cp++ = (c & 7) + '0';
+ }
+ if (c)
+ continue;
+ if (argv_count) {
+ if (--argv_count == 0) {
+ if (truncated) {
+ cp = last_start;
+ memmove(cp, "... ", 4);
+ cp += 4;
+ }
+ memmove(cp, "} envp[]={ ", 11);
+ cp += 11;
+ last_start = cp;
+ truncated = false;
+ }
+ } else if (envp_count) {
+ if (--envp_count == 0) {
+ if (truncated) {
+ cp = last_start;
+ memmove(cp, "... ", 4);
+ cp += 4;
+ }
+ }
+ }
+ if (!argv_count && !envp_count)
+ break;
+ }
+ offset = 0;
+ }
+ *cp++ = '}';
+ *cp = '\0';
+ return buffer;
+out:
+ snprintf(buffer, tomoyo_buffer_len - 1,
+ "argv[]={ ... } envp[]= { ... }");
+ return buffer;
+}
+
+/**
+ * tomoyo_filetype - Get string representation of file type.
+ *
+ * @mode: Mode value for stat().
+ *
+ * Returns file type string.
+ */
+static inline const char *tomoyo_filetype(const mode_t mode)
+{
+ switch (mode & S_IFMT) {
+ case S_IFREG:
+ case 0:
+ return tomoyo_condition_keyword[TOMOYO_TYPE_IS_FILE];
+ case S_IFDIR:
+ return tomoyo_condition_keyword[TOMOYO_TYPE_IS_DIRECTORY];
+ case S_IFLNK:
+ return tomoyo_condition_keyword[TOMOYO_TYPE_IS_SYMLINK];
+ case S_IFIFO:
+ return tomoyo_condition_keyword[TOMOYO_TYPE_IS_FIFO];
+ case S_IFSOCK:
+ return tomoyo_condition_keyword[TOMOYO_TYPE_IS_SOCKET];
+ case S_IFBLK:
+ return tomoyo_condition_keyword[TOMOYO_TYPE_IS_BLOCK_DEV];
+ case S_IFCHR:
+ return tomoyo_condition_keyword[TOMOYO_TYPE_IS_CHAR_DEV];
+ }
+ return "unknown"; /* This should not happen. */
+}
+
/**
* tomoyo_print_header - Get header line of audit log.
*
{
struct tomoyo_time stamp;
const pid_t gpid = task_pid_nr(current);
+ struct tomoyo_obj_info *obj = r->obj;
static const int tomoyo_buffer_len = 4096;
char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS);
int pos;
+ u8 i;
if (!buffer)
return NULL;
{
current_uid(), current_gid(), current_euid(),
current_egid(), current_suid(), current_sgid(),
current_fsuid(), current_fsgid());
+ if (!obj)
+ goto no_obj_info;
+ if (!obj->validate_done) {
+ tomoyo_get_attributes(obj);
+ obj->validate_done = true;
+ }
+ for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) {
+ struct tomoyo_mini_stat *stat;
+ unsigned int dev;
+ mode_t mode;
+ if (!obj->stat_valid[i])
+ continue;
+ stat = &obj->stat[i];
+ dev = stat->dev;
+ mode = stat->mode;
+ if (i & 1) {
+ pos += snprintf(buffer + pos,
+ tomoyo_buffer_len - 1 - pos,
+ " path%u.parent={ uid=%u gid=%u "
+ "ino=%lu perm=0%o }", (i >> 1) + 1,
+ stat->uid, stat->gid, (unsigned long)
+ stat->ino, stat->mode & S_IALLUGO);
+ continue;
+ }
+ pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos,
+ " path%u={ uid=%u gid=%u ino=%lu major=%u"
+ " minor=%u perm=0%o type=%s", (i >> 1) + 1,
+ stat->uid, stat->gid, (unsigned long)
+ stat->ino, MAJOR(dev), MINOR(dev),
+ mode & S_IALLUGO, tomoyo_filetype(mode));
+ if (S_ISCHR(mode) || S_ISBLK(mode)) {
+ dev = stat->rdev;
+ pos += snprintf(buffer + pos,
+ tomoyo_buffer_len - 1 - pos,
+ " dev_major=%u dev_minor=%u",
+ MAJOR(dev), MINOR(dev));
+ }
+ pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos,
+ " }");
+ }
+no_obj_info:
if (pos < tomoyo_buffer_len - 1)
return buffer;
kfree(buffer);
va_list args)
{
char *buf = NULL;
+ char *bprm_info = NULL;
const char *header = NULL;
+ char *realpath = NULL;
+ const char *symlink = NULL;
int pos;
const char *domainname = r->domain->domainname->name;
header = tomoyo_print_header(r);
return NULL;
/* +10 is for '\n' etc. and '\0'. */
len += strlen(domainname) + strlen(header) + 10;
+ if (r->ee) {
+ struct file *file = r->ee->bprm->file;
+ realpath = tomoyo_realpath_from_path(&file->f_path);
+ bprm_info = tomoyo_print_bprm(r->ee->bprm, &r->ee->dump);
+ if (!realpath || !bprm_info)
+ goto out;
+ /* +80 is for " exec={ realpath=\"%s\" argc=%d envc=%d %s }" */
+ len += strlen(realpath) + 80 + strlen(bprm_info);
+ } else if (r->obj && r->obj->symlink_target) {
+ symlink = r->obj->symlink_target->name;
+ /* +18 is for " symlink.target=\"%s\"" */
+ len += 18 + strlen(symlink);
+ }
len = tomoyo_round2(len);
buf = kzalloc(len, GFP_NOFS);
if (!buf)
goto out;
len--;
pos = snprintf(buf, len, "%s", header);
+ if (realpath) {
+ struct linux_binprm *bprm = r->ee->bprm;
+ pos += snprintf(buf + pos, len - pos,
+ " exec={ realpath=\"%s\" argc=%d envc=%d %s }",
+ realpath, bprm->argc, bprm->envc, bprm_info);
+ } else if (symlink)
+ pos += snprintf(buf + pos, len - pos, " symlink.target=\"%s\"",
+ symlink);
pos += snprintf(buf + pos, len - pos, "\n%s\n", domainname);
vsnprintf(buf + pos, len - pos, fmt, args);
out:
+ kfree(realpath);
+ kfree(bprm_info);
kfree(header);
return buf;
}