Skip to content

Commit

Permalink
[PATCH] log more info for directory entry change events
Browse files Browse the repository at this point in the history
When an audit event involves changes to a directory entry, include
a PATH record for the directory itself.  A few other notable changes:

    - fixed audit_inode_child() hooks in fsnotify_move()
    - removed unused flags arg from audit_inode()
    - added audit log routines for logging a portion of a string

Here's some sample output.

before patch:
type=SYSCALL msg=audit(1149821605.320:26): arch=40000003 syscall=39 success=yes exit=0 a0=bf8d3c7c a1=1ff a2=804e1b8 a3=bf8d3c7c items=1 ppid=739 pid=800 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=ttyS0 comm="mkdir" exe="/bin/mkdir" subj=root:system_r:unconfined_t:s0-s0:c0.c255
type=CWD msg=audit(1149821605.320:26):  cwd="/root"
type=PATH msg=audit(1149821605.320:26): item=0 name="foo" parent=164068 inode=164010 dev=03:00 mode=040755 ouid=0 ogid=0 rdev=00:00 obj=root:object_r:user_home_t:s0

after patch:
type=SYSCALL msg=audit(1149822032.332:24): arch=40000003 syscall=39 success=yes exit=0 a0=bfdd9c7c a1=1ff a2=804e1b8 a3=bfdd9c7c items=2 ppid=714 pid=777 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=ttyS0 comm="mkdir" exe="/bin/mkdir" subj=root:system_r:unconfined_t:s0-s0:c0.c255
type=CWD msg=audit(1149822032.332:24):  cwd="/root"
type=PATH msg=audit(1149822032.332:24): item=0 name="/root" inode=164068 dev=03:00 mode=040750 ouid=0 ogid=0 rdev=00:00 obj=root:object_r:user_home_dir_t:s0
type=PATH msg=audit(1149822032.332:24): item=1 name="foo" inode=164010 dev=03:00 mode=040755 ouid=0 ogid=0 rdev=00:00 obj=root:object_r:user_home_t:s0

