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

Unified · Split

5 files
  1. fs/btrfs/ioctl.c +1 −1
  2. fs/namei.c +1 −1
  3. include/linux/audit.h +11 −5
  4. include/linux/fsnotify.h +4 −4
  5. kernel/auditsc.c +30 −27
fs/btrfs/ioctl.c+1−1
@@ -638,7 +638,7 @@ static int btrfs_may_delete(struct inode *dir,struct dentry *victim,int isdir) · 637 unmodified lines
638638 return -ENOENT;
639639
640640 BUG_ON(victim->d_parent->d_inode != dir);
641− audit_inode_child(dir, victim);
641+ audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
642642
643643 error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
644644 if (error)
fs/namei.c+1−1
@@ -2176,7 +2176,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir) · 2175 unmodified lines
21762176 return -ENOENT;
21772177
21782178 BUG_ON(victim->d_parent->d_inode != dir);
2179− audit_inode_child(dir, victim);
2179+ audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
21802180
21812181 error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
21822182 if (error)
include/linux/audit.h+11−5
@@ -457,6 +457,8 @@ extern int audit_classify_arch(int arch); · 456 unmodified lines
457457 #define AUDIT_TYPE_UNKNOWN 0 /* we don't know yet */
458458 #define AUDIT_TYPE_NORMAL 1 /* a "normal" audit record */
459459 #define AUDIT_TYPE_PARENT 2 /* a parent audit record */
460+#define AUDIT_TYPE_CHILD_DELETE 3 /* a child being deleted */
461+#define AUDIT_TYPE_CHILD_CREATE 4 /* a child being created */
460462
461463 #ifdef CONFIG_AUDITSYSCALL
462464 /* These are defined in auditsc.c */
@@ -472,7 +474,8 @@ extern void audit_putname(const char *name); · 9 unmodified lines
472474 extern void __audit_inode(const char *name, const struct dentry *dentry,
473475 unsigned int parent);
474476 extern void __audit_inode_child(const struct inode *parent,
475− const struct dentry *dentry);
477+ const struct dentry *dentry,
478+ const unsigned char type);
476479 extern void __audit_seccomp(unsigned long syscall, long signr, int code);
477480 extern void __audit_ptrace(struct task_struct *t);
478481
@@ -513,9 +516,10 @@ static inline void audit_inode(const char *name, const struct dentry *dentry, · 34 unmodified lines
513516 __audit_inode(name, dentry, parent);
514517 }
515518 static inline void audit_inode_child(const struct inode *parent,
516− const struct dentry *dentry) {
519+ const struct dentry *dentry,
520+ const unsigned char type) {
517521 if (unlikely(!audit_dummy_context()))
518− __audit_inode_child(parent, dentry);
522+ __audit_inode_child(parent, dentry, type);
519523 }
520524 void audit_core_dumps(long signr);
521525
@@ -667,13 +671,15 @@ static inline void __audit_inode(const char *name, const struct dentry *dentry, · 145 unmodified lines
667671 unsigned int parent)
668672 { }
669673 static inline void __audit_inode_child(const struct inode *parent,
670− const struct dentry *dentry)
674+ const struct dentry *dentry,
675+ const unsigned char type)
671676 { }
672677 static inline void audit_inode(const char *name, const struct dentry *dentry,
673678 unsigned int parent)
674679 { }
675680 static inline void audit_inode_child(const struct inode *parent,
676− const struct dentry *dentry)
681+ const struct dentry *dentry,
682+ const unsigned char type)
677683 { }
678684 static inline void audit_core_dumps(long signr)
679685 { }
include/linux/fsnotify.h+4−4
@@ -109,7 +109,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, · 108 unmodified lines
109109
110110 if (source)
111111 fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0);
112− audit_inode_child(new_dir, moved);
112+ audit_inode_child(new_dir, moved, AUDIT_TYPE_CHILD_CREATE);
113113 }
114114
115115 /*
@@ -155,7 +155,7 @@ static inline void fsnotify_inoderemove(struct inode *inode) · 39 unmodified lines
155155 */
156156 static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
157157 {
158− audit_inode_child(inode, dentry);
158+ audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
159159
160160 fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
161161 }
@@ -168,7 +168,7 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry) · 6 unmodified lines
168168 static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry)
169169 {
170170 fsnotify_link_count(inode);
171− audit_inode_child(dir, new_dentry);
171+ audit_inode_child(dir, new_dentry, AUDIT_TYPE_CHILD_CREATE);
172172
173173 fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name, 0);
174174 }
@@ -181,7 +181,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) · 6 unmodified lines
181181 __u32 mask = (FS_CREATE | FS_ISDIR);
182182 struct inode *d_inode = dentry->d_inode;
183183
184− audit_inode_child(inode, dentry);
184+ audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
185185
186186 fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
187187 }
kernel/auditsc.c+30−27
@@ -2189,6 +2189,7 @@ out: · 2188 unmodified lines
21892189 * __audit_inode_child - collect inode info for created/removed objects
21902190 * @parent: inode of dentry parent
21912191 * @dentry: dentry being audited
2192+ * @type: AUDIT_TYPE_* value that we're looking for
21922193 *
21932194 * For syscalls that create or remove filesystem objects, audit_inode
21942195 * can only collect information for the filesystem object's parent.
@@ -2199,13 +2200,13 @@ out: · 4 unmodified lines
21992200 * unsuccessful attempts.
22002201 */
22012202 void __audit_inode_child(const struct inode *parent,
2202− const struct dentry *dentry)
2203+ const struct dentry *dentry,
2204+ const unsigned char type)
22032205 {
22042206 struct audit_context *context = current->audit_context;
2205− const char *found_parent = NULL, *found_child = NULL;
22062207 const struct inode *inode = dentry->d_inode;
22072208 const char *dname = dentry->d_name.name;
2208− struct audit_names *n;
2209+ struct audit_names *n, *found_parent = NULL, *found_child = NULL;
22092210
22102211 if (!context->in_syscall)
22112212 return;
@@ -2213,63 +2214,65 @@ void __audit_inode_child(const struct inode *parent, · 1 unmodified line
22132214 if (inode)
22142215 handle_one(inode);
22152216
2216− /* parent is more likely, look for it first */
2217+ /* look for a parent entry first */
22172218 list_for_each_entry(n, &context->names_list, list) {
2218− if (!n->name)
2219+ if (!n->name || n->type != AUDIT_TYPE_PARENT)
22192220 continue;
22202221
22212222 if (n->ino == parent->i_ino &&
22222223 !audit_compare_dname_path(dname, n->name, n->name_len)) {
2223− found_parent = n->name;
2224− goto add_names;
2224+ found_parent = n;
2225+ break;
22252226 }
22262227 }
22272228
2228− /* no matching parent, look for matching child */
2229+ /* is there a matching child entry? */
22292230 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))
22312237 continue;
22322238
2233− /* strcmp() is the more likely scenario */
22342239 if (!strcmp(dname, n->name) ||
22352240 !audit_compare_dname_path(dname, n->name,
2241+ found_parent ?
2242+ found_parent->name_len :
22362243 AUDIT_NAME_FULL)) {
2237− if (inode)
2238− audit_copy_inode(n, dentry, inode);
2239− else
2240− n->ino = (unsigned long)-1;
2241− n->type = AUDIT_TYPE_NORMAL;
2242− found_child = n->name;
2243− goto add_names;
2244+ found_child = n;
2245+ break;
22442246 }
22452247 }
22462248
2247−add_names:
22482249 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);
22502252 if (!n)
22512253 return;
22522254 audit_copy_inode(n, NULL, parent);
22532255 }
22542256
22552257 if (!found_child) {
2256− n = audit_alloc_name(context, AUDIT_TYPE_NORMAL);
2257− if (!n)
2258+ found_child = audit_alloc_name(context, type);
2259+ if (!found_child)
22582260 return;
22592261
22602262 /* Re-use the name belonging to the slot for a matching parent
22612263 * directory. All names for this context are relinquished in
22622264 * audit_free_names() */
22632265 if (found_parent) {
2264− n->name = found_parent;
2265− n->name_len = AUDIT_NAME_FULL;
2266+ found_child->name = found_parent->name;
2267+ found_child->name_len = AUDIT_NAME_FULL;
22662268 /* don't call __putname() */
2267− n->name_put = false;
2269+ found_child->name_put = false;
22682270 }
2269−
2270− if (inode)
2271− audit_copy_inode(n, dentry, inode);
22722271 }
2272+ if (inode)
2273+ audit_copy_inode(found_child, dentry, inode);
2274+ else
2275+ found_child->ino = (unsigned long)-1;
22732276 }
22742277 EXPORT_SYMBOL_GPL(__audit_inode_child);
22752278