Commit cae3cf8f authored by Linus Torvalds's avatar Linus Torvalds

Merge

parents 94dad77b 76ae6d56
......@@ -26,6 +26,7 @@
#include <linux/smp_lock.h>
#include <linux/user.h>
#include <linux/security.h>
#include <linux/audit.h>
#include <asm/cpu.h>
#include <asm/fpu.h>
......
......@@ -31,6 +31,7 @@
#include <linux/ptrace.h>
#include <linux/user.h>
#include <linux/security.h>
#include <linux/audit.h>
#include <asm/segment.h>
#include <asm/page.h>
......
......@@ -9,6 +9,7 @@
#include "linux/smp_lock.h"
#include "linux/security.h"
#include "linux/ptrace.h"
#include "linux/audit.h"
#ifdef CONFIG_PROC_MM
#include "linux/proc_mm.h"
#endif
......@@ -336,11 +337,15 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
if (unlikely(current->audit_context)) {
if (!entryexit)
audit_syscall_entry(current, regs->orig_eax,
regs->ebx, regs->ecx,
regs->edx, regs->esi);
audit_syscall_entry(current,
UPT_SYSCALL_NR(&regs->regs),
UPT_SYSCALL_ARG1(&regs->regs),
UPT_SYSCALL_ARG2(&regs->regs),
UPT_SYSCALL_ARG3(&regs->regs),
UPT_SYSCALL_ARG4(&regs->regs));
else
audit_syscall_exit(current, regs->eax);
audit_syscall_exit(current,
UPT_SYSCALL_RET(&regs->regs));
}
/* Fake a debug trap */
......
......@@ -148,11 +148,22 @@ char * getname(const char __user * filename)
result = ERR_PTR(retval);
}
}
if (unlikely(current->audit_context) && !IS_ERR(result) && result)
audit_getname(result);
audit_getname(result);
return result;
}
#ifdef CONFIG_AUDITSYSCALL
void putname(const char *name)
{
if (unlikely(current->audit_context))
audit_putname(name);
else
__putname(name);
}
EXPORT_SYMBOL(putname);
#endif
/**
* generic_permission - check for access rights on a Posix-like filesystem
* @inode: inode to check access rights for
......@@ -1012,9 +1023,7 @@ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata
retval = link_path_walk(name, nd);
if (unlikely(current->audit_context
&& nd && nd->dentry && nd->dentry->d_inode))
audit_inode(name,
nd->dentry->d_inode->i_ino,
nd->dentry->d_inode->i_rdev);
audit_inode(name, nd->dentry->d_inode);
return retval;
}
......
......@@ -34,6 +34,7 @@
#include <linux/ptrace.h>
#include <linux/seccomp.h>
#include <linux/cpuset.h>
#include <linux/audit.h>
#include "internal.h"
/*
......
......@@ -125,10 +125,9 @@ struct audit_rule { /* for AUDIT_LIST, AUDIT_ADD, and AUDIT_DEL */
#ifdef __KERNEL__
#ifdef CONFIG_AUDIT
struct audit_buffer;
struct audit_context;
#endif
struct inode;
#ifdef CONFIG_AUDITSYSCALL
/* These are defined in auditsc.c */
......@@ -141,7 +140,7 @@ extern void audit_syscall_entry(struct task_struct *task,
extern void audit_syscall_exit(struct task_struct *task, int return_code);
extern void audit_getname(const char *name);
extern void audit_putname(const char *name);
extern void audit_inode(const char *name, unsigned long ino, dev_t rdev);
extern void audit_inode(const char *name, const struct inode *inode);
/* Private API (for audit.c only) */
extern int audit_receive_filter(int type, int pid, int uid, int seq,
......@@ -150,6 +149,7 @@ extern void audit_get_stamp(struct audit_context *ctx,
struct timespec *t, int *serial);
extern int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid);
extern uid_t audit_get_loginuid(struct audit_context *ctx);
extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
#else
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
......@@ -157,8 +157,9 @@ extern uid_t audit_get_loginuid(struct audit_context *ctx);
#define audit_syscall_exit(t,r) do { ; } while (0)
#define audit_getname(n) do { ; } while (0)
#define audit_putname(n) do { ; } while (0)
#define audit_inode(n,i,d) do { ; } while (0)
#define audit_inode(n,i) do { ; } while (0)
#define audit_get_loginuid(c) ({ -1; })
#define audit_ipc_perms(q,u,g,m) ({ 0; })
#endif
#ifdef CONFIG_AUDIT
......
......@@ -212,7 +212,6 @@ extern int dir_notify_enable;
#include <linux/list.h>
#include <linux/radix-tree.h>
#include <linux/prio_tree.h>
#include <linux/audit.h>
#include <linux/init.h>
#include <asm/atomic.h>
......@@ -1272,13 +1271,7 @@ extern void __init vfs_caches_init(unsigned long);
#ifndef CONFIG_AUDITSYSCALL
#define putname(name) __putname(name)
#else
#define putname(name) \
do { \
if (unlikely(current->audit_context)) \
audit_putname(name); \
else \
__putname(name); \
} while (0)
extern void putname(const char *name);
#endif
extern int register_blkdev(unsigned int, const char *);
......
......@@ -25,6 +25,7 @@
#include <linux/security.h>
#include <linux/sched.h>
#include <linux/syscalls.h>
#include <linux/audit.h>
#include <asm/current.h>
#include <asm/uaccess.h>
#include "util.h"
......@@ -425,6 +426,8 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
return -EFAULT;
if (copy_msqid_from_user (&setbuf, buf, version))
return -EFAULT;
if ((err = audit_ipc_perms(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode)))
return err;
break;
case IPC_RMID:
break;
......
......@@ -72,6 +72,7 @@
#include <linux/smp_lock.h>
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/audit.h>
#include <asm/uaccess.h>
#include "util.h"
......@@ -803,6 +804,8 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
if(cmd == IPC_SET) {
if(copy_semid_from_user (&setbuf, arg.buf, version))
return -EFAULT;
if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode)))
return err;
}
sma = sem_lock(semid);
if(sma==NULL)
......
......@@ -27,6 +27,7 @@
#include <linux/shmem_fs.h>
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/audit.h>
#include <asm/uaccess.h>
#include "util.h"
......@@ -600,6 +601,8 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
err = -EFAULT;
goto out;
}
if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode)))
return err;
down(&shm_ids.sem);
shp = shm_lock(shmid);
err=-EINVAL;
......
......@@ -89,9 +89,30 @@ enum audit_state {
struct audit_names {
const char *name;
unsigned long ino;
dev_t dev;
umode_t mode;
uid_t uid;
gid_t gid;
dev_t rdev;
};
struct audit_aux_data {
struct audit_aux_data *next;
int type;
};
#define AUDIT_AUX_IPCPERM 0
struct audit_aux_data_ipcctl {
struct audit_aux_data d;
struct ipc_perm p;
unsigned long qbytes;
uid_t uid;
gid_t gid;
mode_t mode;
};
/* The per-task audit context. */
struct audit_context {
int in_syscall; /* 1 if task is in a syscall */
......@@ -107,6 +128,7 @@ struct audit_context {
int name_count;
struct audit_names names[AUDIT_NAMES];
struct audit_context *previous; /* For nested syscalls */
struct audit_aux_data *aux;
/* Save things to print about task_struct */
pid_t pid;
......@@ -338,7 +360,7 @@ static int audit_filter_rules(struct task_struct *tsk,
case AUDIT_DEVMAJOR:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
if (MAJOR(ctx->names[j].rdev)==value) {
if (MAJOR(ctx->names[j].dev)==value) {
++result;
break;
}
......@@ -348,7 +370,7 @@ static int audit_filter_rules(struct task_struct *tsk,
case AUDIT_DEVMINOR:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
if (MINOR(ctx->names[j].rdev)==value) {
if (MINOR(ctx->names[j].dev)==value) {
++result;
break;
}
......@@ -504,6 +526,16 @@ static inline void audit_free_names(struct audit_context *context)
context->name_count = 0;
}
static inline void audit_free_aux(struct audit_context *context)
{
struct audit_aux_data *aux;
while ((aux = context->aux)) {
context->aux = aux->next;
kfree(aux);
}
}
static inline void audit_zero_context(struct audit_context *context,
enum audit_state state)
{
......@@ -570,6 +602,7 @@ static inline void audit_free_context(struct audit_context *context)
context->name_count, count);
}
audit_free_names(context);
audit_free_aux(context);
kfree(context);
context = previous;
} while (context);
......@@ -607,6 +640,29 @@ static void audit_log_exit(struct audit_context *context)
context->euid, context->suid, context->fsuid,
context->egid, context->sgid, context->fsgid);
audit_log_end(ab);
while (context->aux) {
struct audit_aux_data *aux;
ab = audit_log_start(context);
if (!ab)
continue; /* audit_panic has been called */
aux = context->aux;
context->aux = aux->next;
audit_log_format(ab, "auxitem=%d", aux->type);
switch (aux->type) {
case AUDIT_AUX_IPCPERM: {
struct audit_aux_data_ipcctl *axi = (void *)aux;
audit_log_format(ab,
" qbytes=%lx uid=%d gid=%d mode=%x",
axi->qbytes, axi->uid, axi->gid, axi->mode);
}
}
audit_log_end(ab);
kfree(aux);
}
for (i = 0; i < context->name_count; i++) {
ab = audit_log_start(context);
if (!ab)
......@@ -616,12 +672,14 @@ static void audit_log_exit(struct audit_context *context)
audit_log_format(ab, " name=%s",
context->names[i].name);
if (context->names[i].ino != (unsigned long)-1)
audit_log_format(ab, " inode=%lu",
context->names[i].ino);
/* FIXME: should use format_dev_t, but ab structure is
* opaque. */
if (context->names[i].rdev != -1)
audit_log_format(ab, " dev=%02x:%02x",
audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o"
" uid=%d gid=%d 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),
MINOR(context->names[i].rdev));
audit_log_end(ab);
......@@ -789,6 +847,7 @@ void audit_syscall_exit(struct task_struct *tsk, int return_code)
tsk->audit_context = new_context;
} else {
audit_free_names(context);
audit_free_aux(context);
audit_zero_context(context, context->state);
tsk->audit_context = context;
}
......@@ -800,7 +859,9 @@ void audit_getname(const char *name)
{
struct audit_context *context = current->audit_context;
BUG_ON(!context);
if (!context || IS_ERR(name) || !name)
return;
if (!context->in_syscall) {
#if AUDIT_DEBUG == 2
printk(KERN_ERR "%s:%d(:%d): ignoring getname(%p)\n",
......@@ -812,7 +873,6 @@ void audit_getname(const char *name)
BUG_ON(context->name_count >= AUDIT_NAMES);
context->names[context->name_count].name = name;
context->names[context->name_count].ino = (unsigned long)-1;
context->names[context->name_count].rdev = -1;
++context->name_count;
}
......@@ -855,11 +915,10 @@ void audit_putname(const char *name)
}
#endif
}
EXPORT_SYMBOL(audit_putname);
/* Store the inode and device from a lookup. Called from
* fs/namei.c:path_lookup(). */
void audit_inode(const char *name, unsigned long ino, dev_t rdev)
void audit_inode(const char *name, const struct inode *inode)
{
int idx;
struct audit_context *context = current->audit_context;
......@@ -885,8 +944,12 @@ void audit_inode(const char *name, unsigned long ino, dev_t rdev)
++context->ino_count;
#endif
}
context->names[idx].ino = ino;
context->names[idx].rdev = rdev;
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;
}
void audit_get_stamp(struct audit_context *ctx,
......@@ -927,3 +990,26 @@ uid_t audit_get_loginuid(struct audit_context *ctx)
{
return ctx ? ctx->loginuid : -1;
}
int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
{
struct audit_aux_data_ipcctl *ax;
struct audit_context *context = current->audit_context;
if (likely(!context))
return 0;
ax = kmalloc(sizeof(*ax), GFP_KERNEL);
if (!ax)
return -ENOMEM;
ax->qbytes = qbytes;
ax->uid = uid;
ax->gid = gid;
ax->mode = mode;
ax->d.type = AUDIT_AUX_IPCPERM;
ax->d.next = context->aux;
context->aux = (void *)ax;
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment