linux-kselftest-4.14-rc1-update

This update consists of:
 
 -- TAP13 framework API and converting tests to TAP13 continues. A few
    more tests are converted and kselftest common RUN_TESTS in lib.mk
    is enhanced to print TAP13 to cover test shell scripts that won't
    be able to use kselftest API.
 
 -- Several fixes to existing tests to not fail in unsupported cases.
    This has been an ongoing work based on the feedback from stable
    release kselftest users.
 
 -- A new watchdog test and much needed cleanups to the existing tests
    from Eugeniu Rosca.
 
 -- Changes to kselftest common lib.mk framework to make RUN_TESTS a
    function to be called from individual test make files to run stress
    and destructive sub-tests.
 -----BEGIN PGP SIGNATURE-----
 
 iQIcBAABCAAGBQJZssCNAAoJEAsCRMQNDUMcYKIQAI0z63hsXAXuBO5ZPBEEwjzn
 +sLudsF6PLB4DjbRsGO/S8EXiYW+BZf7Ny3qYO838aUsZFia3w5AhRq91tTf0WzW
 e41qj5AA/y2YaJDL/Q3oebyj4JzhhhkfjNLEap0vfwNDzVlr9mEXO3sfspFe7pWz
 hAWGPXS8W4O6ZmIFHUwkYdoJhYp9s6vysyO5ZXh9TEbSUnytlYJ35Y2vaDEfHWyR
 DbBj8FOgZhmud4aVbAQ5kOH/rB+rRCYgptF3VUmlyOOHJA7QbQofChDkA0G2WcSZ
 4zoGSah/Kx9C3+H3o7u/FyoMXCiJYr49z1Mzgpf3193gIdH694DbDT9mqZtBgDbt
 0irjg2BNmv/8SdX0fudSj7hbt9uTjGYshl48jlKYU+/d/0jtepV1NUMF7zoYYdNN
 PhT2lUR799M09+0+O6kJ7ESkiVLriVkkY0ORW9qGuD2FxLRk0XJzrAacrD5DsEgk
 6Hq/mA1v4HsvoeSZz+2AIMrrQcAsCVWXuseWsN88EU+HPMaKVclcZQ10fXI3zHB+
 BtCiYz9xI+E1sI4MLeSqg2nxZhLhM1Jx+RZA6W38fZIxeaUsItt3OxTFMOFDMky+
 Ahqb+CCCxS8ai7hy9XNBIh1BRjXPbZJCILTdjy82S+xNSRU8qbO7qF3+eoRGP1dB
 UWdB0+1ftkyf8CbqqC60
 =RVb5
 -----END PGP SIGNATURE-----

Merge tag 'linux-kselftest-4.14-rc1-update' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull kselftest updates from Shuah Khan:

 - TAP13 framework API and converting tests to TAP13 continues. A few
   more tests are converted and kselftest common RUN_TESTS in lib.mk is
   enhanced to print TAP13 to cover test shell scripts that won't be
   able to use kselftest API.

 - Several fixes to existing tests to not fail in unsupported cases.
   This has been an ongoing work based on the feedback from stable
   release kselftest users.

 - A new watchdog test and much needed cleanups to the existing tests
   from Eugeniu Rosca.

 - Changes to kselftest common lib.mk framework to make RUN_TESTS a
   function to be called from individual test make files to run stress
   and destructive sub-tests.

* tag 'linux-kselftest-4.14-rc1-update' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: (41 commits)
  selftests: Enhance kselftest_harness.h to print which assert failed
  selftests: lib.mk: change RUN_TESTS to print messages in TAP13 format
  selftests: change lib.mk RUN_TESTS to take test list as an argument
  selftests: lib.mk: suppress "cd" output from run_tests target
  selftests: kselftest framework: change skip exit code to 0
  selftests/timers: make loop consistent with array size
  selftests: timers: remove rtctest_setdate from run_destructive_tests
  selftests: timers: Fix run_destructive_tests target to handle skipped tests
  kselftests: timers: leap-a-day: Change default arguments to help test runs
  selftests: timers: drop support for !KTEST case
  rtc: rtctest: Improve support detection
  selftests/cpu-hotplug: Skip test when there is only one online cpu
  selftests/cpu-hotplug: exit with failure when test occured unexpected behaviors
  selftests: futex: convert test to use ksft TAP13 framework
  selftests: capabilities: convert error output to TAP13 ksft framework
  selftests: memfd: Align STACK_SIZE for ARM AArch64 system
  selftests: warn if failure is due to lack of executable bit
  selftests: kselftest framework: add error counter
  selftests: capabilities: convert the test to use TAP13 ksft framework
  selftests: capabilities: fix to run Non-root +ia, sgidroot => i test
  ...
This commit is contained in:
Linus Torvalds 2017-09-08 15:11:20 -07:00
commit 6d6218976d
47 changed files with 510 additions and 483 deletions

View File

@ -367,11 +367,11 @@ static void launch_tests(void)
/* Icebp traps */
ptrace(PTRACE_CONT, child_pid, NULL, 0);
check_success("Test icebp");
check_success("Test icebp\n");
/* Int 3 traps */
ptrace(PTRACE_CONT, child_pid, NULL, 0);
check_success("Test int 3 trap");
check_success("Test int 3 trap\n");
ptrace(PTRACE_CONT, child_pid, NULL, 0);
}

View File

