audit_watch.c 14.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/* audit_watch.c -- watching inodes
 *
 * Copyright 2003-2009 Red Hat, Inc.
 * Copyright 2005 Hewlett-Packard Development Company, L.P.
 * Copyright 2005 IBM Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

22
#include <linux/file.h>
23 24 25 26 27
#include <linux/kernel.h>
#include <linux/audit.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
#include <linux/fs.h>
28
#include <linux/fsnotify_backend.h>
29 30
#include <linux/namei.h>
#include <linux/netlink.h>
31
#include <linux/refcount.h>
32
#include <linux/sched.h>
33
#include <linux/slab.h>
34 35 36 37 38 39
#include <linux/security.h>
#include "audit.h"

/*
 * Reference counting:
 *
40
 * audit_parent: lifetime is from audit_init_parent() to receipt of an FS_IGNORED
41 42 43 44 45 46 47 48 49
 * 	event.  Each audit_watch holds a reference to its associated parent.
 *
 * audit_watch: if added to lists, lifetime is from audit_init_watch() to
 * 	audit_remove_watch().  Additionally, an audit_watch may exist
 * 	temporarily to assist in searching existing filter data.  Each
 * 	audit_krule holds a reference to its associated watch.
 */

struct audit_watch {
50
	refcount_t		count;	/* reference count */
51
	dev_t			dev;	/* associated superblock device */
52
	char			*path;	/* insertion path */
53 54 55
	unsigned long		ino;	/* associated inode number */
	struct audit_parent	*parent; /* associated parent */
	struct list_head	wlist;	/* entry in parent->watches list */
56
	struct list_head	rules;	/* anchor for krule->rlist */
57 58 59
};

struct audit_parent {
60
	struct list_head	watches; /* anchor for audit_watch->wlist */
61
	struct fsnotify_mark mark; /* fsnotify mark on the inode */
62 63
};

64
/* fsnotify handle. */
65
static struct fsnotify_group *audit_watch_group;
66

67 68
/* fsnotify events we care about. */
#define AUDIT_FS_WATCH (FS_MOVE | FS_CREATE | FS_DELETE | FS_DELETE_SELF |\
Jan Kara's avatar
Jan Kara committed
69
			FS_MOVE_SELF | FS_EVENT_ON_CHILD | FS_UNMOUNT)
70

71 72 73 74 75 76
static void audit_free_parent(struct audit_parent *parent)
{
	WARN_ON(!list_empty(&parent->watches));
	kfree(parent);
}

77
static void audit_watch_free_mark(struct fsnotify_mark *entry)
78 79 80
{
	struct audit_parent *parent;

81
	parent = container_of(entry, struct audit_parent, mark);
82
	audit_free_parent(parent);
83 84
}

85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
static void audit_get_parent(struct audit_parent *parent)
{
	if (likely(parent))
		fsnotify_get_mark(&parent->mark);
}

static void audit_put_parent(struct audit_parent *parent)
{
	if (likely(parent))
		fsnotify_put_mark(&parent->mark);
}

/*
 * Find and return the audit_parent on the given inode.  If found a reference
 * is taken on this parent.
 */
static inline struct audit_parent *audit_find_parent(struct inode *inode)
{
	struct audit_parent *parent = NULL;
104
	struct fsnotify_mark *entry;
105

106
	entry = fsnotify_find_mark(&inode->i_fsnotify_marks, audit_watch_group);
107 108 109 110 111 112
	if (entry)
		parent = container_of(entry, struct audit_parent, mark);

	return parent;
}

113 114
void audit_get_watch(struct audit_watch *watch)
{
115
	refcount_inc(&watch->count);
116 117 118 119
}

void audit_put_watch(struct audit_watch *watch)
{
120
	if (refcount_dec_and_test(&watch->count)) {
121 122 123 124 125 126 127
		WARN_ON(watch->parent);
		WARN_ON(!list_empty(&watch->rules));
		kfree(watch->path);
		kfree(watch);
	}
}

