Signed-off-by: Andrew Morton --- 25-akpm/arch/mips/kernel/ptrace.c | 1 25-akpm/arch/s390/kernel/ptrace.c | 1 25-akpm/arch/um/kernel/ptrace.c | 13 +++- 25-akpm/fs/namei.c | 19 ++++-- 25-akpm/fs/proc/base.c | 1 25-akpm/include/linux/audit.h | 9 ++- 25-akpm/include/linux/fs.h | 9 --- 25-akpm/ipc/msg.c | 3 + 25-akpm/ipc/sem.c | 3 + 25-akpm/ipc/shm.c | 3 + 25-akpm/kernel/auditsc.c | 114 +++++++++++++++++++++++++++++++++----- 11 files changed, 143 insertions(+), 33 deletions(-) diff -puN arch/mips/kernel/ptrace.c~bk-audit arch/mips/kernel/ptrace.c --- 25/arch/mips/kernel/ptrace.c~bk-audit 2005-03-07 21:41:28.000000000 -0800 +++ 25-akpm/arch/mips/kernel/ptrace.c 2005-03-07 21:41:28.000000000 -0800 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include diff -puN arch/s390/kernel/ptrace.c~bk-audit arch/s390/kernel/ptrace.c --- 25/arch/s390/kernel/ptrace.c~bk-audit 2005-03-07 21:41:28.000000000 -0800 +++ 25-akpm/arch/s390/kernel/ptrace.c 2005-03-07 21:41:28.000000000 -0800 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include diff -puN arch/um/kernel/ptrace.c~bk-audit arch/um/kernel/ptrace.c --- 25/arch/um/kernel/ptrace.c~bk-audit 2005-03-07 21:41:28.000000000 -0800 +++ 25-akpm/arch/um/kernel/ptrace.c 2005-03-07 21:41:28.000000000 -0800 @@ -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 *re 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(®s->regs), + UPT_SYSCALL_ARG1(®s->regs), + UPT_SYSCALL_ARG2(®s->regs), + UPT_SYSCALL_ARG3(®s->regs), + UPT_SYSCALL_ARG4(®s->regs)); else - audit_syscall_exit(current, regs->eax); + audit_syscall_exit(current, + UPT_SYSCALL_RET(®s->regs)); } /* Fake a debug trap */ diff -puN fs/namei.c~bk-audit fs/namei.c --- 25/fs/namei.c~bk-audit 2005-03-07 21:41:28.000000000 -0800 +++ 25-akpm/fs/namei.c 2005-03-07 21:41:28.000000000 -0800 @@ -148,11 +148,22 @@ char * getname(const char __user * filen 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 @@ -981,9 +992,7 @@ int fastcall path_lookup(const char *nam 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; } diff -puN fs/proc/base.c~bk-audit fs/proc/base.c --- 25/fs/proc/base.c~bk-audit 2005-03-07 21:41:28.000000000 -0800 +++ 25-akpm/fs/proc/base.c 2005-03-07 21:41:42.000000000 -0800 @@ -33,6 +33,7 @@ #include #include #include +#include #include "internal.h" /* diff -puN include/linux/audit.h~bk-audit include/linux/audit.h --- 25/include/linux/audit.h~bk-audit 2005-03-07 21:41:28.000000000 -0800 +++ 25-akpm/include/linux/audit.h 2005-03-07 21:41:28.000000000 -0800 @@ -131,6 +131,9 @@ struct audit_context; #endif #ifdef CONFIG_AUDITSYSCALL +/* forward decl for audit_inode */ +struct inode; + /* These are defined in auditsc.c */ /* Public API */ extern int audit_alloc(struct task_struct *task); @@ -141,7 +144,7 @@ extern void audit_syscall_entry(struct t 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 +153,7 @@ extern void audit_get_stamp(struct audit 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 +161,9 @@ extern uid_t audit_get_loginuid(struct a #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 diff -puN include/linux/fs.h~bk-audit include/linux/fs.h --- 25/include/linux/fs.h~bk-audit 2005-03-07 21:41:28.000000000 -0800 +++ 25-akpm/include/linux/fs.h 2005-03-07 21:41:28.000000000 -0800 @@ -212,7 +212,6 @@ extern int dir_notify_enable; #include #include #include -#include #include #include @@ -1270,13 +1269,7 @@ extern void __init vfs_caches_init(unsig #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 *); diff -puN ipc/msg.c~bk-audit ipc/msg.c --- 25/ipc/msg.c~bk-audit 2005-03-07 21:41:28.000000000 -0800 +++ 25-akpm/ipc/msg.c 2005-03-07 21:41:28.000000000 -0800 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include "util.h" @@ -425,6 +426,8 @@ asmlinkage long sys_msgctl (int msqid, i 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; diff -puN ipc/sem.c~bk-audit ipc/sem.c --- 25/ipc/sem.c~bk-audit 2005-03-07 21:41:28.000000000 -0800 +++ 25-akpm/ipc/sem.c 2005-03-07 21:41:28.000000000 -0800 @@ -72,6 +72,7 @@ #include #include #include +#include #include #include "util.h" @@ -803,6 +804,8 @@ static int semctl_down(int semid, int se 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) diff -puN ipc/shm.c~bk-audit ipc/shm.c --- 25/ipc/shm.c~bk-audit 2005-03-07 21:41:28.000000000 -0800 +++ 25-akpm/ipc/shm.c 2005-03-07 21:41:28.000000000 -0800 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "util.h" @@ -600,6 +601,8 @@ asmlinkage long sys_shmctl (int shmid, i 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; diff -puN kernel/auditsc.c~bk-audit kernel/auditsc.c --- 25/kernel/auditsc.c~bk-audit 2005-03-07 21:41:28.000000000 -0800 +++ 25-akpm/kernel/auditsc.c 2005-03-07 21:41:28.000000000 -0800 @@ -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 tas 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 tas 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(stru 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(st 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->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_ 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_stru 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, unsig ++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_co { 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; +} _