@ -1,7 +1,6 @@
#define _GNU_SOURCE
#include <cap-ng.h>
#include <err.h>
#include <linux/capability.h>
#include <stdbool.h>
#include <string.h>
@ -18,6 +17,8 @@
#include <sys/prctl.h>
#include <sys/stat.h>
#include "../kselftest.h"
#ifndef PR_CAP_AMBIENT
#define PR_CAP_AMBIENT 47
# define PR_CAP_AMBIENT_IS_SET 1
@ -27,6 +28,7 @@
#endif
static int nerrs;
static pid_t mpid; /* main() pid is used to avoid duplicate test counts */
static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list ap)
{
@ -36,29 +38,32 @@ static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list
int buf_len;
buf_len = vsnprintf(buf, sizeof(buf), fmt, ap);
if (buf_len < 0) {
err(1, "vsnprintf failed");
}
if (buf_len >= sizeof(buf)) {
errx(1, "vsnprintf output truncated");
}
if (buf_len < 0)
ksft_exit_fail_msg("vsnprintf failed - %s\n", strerror(errno));
if (buf_len >= sizeof(buf))
ksft_exit_fail_msg("vsnprintf output truncated\n");
fd = open(filename, O_WRONLY);
if (fd < 0) {
if ((errno == ENOENT) && enoent_ok)
return;
err(1, "open of %s failed", filename);
ksft_exit_fail_msg("open of %s failed - %s\n",
filename, strerror(errno));
}
written = write(fd, buf, buf_len);
if (written != buf_len) {
if (written >= 0) {
errx(1, "short write to %s", filename);
ksft_exit_fail_msg("short write to %s\n", filename);
} else {
err(1, "write to %s failed", filename);
ksft_exit_fail_msg("write to %s failed - %s\n",
filename, strerror(errno));
}
}
if (close(fd) != 0) {
err(1, "close of %s failed", filename);
ksft_exit_fail_msg("close of %s failed - %s\n",
filename, strerror(errno));
}
}
@ -95,11 +100,12 @@ static bool create_and_enter_ns(uid_t inner_uid)
*/
if (unshare(CLONE_NEWNS) == 0) {
printf("[NOTE]\tUsing global UIDs for tests\n");
ksft_print_msg("[NOTE]\tUsing global UIDs for tests\n");
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0)
err(1, "PR_SET_KEEPCAPS");
ksft_exit_fail_msg("PR_SET_KEEPCAPS - %s\n",
strerror(errno));
if (setresuid(inner_uid, inner_uid, -1) != 0)
err(1, "setresuid");
ksft_exit_fail_msg("setresuid - %s\n", strerror(errno));
// Re-enable effective caps
capng_get_caps_process();
@ -107,22 +113,24 @@ static bool create_and_enter_ns(uid_t inner_uid)
if (capng_have_capability(CAPNG_PERMITTED, i))
capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, i);
if (capng_apply(CAPNG_SELECT_CAPS) != 0)
err(1, "capng_apply");
ksft_exit_fail_msg(
"capng_apply - %s\n", strerror(errno));
have_outer_privilege = true;
} else if (unshare(CLONE_NEWUSER | CLONE_NEWNS) == 0) {
printf("[NOTE]\tUsing a user namespace for tests\n");
ksft_print_msg("[NOTE]\tUsing a user namespace for tests\n");
maybe_write_file("/proc/self/setgroups", "deny");
write_file("/proc/self/uid_map", "%d %d 1", inner_uid, outer_uid);
write_file("/proc/self/gid_map", "0 %d 1", outer_gid);
have_outer_privilege = false;
} else {
errx(1, "must be root or be able to create a userns");
ksft_exit_skip("must be root or be able to create a userns\n");
}
if (mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0)
err(1, "remount everything private");
ksft_exit_fail_msg("remount everything private - %s\n",
strerror(errno));
return have_outer_privilege;
}
@ -131,20 +139,22 @@ static void chdir_to_tmpfs(void)
{
char cwd[PATH_MAX];
if (getcwd(cwd, sizeof(cwd)) != cwd)
err(1, "getcwd");
ksft_exit_fail_msg("getcwd - %s\n", strerror(errno));
if (mount("private_tmp", ".", "tmpfs", 0, "mode=0777") != 0)
err(1, "mount private tmpfs");
ksft_exit_fail_msg("mount private tmpfs - %s\n",
strerror(errno));
if (chdir(cwd) != 0)
err(1, "chdir to private tmpfs");
ksft_exit_fail_msg("chdir to private tmpfs - %s\n",
strerror(errno));
}
static void copy_fromat_to(int fromfd, const char *fromname, const char *toname)
{
int from = openat(fromfd, fromname, O_RDONLY);
if (from == -1)
err(1, "open copy source");
ksft_exit_fail_msg("open copy source - %s\n", strerror(errno));
int to = open(toname, O_CREAT | O_WRONLY | O_EXCL, 0700);
@ -154,10 +164,11 @@ static void copy_fromat_to(int fromfd, const char *fromname, const char *toname)
if (sz == 0)
break;
if (sz < 0)
err(1, "read");
ksft_exit_fail_msg("read - %s\n", strerror(errno));
if (write(to, buf, sz) != sz)
err(1, "write"); /* no short writes on tmpfs */
/* no short writes on tmpfs */
ksft_exit_fail_msg("write - %s\n", strerror(errno));
}
close(from);
@ -174,18 +185,20 @@ static bool fork_wait(void)
int status;
if (waitpid(child, &status, 0) != child ||
!WIFEXITED(status)) {
printf("[FAIL]\tChild died\n");
ksft_print_msg("Child died\n");
nerrs++;
} else if (WEXITSTATUS(status) != 0) {
printf("[FAIL]\tChild failed\n");
ksft_print_msg("Child failed\n");
nerrs++;
} else {
printf("[OK]\tChild succeeded\n");
/* don't print this message for mpid */
if (getpid() != mpid)
ksft_test_result_pass("Passed\n");
}
return false;
} else {
err(1, "fork");
ksft_exit_fail_msg("fork - %s\n", strerror(errno));
return false;
}
}
@ -195,7 +208,7 @@ static void exec_other_validate_cap(const char *name,
execl(name, name, (eff ? "1" : "0"),
(perm ? "1" : "0"), (inh ? "1" : "0"), (ambient ? "1" : "0"),
NULL);
err(1, "execl");
ksft_exit_fail_msg("execl - %s\n", strerror(errno));
}
static void exec_validate_cap(bool eff, bool perm, bool inh, bool ambient)
@ -209,7 +222,8 @@ static int do_tests(int uid, const char *our_path)
int ourpath_fd = open(our_path, O_RDONLY | O_DIRECTORY);
if (ourpath_fd == -1)
err(1, "open '%s'", our_path);
ksft_exit_fail_msg("open '%s' - %s\n",
our_path, strerror(errno));
chdir_to_tmpfs();
@ -221,30 +235,30 @@ static int do_tests(int uid, const char *our_path)
copy_fromat_to(ourpath_fd, "validate_cap",
"validate_cap_suidroot");
if (chown("validate_cap_suidroot", 0, -1) != 0)
err(1, "chown");
ksft_exit_fail_msg("chown - %s\n", strerror(errno));
if (chmod("validate_cap_suidroot", S_ISUID | 0700) != 0)
err(1, "chmod");
ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
copy_fromat_to(ourpath_fd, "validate_cap",
"validate_cap_suidnonroot");
if (chown("validate_cap_suidnonroot", uid + 1, -1) != 0)
err(1, "chown");
ksft_exit_fail_msg("chown - %s\n", strerror(errno));
if (chmod("validate_cap_suidnonroot", S_ISUID | 0700) != 0)
err(1, "chmod");
ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
copy_fromat_to(ourpath_fd, "validate_cap",
"validate_cap_sgidroot");
if (chown("validate_cap_sgidroot", -1, 0) != 0)
err(1, "chown");
ksft_exit_fail_msg("chown - %s\n", strerror(errno));
if (chmod("validate_cap_sgidroot", S_ISGID | 0710) != 0)
err(1, "chmod");
ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
copy_fromat_to(ourpath_fd, "validate_cap",
"validate_cap_sgidnonroot");
if (chown("validate_cap_sgidnonroot", -1, gid + 1) != 0)
err(1, "chown");
ksft_exit_fail_msg("chown - %s\n", strerror(errno));
if (chmod("validate_cap_sgidnonroot", S_ISGID | 0710) != 0)
err(1, "chmod");
ksft_exit_fail_msg("chmod - %s\n", strerror(errno));
}
capng_get_caps_process();
@ -252,147 +266,162 @@ static int do_tests(int uid, const char *our_path)
/* Make sure that i starts out clear */
capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
if (capng_apply(CAPNG_SELECT_CAPS) != 0)
err(1, "capng_apply");
ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
if (uid == 0) {
printf("[RUN]\tRoot => ep\n");
ksft_print_msg("[RUN]\tRoot => ep\n");
if (fork_wait())
exec_validate_cap(true, true, false, false);
} else {
printf("[RUN]\tNon-root => no caps\n");
ksft_print_msg("[RUN]\tNon-root => no caps\n");
if (fork_wait())
exec_validate_cap(false, false, false, false);
}
printf("[OK]\tCheck cap_ambient manipulation rules\n");
ksft_print_msg("Check cap_ambient manipulation rules\n");
/* We should not be able to add ambient caps yet. */
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != -1 || errno != EPERM) {
if (errno == EINVAL)
printf("[FAIL]\tPR_CAP_AMBIENT_RAISE isn't supported\n");
ksft_test_result_fail(
"PR_CAP_AMBIENT_RAISE isn't supported\n");
else
printf("[FAIL]\tPR_CAP_AMBIENT_RAISE should have failed eith EPERM on a non-inheritable cap\n");
ksft_test_result_fail(
"PR_CAP_AMBIENT_RAISE should have failed eith EPERM on a non-inheritable cap\n");
return 1;
}
printf("[OK]\tPR_CAP_AMBIENT_RAISE failed on non-inheritable cap\n");
ksft_test_result_pass(
"PR_CAP_AMBIENT_RAISE failed on non-inheritable cap\n");
capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_RAW);
capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_NET_RAW);
capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_NET_RAW);
if (capng_apply(CAPNG_SELECT_CAPS) != 0)
err(1, "capng_apply");
ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_RAW, 0, 0, 0) != -1 || errno != EPERM) {
printf("[FAIL]\tPR_CAP_AMBIENT_RAISE should have failed on a non-permitted cap\n");
ksft_test_result_fail(
"PR_CAP_AMBIENT_RAISE should have failed on a non-permitted cap\n");
return 1;
}
printf("[OK]\tPR_CAP_AMBIENT_RAISE failed on non-permitted cap\n");
ksft_test_result_pass(
"PR_CAP_AMBIENT_RAISE failed on non-permitted cap\n");
capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
if (capng_apply(CAPNG_SELECT_CAPS) != 0)
err(1, "capng_apply");
ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) {
printf("[FAIL]\tPR_CAP_AMBIENT_RAISE should have succeeded\n");
ksft_test_result_fail(
"PR_CAP_AMBIENT_RAISE should have succeeded\n");
return 1;
}
printf("[OK]\tPR_CAP_AMBIENT_RAISE worked\n");
ksft_test_result_pass("PR_CAP_AMBIENT_RAISE worked\n");
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 1) {
printf("[FAIL]\tPR_CAP_AMBIENT_IS_SET is broken\n");
ksft_test_result_fail("PR_CAP_AMBIENT_IS_SET is broken\n");
return 1;
}
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0, 0) != 0)
err(1, "PR_CAP_AMBIENT_CLEAR_ALL");
ksft_exit_fail_msg("PR_CAP_AMBIENT_CLEAR_ALL - %s\n",
strerror(errno));
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) {
printf("[FAIL]\tPR_CAP_AMBIENT_CLEAR_ALL didn't work\n");
ksft_test_result_fail(
"PR_CAP_AMBIENT_CLEAR_ALL didn't work\n");
return 1;
}
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0)
err(1, "PR_CAP_AMBIENT_RAISE");
ksft_exit_fail_msg("PR_CAP_AMBIENT_RAISE - %s\n",
strerror(errno));
capng_update(CAPNG_DROP, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
if (capng_apply(CAPNG_SELECT_CAPS) != 0)
err(1, "capng_apply");
ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0) {
printf("[FAIL]\tDropping I should have dropped A\n");
ksft_test_result_fail("Dropping I should have dropped A\n");
return 1;
}
printf("[OK]\tBasic manipulation appears to work\n");
ksft_test_result_pass("Basic manipulation appears to work\n");
capng_update(CAPNG_ADD, CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE);
if (capng_apply(CAPNG_SELECT_CAPS) != 0)
err(1, "capng_apply");
ksft_exit_fail_msg("capng_apply - %s\n", strerror(errno));
if (uid == 0) {
printf("[RUN]\tRoot +i => eip\n");
ksft_print_msg("[RUN]\tRoot +i => eip\n");
if (fork_wait())
exec_validate_cap(true, true, true, false);
} else {
printf("[RUN]\tNon-root +i => i\n");
ksft_print_msg("[RUN]\tNon-root +i => i\n");
if (fork_wait())
exec_validate_cap(false, false, true, false);
}
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_BIND_SERVICE, 0, 0, 0) != 0)
err(1, "PR_CAP_AMBIENT_RAISE");
ksft_exit_fail_msg("PR_CAP_AMBIENT_RAISE - %s\n",
strerror(errno));
printf("[RUN]\tUID %d +ia => eipa\n", uid);
ksft_print_msg("[RUN]\tUID %d +ia => eipa\n", uid);
if (fork_wait())
exec_validate_cap(true, true, true, true);
/* The remaining tests need real privilege */
if (!have_outer_privilege) {
printf("[SKIP]\tSUID/SGID tests (needs privilege)\n");
ksft_test_result_skip("SUID/SGID tests (needs privilege)\n");
goto done;
}
if (uid == 0) {
printf("[RUN]\tRoot +ia, suidroot => eipa\n");
ksft_print_msg("[RUN]\tRoot +ia, suidroot => eipa\n");
if (fork_wait())
exec_other_validate_cap("./validate_cap_suidroot",
true, true, true, true);
printf("[RUN]\tRoot +ia, suidnonroot => ip\n");
ksft_print_msg("[RUN]\tRoot +ia, suidnonroot => ip\n");
if (fork_wait())
exec_other_validate_cap("./validate_cap_suidnonroot",
false, true, true, false);
printf("[RUN]\tRoot +ia, sgidroot => eipa\n");
ksft_print_msg("[RUN]\tRoot +ia, sgidroot => eipa\n");
if (fork_wait())
exec_other_validate_cap("./validate_cap_sgidroot",
true, true, true, true);
if (fork_wait()) {
printf("[RUN]\tRoot, gid != 0, +ia, sgidroot => eip\n");
ksft_print_msg(
"[RUN]\tRoot, gid != 0, +ia, sgidroot => eip\n");
if (setresgid(1, 1, 1) != 0)
err(1, "setresgid");
ksft_exit_fail_msg("setresgid - %s\n",
strerror(errno));
exec_other_validate_cap("./validate_cap_sgidroot",
true, true, true, false);
}
printf("[RUN]\tRoot +ia, sgidnonroot => eip\n");
ksft_print_msg("[RUN]\tRoot +ia, sgidnonroot => eip\n");
if (fork_wait())
exec_other_validate_cap("./validate_cap_sgidnonroot",
true, true, true, false);
} else {
printf("[RUN]\tNon-root +ia, sgidnonroot => i\n");
exec_other_validate_cap("./validate_cap_sgidnonroot",
ksft_print_msg("[RUN]\tNon-root +ia, sgidnonroot => i\n");
if (fork_wait())
exec_other_validate_cap("./validate_cap_sgidnonroot",
false, false, true, false);
if (fork_wait()) {
printf("[RUN]\tNon-root +ia, sgidroot => i\n");
ksft_print_msg("[RUN]\tNon-root +ia, sgidroot => i\n");
if (setresgid(1, 1, 1) != 0)
err(1, "setresgid");
ksft_exit_fail_msg("setresgid - %s\n",
strerror(errno));
exec_other_validate_cap("./validate_cap_sgidroot",
false, false, true, false);
}
}
done:
ksft_print_cnts();
return nerrs ? 1 : 0;
}
@ -400,23 +429,29 @@ int main(int argc, char **argv)
{
char *tmp1, *tmp2, *our_path;
ksft_print_header();
/* Find our path */
tmp1 = strdup(argv[0]);
if (!tmp1)
err(1, "strdup");
ksft_exit_fail_msg("strdup - %s\n", strerror(errno));
tmp2 = dirname(tmp1);
our_path = strdup(tmp2);
if (!our_path)
err(1, "strdup");
ksft_exit_fail_msg("strdup - %s\n", strerror(errno));
free(tmp1);
mpid = getpid();
if (fork_wait()) {
printf("[RUN]\t+++ Tests with uid == 0 +++\n");
ksft_print_msg("[RUN]\t+++ Tests with uid == 0 +++\n");
return do_tests(0, our_path);
}
ksft_print_msg("==================================================\n");
if (fork_wait()) {
printf("[RUN]\t+++ Tests with uid != 0 +++\n");
ksft_print_msg("[RUN]\t+++ Tests with uid != 0 +++\n");
return do_tests(1, our_path);
}

View File

@ -1,5 +1,4 @@
#include <cap-ng.h>
#include <err.h>
#include <linux/capability.h>
#include <stdbool.h>
#include <string.h>
@ -7,6 +6,8 @@
#include <sys/prctl.h>
#include <sys/auxv.h>
#include "../kselftest.h"
#ifndef PR_CAP_AMBIENT
#define PR_CAP_AMBIENT 47
# define PR_CAP_AMBIENT_IS_SET 1
@ -25,8 +26,10 @@ static bool bool_arg(char **argv, int i)
return false;
else if (!strcmp(argv[i], "1"))
return true;
else
errx(1, "wrong argv[%d]", i);
else {
ksft_exit_fail_msg("wrong argv[%d]\n", i);
return false;
}
}
int main(int argc, char **argv)
@ -39,7 +42,7 @@ int main(int argc, char **argv)
*/
if (argc != 5)
errx(1, "wrong argc");
ksft_exit_fail_msg("wrong argc\n");
#ifdef HAVE_GETAUXVAL
if (getauxval(AT_SECURE))
@ -51,23 +54,26 @@ int main(int argc, char **argv)
capng_get_caps_process();
if (capng_have_capability(CAPNG_EFFECTIVE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 1)) {
printf("[FAIL]\tWrong effective state%s\n", atsec);
ksft_print_msg("Wrong effective state%s\n", atsec);
return 1;
}
if (capng_have_capability(CAPNG_PERMITTED, CAP_NET_BIND_SERVICE) != bool_arg(argv, 2)) {
printf("[FAIL]\tWrong permitted state%s\n", atsec);
ksft_print_msg("Wrong permitted state%s\n", atsec);
return 1;
}
if (capng_have_capability(CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 3)) {
printf("[FAIL]\tWrong inheritable state%s\n", atsec);
ksft_print_msg("Wrong inheritable state%s\n", atsec);
return 1;
}
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != bool_arg(argv, 4)) {
printf("[FAIL]\tWrong ambient state%s\n", atsec);
ksft_print_msg("Wrong ambient state%s\n", atsec);
return 1;
}
printf("[OK]\tCapabilities after execve were correct\n");
ksft_print_msg("%s: Capabilities after execve were correct\n",
"validate_cap:");
return 0;
}

