On Fri, Mar 01, 2019 at 04:23:05PM +0100, Peter Zijlstra wrote:

> But yes, I'll try some annotation, see what that looks like.

OK; that took a lot of time.. and a number of objtool bugs fixed but I
think I have something that I don't hate -- although it is not as solid
as I'd like it to be.


unmodified:

0000 0000000000000150 <__asan_load1>:
0000  150:      48 b8 ff ff ff ff ff    movabs $0xffff7fffffffffff,%rax
0007  157:      7f ff ff
000a  15a:      48 8b 0c 24             mov    (%rsp),%rcx
000e  15e:      48 39 c7                cmp    %rax,%rdi
0011  161:      76 23                   jbe    186 <__asan_load1+0x36>
0013  163:      48 b8 00 00 00 00 00    movabs $0xdffffc0000000000,%rax
001a  16a:      fc ff df
001d  16d:      48 89 fa                mov    %rdi,%rdx
0020  170:      48 c1 ea 03             shr    $0x3,%rdx
0024  174:      0f b6 04 02             movzbl (%rdx,%rax,1),%eax
0028  178:      84 c0                   test   %al,%al
002a  17a:      75 01                   jne    17d <__asan_load1+0x2d>
002c  17c:      c3                      retq
002d  17d:      89 fa                   mov    %edi,%edx
002f  17f:      83 e2 07                and    $0x7,%edx
0032  182:      38 d0                   cmp    %dl,%al
0034  184:      7f f6                   jg     17c <__asan_load1+0x2c>
0036  186:      31 d2                   xor    %edx,%edx
0038  188:      be 01 00 00 00          mov    $0x1,%esi
003d  18d:      e9 00 00 00 00          jmpq   192 <__asan_load1+0x42>
003e                    18e: R_X86_64_PLT32     kasan_report-0x4

exception:

0000 0000000000000150 <__asan_load1>:
0000  150:      48 b8 ff ff ff ff ff    movabs $0xffff7fffffffffff,%rax
0007  157:      7f ff ff
000a  15a:      48 8b 0c 24             mov    (%rsp),%rcx
000e  15e:      48 39 c7                cmp    %rax,%rdi
0011  161:      76 23                   jbe    186 <__asan_load1+0x36>
0013  163:      48 b8 00 00 00 00 00    movabs $0xdffffc0000000000,%rax
001a  16a:      fc ff df
001d  16d:      48 89 fa                mov    %rdi,%rdx
0020  170:      48 c1 ea 03             shr    $0x3,%rdx
0024  174:      0f b6 04 02             movzbl (%rdx,%rax,1),%eax
0028  178:      84 c0                   test   %al,%al
002a  17a:      75 01                   jne    17d <__asan_load1+0x2d>
002c  17c:      c3                      retq
002d  17d:      89 fa                   mov    %edi,%edx
002f  17f:      83 e2 07                and    $0x7,%edx
0032  182:      38 d0                   cmp    %dl,%al
0034  184:      7f f6                   jg     17c <__asan_load1+0x2c>
0036  186:      65 48 8b 04 25 00 00    mov    %gs:0x0,%rax
003d  18d:      00 00
003b                    18b: R_X86_64_32S       current_task
003f  18f:      8b 80 68 08 00 00       mov    0x868(%rax),%eax
0045  195:      85 c0                   test   %eax,%eax
0047  197:      75 e3                   jne    17c <__asan_load1+0x2c>
0049  199:      be 01 00 00 00          mov    $0x1,%esi
004e  19e:      31 d2                   xor    %edx,%edx
0050  1a0:      0f 0b                   ud2
0052  1a2:      c3                      retq

annotated:

