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:
Коммит
6d6218976d
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]));
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
CONFIG_USER_NS=y
|
||||
CONFIG_UTS_NS=y
|
||||
CONFIG_PID_NS=y
|
|
@ -0,0 +1,2 @@
|
|||
logs
|
||||
*uuid
|
|
@ -1,3 +1,4 @@
|
|||
CFLAGS += -I../../../../usr/include/
|
||||
TEST_PROGS := testptp
|
||||
LDLIBS += -lrt
|
||||
all: $(TEST_PROGS)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
default_file_splice_read
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче