mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 12:44:11 +08:00
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>
This commit is contained in:
parent
05c7a9cb27
commit
57d4657716
@ -2720,7 +2720,7 @@ filename_mountpoint(int dfd, struct filename *name, struct path *path,
|
|||||||
if (unlikely(error == -ESTALE))
|
if (unlikely(error == -ESTALE))
|
||||||
error = path_mountpoint(&nd, flags | LOOKUP_REVAL, path);
|
error = path_mountpoint(&nd, flags | LOOKUP_REVAL, path);
|
||||||
if (likely(!error))
|
if (likely(!error))
|
||||||
audit_inode(name, path->dentry, 0);
|
audit_inode(name, path->dentry, flags & LOOKUP_NO_EVAL);
|
||||||
restore_nameidata();
|
restore_nameidata();
|
||||||
putname(name);
|
putname(name);
|
||||||
return error;
|
return error;
|
||||||
|
@ -1640,6 +1640,8 @@ int ksys_umount(char __user *name, int flags)
|
|||||||
if (!(flags & UMOUNT_NOFOLLOW))
|
if (!(flags & UMOUNT_NOFOLLOW))
|
||||||
lookup_flags |= LOOKUP_FOLLOW;
|
lookup_flags |= LOOKUP_FOLLOW;
|
||||||
|
|
||||||
|
lookup_flags |= LOOKUP_NO_EVAL;
|
||||||
|
|
||||||
retval = user_path_mountpoint_at(AT_FDCWD, name, lookup_flags, &path);
|
retval = user_path_mountpoint_at(AT_FDCWD, name, lookup_flags, &path);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
|
#include <linux/namei.h> /* LOOKUP_* */
|
||||||
#include <uapi/linux/audit.h>
|
#include <uapi/linux/audit.h>
|
||||||
|
|
||||||
#define AUDIT_INO_UNSET ((unsigned long)-1)
|
#define AUDIT_INO_UNSET ((unsigned long)-1)
|
||||||
@ -248,6 +249,7 @@ extern void __audit_getname(struct filename *name);
|
|||||||
|
|
||||||
#define AUDIT_INODE_PARENT 1 /* dentry represents the parent */
|
#define AUDIT_INODE_PARENT 1 /* dentry represents the parent */
|
||||||
#define AUDIT_INODE_HIDDEN 2 /* audit record should be hidden */
|
#define AUDIT_INODE_HIDDEN 2 /* audit record should be hidden */
|
||||||
|
#define AUDIT_INODE_NOEVAL 4 /* audit record incomplete */
|
||||||
extern void __audit_inode(struct filename *name, const struct dentry *dentry,
|
extern void __audit_inode(struct filename *name, const struct dentry *dentry,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
extern void __audit_file(const struct file *);
|
extern void __audit_file(const struct file *);
|
||||||
@ -308,12 +310,15 @@ static inline void audit_getname(struct filename *name)
|
|||||||
}
|
}
|
||||||
static inline void audit_inode(struct filename *name,
|
static inline void audit_inode(struct filename *name,
|
||||||
const struct dentry *dentry,
|
const struct dentry *dentry,
|
||||||
unsigned int parent) {
|
unsigned int flags) {
|
||||||
if (unlikely(!audit_dummy_context())) {
|
if (unlikely(!audit_dummy_context())) {
|
||||||
unsigned int flags = 0;
|
unsigned int aflags = 0;
|
||||||
if (parent)
|
|
||||||
flags |= AUDIT_INODE_PARENT;
|
if (flags & LOOKUP_PARENT)
|
||||||
__audit_inode(name, dentry, flags);
|
aflags |= AUDIT_INODE_PARENT;
|
||||||
|
if (flags & LOOKUP_NO_EVAL)
|
||||||
|
aflags |= AUDIT_INODE_NOEVAL;
|
||||||
|
__audit_inode(name, dentry, aflags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static inline void audit_file(struct file *file)
|
static inline void audit_file(struct file *file)
|
||||||
|
@ -24,6 +24,8 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
|
|||||||
* - internal "there are more path components" flag
|
* - internal "there are more path components" flag
|
||||||
* - dentry cache is untrusted; force a real lookup
|
* - dentry cache is untrusted; force a real lookup
|
||||||
* - suppress terminal automount
|
* - suppress terminal automount
|
||||||
|
* - skip revalidation
|
||||||
|
* - don't fetch xattrs on audit_inode
|
||||||
*/
|
*/
|
||||||
#define LOOKUP_FOLLOW 0x0001
|
#define LOOKUP_FOLLOW 0x0001
|
||||||
#define LOOKUP_DIRECTORY 0x0002
|
#define LOOKUP_DIRECTORY 0x0002
|
||||||
@ -33,6 +35,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
|
|||||||
#define LOOKUP_REVAL 0x0020
|
#define LOOKUP_REVAL 0x0020
|
||||||
#define LOOKUP_RCU 0x0040
|
#define LOOKUP_RCU 0x0040
|
||||||
#define LOOKUP_NO_REVAL 0x0080
|
#define LOOKUP_NO_REVAL 0x0080
|
||||||
|
#define LOOKUP_NO_EVAL 0x0100
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Intent data
|
* Intent data
|
||||||
|
@ -2082,6 +2082,10 @@ void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap)
|
|||||||
|
|
||||||
static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
|
static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
|
||||||
{
|
{
|
||||||
|
if (name->fcap_ver == -1) {
|
||||||
|
audit_log_format(ab, " cap_fe=? cap_fver=? cap_fp=? cap_fi=?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
audit_log_cap(ab, "cap_fp", &name->fcap.permitted);
|
audit_log_cap(ab, "cap_fp", &name->fcap.permitted);
|
||||||
audit_log_cap(ab, "cap_fi", &name->fcap.inheritable);
|
audit_log_cap(ab, "cap_fi", &name->fcap.inheritable);
|
||||||
audit_log_format(ab, " cap_fe=%d cap_fver=%x cap_frootid=%d",
|
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,
|
|||||||
|
|
||||||
/* Copy inode data into an audit_names. */
|
/* Copy inode data into an audit_names. */
|
||||||
void audit_copy_inode(struct audit_names *name, const struct dentry *dentry,
|
void audit_copy_inode(struct audit_names *name, const struct dentry *dentry,
|
||||||
struct inode *inode)
|
struct inode *inode, unsigned int flags)
|
||||||
{
|
{
|
||||||
name->ino = inode->i_ino;
|
name->ino = inode->i_ino;
|
||||||
name->dev = inode->i_sb->s_dev;
|
name->dev = inode->i_sb->s_dev;
|
||||||
@ -2123,6 +2127,10 @@ void audit_copy_inode(struct audit_names *name, const struct dentry *dentry,
|
|||||||
name->gid = inode->i_gid;
|
name->gid = inode->i_gid;
|
||||||
name->rdev = inode->i_rdev;
|
name->rdev = inode->i_rdev;
|
||||||
security_inode_getsecid(inode, &name->osid);
|
security_inode_getsecid(inode, &name->osid);
|
||||||
|
if (flags & AUDIT_INODE_NOEVAL) {
|
||||||
|
name->fcap_ver = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
audit_copy_fcaps(name, dentry);
|
audit_copy_fcaps(name, dentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +215,7 @@ extern void audit_log_session_info(struct audit_buffer *ab);
|
|||||||
|
|
||||||
extern void audit_copy_inode(struct audit_names *name,
|
extern void audit_copy_inode(struct audit_names *name,
|
||||||
const struct dentry *dentry,
|
const struct dentry *dentry,
|
||||||
struct inode *inode);
|
struct inode *inode, unsigned int flags);
|
||||||
extern void audit_log_cap(struct audit_buffer *ab, char *prefix,
|
extern void audit_log_cap(struct audit_buffer *ab, char *prefix,
|
||||||
kernel_cap_t *cap);
|
kernel_cap_t *cap);
|
||||||
extern void audit_log_name(struct audit_context *context,
|
extern void audit_log_name(struct audit_context *context,
|
||||||
|
@ -1856,7 +1856,7 @@ out:
|
|||||||
n->type = AUDIT_TYPE_NORMAL;
|
n->type = AUDIT_TYPE_NORMAL;
|
||||||
}
|
}
|
||||||
handle_path(dentry);
|
handle_path(dentry);
|
||||||
audit_copy_inode(n, dentry, inode);
|
audit_copy_inode(n, dentry, inode, flags & AUDIT_INODE_NOEVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __audit_file(const struct file *file)
|
void __audit_file(const struct file *file)
|
||||||
@ -1955,7 +1955,7 @@ void __audit_inode_child(struct inode *parent,
|
|||||||
n = audit_alloc_name(context, AUDIT_TYPE_PARENT);
|
n = audit_alloc_name(context, AUDIT_TYPE_PARENT);
|
||||||
if (!n)
|
if (!n)
|
||||||
return;
|
return;
|
||||||
audit_copy_inode(n, NULL, parent);
|
audit_copy_inode(n, NULL, parent, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found_child) {
|
if (!found_child) {
|
||||||
@ -1974,7 +1974,7 @@ void __audit_inode_child(struct inode *parent,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (inode)
|
if (inode)
|
||||||
audit_copy_inode(found_child, dentry, inode);
|
audit_copy_inode(found_child, dentry, inode, 0);
|
||||||
else
|
else
|
||||||
found_child->ino = AUDIT_INO_UNSET;
|
found_child->ino = AUDIT_INO_UNSET;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user