Blame view
kernel/audit_fsnotify.c
5.22 KB
c942fddf8 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
7f4929428 audit: clean simp... |
2 3 4 5 6 |
/* audit_fsnotify.c -- tracking inodes * * Copyright 2003-2009,2014-2015 Red Hat, Inc. * Copyright 2005 Hewlett-Packard Development Company, L.P. * Copyright 2005 IBM Corporation |
7f4929428 audit: clean simp... |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
*/ #include <linux/kernel.h> #include <linux/audit.h> #include <linux/kthread.h> #include <linux/mutex.h> #include <linux/fs.h> #include <linux/fsnotify_backend.h> #include <linux/namei.h> #include <linux/netlink.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/security.h> #include "audit.h" /* * this mark lives on the parent directory of the inode in question. * but dev, ino, and path are about the child */ struct audit_fsnotify_mark { dev_t dev; /* associated superblock device */ unsigned long ino; /* associated inode number */ char *path; /* insertion path */ struct fsnotify_mark mark; /* fsnotify mark on the inode */ struct audit_krule *rule; }; /* fsnotify handle. */ static struct fsnotify_group *audit_fsnotify_group; /* fsnotify events we care about. */ #define AUDIT_FS_EVENTS (FS_MOVE | FS_CREATE | FS_DELETE | FS_DELETE_SELF |\ |
7dbe60801 audit: do not set... |
39 |
FS_MOVE_SELF) |
7f4929428 audit: clean simp... |
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
static void audit_fsnotify_mark_free(struct audit_fsnotify_mark *audit_mark) { kfree(audit_mark->path); kfree(audit_mark); } static void audit_fsnotify_free_mark(struct fsnotify_mark *mark) { struct audit_fsnotify_mark *audit_mark; audit_mark = container_of(mark, struct audit_fsnotify_mark, mark); audit_fsnotify_mark_free(audit_mark); } char *audit_mark_path(struct audit_fsnotify_mark *mark) { return mark->path; } int audit_mark_compare(struct audit_fsnotify_mark *mark, unsigned long ino, dev_t dev) { if (mark->ino == AUDIT_INO_UNSET) return 0; return (mark->ino == ino) && (mark->dev == dev); } static void audit_update_mark(struct audit_fsnotify_mark *audit_mark, |
3cd5eca8d fsnotify: constif... |
68 |
const struct inode *inode) |
7f4929428 audit: clean simp... |
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
{ audit_mark->dev = inode ? inode->i_sb->s_dev : AUDIT_DEV_UNSET; audit_mark->ino = inode ? inode->i_ino : AUDIT_INO_UNSET; } struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule, char *pathname, int len) { struct audit_fsnotify_mark *audit_mark; struct path path; struct dentry *dentry; struct inode *inode; int ret; if (pathname[0] != '/' || pathname[len-1] == '/') return ERR_PTR(-EINVAL); dentry = kern_path_locked(pathname, &path); if (IS_ERR(dentry)) return (void *)dentry; /* returning an error */ inode = path.dentry->d_inode; |
5955102c9 wrappers for ->i_... |
89 |
inode_unlock(inode); |
7f4929428 audit: clean simp... |
90 91 92 93 94 95 |
audit_mark = kzalloc(sizeof(*audit_mark), GFP_KERNEL); if (unlikely(!audit_mark)) { audit_mark = ERR_PTR(-ENOMEM); goto out; } |
054c636e5 fsnotify: Move ->... |
96 |
fsnotify_init_mark(&audit_mark->mark, audit_fsnotify_group); |
7f4929428 audit: clean simp... |
97 98 99 100 |
audit_mark->mark.mask = AUDIT_FS_EVENTS; audit_mark->path = pathname; audit_update_mark(audit_mark, dentry->d_inode); audit_mark->rule = krule; |
b249f5be6 fsnotify: add fsn... |
101 |
ret = fsnotify_add_inode_mark(&audit_mark->mark, inode, true); |
7f4929428 audit: clean simp... |
102 |
if (ret < 0) { |
7b1293234 fsnotify: Add gro... |
103 |
fsnotify_put_mark(&audit_mark->mark); |
7f4929428 audit: clean simp... |
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
audit_mark = ERR_PTR(ret); } out: dput(dentry); path_put(&path); return audit_mark; } static void audit_mark_log_rule_change(struct audit_fsnotify_mark *audit_mark, char *op) { struct audit_buffer *ab; struct audit_krule *rule = audit_mark->rule; if (!audit_enabled) return; |
626abcd13 audit: add syscal... |
119 |
ab = audit_log_start(audit_context(), GFP_NOFS, AUDIT_CONFIG_CHANGE); |
7f4929428 audit: clean simp... |
120 121 |
if (unlikely(!ab)) return; |
a2c97da11 audit: use sessio... |
122 |
audit_log_session_info(ab); |
d0a3f18a7 audit: minimize o... |
123 |
audit_log_format(ab, " op=%s path=", op); |
7f4929428 audit: clean simp... |
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
audit_log_untrustedstring(ab, audit_mark->path); audit_log_key(ab, rule->filterkey); audit_log_format(ab, " list=%d res=1", rule->listnr); audit_log_end(ab); } void audit_remove_mark(struct audit_fsnotify_mark *audit_mark) { fsnotify_destroy_mark(&audit_mark->mark, audit_fsnotify_group); fsnotify_put_mark(&audit_mark->mark); } void audit_remove_mark_rule(struct audit_krule *krule) { struct audit_fsnotify_mark *mark = krule->exe; audit_remove_mark(mark); } static void audit_autoremove_mark_rule(struct audit_fsnotify_mark *audit_mark) { struct audit_krule *rule = audit_mark->rule; struct audit_entry *entry = container_of(rule, struct audit_entry, rule); audit_mark_log_rule_change(audit_mark, "autoremove_rule"); audit_del_rule(entry); } /* Update mark data in audit rules based on fsnotify events. */ |
b9a1b9772 fsnotify: create ... |
153 154 |
static int audit_mark_handle_event(struct fsnotify_mark *inode_mark, u32 mask, struct inode *inode, struct inode *dir, |
c9be99c86 fsnotify: general... |
155 |
const struct qstr *dname, u32 cookie) |
7f4929428 audit: clean simp... |
156 157 |
{ struct audit_fsnotify_mark *audit_mark; |
7f4929428 audit: clean simp... |
158 159 |
audit_mark = container_of(inode_mark, struct audit_fsnotify_mark, mark); |
b9a1b9772 fsnotify: create ... |
160 161 |
if (WARN_ON_ONCE(inode_mark->group != audit_fsnotify_group) || WARN_ON_ONCE(!inode)) |
7f4929428 audit: clean simp... |
162 |
return 0; |
7f4929428 audit: clean simp... |
163 164 |
if (mask & (FS_CREATE|FS_MOVED_TO|FS_DELETE|FS_MOVED_FROM)) { |
795d673af audit_compare_dna... |
165 |
if (audit_compare_dname_path(dname, audit_mark->path, AUDIT_NAME_FULL)) |
7f4929428 audit: clean simp... |
166 167 |
return 0; audit_update_mark(audit_mark, inode); |
b9a1b9772 fsnotify: create ... |
168 |
} else if (mask & (FS_DELETE_SELF|FS_UNMOUNT|FS_MOVE_SELF)) { |
7f4929428 audit: clean simp... |
169 |
audit_autoremove_mark_rule(audit_mark); |
b9a1b9772 fsnotify: create ... |
170 |
} |
7f4929428 audit: clean simp... |
171 172 173 174 175 |
return 0; } static const struct fsnotify_ops audit_mark_fsnotify_ops = { |
b9a1b9772 fsnotify: create ... |
176 |
.handle_inode_event = audit_mark_handle_event, |
054c636e5 fsnotify: Move ->... |
177 |
.free_mark = audit_fsnotify_free_mark, |
7f4929428 audit: clean simp... |
178 179 180 181 182 183 184 185 186 187 188 189 |
}; static int __init audit_fsnotify_init(void) { audit_fsnotify_group = fsnotify_alloc_group(&audit_mark_fsnotify_ops); if (IS_ERR(audit_fsnotify_group)) { audit_fsnotify_group = NULL; audit_panic("cannot create audit fsnotify group"); } return 0; } device_initcall(audit_fsnotify_init); |