0000 0000000000000150 <__asan_load1>:
0000  150:      48 b8 ff ff ff ff ff    movabs $0xffff7fffffffffff,%rax
0007  157:      7f ff ff
000a  15a:      53                      push   %rbx
000b  15b:      48 8b 4c 24 08          mov    0x8(%rsp),%rcx
0010  160:      48 39 c7                cmp    %rax,%rdi
0013  163:      76 24                   jbe    189 <__asan_load1+0x39>
0015  165:      48 b8 00 00 00 00 00    movabs $0xdffffc0000000000,%rax
001c  16c:      fc ff df
001f  16f:      48 89 fa                mov    %rdi,%rdx
0022  172:      48 c1 ea 03             shr    $0x3,%rdx
0026  176:      0f b6 04 02             movzbl (%rdx,%rax,1),%eax
002a  17a:      84 c0                   test   %al,%al
002c  17c:      75 02                   jne    180 <__asan_load1+0x30>
002e  17e:      5b                      pop    %rbx
002f  17f:      c3                      retq
0030  180:      89 fa                   mov    %edi,%edx
0032  182:      83 e2 07                and    $0x7,%edx
0035  185:      38 d0                   cmp    %dl,%al
0037  187:      7f f5                   jg     17e <__asan_load1+0x2e>
0039  189:      9c                      pushfq
003a  18a:      5b                      pop    %rbx
003b  18b:      90                      nop
003c  18c:      90                      nop
003d  18d:      90                      nop
003e  18e:      31 d2                   xor    %edx,%edx
0040  190:      be 01 00 00 00          mov    $0x1,%esi
0045  195:      e8 00 00 00 00          callq  19a <__asan_load1+0x4a>
0046                    196: R_X86_64_PLT32     __kasan_report-0x4
004a  19a:      53                      push   %rbx
004b  19b:      9d                      popfq
004c  19c:      5b                      pop    %rbx
004d  19d:      c3                      retq


---
--- a/arch/x86/include/asm/kasan.h
+++ b/arch/x86/include/asm/kasan.h
@@ -28,6 +28,23 @@
 #ifdef CONFIG_KASAN
 void __init kasan_early_init(void);
 void __init kasan_init(void);
+
+#include <asm/smap.h>
+
+extern void __kasan_report(unsigned long addr, size_t size, bool is_write, 
unsigned long ip);
+
+static __always_inline
+void kasan_report(unsigned long addr, size_t size, bool is_write, unsigned 
long ip)
+{
+       unsigned long flags;
+
+       flags = smap_save();
+       __kasan_report(addr, size, is_write, ip);
+       smap_restore(flags);
+
+}
+#define kasan_report kasan_report
+
 #else
 static inline void kasan_early_init(void) { }
 static inline void kasan_init(void) { }
--- a/arch/x86/include/asm/smap.h
+++ b/arch/x86/include/asm/smap.h
@@ -46,6 +46,8 @@
 
 #ifdef CONFIG_X86_SMAP
 
+#include <asm/irqflags.h>
+
 static __always_inline void clac(void)
 {
        /* Note: a barrier is implicit in alternative() */
@@ -58,6 +60,18 @@ static __always_inline void stac(void)
        alternative("", __stringify(__ASM_STAC), X86_FEATURE_SMAP);
 }
 
+static __always_inline unsigned long smap_save(void)
+{
+       unsigned long flags = arch_local_save_flags();
+       clac();
+       return flags;
+}
+
+static __always_inline void smap_restore(unsigned long flags)
+{
+       arch_local_irq_restore(flags);
+}
+
 /* These macros can be used in asm() statements */
 #define ASM_CLAC \
        ALTERNATIVE("", __stringify(__ASM_CLAC), X86_FEATURE_SMAP)
@@ -69,6 +83,9 @@ static __always_inline void stac(void)
 static inline void clac(void) { }
 static inline void stac(void) { }
 
