diff options
author | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2017-01-17 06:45:41 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-03-12 00:41:44 -0500 |
commit | d9cc31683a16f5619217d80c3d8e608c23c41afc (patch) | |
tree | 68115d5b3adbcaf99f291bc20efe5906ae44ed9e /security/integrity | |
parent | 270e84a1e6effd6c0c6e9b13b196b5fdaa392954 (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.h | 2 | ||||
-rw-r--r-- | security/integrity/ima/ima_api.c | 20 | ||||
-rw-r--r-- | security/integrity/ima/ima_main.c | 8 |
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); |
175 | void ima_free_template_entry(struct ima_template_entry *entry); | 175 | void ima_free_template_entry(struct ima_template_entry *entry); |
176 | const char *ima_d_path(const struct path *path, char **pathbuf); | 176 | const char *ima_d_path(const struct path *path, char **pathbuf, char *filename); |
177 | 177 | ||
178 | /* IMA policy related functions */ | 178 | /* IMA policy related functions */ |
179 | int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, | 179 | int 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 | ||
321 | const 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 | */ | ||
331 | const 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, |