summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Guy Briggs <rgb@redhat.com>2019-01-23 13:35:00 -0500
committerPaul Moore <paul@paul-moore.com>2019-01-30 20:51:47 -0500
commit57d4657716aca81ef4d7ec23e8123d26e3d28954 (patch)
tree61af3d955d7a01767f7d1e6ede67ca6096cc8a07
parent05c7a9cb2727cd3c3d8e767f48e5cd18486a8d16 (diff)
audit: ignore fcaps on umount
Don't fetch fcaps when umount2 is called to avoid a process hang while it waits for the missing resource to (possibly never) re-appear. Note the comment above user_path_mountpoint_at(): * A umount is a special case for path walking. We're not actually interested * in the inode in this situation, and ESTALE errors can be a problem. We * simply want track down the dentry and vfsmount attached at the mountpoint * and avoid revalidating the last component. This can happen on ceph, cifs, 9p, lustre, fuse (gluster) or NFS. Please see the github issue tracker https://github.com/linux-audit/audit-kernel/issues/100 Signed-off-by: Richard Guy Briggs <rgb@redhat.com> [PM: merge fuzz in audit_log_fcaps()] Signed-off-by: Paul Moore <paul@paul-moore.com>
-rw-r--r--fs/namei.c2
-rw-r--r--fs/namespace.c2
-rw-r--r--include/linux/audit.h15
-rw-r--r--include/linux/namei.h3
-rw-r--r--kernel/audit.c10
-rw-r--r--kernel/audit.h2
-rw-r--r--kernel/auditsc.c6
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 */
251extern void __audit_inode(struct filename *name, const struct dentry *dentry, 253extern void __audit_inode(struct filename *name, const struct dentry *dentry,
252 unsigned int flags); 254 unsigned int flags);
253extern void __audit_file(const struct file *); 255extern void __audit_file(const struct file *);
@@ -308,12 +310,15 @@ static inline void audit_getname(struct filename *name)
308} 310}
309static inline void audit_inode(struct filename *name, 311static 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}
319static inline void audit_file(struct file *file) 324static 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
2083static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name) 2083static 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. */
2116void audit_copy_inode(struct audit_names *name, const struct dentry *dentry, 2120void 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
216extern void audit_copy_inode(struct audit_names *name, 216extern 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);
219extern void audit_log_cap(struct audit_buffer *ab, char *prefix, 219extern void audit_log_cap(struct audit_buffer *ab, char *prefix,
220 kernel_cap_t *cap); 220 kernel_cap_t *cap);
221extern void audit_log_name(struct audit_context *context, 221extern 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
1862void __audit_file(const struct file *file) 1862void __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}