summaryrefslogtreecommitdiffstats
path: root/kernel/auditsc.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2012-10-10 15:25:23 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-10-12 00:32:01 -0400
commitbfcec7087458812f575d9022b2d151641f34ee84 (patch)
tree6c0f7dd3b016992da8d113ceeaae404c6abc03a1 /kernel/auditsc.c
parent78e2e802a8519031e5858595070b39713e26340d (diff)
audit: set the name_len in audit_inode for parent lookups
Currently, this gets set mostly by happenstance when we call into audit_inode_child. While that might be a little more efficient, it seems wrong. If the syscall ends up failing before audit_inode_child ever gets called, then you'll have an audit_names record that shows the full path but has the parent inode info attached. Fix this by passing in a parent flag when we call audit_inode that gets set to the value of LOOKUP_PARENT. We can then fix up the pathname for the audit entry correctly from the get-go. While we're at it, clean up the no-op macro for audit_inode in the !CONFIG_AUDITSYSCALL case. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel/auditsc.c')
-rw-r--r--kernel/auditsc.c41
1 files changed, 29 insertions, 12 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 19b232f86d70..b87b28947acc 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2135,13 +2135,13 @@ static void audit_copy_inode(struct audit_names *name, const struct dentry *dent
2135} 2135}
2136 2136
2137/** 2137/**
2138 * audit_inode - store the inode and device from a lookup 2138 * __audit_inode - store the inode and device from a lookup
2139 * @name: name being audited 2139 * @name: name being audited
2140 * @dentry: dentry being audited 2140 * @dentry: dentry being audited
2141 * 2141 * @parent: does this dentry represent the parent?
2142 * Called from fs/namei.c:path_lookup().
2143 */ 2142 */
2144void __audit_inode(const char *name, const struct dentry *dentry) 2143void __audit_inode(const char *name, const struct dentry *dentry,
2144 unsigned int parent)
2145{ 2145{
2146 struct audit_context *context = current->audit_context; 2146 struct audit_context *context = current->audit_context;
2147 const struct inode *inode = dentry->d_inode; 2147 const struct inode *inode = dentry->d_inode;
@@ -2154,19 +2154,38 @@ void __audit_inode(const char *name, const struct dentry *dentry)
2154 goto out_alloc; 2154 goto out_alloc;
2155 2155
2156 list_for_each_entry_reverse(n, &context->names_list, list) { 2156 list_for_each_entry_reverse(n, &context->names_list, list) {
2157 if (n->name == name) 2157 /* does the name pointer match? */
2158 goto out; 2158 if (n->name != name)
2159 continue;
2160
2161 /* match the correct record type */
2162 if (parent) {
2163 if (n->type == AUDIT_TYPE_PARENT ||
2164 n->type == AUDIT_TYPE_UNKNOWN)
2165 goto out;
2166 } else {
2167 if (n->type != AUDIT_TYPE_PARENT)
2168 goto out;
2169 }
2159 } 2170 }
2160 2171
2161out_alloc: 2172out_alloc:
2162 /* unable to find the name from a previous getname() */ 2173 /* unable to find the name from a previous getname(). Allocate a new
2174 * anonymous entry.
2175 */
2163 n = audit_alloc_name(context, AUDIT_TYPE_NORMAL); 2176 n = audit_alloc_name(context, AUDIT_TYPE_NORMAL);
2164 if (!n) 2177 if (!n)
2165 return; 2178 return;
2166out: 2179out:
2180 if (parent) {
2181 n->name_len = n->name ? parent_len(n->name) : AUDIT_NAME_FULL;
2182 n->type = AUDIT_TYPE_PARENT;
2183 } else {
2184 n->name_len = AUDIT_NAME_FULL;
2185 n->type = AUDIT_TYPE_NORMAL;
2186 }
2167 handle_path(dentry); 2187 handle_path(dentry);
2168 audit_copy_inode(n, dentry, inode); 2188 audit_copy_inode(n, dentry, inode);
2169 n->type = AUDIT_TYPE_NORMAL;
2170} 2189}
2171 2190
2172/** 2191/**
@@ -2190,7 +2209,6 @@ void __audit_inode_child(const struct inode *parent,
2190 const struct inode *inode = dentry->d_inode; 2209 const struct inode *inode = dentry->d_inode;
2191 const char *dname = dentry->d_name.name; 2210 const char *dname = dentry->d_name.name;
2192 struct audit_names *n; 2211 struct audit_names *n;
2193 int dirlen = 0;
2194 2212
2195 if (!context->in_syscall) 2213 if (!context->in_syscall)
2196 return; 2214 return;
@@ -2204,8 +2222,7 @@ void __audit_inode_child(const struct inode *parent,
2204 continue; 2222 continue;
2205 2223
2206 if (n->ino == parent->i_ino && 2224 if (n->ino == parent->i_ino &&
2207 !audit_compare_dname_path(dname, n->name, &dirlen)) { 2225 !audit_compare_dname_path(dname, n->name, NULL)) {
2208 n->name_len = dirlen; /* update parent data in place */
2209 found_parent = n->name; 2226 found_parent = n->name;
2210 goto add_names; 2227 goto add_names;
2211 } 2228 }
@@ -2218,7 +2235,7 @@ void __audit_inode_child(const struct inode *parent,
2218 2235
2219 /* strcmp() is the more likely scenario */ 2236 /* strcmp() is the more likely scenario */
2220 if (!strcmp(dname, n->name) || 2237 if (!strcmp(dname, n->name) ||
2221 !audit_compare_dname_path(dname, n->name, &dirlen)) { 2238 !audit_compare_dname_path(dname, n->name, NULL)) {
2222 if (inode) 2239 if (inode)
2223 audit_copy_inode(n, dentry, inode); 2240 audit_copy_inode(n, dentry, inode);
2224 else 2241 else