diff options
author | Amy Griffis <amy.griffis@hp.com> | 2006-07-13 13:16:02 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2006-08-03 10:50:21 -0400 |
commit | 3e2efce067cec0099f99ae59f28feda99b02b498 (patch) | |
tree | 94577cb6cb7f223319bb89a805b2d6945d42632e | |
parent | 46f5960fdbf359f0c75989854bbaebc1de7a1eb4 (diff) |
[PATCH] fix faulty inode data collection for open() with O_CREAT
When the specified path is an existing file or when it is a symlink, audit
collects the wrong inode number, which causes it to miss the open() event.
Adding a second hook to the open() path fixes this.
Also add audit_copy_inode() to consolidate some code.
Signed-off-by: Amy Griffis <amy.griffis@hp.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/namei.c | 2 | ||||
-rw-r--r-- | include/linux/audit.h | 7 | ||||
-rw-r--r-- | kernel/auditsc.c | 63 |
3 files changed, 50 insertions, 22 deletions
diff --git a/fs/namei.c b/fs/namei.c index e01070d7bf58..47a7bad92d2a 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1659,6 +1659,7 @@ do_last: | |||
1659 | * It already exists. | 1659 | * It already exists. |
1660 | */ | 1660 | */ |
1661 | mutex_unlock(&dir->d_inode->i_mutex); | 1661 | mutex_unlock(&dir->d_inode->i_mutex); |
1662 | audit_inode_update(path.dentry->d_inode); | ||
1662 | 1663 | ||
1663 | error = -EEXIST; | 1664 | error = -EEXIST; |
1664 | if (flag & O_EXCL) | 1665 | if (flag & O_EXCL) |
@@ -1669,6 +1670,7 @@ do_last: | |||
1669 | if (flag & O_NOFOLLOW) | 1670 | if (flag & O_NOFOLLOW) |
1670 | goto exit_dput; | 1671 | goto exit_dput; |
1671 | } | 1672 | } |
1673 | |||
1672 | error = -ENOENT; | 1674 | error = -ENOENT; |
1673 | if (!path.dentry->d_inode) | 1675 | if (!path.dentry->d_inode) |
1674 | goto exit_dput; | 1676 | goto exit_dput; |
diff --git a/include/linux/audit.h b/include/linux/audit.h index b27d7debc5a1..e7e5e5348987 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
@@ -328,6 +328,7 @@ extern void audit_putname(const char *name); | |||
328 | extern void __audit_inode(const char *name, const struct inode *inode); | 328 | extern void __audit_inode(const char *name, const struct inode *inode); |
329 | extern void __audit_inode_child(const char *dname, const struct inode *inode, | 329 | extern void __audit_inode_child(const char *dname, const struct inode *inode, |
330 | unsigned long pino); | 330 | unsigned long pino); |
331 | extern void __audit_inode_update(const struct inode *inode); | ||
331 | static inline void audit_getname(const char *name) | 332 | static inline void audit_getname(const char *name) |
332 | { | 333 | { |
333 | if (unlikely(current->audit_context)) | 334 | if (unlikely(current->audit_context)) |
@@ -343,6 +344,10 @@ static inline void audit_inode_child(const char *dname, | |||
343 | if (unlikely(current->audit_context)) | 344 | if (unlikely(current->audit_context)) |
344 | __audit_inode_child(dname, inode, pino); | 345 | __audit_inode_child(dname, inode, pino); |
345 | } | 346 | } |
347 | static inline void audit_inode_update(const struct inode *inode) { | ||
348 | if (unlikely(current->audit_context)) | ||
349 | __audit_inode_update(inode); | ||
350 | } | ||
346 | 351 | ||
347 | /* Private API (for audit.c only) */ | 352 | /* Private API (for audit.c only) */ |
348 | extern unsigned int audit_serial(void); | 353 | extern unsigned int audit_serial(void); |
@@ -414,8 +419,10 @@ static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat) | |||
414 | #define audit_putname(n) do { ; } while (0) | 419 | #define audit_putname(n) do { ; } while (0) |
415 | #define __audit_inode(n,i) do { ; } while (0) | 420 | #define __audit_inode(n,i) do { ; } while (0) |
416 | #define __audit_inode_child(d,i,p) do { ; } while (0) | 421 | #define __audit_inode_child(d,i,p) do { ; } while (0) |
422 | #define __audit_inode_update(i) do { ; } while (0) | ||
417 | #define audit_inode(n,i) do { ; } while (0) | 423 | #define audit_inode(n,i) do { ; } while (0) |
418 | #define audit_inode_child(d,i,p) do { ; } while (0) | 424 | #define audit_inode_child(d,i,p) do { ; } while (0) |
425 | #define audit_inode_update(i) do { ; } while (0) | ||
419 | #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0) | 426 | #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0) |
420 | #define audit_get_loginuid(c) ({ -1; }) | 427 | #define audit_get_loginuid(c) ({ -1; }) |
421 | #define audit_ipc_obj(i) ({ 0; }) | 428 | #define audit_ipc_obj(i) ({ 0; }) |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index ae40ac8c39e7..b939ed2da3ee 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -1199,14 +1199,18 @@ void audit_putname(const char *name) | |||
1199 | #endif | 1199 | #endif |
1200 | } | 1200 | } |
1201 | 1201 | ||
1202 | static void audit_inode_context(int idx, const struct inode *inode) | 1202 | /* Copy inode data into an audit_names. */ |
1203 | static void audit_copy_inode(struct audit_names *name, const struct inode *inode) | ||
1203 | { | 1204 | { |
1204 | struct audit_context *context = current->audit_context; | 1205 | name->ino = inode->i_ino; |
1205 | 1206 | name->dev = inode->i_sb->s_dev; | |
1206 | selinux_get_inode_sid(inode, &context->names[idx].osid); | 1207 | name->mode = inode->i_mode; |
1208 | name->uid = inode->i_uid; | ||
1209 | name->gid = inode->i_gid; | ||
1210 | name->rdev = inode->i_rdev; | ||
1211 | selinux_get_inode_sid(inode, &name->osid); | ||
1207 | } | 1212 | } |
1208 | 1213 | ||
1209 | |||
1210 | /** | 1214 | /** |
1211 | * audit_inode - store the inode and device from a lookup | 1215 | * audit_inode - store the inode and device from a lookup |
1212 | * @name: name being audited | 1216 | * @name: name being audited |
@@ -1240,13 +1244,7 @@ void __audit_inode(const char *name, const struct inode *inode) | |||
1240 | ++context->ino_count; | 1244 | ++context->ino_count; |
1241 | #endif | 1245 | #endif |
1242 | } | 1246 | } |
1243 | context->names[idx].ino = inode->i_ino; | 1247 | audit_copy_inode(&context->names[idx], inode); |
1244 | context->names[idx].dev = inode->i_sb->s_dev; | ||
1245 | context->names[idx].mode = inode->i_mode; | ||
1246 | context->names[idx].uid = inode->i_uid; | ||
1247 | context->names[idx].gid = inode->i_gid; | ||
1248 | context->names[idx].rdev = inode->i_rdev; | ||
1249 | audit_inode_context(idx, inode); | ||
1250 | } | 1248 | } |
1251 | 1249 | ||
1252 | /** | 1250 | /** |
@@ -1302,16 +1300,37 @@ update_context: | |||
1302 | context->names[idx].name_len = AUDIT_NAME_FULL; | 1300 | context->names[idx].name_len = AUDIT_NAME_FULL; |
1303 | context->names[idx].name_put = 0; /* don't call __putname() */ | 1301 | context->names[idx].name_put = 0; /* don't call __putname() */ |
1304 | 1302 | ||
1305 | if (inode) { | 1303 | if (!inode) |
1306 | context->names[idx].ino = inode->i_ino; | 1304 | context->names[idx].ino = (unsigned long)-1; |
1307 | context->names[idx].dev = inode->i_sb->s_dev; | 1305 | else |
1308 | context->names[idx].mode = inode->i_mode; | 1306 | audit_copy_inode(&context->names[idx], inode); |
1309 | context->names[idx].uid = inode->i_uid; | 1307 | } |
1310 | context->names[idx].gid = inode->i_gid; | 1308 | |
1311 | context->names[idx].rdev = inode->i_rdev; | 1309 | /** |
1312 | audit_inode_context(idx, inode); | 1310 | * audit_inode_update - update inode info for last collected name |
1313 | } else | 1311 | * @inode: inode being audited |
1314 | context->names[idx].ino = (unsigned long)-1; | 1312 | * |
1313 | * When open() is called on an existing object with the O_CREAT flag, the inode | ||
1314 | * data audit initially collects is incorrect. This additional hook ensures | ||
1315 | * audit has the inode data for the actual object to be opened. | ||
1316 | */ | ||
1317 | void __audit_inode_update(const struct inode *inode) | ||
1318 | { | ||
1319 | struct audit_context *context = current->audit_context; | ||
1320 | int idx; | ||
1321 | |||
1322 | if (!context->in_syscall || !inode) | ||
1323 | return; | ||
1324 | |||
1325 | if (context->name_count == 0) { | ||
1326 | context->name_count++; | ||
1327 | #if AUDIT_DEBUG | ||
1328 | context->ino_count++; | ||
1329 | #endif | ||
1330 | } | ||
1331 | idx = context->name_count - 1; | ||
1332 | |||
1333 | audit_copy_inode(&context->names[idx], inode); | ||
1315 | } | 1334 | } |
1316 | 1335 | ||
1317 | /** | 1336 | /** |