From 3636c8e7e47870cbb1d8fb2d0b3aaa4ef6343427 Mon Sep 17 00:00:00 2001 From: Ken Sato Date: Mon, 2 Jul 2018 13:15:32 +0900 Subject: [PATCH] setrlimit: Check arguments in the same order as in Linux (1) Check if rlim's address is valid (2) Check if soft-limit does not exceed hard-limit Fujitsu: POSTK_DEBUG_TEMP_FIX_3 Refs: #1050 Change-Id: I5bf1008ce172f9dff64ec89b1f97614926abaf13 --- kernel/syscall.c | 22 +++++------- test/issues/1050/C1050.sh | 72 +++++++++++++++++++++++++++++++++++++ test/issues/1050/CT_001.c | 66 ++++++++++++++++++++++++++++++++++ test/issues/1050/CT_002.c | 66 ++++++++++++++++++++++++++++++++++ test/issues/1050/CT_003.c | 66 ++++++++++++++++++++++++++++++++++ test/issues/1050/CT_004.c | 66 ++++++++++++++++++++++++++++++++++ test/issues/1050/Makefile | 26 ++++++++++++++ test/issues/1050/README | 52 +++++++++++++++++++++++++++ test/issues/1050/result.log | 35 ++++++++++++++++++ test/issues/1050/test_chk.h | 23 ++++++++++++ 10 files changed, 481 insertions(+), 13 deletions(-) create mode 100644 test/issues/1050/C1050.sh create mode 100644 test/issues/1050/CT_001.c create mode 100644 test/issues/1050/CT_002.c create mode 100644 test/issues/1050/CT_003.c create mode 100644 test/issues/1050/CT_004.c create mode 100644 test/issues/1050/Makefile create mode 100644 test/issues/1050/README create mode 100644 test/issues/1050/result.log create mode 100644 test/issues/1050/test_chk.h diff --git a/kernel/syscall.c b/kernel/syscall.c index 168831bb..0803d26a 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -5565,16 +5565,16 @@ SYSCALL_DECLARE(setrlimit) struct rlimit *rlm = (struct rlimit *)ihk_mc_syscall_arg1(ctx); struct thread *thread = cpu_local_var(current); int i; -#ifdef POSTK_DEBUG_TEMP_FIX_3 /* If rlim_cur is greater than rlim_max, return -EINVAL (S64FX_19) */ struct rlimit new_rlim; - - if (copy_from_user(&new_rlim, rlm, sizeof(*rlm))) - return -EFAULT; - if (new_rlim.rlim_cur > new_rlim.rlim_max) - return -EINVAL; -#endif /* POSTK_DEBUG_TEMP_FIX_3 */ int mcresource; + if (copy_from_user(&new_rlim, rlm, sizeof(*rlm))) { + return -EFAULT; + } + if (new_rlim.rlim_cur > new_rlim.rlim_max) { + return -EINVAL; + } + switch(resource){ case RLIMIT_FSIZE: case RLIMIT_NOFILE: @@ -5595,12 +5595,8 @@ SYSCALL_DECLARE(setrlimit) return syscall_generic_forwarding(__NR_setrlimit, ctx); } -#ifdef POSTK_DEBUG_TEMP_FIX_3 /* If rlim_cur is greater than rlim_max, return -EINVAL (S64FX_19) */ - memcpy(thread->proc->rlimit + mcresource, &new_rlim, sizeof(new_rlim)); -#else /* POSTK_DEBUG_TEMP_FIX_3 */ - if(copy_from_user(thread->proc->rlimit + mcresource, rlm, sizeof(struct rlimit))) - return -EFAULT; -#endif /* POSTK_DEBUG_TEMP_FIX_3 */ + memcpy(thread->proc->rlimit + mcresource, &new_rlim, + sizeof(new_rlim)); return 0; } diff --git a/test/issues/1050/C1050.sh b/test/issues/1050/C1050.sh new file mode 100644 index 00000000..e9e0a989 --- /dev/null +++ b/test/issues/1050/C1050.sh @@ -0,0 +1,72 @@ +#!/bin/sh +BIN= +SBIN= +OSTEST= +LTP= +BOOTPARAM="-c 1-7,9-15,17-23,25-31 -m 10G@0,10G@1 -r 1-7:0+9-15:8+17-23:16+25-31:24" + +if [ -f ../../../config.h ]; then + str=`grep "^#define BINDIR " ../../../config.h | head -1 | sed 's/^#define BINDIR /BINDIR=/'` + eval $str +fi +if [ "x$BINDIR" = x ];then + BINDIR="$BIN" +fi + +if [ -f ../../../Makefile ]; then + str=`grep ^SBINDIR ../../../Makefile | head -1 | sed 's/ //g'` + eval $str +fi +if [ "x$SBINDIR" = x ];then + SBINDIR="$SBIN" +fi + +if [ -f $HOME/ltp/testcases/bin/sched_setaffinity01 ]; then + LTPDIR=$HOME/ltp/testcases +fi +if [ "x$LTPDIR" = x ]; then + LTPDIR="$LTP" +fi + +if [ -f $HOME/ostest/bin/test_mck ]; then + OSTESTDIR=$HOME/ostest/ +fi +if [ "x$OSTESTDIR" = x ]; then + OSTESTDIR="$OSTEST" +fi + +if [ ! -x $SBINDIR/mcstop+release.sh ]; then + echo mcstop+releas: not found >&2 + exit 1 +fi +echo -n "mcstop+release.sh ... " +sudo $SBINDIR/mcstop+release.sh +echo "done" + +if [ ! -x $SBINDIR/mcreboot.sh ]; then + echo mcreboot: not found >&2 + exit 1 +fi +echo -n "mcreboot.sh $BOOTPARAM ... " +sudo $SBINDIR/mcreboot.sh $BOOTPARAM +echo "done" + +if [ ! -x $BINDIR/mcexec ]; then + echo mcexec: not found >&2 + exit 1 +fi + +tid=001 +echo "*** RT_$tid start *******************************" +sudo $BINDIR/mcexec $OSTESTDIR/bin/test_mck -s setrlimit -n 15 2>&1 | tee ./RT_${tid}.txt +if grep "RESULT: ok" ./RT_${tid}.txt > /dev/null 2>&1 ; then + echo "*** RT_$tid: PASSED" +else + echo "*** RT_$tid: FAILED" +fi +echo "" + +sudo $BINDIR/mcexec ./CT_001 +sudo $BINDIR/mcexec ./CT_002 +sudo $BINDIR/mcexec ./CT_003 +sudo $BINDIR/mcexec ./CT_004 diff --git a/test/issues/1050/CT_001.c b/test/issues/1050/CT_001.c new file mode 100644 index 00000000..391a50c9 --- /dev/null +++ b/test/issues/1050/CT_001.c @@ -0,0 +1,66 @@ +#define _GNU_SOURCE 1 + +#include +#include +#include +#include +#include +#include +#include +#include "./test_chk.h" + +#define TEST_NAME "CT_001" + +int main(int argc, char **argv) +{ + struct rlimit get_rlim, set_rlim; + int rc, resource; + int __errno; + rlim_t set_max, set_cur; + + + printf("*** %s start *******************************\n", TEST_NAME); + CHKANDJUMP(geteuid() != 0, "Test needs to be run as root"); + + resource = RLIMIT_NPROC; + rc = getrlimit(resource, &get_rlim); + + OKNG(rc != 0, "getrlimit cur:%lx max:%lx", + get_rlim.rlim_cur, get_rlim.rlim_max); + + set_max = get_rlim.rlim_max - 10; + if (get_rlim.rlim_cur > set_max) { + set_cur = set_max; + } + else { + set_cur = get_rlim.rlim_cur; + } + + set_rlim.rlim_cur = set_cur; + set_rlim.rlim_max = set_max; + + errno = 0; + rc = setrlimit(resource, &set_rlim); + __errno = errno; + + OKNG(rc != 0, "setrlimit cur:%lx max:%lx returned %d" + " (expect return is 0)", + set_rlim.rlim_cur, set_rlim.rlim_max, rc); + + OKNG(__errno != 0, "errno after setrlimit :%d" + " (expect error is 0)", __errno); + + rc = getrlimit(resource, &get_rlim); + OKNG(get_rlim.rlim_max != set_max, "getrlimit cur:%lx max:%lx" + " (expect max is %lx)", + get_rlim.rlim_cur, get_rlim.rlim_max, set_max); + + printf("*** %s PASSED\n\n", TEST_NAME); + + return 0; + +fn_fail: + printf("*** %s FAILED\n\n", TEST_NAME); + + return -1; +} diff --git a/test/issues/1050/CT_002.c b/test/issues/1050/CT_002.c new file mode 100644 index 00000000..09a6dc70 --- /dev/null +++ b/test/issues/1050/CT_002.c @@ -0,0 +1,66 @@ +#define _GNU_SOURCE 1 + +#include +#include +#include +#include +#include +#include +#include +#include "./test_chk.h" + +#define TEST_NAME "CT_002" + +int main(int argc, char **argv) +{ + struct rlimit get_rlim, set_rlim; + int rc, resource; + int __errno; + rlim_t set_max, set_cur; + + + printf("*** %s start *******************************\n", TEST_NAME); + CHKANDJUMP(geteuid() != 0, "Test needs to be run as root"); + + resource = RLIMIT_NPROC; + rc = getrlimit(resource, &get_rlim); + + OKNG(rc != 0, "getrlimit cur:%lx max:%lx", + get_rlim.rlim_cur, get_rlim.rlim_max); + + set_max = get_rlim.rlim_max + 10; + if (get_rlim.rlim_cur > set_max) { + set_cur = set_max; + } + else { + set_cur = get_rlim.rlim_cur; + } + + set_rlim.rlim_cur = set_cur; + set_rlim.rlim_max = set_max; + + errno = 0; + rc = setrlimit(resource, &set_rlim); + __errno = errno; + + OKNG(rc != 0, "setrlimit cur:%lx max:%lx returned %d" + " (expect return is 0)", + set_rlim.rlim_cur, set_rlim.rlim_max, rc); + + OKNG(__errno != 0, "errno after setrlimit :%d" + " (expect error is 0)", __errno); + + rc = getrlimit(resource, &get_rlim); + OKNG(get_rlim.rlim_max != set_max, "getrlimit cur:%lx max:%lx" + " (expect max is %lx)", + get_rlim.rlim_cur, get_rlim.rlim_max, set_max); + + printf("*** %s PASSED\n\n", TEST_NAME); + + return 0; + +fn_fail: + printf("*** %s FAILED\n\n", TEST_NAME); + + return -1; +} diff --git a/test/issues/1050/CT_003.c b/test/issues/1050/CT_003.c new file mode 100644 index 00000000..e54ecf94 --- /dev/null +++ b/test/issues/1050/CT_003.c @@ -0,0 +1,66 @@ +#define _GNU_SOURCE 1 + +#include +#include +#include +#include +#include +#include +#include +#include "./test_chk.h" + +#define TEST_NAME "CT_003" + +int main(int argc, char **argv) +{ + struct rlimit get_rlim, set_rlim; + int rc, resource; + int __errno; + rlim_t set_max, set_cur; + + + printf("*** %s start *******************************\n", TEST_NAME); + CHKANDJUMP(geteuid() != 0, "Test needs to be run as root"); + + resource = RLIMIT_MSGQUEUE; + rc = getrlimit(resource, &get_rlim); + + OKNG(rc != 0, "getrlimit cur:%lx max:%lx", + get_rlim.rlim_cur, get_rlim.rlim_max); + + set_max = get_rlim.rlim_max - 10; + if (get_rlim.rlim_cur > set_max) { + set_cur = set_max; + } + else { + set_cur = get_rlim.rlim_cur; + } + + set_rlim.rlim_cur = set_cur; + set_rlim.rlim_max = set_max; + + errno = 0; + rc = setrlimit(resource, &set_rlim); + __errno = errno; + + OKNG(rc != 0, "setrlimit cur:%lx max:%lx returned %d" + " (expect return is 0)", + set_rlim.rlim_cur, set_rlim.rlim_max, rc); + + OKNG(__errno != 0, "errno after setrlimit :%d" + " (expect error is 0)", __errno); + + rc = getrlimit(resource, &get_rlim); + OKNG(get_rlim.rlim_max != set_max, "getrlimit cur:%lx max:%lx" + " (expect max is %lx)", + get_rlim.rlim_cur, get_rlim.rlim_max, set_max); + + printf("*** %s PASSED\n\n", TEST_NAME); + + return 0; + +fn_fail: + printf("*** %s FAILED\n\n", TEST_NAME); + + return -1; +} diff --git a/test/issues/1050/CT_004.c b/test/issues/1050/CT_004.c new file mode 100644 index 00000000..a23245ba --- /dev/null +++ b/test/issues/1050/CT_004.c @@ -0,0 +1,66 @@ +#define _GNU_SOURCE 1 + +#include +#include +#include +#include +#include +#include +#include +#include "./test_chk.h" + +#define TEST_NAME "CT_004" + +int main(int argc, char **argv) +{ + struct rlimit get_rlim, set_rlim; + int rc, resource; + int __errno; + rlim_t set_max, set_cur; + + + printf("*** %s start *******************************\n", TEST_NAME); + CHKANDJUMP(geteuid() != 0, "Test needs to be run as root"); + + resource = RLIMIT_MSGQUEUE; + rc = getrlimit(resource, &get_rlim); + + OKNG(rc != 0, "getrlimit cur:%lx max:%lx", + get_rlim.rlim_cur, get_rlim.rlim_max); + + set_max = get_rlim.rlim_max + 10; + if (get_rlim.rlim_cur > set_max) { + set_cur = set_max; + } + else { + set_cur = get_rlim.rlim_cur; + } + + set_rlim.rlim_cur = set_cur; + set_rlim.rlim_max = set_max; + + errno = 0; + rc = setrlimit(resource, &set_rlim); + __errno = errno; + + OKNG(rc != 0, "setrlimit cur:%lx max:%lx returned %d" + " (expect return is 0)", + set_rlim.rlim_cur, set_rlim.rlim_max, rc); + + OKNG(__errno != 0, "errno after setrlimit :%d" + " (expect error is 0)", __errno); + + rc = getrlimit(resource, &get_rlim); + OKNG(get_rlim.rlim_max != set_max, "getrlimit cur:%lx max:%lx" + " (expect max is %lx)", + get_rlim.rlim_cur, get_rlim.rlim_max, set_max); + + printf("*** %s PASSED\n\n", TEST_NAME); + + return 0; + +fn_fail: + printf("*** %s FAILED\n\n", TEST_NAME); + + return -1; +} diff --git a/test/issues/1050/Makefile b/test/issues/1050/Makefile new file mode 100644 index 00000000..5afa4b35 --- /dev/null +++ b/test/issues/1050/Makefile @@ -0,0 +1,26 @@ +CC = gcc +TARGET=CT_001 CT_002 CT_003 CT_004 + +CPPFLAGS = +LDFLAGS = + +all: $(TARGET) + +CT_001: CT_001.c + $(CC) -o $@ $^ $(LDFLAGS) + +CT_002: CT_002.c + $(CC) -o $@ $^ $(LDFLAGS) + +CT_003: CT_003.c + $(CC) -o $@ $^ $(LDFLAGS) + +CT_004: CT_004.c + $(CC) -o $@ $^ $(LDFLAGS) + +test: all + @sh ./C1050.sh + +clean: + rm -f $(TARGET) *.o + diff --git a/test/issues/1050/README b/test/issues/1050/README new file mode 100644 index 00000000..1330f783 --- /dev/null +++ b/test/issues/1050/README @@ -0,0 +1,52 @@ +【Issue#1050 動作確認】 +□ テスト内容 +1. Issueで報告された再現プログラムでの確認 +RT_001: ostest-setrlimit.015 + rlim_max(ハードリミット)を超えるrlim_cur(ソフトリミット)を指定した場合、 + -1が返り、errnoにEINVALが設定されることを確認 + +2. 既存のsched_setaffinity機能に影響がないことをテストプログラムを用いて確認 + なお、以下のテストプログラムは特権ユーザ権限で実行する +CT_001: Linuxに処理移譲しないresource指定で、rlim_maxを減少させる操作の確認 + RLIMIT_NPROC をresourceに指定し、以下を確認 + 1. getrlimitで、現在のrlim_max の値を取得 + 2. setrlimitで、現在のrlim_max - 10 の値を設定 + 3. setrlimitが成功し、0を返すことを確認 + 4. errnoが変更されていないことを確認 + 5. getrlimitで、変更後の値が設定されていることを確認 + +CT_002: Linuxに処理移譲しないresource指定で、rlim_maxを増加させる操作の確認 + RLIMIT_NPROC をresourceに指定し、以下を確認 + 1. getrlimitで、現在のrlim_max の値を取得 + 2. setrlimitで、現在のrlim_max + 10 の値を設定 + 3. setrlimitが成功し、0を返すことを確認 + 4. errnoが変更されていないことを確認 + 5. getrlimitで、値が変更されていることを確認 + +CT_003: Linuxに処理移譲するresource指定で、rlim_maxを減少させる操作の確認 + RLIMIT_MSGQUEUE をresourceに指定し、以下を確認 + 1. getrlimitで、現在のrlim_max の値を取得 + 2. setrlimitで、現在のrlim_max - 10 の値を設定 + 3. setrlimitが成功し、0を返すことを確認 + 4. errnoが変更されていないことを確認 + 5. getrlimitで、変更後の値が設定されていることを確認 + +CT_004: Linuxに処理移譲するresource指定で、rlim_maxを増加させる操作の確認 + RLIMIT_MSGQUEUE をresourceに指定し、以下を確認 + 1. getrlimitで、現在のrlim_max の値を取得 + 2. setrlimitで、現在のrlim_max + 10 の値を設定 + 3. setrlimitが成功し、0を返すことを確認 + 4. errnoが変更されていないことを確認 + 5. getrlimitで、値が変更されていることを確認 + +□ 実行手順 +$ make test + +実行できない場合は、C1050.shの以下の行を適切に書き換えた後に実行。 +BIN= mcexec が存在するパス +SBIN= mcreboot.sh が存在するパス +OSTEST= OSTESTが存在するパス + +□ 実行結果 +result.log 参照。 +すべての項目をPASSしていることを確認。 diff --git a/test/issues/1050/result.log b/test/issues/1050/result.log new file mode 100644 index 00000000..d0f1a3fc --- /dev/null +++ b/test/issues/1050/result.log @@ -0,0 +1,35 @@ +*** RT_001 start ******************************* +TEST_SUITE: setrlimit +TEST_NUMBER: 15 +ARGS: +setrlimit() = -1, errno = 22 +RESULT: ok +*** RT_001: PASSED + +*** CT_001 start ******************************* + [OK] getrlimit cur:3eb1e max:3eb1e + [OK] setrlimit cur:3eb14 max:3eb14 returned 0 (expect return is 0) + [OK] errno after setrlimit :0 (expect error is 0) + [OK] getrlimit cur:3eb14 max:3eb14 (expect max is 3eb14) +*** CT_001 PASSED + +*** CT_002 start ******************************* + [OK] getrlimit cur:3eb1e max:3eb1e + [OK] setrlimit cur:3eb1e max:3eb28 returned 0 (expect return is 0) + [OK] errno after setrlimit :0 (expect error is 0) + [OK] getrlimit cur:3eb1e max:3eb28 (expect max is 3eb28) +*** CT_002 PASSED + +*** CT_003 start ******************************* + [OK] getrlimit cur:c8000 max:c8000 + [OK] setrlimit cur:c7ff6 max:c7ff6 returned 0 (expect return is 0) + [OK] errno after setrlimit :0 (expect error is 0) + [OK] getrlimit cur:c7ff6 max:c7ff6 (expect max is c7ff6) +*** CT_003 PASSED + +*** CT_004 start ******************************* + [OK] getrlimit cur:c8000 max:c8000 + [OK] setrlimit cur:c8000 max:c800a returned 0 (expect return is 0) + [OK] errno after setrlimit :0 (expect error is 0) + [OK] getrlimit cur:c8000 max:c800a (expect max is c800a) +*** CT_004 PASSED diff --git a/test/issues/1050/test_chk.h b/test/issues/1050/test_chk.h new file mode 100644 index 00000000..4cef42e8 --- /dev/null +++ b/test/issues/1050/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