Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 23979
b: refs/heads/master
c: 73241cc
h: refs/heads/master
i:
  23977: 397c51c
  23975: 06ddbd5
v: v3
  • Loading branch information
Amy Griffis authored and Al Viro committed Mar 20, 2006
1 parent e496f0d commit 11accf1
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 29 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f38aa94224c5517a40ba56d453779f70d3229803
refs/heads/master: 73241ccca0f7786933f1d31b3d86f2456549953a
1 change: 1 addition & 0 deletions trunk/fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -1353,6 +1353,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
return -ENOENT;

BUG_ON(victim->d_parent->d_inode != dir);
audit_inode_child(victim->d_name.name, victim->d_inode, dir->i_ino);

error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
if (error)
Expand Down
8 changes: 7 additions & 1 deletion trunk/fs/open.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <linux/pagemap.h>
#include <linux/syscalls.h>
#include <linux/rcupdate.h>
#include <linux/audit.h>

#include <asm/unistd.h>

Expand Down Expand Up @@ -626,6 +627,8 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
dentry = file->f_dentry;
inode = dentry->d_inode;

audit_inode(NULL, inode, 0);

err = -EROFS;
if (IS_RDONLY(inode))
goto out_putf;
Expand Down Expand Up @@ -775,7 +778,10 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)

file = fget(fd);
if (file) {
error = chown_common(file->f_dentry, user, group);
struct dentry * dentry;
dentry = file->f_dentry;
audit_inode(NULL, dentry->d_inode, 0);
error = chown_common(dentry, user, group);
fput(file);
}
return error;
Expand Down
11 changes: 9 additions & 2 deletions trunk/fs/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <linux/syscalls.h>
#include <linux/module.h>
#include <linux/fsnotify.h>
#include <linux/audit.h>
#include <asm/uaccess.h>


