cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

audit_watch.c (14022B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/* audit_watch.c -- watching inodes
      3 *
      4 * Copyright 2003-2009 Red Hat, Inc.
      5 * Copyright 2005 Hewlett-Packard Development Company, L.P.
      6 * Copyright 2005 IBM Corporation
      7 */
      8
      9#include <linux/file.h>
     10#include <linux/kernel.h>
     11#include <linux/audit.h>
     12#include <linux/kthread.h>
     13#include <linux/mutex.h>
     14#include <linux/fs.h>
     15#include <linux/fsnotify_backend.h>
     16#include <linux/namei.h>
     17#include <linux/netlink.h>
     18#include <linux/refcount.h>
     19#include <linux/sched.h>
     20#include <linux/slab.h>
     21#include <linux/security.h>
     22#include "audit.h"
     23
     24/*
     25 * Reference counting:
     26 *
     27 * audit_parent: lifetime is from audit_init_parent() to receipt of an FS_IGNORED
     28 * 	event.  Each audit_watch holds a reference to its associated parent.
     29 *
     30 * audit_watch: if added to lists, lifetime is from audit_init_watch() to
     31 * 	audit_remove_watch().  Additionally, an audit_watch may exist
     32 * 	temporarily to assist in searching existing filter data.  Each
     33 * 	audit_krule holds a reference to its associated watch.
     34 */
     35
     36struct audit_watch {
     37	refcount_t		count;	/* reference count */
     38	dev_t			dev;	/* associated superblock device */
     39	char			*path;	/* insertion path */
     40	unsigned long		ino;	/* associated inode number */
     41	struct audit_parent	*parent; /* associated parent */
     42	struct list_head	wlist;	/* entry in parent->watches list */
     43	struct list_head	rules;	/* anchor for krule->rlist */
     44};
     45
     46struct audit_parent {
     47	struct list_head	watches; /* anchor for audit_watch->wlist */
     48	struct fsnotify_mark mark; /* fsnotify mark on the inode */
     49};
     50
     51/* fsnotify handle. */
     52static struct fsnotify_group *audit_watch_group;
     53
     54/* fsnotify events we care about. */
     55#define AUDIT_FS_WATCH (FS_MOVE | FS_CREATE | FS_DELETE | FS_DELETE_SELF |\
     56			FS_MOVE_SELF | FS_UNMOUNT)
     57
     58static void audit_free_parent(struct audit_parent *parent)
     59{
     60	WARN_ON(!list_empty(&parent->watches));
     61	kfree(parent);
     62}
     63
     64static void audit_watch_free_mark(struct fsnotify_mark *entry)
     65{
     66	struct audit_parent *parent;
     67
     68	parent = container_of(entry, struct audit_parent, mark);
     69	audit_free_parent(parent);
     70}
     71
     72static void audit_get_parent(struct audit_parent *parent)
     73{
     74	if (likely(parent))
     75		fsnotify_get_mark(&parent->mark);
     76}
     77
     78static void audit_put_parent(struct audit_parent *parent)
     79{
     80	if (likely(parent))
     81		fsnotify_put_mark(&parent->mark);
     82}
     83
     84/*
     85 * Find and return the audit_parent on the given inode.  If found a reference
     86 * is taken on this parent.
     87 */
     88static inline struct audit_parent *audit_find_parent(struct inode *inode)
     89{
     90	struct audit_parent *parent = NULL;
     91	struct fsnotify_mark *entry;
     92
     93	entry = fsnotify_find_mark(&inode->i_fsnotify_marks, audit_watch_group);
     94	if (entry)
     95		parent = container_of(entry, struct audit_parent, mark);
     96
     97	return parent;
     98}
     99
    100void audit_get_watch(struct audit_watch *watch)
    101{
    102	refcount_inc(&watch->count);
    103}
    104
    105void audit_put_watch(struct audit_watch *watch)
    106{
    107	if (refcount_dec_and_test(&watch->count)) {
    108		WARN_ON(watch->parent);
    109		WARN_ON(!list_empty(&watch->rules));
    110		kfree(watch->path);
    111		kfree(watch);
    112	}
    113}
    114
    115static void audit_remove_watch(struct audit_watch *watch)
    116{
    117	list_del(&watch->wlist);
    118	audit_put_parent(watch->parent);
    119	watch->parent = NULL;
    120	audit_put_watch(watch); /* match initial get */
    121}
    122
    123char *audit_watch_path(struct audit_watch *watch)
    124{
    125	return watch->path;
    126}
    127
    128int audit_watch_compare(struct audit_watch *watch, unsigned long ino, dev_t dev)
    129{
    130	return (watch->ino != AUDIT_INO_UNSET) &&
    131		(watch->ino == ino) &&
    132		(watch->dev == dev);
    133}
    134
    135/* Initialize a parent watch entry. */
    136static struct audit_parent *audit_init_parent(struct path *path)
    137{
    138	struct inode *inode = d_backing_inode(path->dentry);
    139	struct audit_parent *parent;
    140	int ret;
    141
    142	parent = kzalloc(sizeof(*parent), GFP_KERNEL);
    143	if (unlikely(!parent))
    144		return ERR_PTR(-ENOMEM);
    145
    146	INIT_LIST_HEAD(&parent->watches);
    147
    148	fsnotify_init_mark(&parent->mark, audit_watch_group);
    149	parent->mark.mask = AUDIT_FS_WATCH;
    150	ret = fsnotify_add_inode_mark(&parent->mark, inode, 0);
    151	if (ret < 0) {
    152		audit_free_parent(parent);
    153		return ERR_PTR(ret);
    154	}
    155
    156	return parent;
    157}
    158
    159/* Initialize a watch entry. */
    160static struct audit_watch *audit_init_watch(char *path)
    161{
    162	struct audit_watch *watch;
    163
    164	watch = kzalloc(sizeof(*watch), GFP_KERNEL);
    165	if (unlikely(!watch))
    166		return ERR_PTR(-ENOMEM);
    167
    168	INIT_LIST_HEAD(&watch->rules);
    169	refcount_set(&watch->count, 1);
    170	watch->path = path;
    171	watch->dev = AUDIT_DEV_UNSET;
    172	watch->ino = AUDIT_INO_UNSET;
    173
    174	return watch;
    175}
    176
    177/* Translate a watch string to kernel representation. */
    178int audit_to_watch(struct audit_krule *krule, char *path, int len, u32 op)
    179{
    180	struct audit_watch *watch;
    181
    182	if (!audit_watch_group)
    183		return -EOPNOTSUPP;
    184
    185	if (path[0] != '/' || path[len-1] == '/' ||
    186	    (krule->listnr != AUDIT_FILTER_EXIT &&
    187	     krule->listnr != AUDIT_FILTER_URING_EXIT) ||
    188	    op != Audit_equal ||
    189	    krule->inode_f || krule->watch || krule->tree)
    190		return -EINVAL;
    191
    192	watch = audit_init_watch(path);
    193	if (IS_ERR(watch))
    194		return PTR_ERR(watch);
    195
    196	krule->watch = watch;
    197
    198	return 0;
    199}
    200
    201/* Duplicate the given audit watch.  The new watch's rules list is initialized
    202 * to an empty list and wlist is undefined. */
    203static struct audit_watch *audit_dupe_watch(struct audit_watch *old)
    204{
    205	char *path;
    206	struct audit_watch *new;
    207
    208	path = kstrdup(old->path, GFP_KERNEL);
    209	if (unlikely(!path))
    210		return ERR_PTR(-ENOMEM);
    211
    212	new = audit_init_watch(path);
    213	if (IS_ERR(new)) {
    214		kfree(path);
    215		goto out;
    216	}
    217
    218	new->dev = old->dev;
    219	new->ino = old->ino;
    220	audit_get_parent(old->parent);
    221	new->parent = old->parent;
    222
    223out:
    224	return new;
    225}
    226
    227static void audit_watch_log_rule_change(struct audit_krule *r, struct audit_watch *w, char *op)
    228{
    229	struct audit_buffer *ab;
    230
    231	if (!audit_enabled)
    232		return;
    233	ab = audit_log_start(audit_context(), GFP_NOFS, AUDIT_CONFIG_CHANGE);
    234	if (!ab)
    235		return;
    236	audit_log_session_info(ab);
    237	audit_log_format(ab, "op=%s path=", op);
    238	audit_log_untrustedstring(ab, w->path);
    239	audit_log_key(ab, r->filterkey);
    240	audit_log_format(ab, " list=%d res=1", r->listnr);
    241	audit_log_end(ab);
    242}
    243
    244/* Update inode info in audit rules based on filesystem event. */
    245static void audit_update_watch(struct audit_parent *parent,
    246			       const struct qstr *dname, dev_t dev,
    247			       unsigned long ino, unsigned invalidating)
    248{
    249	struct audit_watch *owatch, *nwatch, *nextw;
    250	struct audit_krule *r, *nextr;
    251	struct audit_entry *oentry, *nentry;
    252
    253	mutex_lock(&audit_filter_mutex);
    254	/* Run all of the watches on this parent looking for the one that
    255	 * matches the given dname */
    256	list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) {
    257		if (audit_compare_dname_path(dname, owatch->path,
    258					     AUDIT_NAME_FULL))
    259			continue;
    260
    261		/* If the update involves invalidating rules, do the inode-based
    262		 * filtering now, so we don't omit records. */
    263		if (invalidating && !audit_dummy_context())
    264			audit_filter_inodes(current, audit_context());
    265
    266		/* updating ino will likely change which audit_hash_list we
    267		 * are on so we need a new watch for the new list */
    268		nwatch = audit_dupe_watch(owatch);
    269		if (IS_ERR(nwatch)) {
    270			mutex_unlock(&audit_filter_mutex);
    271			audit_panic("error updating watch, skipping");
    272			return;
    273		}
    274		nwatch->dev = dev;
    275		nwatch->ino = ino;
    276
    277		list_for_each_entry_safe(r, nextr, &owatch->rules, rlist) {
    278
    279			oentry = container_of(r, struct audit_entry, rule);
    280			list_del(&oentry->rule.rlist);
    281			list_del_rcu(&oentry->list);
    282
    283			nentry = audit_dupe_rule(&oentry->rule);
    284			if (IS_ERR(nentry)) {
    285				list_del(&oentry->rule.list);
    286				audit_panic("error updating watch, removing");
    287			} else {
    288				int h = audit_hash_ino((u32)ino);
    289
    290				/*
    291				 * nentry->rule.watch == oentry->rule.watch so
    292				 * we must drop that reference and set it to our
    293				 * new watch.
    294				 */
    295				audit_put_watch(nentry->rule.watch);
    296				audit_get_watch(nwatch);
    297				nentry->rule.watch = nwatch;
    298				list_add(&nentry->rule.rlist, &nwatch->rules);
    299				list_add_rcu(&nentry->list, &audit_inode_hash[h]);
    300				list_replace(&oentry->rule.list,
    301					     &nentry->rule.list);
    302			}
    303			if (oentry->rule.exe)
    304				audit_remove_mark(oentry->rule.exe);
    305
    306			call_rcu(&oentry->rcu, audit_free_rule_rcu);
    307		}
    308
    309		audit_remove_watch(owatch);
    310		goto add_watch_to_parent; /* event applies to a single watch */
    311	}
    312	mutex_unlock(&audit_filter_mutex);
    313	return;
    314
    315add_watch_to_parent:
    316	list_add(&nwatch->wlist, &parent->watches);
    317	mutex_unlock(&audit_filter_mutex);
    318	return;
    319}
    320
    321/* Remove all watches & rules associated with a parent that is going away. */
    322static void audit_remove_parent_watches(struct audit_parent *parent)
    323{
    324	struct audit_watch *w, *nextw;
    325	struct audit_krule *r, *nextr;
    326	struct audit_entry *e;
    327
    328	mutex_lock(&audit_filter_mutex);
    329	list_for_each_entry_safe(w, nextw, &parent->watches, wlist) {
    330		list_for_each_entry_safe(r, nextr, &w->rules, rlist) {
    331			e = container_of(r, struct audit_entry, rule);
    332			audit_watch_log_rule_change(r, w, "remove_rule");
    333			if (e->rule.exe)
    334				audit_remove_mark(e->rule.exe);
    335			list_del(&r->rlist);
    336			list_del(&r->list);
    337			list_del_rcu(&e->list);
    338			call_rcu(&e->rcu, audit_free_rule_rcu);
    339		}
    340		audit_remove_watch(w);
    341	}
    342	mutex_unlock(&audit_filter_mutex);
    343
    344	fsnotify_destroy_mark(&parent->mark, audit_watch_group);
    345}
    346
    347/* Get path information necessary for adding watches. */
    348static int audit_get_nd(struct audit_watch *watch, struct path *parent)
    349{
    350	struct dentry *d = kern_path_locked(watch->path, parent);
    351	if (IS_ERR(d))
    352		return PTR_ERR(d);
    353	if (d_is_positive(d)) {
    354		/* update watch filter fields */
    355		watch->dev = d->d_sb->s_dev;
    356		watch->ino = d_backing_inode(d)->i_ino;
    357	}
    358	inode_unlock(d_backing_inode(parent->dentry));
    359	dput(d);
    360	return 0;
    361}
    362
    363/* Associate the given rule with an existing parent.
    364 * Caller must hold audit_filter_mutex. */
    365static void audit_add_to_parent(struct audit_krule *krule,
    366				struct audit_parent *parent)
    367{
    368	struct audit_watch *w, *watch = krule->watch;
    369	int watch_found = 0;
    370
    371	BUG_ON(!mutex_is_locked(&audit_filter_mutex));
    372
    373	list_for_each_entry(w, &parent->watches, wlist) {
    374		if (strcmp(watch->path, w->path))
    375			continue;
    376
    377		watch_found = 1;
    378
    379		/* put krule's ref to temporary watch */
    380		audit_put_watch(watch);
    381
    382		audit_get_watch(w);
    383		krule->watch = watch = w;
    384
    385		audit_put_parent(parent);
    386		break;
    387	}
    388
    389	if (!watch_found) {
    390		watch->parent = parent;
    391
    392		audit_get_watch(watch);
    393		list_add(&watch->wlist, &parent->watches);
    394	}
    395	list_add(&krule->rlist, &watch->rules);
    396}
    397
    398/* Find a matching watch entry, or add this one.
    399 * Caller must hold audit_filter_mutex. */
    400int audit_add_watch(struct audit_krule *krule, struct list_head **list)
    401{
    402	struct audit_watch *watch = krule->watch;
    403	struct audit_parent *parent;
    404	struct path parent_path;
    405	int h, ret = 0;
    406
    407	/*
    408	 * When we will be calling audit_add_to_parent, krule->watch might have
    409	 * been updated and watch might have been freed.
    410	 * So we need to keep a reference of watch.
    411	 */
    412	audit_get_watch(watch);
    413
    414	mutex_unlock(&audit_filter_mutex);
    415
    416	/* Avoid calling path_lookup under audit_filter_mutex. */
    417	ret = audit_get_nd(watch, &parent_path);
    418
    419	/* caller expects mutex locked */
    420	mutex_lock(&audit_filter_mutex);
    421
    422	if (ret) {
    423		audit_put_watch(watch);
    424		return ret;
    425	}
    426
    427	/* either find an old parent or attach a new one */
    428	parent = audit_find_parent(d_backing_inode(parent_path.dentry));
    429	if (!parent) {
    430		parent = audit_init_parent(&parent_path);
    431		if (IS_ERR(parent)) {
    432			ret = PTR_ERR(parent);
    433			goto error;
    434		}
    435	}
    436
    437	audit_add_to_parent(krule, parent);
    438
    439	h = audit_hash_ino((u32)watch->ino);
    440	*list = &audit_inode_hash[h];
    441error:
    442	path_put(&parent_path);
    443	audit_put_watch(watch);
    444	return ret;
    445}
    446
    447void audit_remove_watch_rule(struct audit_krule *krule)
    448{
    449	struct audit_watch *watch = krule->watch;
    450	struct audit_parent *parent = watch->parent;
    451
    452	list_del(&krule->rlist);
    453
    454	if (list_empty(&watch->rules)) {
    455		/*
    456		 * audit_remove_watch() drops our reference to 'parent' which
    457		 * can get freed. Grab our own reference to be safe.
    458		 */
    459		audit_get_parent(parent);
    460		audit_remove_watch(watch);
    461		if (list_empty(&parent->watches))
    462			fsnotify_destroy_mark(&parent->mark, audit_watch_group);
    463		audit_put_parent(parent);
    464	}
    465}
    466
    467/* Update watch data in audit rules based on fsnotify events. */
    468static int audit_watch_handle_event(struct fsnotify_mark *inode_mark, u32 mask,
    469				    struct inode *inode, struct inode *dir,
    470				    const struct qstr *dname, u32 cookie)
    471{
    472	struct audit_parent *parent;
    473
    474	parent = container_of(inode_mark, struct audit_parent, mark);
    475
    476	if (WARN_ON_ONCE(inode_mark->group != audit_watch_group))
    477		return 0;
    478
    479	if (mask & (FS_CREATE|FS_MOVED_TO) && inode)
    480		audit_update_watch(parent, dname, inode->i_sb->s_dev, inode->i_ino, 0);
    481	else if (mask & (FS_DELETE|FS_MOVED_FROM))
    482		audit_update_watch(parent, dname, AUDIT_DEV_UNSET, AUDIT_INO_UNSET, 1);
    483	else if (mask & (FS_DELETE_SELF|FS_UNMOUNT|FS_MOVE_SELF))
    484		audit_remove_parent_watches(parent);
    485
    486	return 0;
    487}
    488
    489static const struct fsnotify_ops audit_watch_fsnotify_ops = {
    490	.handle_inode_event =	audit_watch_handle_event,
    491	.free_mark =		audit_watch_free_mark,
    492};
    493
    494static int __init audit_watch_init(void)
    495{
    496	audit_watch_group = fsnotify_alloc_group(&audit_watch_fsnotify_ops, 0);
    497	if (IS_ERR(audit_watch_group)) {
    498		audit_watch_group = NULL;
    499		audit_panic("cannot create audit fsnotify group");
    500	}
    501	return 0;
    502}
    503device_initcall(audit_watch_init);
    504
    505int audit_dupe_exe(struct audit_krule *new, struct audit_krule *old)
    506{
    507	struct audit_fsnotify_mark *audit_mark;
    508	char *pathname;
    509
    510	pathname = kstrdup(audit_mark_path(old->exe), GFP_KERNEL);
    511	if (!pathname)
    512		return -ENOMEM;
    513
    514	audit_mark = audit_alloc_mark(new, pathname, strlen(pathname));
    515	if (IS_ERR(audit_mark)) {
    516		kfree(pathname);
    517		return PTR_ERR(audit_mark);
    518	}
    519	new->exe = audit_mark;
    520
    521	return 0;
    522}
    523
    524int audit_exe_compare(struct task_struct *tsk, struct audit_fsnotify_mark *mark)
    525{
    526	struct file *exe_file;
    527	unsigned long ino;
    528	dev_t dev;
    529
    530	exe_file = get_task_exe_file(tsk);
    531	if (!exe_file)
    532		return 0;
    533	ino = file_inode(exe_file)->i_ino;
    534	dev = file_inode(exe_file)->i_sb->s_dev;
    535	fput(exe_file);
    536	return audit_mark_compare(mark, ino, dev);
    537}