diff --git a/demos/linux-ltp/0001-Make-it-work-on-Occlum.patch b/demos/linux-ltp/0001-Make-it-work-on-Occlum.patch new file mode 100644 index 00000000..37af3a66 --- /dev/null +++ b/demos/linux-ltp/0001-Make-it-work-on-Occlum.patch @@ -0,0 +1,104 @@ +From a8b88e78b863d54135436a866d375c67aaaec905 Mon Sep 17 00:00:00 2001 +From: "Zheng, Qi" +Date: Tue, 19 Oct 2021 10:53:08 +0800 +Subject: [PATCH] Make it work on Occlum + +Signed-off-by: Zheng, Qi +--- + lib/tst_kvercmp.c | 4 +++- + lib/tst_test.c | 21 +++++++++++---------- + 2 files changed, 14 insertions(+), 11 deletions(-) + +diff --git a/lib/tst_kvercmp.c b/lib/tst_kvercmp.c +index 8bf65d309..d299c4cb5 100644 +--- a/lib/tst_kvercmp.c ++++ b/lib/tst_kvercmp.c +@@ -102,7 +102,9 @@ int tst_kvercmp(int r1, int r2, int r3) + { + struct utsname uval; + +- uname(&uval); ++ //uname(&uval); ++ /* Hack the uname kernel version to 4.19.1 to make it work on Occlum */ ++ strcpy(uval.release, "4.19.1"); + + return tst_kvcmp(uval.release, r1, r2, r3); + } +diff --git a/lib/tst_test.c b/lib/tst_test.c +index ec80e17a6..a8c414ac8 100644 +--- a/lib/tst_test.c ++++ b/lib/tst_test.c +@@ -1163,7 +1163,7 @@ static void run_tests(void) + tst_test->test_all(); + + if (getpid() != main_pid) { +- exit(0); ++ _exit(0); + } + + tst_reap_children(); +@@ -1178,7 +1178,7 @@ static void run_tests(void) + tst_test->test(i); + + if (getpid() != main_pid) { +- exit(0); ++ _exit(0); + } + + tst_reap_children(); +@@ -1230,7 +1230,7 @@ static void heartbeat(void) + exit(TBROK); + } + +- kill(getppid(), SIGUSR1); ++ //kill(getppid(), SIGUSR1); + } + + static void testrun(void) +@@ -1265,7 +1265,7 @@ static void testrun(void) + } + + do_test_cleanup(); +- exit(0); ++ _exit(0); + } + + static pid_t test_pid; +@@ -1374,27 +1374,28 @@ static int fork_testrun(void) + { + int status; + +- if (tst_test->timeout) ++ /*if (tst_test->timeout) + tst_set_timeout(tst_test->timeout); + else +- tst_set_timeout(300); ++ tst_set_timeout(300);*/ + + SAFE_SIGNAL(SIGINT, sigint_handler); + +- test_pid = fork(); ++ test_pid = vfork(); + if (test_pid < 0) + tst_brk(TBROK | TERRNO, "fork()"); + + if (!test_pid) { +- SAFE_SIGNAL(SIGALRM, SIG_DFL); ++ tst_res(TINFO, "In Child process ...\n"); ++ //SAFE_SIGNAL(SIGALRM, SIG_DFL); + SAFE_SIGNAL(SIGUSR1, SIG_DFL); + SAFE_SIGNAL(SIGINT, SIG_DFL); + SAFE_SETPGID(0, 0); + testrun(); + } + +- SAFE_WAITPID(test_pid, &status, 0); +- alarm(0); ++ waitpid(test_pid, &status, 0); ++ //alarm(0); + SAFE_SIGNAL(SIGINT, SIG_DFL); + + if (tst_test->taint_check && tst_taint_check()) { +-- +2.25.1 + diff --git a/demos/linux-ltp/0002-Ignore-some-test-cases-which-crash-the-Occlum.patch b/demos/linux-ltp/0002-Ignore-some-test-cases-which-crash-the-Occlum.patch new file mode 100644 index 00000000..59c3e515 --- /dev/null +++ b/demos/linux-ltp/0002-Ignore-some-test-cases-which-crash-the-Occlum.patch @@ -0,0 +1,261 @@ +From 93d9429fa9b0b3856258422894697621c5c093b9 Mon Sep 17 00:00:00 2001 +From: "Zheng, Qi" +Date: Tue, 19 Oct 2021 17:17:03 +0800 +Subject: [PATCH] Ignore some test cases which crash the Occlum + +Signed-off-by: Zheng, Qi +--- + runtest/syscalls | 80 ++++++++++++++++++++++++------------------------ + 1 file changed, 40 insertions(+), 40 deletions(-) + +diff --git a/runtest/syscalls b/runtest/syscalls +index 29d7752c7..0d2f9dc67 100644 +--- a/runtest/syscalls ++++ b/runtest/syscalls +@@ -93,7 +93,7 @@ clock_nanosleep02 clock_nanosleep02 + clock_nanosleep03 clock_nanosleep03 + clock_nanosleep04 clock_nanosleep04 + +-clock_gettime01 clock_gettime01 ++#clock_gettime01 clock_gettime01 + clock_gettime02 clock_gettime02 + clock_gettime03 clock_gettime03 + clock_gettime04 clock_gettime04 +@@ -124,7 +124,7 @@ close_range02 close_range02 + + confstr01 confstr01 + +-connect01 connect01 ++#connect01 connect01 + connect02 connect02 + + creat01 creat01 +@@ -148,14 +148,14 @@ dup05 dup05 + dup06 dup06 + dup07 dup07 + +-dup201 dup201 ++#dup201 dup201 + dup202 dup202 + dup203 dup203 + dup204 dup204 + dup205 dup205 + + dup3_01 dup3_01 +-dup3_02 dup3_02 ++#dup3_02 dup3_02 + + epoll_create01 epoll_create01 + epoll_create02 epoll_create02 +@@ -165,7 +165,7 @@ epoll01 epoll-ltp + epoll_ctl01 epoll_ctl01 + epoll_ctl02 epoll_ctl02 + epoll_ctl03 epoll_ctl03 +-epoll_ctl04 epoll_ctl04 ++#epoll_ctl04 epoll_ctl04 + epoll_ctl05 epoll_ctl05 + epoll_wait01 epoll_wait01 + epoll_wait02 epoll_wait02 +@@ -407,8 +407,8 @@ fsync04 fsync04 + + ftruncate01 ftruncate01 + ftruncate01_64 ftruncate01_64 +-ftruncate03 ftruncate03 +-ftruncate03_64 ftruncate03_64 ++#ftruncate03 ftruncate03 ++#ftruncate03_64 ftruncate03_64 + ftruncate04 ftruncate04 + ftruncate04_64 ftruncate04_64 + +@@ -486,17 +486,17 @@ getrandom04 getrandom04 + + getresgid01 getresgid01 + getresgid01_16 getresgid01_16 +-getresgid02 getresgid02 +-getresgid02_16 getresgid02_16 +-getresgid03 getresgid03 +-getresgid03_16 getresgid03_16 ++#getresgid02 getresgid02 ++#getresgid02_16 getresgid02_16 ++#getresgid03 getresgid03 ++#getresgid03_16 getresgid03_16 + + getresuid01 getresuid01 + getresuid01_16 getresuid01_16 +-getresuid02 getresuid02 +-getresuid02_16 getresuid02_16 +-getresuid03 getresuid03 +-getresuid03_16 getresuid03_16 ++#getresuid02 getresuid02 ++#getresuid02_16 getresuid02_16 ++#getresuid03 getresuid03 ++#getresuid03_16 getresuid03_16 + + getrlimit01 getrlimit01 + getrlimit02 getrlimit02 +@@ -522,7 +522,7 @@ getsockopt02 getsockopt02 + gettid01 gettid01 + + gettimeofday01 gettimeofday01 +-gettimeofday02 gettimeofday02 ++#gettimeofday02 gettimeofday02 + + getuid01 getuid01 + getuid01_16 getuid01_16 +@@ -651,7 +651,7 @@ kill06 kill06 + kill07 kill07 + kill08 kill08 + kill09 kill09 +-kill10 kill10 ++#kill10 kill10 + kill11 kill11 + kill12 kill12 + kill13 kill13 +@@ -742,13 +742,13 @@ mkdirat01 mkdirat01 + mkdirat02 mkdirat02 + + mknod01 mknod01 +-mknod02 mknod02 +-mknod03 mknod03 +-mknod04 mknod04 ++#mknod02 mknod02 ++#mknod03 mknod03 ++#mknod04 mknod04 + mknod05 mknod05 + mknod06 mknod06 + mknod07 mknod07 +-mknod08 mknod08 ++#mknod08 mknod08 + mknod09 mknod09 + + #mknodat test cases +@@ -767,11 +767,11 @@ mlock203 mlock203 + qmm01 mmap001 -m 1 + mmap01 mmap01 + mmap02 mmap02 +-mmap03 mmap03 ++#mmap03 mmap03 + mmap04 mmap04 + mmap05 mmap05 +-mmap06 mmap06 +-mmap07 mmap07 ++#mmap06 mmap06 ++#mmap07 mmap07 + mmap08 mmap08 + mmap09 mmap09 + mmap12 mmap12 +@@ -961,7 +961,7 @@ pipe03 pipe03 + pipe04 pipe04 + pipe05 pipe05 + pipe06 pipe06 +-pipe07 pipe07 ++#pipe07 pipe07 + pipe08 pipe08 + pipe09 pipe09 + pipe10 pipe10 +@@ -1073,7 +1073,7 @@ quotactl06 quotactl06 + quotactl07 quotactl07 + + read01 read01 +-read02 read02 ++#read02 read02 + read03 read03 + read04 read04 + +@@ -1099,9 +1099,9 @@ realpath01 realpath01 + reboot01 reboot01 + reboot02 reboot02 + +-recv01 recv01 ++#recv01 recv01 + +-recvfrom01 recvfrom01 ++#recvfrom01 recvfrom01 + + recvmsg01 recvmsg01 + recvmsg02 recvmsg02 +@@ -1121,7 +1121,7 @@ rename02 rename02 + rename03 rename03 + rename04 rename04 + rename05 rename05 +-rename06 rename06 ++#rename06 rename06 + rename07 rename07 + rename08 rename08 + rename09 rename09 +@@ -1222,7 +1222,7 @@ semop01 semop01 + semop02 semop02 + semop03 semop03 + +-send01 send01 ++#send01 send01 + send02 send02 + + sendfile02 sendfile02 +@@ -1250,7 +1250,7 @@ sendmsg03 sendmsg03 + sendmmsg01 sendmmsg01 + sendmmsg02 sendmmsg02 + +-sendto01 sendto01 ++#sendto01 sendto01 + sendto02 sendto02 + sendto03 sendto03 + +@@ -1437,7 +1437,7 @@ signal02 signal02 + signal03 signal03 + signal04 signal04 + signal05 signal05 +-signal06 signal06 ++#signal06 signal06 + + signalfd01 signalfd01 + +@@ -1516,7 +1516,7 @@ switch01 endian_switch01 + + symlink01 symlink01 + symlink02 symlink02 +-symlink03 symlink03 ++#symlink03 symlink03 + symlink04 symlink04 + symlink05 symlink05 + +@@ -1696,14 +1696,14 @@ waitid02 waitid02 + + write01 write01 + write02 write02 +-write03 write03 ++#write03 write03 + write04 write04 +-write05 write05 ++#write05 write05 + +-writev01 writev01 +-writev02 writev02 ++#writev01 writev01 ++#writev02 writev02 + writev03 writev03 +-writev05 writev05 ++#writev05 writev05 + writev06 writev06 + writev07 writev07 + +@@ -1714,14 +1714,14 @@ futex_cmp_requeue01 futex_cmp_requeue01 + futex_cmp_requeue02 futex_cmp_requeue02 + futex_wait01 futex_wait01 + futex_wait02 futex_wait02 +-futex_wait03 futex_wait03 ++#futex_wait03 futex_wait03 + futex_wait04 futex_wait04 + futex_wait05 futex_wait05 + futex_wake01 futex_wake01 + futex_wake02 futex_wake02 + futex_wake03 futex_wake03 + futex_wake04 futex_wake04 +-futex_wait_bitset01 futex_wait_bitset01 ++#futex_wait_bitset01 futex_wait_bitset01 + + memfd_create01 memfd_create01 + memfd_create02 memfd_create02 +-- +2.25.1 + diff --git a/demos/linux-ltp/README.md b/demos/linux-ltp/README.md new file mode 100644 index 00000000..c4c96bfc --- /dev/null +++ b/demos/linux-ltp/README.md @@ -0,0 +1,45 @@ +# Run Linux LTP on Occlum + +In this demo, we will show how to run the Linux LTP inside Occlum. + +Linux [`LTP`](https://github.com/linux-test-project/ltp) is the most popular test suite for Linux. +Occlum could also apply the LTP to verify the stability and compatibility to Linux app. + +Because Occlum doesn't support `fork`, `vfork` has to be used instead in the LTP test. +And a light weight [`test script`](./run-ltp.sh) running in Occlum is provided to be used in this demo. + +## Download and build the Linux LTP from source code +``` +./dl_and_build_ltp.sh +``` + +Two patches are applied to make it work on Occlum. +Many test cases are failed due to multiple reasons, such as syscall is not implemented or not completely implemented in Occlum. + +* Some test cases may make the Occlum crash or hang (Only checked the cases in syscalls), they are ignored by applying the [`patch`](./0002-Ignore-some-test-cases-which-crash-the-Occlum.patch) + +It may be updated with Occlum development. + +## Prepare the Occlum instance for LTP demo +``` +./prepare_ltp.sh +``` + +## Run the LTP demo + +The script `run-ltp.sh` supports two optional arguments as below. +``` + usage: run-ltp.sh [options] + + options: + -f CMDFILES Execute user defined list of testcases + -s PATTERN Only run test cases which match PATTERN. + + example: run-ltp.sh -f syscalls -s timerfd +``` + +If no options provided, all the test cases in syscalls will be run one by one. + +Note: + +* The `CMDFILES` are defined in the LTP install path, such as `ltp_instance/image/opt/ltp/runtest/` in this demo. diff --git a/demos/linux-ltp/dl_and_build_ltp.sh b/demos/linux-ltp/dl_and_build_ltp.sh new file mode 100755 index 00000000..ca57ec23 --- /dev/null +++ b/demos/linux-ltp/dl_and_build_ltp.sh @@ -0,0 +1,21 @@ +#! /bin/bash +set -e + +SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +TAG=20210927 +LTP_INSTALL_DIR=${SCRIPT_DIR}/ltp_install/ltp + +rm -rf ltp +rm -rf $LTP_INSTALL_DIR && mkdir -p ${LTP_INSTALL_DIR} +git clone -b $TAG https://github.com/linux-test-project/ltp.git + +pushd ltp +# Apply patch to support running ltp in Occlum +git apply ../0001-Make-it-work-on-Occlum.patch +git apply ../0002-Ignore-some-test-cases-which-crash-the-Occlum.patch +make autotools +./configure --prefix=${LTP_INSTALL_DIR} +make -j && make install + +popd \ No newline at end of file diff --git a/demos/linux-ltp/ltp.yaml b/demos/linux-ltp/ltp.yaml new file mode 100644 index 00000000..50619b9b --- /dev/null +++ b/demos/linux-ltp/ltp.yaml @@ -0,0 +1,63 @@ +includes: + - base.yaml +# bash +targets: + # copy LTP + - target: /opt + copy: + - dirs: + - ../ltp_install/ltp + # copy bash and busybox + - target: /bin + copy: + - files: + - /opt/occlum/toolchains/bash/glibc/bash + - /opt/occlum/toolchains/busybox/glibc/busybox + # copy test script + - target: /opt/ltp + copy: + - files: + - ../run-ltp.sh + - target: /bin + # build a symlink: ln -s $linksrc $target/linkname + createlinks: + - src: /bin/bash + linkname: sh + - src: /bin/busybox + linkname: basename + - src: /bin/busybox + linkname: echo + - src: /bin/busybox + linkname: sed + - src: /bin/busybox + linkname: grep + - src: /bin/busybox + linkname: cp + - src: /bin/busybox + linkname: mkdir + - src: /bin/busybox + linkname: cat + - src: /bin/busybox + linkname: dirname + - src: /bin/busybox + linkname: date + - src: /bin/busybox + linkname: pwd + - src: /bin/busybox + linkname: mktemp + - src: /bin/busybox + linkname: chmod + - src: /bin/busybox + linkname: rm + - src: /bin/busybox + linkname: awk + - src: /bin/busybox + linkname: cut + - src: /bin/busybox + linkname: tr + - src: /bin/busybox + linkname: id + - src: /bin/busybox + linkname: mv + - src: /bin/busybox + linkname: uname diff --git a/demos/linux-ltp/prepare_ltp.sh b/demos/linux-ltp/prepare_ltp.sh new file mode 100755 index 00000000..eb286061 --- /dev/null +++ b/demos/linux-ltp/prepare_ltp.sh @@ -0,0 +1,20 @@ +#! /bin/bash +set -e + +rm -rf ltp_instance +occlum new ltp_instance + +cd ltp_instance +rm -rf image +copy_bom -f ../ltp.yaml --root image --include-dir /opt/occlum/etc/template + +new_json="$(jq '.resource_limits.user_space_size = "3000MB" | + .resource_limits.kernel_space_heap_size ="512MB" | + .resource_limits.kernel_space_stack_size ="4MB" | + .resource_limits.max_num_of_threads = 96 | + .entry_points = [ "/opt/ltp" ] | + .env.default = [ "OCCLUM=yes", "LTPROOT=/opt/ltp", "TMP=/tmp", "HOME=/root" ]' Occlum.json)" && \ +echo "${new_json}" > Occlum.json + +occlum build + diff --git a/demos/linux-ltp/run-ltp.sh b/demos/linux-ltp/run-ltp.sh new file mode 100755 index 00000000..3b533685 --- /dev/null +++ b/demos/linux-ltp/run-ltp.sh @@ -0,0 +1,109 @@ +#!/bin/sh + +setup() +{ + export LTPROOT=${LTPROOT:-/opt/ltp} + export TMP="/tmp" + export PATH="${PATH}:${LTPROOT}/testcases/bin:${LTPROOT}/bin" + + [ -d "$LTPROOT/testcases/bin" ] || + { + echo "FATAL: LTP not installed correctly" + echo "INFO: Follow directions in INSTALL!" + exit 1 + } + + rm -rf ${TMP}/alltests* +} + +usage() +{ + cat <<-EOF >&2 + + usage: ${0##*/} [options] + + options: + -f CMDFILES Execute user defined list of testcases + -h Help. Prints all available options. + -s PATTERN Only run test cases which match PATTERN. + + example: ${0##*/} -f syscalls -s timerfd + + + EOF +exit 0 +} + +main() +{ + local CMDFILES='syscalls' + local TAG_RESTRICT_STRING= + + version_date=$(cat "$LTPROOT/Version") + + echo "$version_date" + + while getopts f:hs: arg + do case $arg in + f) # Execute user defined set of testcases. + CMDFILES=$OPTARG;; + h) usage;; + s) TAG_RESTRICT_STRING=$OPTARG;; + \?) usage;; + esac + done + + echo "INFO: Test on files $CMDFILES" + + [ -n "$CMDFILES" ] && \ + { + #for scenfile in `echo "$CMDFILES" | tr ',' ' '` + for scenfile in `echo "$CMDFILES"` + do + [ -f "$scenfile" ] || scenfile="$LTPROOT/runtest/$scenfile" + cat "$scenfile" >> ${TMP}/alltests.tmp || \ + { + echo "FATAL: unable to create command file" + rm -Rf "$TMP" + exit 1 + } + done + } + + # Skip the lines start with # + grep -v "^#" ${TMP}/alltests.tmp > ${TMP}/alltests + + # If enabled, execute only test cases that match the PATTERN + if [ -n "$TAG_RESTRICT_STRING" ] + then + mv -f ${TMP}/alltests ${TMP}/alltests.orig + grep $TAG_RESTRICT_STRING ${TMP}/alltests.orig > ${TMP}/alltests + echo "INFO: Restricted to $TAG_RESTRICT_STRING" + fi + + #grep -v "^#" "${TMP}/alltests" | while read -r line + while read -r line + do + # ignore empty lines + [ "x$line" = x ] && continue + + line_array=($line) + name=${line_array[0]} + bin=${line_array[1]} + len=${#line_array[@]} + idx=2 + args=() + + echo "INFO: Test case: $name" + if [ $len -gt 2 ] + then + args=${line_array[@]:$idx:$((len - idx))} + fi + echo "INFO: ... Commands: $bin $args" + + $LTPROOT/testcases/bin/$bin + done < "${TMP}/alltests" +} + +setup +main "$@" \ No newline at end of file