aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmy Griffis <amy.griffis@hp.com>2006-07-13 13:16:02 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2006-08-03 10:50:21 -0400
commit3e2efce067cec0099f99ae59f28feda99b02b498 (patch)
tree94577cb6cb7f223319bb89a805b2d6945d42632e
parent46f5960fdbf359f0c75989854bbaebc1de7a1eb4 (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.c2
-rw-r--r--include/linux/audit.h7
-rw-r--r--kernel/auditsc.c63
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);
328extern void __audit_inode(const char *name, const struct inode *inode); 328extern void __audit_inode(const char *name, const struct inode *inode);
329extern void __audit_inode_child(const char *dname, const struct inode *inode, 329extern void __audit_inode_child(const char *dname, const struct inode *inode,
330 unsigned long pino); 330 unsigned long pino);
331extern void __audit_inode_update(const struct inode *inode);
331static inline void audit_getname(const char *name) 332static 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}
347static 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) */
348extern unsigned int audit_serial(void); 353extern 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
1202static void audit_inode_context(int idx, const struct inode *inode) 1202/* Copy inode data into an audit_names. */
1203static 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 */
1317void __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/**