Commit 853da002 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'audit.b38' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current

* 'audit.b38' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current:
  [PATCH] Abnormal End of Processes
  [PATCH] match audit name data
  [PATCH] complete message queue auditing
  [PATCH] audit inode for all xattr syscalls
  [PATCH] initialize name osid
  [PATCH] audit signal recipients
  [PATCH] add SIGNAL syscall class (v3)
  [PATCH] auditing ptrace
parents 5884c406 0a4ff8c2
...@@ -20,6 +20,11 @@ unsigned ia32_read_class[] = { ...@@ -20,6 +20,11 @@ unsigned ia32_read_class[] = {
~0U ~0U
}; };
unsigned ia32_signal_class[] = {
#include <asm-generic/audit_signal.h>
~0U
};
int ia32_classify_syscall(unsigned syscall) int ia32_classify_syscall(unsigned syscall)
{ {
switch(syscall) { switch(syscall) {
......
...@@ -23,6 +23,20 @@ static unsigned chattr_class[] = { ...@@ -23,6 +23,20 @@ static unsigned chattr_class[] = {
~0U ~0U
}; };
static unsigned signal_class[] = {
#include <asm-generic/audit_signal.h>
~0U
};
int audit_classify_arch(int arch)
{
#ifdef CONFIG_IA32_SUPPORT
if (arch == AUDIT_ARCH_I386)
return 1;
#endif
return 0;
}
int audit_classify_syscall(int abi, unsigned syscall) int audit_classify_syscall(int abi, unsigned syscall)
{ {
#ifdef CONFIG_IA32_SUPPORT #ifdef CONFIG_IA32_SUPPORT
...@@ -49,15 +63,18 @@ static int __init audit_classes_init(void) ...@@ -49,15 +63,18 @@ static int __init audit_classes_init(void)
extern __u32 ia32_write_class[]; extern __u32 ia32_write_class[];
extern __u32 ia32_read_class[]; extern __u32 ia32_read_class[];
extern __u32 ia32_chattr_class[]; extern __u32 ia32_chattr_class[];
extern __u32 ia32_signal_class[];
audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class); audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class);
audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class); audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class); audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class); audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
audit_register_class(AUDIT_CLASS_SIGNAL_32, ia32_signal_class);
#endif #endif
audit_register_class(AUDIT_CLASS_WRITE, write_class); audit_register_class(AUDIT_CLASS_WRITE, write_class);
audit_register_class(AUDIT_CLASS_READ, read_class); audit_register_class(AUDIT_CLASS_READ, read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
return 0; return 0;
} }
......
...@@ -23,6 +23,20 @@ static unsigned chattr_class[] = { ...@@ -23,6 +23,20 @@ static unsigned chattr_class[] = {
~0U ~0U
}; };
static unsigned signal_class[] = {
#include <asm-generic/audit_signal.h>
~0U
};
int audit_classify_arch(int arch)
{
#ifdef CONFIG_PPC64
if (arch == AUDIT_ARCH_PPC)
return 1;
#endif
return 0;
}
int audit_classify_syscall(int abi, unsigned syscall) int audit_classify_syscall(int abi, unsigned syscall)
{ {
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
...@@ -51,15 +65,18 @@ static int __init audit_classes_init(void) ...@@ -51,15 +65,18 @@ static int __init audit_classes_init(void)
extern __u32 ppc32_write_class[]; extern __u32 ppc32_write_class[];
extern __u32 ppc32_read_class[]; extern __u32 ppc32_read_class[];
extern __u32 ppc32_chattr_class[]; extern __u32 ppc32_chattr_class[];
extern __u32 ppc32_signal_class[];
audit_register_class(AUDIT_CLASS_WRITE_32, ppc32_write_class); audit_register_class(AUDIT_CLASS_WRITE_32, ppc32_write_class);
audit_register_class(AUDIT_CLASS_READ_32, ppc32_read_class); audit_register_class(AUDIT_CLASS_READ_32, ppc32_read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ppc32_dir_class); audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ppc32_dir_class);
audit_register_class(AUDIT_CLASS_CHATTR_32, ppc32_chattr_class); audit_register_class(AUDIT_CLASS_CHATTR_32, ppc32_chattr_class);
audit_register_class(AUDIT_CLASS_SIGNAL_32, ppc32_signal_class);
#endif #endif
audit_register_class(AUDIT_CLASS_WRITE, write_class); audit_register_class(AUDIT_CLASS_WRITE, write_class);
audit_register_class(AUDIT_CLASS_READ, read_class); audit_register_class(AUDIT_CLASS_READ, read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
return 0; return 0;
} }
......
...@@ -21,6 +21,11 @@ unsigned ppc32_read_class[] = { ...@@ -21,6 +21,11 @@ unsigned ppc32_read_class[] = {
~0U ~0U
}; };
unsigned ppc32_signal_class[] = {
#include <asm-generic/audit_signal.h>
~0U
};
int ppc32_classify_syscall(unsigned syscall) int ppc32_classify_syscall(unsigned syscall)
{ {
switch(syscall) { switch(syscall) {
......
...@@ -23,6 +23,20 @@ static unsigned chattr_class[] = { ...@@ -23,6 +23,20 @@ static unsigned chattr_class[] = {
~0U ~0U
}; };
static unsigned signal_class[] = {
#include <asm-generic/audit_signal.h>
~0U
};
int audit_classify_arch(int arch)
{
#ifdef CONFIG_COMPAT
if (arch == AUDIT_ARCH_S390)
return 1;
#endif
return 0;
}
int audit_classify_syscall(int abi, unsigned syscall) int audit_classify_syscall(int abi, unsigned syscall)
{ {
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
...@@ -51,15 +65,18 @@ static int __init audit_classes_init(void) ...@@ -51,15 +65,18 @@ static int __init audit_classes_init(void)
extern __u32 s390_write_class[]; extern __u32 s390_write_class[];
extern __u32 s390_read_class[]; extern __u32 s390_read_class[];
extern __u32 s390_chattr_class[]; extern __u32 s390_chattr_class[];
extern __u32 s390_signal_class[];
audit_register_class(AUDIT_CLASS_WRITE_32, s390_write_class); audit_register_class(AUDIT_CLASS_WRITE_32, s390_write_class);
audit_register_class(AUDIT_CLASS_READ_32, s390_read_class); audit_register_class(AUDIT_CLASS_READ_32, s390_read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE_32, s390_dir_class); audit_register_class(AUDIT_CLASS_DIR_WRITE_32, s390_dir_class);
audit_register_class(AUDIT_CLASS_CHATTR_32, s390_chattr_class); audit_register_class(AUDIT_CLASS_CHATTR_32, s390_chattr_class);
audit_register_class(AUDIT_CLASS_SIGNAL_32, s390_signal_class);
#endif #endif
audit_register_class(AUDIT_CLASS_WRITE, write_class); audit_register_class(AUDIT_CLASS_WRITE, write_class);
audit_register_class(AUDIT_CLASS_READ, read_class); audit_register_class(AUDIT_CLASS_READ, read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
return 0; return 0;
} }
......
...@@ -21,6 +21,11 @@ unsigned s390_read_class[] = { ...@@ -21,6 +21,11 @@ unsigned s390_read_class[] = {
~0U ~0U
}; };
unsigned s390_signal_class[] = {
#include <asm-generic/audit_signal.h>
~0U
};
int s390_classify_syscall(unsigned syscall) int s390_classify_syscall(unsigned syscall)
{ {
switch(syscall) { switch(syscall) {
......
...@@ -23,6 +23,20 @@ static unsigned chattr_class[] = { ...@@ -23,6 +23,20 @@ static unsigned chattr_class[] = {
~0U ~0U
}; };
static unsigned signal_class[] = {
#include <asm-generic/audit_signal.h>
~0U
};
int audit_classify_arch(int arch)
{
#ifdef CONFIG_SPARC32_COMPAT
if (arch == AUDIT_ARCH_SPARC)
return 1;
#endif
return 0;
}
int audit_classify_syscall(int abi, unsigned syscall) int audit_classify_syscall(int abi, unsigned syscall)
{ {
#ifdef CONFIG_SPARC32_COMPAT #ifdef CONFIG_SPARC32_COMPAT
...@@ -51,15 +65,18 @@ static int __init audit_classes_init(void) ...@@ -51,15 +65,18 @@ static int __init audit_classes_init(void)
extern __u32 sparc32_write_class[]; extern __u32 sparc32_write_class[];
extern __u32 sparc32_read_class[]; extern __u32 sparc32_read_class[];
extern __u32 sparc32_chattr_class[]; extern __u32 sparc32_chattr_class[];
extern __u32 sparc32_signal_class[];
audit_register_class(AUDIT_CLASS_WRITE_32, sparc32_write_class); audit_register_class(AUDIT_CLASS_WRITE_32, sparc32_write_class);
audit_register_class(AUDIT_CLASS_READ_32, sparc32_read_class); audit_register_class(AUDIT_CLASS_READ_32, sparc32_read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE_32, sparc32_dir_class); audit_register_class(AUDIT_CLASS_DIR_WRITE_32, sparc32_dir_class);
audit_register_class(AUDIT_CLASS_CHATTR_32, sparc32_chattr_class); audit_register_class(AUDIT_CLASS_CHATTR_32, sparc32_chattr_class);
audit_register_class(AUDIT_CLASS_SIGNAL_32, sparc32_signal_class);
#endif #endif
audit_register_class(AUDIT_CLASS_WRITE, write_class); audit_register_class(AUDIT_CLASS_WRITE, write_class);
audit_register_class(AUDIT_CLASS_READ, read_class); audit_register_class(AUDIT_CLASS_READ, read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
return 0; return 0;
} }
......
...@@ -20,6 +20,11 @@ unsigned sparc32_read_class[] = { ...@@ -20,6 +20,11 @@ unsigned sparc32_read_class[] = {
~0U ~0U
}; };
unsigned sparc32_signal_class[] = {
#include <asm-generic/audit_signal.h>
~0U
};
int sparc32_classify_syscall(unsigned syscall) int sparc32_classify_syscall(unsigned syscall)
{ {
switch(syscall) { switch(syscall) {
......
...@@ -20,6 +20,11 @@ unsigned ia32_read_class[] = { ...@@ -20,6 +20,11 @@ unsigned ia32_read_class[] = {
~0U ~0U
}; };
unsigned ia32_signal_class[] = {
#include <asm-generic/audit_signal.h>
~0U
};
int ia32_classify_syscall(unsigned syscall) int ia32_classify_syscall(unsigned syscall)
{ {
switch(syscall) { switch(syscall) {
......
...@@ -23,6 +23,20 @@ static unsigned chattr_class[] = { ...@@ -23,6 +23,20 @@ static unsigned chattr_class[] = {
~0U ~0U
}; };
static unsigned signal_class[] = {
#include <asm-generic/audit_signal.h>
~0U
};
int audit_classify_arch(int arch)
{
#ifdef CONFIG_IA32_EMULATION
if (arch == AUDIT_ARCH_I386)
return 1;
#endif
return 0;
}
int audit_classify_syscall(int abi, unsigned syscall) int audit_classify_syscall(int abi, unsigned syscall)
{ {
#ifdef CONFIG_IA32_EMULATION #ifdef CONFIG_IA32_EMULATION
...@@ -49,15 +63,18 @@ static int __init audit_classes_init(void) ...@@ -49,15 +63,18 @@ static int __init audit_classes_init(void)
extern __u32 ia32_write_class[]; extern __u32 ia32_write_class[];
extern __u32 ia32_read_class[]; extern __u32 ia32_read_class[];
extern __u32 ia32_chattr_class[]; extern __u32 ia32_chattr_class[];
extern __u32 ia32_signal_class[];
audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class); audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class);
audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class); audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class); audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class); audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
audit_register_class(AUDIT_CLASS_SIGNAL_32, ia32_signal_class);
#endif #endif
audit_register_class(AUDIT_CLASS_WRITE, write_class); audit_register_class(AUDIT_CLASS_WRITE, write_class);
audit_register_class(AUDIT_CLASS_READ, read_class); audit_register_class(AUDIT_CLASS_READ, read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
return 0; return 0;
} }
......
...@@ -1495,6 +1495,8 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) ...@@ -1495,6 +1495,8 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
int flag = 0; int flag = 0;
int ispipe = 0; int ispipe = 0;
audit_core_dumps(signr);
binfmt = current->binfmt; binfmt = current->binfmt;
if (!binfmt || !binfmt->core_dump) if (!binfmt || !binfmt->core_dump)
goto fail; goto fail;
......
...@@ -1719,7 +1719,7 @@ do_last: ...@@ -1719,7 +1719,7 @@ do_last:
* It already exists. * It already exists.
*/ */
mutex_unlock(&dir->d_inode->i_mutex); mutex_unlock(&dir->d_inode->i_mutex);
audit_inode_update(path.dentry->d_inode); audit_inode(pathname, path.dentry->d_inode);
error = -EEXIST; error = -EEXIST;
if (flag & O_EXCL) if (flag & O_EXCL)
......
...@@ -350,6 +350,7 @@ sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size) ...@@ -350,6 +350,7 @@ sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size)
f = fget(fd); f = fget(fd);
if (!f) if (!f)
return error; return error;
audit_inode(NULL, f->f_path.dentry->d_inode);
error = getxattr(f->f_path.dentry, name, value, size); error = getxattr(f->f_path.dentry, name, value, size);
fput(f); fput(f);
return error; return error;
...@@ -422,6 +423,7 @@ sys_flistxattr(int fd, char __user *list, size_t size) ...@@ -422,6 +423,7 @@ sys_flistxattr(int fd, char __user *list, size_t size)
f = fget(fd); f = fget(fd);
if (!f) if (!f)
return error; return error;
audit_inode(NULL, f->f_path.dentry->d_inode);
error = listxattr(f->f_path.dentry, list, size); error = listxattr(f->f_path.dentry, list, size);
fput(f); fput(f);
return error; return error;
......
__NR_kill,
__NR_tgkill,
__NR_tkill,
...@@ -91,6 +91,7 @@ ...@@ -91,6 +91,7 @@
#define AUDIT_MQ_GETSETATTR 1315 /* POSIX MQ get/set attribute record type */ #define AUDIT_MQ_GETSETATTR 1315 /* POSIX MQ get/set attribute record type */
#define AUDIT_KERNEL_OTHER 1316 /* For use by 3rd party modules */ #define AUDIT_KERNEL_OTHER 1316 /* For use by 3rd party modules */
#define AUDIT_FD_PAIR 1317 /* audit record for pipe/socketpair */ #define AUDIT_FD_PAIR 1317 /* audit record for pipe/socketpair */
#define AUDIT_OBJ_PID 1318 /* ptrace target */
#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
...@@ -111,6 +112,7 @@ ...@@ -111,6 +112,7 @@
#define AUDIT_FIRST_KERN_ANOM_MSG 1700 #define AUDIT_FIRST_KERN_ANOM_MSG 1700
#define AUDIT_LAST_KERN_ANOM_MSG 1799 #define AUDIT_LAST_KERN_ANOM_MSG 1799
#define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */ #define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */
#define AUDIT_ANOM_ABEND 1701 /* Process ended abnormally */
#define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */ #define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */
...@@ -148,6 +150,8 @@ ...@@ -148,6 +150,8 @@
#define AUDIT_CLASS_READ_32 5 #define AUDIT_CLASS_READ_32 5
#define AUDIT_CLASS_WRITE 6 #define AUDIT_CLASS_WRITE 6
#define AUDIT_CLASS_WRITE_32 7 #define AUDIT_CLASS_WRITE_32 7
#define AUDIT_CLASS_SIGNAL 8
#define AUDIT_CLASS_SIGNAL_32 9
/* This bitmask is used to validate user input. It represents all bits that /* This bitmask is used to validate user input. It represents all bits that
* are currently used in an audit field constant understood by the kernel. * are currently used in an audit field constant understood by the kernel.
...@@ -337,6 +341,7 @@ struct mqstat; ...@@ -337,6 +341,7 @@ struct mqstat;
#define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS ) #define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS )
extern int __init audit_register_class(int class, unsigned *list); extern int __init audit_register_class(int class, unsigned *list);
extern int audit_classify_syscall(int abi, unsigned syscall); extern int audit_classify_syscall(int abi, unsigned syscall);
extern int audit_classify_arch(int arch);
#ifdef CONFIG_AUDITSYSCALL #ifdef CONFIG_AUDITSYSCALL
/* These are defined in auditsc.c */ /* These are defined in auditsc.c */
/* Public API */ /* Public API */
...@@ -351,7 +356,8 @@ extern void audit_putname(const char *name); ...@@ -351,7 +356,8 @@ extern void audit_putname(const char *name);
extern void __audit_inode(const char *name, const struct inode *inode); extern void __audit_inode(const char *name, const struct inode *inode);
extern void __audit_inode_child(const char *dname, const struct inode *inode, extern void __audit_inode_child(const char *dname, const struct inode *inode,
const struct inode *parent); const struct inode *parent);
extern void __audit_inode_update(const struct inode *inode); extern void __audit_ptrace(struct task_struct *t);
static inline int audit_dummy_context(void) static inline int audit_dummy_context(void)
{ {
void *p = current->audit_context; void *p = current->audit_context;
...@@ -372,9 +378,12 @@ static inline void audit_inode_child(const char *dname, ...@@ -372,9 +378,12 @@ static inline void audit_inode_child(const char *dname,
if (unlikely(!audit_dummy_context())) if (unlikely(!audit_dummy_context()))
__audit_inode_child(dname, inode, parent); __audit_inode_child(dname, inode, parent);
} }
static inline void audit_inode_update(const struct inode *inode) { void audit_core_dumps(long signr);
static inline void audit_ptrace(struct task_struct *t)
{
if (unlikely(!audit_dummy_context())) if (unlikely(!audit_dummy_context()))
__audit_inode_update(inode); __audit_ptrace(t);
} }
/* Private API (for audit.c only) */ /* Private API (for audit.c only) */
...@@ -447,6 +456,7 @@ static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat) ...@@ -447,6 +456,7 @@ static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
return 0; return 0;
} }
extern int audit_n_rules; extern int audit_n_rules;
extern int audit_signals;
#else #else
#define audit_alloc(t) ({ 0; }) #define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0) #define audit_free(t) do { ; } while (0)
...@@ -457,10 +467,9 @@ extern int audit_n_rules; ...@@ -457,10 +467,9 @@ extern int audit_n_rules;
#define audit_putname(n) do { ; } while (0) #define audit_putname(n) do { ; } while (0)
#define __audit_inode(n,i) do { ; } while (0) #define __audit_inode(n,i) do { ; } while (0)
#define __audit_inode_child(d,i,p) do { ; } while (0) #define __audit_inode_child(d,i,p) do { ; } while (0)
#define __audit_inode_update(i) do { ; } while (0)
#define audit_inode(n,i) do { ; } while (0) #define audit_inode(n,i) do { ; } while (0)
#define audit_inode_child(d,i,p) do { ; } while (0) #define audit_inode_child(d,i,p) do { ; } while (0)
#define audit_inode_update(i) do { ; } while (0) #define audit_core_dumps(i) do { ; } while (0)
#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0) #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
#define audit_get_loginuid(c) ({ -1; }) #define audit_get_loginuid(c) ({ -1; })
#define audit_log_task_context(b) do { ; } while (0) #define audit_log_task_context(b) do { ; } while (0)
...@@ -477,7 +486,9 @@ extern int audit_n_rules; ...@@ -477,7 +486,9 @@ extern int audit_n_rules;
#define audit_mq_timedreceive(d,l,p,t) ({ 0; }) #define audit_mq_timedreceive(d,l,p,t) ({ 0; })
#define audit_mq_notify(d,n) ({ 0; }) #define audit_mq_notify(d,n) ({ 0; })
#define audit_mq_getsetattr(d,s) ({ 0; }) #define audit_mq_getsetattr(d,s) ({ 0; })
#define audit_ptrace(t) ((void)0)
#define audit_n_rules 0 #define audit_n_rules 0
#define audit_signals 0
#endif #endif
#ifdef CONFIG_AUDIT #ifdef CONFIG_AUDIT
......
...@@ -681,6 +681,7 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, ...@@ -681,6 +681,7 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
if (oflag & O_CREAT) { if (oflag & O_CREAT) {
if (dentry->d_inode) { /* entry already exists */ if (dentry->d_inode) { /* entry already exists */
audit_inode(name, dentry->d_inode);
error = -EEXIST; error = -EEXIST;
if (oflag & O_EXCL) if (oflag & O_EXCL)
goto out; goto out;
...@@ -693,6 +694,7 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, ...@@ -693,6 +694,7 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
error = -ENOENT; error = -ENOENT;
if (!dentry->d_inode) if (!dentry->d_inode)
goto out; goto out;
audit_inode(name, dentry->d_inode);
filp = do_open(dentry, oflag); filp = do_open(dentry, oflag);
} }
...@@ -840,6 +842,7 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, ...@@ -840,6 +842,7 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
if (unlikely(filp->f_op != &mqueue_file_operations)) if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput; goto out_fput;
info = MQUEUE_I(inode); info = MQUEUE_I(inode);
audit_inode(NULL, inode);
if (unlikely(!(filp->f_mode & FMODE_WRITE))) if (unlikely(!(filp->f_mode & FMODE_WRITE)))
goto out_fput; goto out_fput;
...@@ -923,6 +926,7 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, ...@@ -923,6 +926,7 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
if (unlikely(filp->f_op != &mqueue_file_operations)) if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput; goto out_fput;
info = MQUEUE_I(inode); info = MQUEUE_I(inode);
audit_inode(NULL, inode);
if (unlikely(!(filp->f_mode & FMODE_READ))) if (unlikely(!(filp->f_mode & FMODE_READ)))
goto out_fput; goto out_fput;
......
...@@ -83,6 +83,7 @@ struct audit_krule { ...@@ -83,6 +83,7 @@ struct audit_krule {
u32 field_count; u32 field_count;
char *filterkey; /* ties events to rules */ char *filterkey; /* ties events to rules */
struct audit_field *fields; struct audit_field *fields;
struct audit_field *arch_f; /* quick access to arch field */
struct audit_field *inode_f; /* quick access to an inode field */ struct audit_field *inode_f; /* quick access to an inode field */
struct audit_watch *watch; /* associated watch */ struct audit_watch *watch; /* associated watch */
struct list_head rlist; /* entry in audit_watch.rules list */ struct list_head rlist; /* entry in audit_watch.rules list */
...@@ -131,17 +132,19 @@ extern void audit_handle_ievent(struct inotify_watch *, u32, u32, u32, ...@@ -131,17 +132,19 @@ extern void audit_handle_ievent(struct inotify_watch *, u32, u32, u32,
extern int selinux_audit_rule_update(void); extern int selinux_audit_rule_update(void);
#ifdef CONFIG_AUDITSYSCALL #ifdef CONFIG_AUDITSYSCALL
extern void __audit_signal_info(int sig, struct task_struct *t); extern int __audit_signal_info(int sig, struct task_struct *t);
static inline void audit_signal_info(int sig, struct task_struct *t) static inline int audit_signal_info(int sig, struct task_struct *t)
{ {
if (unlikely(audit_pid && t->tgid == audit_pid)) if (unlikely((audit_pid && t->tgid == audit_pid) ||
__audit_signal_info(sig, t); (audit_signals && !audit_dummy_context())))
return __audit_signal_info(sig, t);
return 0;
} }
extern enum audit_state audit_filter_inodes(struct task_struct *, extern enum audit_state audit_filter_inodes(struct task_struct *,
struct audit_context *); struct audit_context *);
extern void audit_set_auditable(struct audit_context *); extern void audit_set_auditable(struct audit_context *);
#else #else
#define audit_signal_info(s,t) #define audit_signal_info(s,t) AUDIT_DISABLED
#define audit_filter_inodes(t,c) AUDIT_DISABLED #define audit_filter_inodes(t,c) AUDIT_DISABLED
#define audit_set_auditable(c) #define audit_set_auditable(c)
#endif #endif
...@@ -311,6 +311,43 @@ int audit_match_class(int class, unsigned syscall) ...@@ -311,6 +311,43 @@ int audit_match_class(int class, unsigned syscall)
return classes[class][AUDIT_WORD(syscall)] & AUDIT_BIT(syscall); return classes[class][AUDIT_WORD(syscall)] & AUDIT_BIT(syscall);
} }
static inline int audit_match_class_bits(int class, u32 *mask)
{
int i;
if (classes[class]) {
for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
if (mask[i] & classes[class][i])
return 0;
}
return 1;
}
static int audit_match_signal(struct audit_entry *entry)
{
struct audit_field *arch = entry->rule.arch_f;
if (!arch) {
/* When arch is unspecified, we must check both masks on biarch
* as syscall number alone is ambiguous. */
return (audit_match_class_bits(AUDIT_CLASS_SIGNAL,
entry->rule.mask) &&
audit_match_class_bits(AUDIT_CLASS_SIGNAL_32,
entry->rule.mask));
}
switch(audit_classify_arch(arch->val)) {
case 0: /* native */
return (audit_match_class_bits(AUDIT_CLASS_SIGNAL,
entry->rule.mask));
case 1: /* 32bit on biarch */
return (audit_match_class_bits(AUDIT_CLASS_SIGNAL_32,
entry->rule.mask));
default:
return 1;
}
}
/* Common user-space to kernel rule translation. */ /* Common user-space to kernel rule translation. */
static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
{ {
...@@ -429,6 +466,7 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) ...@@ -429,6 +466,7 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
err = -EINVAL; err = -EINVAL;
goto exit_free; goto exit_free;
} }
entry->rule.arch_f = f;
break; break;
case AUDIT_PERM: case AUDIT_PERM:
if (f->val & ~15) if (f->val & ~15)
...@@ -519,7 +557,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, ...@@ -519,7 +557,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
case AUDIT_FSGID: case AUDIT_FSGID:
case AUDIT_LOGINUID: case AUDIT_LOGINUID:
case AUDIT_PERS: case AUDIT_PERS:
case AUDIT_ARCH:
case AUDIT_MSGTYPE: case AUDIT_MSGTYPE:
case AUDIT_PPID: case AUDIT_PPID:
case AUDIT_DEVMAJOR: case AUDIT_DEVMAJOR:
...@@ -531,6 +568,9 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, ...@@ -531,6 +568,9 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
case AUDIT_ARG2: case AUDIT_ARG2:
case AUDIT_ARG3: case AUDIT_ARG3:
break; break;
case AUDIT_ARCH:
entry->rule.arch_f = f;
break;
case AUDIT_SUBJ_USER: case AUDIT_SUBJ_USER:
case AUDIT_SUBJ_ROLE: case AUDIT_SUBJ_ROLE:
case AUDIT_SUBJ_TYPE: case AUDIT_SUBJ_TYPE:
...@@ -1221,6 +1261,9 @@ static inline int audit_add_rule(struct audit_entry *entry, ...@@ -1221,6 +1261,9 @@ static inline int audit_add_rule(struct audit_entry *entry,
#ifdef CONFIG_AUDITSYSCALL #ifdef CONFIG_AUDITSYSCALL
if (!dont_count) if (!dont_count)
audit_n_rules++; audit_n_rules++;
if (!audit_match_signal(entry))
audit_signals++;
#endif #endif
mutex_unlock(&audit_filter_mutex); mutex_unlock(&audit_filter_mutex);
...@@ -1294,6 +1337,9 @@ static inline int audit_del_rule(struct audit_entry *entry, ...@@ -1294,6 +1337,9 @@ static inline int audit_del_rule(struct audit_entry *entry,
#ifdef CONFIG_AUDITSYSCALL #ifdef CONFIG_AUDITSYSCALL
if (!dont_count) if (!dont_count)
audit_n_rules--; audit_n_rules--;
if (!audit_match_signal(entry))
audit_signals--;
#endif #endif
mutex_unlock(&audit_filter_mutex); mutex_unlock(&audit_filter_mutex);
......
...@@ -78,17 +78,15 @@ extern int audit_enabled; ...@@ -78,17 +78,15 @@ extern int audit_enabled;
* for saving names from getname(). */ * for saving names from getname(). */
#define AUDIT_NAMES 20 #define AUDIT_NAMES 20
/* AUDIT_NAMES_RESERVED is the number of slots we reserve in the
* audit_context from being used for nameless inodes from
* path_lookup. */
#define AUDIT_NAMES_RESERVED 7
/* Indicates that audit should log the full pathname. */ /* Indicates that audit should log the full pathname. */
#define AUDIT_NAME_FULL -1 #define AUDIT_NAME_FULL -1
/* number of audit rules */ /* number of audit rules */
int audit_n_rules; int audit_n_rules;
/* determines whether we collect data for signals sent */
int audit_signals;
/* When fs/namei.c:getname() is called, we store the pointer in name and /* When fs/namei.c:getname() is called, we store the pointer in name and
* we don't let putname() free it (instead we free all of the saved * we don't let putname() free it (instead we free all of the saved
* pointers at syscall exit time). * pointers at syscall exit time).
...@@ -114,6 +112,9 @@ struct audit_aux_data { ...@@ -114,6 +112,9 @@ struct audit_aux_data {
#define AUDIT_AUX_IPCPERM 0 #define AUDIT_AUX_IPCPERM 0
/* Number of target pids per aux struct. */
#define AUDIT_AUX_PIDS 16
struct audit_aux_data_mq_open { struct audit_aux_data_mq_open {
struct audit_aux_data d; struct audit_aux_data d;
int oflag; int oflag;
...@@ -181,6 +182,13 @@ struct audit_aux_data_path { ...@@ -181,6 +182,13 @@ struct audit_aux_data_path {
struct vfsmount *mnt; struct vfsmount *mnt;
}; };
struct audit_aux_data_pids {
struct audit_aux_data d;
pid_t target_pid[AUDIT_AUX_PIDS];
u32 target_sid[AUDIT_AUX_PIDS];
int pid_count;
};
/* The per-task audit context. */ /* The per-task audit context. */
struct audit_context { struct audit_context {
int dummy; /* must be the first element */ int dummy; /* must be the first element */
...@@ -201,6 +209,7 @@ struct audit_context { ...@@ -201,6 +209,7 @@ struct audit_context {
struct vfsmount * pwdmnt; struct vfsmount * pwdmnt;
struct audit_context *previous; /* For nested syscalls */ struct audit_context *previous; /* For nested syscalls */
struct audit_aux_data *aux; struct audit_aux_data *aux;
struct audit_aux_data *aux_pids;
/* Save things to print about task_struct */ /* Save things to print about task_struct */
pid_t pid, ppid; pid_t pid, ppid;
...@@ -209,6 +218,9 @@ struct audit_context { ...@@ -209,6 +218,9 @@ struct audit_context {
unsigned long personality; unsigned long personality;
int arch; int arch;
pid_t target_pid;
u32 target_sid;
#if AUDIT_DEBUG #if AUDIT_DEBUG
int put_count; int put_count;
int ino_count; int ino_count;
...@@ -654,6 +666,10 @@ static inline void audit_free_aux(struct audit_context *context) ...@@ -654,6 +666,10 @@ static inline void audit_free_aux(struct audit_context *context)
context->aux = aux->next; context->aux = aux->next;
kfree(aux); kfree(aux);
} }
while ((aux = context->aux_pids)) {
context->aux_pids = aux->next;
kfree(aux);
}
} }
static inline void audit_zero_context(struct audit_context *context, static inline void audit_zero_context(struct audit_context *context,
...@@ -795,6 +811,29 @@ static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk ...@@ -795,6 +811,29 @@ static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk
audit_log_task_context(ab); audit_log_task_context(ab);
} }
static int audit_log_pid_context(struct audit_context *context, pid_t pid,
u32 sid)
{
struct audit_buffer *ab;
char *s = NULL;
u32 len;
int rc = 0;
ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
if (!ab)
return 1;
if (selinux_sid_to_string(sid, &s, &len)) {
audit_log_format(ab, "opid=%d obj=(none)", pid);
rc = 1;
} else
audit_log_format(ab, "opid=%d obj=%s", pid, s);
audit_log_end(ab);
kfree(s);
return rc;
}
static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
{ {
int i, call_panic = 0; int i, call_panic = 0;
...@@ -973,6 +1012,21 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts ...@@ -973,6 +1012,21 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
audit_log_end(ab); audit_log_end(ab);
} }
for (aux = context->aux_pids; aux; aux = aux->next) {
struct audit_aux_data_pids *axs = (void *)aux;
int i;
for (i = 0; i < axs->pid_count; i++)
if (audit_log_pid_context(context, axs->target_pid[i],
axs->target_sid[i]))
call_panic = 1;
}
if (context->target_pid &&
audit_log_pid_context(context, context->target_pid,
context->target_sid))
call_panic = 1;
if (context->pwd && context->pwdmnt) { if (context->pwd && context->pwdmnt) {
ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD); ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
if (ab) { if (ab) {
...@@ -1193,6 +1247,10 @@ void audit_syscall_exit(int valid, long return_code) ...@@ -1193,6 +1247,10 @@ void audit_syscall_exit(int valid, long return_code)
} else { } else {
audit_free_names(context); audit_free_names(context);
audit_free_aux(context); audit_free_aux(context);
context->aux = NULL;
context->aux_pids = NULL;
context->target_pid = 0;
context->target_sid = 0;
kfree(context->filterkey); kfree(context->filterkey);
context->filterkey = NULL; context->filterkey = NULL;
tsk->audit_context = context; tsk->audit_context = context;
...@@ -1226,6 +1284,7 @@ void __audit_getname(const char *name) ...@@ -1226,6 +1284,7 @@ void __audit_getname(const char *name)
context->names[context->name_count].name_len = AUDIT_NAME_FULL; context->names[context->name_count].name_len = AUDIT_NAME_FULL;
context->names[context->name_count].name_put = 1; context->names[context->name_count].name_put = 1;
context->names[context->name_count].ino = (unsigned long)-1; context->names[context->name_count].ino = (unsigned long)-1;
context->names[context->name_count].osid = 0;
++context->name_count; ++context->name_count;
if (!context->pwd) { if (!context->pwd) {
read_lock(&current->fs->lock); read_lock(&current->fs->lock);
...@@ -1279,6 +1338,28 @@ void audit_putname(const char *name) ...@@ -1279,6 +1338,28 @@ void audit_putname(const char *name)
#endif #endif
} }
static int audit_inc_name_count(struct audit_context *context,
const struct inode *inode)
{
if (context->name_count >= AUDIT_NAMES) {
if (inode)
printk(KERN_DEBUG "name_count maxed, losing inode data: "
"dev=%02x:%02x, inode=%lu",
MAJOR(inode->i_sb->s_dev),
MINOR(inode->i_sb->s_dev),
inode->i_ino);
else
printk(KERN_DEBUG "name_count maxed, losing inode data");
return 1;
}
context->name_count++;
#if AUDIT_DEBUG
context->ino_count++;
#endif
return 0;
}
/* Copy inode data into an audit_names. */ /* Copy inode data into an audit_names. */
static void audit_copy_inode(struct audit_names *name, const struct inode *inode) static void audit_copy_inode(struct audit_names *name, const struct inode *inode)
{ {
...@@ -1316,13 +1397,10 @@ void __audit_inode(const char *name, const struct inode *inode) ...@@ -1316,13 +1397,10 @@ void __audit_inode(const char *name, const struct inode *inode)
else { else {
/* FIXME: how much do we care about inodes that have no /* FIXME: how much do we care about inodes that have no
* associated name? */ * associated name? */
if (context->name_count >= AUDIT_NAMES - AUDIT_NAMES_RESERVED) if (audit_inc_name_count(context, inode))
return; return;
idx = context->name_count++; idx = context->name_count - 1;
context->names[idx].name = NULL; context->names[idx].name = NULL;
#if AUDIT_DEBUG
++context->ino_count;
#endif
} }
audit_copy_inode(&context->names[idx], inode); audit_copy_inode(&context->names[idx], inode);
} }
...@@ -1346,7 +1424,7 @@ void __audit_inode_child(const char *dname, const struct inode *inode, ...@@ -1346,7 +1424,7 @@ void __audit_inode_child(const char *dname, const struct inode *inode,
{ {
int idx; int idx;
struct audit_context *context = current->audit_context; struct audit_context *context = current->audit_context;
const char *found_name = NULL; const char *found_parent = NULL, *found_child = NULL;
int dirlen = 0; int dirlen = 0;
if (!context->in_syscall) if (!context->in_syscall)
...@@ -1354,88 +1432,73 @@ void __audit_inode_child(const char *dname, const struct inode *inode, ...@@ -1354,88 +1432,73 @@ void __audit_inode_child(const char *dname, const struct inode *inode,
/* determine matching parent */ /* determine matching parent */
if (!dname) if (!dname)
goto update_context; goto add_names;
for (idx = 0; idx < context->name_count; idx++)
if (context->names[idx].ino == parent->i_ino) {
const char *name = context->names[idx].name;
if (!name) /* parent is more likely, look for it first */
continue; for (idx = 0; idx < context->name_count; idx++) {
struct audit_names *n = &context->names[idx];
if (audit_compare_dname_path(dname, name, &dirlen) == 0) { if (!n->name)
context->names[idx].name_len = dirlen; continue;
found_name = name;
break; if (n->ino == parent->i_ino &&
} !audit_compare_dname_path(dname, n->name, &dirlen)) {
n->name_len = dirlen; /* update parent data in place */
found_parent = n->name;
goto add_names;
} }
}
update_context: /* no matching parent, look for matching child */
idx = context->name_count; for (idx = 0; idx < context->name_count; idx++) {
if (context->name_count == AUDIT_NAMES) { struct audit_names *n = &context->names[idx];
printk(KERN_DEBUG "name_count maxed and losing %s\n",
found_name ?: "(null)"); if (!n->name)
return; continue;
/* strcmp() is the more likely scenario */
if (!strcmp(dname, n->name) ||
!audit_compare_dname_path(dname, n->name, &dirlen)) {
if (inode)
audit_copy_inode(n, inode);
else
n->ino = (unsigned long)-1;
found_child = n->name;
goto add_names;
}
} }
context->name_count++;
#if AUDIT_DEBUG add_names:
context->ino_count++; if (!found_parent) {
#endif if (audit_inc_name_count(context, parent))
/* Re-use the name belonging to the slot for a matching parent directory.
* All names for this context are relinquished in audit_free_names() */
context->names[idx].name = found_name;
context->names[idx].name_len = AUDIT_NAME_FULL;
context->names[idx].name_put = 0; /* don't call __putname() */
if (!inode)
context->names[idx].ino = (unsigned long)-1;
else
audit_copy_inode(&context->names[idx], inode);
/* A parent was not found in audit_names, so copy the inode data for the
* provided parent. */
if (!found_name) {
idx = context->name_count;
if (context->name_count == AUDIT_NAMES) {
printk(KERN_DEBUG
"name_count maxed and losing parent inode data: dev=%02x:%02x, inode=%lu",
MAJOR(parent->i_sb->s_dev),
MINOR(parent->i_sb->s_dev),
parent->i_ino);
return; return;
} idx = context->name_count - 1;
context->name_count++; context->names[idx].name = NULL;
#if AUDIT_DEBUG
context->ino_count++;
#endif
audit_copy_inode(&context->names[idx], parent); audit_copy_inode(&context->names[idx], parent);
} }
}
/** if (!found_child) {
* audit_inode_update - update inode info for last collected name if (audit_inc_name_count(context, inode))
* @inode: inode being audited return;
* idx = context->name_count - 1;
* When open() is called on an existing object with the O_CREAT flag, the inode
* data audit initially collects is incorrect. This additional hook ensures
* audit has the inode data for the actual object to be opened.
*/
void __audit_inode_update(const struct inode *inode)
{
struct audit_context *context = current->audit_context;
int idx;
if (!context->in_syscall || !inode) /* Re-use the name belonging to the slot for a matching parent
return; * directory. All names for this context are relinquished in
* audit_free_names() */
if (found_parent) {
context->names[idx].name = found_parent;
context->names[idx].name_len = AUDIT_NAME_FULL;
/* don't call __putname() */
context->names[idx].name_put = 0;
} else {
context->names[idx].name = NULL;
}
if (context->name_count == 0) { if (inode)
context->name_count++; audit_copy_inode(&context->names[idx], inode);
#if AUDIT_DEBUG else
context->ino_count++; context->names[idx].ino = (unsigned long)-1;
#endif
} }
idx = context->name_count - 1;
audit_copy_inode(&context->names[idx], inode);
} }
/** /**
...@@ -1880,6 +1943,14 @@ int audit_sockaddr(int len, void *a) ...@@ -1880,6 +1943,14 @@ int audit_sockaddr(int len, void *a)
return 0; return 0;
} }
void __audit_ptrace(struct task_struct *t)
{
struct audit_context *context = current->audit_context;
context->target_pid = t->pid;
selinux_get_task_sid(t, &context->target_sid);
}
/** /**
* audit_avc_path - record the granting or denial of permissions * audit_avc_path - record the granting or denial of permissions
* @dentry: dentry to record * @dentry: dentry to record
...@@ -1918,15 +1989,17 @@ int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt) ...@@ -1918,15 +1989,17 @@ int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt)
* If the audit subsystem is being terminated, record the task (pid) * If the audit subsystem is being terminated, record the task (pid)
* and uid that is doing that. * and uid that is doing that.
*/ */
void __audit_signal_info(int sig, struct task_struct *t) int __audit_signal_info(int sig, struct task_struct *t)
{ {
struct audit_aux_data_pids *axp;
struct task_struct *tsk = current;
struct audit_context *ctx = tsk->audit_context;
extern pid_t audit_sig_pid; extern pid_t audit_sig_pid;
extern uid_t audit_sig_uid; extern uid_t audit_sig_uid;
extern u32 audit_sig_sid; extern u32 audit_sig_sid;
if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) { if (audit_pid && t->tgid == audit_pid &&
struct task_struct *tsk = current; (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1)) {
struct audit_context *ctx = tsk->audit_context;
audit_sig_pid = tsk->pid; audit_sig_pid = tsk->pid;
if (ctx) if (ctx)
audit_sig_uid = ctx->loginuid; audit_sig_uid = ctx->loginuid;
...@@ -1934,4 +2007,72 @@ void __audit_signal_info(int sig, struct task_struct *t) ...@@ -1934,4 +2007,72 @@ void __audit_signal_info(int sig, struct task_struct *t)
audit_sig_uid = tsk->uid; audit_sig_uid = tsk->uid;
selinux_get_task_sid(tsk, &audit_sig_sid); selinux_get_task_sid(tsk, &audit_sig_sid);
} }
if (!audit_signals) /* audit_context checked in wrapper */
return 0;
/* optimize the common case by putting first signal recipient directly
* in audit_context */
if (!ctx->target_pid) {
ctx->target_pid = t->tgid;
selinux_get_task_sid(t, &ctx->target_sid);
return 0;
}
axp = (void *)ctx->aux_pids;
if (!axp || axp->pid_count == AUDIT_AUX_PIDS) {
axp = kzalloc(sizeof(*axp), GFP_ATOMIC);
if (!axp)
return -ENOMEM;
axp->d.type = AUDIT_OBJ_PID;
axp->d.next = ctx->aux_pids;
ctx->aux_pids = (void *)axp;
}
BUG_ON(axp->pid_count > AUDIT_AUX_PIDS);
axp->target_pid[axp->pid_count] = t->tgid;
selinux_get_task_sid(t, &axp->target_sid[axp->pid_count]);
axp->pid_count++;
return 0;
}
/**
* audit_core_dumps - record information about processes that end abnormally
* @sig: signal value
*
* If a process ends with a core dump, something fishy is going on and we
* should record the event for investigation.
*/
void audit_core_dumps(long signr)
{
struct audit_buffer *ab;
u32 sid;
if (!audit_enabled)
return;
if (signr == SIGQUIT) /* don't care for those */
return;
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
audit_log_format(ab, "auid=%u uid=%u gid=%u",
audit_get_loginuid(current->audit_context),
current->uid, current->gid);
selinux_get_task_sid(current, &sid);
if (sid) {
char *ctx = NULL;
u32 len;
if (selinux_sid_to_string(sid, &ctx, &len))
audit_log_format(ab, " ssid=%u", sid);
else
audit_log_format(ab, " subj=%s", ctx);
kfree(ctx);
}
audit_log_format(ab, " pid=%d comm=", current->pid);
audit_log_untrustedstring(ab, current->comm);
audit_log_format(ab, " sig=%ld", signr);
audit_log_end(ab);
} }
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/audit.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -161,6 +162,8 @@ int ptrace_attach(struct task_struct *task) ...@@ -161,6 +162,8 @@ int ptrace_attach(struct task_struct *task)
{ {
int retval; int retval;
audit_ptrace(task);
retval = -EPERM; retval = -EPERM;
if (task->pid <= 1) if (task->pid <= 1)
goto out; goto out;
......
...@@ -497,6 +497,11 @@ static int check_kill_permission(int sig, struct siginfo *info, ...@@ -497,6 +497,11 @@ static int check_kill_permission(int sig, struct siginfo *info,
int error = -EINVAL; int error = -EINVAL;
if (!valid_signal(sig)) if (!valid_signal(sig))
return error; return error;
error = audit_signal_info(sig, t); /* Let audit system see the signal */
if (error)
return error;
error = -EPERM; error = -EPERM;
if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info)))
&& ((sig != SIGCONT) || && ((sig != SIGCONT) ||
...@@ -506,10 +511,7 @@ static int check_kill_permission(int sig, struct siginfo *info, ...@@ -506,10 +511,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
&& !capable(CAP_KILL)) && !capable(CAP_KILL))
return error; return error;
error = security_task_kill(t, info, sig, 0); return security_task_kill(t, info, sig, 0);
if (!error)
audit_signal_info(sig, t); /* Let audit system see the signal */
return error;
} }
/* forward decl */ /* forward decl */
......
...@@ -23,6 +23,16 @@ static unsigned chattr_class[] = { ...@@ -23,6 +23,16 @@ static unsigned chattr_class[] = {
~0U ~0U
}; };
static unsigned signal_class[] = {
#include <asm-generic/audit_signal.h>
~0U
};
int audit_classify_arch(int arch)
{
return 0;
}
int audit_classify_syscall(int abi, unsigned syscall) int audit_classify_syscall(int abi, unsigned syscall)
{ {
switch(syscall) { switch(syscall) {
...@@ -49,6 +59,7 @@ static int __init audit_classes_init(void) ...@@ -49,6 +59,7 @@ static int __init audit_classes_init(void)
audit_register_class(AUDIT_CLASS_READ, read_class); audit_register_class(AUDIT_CLASS_READ, read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
return 0; 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