Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

16312
2027
233849


[리눅스커널] 시스템 콜: _TIF_SYSCALL_WORK 매크로의 정체 11. 시스템 콜

_TIF_SYSCALL_WORK 매크로의 정체는 다음 코드와 같다.

https://elixir.bootlin.com/linux/v4.19.30/source/arch/arm/include/asm/thread_info.h 
#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
   _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP)

_TIF_SYSCALL_WORK 매크로는 4개의 매크로를 'OR 비트'를 연산한 결과로 치환된다.

_TIF_SYSCALL_TRACE~_TIF_SECCOMP 매크로의 정체를 확인해볼까?

https://elixir.bootlin.com/linux/v4.19.30/source/arch/arm/include/asm/thread_info.h 
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
#define _TIF_SECCOMP (1 << TIF_SECCOMP)

각각 매크로는 TIF_SYSCALL_TRACE부터 TIF_SECCOMP 매크로를 왼쪽 비트 시프트를 연산한 결괏값이다.

이어서 각 매크로의 선언부를 보자.

https://elixir.bootlin.com/linux/v4.19.30/source/arch/arm/include/asm/thread_info.h 
#define TIF_SYSCALL_TRACE 4 /* syscall trace active */
#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */
#define TIF_SYSCALL_TRACEPOINT 6 /* syscall tracepoint instrumentation */
#define TIF_SECCOMP 7 /* seccomp syscall filtering active */

위에 정의된 매크로의 정수값을 참고하면, 다음 매크로는 주석과 같이 해석할 수 있다.

#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) // (1 << 4) = 0x10
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) // (1 << 5) = 0x20
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) // (1 << 6) = 0x40
#define _TIF_SECCOMP (1 << TIF_SECCOMP) // (1 << 7) = 0x80

위 결괏값을 통해 _TIF_SYSCALL_WORK 매크로는 다음과 같이 계산할 수 있다.

#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
   _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP)

_TIF_SYSCALL_WORK = 0x10 | 0x20 | 0x40 | 0x80 = 0xF0

_TIF_SYSCALL_WORK 매크로의 정체는 16진수로 0xF0 이고 2진수로는 1111_0000‬ 이다.

이번에는 ret_fast_syscall 레이블의 어셈블리 코드에서 _TIF_SYSCALL_WORK 매크로가 어떻게 동작하는지 확인해보자.

아래는 ret_fast_syscall 레이블의 코드이다.

https://github.com/raspberrypi/linux/blob/rpi-4.19.y/arch/arm/kernel/entry-common.S
01 ret_fast_syscall:
02 __ret_fast_syscall:
03 UNWIND(.fnstart )
04 UNWIND(.cantunwind )
...
05 tst r1, #_TIF_SYSCALL_WORK
06 bne __sys_trace_return_nosave
07 slow_work_pending:
08 mov r0, sp @ 'regs'
09 mov r2, why @ 'syscall'

아래는 TRACE32로 본 어셈블리 명령어 포멧의 코드이다.

______addr/line|code____|label_____________|mnemonic________________|comment
01 NSR:80101010|1B002C8F                    blne    0x8010C254       ; addr_limit_check_failed
02 NSR:80101014|E5991000                    ldr     r1,[r9]
03 NSR:80101018|E31100FF                    tst     r1,#0xFF         ; r1,#255
04 NSR:8010101C|0A000010                    beq     0x80101064       ; no_work_pending
05 NSR:80101020|E31100F0                    tst     r1,#0xF0         ; r1,#240
06 NSR:80101024|1A00005F                    bne     0x801011A8       ; __sys_trace_return_nosave
07 NSR:80101028|E1A0000D slow_work_pending: cpy     r0,r13
08 NSR:8010102C|E1A02008                    cpy     r2,r8
09 NSR:80101030|EB002C27                    bl      0x8010C0D4       ; do_work_pending

5번째 줄을 보면 'tst     r1,#0xF0' 명령어가 보인다. _TIF_SYSCALL_WORK 매크로의 정체는 계산식과 같이 0xF0인 것이다.

다음 시간에는 tst 명령어의 동작 원리를 살펴보자.

______addr/line|code____|label_____________|mnemonic________________|comment
01 NSR:80101010|1B002C8F                    blne    0x8010C254       ; addr_limit_check_failed
02 NSR:80101014|E5991000                    ldr     r1,[r9]
03 NSR:80101018|E31100FF                    tst     r1,#0xFF         ; r1,#255
04 NSR:8010101C|0A000010                    beq     0x80101064       ; no_work_pending
05 NSR:80101020|E31100F0____________________tst_____r1,#0xF0_________;_r1,#240
06 NSR:80101024|1A00005F                    bne     0x801011A8       ; __sys_trace_return_nosave
07 NSR:80101028|E1A0000D slow_work_pending: cpy     r0,r13
08 NSR:8010102C|E1A02008                    cpy     r2,r8
09 NSR:80101030|EB002C27                    bl      0x8010C0D4       ; do_work_pending

덧글

댓글 입력 영역