aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity
diff options
context:
space:
mode:
authorMimi Zohar <zohar@linux.vnet.ibm.com>2017-01-17 06:45:41 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-03-12 00:41:44 -0500
commitd9cc31683a16f5619217d80c3d8e608c23c41afc (patch)
tree68115d5b3adbcaf99f291bc20efe5906ae44ed9e /security/integrity
parent270e84a1e6effd6c0c6e9b13b196b5fdaa392954 (diff)
ima: fix ima_d_path() possible race with rename
commit bc15ed663e7e53ee4dc3e60f8d09c93a0528c694 upstream. On failure to return a pathname from ima_d_path(), a pointer to dname is returned, which is subsequently used in the IMA measurement list, the IMA audit records, and other audit logging. Saving the pointer to dname for later use has the potential to race with rename. Intead of returning a pointer to dname on failure, this patch returns a pointer to a copy of the filename. Reported-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'security/integrity')
-rw-r--r--security/integrity/ima/ima.h2
-rw-r--r--security/integrity/ima/ima_api.c20
-rw-r--r--security/integrity/ima/ima_main.c8
3 files changed, 24 insertions, 6 deletions
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index db25f54a04fe..df7834aa1b8f 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -173,7 +173,7 @@ int ima_store_template(struct ima_template_entry *entry, int violation,
173 struct inode *inode, 173 struct inode *inode,
174 const unsigned char *filename, int pcr); 174 const unsigned char *filename, int pcr);
175void ima_free_template_entry(struct ima_template_entry *entry); 175void ima_free_template_entry(struct ima_template_entry *entry);
176const char *ima_d_path(const struct path *path, char **pathbuf); 176const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
177 177
178/* IMA policy related functions */ 178/* IMA policy related functions */
179int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, 179int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 9df26a2b75ba..d01a52f8f708 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -318,7 +318,17 @@ void ima_audit_measurement(struct integrity_iint_cache *iint,
318 iint->flags |= IMA_AUDITED; 318 iint->flags |= IMA_AUDITED;
319} 319}
320 320
321const char *ima_d_path(const struct path *path, char **pathbuf) 321/*
322 * ima_d_path - return a pointer to the full pathname
323 *
324 * Attempt to return a pointer to the full pathname for use in the
325 * IMA measurement list, IMA audit records, and auditing logs.
326 *
327 * On failure, return a pointer to a copy of the filename, not dname.
328 * Returning a pointer to dname, could result in using the pointer
329 * after the memory has been freed.
330 */
331const char *ima_d_path(const struct path *path, char **pathbuf, char *namebuf)
322{ 332{
323 char *pathname = NULL; 333 char *pathname = NULL;
324 334
@@ -331,5 +341,11 @@ const char *ima_d_path(const struct path *path, char **pathbuf)
331 pathname = NULL; 341 pathname = NULL;
332 } 342 }
333 } 343 }
334 return pathname ?: (const char *)path->dentry->d_name.name; 344
345 if (!pathname) {
346 strlcpy(namebuf, path->dentry->d_name.name, NAME_MAX);
347 pathname = namebuf;
348 }
349
350 return pathname;
335} 351}
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 423d111b3b94..0e8762945e79 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -83,6 +83,7 @@ static void ima_rdwr_violation_check(struct file *file,
83 const char **pathname) 83 const char **pathname)
84{ 84{
85 struct inode *inode = file_inode(file); 85 struct inode *inode = file_inode(file);
86 char filename[NAME_MAX];
86 fmode_t mode = file->f_mode; 87 fmode_t mode = file->f_mode;
87 bool send_tomtou = false, send_writers = false; 88 bool send_tomtou = false, send_writers = false;
88 89
@@ -102,7 +103,7 @@ static void ima_rdwr_violation_check(struct file *file,
102 if (!send_tomtou && !send_writers) 103 if (!send_tomtou && !send_writers)
103 return; 104 return;
104 105
105 *pathname = ima_d_path(&file->f_path, pathbuf); 106 *pathname = ima_d_path(&file->f_path, pathbuf, filename);
106 107
107 if (send_tomtou) 108 if (send_tomtou)
108 ima_add_violation(file, *pathname, iint, 109 ima_add_violation(file, *pathname, iint,
@@ -161,6 +162,7 @@ static int process_measurement(struct file *file, char *buf, loff_t size,
161 struct integrity_iint_cache *iint = NULL; 162 struct integrity_iint_cache *iint = NULL;
162 struct ima_template_desc *template_desc; 163 struct ima_template_desc *template_desc;
163 char *pathbuf = NULL; 164 char *pathbuf = NULL;
165 char filename[NAME_MAX];
164 const char *pathname = NULL; 166 const char *pathname = NULL;
165 int rc = -ENOMEM, action, must_appraise; 167 int rc = -ENOMEM, action, must_appraise;
166 int pcr = CONFIG_IMA_MEASURE_PCR_IDX; 168 int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
@@ -239,8 +241,8 @@ static int process_measurement(struct file *file, char *buf, loff_t size,
239 goto out_digsig; 241 goto out_digsig;
240 } 242 }
241 243
242 if (!pathname) /* ima_rdwr_violation possibly pre-fetched */ 244 if (!pathbuf) /* ima_rdwr_violation possibly pre-fetched */
243 pathname = ima_d_path(&file->f_path, &pathbuf); 245 pathname = ima_d_path(&file->f_path, &pathbuf, filename);
244 246
245 if (action & IMA_MEASURE) 247 if (action & IMA_MEASURE)
246 ima_store_measurement(iint, file, pathname, 248 ima_store_measurement(iint, file, pathname,