diff options
Diffstat (limited to 'kernel/audit_watch.c')
-rw-r--r-- | kernel/audit_watch.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index da8be6d39c1a..b49ab019fdff 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c | |||
@@ -345,7 +345,7 @@ void audit_inotify_unregister(struct list_head *in_list) | |||
345 | } | 345 | } |
346 | 346 | ||
347 | /* Get path information necessary for adding watches. */ | 347 | /* Get path information necessary for adding watches. */ |
348 | int audit_get_nd(char *path, struct nameidata **ndp, struct nameidata **ndw) | 348 | static int audit_get_nd(char *path, struct nameidata **ndp, struct nameidata **ndw) |
349 | { | 349 | { |
350 | struct nameidata *ndparent, *ndwatch; | 350 | struct nameidata *ndparent, *ndwatch; |
351 | int err; | 351 | int err; |
@@ -380,7 +380,7 @@ int audit_get_nd(char *path, struct nameidata **ndp, struct nameidata **ndw) | |||
380 | } | 380 | } |
381 | 381 | ||
382 | /* Release resources used for watch path information. */ | 382 | /* Release resources used for watch path information. */ |
383 | void audit_put_nd(struct nameidata *ndp, struct nameidata *ndw) | 383 | static void audit_put_nd(struct nameidata *ndp, struct nameidata *ndw) |
384 | { | 384 | { |
385 | if (ndp) { | 385 | if (ndp) { |
386 | path_put(&ndp->path); | 386 | path_put(&ndp->path); |
@@ -426,14 +426,24 @@ static void audit_add_to_parent(struct audit_krule *krule, | |||
426 | 426 | ||
427 | /* Find a matching watch entry, or add this one. | 427 | /* Find a matching watch entry, or add this one. |
428 | * Caller must hold audit_filter_mutex. */ | 428 | * Caller must hold audit_filter_mutex. */ |
429 | int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp, | 429 | int audit_add_watch(struct audit_krule *krule) |
430 | struct nameidata *ndw) | ||
431 | { | 430 | { |
432 | struct audit_watch *watch = krule->watch; | 431 | struct audit_watch *watch = krule->watch; |
433 | struct inotify_watch *i_watch; | 432 | struct inotify_watch *i_watch; |
434 | struct audit_parent *parent; | 433 | struct audit_parent *parent; |
434 | struct nameidata *ndp = NULL, *ndw = NULL; | ||
435 | int ret = 0; | 435 | int ret = 0; |
436 | 436 | ||
437 | mutex_unlock(&audit_filter_mutex); | ||
438 | |||
439 | /* Avoid calling path_lookup under audit_filter_mutex. */ | ||
440 | ret = audit_get_nd(watch->path, &ndp, &ndw); | ||
441 | if (ret) { | ||
442 | /* caller expects mutex locked */ | ||
443 | mutex_lock(&audit_filter_mutex); | ||
444 | goto error; | ||
445 | } | ||
446 | |||
437 | /* update watch filter fields */ | 447 | /* update watch filter fields */ |
438 | if (ndw) { | 448 | if (ndw) { |
439 | watch->dev = ndw->path.dentry->d_inode->i_sb->s_dev; | 449 | watch->dev = ndw->path.dentry->d_inode->i_sb->s_dev; |
@@ -445,15 +455,14 @@ int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp, | |||
445 | * inotify watch is found, inotify_find_watch() grabs a reference before | 455 | * inotify watch is found, inotify_find_watch() grabs a reference before |
446 | * returning. | 456 | * returning. |
447 | */ | 457 | */ |
448 | mutex_unlock(&audit_filter_mutex); | ||
449 | |||
450 | if (inotify_find_watch(audit_ih, ndp->path.dentry->d_inode, | 458 | if (inotify_find_watch(audit_ih, ndp->path.dentry->d_inode, |
451 | &i_watch) < 0) { | 459 | &i_watch) < 0) { |
452 | parent = audit_init_parent(ndp); | 460 | parent = audit_init_parent(ndp); |
453 | if (IS_ERR(parent)) { | 461 | if (IS_ERR(parent)) { |
454 | /* caller expects mutex locked */ | 462 | /* caller expects mutex locked */ |
455 | mutex_lock(&audit_filter_mutex); | 463 | mutex_lock(&audit_filter_mutex); |
456 | return PTR_ERR(parent); | 464 | ret = PTR_ERR(parent); |
465 | goto error; | ||
457 | } | 466 | } |
458 | } else | 467 | } else |
459 | parent = container_of(i_watch, struct audit_parent, wdata); | 468 | parent = container_of(i_watch, struct audit_parent, wdata); |
@@ -468,7 +477,11 @@ int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp, | |||
468 | 477 | ||
469 | /* match get in audit_init_parent or inotify_find_watch */ | 478 | /* match get in audit_init_parent or inotify_find_watch */ |
470 | put_inotify_watch(&parent->wdata); | 479 | put_inotify_watch(&parent->wdata); |
480 | |||
481 | error: | ||
482 | audit_put_nd(ndp, ndw); /* NULL args OK */ | ||
471 | return ret; | 483 | return ret; |
484 | |||
472 | } | 485 | } |
473 | 486 | ||
474 | void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list) | 487 | void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list) |