oops-memcpy

hi3536平台發生oops (memcpy造成)


更新記錄

item note
20160109 第一版
20160116 SDK040

目錄


結論

目前使用Hi3536 Hi3536_SDK_V1.0.5.0版本
遇到系系使用相關pipe功能將會產生oops
因此去除SDK050的内核漏洞修复

SDK050新增下例造成問題

Hi3536 V100R001C0xSPC050 序號:2(内核漏洞修复)
此修正使用了 copy_to_iter_bvec等(iov_iter.c)

為了修正:
CVE-2015-2686是在net/socket.c文件中,影響linux內核3.19.3之前版本。
由於sendto和recvfrom系統調用沒有驗證數據範圍,本地權限用戶,可以利用iov_iter接口的copy_from_iter方法來進行提權。
來源: https://read01.com/7PGEML.html

產生下例的oops問題

  • copy_to_iter_bvec

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    CPU: 0 PID: 1364 Comm: grep Not tainted 3.10.0_hi3536 #1
    task: ce941800 ti: cde58000 task.ti: cde58000
    PC is at kmap_atomic+0x20/0x12c
    LR is at copy_to_iter_bvec+0x4c/0x12c
    pc : [<c002061c>] lr : [<c00a5ff8>] psr: 80000013
    sp : cde59df8 ip : 00000000 fp : 00000001
    r10: 0000045a r9 : cde59e8c r8 : cde59ed0
    r7 : 00000000 r6 : cdd41000 r5 : cde58038 r4 : b6f1ae4c
    r3 : cde58000 r2 : 00000002 r1 : 0000045a r0 : b6f1ae4c
    Flags: Nzcv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
    Control: 10c5387d Table: 4ee6006a DAC: 00000015
  • at _memcpy

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Internal error: Oops: 805 [#1] SMP ARM
    Modules linked in:
    CPU: 3 PID: 2878 Comm: awk Not tainted 3.10.0_hi3536 #1
    task: ce08a000 ti: ce7f2000 task.ti: ce7f2000
    PC is at _memcpy+0xf0/0x330
    LR is at 0x6f
    pc : [<c02cc770>] lr : [<0000006f>] psr: 20000013
    sp : ce7f3dec ip : 00000003 fp : 00000001
    r10: 00000030 r9 : ce7f3e8c r8 : ce7f3ed0
    r7 : 00000000 r6 : cdc0b000 r5 : 00000030 r4 : 0000004d
    r3 : 00000020 r2 : 0000002c r1 : cdc0b003 r0 : 6220b001
    Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
    Cont

目前修正方式

去除050版的内核漏洞修复
[hi3536 sdk050 kernel patch]


比較目前開發Hi3536及HI3535平台

item hi3535 hi3536
uclib/glibc gcc 4.4.1 4.8.3
kernel Linux version 3.4.35_hi3535 Linux version 3.10.0_hi3536
uclibc libuClibc-0.9.32.1.so libuClibc-0.9.33.2.so
busybox busybox-1.16.1 busybox-1.20.2
  • hi3535
    uclibc : arm-hisiv100-linux-uclibcgnueabi
    glibc : arm-hisiv200-linux-gnueabi

  • hi3536
    uclibc : arm-hisiv300-linux-uclibcgnueabi
    glilbc : arm-hisiv100-linux-uclibcgnueabi

toolchain

  • arm-hisiv300-linux-uclibcgnueabi
    gcc version 4.8.3 20131202 (prerelease) (Hisilicon_v300)

    1
    --enable-threads --disable-libmudflap --disable-libssp --disable-libstdcxx-pch --with-arch=armv5te --with-gnu-as --with-gnu-ld --enable-languages=c,c++ --enable-shared --enable-lto --enable-symvers=gnu --enable-__cxa_atexit --enable-nls --enable-clocale=gnu --enable-extra-hisi-multilibs
  • arm-hisiv100-linux-uclibcgnueabi
    gcc version 4.4.1 (Hisilicon_v100(gcc4.4-290+uclibc_0.9.32.1+eabi+linuxpthread))

    1
    --enable-threads --disable-libmudflap --disable-libssp --disable-libstdcxx-pch --with-arch=armv5te --with-gnu-as --with-gnu-ld --enable-languages=c,c++ --enable-shared --enable-lto --enable-symvers=gnu --enable-__cxa_atexit --disable-nls --enable-extra-hisi-multilibs
  • arm-hisiv400-linux-gnueabi-gcc
    gcc version 4.8.3 20131202 (prerelease) (Hisilicon_v400)

    1
    --enable-threads --disable-libmudflap --disable-libssp --disable-libstdcxx-pch --with-arch=armv5te --with-gnu-as --with-gnu-ld --enable-languages=c,c++ --enable-shared --enable-lto --enable-symvers=gnu --enable-__cxa_atexit --enable-nls --enable-clocale=gnu --enable-extra-hisi-multilibs
  • arm-hisiv200-linux-gnueabi
    gcc version 4.4.1 (Hisilicon_v200(gcc4.4-290+glibc-2.11+eabi+nptl))

    1
    --enable-threads --disable-libmudflap --disable-libssp --disable-libstdcxx-pch --with-arch=armv5te --with-gnu-as --with-gnu-ld --enable-languages=c,c++ --enable-shared --enable-lto --enable-symvers=gnu --enable-__cxa_atexit --disable-nls --enable-extra-hisi-multilibs

memcpy oops

  • memcpy oops
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Jan  1 00:00:21 login[1069]: root login on 'pts/0'
    Unable to handle kernel paging request at virtual address f25b1001
    pgd = ce43c000
    [f25b1001] *pgd=00000000
    Internal error: Oops: 805 [#1] SMP ARM
    Modules linked in: hi3536_adec(PO) hi3536_aenc(PO) hi3536_ao(PO) hi3536_ai(PO) hi3536_aio(PO) acodec(PO) gpio(O) hi3536_ive(PO) hi3536_vda(PO) hi3536_jpege(PO) hi3536_h264e(PO) hi3536_)
    CPU: 1 PID: 2967 Comm: awk Tainted: P O 3.10.0_hi3536 #1
    task: cec5e000 ti: cd8fa000 task.ti: cd8fa000
    PC is at _memcpy+0xf0/0x330
    LR is at 0x6f
    pc : [<c02cc770>] lr : [<0000006f>] psr: 20000013
    sp : cd8fbdec ip : 00000003 fp : 00000001
    r10: 00000030 r9 : cd8fbe8c r8 : cd8fbed0
    r7 : 00000000 r6 : cd8ed000 r5 : 00000030 r4 : 0000004d
    r3 : 00000020 r2 : 0000002c r1 : cd8ed003 r0 : f25b1001
    Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
    Control: 10c5387d Table: 4e43c06a DAC: 00000015

hi3536 cpu是無支援非對齊 功能
由於gcc為4.8.3 預設為支援非對齊
因此gcc需要增加(-mno-unaligned-access)

  • 記錄

    • 將hi3536的busybox增加下例flag ( -mno-unaligned-access -fno-aggressive-loop-optimizations)
      測試500 loop仍會發生

      1
      CONFIG_EXTRA_CFLAGS="-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4 -mno-unaligned-access -fno-aggressive-loop-optimizations"
    • 將busybox由1.20.2降為1.16.1
      沒有改善

  • 改由使用xm環境測試
    xx/workspace/bitbucket/hi3536/build-dir/hiv300/hixm/1.0.0/rootfs
    相同情況

  • 改由使用glibc測試
    xx/workspace/bitbucket/hi3536/build-dir/hiv400/hixm/1.0.0/rootfs
    相同情況

  • 目前確定是自製kernel造成的

    • 採用xm雄邁板子flash,直接測試,正常(即無memcpy oops)
    • 採用xm-rootfs, 自已產生-kernel ,測試異常(即產生memcpy oops)
    • 採用xm-rootfs, xm-kernel ,測試正常
    • 採用自製的rootfs及xm-kernel,正常(即無memcpy oops)
    • 採用自製的rootfs及自製kernel,測試異常
  • 採用原廠提供prebuild kernel及自製的rootfs,測試異常(即產生memcpy oops)
    single及master都測試一樣產生異常
    Hi3536_SDK_V1.0.5.0/package/osdrv_single/image_uclibc/uImage_hi3536
    Hi3536_SDK_V1.0.5.0/package/osdrv_single/image_uclibc/uImage_hi3536

  • 測試sdk板子上面原本的kernel,正常

  • 未修改kernel直接測試(make OSDRV_CROSS=arm-hisiv300-linux CPU_TYPE=single) , 測試異常

  • 比較測試kernel,確定SDK040正常,SDK050異常


test alignment

pc

  • $ cat aligment.c
    1
    2
    3
    4
    5
    6
    7
    #include <stdio.h>
    int main(){
    char *str = "\x01\x23\x45\x67\x89\xab\xcd\xef";
    unsigned *u = (unsigned *) (str);
    printf( "%08x\n", *u);
    return 0;
    }

./a.out
67452301

  • cat aligment.c
    1
    2
    3
    4
    5
    6
    7
    #include <stdio.h>
    int main(){
    char *str = "\x01\x23\x45\x67\x89\xab\xcd\xef";
    unsigned *u = (unsigned *) (str +1);
    printf( "%08x\n", *u);
    return 0;
    }

./a.out
89674523

hi3535

  • cat alignment
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /proc/cpu # cat alignment 
    User: 0
    System: 0
    Skipped: 0
    Half: 0
    Word: 0
    DWord: 0
    Multi: 0
    User faults: 2 (fixup)

./a.out
89674523

  • alignment
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    /proc/cpu # echo 0 > alignment 
    alignment: ignoring faults is unsafe on this CPU. Defaulting to fixup mode.

    /proc/cpu # echo 1 > alignment
    alignment: ignoring faults is unsafe on this CPU. Defaulting to fixup mode.

    /proc/cpu # cat alignment
    User: 0
    System: 0
    Skipped: 0
    Half: 0
    Word: 0
    DWord: 0
    Multi: 0
    User faults: 3 (fixup+warn)

    /proc/cpu # /test/a.out
    89674523

    /proc/cpu # echo 2 > alignment
    /proc/cpu # cat alignment
    User: 0
    System: 0
    Skipped: 0
    Half: 0
    Word: 0
    DWord: 0
    Multi: 0
    User faults: 2 (fixup)

hi3536

./a.out
89674523


single char test

  • cat singlechar.c

    1
    2
    3
    4
    5
    6
    7
    #include <stdio.h>

    int main(){
    char c1 = 0xff, c2 = 0x01;
    printf( (c1 > c2) ? "c1>c2\n" : "c1 <= c2" );
    return 0;
    }
  • pc
    $ ./a.out
    c1 <= c2

  • hi3535
    /test # ./a.out
    c1>c2

ARM Toolchain特有- 以char宣告的unsigned char數值
所以跟gcc實做有問題


其它

  • hi3536 uclibc

    1
    2
    3
    4
    5
    6
    $ nm -D libuClibc-0.9.33.2.so | grep memcpy
    0000c474 T __aeabi_memcpy
    0000c474 T __aeabi_memcpy4
    0000c474 T __aeabi_memcpy8
    000319e0 T memcpy
    00034978 T wmemcpy
  • mem_alignment
    cpu為需要對齊(alignmen),當程式發生非對齊,kernel提供相對應該處理程序
    /proc/cpu/aligment


參考