diff options
author | Jeff Layton <jlayton@redhat.com> | 2012-10-10 15:25:23 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-12 00:32:01 -0400 |
commit | bfcec7087458812f575d9022b2d151641f34ee84 (patch) | |
tree | 6c0f7dd3b016992da8d113ceeaae404c6abc03a1 /kernel/auditsc.c | |
parent | 78e2e802a8519031e5858595070b39713e26340d (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.c | 41 |
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 | */ |
2144 | void __audit_inode(const char *name, const struct dentry *dentry) | 2143 | void __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 | ||
2161 | out_alloc: | 2172 | out_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; |
2166 | out: | 2179 | out: |
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 |