aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ioctl.c2
-rw-r--r--fs/namei.c2
-rw-r--r--include/linux/audit.h16
-rw-r--r--include/linux/fsnotify.h8
-rw-r--r--kernel/auditsc.c57
5 files changed, 47 insertions, 38 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 49f4d59ac2c7..61168805f175 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -638,7 +638,7 @@ static int btrfs_may_delete(struct inode *dir,struct dentry *victim,int isdir)
638 return -ENOENT; 638 return -ENOENT;
639 639
640 BUG_ON(victim->d_parent->d_inode != dir); 640 BUG_ON(victim->d_parent->d_inode != dir);
641 audit_inode_child(dir, victim); 641 audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
642 642
643 error = inode_permission(dir, MAY_WRITE | MAY_EXEC); 643 error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
644 if (error) 644 if (error)
diff --git a/fs/namei.c b/fs/namei.c
index 6a92d988573f..ca14d8432d3d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2176,7 +2176,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
2176 return -ENOENT; 2176 return -ENOENT;
2177 2177
2178 BUG_ON(victim->d_parent->d_inode != dir); 2178 BUG_ON(victim->d_parent->d_inode != dir);
2179 audit_inode_child(dir, victim); 2179 audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
2180 2180
2181 error = inode_permission(dir, MAY_WRITE | MAY_EXEC); 2181 error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
2182 if (error) 2182 if (error)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index b11f517dce04..3df643d1ac5b 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -457,6 +457,8 @@ extern int audit_classify_arch(int arch);
457#define AUDIT_TYPE_UNKNOWN 0 /* we don't know yet */ 457#define AUDIT_TYPE_UNKNOWN 0 /* we don't know yet */
458#define AUDIT_TYPE_NORMAL 1 /* a "normal" audit record */ 458#define AUDIT_TYPE_NORMAL 1 /* a "normal" audit record */
459#define AUDIT_TYPE_PARENT 2 /* a parent audit record */ 459#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 */
460 462
461#ifdef CONFIG_AUDITSYSCALL 463#ifdef CONFIG_AUDITSYSCALL
462/* These are defined in auditsc.c */ 464/* These are defined in auditsc.c */
@@ -472,7 +474,8 @@ extern void audit_putname(const char *name);
472extern void __audit_inode(const char *name, const struct dentry *dentry, 474extern void __audit_inode(const char *name, const struct dentry *dentry,
473 unsigned int parent); 475 unsigned int parent);
474extern void __audit_inode_child(const struct inode *parent, 476extern void __audit_inode_child(const struct inode *parent,
475 const struct dentry *dentry); 477 const struct dentry *dentry,
478 const unsigned char type);
476extern void __audit_seccomp(unsigned long syscall, long signr, int code); 479extern void __audit_seccomp(unsigned long syscall, long signr, int code);
477extern void __audit_ptrace(struct task_struct *t); 480extern void __audit_ptrace(struct task_struct *t);
478 481
@@ -513,9 +516,10 @@ static inline void audit_inode(const char *name, const struct dentry *dentry,
513 __audit_inode(name, dentry, parent); 516 __audit_inode(name, dentry, parent);
514} 517}
515static inline void audit_inode_child(const struct inode *parent, 518static inline void audit_inode_child(const struct inode *parent,
516 const struct dentry *dentry) { 519 const struct dentry *dentry,
520 const unsigned char type) {
517 if (unlikely(!audit_dummy_context())) 521 if (unlikely(!audit_dummy_context()))
518 __audit_inode_child(parent, dentry); 522 __audit_inode_child(parent, dentry, type);
519} 523}
520void audit_core_dumps(long signr); 524void audit_core_dumps(long signr);
521 525
@@ -667,13 +671,15 @@ static inline void __audit_inode(const char *name, const struct dentry *dentry,
667 unsigned int parent) 671 unsigned int parent)
668{ } 672{ }
669static inline void __audit_inode_child(const struct inode *parent, 673static inline void __audit_inode_child(const struct inode *parent,
670 const struct dentry *dentry) 674 const struct dentry *dentry,
675 const unsigned char type)
671{ } 676{ }
672static inline void audit_inode(const char *name, const struct dentry *dentry, 677static inline void audit_inode(const char *name, const struct dentry *dentry,
673 unsigned int parent) 678 unsigned int parent)
674{ } 679{ }
675static inline void audit_inode_child(const struct inode *parent, 680static inline void audit_inode_child(const struct inode *parent,
676 const struct dentry *dentry) 681 const struct dentry *dentry,
682 const unsigned char type)
677{ } 683{ }
678static inline void audit_core_dumps(long signr) 684static inline void audit_core_dumps(long signr)
679{ } 685{ }
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 9c284714977d..0fbfb4646d1b 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -109,7 +109,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
109 109
110 if (source) 110 if (source)
111 fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0); 111 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);
113} 113}
114 114
115/* 115/*
@@ -155,7 +155,7 @@ static inline void fsnotify_inoderemove(struct inode *inode)
155 */ 155 */
156static inline void fsnotify_create(struct inode *inode, struct dentry *dentry) 156static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
157{ 157{
158 audit_inode_child(inode, dentry); 158 audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
159 159
160 fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0); 160 fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
161} 161}
@@ -168,7 +168,7 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
168static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry) 168static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry)
169{ 169{
170 fsnotify_link_count(inode); 170 fsnotify_link_count(inode);
171 audit_inode_child(dir, new_dentry); 171 audit_inode_child(dir, new_dentry, AUDIT_TYPE_CHILD_CREATE);
172 172
173 fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name, 0); 173 fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name, 0);
174} 174}
@@ -181,7 +181,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
181 __u32 mask = (FS_CREATE | FS_ISDIR); 181 __u32 mask = (FS_CREATE | FS_ISDIR);
182 struct inode *d_inode = dentry->d_inode; 182 struct inode *d_inode = dentry->d_inode;
183 183
184 audit_inode_child(inode, dentry); 184 audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
185 185
186 fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0); 186 fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
187} 187}
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 0160a68b4d7f..d147585e9ef3 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2189,6 +2189,7 @@ out:
2189 * __audit_inode_child - collect inode info for created/removed objects 2189 * __audit_inode_child - collect inode info for created/removed objects
2190 * @parent: inode of dentry parent 2190 * @parent: inode of dentry parent
2191 * @dentry: dentry being audited 2191 * @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_inode 2194 * 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:
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,
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 parent 2262 /* Re-use the name belonging to the slot for a matching parent
2261 * directory. All names for this context are relinquished in 2263 * 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