Signed-off-by: Amy Griffis <amy.griffis@hp.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
Amy Griffis authored and Al Viro committed Jun 20, 2006
1 parent 6a2bcee commit 9c937dc
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 74 deletions.
2 changes: 1 addition & 1 deletion fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -1127,7 +1127,7 @@ static int fastcall do_path_lookup(int dfd, const char *name,
if (likely(retval == 0)) {
if (unlikely(current->audit_context && nd && nd->dentry &&
nd->dentry->d_inode))
audit_inode(name, nd->dentry->d_inode, flags);
audit_inode(name, nd->dentry->d_inode);
}
out_fail:
return retval;
Expand Down
4 changes: 2 additions & 2 deletions fs/open.c
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
dentry = file->f_dentry;
inode = dentry->d_inode;

audit_inode(NULL, inode, 0);
audit_inode(NULL, inode);

err = -EROFS;
if (IS_RDONLY(inode))
Expand Down Expand Up @@ -786,7 +786,7 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
if (file) {
struct dentry * dentry;
dentry = file->f_dentry;
audit_inode(NULL, dentry->d_inode, 0);
audit_inode(NULL, dentry->d_inode);
error = chown_common(dentry, user, group);
fput(file);
}
Expand Down
4 changes: 2 additions & 2 deletions fs/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ sys_fsetxattr(int fd, char __user *name, void __user *value,
if (!f)
return error;
dentry = f->f_dentry;
audit_inode(NULL, dentry->d_inode, 0);
audit_inode(NULL, dentry->d_inode);
error = setxattr(dentry, name, value, size, flags);
fput(f);
return error;
Expand Down Expand Up @@ -469,7 +469,7 @@ sys_fremovexattr(int fd, char __user *name)
if (!f)
return error;
dentry = f->f_dentry;
audit_inode(NULL, dentry->d_inode, 0);
audit_inode(NULL, dentry->d_inode);
error = removexattr(dentry, name);
fput(f);
return error;
Expand Down
15 changes: 9 additions & 6 deletions include/linux/audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,18 +310,17 @@ extern void audit_syscall_entry(int arch,
extern void audit_syscall_exit(int failed, long return_code);
extern void __audit_getname(const char *name);
extern void audit_putname(const char *name);
extern void __audit_inode(const char *name, const struct inode *inode, unsigned flags);
extern void __audit_inode(const char *name, const struct inode *inode);
extern void __audit_inode_child(const char *dname, const struct inode *inode,
unsigned long pino);
static inline void audit_getname(const char *name)
{
if (unlikely(current->audit_context))
__audit_getname(name);
}
static inline void audit_inode(const char *name, const struct inode *inode,
unsigned flags) {
static inline void audit_inode(const char *name, const struct inode *inode) {
if (unlikely(current->audit_context))
__audit_inode(name, inode, flags);
__audit_inode(name, inode);
}
static inline void audit_inode_child(const char *dname,
const struct inode *inode,
Expand Down Expand Up @@ -398,9 +397,9 @@ static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
#define audit_syscall_exit(f,r) do { ; } while (0)
#define audit_getname(n) do { ; } while (0)
#define audit_putname(n) do { ; } while (0)
#define __audit_inode(n,i,f) do { ; } while (0)
#define __audit_inode(n,i) do { ; } while (0)
#define __audit_inode_child(d,i,p) do { ; } while (0)
#define audit_inode(n,i,f) do { ; } while (0)
#define audit_inode(n,i) do { ; } while (0)
#define audit_inode_child(d,i,p) do { ; } while (0)
#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
#define audit_get_loginuid(c) ({ -1; })
Expand Down Expand Up @@ -435,6 +434,9 @@ extern void audit_log_hex(struct audit_buffer *ab,
size_t len);
extern const char * audit_log_untrustedstring(struct audit_buffer *ab,
const char *string);
extern const char * audit_log_n_untrustedstring(struct audit_buffer *ab,
size_t n,
const char *string);
extern void audit_log_d_path(struct audit_buffer *ab,
const char *prefix,
struct dentry *dentry,
Expand All @@ -452,6 +454,7 @@ extern int audit_receive_filter(int type, int pid, int uid, int seq,
#define audit_log_end(b) do { ; } while (0)
#define audit_log_hex(a,b,l) do { ; } while (0)
#define audit_log_untrustedstring(a,s) do { ; } while (0)
#define audit_log_n_untrustedstring(a,n,s) do { ; } while (0)
#define audit_log_d_path(b,p,d,v) do { ; } while (0)
#endif
#endif
Expand Down
3 changes: 1 addition & 2 deletions include/linux/fsnotify.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
if (source) {
inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL);
}
audit_inode_child(old_name, source, old_dir->i_ino);
audit_inode_child(new_name, target, new_dir->i_ino);
audit_inode_child(new_name, source, new_dir->i_ino);
}

/*
Expand Down
54 changes: 50 additions & 4 deletions kernel/audit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1051,20 +1051,53 @@ void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf,
skb_put(skb, len << 1); /* new string is twice the old string */
}

/*
* Format a string of no more than slen characters into the audit buffer,
* enclosed in quote marks.
*/
static void audit_log_n_string(struct audit_buffer *ab, size_t slen,
const char *string)
{
int avail, new_len;
unsigned char *ptr;
struct sk_buff *skb;

BUG_ON(!ab->skb);
skb = ab->skb;
avail = skb_tailroom(skb);
new_len = slen + 3; /* enclosing quotes + null terminator */
if (new_len > avail) {
avail = audit_expand(ab, new_len);
if (!avail)
return;
}
ptr = skb->tail;
*ptr++ = '"';
memcpy(ptr, string, slen);
ptr += slen;
*ptr++ = '"';
*ptr = 0;
skb_put(skb, slen + 2); /* don't include null terminator */
}

/**
* audit_log_unstrustedstring - log a string that may contain random characters
* audit_log_n_unstrustedstring - log a string that may contain random characters
* @ab: audit_buffer
* @len: lenth of string (not including trailing null)
* @string: string to be logged
*
* This code will escape a string that is passed to it if the string
* contains a control character, unprintable character, double quote mark,
* or a space. Unescaped strings will start and end with a double quote mark.
* Strings that are escaped are printed in hex (2 digits per char).
*
* The caller specifies the number of characters in the string to log, which may
* or may not be the entire string.
*/
const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len,
const char *string)
{
const unsigned char *p = string;
size_t len = strlen(string);

while (*p) {
if (*p == '"' || *p < 0x21 || *p > 0x7f) {
Expand All @@ -1073,10 +1106,23 @@ const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *strin
}
p++;
}
audit_log_format(ab, "\"%s\"", string);
audit_log_n_string(ab, len, string);
return p + 1;
}

/**
* audit_log_unstrustedstring - log a string that may contain random characters
* @ab: audit_buffer
* @string: string to be logged
*
* Same as audit_log_n_unstrustedstring(), except that strlen is used to
* determine string length.
*/
const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
{
return audit_log_n_untrustedstring(ab, strlen(string), string);
}

/* This is a helper-function to print the escaped d_path */
void audit_log_d_path(struct audit_buffer *ab, const char *prefix,
struct dentry *dentry, struct vfsmount *vfsmnt)
Expand Down
3 changes: 2 additions & 1 deletion kernel/audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ static inline int audit_hash_ino(u32 ino)
}

extern int audit_comparator(const u32 left, const u32 op, const u32 right);
extern int audit_compare_dname_path(const char *dname, const char *path);
extern int audit_compare_dname_path(const char *dname, const char *path,
int *dirlen);
extern struct sk_buff * audit_make_reply(int pid, int seq, int type,
int done, int multi,
void *payload, int size);
Expand Down
8 changes: 6 additions & 2 deletions kernel/auditfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -787,7 +787,7 @@ static void audit_update_watch(struct audit_parent *parent,

mutex_lock(&audit_filter_mutex);
list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) {
if (audit_compare_dname_path(dname, owatch->path))
if (audit_compare_dname_path(dname, owatch->path, NULL))
continue;

/* If the update involves invalidating rules, do the inode-based
Expand Down Expand Up @@ -1387,7 +1387,8 @@ int audit_comparator(const u32 left, const u32 op, const u32 right)

/* Compare given dentry name with last component in given path,
* return of 0 indicates a match. */
int audit_compare_dname_path(const char *dname, const char *path)
int audit_compare_dname_path(const char *dname, const char *path,
int *dirlen)
{
int dlen, plen;
const char *p;
Expand Down Expand Up @@ -1416,6 +1417,9 @@ int audit_compare_dname_path(const char *dname, const char *path)
p++;
}

/* return length of path's directory component */
if (dirlen)
*dirlen = p - path;
return strncmp(p, dname, dlen);
}

Expand Down
Loading

0 comments on commit 9c937dc

Please sign in to comment.