aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmy Griffis <amy.griffis@hp.com>2006-06-08 23:19:31 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2006-06-20 05:25:28 -0400
commit9c937dcc71021f2dbf78f904f03d962dd9bcc130 (patch)
tree6ab53c1cf1235515307d521cecc4f76afa34e137
parent6a2bceec0ea7fdc47aef9a3f2f771c201eaabe5d (diff)
[PATCH] log more info for directory entry change events
When an audit event involves changes to a directory entry, include a PATH record for the directory itself. A few other notable changes: - fixed audit_inode_child() hooks in fsnotify_move() - removed unused flags arg from audit_inode() - added audit log routines for logging a portion of a string Here's some sample output. before patch: type=SYSCALL msg=audit(1149821605.320:26): arch=40000003 syscall=39 success=yes exit=0 a0=bf8d3c7c a1=1ff a2=804e1b8 a3=bf8d3c7c items=1 ppid=739 pid=800 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=ttyS0 comm="mkdir" exe="/bin/mkdir" subj=root:system_r:unconfined_t:s0-s0:c0.c255 type=CWD msg=audit(1149821605.320:26): cwd="/root" type=PATH msg=audit(1149821605.320:26): item=0 name="foo" parent=164068 inode=164010 dev=03:00 mode=040755 ouid=0 ogid=0 rdev=00:00 obj=root:object_r:user_home_t:s0 after patch: type=SYSCALL msg=audit(1149822032.332:24): arch=40000003 syscall=39 success=yes exit=0 a0=bfdd9c7c a1=1ff a2=804e1b8 a3=bfdd9c7c items=2 ppid=714 pid=777 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=ttyS0 comm="mkdir" exe="/bin/mkdir" subj=root:system_r:unconfined_t:s0-s0:c0.c255 type=CWD msg=audit(1149822032.332:24): cwd="/root" type=PATH msg=audit(1149822032.332:24): item=0 name="/root" inode=164068 dev=03:00 mode=040750 ouid=0 ogid=0 rdev=00:00 obj=root:object_r:user_home_dir_t:s0 type=PATH msg=audit(1149822032.332:24): item=1 name="foo" inode=164010 dev=03:00 mode=040755 ouid=0 ogid=0 rdev=00:00 obj=root:object_r:user_home_t:s0 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--fs/open.c4
-rw-r--r--fs/xattr.c4
-rw-r--r--include/linux/audit.h15
-rw-r--r--include/linux/fsnotify.h3
-rw-r--r--kernel/audit.c54
-rw-r--r--kernel/audit.h3
-rw-r--r--kernel/auditfilter.c8
-rw-r--r--kernel/auditsc.c123
9 files changed, 142 insertions, 74 deletions
diff --git a/fs/namei.c b/fs/namei.c
index d6e2ee251736..184fe4acf824 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1127,7 +1127,7 @@ out:
1127 if (likely(retval == 0)) { 1127 if (likely(retval == 0)) {
1128 if (unlikely(current->audit_context && nd && nd->dentry && 1128 if (unlikely(current->audit_context && nd && nd->dentry &&
1129 nd->dentry->d_inode)) 1129 nd->dentry->d_inode))
1130 audit_inode(name, nd->dentry->d_inode, flags); 1130 audit_inode(name, nd->dentry->d_inode);
1131 } 1131 }
1132out_fail: 1132out_fail:
1133 return retval; 1133 return retval;
diff --git a/fs/open.c b/fs/open.c
index 317b7c7f38a7..4f178acd4c09 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -633,7 +633,7 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
633 dentry = file->f_dentry; 633 dentry = file->f_dentry;
634 inode = dentry->d_inode; 634 inode = dentry->d_inode;
635 635
636 audit_inode(NULL, inode, 0); 636 audit_inode(NULL, inode);
637 637
638 err = -EROFS; 638 err = -EROFS;
639 if (IS_RDONLY(inode)) 639 if (IS_RDONLY(inode))
@@ -786,7 +786,7 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
786 if (file) { 786 if (file) {
787 struct dentry * dentry; 787 struct dentry * dentry;
788 dentry = file->f_dentry; 788 dentry = file->f_dentry;
789 audit_inode(NULL, dentry->d_inode, 0); 789 audit_inode(NULL, dentry->d_inode);
790 error = chown_common(dentry, user, group); 790 error = chown_common(dentry, user, group);
791 fput(file); 791 fput(file);
792 } 792 }
diff --git a/fs/xattr.c b/fs/xattr.c
index e416190f5e9c..c32f15b5f60f 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -242,7 +242,7 @@ sys_fsetxattr(int fd, char __user *name, void __user *value,
242 if (!f) 242 if (!f)
243 return error; 243 return error;
244 dentry = f->f_dentry; 244 dentry = f->f_dentry;
245 audit_inode(NULL, dentry->d_inode, 0); 245 audit_inode(NULL, dentry->d_inode);
246 error = setxattr(dentry, name, value, size, flags); 246 error = setxattr(dentry, name, value, size, flags);
247 fput(f); 247 fput(f);
248 return error; 248 return error;
@@ -469,7 +469,7 @@ sys_fremovexattr(int fd, char __user *name)
469 if (!f) 469 if (!f)
470 return error; 470 return error;
471 dentry = f->f_dentry; 471 dentry = f->f_dentry;
472 audit_inode(NULL, dentry->d_inode, 0); 472 audit_inode(NULL, dentry->d_inode);
473 error = removexattr(dentry, name); 473 error = removexattr(dentry, name);
474 fput(f); 474 fput(f);
475 return error; 475 return error;
diff --git a/include/linux/audit.h b/include/linux/audit.h
index c78327507f4e..e1c1dbdf9efb 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -310,7 +310,7 @@ extern void audit_syscall_entry(int arch,
310extern void audit_syscall_exit(int failed, long return_code); 310extern void audit_syscall_exit(int failed, long return_code);
311extern void __audit_getname(const char *name); 311extern void __audit_getname(const char *name);
312extern void audit_putname(const char *name); 312extern void audit_putname(const char *name);
313extern void __audit_inode(const char *name, const struct inode *inode, unsigned flags); 313extern void __audit_inode(const char *name, const struct inode *inode);
314extern void __audit_inode_child(const char *dname, const struct inode *inode, 314extern void __audit_inode_child(const char *dname, const struct inode *inode,
315 unsigned long pino); 315 unsigned long pino);
316static inline void audit_getname(const char *name) 316static inline void audit_getname(const char *name)
@@ -318,10 +318,9 @@ static inline void audit_getname(const char *name)
318 if (unlikely(current->audit_context)) 318 if (unlikely(current->audit_context))
319 __audit_getname(name); 319 __audit_getname(name);
320} 320}
321static inline void audit_inode(const char *name, const struct inode *inode, 321static inline void audit_inode(const char *name, const struct inode *inode) {
322 unsigned flags) {
323 if (unlikely(current->audit_context)) 322 if (unlikely(current->audit_context))
324 __audit_inode(name, inode, flags); 323 __audit_inode(name, inode);
325} 324}
326static inline void audit_inode_child(const char *dname, 325static inline void audit_inode_child(const char *dname,
327 const struct inode *inode, 326 const struct inode *inode,
@@ -398,9 +397,9 @@ static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
398#define audit_syscall_exit(f,r) do { ; } while (0) 397#define audit_syscall_exit(f,r) do { ; } while (0)
399#define audit_getname(n) do { ; } while (0) 398#define audit_getname(n) do { ; } while (0)
400#define audit_putname(n) do { ; } while (0) 399#define audit_putname(n) do { ; } while (0)
401#define __audit_inode(n,i,f) do { ; } while (0) 400#define __audit_inode(n,i) do { ; } while (0)
402#define __audit_inode_child(d,i,p) do { ; } while (0) 401#define __audit_inode_child(d,i,p) do { ; } while (0)
403#define audit_inode(n,i,f) do { ; } while (0) 402#define audit_inode(n,i) do { ; } while (0)
404#define audit_inode_child(d,i,p) do { ; } while (0) 403#define audit_inode_child(d,i,p) do { ; } while (0)
405#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0) 404#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
406#define audit_get_loginuid(c) ({ -1; }) 405#define audit_get_loginuid(c) ({ -1; })
@@ -435,6 +434,9 @@ extern void audit_log_hex(struct audit_buffer *ab,
435 size_t len); 434 size_t len);
436extern const char * audit_log_untrustedstring(struct audit_buffer *ab, 435extern const char * audit_log_untrustedstring(struct audit_buffer *ab,
437 const char *string); 436 const char *string);
437extern const char * audit_log_n_untrustedstring(struct audit_buffer *ab,
438 size_t n,
439 const char *string);
438extern void audit_log_d_path(struct audit_buffer *ab, 440extern void audit_log_d_path(struct audit_buffer *ab,
439 const char *prefix, 441 const char *prefix,
440 struct dentry *dentry, 442 struct dentry *dentry,
@@ -452,6 +454,7 @@ extern int audit_receive_filter(int type, int pid, int uid, int seq,
452#define audit_log_end(b) do { ; } while (0) 454#define audit_log_end(b) do { ; } while (0)
453#define audit_log_hex(a,b,l) do { ; } while (0) 455#define audit_log_hex(a,b,l) do { ; } while (0)
454#define audit_log_untrustedstring(a,s) do { ; } while (0) 456#define audit_log_untrustedstring(a,s) do { ; } while (0)
457#define audit_log_n_untrustedstring(a,n,s) do { ; } while (0)
455#define audit_log_d_path(b,p,d,v) do { ; } while (0) 458#define audit_log_d_path(b,p,d,v) do { ; } while (0)
456#endif 459#endif
457#endif 460#endif
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index a9d30442448f..cc5dec70c32c 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -67,8 +67,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
67 if (source) { 67 if (source) {
68 inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL); 68 inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL);
69 } 69 }
70 audit_inode_child(old_name, source, old_dir->i_ino); 70 audit_inode_child(new_name, source, new_dir->i_ino);
71 audit_inode_child(new_name, target, new_dir->i_ino);
72} 71}
73 72
74/* 73/*
diff --git a/kernel/audit.c b/kernel/audit.c
index 0fbf1c116363..7dfac7031bd7 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1051,20 +1051,53 @@ void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf,
1051 skb_put(skb, len << 1); /* new string is twice the old string */ 1051 skb_put(skb, len << 1); /* new string is twice the old string */
1052} 1052}
1053 1053
1054/*
1055 * Format a string of no more than slen characters into the audit buffer,
1056 * enclosed in quote marks.
1057 */
1058static void audit_log_n_string(struct audit_buffer *ab, size_t slen,
1059 const char *string)
1060{
1061 int avail, new_len;
1062 unsigned char *ptr;
1063 struct sk_buff *skb;
1064
1065 BUG_ON(!ab->skb);
1066 skb = ab->skb;
1067 avail = skb_tailroom(skb);
1068 new_len = slen + 3; /* enclosing quotes + null terminator */
1069 if (new_len > avail) {
1070 avail = audit_expand(ab, new_len);
1071 if (!avail)
1072 return;
1073 }
1074 ptr = skb->tail;
1075 *ptr++ = '"';
1076 memcpy(ptr, string, slen);
1077 ptr += slen;
1078 *ptr++ = '"';
1079 *ptr = 0;
1080 skb_put(skb, slen + 2); /* don't include null terminator */
1081}
1082
1054/** 1083/**
1055 * audit_log_unstrustedstring - log a string that may contain random characters 1084 * audit_log_n_unstrustedstring - log a string that may contain random characters
1056 * @ab: audit_buffer 1085 * @ab: audit_buffer
1086 * @len: lenth of string (not including trailing null)
1057 * @string: string to be logged 1087 * @string: string to be logged
1058 * 1088 *
1059 * This code will escape a string that is passed to it if the string 1089 * This code will escape a string that is passed to it if the string
1060 * contains a control character, unprintable character, double quote mark, 1090 * contains a control character, unprintable character, double quote mark,
1061 * or a space. Unescaped strings will start and end with a double quote mark. 1091 * or a space. Unescaped strings will start and end with a double quote mark.
1062 * Strings that are escaped are printed in hex (2 digits per char). 1092 * Strings that are escaped are printed in hex (2 digits per char).
1093 *
1094 * The caller specifies the number of characters in the string to log, which may
1095 * or may not be the entire string.
1063 */ 1096 */
1064const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string) 1097const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len,
1098 const char *string)
1065{ 1099{
1066 const unsigned char *p = string; 1100 const unsigned char *p = string;
1067 size_t len = strlen(string);
1068 1101
1069 while (*p) { 1102 while (*p) {
1070 if (*p == '"' || *p < 0x21 || *p > 0x7f) { 1103 if (*p == '"' || *p < 0x21 || *p > 0x7f) {
@@ -1073,10 +1106,23 @@ const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *strin
1073 } 1106 }
1074 p++; 1107 p++;
1075 } 1108 }
1076 audit_log_format(ab, "\"%s\"", string); 1109 audit_log_n_string(ab, len, string);
1077 return p + 1; 1110 return p + 1;
1078} 1111}
1079 1112
1113/**
1114 * audit_log_unstrustedstring - log a string that may contain random characters
1115 * @ab: audit_buffer
1116 * @string: string to be logged
1117 *
1118 * Same as audit_log_n_unstrustedstring(), except that strlen is used to
1119 * determine string length.
1120 */
1121const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
1122{
1123 return audit_log_n_untrustedstring(ab, strlen(string), string);
1124}
1125
1080/* This is a helper-function to print the escaped d_path */ 1126/* This is a helper-function to print the escaped d_path */
1081void audit_log_d_path(struct audit_buffer *ab, const char *prefix, 1127void audit_log_d_path(struct audit_buffer *ab, const char *prefix,
1082 struct dentry *dentry, struct vfsmount *vfsmnt) 1128 struct dentry *dentry, struct vfsmount *vfsmnt)
diff --git a/kernel/audit.h b/kernel/audit.h
index 58fa44cb8d01..8323e4132a33 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -104,7 +104,8 @@ static inline int audit_hash_ino(u32 ino)
104} 104}
105 105
106extern int audit_comparator(const u32 left, const u32 op, const u32 right); 106extern int audit_comparator(const u32 left, const u32 op, const u32 right);
107extern int audit_compare_dname_path(const char *dname, const char *path); 107extern int audit_compare_dname_path(const char *dname, const char *path,
108 int *dirlen);
108extern struct sk_buff * audit_make_reply(int pid, int seq, int type, 109extern struct sk_buff * audit_make_reply(int pid, int seq, int type,
109 int done, int multi, 110 int done, int multi,
110 void *payload, int size); 111 void *payload, int size);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index a536f7148bcd..4c99d2c586ed 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -787,7 +787,7 @@ static void audit_update_watch(struct audit_parent *parent,
787 787
788 mutex_lock(&audit_filter_mutex); 788 mutex_lock(&audit_filter_mutex);
789 list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) { 789 list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) {
790 if (audit_compare_dname_path(dname, owatch->path)) 790 if (audit_compare_dname_path(dname, owatch->path, NULL))
791 continue; 791 continue;
792 792
793 /* If the update involves invalidating rules, do the inode-based 793 /* If the update involves invalidating rules, do the inode-based
@@ -1387,7 +1387,8 @@ int audit_comparator(const u32 left, const u32 op, const u32 right)
1387 1387
1388/* Compare given dentry name with last component in given path, 1388/* Compare given dentry name with last component in given path,
1389 * return of 0 indicates a match. */ 1389 * return of 0 indicates a match. */
1390int audit_compare_dname_path(const char *dname, const char *path) 1390int audit_compare_dname_path(const char *dname, const char *path,
1391 int *dirlen)
1391{ 1392{
1392 int dlen, plen; 1393 int dlen, plen;
1393 const char *p; 1394 const char *p;
@@ -1416,6 +1417,9 @@ int audit_compare_dname_path(const char *dname, const char *path)
1416 p++; 1417 p++;
1417 } 1418 }
1418 1419
1420 /* return length of path's directory component */
1421 if (dirlen)
1422 *dirlen = p - path;
1419 return strncmp(p, dname, dlen); 1423 return strncmp(p, dname, dlen);
1420} 1424}
1421 1425
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 174a3f624892..851ae0217e4b 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -82,6 +82,9 @@ extern int audit_enabled;
82 * path_lookup. */ 82 * path_lookup. */
83#define AUDIT_NAMES_RESERVED 7 83#define AUDIT_NAMES_RESERVED 7
84 84
85/* Indicates that audit should log the full pathname. */
86#define AUDIT_NAME_FULL -1
87
85/* When fs/namei.c:getname() is called, we store the pointer in name and 88/* When fs/namei.c:getname() is called, we store the pointer in name and
86 * we don't let putname() free it (instead we free all of the saved 89 * we don't let putname() free it (instead we free all of the saved
87 * pointers at syscall exit time). 90 * pointers at syscall exit time).
@@ -89,8 +92,9 @@ extern int audit_enabled;
89 * Further, in fs/namei.c:path_lookup() we store the inode and device. */ 92 * Further, in fs/namei.c:path_lookup() we store the inode and device. */
90struct audit_names { 93struct audit_names {
91 const char *name; 94 const char *name;
95 int name_len; /* number of name's characters to log */
96 unsigned name_put; /* call __putname() for this name */
92 unsigned long ino; 97 unsigned long ino;
93 unsigned long pino;
94 dev_t dev; 98 dev_t dev;
95 umode_t mode; 99 umode_t mode;
96 uid_t uid; 100 uid_t uid;
@@ -296,12 +300,10 @@ static int audit_filter_rules(struct task_struct *tsk,
296 break; 300 break;
297 case AUDIT_INODE: 301 case AUDIT_INODE:
298 if (name) 302 if (name)
299 result = (name->ino == f->val || 303 result = (name->ino == f->val);
300 name->pino == f->val);
301 else if (ctx) { 304 else if (ctx) {
302 for (j = 0; j < ctx->name_count; j++) { 305 for (j = 0; j < ctx->name_count; j++) {
303 if (audit_comparator(ctx->names[j].ino, f->op, f->val) || 306 if (audit_comparator(ctx->names[j].ino, f->op, f->val)) {
304 audit_comparator(ctx->names[j].pino, f->op, f->val)) {
305 ++result; 307 ++result;
306 break; 308 break;
307 } 309 }
@@ -311,8 +313,7 @@ static int audit_filter_rules(struct task_struct *tsk,
311 case AUDIT_WATCH: 313 case AUDIT_WATCH:
312 if (name && rule->watch->ino != (unsigned long)-1) 314 if (name && rule->watch->ino != (unsigned long)-1)
313 result = (name->dev == rule->watch->dev && 315 result = (name->dev == rule->watch->dev &&
314 (name->ino == rule->watch->ino || 316 name->ino == rule->watch->ino);
315 name->pino == rule->watch->ino));
316 break; 317 break;
317 case AUDIT_LOGINUID: 318 case AUDIT_LOGINUID:
318 result = 0; 319 result = 0;
@@ -526,7 +527,7 @@ static inline void audit_free_names(struct audit_context *context)
526#endif 527#endif
527 528
528 for (i = 0; i < context->name_count; i++) { 529 for (i = 0; i < context->name_count; i++) {
529 if (context->names[i].name) 530 if (context->names[i].name && context->names[i].name_put)
530 __putname(context->names[i].name); 531 __putname(context->names[i].name);
531 } 532 }
532 context->name_count = 0; 533 context->name_count = 0;
@@ -850,8 +851,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
850 } 851 }
851 } 852 }
852 for (i = 0; i < context->name_count; i++) { 853 for (i = 0; i < context->name_count; i++) {
853 unsigned long ino = context->names[i].ino; 854 struct audit_names *n = &context->names[i];
854 unsigned long pino = context->names[i].pino;
855 855
856 ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH); 856 ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
857 if (!ab) 857 if (!ab)
@@ -859,33 +859,47 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
859 859
860 audit_log_format(ab, "item=%d", i); 860 audit_log_format(ab, "item=%d", i);
861 861
862 audit_log_format(ab, " name="); 862 if (n->name) {
863 if (context->names[i].name) 863 switch(n->name_len) {
864 audit_log_untrustedstring(ab, context->names[i].name); 864 case AUDIT_NAME_FULL:
865 else 865 /* log the full path */
866 audit_log_format(ab, "(null)"); 866 audit_log_format(ab, " name=");
867 867 audit_log_untrustedstring(ab, n->name);
868 if (pino != (unsigned long)-1) 868 break;
869 audit_log_format(ab, " parent=%lu", pino); 869 case 0:
870 if (ino != (unsigned long)-1) 870 /* name was specified as a relative path and the
871 audit_log_format(ab, " inode=%lu", ino); 871 * directory component is the cwd */
872 if ((pino != (unsigned long)-1) || (ino != (unsigned long)-1)) 872 audit_log_d_path(ab, " name=", context->pwd,
873 audit_log_format(ab, " dev=%02x:%02x mode=%#o" 873 context->pwdmnt);
874 " ouid=%u ogid=%u rdev=%02x:%02x", 874 break;
875 MAJOR(context->names[i].dev), 875 default:
876 MINOR(context->names[i].dev), 876 /* log the name's directory component */
877 context->names[i].mode, 877 audit_log_format(ab, " name=");
878 context->names[i].uid, 878 audit_log_n_untrustedstring(ab, n->name_len,
879 context->names[i].gid, 879 n->name);
880 MAJOR(context->names[i].rdev), 880 }
881 MINOR(context->names[i].rdev)); 881 } else
882 if (context->names[i].osid != 0) { 882 audit_log_format(ab, " name=(null)");
883
884 if (n->ino != (unsigned long)-1) {
885 audit_log_format(ab, " inode=%lu"
886 " dev=%02x:%02x mode=%#o"
887 " ouid=%u ogid=%u rdev=%02x:%02x",
888 n->ino,
889 MAJOR(n->dev),
890 MINOR(n->dev),
891 n->mode,
892 n->uid,
893 n->gid,
894 MAJOR(n->rdev),
895 MINOR(n->rdev));
896 }
897 if (n->osid != 0) {
883 char *ctx = NULL; 898 char *ctx = NULL;
884 u32 len; 899 u32 len;
885 if (selinux_ctxid_to_string( 900 if (selinux_ctxid_to_string(
886 context->names[i].osid, &ctx, &len)) { 901 n->osid, &ctx, &len)) {
887 audit_log_format(ab, " osid=%u", 902 audit_log_format(ab, " osid=%u", n->osid);
888 context->names[i].osid);
889 call_panic = 2; 903 call_panic = 2;
890 } else 904 } else
891 audit_log_format(ab, " obj=%s", ctx); 905 audit_log_format(ab, " obj=%s", ctx);
@@ -1075,6 +1089,8 @@ void __audit_getname(const char *name)
1075 } 1089 }
1076 BUG_ON(context->name_count >= AUDIT_NAMES); 1090 BUG_ON(context->name_count >= AUDIT_NAMES);
1077 context->names[context->name_count].name = name; 1091 context->names[context->name_count].name = name;
1092 context->names[context->name_count].name_len = AUDIT_NAME_FULL;
1093 context->names[context->name_count].name_put = 1;
1078 context->names[context->name_count].ino = (unsigned long)-1; 1094 context->names[context->name_count].ino = (unsigned long)-1;
1079 ++context->name_count; 1095 ++context->name_count;
1080 if (!context->pwd) { 1096 if (!context->pwd) {
@@ -1141,11 +1157,10 @@ static void audit_inode_context(int idx, const struct inode *inode)
1141 * audit_inode - store the inode and device from a lookup 1157 * audit_inode - store the inode and device from a lookup
1142 * @name: name being audited 1158 * @name: name being audited
1143 * @inode: inode being audited 1159 * @inode: inode being audited
1144 * @flags: lookup flags (as used in path_lookup())
1145 * 1160 *
1146 * Called from fs/namei.c:path_lookup(). 1161 * Called from fs/namei.c:path_lookup().
1147 */ 1162 */
1148void __audit_inode(const char *name, const struct inode *inode, unsigned flags) 1163void __audit_inode(const char *name, const struct inode *inode)
1149{ 1164{
1150 int idx; 1165 int idx;
1151 struct audit_context *context = current->audit_context; 1166 struct audit_context *context = current->audit_context;
@@ -1171,20 +1186,13 @@ void __audit_inode(const char *name, const struct inode *inode, unsigned flags)
1171 ++context->ino_count; 1186 ++context->ino_count;
1172#endif 1187#endif
1173 } 1188 }
1189 context->names[idx].ino = inode->i_ino;
1174 context->names[idx].dev = inode->i_sb->s_dev; 1190 context->names[idx].dev = inode->i_sb->s_dev;
1175 context->names[idx].mode = inode->i_mode; 1191 context->names[idx].mode = inode->i_mode;
1176 context->names[idx].uid = inode->i_uid; 1192 context->names[idx].uid = inode->i_uid;
1177 context->names[idx].gid = inode->i_gid; 1193 context->names[idx].gid = inode->i_gid;
1178 context->names[idx].rdev = inode->i_rdev; 1194 context->names[idx].rdev = inode->i_rdev;
1179 audit_inode_context(idx, inode); 1195 audit_inode_context(idx, inode);
1180 if ((flags & LOOKUP_PARENT) && (strcmp(name, "/") != 0) &&
1181 (strcmp(name, ".") != 0)) {
1182 context->names[idx].ino = (unsigned long)-1;
1183 context->names[idx].pino = inode->i_ino;
1184 } else {
1185 context->names[idx].ino = inode->i_ino;
1186 context->names[idx].pino = (unsigned long)-1;
1187 }
1188} 1196}
1189 1197
1190/** 1198/**
@@ -1206,34 +1214,40 @@ void __audit_inode_child(const char *dname, const struct inode *inode,
1206{ 1214{
1207 int idx; 1215 int idx;
1208 struct audit_context *context = current->audit_context; 1216 struct audit_context *context = current->audit_context;
1217 const char *found_name = NULL;
1218 int dirlen = 0;
1209 1219
1210 if (!context->in_syscall) 1220 if (!context->in_syscall)
1211 return; 1221 return;
1212 1222
1213 /* determine matching parent */ 1223 /* determine matching parent */
1214 if (!dname) 1224 if (!dname)
1215 goto no_match; 1225 goto update_context;
1216 for (idx = 0; idx < context->name_count; idx++) 1226 for (idx = 0; idx < context->name_count; idx++)
1217 if (context->names[idx].pino == pino) { 1227 if (context->names[idx].ino == pino) {
1218 const char *name = context->names[idx].name; 1228 const char *name = context->names[idx].name;
1219 1229
1220 if (!name) 1230 if (!name)
1221 continue; 1231 continue;
1222 1232
1223 if (audit_compare_dname_path(dname, name) == 0) 1233 if (audit_compare_dname_path(dname, name, &dirlen) == 0) {
1224 goto update_context; 1234 context->names[idx].name_len = dirlen;
1235 found_name = name;
1236 break;
1237 }
1225 } 1238 }
1226 1239
1227no_match: 1240update_context:
1228 /* catch-all in case match not found */
1229 idx = context->name_count++; 1241 idx = context->name_count++;
1230 context->names[idx].name = NULL;
1231 context->names[idx].pino = pino;
1232#if AUDIT_DEBUG 1242#if AUDIT_DEBUG
1233 context->ino_count++; 1243 context->ino_count++;
1234#endif 1244#endif
1245 /* Re-use the name belonging to the slot for a matching parent directory.
1246 * All names for this context are relinquished in audit_free_names() */
1247 context->names[idx].name = found_name;
1248 context->names[idx].name_len = AUDIT_NAME_FULL;
1249 context->names[idx].name_put = 0; /* don't call __putname() */
1235 1250
1236update_context:
1237 if (inode) { 1251 if (inode) {
1238 context->names[idx].ino = inode->i_ino; 1252 context->names[idx].ino = inode->i_ino;
1239 context->names[idx].dev = inode->i_sb->s_dev; 1253 context->names[idx].dev = inode->i_sb->s_dev;
@@ -1242,7 +1256,8 @@ update_context:
1242 context->names[idx].gid = inode->i_gid; 1256 context->names[idx].gid = inode->i_gid;
1243 context->names[idx].rdev = inode->i_rdev; 1257 context->names[idx].rdev = inode->i_rdev;
1244 audit_inode_context(idx, inode); 1258 audit_inode_context(idx, inode);
1245 } 1259 } else
1260 context->names[idx].ino = (unsigned long)-1;
1246} 1261}
1247 1262
1248/** 1263/**