View File

@ -28,6 +28,12 @@ prerequisite()
echo "CPU online/offline summary:"
online_cpus=`cat $SYSFS/devices/system/cpu/online`
online_max=${online_cpus##*-}
if [[ "$online_cpus" = "$online_max" ]]; then
echo "$msg: since there is only one cpu: $online_cpus"
exit 0
fi
echo -e "\t Cpus in online state: $online_cpus"
offline_cpus=`cat $SYSFS/devices/system/cpu/offline`
@ -89,8 +95,10 @@ online_cpu_expect_success()
if ! online_cpu $cpu; then
echo $FUNCNAME $cpu: unexpected fail >&2
exit 1
elif ! cpu_is_online $cpu; then
echo $FUNCNAME $cpu: unexpected offline >&2
exit 1
fi
}
@ -100,8 +108,10 @@ online_cpu_expect_fail()
if online_cpu $cpu 2> /dev/null; then
echo $FUNCNAME $cpu: unexpected success >&2
exit 1
elif ! cpu_is_offline $cpu; then
echo $FUNCNAME $cpu: unexpected online >&2
exit 1
fi
}
@ -111,8 +121,10 @@ offline_cpu_expect_success()
if ! offline_cpu $cpu; then
echo $FUNCNAME $cpu: unexpected fail >&2
exit 1
elif ! cpu_is_offline $cpu; then
echo $FUNCNAME $cpu: unexpected offline >&2
exit 1
fi
}
@ -122,8 +134,10 @@ offline_cpu_expect_fail()
if offline_cpu $cpu 2> /dev/null; then
echo $FUNCNAME $cpu: unexpected success >&2
exit 1
elif ! cpu_is_online $cpu; then
echo $FUNCNAME $cpu: unexpected offline >&2
exit 1
fi
}

