]> Pileus Git - ~andy/linux/blobdiff - security/tomoyo/audit.c
Merge branch 'next/dt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/linux...
[~andy/linux] / security / tomoyo / audit.c
index f2c869767d79fbb30fb41e4d40a9ff19c7c36bcf..5dbb1f7617c0077550c79c1255b6fb3f943906ac 100644 (file)
 /*
  * 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.
  *
@@ -23,9 +148,11 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r)
 {
        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);
-       pid_t ppid;
+       int pos;
+       u8 i;
        if (!buffer)
                return NULL;
        {
@@ -33,21 +160,62 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r)
                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;
+       pos = 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,
+                      tomoyo_sys_getpid(), tomoyo_sys_getppid(),
+                      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);
+       return NULL;
 }
 
 /**
@@ -67,23 +235,49 @@ char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt,
                      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 = tomoyo_domain()->domainname->name;
+       const char *domainname = r->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;
+       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;
 }