From 95e0b46fcebd7dbf6850dee96046e4c4ddc7f69c Mon Sep 17 00:00:00 2001 From: Li RongQing Date: Thu, 7 Mar 2019 09:16:24 +0800 Subject: audit: fix a memleak caused by auditing load module module.name will be allocated unconditionally when auditing load module, and audit_log_start() can fail with other reasons, or audit_log_exit maybe not called, caused module.name is not freed so free module.name in audit_free_context and __audit_syscall_exit unreferenced object 0xffff88af90837d20 (size 8): comm "modprobe", pid 1036, jiffies 4294704867 (age 3069.138s) hex dump (first 8 bytes): 69 78 67 62 65 00 ff ff ixgbe... backtrace: [<0000000008da28fe>] __audit_log_kern_module+0x33/0x80 [<00000000c1491e61>] load_module+0x64f/0x3850 [<000000007fc9ae3f>] __do_sys_init_module+0x218/0x250 [<0000000000d4a478>] do_syscall_64+0x117/0x400 [<000000004924ded8>] entry_SYSCALL_64_after_hwframe+0x49/0xbe [<000000007dc331dd>] 0xffffffffffffffff Fixes: ca86cad7380e3 ("audit: log module name on init_module") Signed-off-by: Zhang Yu Signed-off-by: Li RongQing [PM: manual merge fixup in __audit_syscall_exit()] Signed-off-by: Paul Moore --- kernel/auditsc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index d1eab1d4a930..fa7b8047aab8 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -840,6 +840,13 @@ static inline void audit_proctitle_free(struct audit_context *context) context->proctitle.len = 0; } +static inline void audit_free_module(struct audit_context *context) +{ + if (context->type == AUDIT_KERN_MODULE) { + kfree(context->module.name); + context->module.name = NULL; + } +} static inline void audit_free_names(struct audit_context *context) { struct audit_names *n, *next; @@ -923,6 +930,7 @@ int audit_alloc(struct task_struct *tsk) static inline void audit_free_context(struct audit_context *context) { + audit_free_module(context); audit_free_names(context); unroll_tree_refs(context, NULL, 0); free_tree_refs(context); @@ -1266,7 +1274,6 @@ static void show_special(struct audit_context *context, int *call_panic) audit_log_format(ab, "name="); if (context->module.name) { audit_log_untrustedstring(ab, context->module.name); - kfree(context->module.name); } else audit_log_format(ab, "(null)"); @@ -1697,6 +1704,7 @@ void __audit_syscall_exit(int success, long return_code) context->in_syscall = 0; context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; + audit_free_module(context); audit_free_names(context); unroll_tree_refs(context, NULL, 0); audit_free_aux(context); -- cgit From 73e65b88feb919f95bdb77c4ed35f69588cf27ee Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Tue, 19 Mar 2019 15:23:29 -0400 Subject: audit: connect LOGIN record to its syscall record Currently the AUDIT_LOGIN event is a standalone record that isn't connected to any other records that may be part of its syscall event. To avoid the confusion of generating two events, connect the records by using its syscall context. Please see the github issue https://github.com/linux-audit/audit-kernel/issues/110 Signed-off-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/audit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/audit.c b/kernel/audit.c index c89ea48c70a6..b96bf69183f4 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -2220,7 +2220,7 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, if (!audit_enabled) return; - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); + ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_LOGIN); if (!ab) return; -- cgit From 2efa48fec0c344a6ca1bba66b15d63d38cf20199 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 20 Mar 2019 21:59:22 +0800 Subject: audit: Make audit_log_cap and audit_copy_inode static Fix sparse warning: kernel/auditsc.c:1150:6: warning: symbol 'audit_log_cap' was not declared. Should it be static? kernel/auditsc.c:1908:6: warning: symbol 'audit_copy_inode' was not declared. Should it be static? Signed-off-by: YueHaibing Acked-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/auditsc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index fa7b8047aab8..17b0007fafc2 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1147,7 +1147,8 @@ out: kfree(buf_head); } -void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap) +static void audit_log_cap(struct audit_buffer *ab, char *prefix, + kernel_cap_t *cap) { int i; @@ -1905,8 +1906,9 @@ static inline int audit_copy_fcaps(struct audit_names *name, } /* Copy inode data into an audit_names. */ -void audit_copy_inode(struct audit_names *name, const struct dentry *dentry, - struct inode *inode, unsigned int flags) +static void audit_copy_inode(struct audit_names *name, + const struct dentry *dentry, + struct inode *inode, unsigned int flags) { name->ino = inode->i_ino; name->dev = inode->i_sb->s_dev; -- cgit From 162f33dd45a7ed606ae07c1e3f22db4ac43a584c Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 18 Mar 2019 02:28:39 +0300 Subject: Move EM_ARCOMPACT and EM_ARCV2 to uapi/linux/elf-em.h These should never have been defined in the arch tree to begin with, and now uapi/linux/audit.h header is going to use EM_ARCOMPACT and EM_ARCV2 in order to define AUDIT_ARCH_ARCOMPACT and AUDIT_ARCH_ARCV2 which are needed to implement syscall_get_arch() which in turn is required to extend the generic ptrace API with PTRACE_GET_SYSCALL_INFO request. Acked-by: Vineet Gupta Acked-by: Paul Moore Cc: Elvira Khabirova Cc: Eugene Syromyatnikov Cc: Alexey Brodkin Cc: Oleg Nesterov Cc: Andy Lutomirski Cc: linux-snps-arc@lists.infradead.org Cc: linux-audit@redhat.com Signed-off-by: Dmitry V. Levin Signed-off-by: Paul Moore --- arch/arc/include/asm/elf.h | 6 +----- include/uapi/linux/elf-em.h | 2 ++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/arc/include/asm/elf.h b/arch/arc/include/asm/elf.h index aa2d6da9d187..2b80c184c9c8 100644 --- a/arch/arc/include/asm/elf.h +++ b/arch/arc/include/asm/elf.h @@ -10,13 +10,9 @@ #define __ASM_ARC_ELF_H #include +#include #include -/* These ELF defines belong to uapi but libc elf.h already defines them */ -#define EM_ARCOMPACT 93 - -#define EM_ARCV2 195 /* ARCv2 Cores */ - #define EM_ARC_INUSE (IS_ENABLED(CONFIG_ISA_ARCOMPACT) ? \ EM_ARCOMPACT : EM_ARCV2) diff --git a/include/uapi/linux/elf-em.h b/include/uapi/linux/elf-em.h index 0c3000faedba..081675ed89cb 100644 --- a/include/uapi/linux/elf-em.h +++ b/include/uapi/linux/elf-em.h @@ -34,6 +34,7 @@ #define EM_M32R 88 /* Renesas M32R */ #define EM_MN10300 89 /* Panasonic/MEI MN10300, AM33 */ #define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ +#define EM_ARCOMPACT 93 /* ARCompact processor */ #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ #define EM_BLACKFIN 106 /* ADI Blackfin Processor */ #define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */ @@ -42,6 +43,7 @@ #define EM_TILEPRO 188 /* Tilera TILEPro */ #define EM_MICROBLAZE 189 /* Xilinx MicroBlaze */ #define EM_TILEGX 191 /* Tilera TILE-Gx */ +#define EM_ARCV2 195 /* ARCv2 Cores */ #define EM_RISCV 243 /* RISC-V */ #define EM_BPF 247 /* Linux BPF - in-kernel virtual machine */ #define EM_CSKY 252 /* C-SKY */ -- cgit From 67f2a8a29311841ba6ab9b0e2d1b8f1e9978cd84 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 18 Mar 2019 02:28:47 +0300 Subject: arc: define syscall_get_arch() syscall_get_arch() is required to be implemented on all architectures in addition to already implemented syscall_get_nr(), syscall_get_arguments(), syscall_get_error(), and syscall_get_return_value() functions in order to extend the generic ptrace API with PTRACE_GET_SYSCALL_INFO request. Acked-by: Vineet Gupta Acked-by: Paul Moore Cc: Elvira Khabirova Cc: Eugene Syromyatnikov Cc: Alexey Brodkin Cc: Oleg Nesterov Cc: Andy Lutomirski Cc: linux-snps-arc@lists.infradead.org Cc: linux-audit@redhat.com Signed-off-by: Dmitry V. Levin Signed-off-by: Paul Moore --- arch/arc/include/asm/syscall.h | 11 +++++++++++ include/uapi/linux/audit.h | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/arch/arc/include/asm/syscall.h b/arch/arc/include/asm/syscall.h index 29de09804306..c7fc4c0c3bcb 100644 --- a/arch/arc/include/asm/syscall.h +++ b/arch/arc/include/asm/syscall.h @@ -9,6 +9,7 @@ #ifndef _ASM_ARC_SYSCALL_H #define _ASM_ARC_SYSCALL_H 1 +#include #include #include #include @@ -68,4 +69,14 @@ syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, } } +static inline int +syscall_get_arch(void) +{ + return IS_ENABLED(CONFIG_ISA_ARCOMPACT) + ? (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) + ? AUDIT_ARCH_ARCOMPACTBE : AUDIT_ARCH_ARCOMPACT) + : (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) + ? AUDIT_ARCH_ARCV2BE : AUDIT_ARCH_ARCV2); +} + #endif diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index f28acd952d03..1626727bb921 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -375,6 +375,10 @@ enum { #define AUDIT_ARCH_AARCH64 (EM_AARCH64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) #define AUDIT_ARCH_ALPHA (EM_ALPHA|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_ARCOMPACT (EM_ARCOMPACT|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_ARCOMPACTBE (EM_ARCOMPACT) +#define AUDIT_ARCH_ARCV2 (EM_ARCV2|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_ARCV2BE (EM_ARCV2) #define AUDIT_ARCH_ARM (EM_ARM|__AUDIT_ARCH_LE) #define AUDIT_ARCH_ARMEB (EM_ARM) #define AUDIT_ARCH_CRIS (EM_CRIS|__AUDIT_ARCH_LE) -- cgit From a43e66478ef7a2f8a7b2823b97cdae6605d34a02 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 18 Mar 2019 02:28:53 +0300 Subject: c6x: define syscall_get_arch() syscall_get_arch() is required to be implemented on all architectures in addition to already implemented syscall_get_nr(), syscall_get_arguments(), syscall_get_error(), and syscall_get_return_value() functions in order to extend the generic ptrace API with PTRACE_GET_SYSCALL_INFO request. Acked-by: Mark Salter Acked-by: Paul Moore Cc: Elvira Khabirova Cc: Eugene Syromyatnikov Cc: Aurelien Jacquiot Cc: Oleg Nesterov Cc: Andy Lutomirski Cc: linux-c6x-dev@linux-c6x.org Cc: linux-audit@redhat.com Signed-off-by: Dmitry V. Levin Signed-off-by: Paul Moore --- arch/c6x/include/asm/syscall.h | 7 +++++++ include/uapi/linux/audit.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/arch/c6x/include/asm/syscall.h b/arch/c6x/include/asm/syscall.h index ae2be315ee9c..39dbd1ef994c 100644 --- a/arch/c6x/include/asm/syscall.h +++ b/arch/c6x/include/asm/syscall.h @@ -11,6 +11,7 @@ #ifndef __ASM_C6X_SYSCALL_H #define __ASM_C6X_SYSCALL_H +#include #include #include @@ -120,4 +121,10 @@ static inline void syscall_set_arguments(struct task_struct *task, } } +static inline int syscall_get_arch(void) +{ + return IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) + ? AUDIT_ARCH_C6XBE : AUDIT_ARCH_C6X; +} + #endif /* __ASM_C6X_SYSCALLS_H */ diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 1626727bb921..35ccf269ca3d 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -381,6 +381,8 @@ enum { #define AUDIT_ARCH_ARCV2BE (EM_ARCV2) #define AUDIT_ARCH_ARM (EM_ARM|__AUDIT_ARCH_LE) #define AUDIT_ARCH_ARMEB (EM_ARM) +#define AUDIT_ARCH_C6X (EM_TI_C6000|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_C6XBE (EM_TI_C6000) #define AUDIT_ARCH_CRIS (EM_CRIS|__AUDIT_ARCH_LE) #define AUDIT_ARCH_CSKY (EM_CSKY|__AUDIT_ARCH_LE) #define AUDIT_ARCH_FRV (EM_FRV) -- cgit From 122a43b107420fec4c69d1bf99706cbb0da40ad9 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 18 Mar 2019 02:29:01 +0300 Subject: h8300: define syscall_get_arch() syscall_get_arch() is required to be implemented on all architectures in addition to already implemented syscall_get_nr(), syscall_get_arguments(), syscall_get_error(), and syscall_get_return_value() functions in order to extend the generic ptrace API with PTRACE_GET_SYSCALL_INFO request. Acked-by: Paul Moore Cc: Elvira Khabirova Cc: Eugene Syromyatnikov Cc: Yoshinori Sato Cc: Oleg Nesterov Cc: Andy Lutomirski Cc: uclinux-h8-devel@lists.sourceforge.jp Cc: linux-audit@redhat.com Signed-off-by: Dmitry V. Levin Signed-off-by: Paul Moore --- arch/h8300/include/asm/syscall.h | 6 ++++++ include/uapi/linux/audit.h | 1 + 2 files changed, 7 insertions(+) diff --git a/arch/h8300/include/asm/syscall.h b/arch/h8300/include/asm/syscall.h index 924990401237..5135910616e2 100644 --- a/arch/h8300/include/asm/syscall.h +++ b/arch/h8300/include/asm/syscall.h @@ -8,6 +8,7 @@ #include #include #include +#include static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs) @@ -47,6 +48,11 @@ syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, } } +static inline int +syscall_get_arch(void) +{ + return AUDIT_ARCH_H8300; +} /* Misc syscall related bits */ diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 35ccf269ca3d..09994181b2d5 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -386,6 +386,7 @@ enum { #define AUDIT_ARCH_CRIS (EM_CRIS|__AUDIT_ARCH_LE) #define AUDIT_ARCH_CSKY (EM_CSKY|__AUDIT_ARCH_LE) #define AUDIT_ARCH_FRV (EM_FRV) +#define AUDIT_ARCH_H8300 (EM_H8_300) #define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE) #define AUDIT_ARCH_IA64 (EM_IA_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) #define AUDIT_ARCH_M32R (EM_M32R) -- cgit From f4780e2db06df05c7349718baf1cd26767aa90f8 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 18 Mar 2019 02:29:08 +0300 Subject: Move EM_HEXAGON to uapi/linux/elf-em.h This should never have been defined in the arch tree to begin with, and now uapi/linux/audit.h header is going to use EM_HEXAGON in order to define AUDIT_ARCH_HEXAGON which is needed to implement syscall_get_arch() which in turn is required to extend the generic ptrace API with PTRACE_GET_SYSCALL_INFO request. Acked-by: Paul Moore Cc: Elvira Khabirova Cc: Eugene Syromyatnikov Cc: Oleg Nesterov Cc: Andy Lutomirski Cc: Richard Kuo Cc: linux-hexagon@vger.kernel.org Cc: linux-audit@redhat.com Signed-off-by: Dmitry V. Levin Signed-off-by: Paul Moore --- arch/hexagon/include/asm/elf.h | 6 +----- include/uapi/linux/elf-em.h | 1 + 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/arch/hexagon/include/asm/elf.h b/arch/hexagon/include/asm/elf.h index 80311e7b8ca6..d10fbd54ae51 100644 --- a/arch/hexagon/include/asm/elf.h +++ b/arch/hexagon/include/asm/elf.h @@ -23,11 +23,7 @@ #include #include - -/* - * This should really be in linux/elf-em.h. - */ -#define EM_HEXAGON 164 /* QUALCOMM Hexagon */ +#include struct elf32_hdr; diff --git a/include/uapi/linux/elf-em.h b/include/uapi/linux/elf-em.h index 081675ed89cb..bd02325028d8 100644 --- a/include/uapi/linux/elf-em.h +++ b/include/uapi/linux/elf-em.h @@ -39,6 +39,7 @@ #define EM_BLACKFIN 106 /* ADI Blackfin Processor */ #define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */ #define EM_TI_C6000 140 /* TI C6X DSPs */ +#define EM_HEXAGON 164 /* QUALCOMM Hexagon */ #define EM_AARCH64 183 /* ARM 64 bit */ #define EM_TILEPRO 188 /* Tilera TILEPro */ #define EM_MICROBLAZE 189 /* Xilinx MicroBlaze */ -- cgit From d093153431dc6e5982ec77aabe31fa38d2041ac0 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 18 Mar 2019 02:29:32 +0300 Subject: hexagon: define syscall_get_arch() syscall_get_arch() is required to be implemented on all architectures in addition to already implemented syscall_get_nr(), syscall_get_arguments(), syscall_get_error(), and syscall_get_return_value() functions in order to extend the generic ptrace API with PTRACE_GET_SYSCALL_INFO request. Acked-by: Paul Moore Cc: Elvira Khabirova Cc: Eugene Syromyatnikov Cc: Richard Kuo Cc: Oleg Nesterov Cc: Andy Lutomirski Cc: linux-hexagon@vger.kernel.org Cc: linux-audit@redhat.com Signed-off-by: Dmitry V. Levin Signed-off-by: Paul Moore --- arch/hexagon/include/asm/syscall.h | 8 ++++++++ include/uapi/linux/audit.h | 1 + 2 files changed, 9 insertions(+) diff --git a/arch/hexagon/include/asm/syscall.h b/arch/hexagon/include/asm/syscall.h index 4af9c7b6f13a..de3917aad3fd 100644 --- a/arch/hexagon/include/asm/syscall.h +++ b/arch/hexagon/include/asm/syscall.h @@ -21,6 +21,8 @@ #ifndef _ASM_HEXAGON_SYSCALL_H #define _ASM_HEXAGON_SYSCALL_H +#include + typedef long (*syscall_fn)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); @@ -43,4 +45,10 @@ static inline void syscall_get_arguments(struct task_struct *task, BUG_ON(i + n > 6); memcpy(args, &(®s->r00)[i], n * sizeof(args[0])); } + +static inline int syscall_get_arch(void) +{ + return AUDIT_ARCH_HEXAGON; +} + #endif diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 09994181b2d5..fc94e74c8b77 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -387,6 +387,7 @@ enum { #define AUDIT_ARCH_CSKY (EM_CSKY|__AUDIT_ARCH_LE) #define AUDIT_ARCH_FRV (EM_FRV) #define AUDIT_ARCH_H8300 (EM_H8_300) +#define AUDIT_ARCH_HEXAGON (EM_HEXAGON) #define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE) #define AUDIT_ARCH_IA64 (EM_IA_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) #define AUDIT_ARCH_M32R (EM_M32R) -- cgit From 92f922f35078245e2acbafcf74fb1947dbbac398 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 18 Mar 2019 02:29:38 +0300 Subject: m68k: define syscall_get_arch() syscall_get_arch() is required to be implemented on all architectures in addition to already implemented syscall_get_nr(), syscall_get_arguments(), syscall_get_error(), and syscall_get_return_value() functions in order to extend the generic ptrace API with PTRACE_GET_SYSCALL_INFO request. Reviewed-by: Geert Uytterhoeven Acked-by: Paul Moore Cc: Elvira Khabirova Cc: Eugene Syromyatnikov Cc: Oleg Nesterov Cc: Andy Lutomirski Cc: linux-m68k@lists.linux-m68k.org Cc: linux-audit@redhat.com Signed-off-by: Dmitry V. Levin Signed-off-by: Paul Moore --- arch/m68k/include/asm/syscall.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 arch/m68k/include/asm/syscall.h diff --git a/arch/m68k/include/asm/syscall.h b/arch/m68k/include/asm/syscall.h new file mode 100644 index 000000000000..d4d7deda8d50 --- /dev/null +++ b/arch/m68k/include/asm/syscall.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_M68K_SYSCALL_H +#define _ASM_M68K_SYSCALL_H + +#include + +static inline int syscall_get_arch(void) +{ + return AUDIT_ARCH_M68K; +} + +#endif /* _ASM_M68K_SYSCALL_H */ -- cgit From 530ff23a8e46814a1be4a516c707d3b0fb292186 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 18 Mar 2019 02:29:48 +0300 Subject: Move EM_NDS32 to uapi/linux/elf-em.h This should never have been defined in the arch tree to begin with, and now uapi/linux/audit.h header is going to use EM_NDS32 in order to define AUDIT_ARCH_NDS32 which is needed to implement syscall_get_arch() which in turn is required to extend the generic ptrace API with PTRACE_GET_SYSCALL_INFO request. Acked-by: Paul Moore Acked-by: Vincent Chen Acked-by: Greentime Hu Cc: Elvira Khabirova Cc: Eugene Syromyatnikov Cc: Oleg Nesterov Cc: Andy Lutomirski Cc: linux-audit@redhat.com Signed-off-by: Dmitry V. Levin Signed-off-by: Paul Moore --- arch/nds32/include/asm/elf.h | 3 +-- include/uapi/linux/elf-em.h | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/nds32/include/asm/elf.h b/arch/nds32/include/asm/elf.h index 95f3ea253e4c..02250626b9f0 100644 --- a/arch/nds32/include/asm/elf.h +++ b/arch/nds32/include/asm/elf.h @@ -10,14 +10,13 @@ #include #include +#include typedef unsigned long elf_greg_t; typedef unsigned long elf_freg_t[3]; extern unsigned int elf_hwcap; -#define EM_NDS32 167 - #define R_NDS32_NONE 0 #define R_NDS32_16_RELA 19 #define R_NDS32_32_RELA 20 diff --git a/include/uapi/linux/elf-em.h b/include/uapi/linux/elf-em.h index bd02325028d8..4b8df722330e 100644 --- a/include/uapi/linux/elf-em.h +++ b/include/uapi/linux/elf-em.h @@ -40,6 +40,8 @@ #define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */ #define EM_TI_C6000 140 /* TI C6X DSPs */ #define EM_HEXAGON 164 /* QUALCOMM Hexagon */ +#define EM_NDS32 167 /* Andes Technology compact code size + embedded RISC processor family */ #define EM_AARCH64 183 /* ARM 64 bit */ #define EM_TILEPRO 188 /* Tilera TILEPro */ #define EM_MICROBLAZE 189 /* Xilinx MicroBlaze */ -- cgit From fa562447e154334523daa44c0b60625d71a345f5 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 18 Mar 2019 02:29:57 +0300 Subject: nds32: define syscall_get_arch() syscall_get_arch() is required to be implemented on all architectures in addition to already implemented syscall_get_nr(), syscall_get_arguments(), syscall_get_error(), and syscall_get_return_value() functions in order to extend the generic ptrace API with PTRACE_GET_SYSCALL_INFO request. Acked-by: Paul Moore Acked-by: Vincent Chen Acked-by: Greentime Hu Cc: Elvira Khabirova Cc: Eugene Syromyatnikov Cc: Oleg Nesterov Cc: Andy Lutomirski Cc: linux-audit@redhat.com Signed-off-by: Dmitry V. Levin Signed-off-by: Paul Moore --- arch/nds32/include/asm/syscall.h | 9 +++++++++ include/uapi/linux/audit.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/arch/nds32/include/asm/syscall.h b/arch/nds32/include/asm/syscall.h index f7e5e86765fe..cc56a3962f8b 100644 --- a/arch/nds32/include/asm/syscall.h +++ b/arch/nds32/include/asm/syscall.h @@ -5,6 +5,7 @@ #ifndef _ASM_NDS32_SYSCALL_H #define _ASM_NDS32_SYSCALL_H 1 +#include #include struct task_struct; struct pt_regs; @@ -185,4 +186,12 @@ void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, memcpy(®s->uregs[0] + i, args, n * sizeof(args[0])); } + +static inline int +syscall_get_arch(void) +{ + return IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) + ? AUDIT_ARCH_NDS32BE : AUDIT_ARCH_NDS32; +} + #endif /* _ASM_NDS32_SYSCALL_H */ diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index fc94e74c8b77..fb0529da4d49 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -401,6 +401,8 @@ enum { #define AUDIT_ARCH_MIPSEL64 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) #define AUDIT_ARCH_MIPSEL64N32 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE|\ __AUDIT_ARCH_CONVENTION_MIPS64_N32) +#define AUDIT_ARCH_NDS32 (EM_NDS32|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_NDS32BE (EM_NDS32) #define AUDIT_ARCH_OPENRISC (EM_OPENRISC) #define AUDIT_ARCH_PARISC (EM_PARISC) #define AUDIT_ARCH_PARISC64 (EM_PARISC|__AUDIT_ARCH_64BIT) -- cgit From 1660aac45e5b49a5ace29fb5b73254617533fcbd Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 18 Mar 2019 02:30:02 +0300 Subject: nios2: define syscall_get_arch() syscall_get_arch() is required to be implemented on all architectures in addition to already implemented syscall_get_nr(), syscall_get_arguments(), syscall_get_error(), and syscall_get_return_value() functions in order to extend the generic ptrace API with PTRACE_GET_SYSCALL_INFO request. Acked-by: Paul Moore Acked-by: Ley Foon Tan Cc: Elvira Khabirova Cc: Eugene Syromyatnikov Cc: Ley Foon Tan Cc: Oleg Nesterov Cc: Andy Lutomirski Cc: nios2-dev@lists.rocketboards.org Cc: linux-audit@redhat.com Signed-off-by: Dmitry V. Levin Signed-off-by: Paul Moore --- arch/nios2/include/asm/syscall.h | 6 ++++++ include/uapi/linux/audit.h | 1 + 2 files changed, 7 insertions(+) diff --git a/arch/nios2/include/asm/syscall.h b/arch/nios2/include/asm/syscall.h index 9de220854c4a..cf35e210fc4d 100644 --- a/arch/nios2/include/asm/syscall.h +++ b/arch/nios2/include/asm/syscall.h @@ -17,6 +17,7 @@ #ifndef __ASM_NIOS2_SYSCALL_H__ #define __ASM_NIOS2_SYSCALL_H__ +#include #include #include @@ -135,4 +136,9 @@ static inline void syscall_set_arguments(struct task_struct *task, } } +static inline int syscall_get_arch(void) +{ + return AUDIT_ARCH_NIOS2; +} + #endif diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index fb0529da4d49..bcc0619b046f 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -403,6 +403,7 @@ enum { __AUDIT_ARCH_CONVENTION_MIPS64_N32) #define AUDIT_ARCH_NDS32 (EM_NDS32|__AUDIT_ARCH_LE) #define AUDIT_ARCH_NDS32BE (EM_NDS32) +#define AUDIT_ARCH_NIOS2 (EM_ALTERA_NIOS2|__AUDIT_ARCH_LE) #define AUDIT_ARCH_OPENRISC (EM_OPENRISC) #define AUDIT_ARCH_PARISC (EM_PARISC) #define AUDIT_ARCH_PARISC64 (EM_PARISC|__AUDIT_ARCH_64BIT) -- cgit From 03f7e6adfbd02d026817d2b0b21c8420fe58e0b3 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 18 Mar 2019 02:30:06 +0300 Subject: Move EM_UNICORE to uapi/linux/elf-em.h This should never have been defined in the arch tree to begin with, and now uapi/linux/audit.h header is going to use EM_UNICORE in order to define AUDIT_ARCH_UNICORE which is needed to implement syscall_get_arch() which in turn is required to extend the generic ptrace API with PTRACE_GET_SYSCALL_INFO request. Acked-by: Paul Moore Cc: Guan Xuetao Cc: Elvira Khabirova Cc: Eugene Syromyatnikov Cc: Oleg Nesterov Cc: Andy Lutomirski Cc: linux-audit@redhat.com Signed-off-by: Dmitry V. Levin Signed-off-by: Paul Moore --- arch/unicore32/include/asm/elf.h | 3 +-- include/uapi/linux/elf-em.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/unicore32/include/asm/elf.h b/arch/unicore32/include/asm/elf.h index 829042d07722..ae66dc1be49e 100644 --- a/arch/unicore32/include/asm/elf.h +++ b/arch/unicore32/include/asm/elf.h @@ -19,6 +19,7 @@ * ELF register definitions.. */ #include +#include typedef unsigned long elf_greg_t; typedef unsigned long elf_freg_t[3]; @@ -28,8 +29,6 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG]; typedef struct fp_state elf_fpregset_t; -#define EM_UNICORE 110 - #define R_UNICORE_NONE 0 #define R_UNICORE_PC24 1 #define R_UNICORE_ABS32 2 diff --git a/include/uapi/linux/elf-em.h b/include/uapi/linux/elf-em.h index 4b8df722330e..f47e853546fa 100644 --- a/include/uapi/linux/elf-em.h +++ b/include/uapi/linux/elf-em.h @@ -37,6 +37,7 @@ #define EM_ARCOMPACT 93 /* ARCompact processor */ #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ #define EM_BLACKFIN 106 /* ADI Blackfin Processor */ +#define EM_UNICORE 110 /* UniCore-32 */ #define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */ #define EM_TI_C6000 140 /* TI C6X DSPs */ #define EM_HEXAGON 164 /* QUALCOMM Hexagon */ -- cgit From b15fe94acece954feda32706e3ca7cc024999aee Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 18 Mar 2019 02:30:11 +0300 Subject: unicore32: define syscall_get_arch() syscall_get_arch() is required to be implemented on all architectures in addition to already implemented syscall_get_nr(), syscall_get_arguments(), syscall_get_error(), and syscall_get_return_value() functions in order to extend the generic ptrace API with PTRACE_GET_SYSCALL_INFO request. Acked-by: Paul Moore Cc: Elvira Khabirova Cc: Eugene Syromyatnikov Cc: Guan Xuetao Cc: Oleg Nesterov Cc: Andy Lutomirski Cc: linux-audit@redhat.com Signed-off-by: Dmitry V. Levin Signed-off-by: Paul Moore --- arch/unicore32/include/asm/syscall.h | 12 ++++++++++++ include/uapi/linux/audit.h | 1 + 2 files changed, 13 insertions(+) create mode 100644 arch/unicore32/include/asm/syscall.h diff --git a/arch/unicore32/include/asm/syscall.h b/arch/unicore32/include/asm/syscall.h new file mode 100644 index 000000000000..3a6b885476b4 --- /dev/null +++ b/arch/unicore32/include/asm/syscall.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_UNICORE_SYSCALL_H +#define _ASM_UNICORE_SYSCALL_H + +#include + +static inline int syscall_get_arch(void) +{ + return AUDIT_ARCH_UNICORE; +} + +#endif /* _ASM_UNICORE_SYSCALL_H */ diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index bcc0619b046f..3901c51c0b93 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -424,6 +424,7 @@ enum { #define AUDIT_ARCH_TILEGX (EM_TILEGX|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) #define AUDIT_ARCH_TILEGX32 (EM_TILEGX|__AUDIT_ARCH_LE) #define AUDIT_ARCH_TILEPRO (EM_TILEPRO|__AUDIT_ARCH_LE) +#define AUDIT_ARCH_UNICORE (EM_UNICORE|__AUDIT_ARCH_LE) #define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) #define AUDIT_ARCH_XTENSA (EM_XTENSA) -- cgit From 16add411645cff83360086e102daa67b25f1e39a Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 18 Mar 2019 02:30:18 +0300 Subject: syscall_get_arch: add "struct task_struct *" argument This argument is required to extend the generic ptrace API with PTRACE_GET_SYSCALL_INFO request: syscall_get_arch() is going to be called from ptrace_request() along with syscall_get_nr(), syscall_get_arguments(), syscall_get_error(), and syscall_get_return_value() functions with a tracee as their argument. The primary intent is that the triple (audit_arch, syscall_nr, arg1..arg6) should describe what system call is being called and what its arguments are. Reverts: 5e937a9ae913 ("syscall_get_arch: remove useless function arguments") Reverts: 1002d94d3076 ("syscall.h: fix doc text for syscall_get_arch()") Reviewed-by: Andy Lutomirski # for x86 Reviewed-by: Palmer Dabbelt Acked-by: Paul Moore Acked-by: Paul Burton # MIPS parts Acked-by: Michael Ellerman (powerpc) Acked-by: Kees Cook # seccomp parts Acked-by: Mark Salter # for the c6x bit Cc: Elvira Khabirova Cc: Eugene Syromyatnikov Cc: Oleg Nesterov Cc: x86@kernel.org Cc: linux-alpha@vger.kernel.org Cc: linux-snps-arc@lists.infradead.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-c6x-dev@linux-c6x.org Cc: uclinux-h8-devel@lists.sourceforge.jp Cc: linux-hexagon@vger.kernel.org Cc: linux-ia64@vger.kernel.org Cc: linux-m68k@lists.linux-m68k.org Cc: linux-mips@vger.kernel.org Cc: nios2-dev@lists.rocketboards.org Cc: openrisc@lists.librecores.org Cc: linux-parisc@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org Cc: linux-riscv@lists.infradead.org Cc: linux-s390@vger.kernel.org Cc: linux-sh@vger.kernel.org Cc: sparclinux@vger.kernel.org Cc: linux-um@lists.infradead.org Cc: linux-xtensa@linux-xtensa.org Cc: linux-arch@vger.kernel.org Cc: linux-audit@redhat.com Signed-off-by: Dmitry V. Levin Signed-off-by: Paul Moore --- arch/alpha/include/asm/syscall.h | 2 +- arch/arc/include/asm/syscall.h | 2 +- arch/arm/include/asm/syscall.h | 2 +- arch/arm64/include/asm/syscall.h | 4 ++-- arch/c6x/include/asm/syscall.h | 2 +- arch/csky/include/asm/syscall.h | 2 +- arch/h8300/include/asm/syscall.h | 2 +- arch/hexagon/include/asm/syscall.h | 2 +- arch/ia64/include/asm/syscall.h | 2 +- arch/m68k/include/asm/syscall.h | 2 +- arch/microblaze/include/asm/syscall.h | 2 +- arch/mips/include/asm/syscall.h | 6 +++--- arch/mips/kernel/ptrace.c | 2 +- arch/nds32/include/asm/syscall.h | 2 +- arch/nios2/include/asm/syscall.h | 2 +- arch/openrisc/include/asm/syscall.h | 2 +- arch/parisc/include/asm/syscall.h | 4 ++-- arch/powerpc/include/asm/syscall.h | 10 ++++++++-- arch/riscv/include/asm/syscall.h | 2 +- arch/s390/include/asm/syscall.h | 4 ++-- arch/sh/include/asm/syscall_32.h | 2 +- arch/sh/include/asm/syscall_64.h | 2 +- arch/sparc/include/asm/syscall.h | 5 +++-- arch/unicore32/include/asm/syscall.h | 2 +- arch/x86/include/asm/syscall.h | 8 +++++--- arch/x86/um/asm/syscall.h | 2 +- arch/xtensa/include/asm/syscall.h | 2 +- include/asm-generic/syscall.h | 5 +++-- kernel/auditsc.c | 4 ++-- kernel/seccomp.c | 4 ++-- 30 files changed, 52 insertions(+), 42 deletions(-) diff --git a/arch/alpha/include/asm/syscall.h b/arch/alpha/include/asm/syscall.h index d73a6fcb519c..11c688c1d7ec 100644 --- a/arch/alpha/include/asm/syscall.h +++ b/arch/alpha/include/asm/syscall.h @@ -4,7 +4,7 @@ #include -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { return AUDIT_ARCH_ALPHA; } diff --git a/arch/arc/include/asm/syscall.h b/arch/arc/include/asm/syscall.h index c7fc4c0c3bcb..caf2697ef5b7 100644 --- a/arch/arc/include/asm/syscall.h +++ b/arch/arc/include/asm/syscall.h @@ -70,7 +70,7 @@ syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, } static inline int -syscall_get_arch(void) +syscall_get_arch(struct task_struct *task) { return IS_ENABLED(CONFIG_ISA_ARCOMPACT) ? (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) diff --git a/arch/arm/include/asm/syscall.h b/arch/arm/include/asm/syscall.h index 06dea6bce293..3940ceac0bdc 100644 --- a/arch/arm/include/asm/syscall.h +++ b/arch/arm/include/asm/syscall.h @@ -104,7 +104,7 @@ static inline void syscall_set_arguments(struct task_struct *task, memcpy(®s->ARM_r0 + i, args, n * sizeof(args[0])); } -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { /* ARM tasks don't change audit architectures on the fly. */ return AUDIT_ARCH_ARM; diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h index ad8be16a39c9..1870df03f774 100644 --- a/arch/arm64/include/asm/syscall.h +++ b/arch/arm64/include/asm/syscall.h @@ -117,9 +117,9 @@ static inline void syscall_set_arguments(struct task_struct *task, * We don't care about endianness (__AUDIT_ARCH_LE bit) here because * AArch64 has the same system calls both on little- and big- endian. */ -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { - if (is_compat_task()) + if (is_compat_thread(task_thread_info(task))) return AUDIT_ARCH_ARM; return AUDIT_ARCH_AARCH64; diff --git a/arch/c6x/include/asm/syscall.h b/arch/c6x/include/asm/syscall.h index 39dbd1ef994c..595057191c9c 100644 --- a/arch/c6x/include/asm/syscall.h +++ b/arch/c6x/include/asm/syscall.h @@ -121,7 +121,7 @@ static inline void syscall_set_arguments(struct task_struct *task, } } -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { return IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) ? AUDIT_ARCH_C6XBE : AUDIT_ARCH_C6X; diff --git a/arch/csky/include/asm/syscall.h b/arch/csky/include/asm/syscall.h index d637445737b7..150ffb894fa2 100644 --- a/arch/csky/include/asm/syscall.h +++ b/arch/csky/include/asm/syscall.h @@ -70,7 +70,7 @@ syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, } static inline int -syscall_get_arch(void) +syscall_get_arch(struct task_struct *task) { return AUDIT_ARCH_CSKY; } diff --git a/arch/h8300/include/asm/syscall.h b/arch/h8300/include/asm/syscall.h index 5135910616e2..d316c3d40d4e 100644 --- a/arch/h8300/include/asm/syscall.h +++ b/arch/h8300/include/asm/syscall.h @@ -49,7 +49,7 @@ syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, } static inline int -syscall_get_arch(void) +syscall_get_arch(struct task_struct *task) { return AUDIT_ARCH_H8300; } diff --git a/arch/hexagon/include/asm/syscall.h b/arch/hexagon/include/asm/syscall.h index de3917aad3fd..47b0bc3f16be 100644 --- a/arch/hexagon/include/asm/syscall.h +++ b/arch/hexagon/include/asm/syscall.h @@ -46,7 +46,7 @@ static inline void syscall_get_arguments(struct task_struct *task, memcpy(args, &(®s->r00)[i], n * sizeof(args[0])); } -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { return AUDIT_ARCH_HEXAGON; } diff --git a/arch/ia64/include/asm/syscall.h b/arch/ia64/include/asm/syscall.h index 1d0b875fec44..47ab33f5448a 100644 --- a/arch/ia64/include/asm/syscall.h +++ b/arch/ia64/include/asm/syscall.h @@ -81,7 +81,7 @@ static inline void syscall_set_arguments(struct task_struct *task, ia64_syscall_get_set_arguments(task, regs, i, n, args, 1); } -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { return AUDIT_ARCH_IA64; } diff --git a/arch/m68k/include/asm/syscall.h b/arch/m68k/include/asm/syscall.h index d4d7deda8d50..465ac039be09 100644 --- a/arch/m68k/include/asm/syscall.h +++ b/arch/m68k/include/asm/syscall.h @@ -4,7 +4,7 @@ #include -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { return AUDIT_ARCH_M68K; } diff --git a/arch/microblaze/include/asm/syscall.h b/arch/microblaze/include/asm/syscall.h index 220decd605a4..77a86fafa974 100644 --- a/arch/microblaze/include/asm/syscall.h +++ b/arch/microblaze/include/asm/syscall.h @@ -101,7 +101,7 @@ static inline void syscall_set_arguments(struct task_struct *task, asmlinkage unsigned long do_syscall_trace_enter(struct pt_regs *regs); asmlinkage void do_syscall_trace_leave(struct pt_regs *regs); -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { return AUDIT_ARCH_MICROBLAZE; } diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h index 6cf8ffb5367e..6a22c9352ef6 100644 --- a/arch/mips/include/asm/syscall.h +++ b/arch/mips/include/asm/syscall.h @@ -140,14 +140,14 @@ extern const unsigned long sys_call_table[]; extern const unsigned long sys32_call_table[]; extern const unsigned long sysn32_call_table[]; -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { int arch = AUDIT_ARCH_MIPS; #ifdef CONFIG_64BIT - if (!test_thread_flag(TIF_32BIT_REGS)) { + if (!test_tsk_thread_flag(task, TIF_32BIT_REGS)) { arch |= __AUDIT_ARCH_64BIT; /* N32 sets only TIF_32BIT_ADDR */ - if (test_thread_flag(TIF_32BIT_ADDR)) + if (test_tsk_thread_flag(task, TIF_32BIT_ADDR)) arch |= __AUDIT_ARCH_CONVENTION_MIPS64_N32; } #endif diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 0057c910bc2f..2ead6ff919b7 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -1418,7 +1418,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) unsigned long args[6]; sd.nr = syscall; - sd.arch = syscall_get_arch(); + sd.arch = syscall_get_arch(current); syscall_get_arguments(current, regs, 0, 6, args); for (i = 0; i < 6; i++) sd.args[i] = args[i]; diff --git a/arch/nds32/include/asm/syscall.h b/arch/nds32/include/asm/syscall.h index cc56a3962f8b..7501e376a6b1 100644 --- a/arch/nds32/include/asm/syscall.h +++ b/arch/nds32/include/asm/syscall.h @@ -188,7 +188,7 @@ void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, } static inline int -syscall_get_arch(void) +syscall_get_arch(struct task_struct *task) { return IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) ? AUDIT_ARCH_NDS32BE : AUDIT_ARCH_NDS32; diff --git a/arch/nios2/include/asm/syscall.h b/arch/nios2/include/asm/syscall.h index cf35e210fc4d..f0f6ae208e78 100644 --- a/arch/nios2/include/asm/syscall.h +++ b/arch/nios2/include/asm/syscall.h @@ -136,7 +136,7 @@ static inline void syscall_set_arguments(struct task_struct *task, } } -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { return AUDIT_ARCH_NIOS2; } diff --git a/arch/openrisc/include/asm/syscall.h b/arch/openrisc/include/asm/syscall.h index 2db9f1cf0694..46b10c674bd2 100644 --- a/arch/openrisc/include/asm/syscall.h +++ b/arch/openrisc/include/asm/syscall.h @@ -72,7 +72,7 @@ syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, memcpy(®s->gpr[3 + i], args, n * sizeof(args[0])); } -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { return AUDIT_ARCH_OPENRISC; } diff --git a/arch/parisc/include/asm/syscall.h b/arch/parisc/include/asm/syscall.h index 8bff1a58c97f..c04ffc6ac928 100644 --- a/arch/parisc/include/asm/syscall.h +++ b/arch/parisc/include/asm/syscall.h @@ -62,11 +62,11 @@ static inline void syscall_rollback(struct task_struct *task, /* do nothing */ } -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { int arch = AUDIT_ARCH_PARISC; #ifdef CONFIG_64BIT - if (!is_compat_task()) + if (!__is_compat_task(task)) arch = AUDIT_ARCH_PARISC64; #endif return arch; diff --git a/arch/powerpc/include/asm/syscall.h b/arch/powerpc/include/asm/syscall.h index 1a0e7a8b1c81..efb50429c9f4 100644 --- a/arch/powerpc/include/asm/syscall.h +++ b/arch/powerpc/include/asm/syscall.h @@ -99,9 +99,15 @@ static inline void syscall_set_arguments(struct task_struct *task, regs->orig_gpr3 = args[0]; } -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { - int arch = is_32bit_task() ? AUDIT_ARCH_PPC : AUDIT_ARCH_PPC64; + int arch; + + if (IS_ENABLED(CONFIG_PPC64) && !test_tsk_thread_flag(task, TIF_32BIT)) + arch = AUDIT_ARCH_PPC64; + else + arch = AUDIT_ARCH_PPC; + #ifdef __LITTLE_ENDIAN__ arch |= __AUDIT_ARCH_LE; #endif diff --git a/arch/riscv/include/asm/syscall.h b/arch/riscv/include/asm/syscall.h index bba3da6ef157..ca120a36a037 100644 --- a/arch/riscv/include/asm/syscall.h +++ b/arch/riscv/include/asm/syscall.h @@ -100,7 +100,7 @@ static inline void syscall_set_arguments(struct task_struct *task, memcpy(®s->a1 + i * sizeof(regs->a1), args, n * sizeof(regs->a0)); } -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { #ifdef CONFIG_64BIT return AUDIT_ARCH_RISCV64; diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h index 96f9a9151fde..5a40ea8b90ea 100644 --- a/arch/s390/include/asm/syscall.h +++ b/arch/s390/include/asm/syscall.h @@ -92,10 +92,10 @@ static inline void syscall_set_arguments(struct task_struct *task, regs->orig_gpr2 = args[0]; } -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { #ifdef CONFIG_COMPAT - if (test_tsk_thread_flag(current, TIF_31BIT)) + if (test_tsk_thread_flag(task, TIF_31BIT)) return AUDIT_ARCH_S390; #endif return AUDIT_ARCH_S390X; diff --git a/arch/sh/include/asm/syscall_32.h b/arch/sh/include/asm/syscall_32.h index 6e118799831c..08de429eccd4 100644 --- a/arch/sh/include/asm/syscall_32.h +++ b/arch/sh/include/asm/syscall_32.h @@ -95,7 +95,7 @@ static inline void syscall_set_arguments(struct task_struct *task, } } -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { int arch = AUDIT_ARCH_SH; diff --git a/arch/sh/include/asm/syscall_64.h b/arch/sh/include/asm/syscall_64.h index 43882580c7f9..9b62a2404531 100644 --- a/arch/sh/include/asm/syscall_64.h +++ b/arch/sh/include/asm/syscall_64.h @@ -63,7 +63,7 @@ static inline void syscall_set_arguments(struct task_struct *task, memcpy(®s->regs[2 + i], args, n * sizeof(args[0])); } -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { int arch = AUDIT_ARCH_SH; diff --git a/arch/sparc/include/asm/syscall.h b/arch/sparc/include/asm/syscall.h index 053989e3f6a6..9ffb367c17fd 100644 --- a/arch/sparc/include/asm/syscall.h +++ b/arch/sparc/include/asm/syscall.h @@ -128,10 +128,11 @@ static inline void syscall_set_arguments(struct task_struct *task, regs->u_regs[UREG_I0 + i + j] = args[j]; } -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { #if defined(CONFIG_SPARC64) && defined(CONFIG_COMPAT) - return in_compat_syscall() ? AUDIT_ARCH_SPARC : AUDIT_ARCH_SPARC64; + return test_tsk_thread_flag(task, TIF_32BIT) + ? AUDIT_ARCH_SPARC : AUDIT_ARCH_SPARC64; #elif defined(CONFIG_SPARC64) return AUDIT_ARCH_SPARC64; #else diff --git a/arch/unicore32/include/asm/syscall.h b/arch/unicore32/include/asm/syscall.h index 3a6b885476b4..607961797fff 100644 --- a/arch/unicore32/include/asm/syscall.h +++ b/arch/unicore32/include/asm/syscall.h @@ -4,7 +4,7 @@ #include -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { return AUDIT_ARCH_UNICORE; } diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h index d653139857af..435f3f09279c 100644 --- a/arch/x86/include/asm/syscall.h +++ b/arch/x86/include/asm/syscall.h @@ -107,7 +107,7 @@ static inline void syscall_set_arguments(struct task_struct *task, memcpy(®s->bx + i, args, n * sizeof(args[0])); } -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { return AUDIT_ARCH_I386; } @@ -236,10 +236,12 @@ static inline void syscall_set_arguments(struct task_struct *task, } } -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { /* x32 tasks should be considered AUDIT_ARCH_X86_64. */ - return in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; + return (IS_ENABLED(CONFIG_IA32_EMULATION) && + task->thread_info.status & TS_COMPAT) + ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; } #endif /* CONFIG_X86_32 */ diff --git a/arch/x86/um/asm/syscall.h b/arch/x86/um/asm/syscall.h index ef898af102d1..56a2f0913e3c 100644 --- a/arch/x86/um/asm/syscall.h +++ b/arch/x86/um/asm/syscall.h @@ -9,7 +9,7 @@ typedef asmlinkage long (*sys_call_ptr_t)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { #ifdef CONFIG_X86_32 return AUDIT_ARCH_I386; diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h index a168bf81c7f4..0681ca656809 100644 --- a/arch/xtensa/include/asm/syscall.h +++ b/arch/xtensa/include/asm/syscall.h @@ -14,7 +14,7 @@ #include #include -static inline int syscall_get_arch(void) +static inline int syscall_get_arch(struct task_struct *task) { return AUDIT_ARCH_XTENSA; } diff --git a/include/asm-generic/syscall.h b/include/asm-generic/syscall.h index 0c938a4354f6..e0d060b43321 100644 --- a/include/asm-generic/syscall.h +++ b/include/asm-generic/syscall.h @@ -144,14 +144,15 @@ void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, /** * syscall_get_arch - return the AUDIT_ARCH for the current system call + * @task: task of interest, must be blocked * * Returns the AUDIT_ARCH_* based on the system call convention in use. * - * It's only valid to call this when current is stopped on entry to a system + * It's only valid to call this when @task is stopped on entry to a system * call, due to %TIF_SYSCALL_TRACE, %TIF_SYSCALL_AUDIT, or %TIF_SECCOMP. * * Architectures which permit CONFIG_HAVE_ARCH_SECCOMP_FILTER must * provide an implementation of this. */ -int syscall_get_arch(void); +int syscall_get_arch(struct task_struct *task); #endif /* _ASM_SYSCALL_H */ diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 17b0007fafc2..98a98e6dca05 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1636,7 +1636,7 @@ void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2, return; } - context->arch = syscall_get_arch(); + context->arch = syscall_get_arch(current); context->major = major; context->argv[0] = a1; context->argv[1] = a2; @@ -2590,7 +2590,7 @@ void audit_seccomp(unsigned long syscall, long signr, int code) return; audit_log_task(ab); audit_log_format(ab, " sig=%ld arch=%x syscall=%ld compat=%d ip=0x%lx code=0x%x", - signr, syscall_get_arch(), syscall, + signr, syscall_get_arch(current), syscall, in_compat_syscall(), KSTK_EIP(current), code); audit_log_end(ab); } diff --git a/kernel/seccomp.c b/kernel/seccomp.c index 54a0347ca812..36f36ab00f48 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -148,7 +148,7 @@ static void populate_seccomp_data(struct seccomp_data *sd) unsigned long args[6]; sd->nr = syscall_get_nr(task, regs); - sd->arch = syscall_get_arch(); + sd->arch = syscall_get_arch(task); syscall_get_arguments(task, regs, 0, 6, args); sd->args[0] = args[0]; sd->args[1] = args[1]; @@ -591,7 +591,7 @@ static void seccomp_init_siginfo(kernel_siginfo_t *info, int syscall, int reason info->si_code = SYS_SECCOMP; info->si_call_addr = (void __user *)KSTK_EIP(current); info->si_errno = reason; - info->si_arch = syscall_get_arch(); + info->si_arch = syscall_get_arch(current); info->si_syscall = syscall; } -- cgit From a1aa08a01f734d48a8f76b12aca9f4e4adae7649 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Tue, 26 Mar 2019 14:49:20 -0400 Subject: audit: link integrity evm_write_xattrs record to syscall event In commit fa516b66a1bf ("EVM: Allow runtime modification of the set of verified xattrs"), the call to audit_log_start() is missing a context to link it to an audit event. Since this event is in user context, add the process' syscall context to the record. In addition, the orphaned keyword "locked" appears in the record. Normalize this by changing it to logging the locking string "." as any other user input in the "xattr=" field. Please see the github issue https://github.com/linux-audit/audit-kernel/issues/109 Signed-off-by: Richard Guy Briggs Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/integrity/evm/evm_secfs.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/security/integrity/evm/evm_secfs.c b/security/integrity/evm/evm_secfs.c index 015aea8fdf1e..3f7cbb238923 100644 --- a/security/integrity/evm/evm_secfs.c +++ b/security/integrity/evm/evm_secfs.c @@ -192,7 +192,8 @@ static ssize_t evm_write_xattrs(struct file *file, const char __user *buf, if (count > XATTR_NAME_MAX) return -E2BIG; - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_EVM_XATTR); + ab = audit_log_start(audit_context(), GFP_KERNEL, + AUDIT_INTEGRITY_EVM_XATTR); if (!ab) return -ENOMEM; @@ -214,6 +215,9 @@ static ssize_t evm_write_xattrs(struct file *file, const char __user *buf, if (len && xattr->name[len-1] == '\n') xattr->name[len-1] = '\0'; + audit_log_format(ab, "xattr="); + audit_log_untrustedstring(ab, xattr->name); + if (strcmp(xattr->name, ".") == 0) { evm_xattrs_locked = 1; newattrs.ia_mode = S_IFREG | 0440; @@ -222,15 +226,11 @@ static ssize_t evm_write_xattrs(struct file *file, const char __user *buf, inode_lock(inode); err = simple_setattr(evm_xattrs, &newattrs); inode_unlock(inode); - audit_log_format(ab, "locked"); if (!err) err = count; goto out; } - audit_log_format(ab, "xattr="); - audit_log_untrustedstring(ab, xattr->name); - if (strncmp(xattr->name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) != 0) { err = -EINVAL; -- cgit From 699c1868a743f530081f429058616a2dd5d8a4b2 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Mon, 8 Apr 2019 12:50:57 -0400 Subject: audit: purge unnecessary list_empty calls The original conditions that led to the use of list_empty() to optimize list_for_each_entry_rcu() in auditfilter.c and auditsc.c code have been removed without removing the list_empty() call, but this code example has been copied several times. Remove the unnecessary list_empty() calls. Please see upstream github issue https://github.com/linux-audit/audit-kernel/issues/112 Signed-off-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/auditfilter.c | 2 -- kernel/auditsc.c | 64 ++++++++++++++++++++++------------------------------ 2 files changed, 27 insertions(+), 39 deletions(-) diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 63f8b3f26fab..2c3c2f349b23 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -1315,8 +1315,6 @@ int audit_filter(int msgtype, unsigned int listtype) int ret = 1; /* Audit by default */ rcu_read_lock(); - if (list_empty(&audit_filter_list[listtype])) - goto unlock_and_return; list_for_each_entry_rcu(e, &audit_filter_list[listtype], list) { int i, result = 0; diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 98a98e6dca05..51a2ceb3a1ca 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -771,15 +771,13 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk, return AUDIT_DISABLED; rcu_read_lock(); - if (!list_empty(list)) { - list_for_each_entry_rcu(e, list, list) { - if (audit_in_mask(&e->rule, ctx->major) && - audit_filter_rules(tsk, &e->rule, ctx, NULL, - &state, false)) { - rcu_read_unlock(); - ctx->current_state = state; - return state; - } + list_for_each_entry_rcu(e, list, list) { + if (audit_in_mask(&e->rule, ctx->major) && + audit_filter_rules(tsk, &e->rule, ctx, NULL, + &state, false)) { + rcu_read_unlock(); + ctx->current_state = state; + return state; } } rcu_read_unlock(); @@ -798,9 +796,6 @@ static int audit_filter_inode_name(struct task_struct *tsk, struct audit_entry *e; enum audit_state state; - if (list_empty(list)) - return 0; - list_for_each_entry_rcu(e, list, list) { if (audit_in_mask(&e->rule, ctx->major) && audit_filter_rules(tsk, &e->rule, ctx, n, &state, false)) { @@ -808,7 +803,6 @@ static int audit_filter_inode_name(struct task_struct *tsk, return 1; } } - return 0; } @@ -1945,18 +1939,16 @@ void __audit_inode(struct filename *name, const struct dentry *dentry, return; rcu_read_lock(); - if (!list_empty(list)) { - list_for_each_entry_rcu(e, list, list) { - for (i = 0; i < e->rule.field_count; i++) { - struct audit_field *f = &e->rule.fields[i]; - - if (f->type == AUDIT_FSTYPE - && audit_comparator(inode->i_sb->s_magic, - f->op, f->val) - && e->rule.action == AUDIT_NEVER) { - rcu_read_unlock(); - return; - } + list_for_each_entry_rcu(e, list, list) { + for (i = 0; i < e->rule.field_count; i++) { + struct audit_field *f = &e->rule.fields[i]; + + if (f->type == AUDIT_FSTYPE + && audit_comparator(inode->i_sb->s_magic, + f->op, f->val) + && e->rule.action == AUDIT_NEVER) { + rcu_read_unlock(); + return; } } } @@ -2065,18 +2057,16 @@ void __audit_inode_child(struct inode *parent, return; rcu_read_lock(); - if (!list_empty(list)) { - list_for_each_entry_rcu(e, list, list) { - for (i = 0; i < e->rule.field_count; i++) { - struct audit_field *f = &e->rule.fields[i]; - - if (f->type == AUDIT_FSTYPE - && audit_comparator(parent->i_sb->s_magic, - f->op, f->val) - && e->rule.action == AUDIT_NEVER) { - rcu_read_unlock(); - return; - } + list_for_each_entry_rcu(e, list, list) { + for (i = 0; i < e->rule.field_count; i++) { + struct audit_field *f = &e->rule.fields[i]; + + if (f->type == AUDIT_FSTYPE + && audit_comparator(parent->i_sb->s_magic, + f->op, f->val) + && e->rule.action == AUDIT_NEVER) { + rcu_read_unlock(); + return; } } } -- cgit From 2d87a0674bd60d855e4008e2d84f5b23d7cb9b7d Mon Sep 17 00:00:00 2001 From: Ondrej Mosnacek Date: Wed, 10 Apr 2019 11:14:19 +0200 Subject: timekeeping: Audit clock adjustments Emit an audit record whenever the system clock is changed (i.e. shifted by a non-zero offset) by a syscall from userspace. The syscalls than can (at the time of writing) trigger such record are: - settimeofday(2), stime(2), clock_settime(2) -- via do_settimeofday64() - adjtimex(2), clock_adjtime(2) -- via do_adjtimex() The new records have type AUDIT_TIME_INJOFFSET and contain the following fields: - sec -- the 'seconds' part of the offset - nsec -- the 'nanoseconds' part of the offset Example record (time was shifted backwards by ~15.875 seconds): type=TIME_INJOFFSET msg=audit(1530616049.652:13): sec=-16 nsec=124887145 The records of this type will be associated with the corresponding syscall records. Signed-off-by: Ondrej Mosnacek Reviewed-by: Richard Guy Briggs Reviewed-by: Thomas Gleixner [PM: fixed a line width problem in __audit_tk_injoffset()] Signed-off-by: Paul Moore --- include/linux/audit.h | 14 ++++++++++++++ include/uapi/linux/audit.h | 1 + kernel/auditsc.c | 7 +++++++ kernel/time/timekeeping.c | 6 ++++++ 4 files changed, 28 insertions(+) diff --git a/include/linux/audit.h b/include/linux/audit.h index 1e69d9fe16da..2c62c0468888 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -365,6 +365,7 @@ extern void __audit_log_capset(const struct cred *new, const struct cred *old); extern void __audit_mmap_fd(int fd, int flags); extern void __audit_log_kern_module(char *name); extern void __audit_fanotify(unsigned int response); +extern void __audit_tk_injoffset(struct timespec64 offset); static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) { @@ -467,6 +468,16 @@ static inline void audit_fanotify(unsigned int response) __audit_fanotify(response); } +static inline void audit_tk_injoffset(struct timespec64 offset) +{ + /* ignore no-op events */ + if (offset.tv_sec == 0 && offset.tv_nsec == 0) + return; + + if (!audit_dummy_context()) + __audit_tk_injoffset(offset); +} + extern int audit_n_rules; extern int audit_signals; #else /* CONFIG_AUDITSYSCALL */ @@ -580,6 +591,9 @@ static inline void audit_log_kern_module(char *name) static inline void audit_fanotify(unsigned int response) { } +static inline void audit_tk_injoffset(struct timespec64 offset) +{ } + static inline void audit_ptrace(struct task_struct *t) { } #define audit_n_rules 0 diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 3901c51c0b93..ab58d67baf4d 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -114,6 +114,7 @@ #define AUDIT_REPLACE 1329 /* Replace auditd if this packet unanswerd */ #define AUDIT_KERN_MODULE 1330 /* Kernel Module events */ #define AUDIT_FANOTIFY 1331 /* Fanotify access decision */ +#define AUDIT_TIME_INJOFFSET 1332 /* Timekeeping offset injected */ #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 51a2ceb3a1ca..3843495d0083 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -2512,6 +2512,13 @@ void __audit_fanotify(unsigned int response) AUDIT_FANOTIFY, "resp=%u", response); } +void __audit_tk_injoffset(struct timespec64 offset) +{ + audit_log(audit_context(), GFP_KERNEL, AUDIT_TIME_INJOFFSET, + "sec=%lli nsec=%li", + (long long)offset.tv_sec, offset.tv_nsec); +} + static void audit_log_task(struct audit_buffer *ab) { kuid_t auid, uid; diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index f986e1918d12..3d24be4cd607 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "tick-internal.h" #include "ntp_internal.h" @@ -1250,6 +1251,9 @@ out: /* signal hrtimers about time change */ clock_was_set(); + if (!ret) + audit_tk_injoffset(ts_delta); + return ret; } EXPORT_SYMBOL(do_settimeofday64); @@ -2322,6 +2326,8 @@ int do_adjtimex(struct __kernel_timex *txc) ret = timekeeping_inject_offset(&delta); if (ret) return ret; + + audit_tk_injoffset(delta); } ktime_get_real_ts64(&ts); -- cgit From 7e8eda734d30de81d06a949c9bf9853c445ede4e Mon Sep 17 00:00:00 2001 From: Ondrej Mosnacek Date: Wed, 10 Apr 2019 11:14:20 +0200 Subject: ntp: Audit NTP parameters adjustment Emit an audit record every time selected NTP parameters are modified from userspace (via adjtimex(2) or clock_adjtime(2)). These parameters may be used to indirectly change system clock, and thus their modifications should be audited. Such events will now generate records of type AUDIT_TIME_ADJNTPVAL containing the following fields: - op -- which value was adjusted: - offset -- corresponding to the time_offset variable - freq -- corresponding to the time_freq variable - status -- corresponding to the time_status variable - adjust -- corresponding to the time_adjust variable - tick -- corresponding to the tick_usec variable - tai -- corresponding to the timekeeping's TAI offset - old -- the old value - new -- the new value Example records: type=TIME_ADJNTPVAL msg=audit(1530616044.507:7): op=status old=64 new=8256 type=TIME_ADJNTPVAL msg=audit(1530616044.511:11): op=freq old=0 new=49180377088000 The records of this type will be associated with the corresponding syscall records. An overview of parameter changes that can be done via do_adjtimex() (based on information from Miroslav Lichvar) and whether they are audited: __timekeeping_set_tai_offset() -- sets the offset from the International Atomic Time (AUDITED) NTP variables: time_offset -- can adjust the clock by up to 0.5 seconds per call and also speed it up or slow down by up to about 0.05% (43 seconds per day) (AUDITED) time_freq -- can speed up or slow down by up to about 0.05% (AUDITED) time_status -- can insert/delete leap seconds and it also enables/ disables synchronization of the hardware real-time clock (AUDITED) time_maxerror, time_esterror -- change error estimates used to inform userspace applications (NOT AUDITED) time_constant -- controls the speed of the clock adjustments that are made when time_offset is set (NOT AUDITED) time_adjust -- can temporarily speed up or slow down the clock by up to 0.05% (AUDITED) tick_usec -- a more extreme version of time_freq; can speed up or slow down the clock by up to 10% (AUDITED) Signed-off-by: Ondrej Mosnacek Reviewed-by: Richard Guy Briggs Reviewed-by: Thomas Gleixner Signed-off-by: Paul Moore --- include/linux/audit.h | 61 ++++++++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/audit.h | 1 + kernel/auditsc.c | 22 +++++++++++++++++ kernel/time/ntp.c | 22 ++++++++++++++--- kernel/time/ntp_internal.h | 4 ++- kernel/time/timekeeping.c | 7 +++++- 6 files changed, 112 insertions(+), 5 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 2c62c0468888..43a23e28ba23 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -86,6 +86,29 @@ struct audit_field { u32 op; }; +enum audit_ntp_type { + AUDIT_NTP_OFFSET, + AUDIT_NTP_FREQ, + AUDIT_NTP_STATUS, + AUDIT_NTP_TAI, + AUDIT_NTP_TICK, + AUDIT_NTP_ADJUST, + + AUDIT_NTP_NVALS /* count */ +}; + +#ifdef CONFIG_AUDITSYSCALL +struct audit_ntp_val { + long long oldval, newval; +}; + +struct audit_ntp_data { + struct audit_ntp_val vals[AUDIT_NTP_NVALS]; +}; +#else +struct audit_ntp_data {}; +#endif + extern int is_audit_feature_set(int which); extern int __init audit_register_class(int class, unsigned *list); @@ -366,6 +389,7 @@ extern void __audit_mmap_fd(int fd, int flags); extern void __audit_log_kern_module(char *name); extern void __audit_fanotify(unsigned int response); extern void __audit_tk_injoffset(struct timespec64 offset); +extern void __audit_ntp_log(const struct audit_ntp_data *ad); static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) { @@ -478,6 +502,29 @@ static inline void audit_tk_injoffset(struct timespec64 offset) __audit_tk_injoffset(offset); } +static inline void audit_ntp_init(struct audit_ntp_data *ad) +{ + memset(ad, 0, sizeof(*ad)); +} + +static inline void audit_ntp_set_old(struct audit_ntp_data *ad, + enum audit_ntp_type type, long long val) +{ + ad->vals[type].oldval = val; +} + +static inline void audit_ntp_set_new(struct audit_ntp_data *ad, + enum audit_ntp_type type, long long val) +{ + ad->vals[type].newval = val; +} + +static inline void audit_ntp_log(const struct audit_ntp_data *ad) +{ + if (!audit_dummy_context()) + __audit_ntp_log(ad); +} + extern int audit_n_rules; extern int audit_signals; #else /* CONFIG_AUDITSYSCALL */ @@ -594,6 +641,20 @@ static inline void audit_fanotify(unsigned int response) static inline void audit_tk_injoffset(struct timespec64 offset) { } +static inline void audit_ntp_init(struct audit_ntp_data *ad) +{ } + +static inline void audit_ntp_set_old(struct audit_ntp_data *ad, + enum audit_ntp_type type, long long val) +{ } + +static inline void audit_ntp_set_new(struct audit_ntp_data *ad, + enum audit_ntp_type type, long long val) +{ } + +static inline void audit_ntp_log(const struct audit_ntp_data *ad) +{ } + static inline void audit_ptrace(struct task_struct *t) { } #define audit_n_rules 0 diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index ab58d67baf4d..a1280af20336 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -115,6 +115,7 @@ #define AUDIT_KERN_MODULE 1330 /* Kernel Module events */ #define AUDIT_FANOTIFY 1331 /* Fanotify access decision */ #define AUDIT_TIME_INJOFFSET 1332 /* Timekeeping offset injected */ +#define AUDIT_TIME_ADJNTPVAL 1333 /* NTP value adjustment */ #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 3843495d0083..5371b59bde36 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -2519,6 +2519,28 @@ void __audit_tk_injoffset(struct timespec64 offset) (long long)offset.tv_sec, offset.tv_nsec); } +static void audit_log_ntp_val(const struct audit_ntp_data *ad, + const char *op, enum audit_ntp_type type) +{ + const struct audit_ntp_val *val = &ad->vals[type]; + + if (val->newval == val->oldval) + return; + + audit_log(audit_context(), GFP_KERNEL, AUDIT_TIME_ADJNTPVAL, + "op=%s old=%lli new=%lli", op, val->oldval, val->newval); +} + +void __audit_ntp_log(const struct audit_ntp_data *ad) +{ + audit_log_ntp_val(ad, "offset", AUDIT_NTP_OFFSET); + audit_log_ntp_val(ad, "freq", AUDIT_NTP_FREQ); + audit_log_ntp_val(ad, "status", AUDIT_NTP_STATUS); + audit_log_ntp_val(ad, "tai", AUDIT_NTP_TAI); + audit_log_ntp_val(ad, "tick", AUDIT_NTP_TICK); + audit_log_ntp_val(ad, "adjust", AUDIT_NTP_ADJUST); +} + static void audit_log_task(struct audit_buffer *ab) { kuid_t auid, uid; diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 92a90014a925..ac5555e25733 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "ntp_internal.h" #include "timekeeping_internal.h" @@ -709,7 +710,7 @@ static inline void process_adjtimex_modes(const struct __kernel_timex *txc, * kernel time-keeping variables. used by xntpd. */ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts, - s32 *time_tai) + s32 *time_tai, struct audit_ntp_data *ad) { int result; @@ -720,14 +721,29 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts, /* adjtime() is independent from ntp_adjtime() */ time_adjust = txc->offset; ntp_update_frequency(); + + audit_ntp_set_old(ad, AUDIT_NTP_ADJUST, save_adjust); + audit_ntp_set_new(ad, AUDIT_NTP_ADJUST, time_adjust); } txc->offset = save_adjust; } else { - /* If there are input parameters, then process them: */ - if (txc->modes) + if (txc->modes) { + audit_ntp_set_old(ad, AUDIT_NTP_OFFSET, time_offset); + audit_ntp_set_old(ad, AUDIT_NTP_FREQ, time_freq); + audit_ntp_set_old(ad, AUDIT_NTP_STATUS, time_status); + audit_ntp_set_old(ad, AUDIT_NTP_TAI, *time_tai); + audit_ntp_set_old(ad, AUDIT_NTP_TICK, tick_usec); + process_adjtimex_modes(txc, time_tai); + audit_ntp_set_new(ad, AUDIT_NTP_OFFSET, time_offset); + audit_ntp_set_new(ad, AUDIT_NTP_FREQ, time_freq); + audit_ntp_set_new(ad, AUDIT_NTP_STATUS, time_status); + audit_ntp_set_new(ad, AUDIT_NTP_TAI, *time_tai); + audit_ntp_set_new(ad, AUDIT_NTP_TICK, tick_usec); + } + txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ, NTP_SCALE_SHIFT); if (!(time_status & STA_NANO)) diff --git a/kernel/time/ntp_internal.h b/kernel/time/ntp_internal.h index 40e6122e634e..908ecaa65fc3 100644 --- a/kernel/time/ntp_internal.h +++ b/kernel/time/ntp_internal.h @@ -8,6 +8,8 @@ extern void ntp_clear(void); extern u64 ntp_tick_length(void); extern ktime_t ntp_get_next_leap(void); extern int second_overflow(time64_t secs); -extern int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts, s32 *time_tai); +extern int __do_adjtimex(struct __kernel_timex *txc, + const struct timespec64 *ts, + s32 *time_tai, struct audit_ntp_data *ad); extern void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts); #endif /* _LINUX_NTP_INTERNAL_H */ diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 3d24be4cd607..f366f2fdf1b0 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -2307,6 +2307,7 @@ static int timekeeping_validate_timex(const struct __kernel_timex *txc) int do_adjtimex(struct __kernel_timex *txc) { struct timekeeper *tk = &tk_core.timekeeper; + struct audit_ntp_data ad; unsigned long flags; struct timespec64 ts; s32 orig_tai, tai; @@ -2330,13 +2331,15 @@ int do_adjtimex(struct __kernel_timex *txc) audit_tk_injoffset(delta); } + audit_ntp_init(&ad); + ktime_get_real_ts64(&ts); raw_spin_lock_irqsave(&timekeeper_lock, flags); write_seqcount_begin(&tk_core.seq); orig_tai = tai = tk->tai_offset; - ret = __do_adjtimex(txc, &ts, &tai); + ret = __do_adjtimex(txc, &ts, &tai, &ad); if (tai != orig_tai) { __timekeeping_set_tai_offset(tk, tai); @@ -2347,6 +2350,8 @@ int do_adjtimex(struct __kernel_timex *txc) write_seqcount_end(&tk_core.seq); raw_spin_unlock_irqrestore(&timekeeper_lock, flags); + audit_ntp_log(&ad); + /* Update the multiplier immediately if frequency was set directly */ if (txc->modes & (ADJ_FREQUENCY | ADJ_TICK)) timekeeping_advance(TK_ADV_FREQ); -- cgit From 70c4cf17e445264453bc5323db3e50aa0ac9e81f Mon Sep 17 00:00:00 2001 From: Wenwen Wang Date: Fri, 19 Apr 2019 20:49:29 -0500 Subject: audit: fix a memory leak bug In audit_rule_change(), audit_data_to_entry() is firstly invoked to translate the payload data to the kernel's rule representation. In audit_data_to_entry(), depending on the audit field type, an audit tree may be created in audit_make_tree(), which eventually invokes kmalloc() to allocate the tree. Since this tree is a temporary tree, it will be then freed in the following execution, e.g., audit_add_rule() if the message type is AUDIT_ADD_RULE or audit_del_rule() if the message type is AUDIT_DEL_RULE. However, if the message type is neither AUDIT_ADD_RULE nor AUDIT_DEL_RULE, i.e., the default case of the switch statement, this temporary tree is not freed. To fix this issue, only allocate the tree when the type is AUDIT_ADD_RULE or AUDIT_DEL_RULE. Signed-off-by: Wenwen Wang Reviewed-by: Richard Guy Briggs Signed-off-by: Paul Moore --- kernel/auditfilter.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 2c3c2f349b23..1bc6410413e6 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -1114,22 +1114,24 @@ int audit_rule_change(int type, int seq, void *data, size_t datasz) int err = 0; struct audit_entry *entry; - entry = audit_data_to_entry(data, datasz); - if (IS_ERR(entry)) - return PTR_ERR(entry); - switch (type) { case AUDIT_ADD_RULE: + entry = audit_data_to_entry(data, datasz); + if (IS_ERR(entry)) + return PTR_ERR(entry); err = audit_add_rule(entry); audit_log_rule_change("add_rule", &entry->rule, !err); break; case AUDIT_DEL_RULE: + entry = audit_data_to_entry(data, datasz); + if (IS_ERR(entry)) + return PTR_ERR(entry); err = audit_del_rule(entry); audit_log_rule_change("remove_rule", &entry->rule, !err); break; default: - err = -EINVAL; WARN_ON(1); + return -EINVAL; } if (err || type == AUDIT_DEL_RULE) { -- cgit