diff options
| -rw-r--r-- | fs/namei.c | 2 | ||||
| -rw-r--r-- | fs/namespace.c | 2 | ||||
| -rw-r--r-- | include/linux/audit.h | 15 | ||||
| -rw-r--r-- | include/linux/namei.h | 3 | ||||
| -rw-r--r-- | kernel/audit.c | 10 | ||||
| -rw-r--r-- | kernel/audit.h | 2 | ||||
| -rw-r--r-- | kernel/auditsc.c | 6 |
7 files changed, 29 insertions, 11 deletions
diff --git a/fs/namei.c b/fs/namei.c index 914178cdbe94..87d7710a2e1d 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -2720,7 +2720,7 @@ filename_mountpoint(int dfd, struct filename *name, struct path *path, | |||
| 2720 | if (unlikely(error == -ESTALE)) | 2720 | if (unlikely(error == -ESTALE)) |
| 2721 | error = path_mountpoint(&nd, flags | LOOKUP_REVAL, path); | 2721 | error = path_mountpoint(&nd, flags | LOOKUP_REVAL, path); |
| 2722 | if (likely(!error)) | 2722 | if (likely(!error)) |
| 2723 | audit_inode(name, path->dentry, 0); | 2723 | audit_inode(name, path->dentry, flags & LOOKUP_NO_EVAL); |
| 2724 | restore_nameidata(); | 2724 | restore_nameidata(); |
| 2725 | putname(name); | 2725 | putname(name); |
| 2726 | return error; | 2726 | return error; |
diff --git a/fs/namespace.c b/fs/namespace.c index a677b59efd74..e5de0e372df2 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -1640,6 +1640,8 @@ int ksys_umount(char __user *name, int flags) | |||
| 1640 | if (!(flags & UMOUNT_NOFOLLOW)) | 1640 | if (!(flags & UMOUNT_NOFOLLOW)) |
| 1641 | lookup_flags |= LOOKUP_FOLLOW; | 1641 | lookup_flags |= LOOKUP_FOLLOW; |
| 1642 | 1642 | ||
| 1643 | lookup_flags |= LOOKUP_NO_EVAL; | ||
| 1644 | |||
| 1643 | retval = user_path_mountpoint_at(AT_FDCWD, name, lookup_flags, &path); | 1645 | retval = user_path_mountpoint_at(AT_FDCWD, name, lookup_flags, &path); |
| 1644 | if (retval) | 1646 | if (retval) |
| 1645 | goto out; | 1647 | goto out; |
diff --git a/include/linux/audit.h b/include/linux/audit.h index ecb5d317d6a2..29251b18331a 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | 25 | ||
| 26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
| 27 | #include <linux/ptrace.h> | 27 | #include <linux/ptrace.h> |
| 28 | #include <linux/namei.h> /* LOOKUP_* */ | ||
| 28 | #include <uapi/linux/audit.h> | 29 | #include <uapi/linux/audit.h> |
| 29 | 30 | ||
| 30 | #define AUDIT_INO_UNSET ((unsigned long)-1) | 31 | #define AUDIT_INO_UNSET ((unsigned long)-1) |
| @@ -248,6 +249,7 @@ extern void __audit_getname(struct filename *name); | |||
| 248 | 249 | ||
| 249 | #define AUDIT_INODE_PARENT 1 /* dentry represents the parent */ | 250 | #define AUDIT_INODE_PARENT 1 /* dentry represents the parent */ |
| 250 | #define AUDIT_INODE_HIDDEN 2 /* audit record should be hidden */ | 251 | #define AUDIT_INODE_HIDDEN 2 /* audit record should be hidden */ |
| 252 | #define AUDIT_INODE_NOEVAL 4 /* audit record incomplete */ | ||
| 251 | extern void __audit_inode(struct filename *name, const struct dentry *dentry, | 253 | extern void __audit_inode(struct filename *name, const struct dentry *dentry, |
| 252 | unsigned int flags); | 254 | unsigned int flags); |
| 253 | extern void __audit_file(const struct file *); | 255 | extern void __audit_file(const struct file *); |
| @@ -308,12 +310,15 @@ static inline void audit_getname(struct filename *name) | |||
| 308 | } | 310 | } |
| 309 | static inline void audit_inode(struct filename *name, | 311 | static inline void audit_inode(struct filename *name, |
| 310 | const struct dentry *dentry, | 312 | const struct dentry *dentry, |
| 311 | unsigned int parent) { | 313 | unsigned int flags) { |
| 312 | if (unlikely(!audit_dummy_context())) { | 314 | if (unlikely(!audit_dummy_context())) { |
| 313 | unsigned int flags = 0; | 315 | unsigned int aflags = 0; |
| 314 | if (parent) | 316 | |
| 315 | flags |= AUDIT_INODE_PARENT; | 317 | if (flags & LOOKUP_PARENT) |
| 316 | __audit_inode(name, dentry, flags); | 318 | aflags |= AUDIT_INODE_PARENT; |
| 319 | if (flags & LOOKUP_NO_EVAL) | ||
| 320 | aflags |= AUDIT_INODE_NOEVAL; | ||
| 321 | __audit_inode(name, dentry, aflags); | ||
| 317 | } | 322 | } |
| 318 | } | 323 | } |
| 319 | static inline void audit_file(struct file *file) | 324 | static inline void audit_file(struct file *file) |
diff --git a/include/linux/namei.h b/include/linux/namei.h index a78606e8e3df..9138b4471dbf 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h | |||
| @@ -24,6 +24,8 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; | |||
| 24 | * - internal "there are more path components" flag | 24 | * - internal "there are more path components" flag |
| 25 | * - dentry cache is untrusted; force a real lookup | 25 | * - dentry cache is untrusted; force a real lookup |
| 26 | * - suppress terminal automount | 26 | * - suppress terminal automount |
| 27 | * - skip revalidation | ||
| 28 | * - don't fetch xattrs on audit_inode | ||
| 27 | */ | 29 | */ |
| 28 | #define LOOKUP_FOLLOW 0x0001 | 30 | #define LOOKUP_FOLLOW 0x0001 |
| 29 | #define LOOKUP_DIRECTORY 0x0002 | 31 | #define LOOKUP_DIRECTORY 0x0002 |
| @@ -33,6 +35,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; | |||
| 33 | #define LOOKUP_REVAL 0x0020 | 35 | #define LOOKUP_REVAL 0x0020 |
| 34 | #define LOOKUP_RCU 0x0040 | 36 | #define LOOKUP_RCU 0x0040 |
| 35 | #define LOOKUP_NO_REVAL 0x0080 | 37 | #define LOOKUP_NO_REVAL 0x0080 |
| 38 | #define LOOKUP_NO_EVAL 0x0100 | ||
| 36 | 39 | ||
| 37 | /* | 40 | /* |
| 38 | * Intent data | 41 | * Intent data |
diff --git a/kernel/audit.c b/kernel/audit.c index 3f3f1888cac7..b7177a8def2e 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
| @@ -2082,6 +2082,10 @@ void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap) | |||
| 2082 | 2082 | ||
| 2083 | static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name) | 2083 | static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name) |
| 2084 | { | 2084 | { |
| 2085 | if (name->fcap_ver == -1) { | ||
| 2086 | audit_log_format(ab, " cap_fe=? cap_fver=? cap_fp=? cap_fi=?"); | ||
| 2087 | return; | ||
| 2088 | } | ||
| 2085 | audit_log_cap(ab, "cap_fp", &name->fcap.permitted); | 2089 | audit_log_cap(ab, "cap_fp", &name->fcap.permitted); |
| 2086 | audit_log_cap(ab, "cap_fi", &name->fcap.inheritable); | 2090 | audit_log_cap(ab, "cap_fi", &name->fcap.inheritable); |
| 2087 | audit_log_format(ab, " cap_fe=%d cap_fver=%x cap_frootid=%d", | 2091 | audit_log_format(ab, " cap_fe=%d cap_fver=%x cap_frootid=%d", |
| @@ -2114,7 +2118,7 @@ static inline int audit_copy_fcaps(struct audit_names *name, | |||
| 2114 | 2118 | ||
| 2115 | /* Copy inode data into an audit_names. */ | 2119 | /* Copy inode data into an audit_names. */ |
| 2116 | void audit_copy_inode(struct audit_names *name, const struct dentry *dentry, | 2120 | void audit_copy_inode(struct audit_names *name, const struct dentry *dentry, |
| 2117 | struct inode *inode) | 2121 | struct inode *inode, unsigned int flags) |
| 2118 | { | 2122 | { |
| 2119 | name->ino = inode->i_ino; | 2123 | name->ino = inode->i_ino; |
| 2120 | name->dev = inode->i_sb->s_dev; | 2124 | name->dev = inode->i_sb->s_dev; |
| @@ -2123,6 +2127,10 @@ void audit_copy_inode(struct audit_names *name, const struct dentry *dentry, | |||
| 2123 | name->gid = inode->i_gid; | 2127 | name->gid = inode->i_gid; |
| 2124 | name->rdev = inode->i_rdev; | 2128 | name->rdev = inode->i_rdev; |
| 2125 | security_inode_getsecid(inode, &name->osid); | 2129 | security_inode_getsecid(inode, &name->osid); |
| 2130 | if (flags & AUDIT_INODE_NOEVAL) { | ||
| 2131 | name->fcap_ver = -1; | ||
| 2132 | return; | ||
| 2133 | } | ||
| 2126 | audit_copy_fcaps(name, dentry); | 2134 | audit_copy_fcaps(name, dentry); |
| 2127 | } | 2135 | } |
| 2128 | 2136 | ||
diff --git a/kernel/audit.h b/kernel/audit.h index 9acb8691ed87..002f0f7ba732 100644 --- a/kernel/audit.h +++ b/kernel/audit.h | |||
| @@ -215,7 +215,7 @@ extern void audit_log_session_info(struct audit_buffer *ab); | |||
| 215 | 215 | ||
| 216 | extern void audit_copy_inode(struct audit_names *name, | 216 | extern void audit_copy_inode(struct audit_names *name, |
| 217 | const struct dentry *dentry, | 217 | const struct dentry *dentry, |
| 218 | struct inode *inode); | 218 | struct inode *inode, unsigned int flags); |
| 219 | extern void audit_log_cap(struct audit_buffer *ab, char *prefix, | 219 | extern void audit_log_cap(struct audit_buffer *ab, char *prefix, |
| 220 | kernel_cap_t *cap); | 220 | kernel_cap_t *cap); |
| 221 | extern void audit_log_name(struct audit_context *context, | 221 | extern void audit_log_name(struct audit_context *context, |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index a2696ce790f9..68da71001096 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -1856,7 +1856,7 @@ out: | |||
| 1856 | n->type = AUDIT_TYPE_NORMAL; | 1856 | n->type = AUDIT_TYPE_NORMAL; |
| 1857 | } | 1857 | } |
| 1858 | handle_path(dentry); | 1858 | handle_path(dentry); |
| 1859 | audit_copy_inode(n, dentry, inode); | 1859 | audit_copy_inode(n, dentry, inode, flags & AUDIT_INODE_NOEVAL); |
| 1860 | } | 1860 | } |
| 1861 | 1861 | ||
| 1862 | void __audit_file(const struct file *file) | 1862 | void __audit_file(const struct file *file) |
| @@ -1955,7 +1955,7 @@ void __audit_inode_child(struct inode *parent, | |||
| 1955 | n = audit_alloc_name(context, AUDIT_TYPE_PARENT); | 1955 | n = audit_alloc_name(context, AUDIT_TYPE_PARENT); |
| 1956 | if (!n) | 1956 | if (!n) |
| 1957 | return; | 1957 | return; |
| 1958 | audit_copy_inode(n, NULL, parent); | 1958 | audit_copy_inode(n, NULL, parent, 0); |
| 1959 | } | 1959 | } |
| 1960 | 1960 | ||
| 1961 | if (!found_child) { | 1961 | if (!found_child) { |
| @@ -1974,7 +1974,7 @@ void __audit_inode_child(struct inode *parent, | |||
| 1974 | } | 1974 | } |
| 1975 | 1975 | ||
| 1976 | if (inode) | 1976 | if (inode) |
| 1977 | audit_copy_inode(found_child, dentry, inode); | 1977 | audit_copy_inode(found_child, dentry, inode, 0); |
| 1978 | else | 1978 | else |
| 1979 | found_child->ino = AUDIT_INO_UNSET; | 1979 | found_child->ino = AUDIT_INO_UNSET; |
| 1980 | } | 1980 | } |