128
static void audit_remove_watch(struct audit_watch *watch)
129 130
{
	list_del(&watch->wlist);
131
	audit_put_parent(watch->parent);
132 133 134 135 136 137 138 139 140
	watch->parent = NULL;
	audit_put_watch(watch); /* match initial get */
}

char *audit_watch_path(struct audit_watch *watch)
{
	return watch->path;
}

141
int audit_watch_compare(struct audit_watch *watch, unsigned long ino, dev_t dev)
142
{
143
	return (watch->ino != AUDIT_INO_UNSET) &&
144 145
		(watch->ino == ino) &&
		(watch->dev == dev);
146 147 148
}

/* Initialize a parent watch entry. */
Al Viro's avatar
Al Viro committed
149
static struct audit_parent *audit_init_parent(struct path *path)
150
{
151
	struct inode *inode = d_backing_inode(path->dentry);
152
	struct audit_parent *parent;
153
	int ret;
154 155 156 157 158 159 160

	parent = kzalloc(sizeof(*parent), GFP_KERNEL);
	if (unlikely(!parent))
		return ERR_PTR(-ENOMEM);

	INIT_LIST_HEAD(&parent->watches);

161
	fsnotify_init_mark(&parent->mark, audit_watch_group);
162
	parent->mark.mask = AUDIT_FS_WATCH;
163
	ret = fsnotify_add_inode_mark(&parent->mark, inode, 0);
164
	if (ret < 0) {
165
		audit_free_parent(parent);
166
		return ERR_PTR(ret);
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
	}

	return parent;
}

/* Initialize a watch entry. */
static struct audit_watch *audit_init_watch(char *path)
{
	struct audit_watch *watch;

	watch = kzalloc(sizeof(*watch), GFP_KERNEL);
	if (unlikely(!watch))
		return ERR_PTR(-ENOMEM);

	INIT_LIST_HEAD(&watch->rules);
182
	refcount_set(&watch->count, 1);
183
	watch->path = path;
184 185
	watch->dev = AUDIT_DEV_UNSET;
	watch->ino = AUDIT_INO_UNSET;
186 187 188 189

	return watch;
}

Wei Yuan's avatar
Wei Yuan committed
190
/* Translate a watch string to kernel representation. */
191 192 193 194
int audit_to_watch(struct audit_krule *krule, char *path, int len, u32 op)
{
	struct audit_watch *watch;

195
	if (!audit_watch_group)
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
		return -EOPNOTSUPP;

	if (path[0] != '/' || path[len-1] == '/' ||
	    krule->listnr != AUDIT_FILTER_EXIT ||
	    op != Audit_equal ||
	    krule->inode_f || krule->watch || krule->tree)
		return -EINVAL;

	watch = audit_init_watch(path);
	if (IS_ERR(watch))
		return PTR_ERR(watch);

	krule->watch = watch;

	return 0;
}

/* Duplicate the given audit watch.  The new watch's rules list is initialized
 * to an empty list and wlist is undefined. */
static struct audit_watch *audit_dupe_watch(struct audit_watch *old)
{
	char *path;
	struct audit_watch *new;

	path = kstrdup(old->path, GFP_KERNEL);
	if (unlikely(!path))
		return ERR_PTR(-ENOMEM);

	new = audit_init_watch(path);
	if (IS_ERR(new)) {
		kfree(path);
		goto out;
	}

	new->dev = old->dev;
	new->ino = old->ino;
232
	audit_get_parent(old->parent);
233 234 235 236 237 238 239 240 241 242 243
	new->parent = old->parent;

out:
	return new;
}

static void audit_watch_log_rule_change(struct audit_krule *r, struct audit_watch *w, char *op)
{
	if (audit_enabled) {
		struct audit_buffer *ab;
		ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE);
244 245
		if (unlikely(!ab))
			return;
246
		audit_log_format(ab, "auid=%u ses=%u op=%s",
247
				 from_kuid(&init_user_ns, audit_get_loginuid(current)),
248
				 audit_get_sessionid(current), op);
249 250
		audit_log_format(ab, " path=");
		audit_log_untrustedstring(ab, w->path);
251
		audit_log_key(ab, r->filterkey);
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
		audit_log_format(ab, " list=%d res=1", r->listnr);
		audit_log_end(ab);
	}
}

