summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorMimi Zohar <zohar@linux.vnet.ibm.com>2017-01-17 06:45:41 -0500
committerMimi Zohar <zohar@linux.vnet.ibm.com>2017-01-27 14:16:02 -0500
commitbc15ed663e7e53ee4dc3e60f8d09c93a0528c694 (patch)
tree7ab298e6fac6256585436cd3f78b8b1fa36daa02 /security
parent710584b9daefe25a2b5dc2c6c10dbb00e1b3b451 (diff)
ima: fix ima_d_path() possible race with rename
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> Cc: stable@vger.kernel.org
Diffstat (limited to 'security')
-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 5e6180a4da7d..b563fbd4d122 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -204,7 +204,7 @@ int ima_store_template(struct ima_template_entry *entry, int violation,
204 struct inode *inode, 204 struct inode *inode,
205 const unsigned char *filename, int pcr); 205 const unsigned char *filename, int pcr);
206void ima_free_template_entry(struct ima_template_entry *entry); 206void ima_free_template_entry(struct ima_template_entry *entry);
207const char *ima_d_path(const struct path *path, char **pathbuf); 207const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
208 208
209/* IMA policy related functions */ 209/* IMA policy related functions */
210int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, 210int 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 50818c60538b..d5e492bd2899 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,