ima: use full pathnames in measurement list
authorMimi Zohar <zohar@linux.vnet.ibm.com>
Wed, 20 Jun 2012 13:32:55 +0000 (09:32 -0400)
committerMimi Zohar <zohar@linux.vnet.ibm.com>
Mon, 2 Jul 2012 20:43:29 +0000 (16:43 -0400)
The IMA measurement list contains filename hints, which can be
ambigious without the full pathname.  This patch replaces the
filename hint with the full pathname, simplifying for userspace
the correlating of file hash measurements with files.

Change log v1:
- Revert to short filenames, when full pathname is longer than IMA
  measurement buffer size. (Based on Dmitry's review)

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
security/integrity/ima/ima_api.c
security/integrity/ima/ima_main.c

index 88a2788b981d96ab543ac982c8935b09e56b26e3..032ff03ad9078bc956faa6c6e6d6759b6e2a0420 100644 (file)
@@ -175,7 +175,9 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
        }
        memset(&entry->template, 0, sizeof(entry->template));
        memcpy(entry->template.digest, iint->digest, IMA_DIGEST_SIZE);
-       strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
+       strcpy(entry->template.file_name,
+              (strlen(filename) > IMA_EVENT_NAME_LEN_MAX) ?
+              file->f_dentry->d_name.name : filename);
 
        result = ima_store_template(entry, violation, inode);
        if (!result || result == -EEXIST)
index b17be79b9cf24b8f2319ea2d54875b0a048dcfdf..a0e631a1905859acefa8f814aef1c9c20d997818 100644 (file)
@@ -54,6 +54,7 @@ static void ima_rdwr_violation_check(struct file *file)
        fmode_t mode = file->f_mode;
        int rc;
        bool send_tomtou = false, send_writers = false;
+       unsigned char *pathname = NULL, *pathbuf = NULL;
 
        if (!S_ISREG(inode->i_mode) || !ima_initialized)
                return;
@@ -75,12 +76,27 @@ static void ima_rdwr_violation_check(struct file *file)
 out:
        mutex_unlock(&inode->i_mutex);
 
+       if (!send_tomtou && !send_writers)
+               return;
+
+       /* We will allow 11 spaces for ' (deleted)' to be appended */
+       pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL);
+       if (pathbuf) {
+               pathname = d_path(&file->f_path, pathbuf, PATH_MAX + 11);
+               if (IS_ERR(pathname))
+                       pathname = NULL;
+               else if (strlen(pathname) > IMA_EVENT_NAME_LEN_MAX)
+                       pathname = NULL;
+       }
        if (send_tomtou)
-               ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
-                                 "ToMToU");
+               ima_add_violation(inode,
+                                 !pathname ? dentry->d_name.name : pathname,
+                                 "invalid_pcr", "ToMToU");
        if (send_writers)
-               ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
-                                 "open_writers");
+               ima_add_violation(inode,
+                                 !pathname ? dentry->d_name.name : pathname,
+                                 "invalid_pcr", "open_writers");
+       kfree(pathbuf);
 }
 
 static void ima_check_last_writer(struct integrity_iint_cache *iint,
@@ -123,6 +139,7 @@ static int process_measurement(struct file *file, const unsigned char *filename,
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct integrity_iint_cache *iint;
+       unsigned char *pathname = NULL, *pathbuf = NULL;
        int rc = 0;
 
        if (!ima_initialized || !S_ISREG(inode->i_mode))
@@ -147,8 +164,21 @@ retry:
                goto out;
 
        rc = ima_collect_measurement(iint, file);
-       if (!rc)
-               ima_store_measurement(iint, file, filename);
+       if (rc != 0)
+               goto out;
+
+       if (function != BPRM_CHECK) {
+               /* We will allow 11 spaces for ' (deleted)' to be appended */
+               pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL);
+               if (pathbuf) {
+                       pathname =
+                           d_path(&file->f_path, pathbuf, PATH_MAX + 11);
+                       if (IS_ERR(pathname))
+                               pathname = NULL;
+               }
+       }
+       ima_store_measurement(iint, file, !pathname ? filename : pathname);
+       kfree(pathbuf);
 out:
        mutex_unlock(&iint->mutex);
        return rc;