diff options
-rw-r--r-- | kernel/audit.h | 5 | ||||
-rw-r--r-- | kernel/audit_watch.c | 27 | ||||
-rw-r--r-- | kernel/auditfilter.c | 15 |
3 files changed, 23 insertions, 24 deletions
diff --git a/kernel/audit.h b/kernel/audit.h index 704d5b01d9fd..bb1c0d69db08 100644 --- a/kernel/audit.h +++ b/kernel/audit.h | |||
@@ -109,10 +109,7 @@ extern dev_t audit_watch_dev(struct audit_watch *watch); | |||
109 | extern void audit_put_watch(struct audit_watch *watch); | 109 | extern void audit_put_watch(struct audit_watch *watch); |
110 | extern void audit_get_watch(struct audit_watch *watch); | 110 | extern void audit_get_watch(struct audit_watch *watch); |
111 | extern int audit_to_watch(struct audit_krule *krule, char *path, int len, u32 op); | 111 | extern int audit_to_watch(struct audit_krule *krule, char *path, int len, u32 op); |
112 | extern int audit_get_nd(char *path, struct nameidata **ndp, struct nameidata **ndw); | 112 | extern int audit_add_watch(struct audit_krule *krule); |
113 | extern void audit_put_nd(struct nameidata *ndp, struct nameidata *ndw); | ||
114 | extern int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp, | ||
115 | struct nameidata *ndw); | ||
116 | extern void audit_remove_watch(struct audit_watch *watch); | 113 | extern void audit_remove_watch(struct audit_watch *watch); |
117 | extern void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list); | 114 | extern void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list); |
118 | extern void audit_inotify_unregister(struct list_head *in_list); | 115 | extern void audit_inotify_unregister(struct list_head *in_list); |
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) |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 9d4c93437de6..21b623595aad 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
@@ -864,7 +864,6 @@ static inline int audit_add_rule(struct audit_entry *entry) | |||
864 | struct audit_entry *e; | 864 | struct audit_entry *e; |
865 | struct audit_watch *watch = entry->rule.watch; | 865 | struct audit_watch *watch = entry->rule.watch; |
866 | struct audit_tree *tree = entry->rule.tree; | 866 | struct audit_tree *tree = entry->rule.tree; |
867 | struct nameidata *ndp = NULL, *ndw = NULL; | ||
868 | struct list_head *list; | 867 | struct list_head *list; |
869 | int h, err; | 868 | int h, err; |
870 | #ifdef CONFIG_AUDITSYSCALL | 869 | #ifdef CONFIG_AUDITSYSCALL |
@@ -878,8 +877,8 @@ static inline int audit_add_rule(struct audit_entry *entry) | |||
878 | 877 | ||
879 | mutex_lock(&audit_filter_mutex); | 878 | mutex_lock(&audit_filter_mutex); |
880 | e = audit_find_rule(entry, &list); | 879 | e = audit_find_rule(entry, &list); |
881 | mutex_unlock(&audit_filter_mutex); | ||
882 | if (e) { | 880 | if (e) { |
881 | mutex_unlock(&audit_filter_mutex); | ||
883 | err = -EEXIST; | 882 | err = -EEXIST; |
884 | /* normally audit_add_tree_rule() will free it on failure */ | 883 | /* normally audit_add_tree_rule() will free it on failure */ |
885 | if (tree) | 884 | if (tree) |
@@ -887,17 +886,9 @@ static inline int audit_add_rule(struct audit_entry *entry) | |||
887 | goto error; | 886 | goto error; |
888 | } | 887 | } |
889 | 888 | ||
890 | /* Avoid calling path_lookup under audit_filter_mutex. */ | ||
891 | if (watch) { | ||
892 | err = audit_get_nd(audit_watch_path(watch), &ndp, &ndw); | ||
893 | if (err) | ||
894 | goto error; | ||
895 | } | ||
896 | |||
897 | mutex_lock(&audit_filter_mutex); | ||
898 | if (watch) { | 889 | if (watch) { |
899 | /* audit_filter_mutex is dropped and re-taken during this call */ | 890 | /* audit_filter_mutex is dropped and re-taken during this call */ |
900 | err = audit_add_watch(&entry->rule, ndp, ndw); | 891 | err = audit_add_watch(&entry->rule); |
901 | if (err) { | 892 | if (err) { |
902 | mutex_unlock(&audit_filter_mutex); | 893 | mutex_unlock(&audit_filter_mutex); |
903 | goto error; | 894 | goto error; |
@@ -942,11 +933,9 @@ static inline int audit_add_rule(struct audit_entry *entry) | |||
942 | #endif | 933 | #endif |
943 | mutex_unlock(&audit_filter_mutex); | 934 | mutex_unlock(&audit_filter_mutex); |
944 | 935 | ||
945 | audit_put_nd(ndp, ndw); /* NULL args OK */ | ||
946 | return 0; | 936 | return 0; |
947 | 937 | ||
948 | error: | 938 | error: |
949 | audit_put_nd(ndp, ndw); /* NULL args OK */ | ||
950 | if (watch) | 939 | if (watch) |
951 | audit_put_watch(watch); /* tmp watch, matches initial get */ | 940 | audit_put_watch(watch); /* tmp watch, matches initial get */ |
952 | return err; | 941 | return err; |