Expand Down Expand Up @@ -234,12 +235,15 @@ sys_fsetxattr(int fd, char __user *name, void __user *value,
size_t size, int flags)
{
struct file *f;
struct dentry *dentry;
int error = -EBADF;

f = fget(fd);
if (!f)
return error;
error = setxattr(f->f_dentry, name, value, size, flags);
dentry = f->f_dentry;
audit_inode(NULL, dentry->d_inode, 0);
error = setxattr(dentry, name, value, size, flags);
fput(f);
return error;
}
Expand Down Expand Up @@ -458,12 +462,15 @@ asmlinkage long
sys_fremovexattr(int fd, char __user *name)
{
struct file *f;
struct dentry *dentry;
int error = -EBADF;

f = fget(fd);
if (!f)
return error;
error = removexattr(f->f_dentry, name);
dentry = f->f_dentry;
audit_inode(NULL, dentry->d_inode, 0);
error = removexattr(dentry, name);
fput(f);
return error;
}
Expand Down
18 changes: 17 additions & 1 deletion trunk/include/linux/audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,20 @@ extern void audit_syscall_entry(struct task_struct *task, int arch,
extern void audit_syscall_exit(struct task_struct *task, 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, unsigned flags);
extern void __audit_inode_child(const char *dname, const struct inode *inode,
unsigned long pino);
static inline void audit_inode(const char *name, const struct inode *inode,
unsigned flags) {
if (unlikely(current->audit_context))
__audit_inode(name, inode, flags);
}
static inline void audit_inode_child(const char *dname,
const struct inode *inode,
unsigned long pino) {
if (unlikely(current->audit_context))
__audit_inode_child(dname, inode, pino);
}

/* Private API (for audit.c only) */
extern int audit_receive_filter(int type, int pid, int uid, int seq,
Expand All @@ -283,7 +296,10 @@ extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
#define audit_syscall_exit(t,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_child(d,i,p) do { ; } while (0)
#define audit_inode(n,i,f) do { ; } while (0)
#define audit_inode_child(d,i,p) do { ; } while (0)
#define audit_receive_filter(t,p,u,s,d,l) ({ -EOPNOTSUPP; })
#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
#define audit_get_loginuid(c) ({ -1; })
Expand Down
5 changes: 5 additions & 0 deletions trunk/include/linux/fsnotify.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include <linux/dnotify.h>
#include <linux/inotify.h>
#include <linux/audit.h>

/*
* fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
Expand Down Expand Up @@ -45,6 +46,8 @@ 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);
}
audit_inode_child(old_name, source, old_dir->i_ino);
audit_inode_child(new_name, target, new_dir->i_ino);
}

/*
Expand Down Expand Up @@ -74,6 +77,7 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
{
inode_dir_notify(inode, DN_CREATE);
inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name);
audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino);
}

/*
Expand All @@ -84,6 +88,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
inode_dir_notify(inode, DN_CREATE);
inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0,
dentry->d_name.name);
audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino);
}

/*
Expand Down
142 changes: 118 additions & 24 deletions trunk/kernel/auditsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Handles all system-call specific auditing features.
*
* Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
* Copyright 2005 Hewlett-Packard Development Company, L.P.
* Copyright (C) 2005 IBM Corporation
* All Rights Reserved.
*
Expand Down Expand Up @@ -31,11 +32,16 @@
* The support of additional filter rules compares (>, <, >=, <=) was
* added by Dustin Kirkland <dustin.kirkland@us.ibm.com>, 2005.
*
* Modified by Amy Griffis <amy.griffis@hp.com> to collect additional
* filesystem information.
*/

#include <linux/init.h>
#include <asm/types.h>
#include <asm/atomic.h>
#include <asm/types.h>
#include <linux/fs.h>
#include <linux/namei.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/mount.h>
Expand Down Expand Up @@ -97,12 +103,12 @@ enum audit_state {
struct audit_names {
const char *name;
unsigned long ino;
unsigned long pino;
dev_t dev;
umode_t mode;
uid_t uid;
gid_t gid;
dev_t rdev;
unsigned flags;
};

struct audit_aux_data {
Expand Down Expand Up @@ -515,7 +521,8 @@ static int audit_filter_rules(struct task_struct *tsk,
case AUDIT_INODE:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
if ( audit_comparator(ctx->names[j].ino, op, value)) {
if (audit_comparator(ctx->names[j].ino, op, value) ||
audit_comparator(ctx->names[j].pino, op, value)) {
++result;
break;
}
Expand Down Expand Up @@ -696,17 +703,17 @@ static inline void audit_free_names(struct audit_context *context)
#if AUDIT_DEBUG == 2
if (context->auditable
||context->put_count + context->ino_count != context->name_count) {
printk(KERN_ERR "audit.c:%d(:%d): major=%d in_syscall=%d"
printk(KERN_ERR "%s:%d(:%d): major=%d in_syscall=%d"
" name_count=%d put_count=%d"
" ino_count=%d [NOT freeing]\n",
__LINE__,
__FILE__, __LINE__,
context->serial, context->major, context->in_syscall,
context->name_count, context->put_count,
context->ino_count);
for (i = 0; i < context->name_count; i++)
printk(KERN_ERR "names[%d] = %p = %s\n", i,
context->names[i].name,
context->names[i].name);
context->names[i].name ?: "(null)");
dump_stack();
return;
}
Expand Down Expand Up @@ -932,27 +939,34 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
}
}
for (i = 0; i < context->name_count; i++) {
unsigned long ino = context->names[i].ino;
unsigned long pino = context->names[i].pino;

ab = audit_log_start(context, gfp_mask, AUDIT_PATH);
if (!ab)
continue; /* audit_panic has been called */

audit_log_format(ab, "item=%d", i);
if (context->names[i].name) {
audit_log_format(ab, " name=");

audit_log_format(ab, " name=");
if (context->names[i].name)
audit_log_untrustedstring(ab, context->names[i].name);
}
audit_log_format(ab, " flags=%x\n", context->names[i].flags);

if (context->names[i].ino != (unsigned long)-1)
audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o"
" ouid=%u ogid=%u rdev=%02x:%02x",
context->names[i].ino,
MAJOR(context->names[i].dev),
MINOR(context->names[i].dev),
context->names[i].mode,
context->names[i].uid,
context->names[i].gid,
MAJOR(context->names[i].rdev),
else
audit_log_format(ab, "(null)");

if (pino != (unsigned long)-1)
audit_log_format(ab, " parent=%lu", pino);
if (ino != (unsigned long)-1)
audit_log_format(ab, " inode=%lu", ino);
if ((pino != (unsigned long)-1) || (ino != (unsigned long)-1))
audit_log_format(ab, " dev=%02x:%02x mode=%#o"
" ouid=%u ogid=%u rdev=%02x:%02x",
MAJOR(context->names[i].dev),
MINOR(context->names[i].dev),
context->names[i].mode,
context->names[i].uid,
context->names[i].gid,
MAJOR(context->names[i].rdev),
MINOR(context->names[i].rdev));
audit_log_end(ab);
}
Expand Down Expand Up @@ -1174,7 +1188,7 @@ void audit_putname(const char *name)
for (i = 0; i < context->name_count; i++)
printk(KERN_ERR "name[%d] = %p = %s\n", i,
context->names[i].name,
context->names[i].name);
context->names[i].name ?: "(null)");
}
#endif
__putname(name);
Expand Down Expand Up @@ -1204,7 +1218,7 @@ void audit_putname(const char *name)
*
* Called from fs/namei.c:path_lookup().
*/
void audit_inode(const char *name, const struct inode *inode, unsigned flags)
void __audit_inode(const char *name, const struct inode *inode, unsigned flags)
{
int idx;
struct audit_context *context = current->audit_context;
Expand All @@ -1230,13 +1244,93 @@ void audit_inode(const char *name, const struct inode *inode, unsigned flags)
++context->ino_count;
#endif
}
context->names[idx].flags = flags;
context->names[idx].ino = inode->i_ino;
context->names[idx].dev = inode->i_sb->s_dev;
context->names[idx].mode = inode->i_mode;
context->names[idx].uid = inode->i_uid;
context->names[idx].gid = inode->i_gid;
context->names[idx].rdev = inode->i_rdev;
if ((flags & LOOKUP_PARENT) && (strcmp(name, "/") != 0) &&
(strcmp(name, ".") != 0)) {
context->names[idx].ino = (unsigned long)-1;
context->names[idx].pino = inode->i_ino;
} else {
context->names[idx].ino = inode->i_ino;
context->names[idx].pino = (unsigned long)-1;
}
}

/**
* audit_inode_child - collect inode info for created/removed objects
* @dname: inode's dentry name
* @inode: inode being audited
* @pino: inode number of dentry parent
*
* For syscalls that create or remove filesystem objects, audit_inode
* can only collect information for the filesystem object's parent.
* This call updates the audit context with the child's information.
* Syscalls that create a new filesystem object must be hooked after
* the object is created. Syscalls that remove a filesystem object
* must be hooked prior, in order to capture the target inode during
* unsuccessful attempts.
*/
void __audit_inode_child(const char *dname, const struct inode *inode,
unsigned long pino)
{
int idx;
struct audit_context *context = current->audit_context;

if (!context->in_syscall)
return;

/* determine matching parent */
if (dname)
for (idx = 0; idx < context->name_count; idx++)
if (context->names[idx].pino == pino) {
const char *n;
const char *name = context->names[idx].name;
int dlen = strlen(dname);
int nlen = name ? strlen(name) : 0;

if (nlen < dlen)
continue;

/* disregard trailing slashes */
n = name + nlen - 1;
while ((*n == '/') && (n > name))
n--;

/* find last path component */
n = n - dlen + 1;
if (n < name)
continue;
else if (n > name) {
if (*--n != '/')
continue;
else
n++;
}

if (strncmp(n, dname, dlen) == 0)
goto update_context;
}

/* catch-all in case match not found */
idx = context->name_count++;
context->names[idx].name = NULL;
context->names[idx].pino = pino;
#if AUDIT_DEBUG
context->ino_count++;
#endif

update_context:
if (inode) {
context->names[idx].ino = inode->i_ino;
context->names[idx].dev = inode->i_sb->s_dev;
context->names[idx].mode = inode->i_mode;
context->names[idx].uid = inode->i_uid;
context->names[idx].gid = inode->i_gid;
context->names[idx].rdev = inode->i_rdev;
}
}

/**
Expand Down

0 comments on commit 11accf1

Please sign in to comment.