/* Update inode info in audit rules based on filesystem event. */
static void audit_update_watch(struct audit_parent *parent,
			       const char *dname, dev_t dev,
			       unsigned long ino, unsigned invalidating)
{
	struct audit_watch *owatch, *nwatch, *nextw;
	struct audit_krule *r, *nextr;
	struct audit_entry *oentry, *nentry;

	mutex_lock(&audit_filter_mutex);
267 268
	/* Run all of the watches on this parent looking for the one that
	 * matches the given dname */
269
	list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) {
270 271
		if (audit_compare_dname_path(dname, owatch->path,
					     AUDIT_NAME_FULL))
272 273 274 275
			continue;

		/* If the update involves invalidating rules, do the inode-based
		 * filtering now, so we don't omit records. */
276
		if (invalidating && !audit_dummy_context())
277
			audit_filter_inodes(current, audit_context());
278

279 280
		/* updating ino will likely change which audit_hash_list we
		 * are on so we need a new watch for the new list */
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
		nwatch = audit_dupe_watch(owatch);
		if (IS_ERR(nwatch)) {
			mutex_unlock(&audit_filter_mutex);
			audit_panic("error updating watch, skipping");
			return;
		}
		nwatch->dev = dev;
		nwatch->ino = ino;

		list_for_each_entry_safe(r, nextr, &owatch->rules, rlist) {

			oentry = container_of(r, struct audit_entry, rule);
			list_del(&oentry->rule.rlist);
			list_del_rcu(&oentry->list);

296
			nentry = audit_dupe_rule(&oentry->rule);
297 298 299 300 301
			if (IS_ERR(nentry)) {
				list_del(&oentry->rule.list);
				audit_panic("error updating watch, removing");
			} else {
				int h = audit_hash_ino((u32)ino);
302 303 304 305 306 307 308 309 310

				/*
				 * nentry->rule.watch == oentry->rule.watch so
				 * we must drop that reference and set it to our
				 * new watch.
				 */
				audit_put_watch(nentry->rule.watch);
				audit_get_watch(nwatch);
				nentry->rule.watch = nwatch;
311 312 313 314 315
				list_add(&nentry->rule.rlist, &nwatch->rules);
				list_add_rcu(&nentry->list, &audit_inode_hash[h]);
				list_replace(&oentry->rule.list,
					     &nentry->rule.list);
			}
316 317
			if (oentry->rule.exe)
				audit_remove_mark(oentry->rule.exe);
318

319
			audit_watch_log_rule_change(r, owatch, "updated_rules");
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346

			call_rcu(&oentry->rcu, audit_free_rule_rcu);
		}

		audit_remove_watch(owatch);
		goto add_watch_to_parent; /* event applies to a single watch */
	}
	mutex_unlock(&audit_filter_mutex);
	return;

add_watch_to_parent:
	list_add(&nwatch->wlist, &parent->watches);
	mutex_unlock(&audit_filter_mutex);
	return;
}

/* Remove all watches & rules associated with a parent that is going away. */
static void audit_remove_parent_watches(struct audit_parent *parent)
{
	struct audit_watch *w, *nextw;
	struct audit_krule *r, *nextr;
	struct audit_entry *e;

	mutex_lock(&audit_filter_mutex);
	list_for_each_entry_safe(w, nextw, &parent->watches, wlist) {
		list_for_each_entry_safe(r, nextr, &w->rules, rlist) {
			e = container_of(r, struct audit_entry, rule);
347
			audit_watch_log_rule_change(r, w, "remove_rule");
348 349
			if (e->rule.exe)
				audit_remove_mark(e->rule.exe);
350 351 352 353 354 355 356 357
			list_del(&r->rlist);
			list_del(&r->list);
			list_del_rcu(&e->list);
			call_rcu(&e->rcu, audit_free_rule_rcu);
		}
		audit_remove_watch(w);
	}
	mutex_unlock(&audit_filter_mutex);
358

359
	fsnotify_destroy_mark(&parent->mark, audit_watch_group);
360 361 362
}

