History

audit: overhaul __audit_inode_child to accomodate retrying

In order to accomodate retrying path-based syscalls, we need to add a new "type" argument to audit_inode_child. This will tell us whether we're looking for a child entry that represents a create or a delete. If we find a parent, don't automatically assume that we need to create a new entry. Instead, use the information we have to try to find an existing entry first. Update it if one is found and create a new one if not.

Jeff Layton committed 14 years ago

Commit 4fa6b5e1 parent e3d6b075 files · +47 −38Browse files

Showing the changes to kernel (1 of 5 files). Show all

Unified · Split

kernel/auditsc.c+30−27
@@ -2189,6 +2189,7 @@ out: · 2188 unmodified lines
2189 * __audit_inode_child - collect inode info for created/removed objects2189 * __audit_inode_child - collect inode info for created/removed objects
2190 * @parent: inode of dentry parent2190 * @parent: inode of dentry parent
2191 * @dentry: dentry being audited2191 * @dentry: dentry being audited
2192 * @type: AUDIT_TYPE_* value that we're looking for
2192 *2193 *
2193 * For syscalls that create or remove filesystem objects, audit_inode2194 * For syscalls that create or remove filesystem objects, audit_inode
2194 * can only collect information for the filesystem object's parent.2195 * can only collect information for the filesystem object's parent.
@@ -2199,13 +2200,13 @@ out: · 4 unmodified lines
2199 * unsuccessful attempts.2200 * unsuccessful attempts.
2200 */2201 */
2201void __audit_inode_child(const struct inode *parent,2202void __audit_inode_child(const struct inode *parent,
2202 const struct dentry *dentry)2203 const struct dentry *dentry,
2204 const unsigned char type)
2203{2205{
2204 struct audit_context *context = current->audit_context;2206 struct audit_context *context = current->audit_context;
2205 const char *found_parent = NULL, *found_child = NULL;
2206 const struct inode *inode = dentry->d_inode;2207 const struct inode *inode = dentry->d_inode;
2207 const char *dname = dentry->d_name.name;2208 const char *dname = dentry->d_name.name;
2208 struct audit_names *n;2209 struct audit_names *n, *found_parent = NULL, *found_child = NULL;
2209 2210
2210 if (!context->in_syscall)2211 if (!context->in_syscall)
2211 return;2212 return;
@@ -2213,63 +2214,65 @@ void __audit_inode_child(const struct inode *parent, · 1 unmodified line
2213 if (inode)2214 if (inode)
2214 handle_one(inode);2215 handle_one(inode);
2215 2216
2216 /* parent is more likely, look for it first */2217 /* look for a parent entry first */
2217 list_for_each_entry(n, &context->names_list, list) {2218 list_for_each_entry(n, &context->names_list, list) {
2218 if (!n->name)2219 if (!n->name || n->type != AUDIT_TYPE_PARENT)
2219 continue;2220 continue;
2220 2221
2221 if (n->ino == parent->i_ino &&2222 if (n->ino == parent->i_ino &&
2222 !audit_compare_dname_path(dname, n->name, n->name_len)) {2223 !audit_compare_dname_path(dname, n->name, n->name_len)) {
2223 found_parent = n->name;2224 found_parent = n;
2224 goto add_names;2225 break;
2225 }2226 }
2226 }2227 }
2227 2228
2228 /* no matching parent, look for matching child */2229 /* is there a matching child entry? */
2229 list_for_each_entry(n, &context->names_list, list) {2230 list_for_each_entry(n, &context->names_list, list) {
2230 if (!n->name)2231 /* can only match entries that have a name */
2232 if (!n->name || n->type != type)
2233 continue;
2234
2235 /* if we found a parent, make sure this one is a child of it */
2236 if (found_parent && (n->name != found_parent->name))
2231 continue;2237 continue;
2232 2238
2233 /* strcmp() is the more likely scenario */
2234 if (!strcmp(dname, n->name) ||2239 if (!strcmp(dname, n->name) ||
2235 !audit_compare_dname_path(dname, n->name,2240 !audit_compare_dname_path(dname, n->name,
2241 found_parent ?
2242 found_parent->name_len :
2236 AUDIT_NAME_FULL)) {2243 AUDIT_NAME_FULL)) {
2237 if (inode)2244 found_child = n;
2238 audit_copy_inode(n, dentry, inode);2245 break;
2239 else
2240 n->ino = (unsigned long)-1;
2241 n->type = AUDIT_TYPE_NORMAL;
2242 found_child = n->name;
2243 goto add_names;
2244 }2246 }
2245 }2247 }
2246 2248
2247add_names:
2248 if (!found_parent) {2249 if (!found_parent) {
2249 n = audit_alloc_name(context, AUDIT_TYPE_NORMAL);2250 /* create a new, "anonymous" parent record */
2251 n = audit_alloc_name(context, AUDIT_TYPE_PARENT);
2250 if (!n)2252 if (!n)
2251 return;2253 return;
2252 audit_copy_inode(n, NULL, parent);2254 audit_copy_inode(n, NULL, parent);
2253 }2255 }
2254 2256
2255 if (!found_child) {2257 if (!found_child) {
2256 n = audit_alloc_name(context, AUDIT_TYPE_NORMAL);2258 found_child = audit_alloc_name(context, type);
2257 if (!n)2259 if (!found_child)
2258 return;2260 return;
2259 2261
2260 /* Re-use the name belonging to the slot for a matching parent2262 /* Re-use the name belonging to the slot for a matching parent
2261 * directory. All names for this context are relinquished in2263 * directory. All names for this context are relinquished in
2262 * audit_free_names() */2264 * audit_free_names() */
2263 if (found_parent) {2265 if (found_parent) {
2264 n->name = found_parent;2266 found_child->name = found_parent->name;
2265 n->name_len = AUDIT_NAME_FULL;2267 found_child->name_len = AUDIT_NAME_FULL;
2266 /* don't call __putname() */2268 /* don't call __putname() */
2267 n->name_put = false;2269 found_child->name_put = false;
2268 }2270 }
2269
2270 if (inode)
2271 audit_copy_inode(n, dentry, inode);
2272 }2271 }
2272 if (inode)
2273 audit_copy_inode(found_child, dentry, inode);
2274 else
2275 found_child->ino = (unsigned long)-1;
2273}2276}
2274EXPORT_SYMBOL_GPL(__audit_inode_child);2277EXPORT_SYMBOL_GPL(__audit_inode_child);
2275 2278