+static inline unsigned long smap_save(void) { return 0; }
+static inline void smap_restore(unsigned long flags) { }
+
 #define ASM_CLAC
 #define ASM_STAC
 
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -83,6 +83,8 @@ size_t kasan_metadata_size(struct kmem_c
 bool kasan_save_enable_multi_shot(void);
 void kasan_restore_multi_shot(bool enabled);
 
+void __kasan_report(unsigned long addr, size_t size, bool is_write, unsigned 
long ip);
+
 #else /* CONFIG_KASAN */
 
 static inline void kasan_unpoison_shadow(const void *address, size_t size) {}
@@ -153,8 +155,14 @@ static inline void kasan_remove_zero_sha
 static inline void kasan_unpoison_slab(const void *ptr) { }
 static inline size_t kasan_metadata_size(struct kmem_cache *cache) { return 0; 
}
 
+static inline void __kasan_report(unsigned long addr, size_t size, bool 
is_write, unsigned long ip) { }
+
 #endif /* CONFIG_KASAN */
 
+#ifndef kasan_report
+#define kasan_report(addr, size, is_write, ip) __kasan_report(addr, size, 
is_write, ip)
+#endif
+
 #ifdef CONFIG_KASAN_GENERIC
 
 #define KASAN_SHADOW_INIT 0
@@ -177,9 +185,6 @@ void kasan_init_tags(void);
 
 void *kasan_reset_tag(const void *addr);
 
-void kasan_report(unsigned long addr, size_t size,
-               bool is_write, unsigned long ip);
-
 #else /* CONFIG_KASAN_SW_TAGS */
 
 static inline void kasan_init_tags(void) { }
