diff options
-rw-r--r-- | fs/namei.c | 16 | ||||
-rw-r--r-- | include/linux/audit.h | 10 | ||||
-rw-r--r-- | include/linux/fs.h | 6 | ||||
-rw-r--r-- | ipc/mqueue.c | 4 | ||||
-rw-r--r-- | kernel/auditsc.c | 25 |
5 files changed, 42 insertions, 19 deletions
diff --git a/fs/namei.c b/fs/namei.c index 6bbd8fdfb1f5..80b162b142f9 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1999,8 +1999,7 @@ static int filename_lookup(int dfd, struct filename *name, | |||
1999 | flags | LOOKUP_REVAL, nd); | 1999 | flags | LOOKUP_REVAL, nd); |
2000 | 2000 | ||
2001 | if (likely(!retval)) | 2001 | if (likely(!retval)) |
2002 | audit_inode(name->name, nd->path.dentry, | 2002 | audit_inode(name, nd->path.dentry, flags & LOOKUP_PARENT); |
2003 | flags & LOOKUP_PARENT); | ||
2004 | return retval; | 2003 | return retval; |
2005 | } | 2004 | } |
2006 | 2005 | ||
@@ -2674,7 +2673,6 @@ static int do_last(struct nameidata *nd, struct path *path, | |||
2674 | struct path save_parent = { .dentry = NULL, .mnt = NULL }; | 2673 | struct path save_parent = { .dentry = NULL, .mnt = NULL }; |
2675 | bool retried = false; | 2674 | bool retried = false; |
2676 | int error; | 2675 | int error; |
2677 | const char *pathname = name->name; | ||
2678 | 2676 | ||
2679 | nd->flags &= ~LOOKUP_PARENT; | 2677 | nd->flags &= ~LOOKUP_PARENT; |
2680 | nd->flags |= op->intent; | 2678 | nd->flags |= op->intent; |
@@ -2690,7 +2688,7 @@ static int do_last(struct nameidata *nd, struct path *path, | |||
2690 | error = complete_walk(nd); | 2688 | error = complete_walk(nd); |
2691 | if (error) | 2689 | if (error) |
2692 | return error; | 2690 | return error; |
2693 | audit_inode(pathname, nd->path.dentry, 0); | 2691 | audit_inode(name, nd->path.dentry, 0); |
2694 | if (open_flag & O_CREAT) { | 2692 | if (open_flag & O_CREAT) { |
2695 | error = -EISDIR; | 2693 | error = -EISDIR; |
2696 | goto out; | 2694 | goto out; |
@@ -2700,7 +2698,7 @@ static int do_last(struct nameidata *nd, struct path *path, | |||
2700 | error = complete_walk(nd); | 2698 | error = complete_walk(nd); |
2701 | if (error) | 2699 | if (error) |
2702 | return error; | 2700 | return error; |
2703 | audit_inode(pathname, dir, 0); | 2701 | audit_inode(name, dir, 0); |
2704 | goto finish_open; | 2702 | goto finish_open; |
2705 | } | 2703 | } |
2706 | 2704 | ||
@@ -2729,7 +2727,7 @@ static int do_last(struct nameidata *nd, struct path *path, | |||
2729 | if (error) | 2727 | if (error) |
2730 | return error; | 2728 | return error; |
2731 | 2729 | ||
2732 | audit_inode(pathname, dir, 0); | 2730 | audit_inode(name, dir, 0); |
2733 | error = -EISDIR; | 2731 | error = -EISDIR; |
2734 | /* trailing slashes? */ | 2732 | /* trailing slashes? */ |
2735 | if (nd->last.name[nd->last.len]) | 2733 | if (nd->last.name[nd->last.len]) |
@@ -2759,7 +2757,7 @@ retry_lookup: | |||
2759 | !S_ISREG(file->f_path.dentry->d_inode->i_mode)) | 2757 | !S_ISREG(file->f_path.dentry->d_inode->i_mode)) |
2760 | will_truncate = false; | 2758 | will_truncate = false; |
2761 | 2759 | ||
2762 | audit_inode(pathname, file->f_path.dentry, 0); | 2760 | audit_inode(name, file->f_path.dentry, 0); |
2763 | goto opened; | 2761 | goto opened; |
2764 | } | 2762 | } |
2765 | 2763 | ||
@@ -2776,7 +2774,7 @@ retry_lookup: | |||
2776 | * create/update audit record if it already exists. | 2774 | * create/update audit record if it already exists. |
2777 | */ | 2775 | */ |
2778 | if (path->dentry->d_inode) | 2776 | if (path->dentry->d_inode) |
2779 | audit_inode(pathname, path->dentry, 0); | 2777 | audit_inode(name, path->dentry, 0); |
2780 | 2778 | ||
2781 | /* | 2779 | /* |
2782 | * If atomic_open() acquired write access it is dropped now due to | 2780 | * If atomic_open() acquired write access it is dropped now due to |
@@ -2841,7 +2839,7 @@ finish_lookup: | |||
2841 | error = -ENOTDIR; | 2839 | error = -ENOTDIR; |
2842 | if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup) | 2840 | if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup) |
2843 | goto out; | 2841 | goto out; |
2844 | audit_inode(pathname, nd->path.dentry, 0); | 2842 | audit_inode(name, nd->path.dentry, 0); |
2845 | finish_open: | 2843 | finish_open: |
2846 | if (!S_ISREG(nd->inode->i_mode)) | 2844 | if (!S_ISREG(nd->inode->i_mode)) |
2847 | will_truncate = false; | 2845 | will_truncate = false; |
diff --git a/include/linux/audit.h b/include/linux/audit.h index d5d7952ab7d8..e5884f950b4b 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
@@ -474,7 +474,7 @@ extern void __audit_syscall_exit(int ret_success, long ret_value); | |||
474 | extern struct filename *__audit_reusename(const __user char *uptr); | 474 | extern struct filename *__audit_reusename(const __user char *uptr); |
475 | extern void __audit_getname(struct filename *name); | 475 | extern void __audit_getname(struct filename *name); |
476 | extern void audit_putname(struct filename *name); | 476 | extern void audit_putname(struct filename *name); |
477 | extern void __audit_inode(const char *name, const struct dentry *dentry, | 477 | extern void __audit_inode(struct filename *name, const struct dentry *dentry, |
478 | unsigned int parent); | 478 | unsigned int parent); |
479 | extern void __audit_inode_child(const struct inode *parent, | 479 | extern void __audit_inode_child(const struct inode *parent, |
480 | const struct dentry *dentry, | 480 | const struct dentry *dentry, |
@@ -519,7 +519,7 @@ static inline void audit_getname(struct filename *name) | |||
519 | if (unlikely(!audit_dummy_context())) | 519 | if (unlikely(!audit_dummy_context())) |
520 | __audit_getname(name); | 520 | __audit_getname(name); |
521 | } | 521 | } |
522 | static inline void audit_inode(const char *name, const struct dentry *dentry, | 522 | static inline void audit_inode(struct filename *name, const struct dentry *dentry, |
523 | unsigned int parent) { | 523 | unsigned int parent) { |
524 | if (unlikely(!audit_dummy_context())) | 524 | if (unlikely(!audit_dummy_context())) |
525 | __audit_inode(name, dentry, parent); | 525 | __audit_inode(name, dentry, parent); |
@@ -680,14 +680,16 @@ static inline void audit_getname(struct filename *name) | |||
680 | { } | 680 | { } |
681 | static inline void audit_putname(struct filename *name) | 681 | static inline void audit_putname(struct filename *name) |
682 | { } | 682 | { } |
683 | static inline void __audit_inode(const char *name, const struct dentry *dentry, | 683 | static inline void __audit_inode(struct filename *name, |
684 | const struct dentry *dentry, | ||
684 | unsigned int parent) | 685 | unsigned int parent) |
685 | { } | 686 | { } |
686 | static inline void __audit_inode_child(const struct inode *parent, | 687 | static inline void __audit_inode_child(const struct inode *parent, |
687 | const struct dentry *dentry, | 688 | const struct dentry *dentry, |
688 | const unsigned char type) | 689 | const unsigned char type) |
689 | { } | 690 | { } |
690 | static inline void audit_inode(const char *name, const struct dentry *dentry, | 691 | static inline void audit_inode(struct filename *name, |
692 | const struct dentry *dentry, | ||
691 | unsigned int parent) | 693 | unsigned int parent) |
692 | { } | 694 | { } |
693 | static inline void audit_inode_child(const struct inode *parent, | 695 | static inline void audit_inode_child(const struct inode *parent, |
diff --git a/include/linux/fs.h b/include/linux/fs.h index b6b10e7f0ac0..4aa7160a51ce 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2196,9 +2196,11 @@ static inline int break_lease(struct inode *inode, unsigned int mode) | |||
2196 | #endif /* CONFIG_FILE_LOCKING */ | 2196 | #endif /* CONFIG_FILE_LOCKING */ |
2197 | 2197 | ||
2198 | /* fs/open.c */ | 2198 | /* fs/open.c */ |
2199 | struct audit_names; | ||
2199 | struct filename { | 2200 | struct filename { |
2200 | const char *name; /* pointer to actual string */ | 2201 | const char *name; /* pointer to actual string */ |
2201 | const __user char *uptr; /* original userland pointer */ | 2202 | const __user char *uptr; /* original userland pointer */ |
2203 | struct audit_names *aname; | ||
2202 | }; | 2204 | }; |
2203 | 2205 | ||
2204 | extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs, | 2206 | extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs, |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 6c5d9dcc9030..71a3ca18c873 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
@@ -804,7 +804,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, | |||
804 | 804 | ||
805 | if (oflag & O_CREAT) { | 805 | if (oflag & O_CREAT) { |
806 | if (path.dentry->d_inode) { /* entry already exists */ | 806 | if (path.dentry->d_inode) { /* entry already exists */ |
807 | audit_inode(name->name, path.dentry, 0); | 807 | audit_inode(name, path.dentry, 0); |
808 | if (oflag & O_EXCL) { | 808 | if (oflag & O_EXCL) { |
809 | error = -EEXIST; | 809 | error = -EEXIST; |
810 | goto out; | 810 | goto out; |
@@ -824,7 +824,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, | |||
824 | error = -ENOENT; | 824 | error = -ENOENT; |
825 | goto out; | 825 | goto out; |
826 | } | 826 | } |
827 | audit_inode(name->name, path.dentry, 0); | 827 | audit_inode(name, path.dentry, 0); |
828 | filp = do_open(&path, oflag); | 828 | filp = do_open(&path, oflag); |
829 | } | 829 | } |
830 | 830 | ||
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 521163a5d65f..2f186ed80c40 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -2076,6 +2076,7 @@ void __audit_getname(struct filename *name) | |||
2076 | n->name = name; | 2076 | n->name = name; |
2077 | n->name_len = AUDIT_NAME_FULL; | 2077 | n->name_len = AUDIT_NAME_FULL; |
2078 | n->name_put = true; | 2078 | n->name_put = true; |
2079 | name->aname = n; | ||
2079 | 2080 | ||
2080 | if (!context->pwd.dentry) | 2081 | if (!context->pwd.dentry) |
2081 | get_fs_pwd(current->fs, &context->pwd); | 2082 | get_fs_pwd(current->fs, &context->pwd); |
@@ -2166,7 +2167,7 @@ static void audit_copy_inode(struct audit_names *name, const struct dentry *dent | |||
2166 | * @dentry: dentry being audited | 2167 | * @dentry: dentry being audited |
2167 | * @parent: does this dentry represent the parent? | 2168 | * @parent: does this dentry represent the parent? |
2168 | */ | 2169 | */ |
2169 | void __audit_inode(const char *name, const struct dentry *dentry, | 2170 | void __audit_inode(struct filename *name, const struct dentry *dentry, |
2170 | unsigned int parent) | 2171 | unsigned int parent) |
2171 | { | 2172 | { |
2172 | struct audit_context *context = current->audit_context; | 2173 | struct audit_context *context = current->audit_context; |
@@ -2179,9 +2180,29 @@ void __audit_inode(const char *name, const struct dentry *dentry, | |||
2179 | if (!name) | 2180 | if (!name) |
2180 | goto out_alloc; | 2181 | goto out_alloc; |
2181 | 2182 | ||
2183 | #if AUDIT_DEBUG | ||
2184 | /* The struct filename _must_ have a populated ->name */ | ||
2185 | BUG_ON(!name->name); | ||
2186 | #endif | ||
2187 | /* | ||
2188 | * If we have a pointer to an audit_names entry already, then we can | ||
2189 | * just use it directly if the type is correct. | ||
2190 | */ | ||
2191 | n = name->aname; | ||
2192 | if (n) { | ||
2193 | if (parent) { | ||
2194 | if (n->type == AUDIT_TYPE_PARENT || | ||
2195 | n->type == AUDIT_TYPE_UNKNOWN) | ||
2196 | goto out; | ||
2197 | } else { | ||
2198 | if (n->type != AUDIT_TYPE_PARENT) | ||
2199 | goto out; | ||
2200 | } | ||
2201 | } | ||
2202 | |||
2182 | list_for_each_entry_reverse(n, &context->names_list, list) { | 2203 | list_for_each_entry_reverse(n, &context->names_list, list) { |
2183 | /* does the name pointer match? */ | 2204 | /* does the name pointer match? */ |
2184 | if (!n->name || n->name->name != name) | 2205 | if (!n->name || n->name->name != name->name) |
2185 | continue; | 2206 | continue; |
2186 | 2207 | ||
2187 | /* match the correct record type */ | 2208 | /* match the correct record type */ |