@@ -14,6 +14,7 @@ config MIPS
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_USE_QUEUED_SPINLOCKS
select ARCH_WANT_IPC_PARSE_VERSION
+ select AUDIT_ARCH
select BUILDTIME_EXTABLE_SORT
select CLONE_BACKWARDS
select CPU_NO_EFFICIENT_FFS if (TARGET_ISA_REV < 1)
@@ -35,6 +36,7 @@ config MIPS
select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL
select HANDLE_DOMAIN_IRQ
+ select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_COMPILER_H
select HAVE_ARCH_JUMP_LABEL
select HAVE_ARCH_KGDB
@@ -1064,6 +1066,15 @@ config FW_ARC
config ARCH_MAY_HAVE_PC_FDC
bool
+config AUDIT_ARCH
+ bool
+
+config AUDITSYSCALL_O32
+ bool
+
+config AUDITSYSCALL_N32
+ bool
+
config BOOT_RAW
bool
@@ -3149,6 +3160,7 @@ config MIPS32_O32
select COMPAT
select MIPS32_COMPAT
select SYSVIPC_COMPAT if SYSVIPC
+ select AUDITSYSCALL_O32 if AUDITSYSCALL
help
Select this option if you want to run o32 binaries. These are pure
32-bit binaries as used by the 32-bit Linux/MIPS port. Most of
@@ -3162,6 +3174,7 @@ config MIPS32_N32
select COMPAT
select MIPS32_COMPAT
select SYSVIPC_COMPAT if SYSVIPC
+ select AUDITSYSCALL_N32 if AUDITSYSCALL
help
Select this option if you want to run n32 binaries. These are
64-bit binaries using 32-bit quantities for addressing and certain
@@ -21,6 +21,7 @@ struct mips_abi {
int (* const setup_rt_frame)(void *sig_return, struct ksignal *ksig,
struct pt_regs *regs, sigset_t *set);
const unsigned long restart;
+ const int audit_arch;
unsigned off_sc_fpregs;
unsigned off_sc_fpc_csr;
@@ -71,4 +71,14 @@
#endif /* !__ASSEMBLY__ */
+#ifdef CONFIG_MIPS32_N32
+#define NR_syscalls (__NR_N32_Linux + __NR_N32_Linux_syscalls)
+#elif defined(CONFIG_64BIT)
+#define NR_syscalls (__NR_64_Linux + __NR_64_Linux_syscalls)
+#elif defined(CONFIG_32BIT)
+#define NR_syscalls (__NR_O32_Linux + __NR_O32_Linux_syscalls)
+#else
+#error Must know ABIs in use to define NR_syscalls
+#endif
+
#endif /* _ASM_UNISTD_H */
@@ -6,34 +6,37 @@
*
* Copyright (C) 1995, 96, 97, 98, 99, 2000 by Ralf Baechle
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- *
- * Changed system calls macros _syscall5 - _syscall7 to push args 5 to 7 onto
- * the stack. Robin Farine for ACN S.A, Copyright (C) 1996 by ACN S.A
*/
#ifndef _UAPI_ASM_UNISTD_H
#define _UAPI_ASM_UNISTD_H
#include <asm/sgidefs.h>
-#if _MIPS_SIM == _MIPS_SIM_ABI32
+#if (defined(__WANT_SYSCALL_NUMBERS) && \
+ (__WANT_SYSCALL_NUMBERS == _MIPS_SIM_ABI32)) || \
+ (!defined(__WANT_SYSCALL_NUMBERS) && _MIPS_SIM == _MIPS_SIM_ABI32)
#define __NR_Linux 4000
#include <asm/unistd_o32.h>
-#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
+#endif /* Want O32 || _MIPS_SIM == _MIPS_SIM_ABI32 */
-#if _MIPS_SIM == _MIPS_SIM_ABI64
+#if (defined(__WANT_SYSCALL_NUMBERS) && \
+ (__WANT_SYSCALL_NUMBERS == _MIPS_SIM_ABI64)) || \
+ (!defined(__WANT_SYSCALL_NUMBERS) && _MIPS_SIM == _MIPS_SIM_ABI64)
#define __NR_Linux 5000
#include <asm/unistd_n64.h>
-#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
+#endif /* Want N64 || _MIPS_SIM == _MIPS_SIM_ABI64 */
-#if _MIPS_SIM == _MIPS_SIM_NABI32
+#if (defined(__WANT_SYSCALL_NUMBERS) && \
+ (__WANT_SYSCALL_NUMBERS == _MIPS_SIM_NABI32)) || \
+ (!defined(__WANT_SYSCALL_NUMBERS) && _MIPS_SIM == _MIPS_SIM_NABI32)
#define __NR_Linux 6000
#include <asm/unistd_n32.h>
-#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
+#endif /* Want N32 || _MIPS_SIM == _MIPS_SIM_NABI32 */
#endif /* _UAPI_ASM_UNISTD_H */
@@ -106,6 +106,10 @@ obj-$(CONFIG_HW_PERF_EVENTS) += perf_event_mipsxx.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
obj-$(CONFIG_UPROBES) += uprobes.o
+obj-$(CONFIG_AUDITSYSCALL_O32) += audit-o32.o
+obj-$(CONFIG_AUDITSYSCALL_N32) += audit-n32.o
+obj-$(CONFIG_AUDITSYSCALL) += audit-native.o
+
obj-$(CONFIG_MIPS_CM) += mips-cm.o
obj-$(CONFIG_MIPS_CPC) += mips-cpc.o
new file mode 100644
@@ -0,0 +1,58 @@
+#define __WANT_SYSCALL_NUMBERS _MIPS_SIM_NABI32
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/audit.h>
+#include <asm/unistd.h>
+
+static unsigned dir_class_n32[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+static unsigned read_class_n32[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+static unsigned write_class_n32[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+static unsigned chattr_class_n32[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+static unsigned signal_class_n32[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
+int audit_classify_syscall_n32(int abi, unsigned syscall)
+{
+ switch (syscall) {
+ case __NR_open:
+ return 2;
+ case __NR_openat:
+ return 3;
+ case __NR_execve:
+ return 5;
+ default:
+ return 0;
+ }
+}
+
+static int __init audit_classes_n32_init(void)
+{
+ audit_register_class(AUDIT_CLASS_WRITE_N32, write_class_n32);
+ audit_register_class(AUDIT_CLASS_READ_N32, read_class_n32);
+ audit_register_class(AUDIT_CLASS_DIR_WRITE_N32, dir_class_n32);
+ audit_register_class(AUDIT_CLASS_CHATTR_N32, chattr_class_n32);
+ audit_register_class(AUDIT_CLASS_SIGNAL_N32, signal_class_n32);
+
+ return 0;
+}
+
+__initcall(audit_classes_n32_init);
new file mode 100644
@@ -0,0 +1,97 @@
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/audit.h>
+#include <asm/unistd.h>
+
+static unsigned dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+static unsigned read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+static unsigned write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+static unsigned chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
+
+/*
+ * Pretend to be a single architecture
+ */
+int audit_classify_arch(int arch)
+{
+ return 0;
+}
+
+extern int audit_classify_syscall_o32(int abi, unsigned syscall);
+extern int audit_classify_syscall_n32(int abi, unsigned syscall);
+
+int audit_classify_syscall(int abi, unsigned syscall)
+{
+ int res;
+
+ switch (syscall) {
+ case __NR_open:
+ res = 2;
+ break;
+
+ case __NR_openat:
+ res = 3;
+ break;
+
+#ifdef __NR_socketcall /* Only exists on O32 */
+ case __NR_socketcall:
+ res = 4;
+ break;
+#endif
+ case __NR_execve:
+ res = 5;
+ break;
+ default:
+#ifdef CONFIG_AUDITSYSCALL_O32
+ res = audit_classify_syscall_o32(abi, syscall);
+ if (res)
+ break;
+#endif
+#ifdef CONFIG_AUDITSYSCALL_N32
+ res = audit_classify_syscall_n32(abi, syscall);
+ if (res)
+ break;
+#endif
+ if (abi == AUDIT_ARCH_MIPS || abi == AUDIT_ARCH_MIPSEL)
+ res = 1;
+ else if (abi == AUDIT_ARCH_MIPS64 || abi == AUDIT_ARCH_MIPSEL64)
+ res = 0;
+ else if (abi == AUDIT_ARCH_MIPS64N32 || abi == AUDIT_ARCH_MIPSEL64N32)
+ res = 6;
+ }
+
+ return res;
+}
+
+static int __init audit_classes_init(void)
+{
+ audit_register_class(AUDIT_CLASS_WRITE, write_class);
+ audit_register_class(AUDIT_CLASS_READ, read_class);
+ audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
+ audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+ audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
+
+ return 0;
+}
+
+__initcall(audit_classes_init);
new file mode 100644
@@ -0,0 +1,60 @@
+#define __WANT_SYSCALL_NUMBERS _MIPS_SIM_ABI32
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/audit.h>
+#include <linux/unistd.h>
+
+static unsigned dir_class_o32[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+static unsigned read_class_o32[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+static unsigned write_class_o32[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+static unsigned chattr_class_o32[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+static unsigned signal_class_o32[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
+int audit_classify_syscall_o32(int abi, unsigned syscall)
+{
+ switch (syscall) {
+ case __NR_open:
+ return 2;
+ case __NR_openat:
+ return 3;
+ case __NR_socketcall:
+ return 4;
+ case __NR_execve:
+ return 5;
+ default:
+ return 0;
+ }
+}
+
+static int __init audit_classes_o32_init(void)
+{
+ audit_register_class(AUDIT_CLASS_WRITE_32, write_class_o32);
+ audit_register_class(AUDIT_CLASS_READ_32, read_class_o32);
+ audit_register_class(AUDIT_CLASS_DIR_WRITE_32, dir_class_o32);
+ audit_register_class(AUDIT_CLASS_CHATTR_32, chattr_class_o32);
+ audit_register_class(AUDIT_CLASS_SIGNAL_32, signal_class_o32);
+
+ return 0;
+}
+
+__initcall(audit_classes_o32_init);
@@ -8,6 +8,7 @@
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
* Copyright (C) 2014, Imagination Technologies Ltd.
*/
+#include <linux/audit.h>
#include <linux/cache.h>
#include <linux/context_tracking.h>
#include <linux/irqflags.h>
@@ -790,6 +791,23 @@ struct mips_abi mips_abi = {
#endif
.setup_rt_frame = setup_rt_frame,
.restart = __NR_restart_syscall,
+#ifdef CONFIG_64BIT
+# ifdef __BIG_ENDIAN
+ .audit_arch = AUDIT_ARCH_MIPS64,
+# elif defined(__LITTLE_ENDIAN)
+ .audit_arch = AUDIT_ARCH_MIPSEL64,
+# else
+# error "Neither big nor little endian ???"
+# endif
+#else
+# ifdef __BIG_ENDIAN
+ .audit_arch = AUDIT_ARCH_MIPS,
+# elif defined(__LITTLE_ENDIAN)
+ .audit_arch = AUDIT_ARCH_MIPSEL,
+# else
+# error "Neither big nor little endian ???"
+# endif
+#endif
.off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs),
.off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr),
@@ -15,6 +15,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#include <linux/audit.h>
#include <linux/cache.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -153,6 +154,13 @@ static int setup_rt_frame_n32(void *sig_return, struct ksignal *ksig,
struct mips_abi mips_abi_n32 = {
.setup_rt_frame = setup_rt_frame_n32,
.restart = __NR_N32_restart_syscall,
+#ifdef __BIG_ENDIAN
+ .audit_arch = AUDIT_ARCH_MIPS64N32,
+#elif defined(__LITTLE_ENDIAN)
+ .audit_arch = AUDIT_ARCH_MIPSEL64N32,
+#else
+# error "Neither big nor little endian ???"
+#endif
.off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs),
.off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr),
@@ -8,6 +8,7 @@
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
* Copyright (C) 2016, Imagination Technologies Ltd.
*/
+#include <linux/audit.h>
#include <linux/compiler.h>
#include <linux/errno.h>
#include <linux/signal.h>
@@ -244,6 +245,13 @@ struct mips_abi mips_abi_32 = {
.setup_frame = setup_frame_32,
.setup_rt_frame = setup_rt_frame_32,
.restart = __NR_O32_restart_syscall,
+#ifdef __BIG_ENDIAN
+ .audit_arch = AUDIT_ARCH_MIPS,
+#elif defined(__LITTLE_ENDIAN)
+ .audit_arch = AUDIT_ARCH_MIPSEL,
+#else
+# error "Neither big nor little endian ???"
+#endif
.off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs),
.off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr),
@@ -175,7 +175,11 @@
* AUDIT_LIST commands must be implemented. */
#define AUDIT_MAX_FIELDS 64
#define AUDIT_MAX_KEY_LEN 256
+#ifdef __mips__
+#define AUDIT_BITMASK_SIZE 256
+#else
#define AUDIT_BITMASK_SIZE 64
+#endif
#define AUDIT_WORD(nr) ((__u32)((nr)/32))
#define AUDIT_BIT(nr) (1 << ((nr) - AUDIT_WORD(nr)*32))
@@ -191,6 +195,12 @@
#define AUDIT_CLASS_SIGNAL 8
#define AUDIT_CLASS_SIGNAL_32 9
+#define AUDIT_CLASS_DIR_WRITE_N32 10
+#define AUDIT_CLASS_CHATTR_N32 11
+#define AUDIT_CLASS_READ_N32 12
+#define AUDIT_CLASS_WRITE_N32 13
+#define AUDIT_CLASS_SIGNAL_N32 14
+
/* 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.
* If you are adding a new #define AUDIT_<whatever>, please ensure that
@@ -168,6 +168,19 @@ static int audit_match_perm(struct audit_context *ctx, int mask)
return ((mask & AUDIT_PERM_WRITE) && ctx->argv[0] == SYS_BIND);
case 5: /* execve */
return mask & AUDIT_PERM_EXEC;
+#ifdef CONFIG_MIPS
+ case 6: /* for N32 */
+ if ((mask & AUDIT_PERM_WRITE) &&
+ audit_match_class(AUDIT_CLASS_WRITE_N32, n))
+ return 1;
+ if ((mask & AUDIT_PERM_READ) &&
+ audit_match_class(AUDIT_CLASS_READ_N32, n))
+ return 1;
+ if ((mask & AUDIT_PERM_ATTR) &&
+ audit_match_class(AUDIT_CLASS_CHATTR_N32, n))
+ return 1;
+ return 0;
+#endif
default:
return 0;
}