/* Get path information necessary for adding watches. */
Al Viro's avatar
Al Viro committed
363
static int audit_get_nd(struct audit_watch *watch, struct path *parent)
364
{
Al Viro's avatar
Al Viro committed
365 366
	struct dentry *d = kern_path_locked(watch->path, parent);
	if (IS_ERR(d))
Al Viro's avatar
Al Viro committed
367
		return PTR_ERR(d);
Al Viro's avatar
Al Viro committed
368
	inode_unlock(d_backing_inode(parent->dentry));
369
	if (d_is_positive(d)) {
Al Viro's avatar
Al Viro committed
370
		/* update watch filter fields */
371
		watch->dev = d->d_sb->s_dev;
372
		watch->ino = d_backing_inode(d)->i_ino;
373
	}
Al Viro's avatar
Al Viro committed
374
	dput(d);
375 376 377
	return 0;
}

378
/* Associate the given rule with an existing parent.
379 380 381 382 383 384 385
 * Caller must hold audit_filter_mutex. */
static void audit_add_to_parent(struct audit_krule *krule,
				struct audit_parent *parent)
{
	struct audit_watch *w, *watch = krule->watch;
	int watch_found = 0;

386 387
	BUG_ON(!mutex_is_locked(&audit_filter_mutex));

388 389 390 391 392 393
	list_for_each_entry(w, &parent->watches, wlist) {
		if (strcmp(watch->path, w->path))
			continue;

		watch_found = 1;

394
		/* put krule's ref to temporary watch */
395 396 397 398
		audit_put_watch(watch);

		audit_get_watch(w);
		krule->watch = watch = w;
399 400

		audit_put_parent(parent);
401 402 403 404 405 406
		break;
	}

	if (!watch_found) {
		watch->parent = parent;

407
		audit_get_watch(watch);
408 409 410 411 412 413 414
		list_add(&watch->wlist, &parent->watches);
	}
	list_add(&krule->rlist, &watch->rules);
}

/* Find a matching watch entry, or add this one.
 * Caller must hold audit_filter_mutex. */
415
int audit_add_watch(struct audit_krule *krule, struct list_head **list)
416 417 418
{
	struct audit_watch *watch = krule->watch;
	struct audit_parent *parent;
Al Viro's avatar
Al Viro committed
419
	struct path parent_path;
420
	int h, ret = 0;
421

422 423 424 425 426 427 428
	/*
	 * When we will be calling audit_add_to_parent, krule->watch might have
	 * been updated and watch might have been freed.
	 * So we need to keep a reference of watch.
	 */
	audit_get_watch(watch);

429 430 431
	mutex_unlock(&audit_filter_mutex);

	/* Avoid calling path_lookup under audit_filter_mutex. */
Al Viro's avatar
Al Viro committed
432
	ret = audit_get_nd(watch, &parent_path);
433

Al Viro's avatar
Al Viro committed
434
	/* caller expects mutex locked */
435 436
	mutex_lock(&audit_filter_mutex);

437 438
	if (ret) {
		audit_put_watch(watch);
Al Viro's avatar
Al Viro committed
439
		return ret;
440
	}
441

442
	/* either find an old parent or attach a new one */
443
	parent = audit_find_parent(d_backing_inode(parent_path.dentry));
444
	if (!parent) {
Al Viro's avatar
Al Viro committed
445
		parent = audit_init_parent(&parent_path);
446
		if (IS_ERR(parent)) {
447 448
			ret = PTR_ERR(parent);
			goto error;
449
		}
450
	}
451

452
	audit_add_to_parent(krule, parent);
453

454 455
	h = audit_hash_ino((u32)watch->ino);
	*list = &audit_inode_hash[h];
456
error:
Al Viro's avatar
Al Viro committed
457
	path_put(&parent_path);
458
	audit_put_watch(watch);
459 460 461
	return ret;
}