--- a/mm/kasan/generic_report.c
+++ b/mm/kasan/generic_report.c
@@ -118,14 +118,14 @@ const char *get_bug_type(struct kasan_ac
 #define DEFINE_ASAN_REPORT_LOAD(size)                     \
 void __asan_report_load##size##_noabort(unsigned long addr) \
 {                                                         \
-       kasan_report(addr, size, false, _RET_IP_);        \
+       __kasan_report(addr, size, false, _RET_IP_);      \
 }                                                         \
 EXPORT_SYMBOL(__asan_report_load##size##_noabort)
 
 #define DEFINE_ASAN_REPORT_STORE(size)                     \
 void __asan_report_store##size##_noabort(unsigned long addr) \
 {                                                          \
-       kasan_report(addr, size, true, _RET_IP_);          \
+       __kasan_report(addr, size, true, _RET_IP_);        \
 }                                                          \
 EXPORT_SYMBOL(__asan_report_store##size##_noabort)
 
@@ -142,12 +142,12 @@ DEFINE_ASAN_REPORT_STORE(16);
 
 void __asan_report_load_n_noabort(unsigned long addr, size_t size)
 {
-       kasan_report(addr, size, false, _RET_IP_);
+       __kasan_report(addr, size, false, _RET_IP_);
 }
 EXPORT_SYMBOL(__asan_report_load_n_noabort);
 
 void __asan_report_store_n_noabort(unsigned long addr, size_t size)
 {
-       kasan_report(addr, size, true, _RET_IP_);
+       __kasan_report(addr, size, true, _RET_IP_);
 }
 EXPORT_SYMBOL(__asan_report_store_n_noabort);
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -130,8 +130,6 @@ void check_memory_region(unsigned long a
 void *find_first_bad_addr(void *addr, size_t size);
 const char *get_bug_type(struct kasan_access_info *info);
 
-void kasan_report(unsigned long addr, size_t size,
-               bool is_write, unsigned long ip);
 void kasan_report_invalid_free(void *object, unsigned long ip);
 
 #if defined(CONFIG_KASAN_GENERIC) && \
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -281,7 +281,7 @@ void kasan_report_invalid_free(void *obj
        end_report(&flags);
 }
 
-void kasan_report(unsigned long addr, size_t size,
+void __kasan_report(unsigned long addr, size_t size,
                bool is_write, unsigned long ip)
 {
        struct kasan_access_info info;
--- a/tools/objtool/arch.h
+++ b/tools/objtool/arch.h
@@ -43,6 +43,7 @@ enum op_dest_type {
        OP_DEST_REG_INDIRECT,
        OP_DEST_MEM,
        OP_DEST_PUSH,
+       OP_DEST_PUSHF,
        OP_DEST_LEAVE,
 };
 
@@ -57,6 +58,7 @@ enum op_src_type {
        OP_SRC_REG_INDIRECT,
        OP_SRC_CONST,
        OP_SRC_POP,
+       OP_SRC_POPF,
        OP_SRC_ADD,
        OP_SRC_AND,
 };
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -357,13 +357,13 @@ int arch_decode_instruction(struct elf *
                /* pushf */
                *type = INSN_STACK;
                op->src.type = OP_SRC_CONST;
-               op->dest.type = OP_DEST_PUSH;
+               op->dest.type = OP_DEST_PUSHF;
                break;
 
        case 0x9d:
                /* popf */
                *type = INSN_STACK;
-               op->src.type = OP_SRC_POP;
+               op->src.type = OP_SRC_POPF;
                op->dest.type = OP_DEST_MEM;
                break;
 
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1359,11 +1359,11 @@ static int update_insn_state_regs(struct
                return 0;
 
        /* push */
-       if (op->dest.type == OP_DEST_PUSH)
+       if (op->dest.type == OP_DEST_PUSH || op->dest.type == OP_DEST_PUSHF)
                cfa->offset += 8;
 
        /* pop */
-       if (op->src.type == OP_SRC_POP)
+       if (op->src.type == OP_SRC_POP || op->src.type == OP_SRC_POPF)
                cfa->offset -= 8;
 
        /* add immediate to sp */
@@ -1620,6 +1620,7 @@ static int update_insn_state(struct inst
                        break;
 
                case OP_SRC_POP:
+               case OP_SRC_POPF:
                        if (!state->drap && op->dest.type == OP_DEST_REG &&
                            op->dest.reg == cfa->base) {
 
@@ -1684,6 +1685,7 @@ static int update_insn_state(struct inst
                break;
 
        case OP_DEST_PUSH:
+       case OP_DEST_PUSHF:
                state->stack_size += 8;
                if (cfa->base == CFI_SP)
                        cfa->offset += 8;
@@ -1774,7 +1776,7 @@ static int update_insn_state(struct inst
                break;
 
        case OP_DEST_MEM:
-               if (op->src.type != OP_SRC_POP) {
+               if (op->src.type != OP_SRC_POP && op->src.type != OP_SRC_POPF) {
                        WARN_FUNC("unknown stack-related memory operation",
                                  insn->sec, insn->offset);
                        return -1;
@@ -2071,6 +2073,16 @@ static int validate_branch(struct objtoo
                        if (update_insn_state(insn, &state))
                                return 1;
 
+                       if (insn->stack_op.dest.type == OP_DEST_PUSHF) {
+                               if (state.uaccess)
+                                       state.uaccess_stack++;
+                       }
+
+                       if (insn->stack_op.src.type == OP_SRC_POPF) {
+                               if (state.uaccess_stack && 
!--state.uaccess_stack)
+                                       state.uaccess = func_uaccess_safe(func);
+                       }
+
                        break;
 
                case INSN_STAC:
@@ -2088,7 +2100,7 @@ static int validate_branch(struct objtoo
                                return 1;
                        }
 
-                       if (func_uaccess_safe(func)) {
+                       if (func_uaccess_safe(func) && !state.uaccess_stack) {
                                WARN_FUNC("UACCESS-safe disables UACCESS", sec, 
insn->offset);
                                return 1;
                        }
--- a/tools/objtool/check.h
+++ b/tools/objtool/check.h
@@ -32,6 +32,7 @@ struct insn_state {
        unsigned char type;
        bool bp_scratch;
        bool drap, end, uaccess;
+       int uaccess_stack;
        int drap_reg, drap_offset;
        struct cfi_reg vals[CFI_NUM_REGS];
 };

Reply via email to