View File

@ -8,15 +8,18 @@
# Released under the terms of the GPL v2.
usage() { # errno [message]
[ "$2" ] && echo $2
[ ! -z "$2" ] && echo $2
echo "Usage: ftracetest [options] [testcase(s)] [testcase-directory(s)]"
echo " Options:"
echo " -h|--help Show help message"
echo " -k|--keep Keep passed test logs"
echo " -v|--verbose Increase verbosity of test messages"
echo " -vv Alias of -v -v (Show all results in stdout)"
echo " -vvv Alias of -v -v -v (Show all commands immediately)"
echo " --fail-unsupported Treat UNSUPPORTED as a failure"
echo " -d|--debug Debug mode (trace all shell commands)"
echo " -l|--logdir <dir> Save logs on the <dir>"
echo " If <dir> is -, all logs output in console only"
exit $1
}
@ -47,7 +50,7 @@ parse_opts() { # opts
local OPT_TEST_CASES=
local OPT_TEST_DIR=
while [ "$1" ]; do
while [ ! -z "$1" ]; do
case "$1" in
--help|-h)
usage 0
@ -56,15 +59,20 @@ parse_opts() { # opts
KEEP_LOG=1
shift 1
;;
--verbose|-v|-vv)
--verbose|-v|-vv|-vvv)
VERBOSE=$((VERBOSE + 1))
[ $1 = '-vv' ] && VERBOSE=$((VERBOSE + 1))
[ $1 = '-vvv' ] && VERBOSE=$((VERBOSE + 2))
shift 1
;;
--debug|-d)
DEBUG=1
shift 1
;;
--fail-unsupported)
UNSUPPORTED_RESULT=1
shift 1
;;
--logdir|-l)
LOG_DIR=$2
shift 2
@ -88,7 +96,7 @@ parse_opts() { # opts
;;
esac
done
if [ "$OPT_TEST_CASES" ]; then
if [ ! -z "$OPT_TEST_CASES" ]; then
TEST_CASES=$OPT_TEST_CASES
fi
}
@ -108,6 +116,7 @@ LOG_DIR=$TOP_DIR/logs/`date +%Y%m%d-%H%M%S`/
KEEP_LOG=0
DEBUG=0
VERBOSE=0
UNSUPPORTED_RESULT=0
# Parse command-line options
parse_opts $*
@ -119,14 +128,20 @@ if [ -z "$TRACING_DIR" -o ! -d "$TRACING_DIR" ]; then
fi
# Preparing logs
LOG_FILE=$LOG_DIR/ftracetest.log
mkdir -p $LOG_DIR || errexit "Failed to make a log directory: $LOG_DIR"
date > $LOG_FILE
if [ "x$LOG_DIR" = "x-" ]; then
LOG_FILE=
date
else
LOG_FILE=$LOG_DIR/ftracetest.log
mkdir -p $LOG_DIR || errexit "Failed to make a log directory: $LOG_DIR"
date > $LOG_FILE
fi
prlog() { # messages
echo "$@" | tee -a $LOG_FILE
[ -z "$LOG_FILE" ] && echo "$@" || echo "$@" | tee -a $LOG_FILE
}
catlog() { #file
cat $1 | tee -a $LOG_FILE
[ -z "$LOG_FILE" ] && cat $1 || cat $1 | tee -a $LOG_FILE
}
prlog "=== Ftrace unit tests ==="
@ -187,7 +202,7 @@ eval_result() { # sigval
$UNSUPPORTED)
prlog " [UNSUPPORTED]"
UNSUPPORTED_CASES="$UNSUPPORTED_CASES $CASENO"
return 1 # this is not a bug, but the result should be reported.
return $UNSUPPORTED_RESULT # depends on use case
;;
$XFAIL)
prlog " [XFAIL]"
@ -247,12 +262,20 @@ __run_test() { # testfile
# Run one test case
run_test() { # testfile
local testname=`basename $1`
local testlog=`mktemp $LOG_DIR/${testname}-log.XXXXXX`
if [ ! -z "$LOG_FILE" ] ; then
local testlog=`mktemp $LOG_DIR/${testname}-log.XXXXXX`
else
local testlog=/proc/self/fd/1
fi
export TMPDIR=`mktemp -d /tmp/ftracetest-dir.XXXXXX`
testcase $1
echo "execute$INSTANCE: "$1 > $testlog
SIG_RESULT=0
if [ $VERBOSE -ge 2 ]; then
if [ -z "$LOG_FILE" ]; then
__run_test $1 2>&1
elif [ $VERBOSE -ge 3 ]; then
__run_test $1 | tee -a $testlog 2>&1
elif [ $VERBOSE -eq 2 ]; then
__run_test $1 2>> $testlog | tee -a $testlog
else
__run_test $1 >> $testlog 2>&1
@ -260,9 +283,9 @@ run_test() { # testfile
eval_result $SIG_RESULT
if [ $? -eq 0 ]; then
# Remove test log if the test was done as it was expected.
[ $KEEP_LOG -eq 0 ] && rm $testlog
[ $KEEP_LOG -eq 0 -a ! -z "$LOG_FILE" ] && rm $testlog
else
[ $VERBOSE -ge 1 ] && catlog $testlog
[ $VERBOSE -eq 1 -o $VERBOSE -eq 2 ] && catlog $testlog
TOTAL_RESULT=1
fi
rm -rf $TMPDIR

View File

@ -394,9 +394,11 @@ int main(int argc, char *argv[])
}
}
printf("%s: Test requeue functionality\n", basename(argv[0]));
printf("\tArguments: broadcast=%d locked=%d owner=%d timeout=%ldns\n",
broadcast, locked, owner, timeout_ns);
ksft_print_header();
ksft_print_msg("%s: Test requeue functionality\n", basename(argv[0]));
ksft_print_msg(
"\tArguments: broadcast=%d locked=%d owner=%d timeout=%ldns\n",
broadcast, locked, owner, timeout_ns);
/*
* FIXME: unit_test is obsolete now that we parse options and the

View File

@ -78,7 +78,8 @@ int main(int argc, char *argv[])
}
}
printf("%s: Detect mismatched requeue_pi operations\n",
ksft_print_header();
ksft_print_msg("%s: Detect mismatched requeue_pi operations\n",
basename(argv[0]));
if (pthread_create(&child, NULL, blocking_child, NULL)) {

View File

@ -143,9 +143,10 @@ int main(int argc, char *argv[])
}
}
printf("%s: Test signal handling during requeue_pi\n",
ksft_print_header();
ksft_print_msg("%s: Test signal handling during requeue_pi\n",
basename(argv[0]));
printf("\tArguments: <none>\n");
ksft_print_msg("\tArguments: <none>\n");
sa.sa_handler = handle_signal;
sigemptyset(&sa.sa_mask);

View File

@ -97,8 +97,10 @@ int main(int argc, char **argv)
}
}
printf("%s: Test the futex value of private file mappings in FUTEX_WAIT\n",
basename(argv[0]));
ksft_print_header();
ksft_print_msg(
"%s: Test the futex value of private file mappings in FUTEX_WAIT\n",
basename(argv[0]));
ret = pthread_create(&thr, NULL, thr_futex_wait, NULL);
if (ret < 0) {

View File

@ -68,9 +68,10 @@ int main(int argc, char *argv[])
}
}
printf("%s: Block on a futex and wait for timeout\n",
ksft_print_header();
ksft_print_msg("%s: Block on a futex and wait for timeout\n",
basename(argv[0]));
printf("\tArguments: timeout=%ldns\n", timeout_ns);
ksft_print_msg("\tArguments: timeout=%ldns\n", timeout_ns);
/* initialize timeout */
to.tv_sec = 0;

View File

@ -99,7 +99,8 @@ int main(int argc, char **argv)
exit(1);
}
printf("%s: Test the uninitialized futex value in FUTEX_WAIT\n",
ksft_print_header();
ksft_print_msg("%s: Test the uninitialized futex value in FUTEX_WAIT\n",
basename(argv[0]));

View File

@ -64,7 +64,8 @@ int main(int argc, char *argv[])
}
}
printf("%s: Test the unexpected futex value in FUTEX_WAIT\n",
ksft_print_header();
ksft_print_msg("%s: Test the unexpected futex value in FUTEX_WAIT\n",
basename(argv[0]));
info("Calling futex_wait on f1: %u @ %p with val=%u\n", f1, &f1, f1+1);

View File

@ -109,22 +109,20 @@ void log_verbosity(int level)
*/
void print_result(const char *test_name, int ret)
{
const char *result = "Unknown return code";
switch (ret) {
case RET_PASS:
ksft_inc_pass_cnt();
result = PASS;
break;
ksft_test_result_pass("%s\n", test_name);
ksft_print_cnts();
return;
case RET_ERROR:
result = ERROR;
break;
ksft_test_result_error("%s\n", test_name);
ksft_print_cnts();
return;
case RET_FAIL:
ksft_inc_fail_cnt();
result = FAIL;
break;
ksft_test_result_fail("%s\n", test_name);
ksft_print_cnts();
return;
}
printf("selftests: %s [%s]\n", test_name, result);
}
/* log level macros */

View File

@ -19,7 +19,8 @@
#define KSFT_FAIL 1
#define KSFT_XFAIL 2
#define KSFT_XPASS 3
#define KSFT_SKIP 4
/* Treat skip as pass */
#define KSFT_SKIP KSFT_PASS
/* counters */
struct ksft_count {
@ -28,6 +29,7 @@ struct ksft_count {
unsigned int ksft_xfail;
unsigned int ksft_xpass;
unsigned int ksft_xskip;
unsigned int ksft_error;
};
static struct ksft_count ksft_cnt;
@ -36,7 +38,7 @@ static inline int ksft_test_num(void)
{
return ksft_cnt.ksft_pass + ksft_cnt.ksft_fail +
ksft_cnt.ksft_xfail + ksft_cnt.ksft_xpass +
ksft_cnt.ksft_xskip;
ksft_cnt.ksft_xskip + ksft_cnt.ksft_error;
}
static inline void ksft_inc_pass_cnt(void) { ksft_cnt.ksft_pass++; }
@ -44,6 +46,14 @@ static inline void ksft_inc_fail_cnt(void) { ksft_cnt.ksft_fail++; }
static inline void ksft_inc_xfail_cnt(void) { ksft_cnt.ksft_xfail++; }
static inline void ksft_inc_xpass_cnt(void) { ksft_cnt.ksft_xpass++; }
static inline void ksft_inc_xskip_cnt(void) { ksft_cnt.ksft_xskip++; }
static inline void ksft_inc_error_cnt(void) { ksft_cnt.ksft_error++; }
static inline int ksft_get_pass_cnt(void) { return ksft_cnt.ksft_pass; }
static inline int ksft_get_fail_cnt(void) { return ksft_cnt.ksft_fail; }
static inline int ksft_get_xfail_cnt(void) { return ksft_cnt.ksft_xfail; }
static inline int ksft_get_xpass_cnt(void) { return ksft_cnt.ksft_xpass; }
static inline int ksft_get_xskip_cnt(void) { return ksft_cnt.ksft_xskip; }
static inline int ksft_get_error_cnt(void) { return ksft_cnt.ksft_error; }
static inline void ksft_print_header(void)
{
@ -52,6 +62,10 @@ static inline void ksft_print_header(void)
static inline void ksft_print_cnts(void)
{
printf("Pass %d Fail %d Xfail %d Xpass %d Skip %d Error %d\n",
ksft_cnt.ksft_pass, ksft_cnt.ksft_fail,
ksft_cnt.ksft_xfail, ksft_cnt.ksft_xpass,
ksft_cnt.ksft_xskip, ksft_cnt.ksft_error);
printf("1..%d\n", ksft_test_num());
}
@ -101,6 +115,18 @@ static inline void ksft_test_result_skip(const char *msg, ...)
va_end(args);
}
static inline void ksft_test_result_error(const char *msg, ...)
{
va_list args;
ksft_cnt.ksft_error++;
va_start(args, msg);
printf("not ok %d # error ", ksft_test_num());
vprintf(msg, args);
va_end(args);
}
static inline int ksft_exit_pass(void)
{
ksft_print_cnts();

View File

@ -51,6 +51,9 @@
#define __KSELFTEST_HARNESS_H
#define _GNU_SOURCE
#include <asm/types.h>
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@ -84,6 +87,14 @@
* E.g., #define TH_LOG_ENABLED 1
*
* If no definition is provided, logging is enabled by default.
*
* If there is no way to print an error message for the process running the
* test (e.g. not allowed to write to stderr), it is still possible to get the
* ASSERT_* number for which the test failed. This behavior can be enabled by
* writing `_metadata->no_print = true;` before the check sequence that is
* unable to print. When an error occur, instead of printing an error message
* and calling `abort(3)`, the test process call `_exit(2)` with the assert
* number as argument, which is then printed by the parent process.
*/
#define TH_LOG(fmt, ...) do { \
if (TH_LOG_ENABLED) \
@ -555,12 +566,18 @@
* return while still providing an optional block to the API consumer.
*/
#define OPTIONAL_HANDLER(_assert) \
for (; _metadata->trigger; _metadata->trigger = __bail(_assert))
for (; _metadata->trigger; _metadata->trigger = \
__bail(_assert, _metadata->no_print, _metadata->step))
#define __INC_STEP(_metadata) \
if (_metadata->passed && _metadata->step < 255) \
_metadata->step++;
#define __EXPECT(_expected, _seen, _t, _assert) do { \
/* Avoid multiple evaluation of the cases */ \
__typeof__(_expected) __exp = (_expected); \
__typeof__(_seen) __seen = (_seen); \
if (_assert) __INC_STEP(_metadata); \
if (!(__exp _t __seen)) { \
unsigned long long __exp_print = (uintptr_t)__exp; \
unsigned long long __seen_print = (uintptr_t)__seen; \
@ -576,6 +593,7 @@
#define __EXPECT_STR(_expected, _seen, _t, _assert) do { \
const char *__exp = (_expected); \
const char *__seen = (_seen); \
if (_assert) __INC_STEP(_metadata); \
if (!(strcmp(__exp, __seen) _t 0)) { \
__TH_LOG("Expected '%s' %s '%s'.", __exp, #_t, __seen); \
_metadata->passed = 0; \
@ -590,6 +608,8 @@ struct __test_metadata {
int termsig;
int passed;
int trigger; /* extra handler after the evaluation */
__u8 step;
bool no_print; /* manual trigger when TH_LOG_STREAM is not available */
struct __test_metadata *prev, *next;
};
@ -634,10 +654,13 @@ static inline void __register_test(struct __test_metadata *t)
}
}
static inline int __bail(int for_realz)
static inline int __bail(int for_realz, bool no_print, __u8 step)
{
if (for_realz)
if (for_realz) {
if (no_print)
_exit(step);
abort();
}
return 0;
}
@ -655,18 +678,24 @@ void __run_test(struct __test_metadata *t)
t->passed = 0;
} else if (child_pid == 0) {
t->fn(t);
_exit(t->passed);
/* return the step that failed or 0 */
_exit(t->passed ? 0 : t->step);
} else {
/* TODO(wad) add timeout support. */
waitpid(child_pid, &status, 0);
if (WIFEXITED(status)) {
t->passed = t->termsig == -1 ? WEXITSTATUS(status) : 0;
t->passed = t->termsig == -1 ? !WEXITSTATUS(status) : 0;
if (t->termsig != -1) {
fprintf(TH_LOG_STREAM,
"%s: Test exited normally "
"instead of by signal (code: %d)\n",
t->name,
WEXITSTATUS(status));
} else if (!t->passed) {
fprintf(TH_LOG_STREAM,
"%s: Test failed at step #%d\n",
t->name,
WEXITSTATUS(status));
}
} else if (WIFSIGNALED(status)) {
t->passed = 0;

View File

@ -11,15 +11,26 @@ TEST_GEN_FILES := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_FILES))
all: $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES)
.ONESHELL:
define RUN_TESTS
@for TEST in $(TEST_GEN_PROGS) $(TEST_PROGS); do \
@test_num=`echo 0`;
@echo "TAP version 13";
@for TEST in $(1); do \
BASENAME_TEST=`basename $$TEST`; \
cd `dirname $$TEST`; (./$$BASENAME_TEST && echo "selftests: $$BASENAME_TEST [PASS]") || echo "selftests: $$BASENAME_TEST [FAIL]"; cd -;\
test_num=`echo $$test_num+1 | bc`; \
echo "selftests: $$BASENAME_TEST"; \
echo "========================================"; \
if [ ! -x $$BASENAME_TEST ]; then \
echo "selftests: Warning: file $$BASENAME_TEST is not executable, correct this.";\
echo "not ok 1..$$test_num selftests: $$BASENAME_TEST [FAIL]"; \
else \
cd `dirname $$TEST` > /dev/null; (./$$BASENAME_TEST && echo "ok 1..$$test_num selftests: $$BASENAME_TEST [PASS]") || echo "not ok 1..$$test_num selftests: $$BASENAME_TEST [FAIL]"; cd - > /dev/null;\
fi; \
done;
endef
run_tests: all
$(RUN_TESTS)
$(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_PROGS))
define INSTALL_RULE
@if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then \

View File

@ -33,7 +33,7 @@
#include <unistd.h>
#define MFD_DEF_SIZE 8192
#define STACK_SIZE 65535
#define STACK_SIZE 65536
static int sys_memfd_create(const char *name,
unsigned int flags)

View File

@ -0,0 +1,3 @@
CONFIG_USER_NS=y
CONFIG_UTS_NS=y
CONFIG_PID_NS=y

View File

@ -0,0 +1,2 @@
logs
*uuid

View File

@ -1,3 +1,4 @@
CFLAGS += -I../../../../usr/include/
TEST_PROGS := testptp
LDLIBS += -lrt
all: $(TEST_PROGS)

View File

@ -107,7 +107,7 @@ TEST(mode_strict_support)
ASSERT_EQ(0, ret) {
TH_LOG("Kernel does not support CONFIG_SECCOMP");
}
syscall(__NR_exit, 1);
syscall(__NR_exit, 0);
}
TEST_SIGNAL(mode_strict_cannot_call_prctl, SIGKILL)