462
void audit_remove_watch_rule(struct audit_krule *krule)
463 464 465 466 467 468 469
{
	struct audit_watch *watch = krule->watch;
	struct audit_parent *parent = watch->parent;

	list_del(&krule->rlist);

	if (list_empty(&watch->rules)) {
470 471 472 473 474
		/*
		 * audit_remove_watch() drops our reference to 'parent' which
		 * can get freed. Grab our own reference to be safe.
		 */
		audit_get_parent(parent);
475
		audit_remove_watch(watch);
476
		if (list_empty(&parent->watches))
477
			fsnotify_destroy_mark(&parent->mark, audit_watch_group);
478
		audit_put_parent(parent);
479 480 481
	}
}

482
/* Update watch data in audit rules based on fsnotify events. */
483
static int audit_watch_handle_event(struct fsnotify_group *group,
484
				    struct inode *to_tell,
485
				    u32 mask, const void *data, int data_type,
486 487
				    const unsigned char *dname, u32 cookie,
				    struct fsnotify_iter_info *iter_info)
488
{
489
	struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
490
	const struct inode *inode;
491 492
	struct audit_parent *parent;

493
	parent = container_of(inode_mark, struct audit_parent, mark);
494

495
	BUG_ON(group != audit_watch_group);
496

497
	switch (data_type) {
498
	case (FSNOTIFY_EVENT_PATH):
499
		inode = d_backing_inode(((const struct path *)data)->dentry);
500 501
		break;
	case (FSNOTIFY_EVENT_INODE):
502
		inode = (const struct inode *)data;
503 504 505 506 507
		break;
	default:
		BUG();
		inode = NULL;
		break;
508
	}
509

510
	if (mask & (FS_CREATE|FS_MOVED_TO) && inode)
511
		audit_update_watch(parent, dname, inode->i_sb->s_dev, inode->i_ino, 0);
512
	else if (mask & (FS_DELETE|FS_MOVED_FROM))
513
		audit_update_watch(parent, dname, AUDIT_DEV_UNSET, AUDIT_INO_UNSET, 1);
514
	else if (mask & (FS_DELETE_SELF|FS_UNMOUNT|FS_MOVE_SELF))
515
		audit_remove_parent_watches(parent);
516 517 518 519 520 521

	return 0;
}

static const struct fsnotify_ops audit_watch_fsnotify_ops = {
	.handle_event = 	audit_watch_handle_event,
522
	.free_mark =		audit_watch_free_mark,
523 524 525 526
};

static int __init audit_watch_init(void)
{
527
	audit_watch_group = fsnotify_alloc_group(&audit_watch_fsnotify_ops);
528 529 530 531
	if (IS_ERR(audit_watch_group)) {
		audit_watch_group = NULL;
		audit_panic("cannot create audit fsnotify group");
	}
532 533
	return 0;
}
534
device_initcall(audit_watch_init);
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556

int audit_dupe_exe(struct audit_krule *new, struct audit_krule *old)
{
	struct audit_fsnotify_mark *audit_mark;
	char *pathname;

	pathname = kstrdup(audit_mark_path(old->exe), GFP_KERNEL);
	if (!pathname)
		return -ENOMEM;

	audit_mark = audit_alloc_mark(new, pathname, strlen(pathname));
	if (IS_ERR(audit_mark)) {
		kfree(pathname);
		return PTR_ERR(audit_mark);
	}
	new->exe = audit_mark;

	return 0;
}

int audit_exe_compare(struct task_struct *tsk, struct audit_fsnotify_mark *mark)
{
557 558 559 560
	struct file *exe_file;
	unsigned long ino;
	dev_t dev;

561 562 563
	exe_file = get_task_exe_file(tsk);
	if (!exe_file)
		return 0;
Al Viro's avatar
Al Viro committed
564 565
	ino = file_inode(exe_file)->i_ino;
	dev = file_inode(exe_file)->i_sb->s_dev;
566
	fput(exe_file);
567 568
	return audit_mark_compare(mark, ino, dev);
}