From a269d96978af37906c0f65bf1989d999d9751dfc Mon Sep 17 00:00:00 2001 From: Ken Sato Date: Thu, 9 Aug 2018 16:02:46 +0900 Subject: [PATCH] coredump: Exclude special areas Fujitsu: POSTK_DEBUG_TEMP_FIX_38 Refs: #1005 Change-Id: I8934d2aecf06a09469afe131347e42b48b6f67f6 --- arch/x86_64/kernel/gencore.c | 20 ++++-- executer/kernel/mcctrl/syscall.c | 2 - test/issues/1005/C1005.sh | 112 +++++++++++++++++++++++++++++ test/issues/1005/Makefile | 17 +++++ test/issues/1005/README | 31 ++++++++ test/issues/1005/devmap_and_segv.c | 54 ++++++++++++++ test/issues/1005/result.log | 77 ++++++++++++++++++++ test/issues/1005/test_chk.h | 23 ++++++ 8 files changed, 327 insertions(+), 9 deletions(-) create mode 100644 test/issues/1005/C1005.sh create mode 100644 test/issues/1005/Makefile create mode 100644 test/issues/1005/README create mode 100644 test/issues/1005/devmap_and_segv.c create mode 100644 test/issues/1005/result.log create mode 100644 test/issues/1005/test_chk.h diff --git a/arch/x86_64/kernel/gencore.c b/arch/x86_64/kernel/gencore.c index 100f857b..d27e2fd9 100644 --- a/arch/x86_64/kernel/gencore.c +++ b/arch/x86_64/kernel/gencore.c @@ -18,6 +18,12 @@ #define DDEBUG_DEFAULT DDEBUG_PRINT #endif +/* Exclude reserved (mckernel's internal use), device file, + * hole created by mprotect + */ +#define GENCORE_RANGE_IS_INACCESSIBLE(range) \ + ((range->flag & (VR_RESERVED | VR_MEMTYPE_UC | VR_DONTDUMP))) + /* * Generate a core file image, which consists of many chunks. * Returns an allocated table, an etnry of which is a pair of the address @@ -307,12 +313,10 @@ int gencore(struct thread *thread, void *regs, dkprintf("start:%lx end:%lx flag:%lx objoff:%lx\n", range->start, range->end, range->flag, range->objoff); - /* We omit reserved areas because they are only for - mckernel's internal use. */ - if (range->flag & VR_RESERVED) - continue; - if (range->flag & VR_DONTDUMP) + + if (GENCORE_RANGE_IS_INACCESSIBLE(range)) { continue; + } /* We need a chunk for each page for a demand paging area. This can be optimized for spacial complexity but we would lose simplicity instead. */ @@ -401,8 +405,9 @@ int gencore(struct thread *thread, void *regs, unsigned long flag = range->flag; unsigned long size = range->end - range->start; - if (range->flag & VR_RESERVED) + if (GENCORE_RANGE_IS_INACCESSIBLE(range)) { continue; + } ph[i].p_type = PT_LOAD; ph[i].p_flags = ((flag & VR_PROT_READ) ? PF_R : 0) @@ -444,8 +449,9 @@ int gencore(struct thread *thread, void *regs, unsigned long phys; - if (range->flag & VR_RESERVED) + if (GENCORE_RANGE_IS_INACCESSIBLE(range)) { continue; + } if (range->flag & VR_DEMAND_PAGING) { /* Just an ad hoc kluge. */ unsigned long p, start, phys; diff --git a/executer/kernel/mcctrl/syscall.c b/executer/kernel/mcctrl/syscall.c index f193bbd8..0244ca0f 100644 --- a/executer/kernel/mcctrl/syscall.c +++ b/executer/kernel/mcctrl/syscall.c @@ -2255,11 +2255,9 @@ static int writecore(ihk_os_t os, unsigned long rcoretable, int chunks) { phys = ihk_device_map_memory(dev, rphys, size); dprintk("physical %lx, ", phys); pt = ihk_device_map_virtual(dev, phys, size, NULL, 0); -#ifdef POSTK_DEBUG_TEMP_FIX_38 if (pt == NULL) { pt = phys_to_virt(phys); } -#endif /*POSTK_DEBUG_TEMP_FIX_38*/ dprintk("virtual %p\n", pt); if (pt != NULL) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) diff --git a/test/issues/1005/C1005.sh b/test/issues/1005/C1005.sh new file mode 100644 index 00000000..58a70399 --- /dev/null +++ b/test/issues/1005/C1005.sh @@ -0,0 +1,112 @@ +#!/bin/sh + +USELTP=0 +USEOSTEST=0 + +. ../../common.sh + +sudo /bin/sh ${OSTESTDIR}/util/insmod_test_drv.sh + +ulimit_c_bk=`ulimit -Sc` +# set ulimit -c unlimited to dump core +ulimit -Sc unlimited + +$BINDIR/mcexec ./devmap_and_segv | tee ./maps.txt + +# restore ulimit -c +ulimit -c ${ulimit_c_bk} + +sudo /bin/sh ${OSTESTDIR}/util/rmmod_test_drv.sh + +tid=001 +echo "*** CT_$tid start *******************************" +echo "** check file type by readelf" +readelf -h ./core | grep -e "Type:.*CORE" +if [ $? == 0 ]; then + echo "*** CT_$tid PASSED ******************************" +else + echo "*** CT_$tid FAILED ******************************" +fi +echo "" + +# check by gdb +VDSO_ADDR=`grep "\[vdso\]" ./maps.txt | cut -f 1 -d "-"` +DEVMAP_ADDR=`grep "mmap_dev2$" ./maps.txt | cut -f 1 -d "-"` +GDB_OUT="./gdb_out.txt" + +expect -c " + set timeout 3 + log_file -noappend ${GDB_OUT} + + spawn gdb --quiet -c ./core ./devmap_and_segv + # check vdso addr + expect \"(gdb)\" + send \"x 0x${VDSO_ADDR}\n\" + + #check devmap addr + expect \"(gdb)\" + send \"x 0x${DEVMAP_ADDR}\n\" + + #check backtrace + expect \"(gdb)\" + send \"bt\n\" + + #check info registers + expect \"(gdb)\" + send \"info registers\n\" + + # quit gdb_test + expect \"(gdb)\" + send \"quit\n\" + + log_file + interact +" > /dev/null + +tid=002 +echo "*** CT_$tid start *******************************" +echo "** check that core contains vdso data" +grep -A 1 "(gdb) x 0x${VDSO_ADDR}" ${GDB_OUT} +grep -A 1 "(gdb) x 0x${VDSO_ADDR}" ${GDB_OUT} | tail -1 | grep -q "0x${VDSO_ADDR}:\s*0x[0-9a-f]\+" +if [ $? == 0 ]; then + echo "*** CT_$tid PASSED ******************************" +else + echo "*** CT_$tid FAILED ******************************" +fi +echo "" + +tid=003 +echo "*** CT_$tid start *******************************" +echo "** check that core dose NOT contain devmap data" +grep -A 1 "(gdb) x 0x${DEVMAP_ADDR}" ${GDB_OUT} +grep -A 1 "(gdb) x 0x${DEVMAP_ADDR}" ${GDB_OUT} | tail -1 | grep -q "0x${VDSO_ADDR}:\s*0x[0-9a-f]\+" +if [ $? == 1 ]; then + echo "*** CT_$tid PASSED ******************************" +else + echo "*** CT_$tid FAILED ******************************" +fi +echo "" + +tid=004 +echo "*** CT_$tid start *******************************" +echo "** check that core can be backtraced" +grep -A 1 "(gdb) bt" ${GDB_OUT} +grep -A 1 "(gdb) bt" ${GDB_OUT} | tail -1 | grep -q "^#0.*in main" +if [ $? == 0 ]; then + echo "*** CT_$tid PASSED ******************************" +else + echo "*** CT_$tid FAILED ******************************" +fi +echo "" + +tid=005 +echo "*** CT_$tid start *******************************" +echo "** check that core can be got info registers" +grep -A 30 "(gdb) info registers" ${GDB_OUT} +grep -A 30 "(gdb) info registers" ${GDB_OUT} | grep -q "^rip\s*0x.*main" +if [ $? == 0 ]; then + echo "*** CT_$tid PASSED ******************************" +else + echo "*** CT_$tid FAILED ******************************" +fi +echo "" diff --git a/test/issues/1005/Makefile b/test/issues/1005/Makefile new file mode 100644 index 00000000..d8e55287 --- /dev/null +++ b/test/issues/1005/Makefile @@ -0,0 +1,17 @@ +CC = gcc +TARGET=devmap_and_segv + +CPPFLAGS = +LDFLAGS = + +all: $(TARGET) + +devmap_and_segv: devmap_and_segv.c + $(CC) -g -o $@ $^ $(LDFLAGS) + +test: all + @sh ./C1005.sh + +clean: + rm -f $(TARGET) *.o ./core ./core.* ./maps.txt ./gdb_out.txt + diff --git a/test/issues/1005/README b/test/issues/1005/README new file mode 100644 index 00000000..975ec48e --- /dev/null +++ b/test/issues/1005/README @@ -0,0 +1,31 @@ +【Issue#1005 動作確認】 +□ テスト内容 +1. Issueで報告された症状が修正されたことの確認 +CT_001: McKernelのcoreファイルの形式を確認 + readelf -h で、TypeがCOREであることを確認する + +CT_002: vdso領域の内容がcoreファイルに含まれていることの確認 + gdbのxコマンドでvdso領域のアドレスを指定し、 + 内容が表示されることを確認する + +CT_003: device-fileの内容がcoreファイルに含まれていないことの確認 + gdbのxコマンドでdevice-fileをマップした領域のアドレスを指定し、 + 内容を取得できないことを確認する + +CT_004: backtraceの情報がcoreファイルに含まれていることを確認 + gdbのbtコマンドでbacktraceの情報が表示されることを確認する + +CT_005: registersの情報がcoreファイルに含まれていることを確認 + gdbのinfo registersコマンドでregistersの情報が表示されることを確認する + +□ 実行手順 +$ make test + +McKernelのインストール先や、OSTEST, LTPの配置場所は、 +$HOME/.mck_test_config を参照している +.mck_test_config は、McKernelをビルドした際に生成されるmck_test_config.sample ファイルを +$HOMEにコピーし、適宜編集する + +□ 実行結果 +result.log 参照 +すべての項目をPASSしていることを確認 diff --git a/test/issues/1005/devmap_and_segv.c b/test/issues/1005/devmap_and_segv.c new file mode 100644 index 00000000..13606661 --- /dev/null +++ b/test/issues/1005/devmap_and_segv.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "./test_chk.h" + +#define TEST_NAME "devmap_and_segv" + +#define PROCFILE_LEN 128 +#define MAP_LEN 4096 +#define DEV_NAME "/dev/test_mck/mmap_dev2" + +int main(int argc, char *argv[]) +{ + int dev_fd = 0; + pid_t pid = getpid(); + void *dev_map = NULL; + char *segv_addr = NULL; + char cmd[128]; + + printf("*** %s start *******************************\n", TEST_NAME); + + /* open device file */ + dev_fd = open(DEV_NAME, O_RDONLY); + OKNG(dev_fd < 0, "open test_device_file:%s", DEV_NAME); + + /* mmap device file */ + dev_map = mmap(NULL, MAP_LEN, PROT_READ, MAP_SHARED, dev_fd, 0); + OKNG(dev_map == MAP_FAILED, "mmap device file"); + printf(" map dev_file to %p\n", dev_map); + + /* print maps */ + sprintf(cmd, "cat /proc/%d/maps", pid); + system(cmd); + + /* occur segv */ + *segv_addr = '0'; + + printf("*** Why reached here? ***\n"); + return 0; + +fn_fail: + + if (dev_fd > 0) { + close(dev_fd); + } + + return -1; +} diff --git a/test/issues/1005/result.log b/test/issues/1005/result.log new file mode 100644 index 00000000..12e9f053 --- /dev/null +++ b/test/issues/1005/result.log @@ -0,0 +1,77 @@ +insmod /home/satoken/ostest/util/../bin/test_mck.ko +create charcter device /dev/test_mck/mmap_dev(244:0) +create charcter device /dev/test_mck/mmap_dev2(244:1) +000000400000-000000401000 r-xs 0 0:0 0 +000000600000-000000601000 r--s 0 0:0 0 +000000601000-000000602000 rw-s 0 0:0 0 +2aaaaa9f8000-2aaaaaa00000 rw-s 0 0:0 0 +2aaaaaa00000-2aaaaaa21000 r-xs 0 0:0 0 +2aaaaac21000-2aaaaac22000 r--s 0 0:0 0 +2aaaaac22000-2aaaaac24000 rw-s 0 0:0 0 +2aaaaac24000-2aaaaac26000 r-xs 0 0:0 0 [vdso] +2aaaaac26000-2aaaaac27000 rw-p 0 0:0 0 +2aaaaac4d000-2aaaaac4e000 rw-p 0 0:0 0 +2aaaaac4e000-2aaaaae06000 r-xp 0 0:0 0 /usr/lib64/libc-2.17.so +2aaaaae06000-2aaaab006000 ---p 0 0:0 0 /usr/lib64/libc-2.17.so +2aaaab006000-2aaaab00a000 r--p 0 0:0 0 /usr/lib64/libc-2.17.so +2aaaab00a000-2aaaab00c000 rw-p 0 0:0 0 /usr/lib64/libc-2.17.so +2aaaab00c000-2aaaab011000 rw-p 0 0:0 0 +2aaaab011000-2aaaab013000 rw-p 0 0:0 0 +2aaaab013000-2aaaab014000 rw-p 0 0:0 0 +2aaaab014000-2aaaab015000 r--s 0 0:0 0 /dev/test_mck/mmap_dev2 +547fff800000-548000000000 rw-s 0 0:0 0 [stack] +Terminate by signal 11 +remove /dev/test_mck +rmmod /home/satoken/ostest/util/../bin/test_mck.ko +*** CT_001 start ******************************* +** check file type by readelf + Type: CORE (Core file) +*** CT_001 PASSED ****************************** + +*** CT_002 start ******************************* +** check that core contains vdso data +(gdb) x 0x2aaaaac24000 +0x2aaaaac24000: 0x464c457f +*** CT_002 PASSED ****************************** + +*** CT_003 start ******************************* +** check that core dose NOT contain devmap data +(gdb) x 0x2aaaab014000 +0x2aaaab014000: Cannot access memory at address 0x2aaaab014000 +*** CT_003 PASSED ****************************** + +*** CT_004 start ******************************* +** check that core can be backtraced +(gdb) bt +#0 0x0000000000400ad0 in main (argc=1, argv=0x547ffffffd08) at devmap_and_segv.c:42 +*** CT_004 PASSED ****************************** + +*** CT_005 start ******************************* +** check that core can be got info registers +(gdb) info registers +rax 0x0 0 +rbx 0x0 0 +rcx 0x2aaaaac834a0 46912498054304 +rdx 0x0 0 +rsi 0x547ffffffa30 92908732545584 +rdi 0x2 2 +rbp 0x547ffffffc20 0x547ffffffc20 +rsp 0x547ffffffb70 0x547ffffffb70 +r8 0x0 0 +r9 0x547ffffff930 92908732545328 +r10 0x8 8 +r11 0x246 582 +r12 0xffff8001007d0dc0 -140733185192512 +r13 0xffff800100770000 -140733185589248 +r14 0xb98 2968 +r15 0xffff80010078fa9c -140733185459556 +rip 0x400ad0 0x400ad0 +eflags 0x10206 [ PF IF RF ] +cs 0x33 51 +ss 0x3b 59 +ds 0x0 0 +es 0x0 0 +fs 0x0 0 +gs 0x0 0 +(gdb) +*** CT_005 PASSED ****************************** diff --git a/test/issues/1005/test_chk.h b/test/issues/1005/test_chk.h new file mode 100644 index 00000000..4cef42e8 --- /dev/null +++ b/test/issues/1005/test_chk.h @@ -0,0 +1,23 @@ +#ifndef HEADER_TEST_CHK_H +#define HEADER_TEST_CHK_H + +#define CHKANDJUMP(cond, ...) do {\ + if (cond) {\ + fprintf(stderr, " [NG] ");\ + fprintf(stderr, __VA_ARGS__);\ + fprintf(stderr, " failed\n");\ + goto fn_fail;\ + } \ + } while (0) + +#define OKNG(cond, ...) do {\ + if (cond) {\ + CHKANDJUMP(cond, __VA_ARGS__);\ + } else {\ + fprintf(stdout, " [OK] ");\ + fprintf(stdout, __VA_ARGS__);\ + fprintf(stdout, "\n");\ + } \ + } while (0) + +#endif