View File

@ -17,6 +17,8 @@
#include <assert.h>
#include <errno.h>
#include "../kselftest.h"
#ifndef SS_AUTODISARM
#define SS_AUTODISARM (1U << 31)
#endif
@ -41,8 +43,7 @@ void my_usr1(int sig, siginfo_t *si, void *u)
if (sp < (unsigned long)sstack ||
sp >= (unsigned long)sstack + SIGSTKSZ) {
printf("[FAIL]\tSP is not on sigaltstack\n");
exit(EXIT_FAILURE);
ksft_exit_fail_msg("SP is not on sigaltstack\n");
}
/* put some data on stack. other sighandler will try to overwrite it */
aa = alloca(1024);
@ -50,21 +51,22 @@ void my_usr1(int sig, siginfo_t *si, void *u)
p = (struct stk_data *)(aa + 512);
strcpy(p->msg, msg);
p->flag = 1;
printf("[RUN]\tsignal USR1\n");
ksft_print_msg("[RUN]\tsignal USR1\n");
err = sigaltstack(NULL, &stk);
if (err) {
perror("[FAIL]\tsigaltstack()");
ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (stk.ss_flags != SS_DISABLE)
printf("[FAIL]\tss_flags=%x, should be SS_DISABLE\n",
ksft_test_result_fail("tss_flags=%x, should be SS_DISABLE\n",
stk.ss_flags);
else
printf("[OK]\tsigaltstack is disabled in sighandler\n");
ksft_test_result_pass(
"sigaltstack is disabled in sighandler\n");
swapcontext(&sc, &uc);
printf("%s\n", p->msg);
ksft_print_msg("%s\n", p->msg);
if (!p->flag) {
printf("[RUN]\tAborting\n");
ksft_exit_skip("[RUN]\tAborting\n");
exit(EXIT_FAILURE);
}
}
@ -74,13 +76,13 @@ void my_usr2(int sig, siginfo_t *si, void *u)
char *aa;
struct stk_data *p;
printf("[RUN]\tsignal USR2\n");
ksft_print_msg("[RUN]\tsignal USR2\n");
aa = alloca(1024);
/* dont run valgrind on this */
/* try to find the data stored by previous sighandler */
p = memmem(aa, 1024, msg, strlen(msg));
if (p) {
printf("[FAIL]\tsigaltstack re-used\n");
ksft_test_result_fail("sigaltstack re-used\n");
/* corrupt the data */
strcpy(p->msg, msg2);
/* tell other sighandler that his data is corrupted */
@ -90,7 +92,7 @@ void my_usr2(int sig, siginfo_t *si, void *u)
static void switch_fn(void)
{
printf("[RUN]\tswitched to user ctx\n");
ksft_print_msg("[RUN]\tswitched to user ctx\n");
raise(SIGUSR2);
setcontext(&sc);
}
@ -101,6 +103,8 @@ int main(void)
stack_t stk;
int err;
ksft_print_header();
sigemptyset(&act.sa_mask);
act.sa_flags = SA_ONSTACK | SA_SIGINFO;
act.sa_sigaction = my_usr1;
@ -110,19 +114,20 @@ int main(void)
sstack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
if (sstack == MAP_FAILED) {
perror("mmap()");
ksft_exit_fail_msg("mmap() - %s\n", strerror(errno));
return EXIT_FAILURE;
}
err = sigaltstack(NULL, &stk);
if (err) {
perror("[FAIL]\tsigaltstack()");
ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (stk.ss_flags == SS_DISABLE) {
printf("[OK]\tInitial sigaltstack state was SS_DISABLE\n");
ksft_test_result_pass(
"Initial sigaltstack state was SS_DISABLE\n");
} else {
printf("[FAIL]\tInitial sigaltstack state was %x; "
ksft_exit_fail_msg("Initial sigaltstack state was %x; "
"should have been SS_DISABLE\n", stk.ss_flags);
return EXIT_FAILURE;
}
@ -133,7 +138,8 @@ int main(void)
err = sigaltstack(&stk, NULL);
if (err) {
if (errno == EINVAL) {
printf("[NOTE]\tThe running kernel doesn't support SS_AUTODISARM\n");
ksft_exit_skip(
"[NOTE]\tThe running kernel doesn't support SS_AUTODISARM\n");
/*
* If test cases for the !SS_AUTODISARM variant were
* added, we could still run them. We don't have any
@ -142,7 +148,9 @@ int main(void)
*/
return 0;
} else {
perror("[FAIL]\tsigaltstack(SS_ONSTACK | SS_AUTODISARM)");
ksft_exit_fail_msg(
"sigaltstack(SS_ONSTACK | SS_AUTODISARM) %s\n",
strerror(errno));
return EXIT_FAILURE;
}
}
@ -150,7 +158,7 @@ int main(void)
ustack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
if (ustack == MAP_FAILED) {
perror("mmap()");
ksft_exit_fail_msg("mmap() - %s\n", strerror(errno));
return EXIT_FAILURE;
}
getcontext(&uc);
@ -162,16 +170,17 @@ int main(void)
err = sigaltstack(NULL, &stk);
if (err) {
perror("[FAIL]\tsigaltstack()");
ksft_exit_fail_msg("sigaltstack() - %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (stk.ss_flags != SS_AUTODISARM) {
printf("[FAIL]\tss_flags=%x, should be SS_AUTODISARM\n",
ksft_exit_fail_msg("ss_flags=%x, should be SS_AUTODISARM\n",
stk.ss_flags);
exit(EXIT_FAILURE);
}
printf("[OK]\tsigaltstack is still SS_AUTODISARM after signal\n");
ksft_test_result_pass(
"sigaltstack is still SS_AUTODISARM after signal\n");
printf("[OK]\tTest passed\n");
ksft_exit_pass();
return 0;
}

View File

@ -0,0 +1 @@
default_file_splice_read

View File

@ -1,7 +1,4 @@
TEST_PROGS := default_file_splice_read.sh
EXTRA := default_file_splice_read
all: $(TEST_PROGS) $(EXTRA)
TEST_GEN_PROGS_EXTENDED := default_file_splice_read
include ../lib.mk
EXTRA_CLEAN := $(EXTRA)

View File

@ -31,62 +31,83 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
#include "../kselftest.h"
#include "synctest.h"
static int run_test(int (*test)(void), char *name)
{
int result;
pid_t childpid;
int ret;
fflush(stdout);
childpid = fork();
if (childpid) {
waitpid(childpid, &result, 0);
if (WIFEXITED(result))
return WEXITSTATUS(result);
if (WIFEXITED(result)) {
ret = WEXITSTATUS(result);
if (!ret)
ksft_test_result_pass("[RUN]\t%s\n", name);
else
ksft_test_result_fail("[RUN]\t%s\n", name);
return ret;
}
return 1;
}
printf("[RUN]\tExecuting %s\n", name);
exit(test());
}
static int sync_api_supported(void)
static void sync_api_supported(void)
{
struct stat sbuf;
int ret;
return 0 == stat("/sys/kernel/debug/sync/sw_sync", &sbuf);
ret = stat("/sys/kernel/debug/sync/sw_sync", &sbuf);
if (!ret)
return;
if (errno == ENOENT)
ksft_exit_skip("Sync framework not supported by kernel\n");
if (errno == EACCES)
ksft_exit_skip("Run Sync test as root.\n");
ksft_exit_fail_msg("stat failed on /sys/kernel/debug/sync/sw_sync: %s",
strerror(errno));
}
int main(void)
{
int err = 0;
int err;
if (!sync_api_supported()) {
printf("SKIP: Sync framework not supported by kernel\n");
return 0;
}
ksft_print_header();
printf("[RUN]\tTesting sync framework\n");
sync_api_supported();
err += RUN_TEST(test_alloc_timeline);
err += RUN_TEST(test_alloc_fence);
err += RUN_TEST(test_alloc_fence_negative);
ksft_print_msg("[RUN]\tTesting sync framework\n");
err += RUN_TEST(test_fence_one_timeline_wait);
err += RUN_TEST(test_fence_one_timeline_merge);
err += RUN_TEST(test_fence_merge_same_fence);
err += RUN_TEST(test_fence_multi_timeline_wait);
err += RUN_TEST(test_stress_two_threads_shared_timeline);
err += RUN_TEST(test_consumer_stress_multi_producer_single_consumer);
err += RUN_TEST(test_merge_stress_random_merge);
RUN_TEST(test_alloc_timeline);
RUN_TEST(test_alloc_fence);
RUN_TEST(test_alloc_fence_negative);
RUN_TEST(test_fence_one_timeline_wait);
RUN_TEST(test_fence_one_timeline_merge);
RUN_TEST(test_fence_merge_same_fence);
RUN_TEST(test_fence_multi_timeline_wait);
RUN_TEST(test_stress_two_threads_shared_timeline);
RUN_TEST(test_consumer_stress_multi_producer_single_consumer);
RUN_TEST(test_merge_stress_random_merge);
err = ksft_get_fail_cnt();
if (err)
printf("[FAIL]\tsync errors: %d\n", err);
else
printf("[OK]\tsync\n");
ksft_exit_fail_msg("%d out of %d sync tests failed\n",
err, ksft_test_num());
return !!err;
/* need this return to keep gcc happy */
return ksft_exit_pass();
}

View File

@ -29,10 +29,11 @@
#define SELFTESTS_SYNCTEST_H
#include <stdio.h>
#include "../kselftest.h"
#define ASSERT(cond, msg) do { \
if (!(cond)) { \
printf("[ERROR]\t%s", (msg)); \
ksft_print_msg("[ERROR]\t%s", (msg)); \
return 1; \
} \
} while (0)

View File

@ -1,5 +1,4 @@
BUILD_FLAGS = -DKTEST
CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS)
CFLAGS += -O3 -Wl,-no-as-needed -Wall
LDFLAGS += -lrt -lpthread -lm
# these are all "safe" tests that don't modify
@ -7,9 +6,11 @@ LDFLAGS += -lrt -lpthread -lm
TEST_GEN_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \
inconsistency-check raw_skew threadtest rtctest
TEST_GEN_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex adjtick change_skew \
DESTRUCTIVE_TESTS = alarmtimer-suspend valid-adjtimex adjtick change_skew \
skew_consistency clocksource-switch freq-step leap-a-day \
leapcrash set-tai set-2038 set-tz rtctest_setdate
leapcrash set-tai set-2038 set-tz
TEST_GEN_PROGS_EXTENDED = $(DESTRUCTIVE_TESTS) rtctest_setdate
include ../lib.mk
@ -18,16 +19,4 @@ include ../lib.mk
# and may modify the system time or trigger
# other behavior like suspend
run_destructive_tests: run_tests
./alarmtimer-suspend
./valid-adjtimex
./adjtick
./change_skew
./skew_consistency
./clocksource-switch
./freq-step
./leap-a-day -s -i 10
./leapcrash
./set-tz
./set-tai
./set-2038
$(call RUN_TESTS, $(DESTRUCTIVE_TESTS))

View File

@ -23,18 +23,7 @@
#include <sys/timex.h>
#include <time.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
#define CLOCK_MONOTONIC_RAW 4

View File

@ -28,18 +28,7 @@
#include <signal.h>
#include <stdlib.h>
#include <pthread.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 1

View File

@ -28,18 +28,7 @@
#include <sys/time.h>
#include <sys/timex.h>
#include <time.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
#define NSEC_PER_SEC 1000000000LL

View File

@ -34,18 +34,7 @@
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
int get_clocksources(char list[][30])
@ -61,7 +50,7 @@ int get_clocksources(char list[][30])
close(fd);
for (i = 0; i < 30; i++)
for (i = 0; i < 10; i++)
list[i][0] = '\0';
head = buf;

View File

@ -28,18 +28,7 @@
#include <sys/timex.h>
#include <string.h>
#include <signal.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
#define CALLS_PER_LOOP 64
#define NSEC_PER_SEC 1000000000ULL

View File

@ -48,18 +48,7 @@
#include <string.h>
#include <signal.h>
#include <unistd.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
#define NSEC_PER_SEC 1000000000ULL
#define CLOCK_TAI 11
@ -190,18 +179,18 @@ int main(int argc, char **argv)
struct sigevent se;
struct sigaction act;
int signum = SIGRTMAX;
int settime = 0;
int settime = 1;
int tai_time = 0;
int insert = 1;
int iterations = -1;
int iterations = 10;
int opt;
/* Process arguments */
while ((opt = getopt(argc, argv, "sti:")) != -1) {
switch (opt) {
case 's':
printf("Setting time to speed up testing\n");
settime = 1;
case 'w':
printf("Only setting leap-flag, not changing time. It could take up to a day for leap to trigger.\n");
settime = 0;
break;
case 'i':
iterations = atoi(optarg);
@ -210,9 +199,10 @@ int main(int argc, char **argv)
tai_time = 1;
break;
default:
printf("Usage: %s [-s] [-i <iterations>]\n", argv[0]);
printf(" -s: Set time to right before leap second each iteration\n");
printf(" -i: Number of iterations\n");
printf("Usage: %s [-w] [-i <iterations>]\n", argv[0]);
printf(" -w: Set flag and wait for leap second each iteration");
printf(" (default sets time to right before leapsecond)\n");
printf(" -i: Number of iterations (-1 = infinite, default is 10)\n");
printf(" -t: Print TAI time\n");
exit(-1);
}

View File

@ -22,20 +22,7 @@
#include <sys/timex.h>
#include <string.h>
#include <signal.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
/* clear NTP time_status & time_state */
int clear_time_state(void)

View File

@ -29,18 +29,7 @@
#include <signal.h>
#include <errno.h>
#include <mqueue.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
#define NSEC_PER_SEC 1000000000ULL

View File

@ -27,18 +27,7 @@
#include <sys/timex.h>
#include <string.h>
#include <signal.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
#define NSEC_PER_SEC 1000000000ULL

View File

@ -24,18 +24,7 @@
#include <sys/timex.h>
#include <string.h>
#include <signal.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
#define NSEC_PER_SEC 1000000000ULL

View File

@ -25,19 +25,7 @@
#include <sys/time.h>
#include <sys/timex.h>
#include <time.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
#define CLOCK_MONOTONIC_RAW 4
#define NSEC_PER_SEC 1000000000LL

View File

@ -221,6 +221,11 @@ test_READ:
/* Read the current alarm settings */
retval = ioctl(fd, RTC_ALM_READ, &rtc_tm);
if (retval == -1) {
if (errno == EINVAL) {
fprintf(stderr,
"\n...EINVAL reading current alarm setting.\n");
goto test_PIE;
}
perror("RTC_ALM_READ ioctl");
exit(errno);
}
@ -231,7 +236,7 @@ test_READ:
/* Enable alarm interrupts */
retval = ioctl(fd, RTC_AIE_ON, 0);
if (retval == -1) {
if (errno == EINVAL) {
if (errno == EINVAL || errno == EIO) {
fprintf(stderr,
"\n...Alarm IRQs not supported.\n");
goto test_PIE;

View File

@ -27,18 +27,7 @@
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
#define NSEC_PER_SEC 1000000000LL

View File

@ -23,18 +23,7 @@
#include <string.h>
#include <signal.h>
#include <unistd.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
int set_tai(int offset)
{

View File

@ -28,18 +28,7 @@
#include <signal.h>
#include <stdlib.h>
#include <pthread.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 1

View File

@ -23,18 +23,7 @@
#include <string.h>
#include <signal.h>
#include <unistd.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
int set_tz(int min, int dst)
{

View File

@ -35,18 +35,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
#define NSEC_PER_SEC 1000000000LL

View File

@ -21,19 +21,7 @@
#include <stdlib.h>
#include <sys/time.h>
#include <pthread.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
/* serializes shared list access */
pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER;

View File

@ -32,18 +32,7 @@
#include <string.h>
#include <signal.h>
#include <unistd.h>
#ifdef KTEST
#include "../kselftest.h"
#else
static inline int ksft_exit_pass(void)
{
exit(0);
}
static inline int ksft_exit_fail(void)
{
exit(1);
}
#endif
#define NSEC_PER_SEC 1000000000LL
#define USEC_PER_SEC 1000000LL

View File

@ -9,12 +9,25 @@
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/watchdog.h>
#define DEFAULT_PING_RATE 1
int fd;
const char v = 'V';
static const char sopts[] = "bdehp:t:";
static const struct option lopts[] = {
{"bootstatus", no_argument, NULL, 'b'},
{"disable", no_argument, NULL, 'd'},
{"enable", no_argument, NULL, 'e'},
{"help", no_argument, NULL, 'h'},
{"pingrate", required_argument, NULL, 'p'},
{"timeout", required_argument, NULL, 't'},
{NULL, no_argument, NULL, 0x0}
};
/*
* This function simply sends an IOCTL to the driver, which in turn ticks
@ -23,12 +36,12 @@ const char v = 'V';
*/
static void keep_alive(void)
{
int dummy;
int ret;
int dummy;
int ret;
ret = ioctl(fd, WDIOC_KEEPALIVE, &dummy);
if (!ret)
printf(".");
ret = ioctl(fd, WDIOC_KEEPALIVE, &dummy);
if (!ret)
printf(".");
}
/*
@ -38,75 +51,110 @@ static void keep_alive(void)
static void term(int sig)
{
int ret = write(fd, &v, 1);
int ret = write(fd, &v, 1);
close(fd);
if (ret < 0)
printf("\nStopping watchdog ticks failed (%d)...\n", errno);
else
printf("\nStopping watchdog ticks...\n");
exit(0);
close(fd);
if (ret < 0)
printf("\nStopping watchdog ticks failed (%d)...\n", errno);
else
printf("\nStopping watchdog ticks...\n");
exit(0);
}
static void usage(char *progname)
{
printf("Usage: %s [options]\n", progname);
printf(" -b, --bootstatus Get last boot status (Watchdog/POR)\n");
printf(" -d, --disable Turn off the watchdog timer\n");
printf(" -e, --enable Turn on the watchdog timer\n");
printf(" -h, --help Print the help message\n");
printf(" -p, --pingrate=P Set ping rate to P seconds (default %d)\n", DEFAULT_PING_RATE);
printf(" -t, --timeout=T Set timeout to T seconds\n");
printf("\n");
printf("Parameters are parsed left-to-right in real-time.\n");
printf("Example: %s -d -t 10 -p 5 -e\n", progname);
}
int main(int argc, char *argv[])
{
int flags;
unsigned int ping_rate = 1;
int ret;
int i;
int flags;
unsigned int ping_rate = DEFAULT_PING_RATE;
int ret;
int c;
int oneshot = 0;
setbuf(stdout, NULL);
setbuf(stdout, NULL);
fd = open("/dev/watchdog", O_WRONLY);
fd = open("/dev/watchdog", O_WRONLY);
if (fd == -1) {
printf("Watchdog device not enabled.\n");
exit(-1);
}
if (fd == -1) {
printf("Watchdog device not enabled.\n");
exit(-1);
}
for (i = 1; i < argc; i++) {
if (!strncasecmp(argv[i], "-d", 2)) {
flags = WDIOS_DISABLECARD;
ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
if (!ret)
printf("Watchdog card disabled.\n");
} else if (!strncasecmp(argv[i], "-e", 2)) {
flags = WDIOS_ENABLECARD;
ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
if (!ret)
printf("Watchdog card enabled.\n");
} else if (!strncasecmp(argv[i], "-t", 2) && argv[2]) {
flags = atoi(argv[i + 1]);
ret = ioctl(fd, WDIOC_SETTIMEOUT, &flags);
if (!ret)
printf("Watchdog timeout set to %u seconds.\n", flags);
i++;
} else if (!strncasecmp(argv[i], "-p", 2) && argv[2]) {
ping_rate = strtoul(argv[i + 1], NULL, 0);
printf("Watchdog ping rate set to %u seconds.\n", ping_rate);
i++;
} else {
printf("-d to disable, -e to enable, -t <n> to set "
"the timeout,\n-p <n> to set the ping rate, and ");
printf("run by itself to tick the card.\n");
printf("Parameters are parsed left-to-right in real-time.\n");
printf("Example: %s -d -t 10 -p 5 -e\n", argv[0]);
goto end;
}
}
while ((c = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
switch (c) {
case 'b':
flags = 0;
oneshot = 1;
ret = ioctl(fd, WDIOC_GETBOOTSTATUS, &flags);
if (!ret)
printf("Last boot is caused by: %s.\n", (flags != 0) ?
"Watchdog" : "Power-On-Reset");
else
printf("WDIOC_GETBOOTSTATUS errno '%s'\n", strerror(errno));
break;
case 'd':
flags = WDIOS_DISABLECARD;
ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
if (!ret)
printf("Watchdog card disabled.\n");
else
printf("WDIOS_DISABLECARD errno '%s'\n", strerror(errno));
break;
case 'e':
flags = WDIOS_ENABLECARD;
ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
if (!ret)
printf("Watchdog card enabled.\n");
else
printf("WDIOS_ENABLECARD errno '%s'\n", strerror(errno));
break;
case 'p':
ping_rate = strtoul(optarg, NULL, 0);
if (!ping_rate)
ping_rate = DEFAULT_PING_RATE;
printf("Watchdog ping rate set to %u seconds.\n", ping_rate);
break;
case 't':
flags = strtoul(optarg, NULL, 0);
ret = ioctl(fd, WDIOC_SETTIMEOUT, &flags);
if (!ret)
printf("Watchdog timeout set to %u seconds.\n", flags);
else
printf("WDIOC_SETTIMEOUT errno '%s'\n", strerror(errno));
break;
default:
usage(argv[0]);
goto end;
}
}
printf("Watchdog Ticking Away!\n");
if (oneshot)
goto end;
signal(SIGINT, term);
printf("Watchdog Ticking Away!\n");
while(1) {
keep_alive();
sleep(ping_rate);
}
signal(SIGINT, term);
while (1) {
keep_alive();
sleep(ping_rate);
}
end:
ret = write(fd, &v, 1);
if (ret < 0)
printf("Stopping watchdog ticks failed (%d)...\n", errno);
close(fd);
return 0;
ret = write(fd, &v, 1);
if (ret < 0)
printf("Stopping watchdog ticks failed (%d)...\n", errno);
close(fd);
return 0;
}