bk://linux-audit.bkbits.net/audit-2.6-mm chrisw@osdl.org|ChangeSet|20050312013821|62477 chrisw # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/03/15 23:46:54-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-audit # # fs/proc/base.c # 2005/03/15 23:46:49-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/12 12:49:23-08:00 akpm@bix.(none) # Merge bk://linux-audit.bkbits.net/audit-2.6-mm # into bix.(none):/usr/src/bk-audit # # include/linux/audit.h # 2005/03/12 12:49:19-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/12 12:48:02-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-audit # # include/linux/audit.h # 2005/03/12 12:47:57-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/11 17:38:21-08:00 chrisw@osdl.org # Make audit.h forward declarations unconditional. # # Signed-off-by: Chris Wright # # include/linux/audit.h # 2005/03/11 17:37:39-08:00 chrisw@osdl.org +1 -5 # Make audit.h forward declarations unconditional. # # ChangeSet # 2005/03/10 17:50:49-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-audit # # fs/namei.c # 2005/03/10 17:50:44-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/10 12:59:07-08:00 akpm@bix.(none) # Merge # # fs/proc/base.c # 2005/03/10 12:59:05-08:00 akpm@bix.(none) +0 -0 # SCCS merged # # kernel/auditsc.c # 2005/03/10 12:53:45-08:00 akpm@bix.(none) +0 -0 # Auto merged # # include/linux/fs.h # 2005/03/10 12:53:45-08:00 akpm@bix.(none) +0 -0 # Auto merged # # fs/namei.c # 2005/03/10 12:53:45-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/um/kernel/ptrace.c # 2005/03/10 12:53:45-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/mips/kernel/ptrace.c # 2005/03/10 12:53:45-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2005/03/03 11:57:09-08:00 chrisw@osdl.org # Inode audit records are currently showing only name, inode, and dev. # The device is calculated incorrectly, and similarly dev based filtering # is broken. Fix device node problems and add some more useful data to # inode audit record -- mode, uid, gid of inode. # # Signed-off-by: Chris Wright # # kernel/auditsc.c # 2005/03/03 11:55:34-08:00 chrisw@osdl.org +21 -12 # fix audit_inode and dev filtering # # include/linux/audit.h # 2005/03/03 11:55:24-08:00 chrisw@osdl.org +5 -2 # audit_inode now takes inode object # # fs/namei.c # 2005/03/03 11:53:57-08:00 chrisw@osdl.org +1 -3 # audit_inode now takes inode object # # ChangeSet # 2005/03/03 11:21:52-08:00 jdike@addtoit.com # # For UML, this is fine as far as it goes, but you're adding register references # to arch-independent code, so this is needed as well: # # Signed-off-by: Jeff Dike # Signed-off-by: Chris Wright # # arch/um/kernel/ptrace.c # 2005/03/03 08:42:41-08:00 jdike@addtoit.com +8 -4 # Re: 2.6.11-rc5-mm1 # # ChangeSet # 2005/03/01 14:34:18-08:00 chrisw@osdl.org # A closer sweep of configurable audit symbols shows the following need # audit.h included when audit.h is detangled from fs.h. # # arch/um/kernel/ptrace.c for audit_syscall_entry/exit # arch/s390/kernel/ptrace.c for audit_syscall_entry/exit # arch/mips/kernel/ptrace.c for audit_syscall_entry/exit # # Signed-off-by: Chris Wright # # arch/um/kernel/ptrace.c # 2005/03/01 14:34:12-08:00 chrisw@osdl.org +1 -0 # include audit.h for audit_syscall_entry/exit # # arch/s390/kernel/ptrace.c # 2005/03/01 14:34:12-08:00 chrisw@osdl.org +1 -0 # include audit.h for audit_syscall_entry/exit # # arch/mips/kernel/ptrace.c # 2005/03/01 14:34:12-08:00 chrisw@osdl.org +1 -0 # include audit.h for audit_syscall_entry/exit # # ChangeSet # 2005/03/01 14:30:53-08:00 chrisw@osdl.org # Currently touching audit.h triggers a large rebuild because it's sucked # in via fs.h. It's there because of the getname()/putname() requirements # that come with CONFIG_AUDITSYSCALL. Remove header dependency by pushing # relevant putname() implementation into fs/namei.c. It adds function # call overhead for putname() callers when CONFIG_AUDITSYSCALL is set, # quite minor cost for detangled source. # # Signed-off-by: Chris Wright # # kernel/auditsc.c # 2005/03/01 14:30:46-08:00 chrisw@osdl.org +3 -2 # audit_getname call is completely selfcontained now, and audit_putname # no longer needs to be exported since it's not inlined in fs.h. # # include/linux/fs.h # 2005/03/01 14:30:46-08:00 chrisw@osdl.org +1 -8 # Move putname implementation to fs/namei.c when CONFIG_AUDITSYSCALL # is set. Remove audit.h include to detangle from fs.h. # # fs/proc/base.c # 2005/03/01 14:30:46-08:00 chrisw@osdl.org +1 -0 # add audit.h include for audit_get/set_loginuid # # fs/namei.c # 2005/03/01 14:30:46-08:00 chrisw@osdl.org +13 -2 # Move putname implementation to fs/namei.c when CONFIG_AUDITSYSCALL # is set. # # ChangeSet # 2005/03/01 09:15:37+00:00 dwmw2@shinybook.infradead.org # Audit IPC object owner/permission changes. # # Add linked list of auxiliary data to audit_context # Add callbacks in IPC_SET functions to record requested changes. # # Signed-off-by: David Woodhouse # # kernel/auditsc.c # 2005/03/01 09:15:21+00:00 dwmw2@shinybook.infradead.org +76 -0 # Implement linked list for auxiliary data, use it for audit_ipc_perms() # # ipc/shm.c # 2005/03/01 09:15:21+00:00 dwmw2@shinybook.infradead.org +3 -0 # Call audit_ipc_perms() for IPC_SET # # ipc/sem.c # 2005/03/01 09:15:21+00:00 dwmw2@shinybook.infradead.org +3 -0 # Call audit_ipc_perms() for IPC_SET # # ipc/msg.c # 2005/03/01 09:15:21+00:00 dwmw2@shinybook.infradead.org +3 -0 # Call audit_ipc_perms() for IPC_SET # # include/linux/audit.h # 2005/03/01 09:15:21+00:00 dwmw2@shinybook.infradead.org +2 -0 # Add audit_ipc_perms() definition. # diff -Nru a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c --- a/arch/mips/kernel/ptrace.c 2005-03-15 23:48:24 -08:00 +++ b/arch/mips/kernel/ptrace.c 2005-03-15 23:48:24 -08:00 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c --- a/arch/s390/kernel/ptrace.c 2005-03-15 23:48:24 -08:00 +++ b/arch/s390/kernel/ptrace.c 2005-03-15 23:48:24 -08:00 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c --- a/arch/um/kernel/ptrace.c 2005-03-15 23:48:24 -08:00 +++ b/arch/um/kernel/ptrace.c 2005-03-15 23:48:24 -08:00 @@ -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 @@ 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 -Nru a/fs/namei.c b/fs/namei.c --- a/fs/namei.c 2005-03-15 23:48:24 -08:00 +++ b/fs/namei.c 2005-03-15 23:48:24 -08:00 @@ -148,11 +148,22 @@ 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 @@ 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 -Nru a/fs/proc/base.c b/fs/proc/base.c --- a/fs/proc/base.c 2005-03-15 23:48:24 -08:00 +++ b/fs/proc/base.c 2005-03-15 23:48:24 -08:00 @@ -34,6 +34,7 @@ #include #include #include +#include #include "internal.h" /* diff -Nru a/include/linux/audit.h b/include/linux/audit.h --- a/include/linux/audit.h 2005-03-15 23:48:24 -08:00 +++ b/include/linux/audit.h 2005-03-15 23:48:24 -08:00 @@ -125,10 +125,9 @@ #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_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 @@ 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 @@ #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 -Nru a/include/linux/fs.h b/include/linux/fs.h --- a/include/linux/fs.h 2005-03-15 23:48:24 -08:00 +++ b/include/linux/fs.h 2005-03-15 23:48:24 -08:00 @@ -212,7 +212,6 @@ #include #include #include -#include #include #include @@ -1272,13 +1271,7 @@ #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 -Nru a/ipc/msg.c b/ipc/msg.c --- a/ipc/msg.c 2005-03-15 23:48:24 -08:00 +++ b/ipc/msg.c 2005-03-15 23:48:24 -08:00 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include "util.h" @@ -425,6 +426,8 @@ 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 -Nru a/ipc/sem.c b/ipc/sem.c --- a/ipc/sem.c 2005-03-15 23:48:24 -08:00 +++ b/ipc/sem.c 2005-03-15 23:48:24 -08:00 @@ -72,6 +72,7 @@ #include #include #include +#include #include #include "util.h" @@ -803,6 +804,8 @@ 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 -Nru a/ipc/shm.c b/ipc/shm.c --- a/ipc/shm.c 2005-03-15 23:48:24 -08:00 +++ b/ipc/shm.c 2005-03-15 23:48:24 -08:00 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "util.h" @@ -600,6 +601,8 @@ 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 -Nru a/kernel/auditsc.c b/kernel/auditsc.c --- a/kernel/auditsc.c 2005-03-15 23:48:24 -08:00 +++ b/kernel/auditsc.c 2005-03-15 23:48:24 -08:00 @@ -89,9 +89,30 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ context->name_count, count); } audit_free_names(context); + audit_free_aux(context); kfree(context); context = previous; } while (context); @@ -607,6 +640,29 @@ 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 @@ 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 @@ 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 @@ { 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 @@ 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 @@ } #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 @@ ++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, @@ -926,4 +989,27 @@ 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; }