1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2019 Linaro Limited. All rights reserved. 4f08c3bdfSopenharmony_ci * Author: Rafael David Tinoco <rafael.tinoco@linaro.org> 5f08c3bdfSopenharmony_ci */ 6f08c3bdfSopenharmony_ci 7f08c3bdfSopenharmony_ci/* 8f08c3bdfSopenharmony_ci * Basic tests for errors of clock_settime(2) on different clock types. 9f08c3bdfSopenharmony_ci */ 10f08c3bdfSopenharmony_ci 11f08c3bdfSopenharmony_ci#include "config.h" 12f08c3bdfSopenharmony_ci#include "time64_variants.h" 13f08c3bdfSopenharmony_ci#include "tst_timer.h" 14f08c3bdfSopenharmony_ci#include "tst_safe_clocks.h" 15f08c3bdfSopenharmony_ci 16f08c3bdfSopenharmony_ci#define DELTA_SEC 10 17f08c3bdfSopenharmony_ci 18f08c3bdfSopenharmony_cistatic void *bad_addr; 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_cistruct test_case { 21f08c3bdfSopenharmony_ci clockid_t type; 22f08c3bdfSopenharmony_ci int exp_err; 23f08c3bdfSopenharmony_ci int replace; 24f08c3bdfSopenharmony_ci long tv_sec; 25f08c3bdfSopenharmony_ci long tv_nsec; 26f08c3bdfSopenharmony_ci}; 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_cistruct test_case tc[] = { 29f08c3bdfSopenharmony_ci { /* case 01: REALTIME: timespec NULL */ 30f08c3bdfSopenharmony_ci .type = CLOCK_REALTIME, 31f08c3bdfSopenharmony_ci .exp_err = EFAULT, 32f08c3bdfSopenharmony_ci .replace = 1, 33f08c3bdfSopenharmony_ci .tv_sec = 0, 34f08c3bdfSopenharmony_ci .tv_nsec = 0, 35f08c3bdfSopenharmony_ci }, 36f08c3bdfSopenharmony_ci { /* case 02: REALTIME: tv_sec = -1 */ 37f08c3bdfSopenharmony_ci .type = CLOCK_REALTIME, 38f08c3bdfSopenharmony_ci .exp_err = EINVAL, 39f08c3bdfSopenharmony_ci .replace = 1, 40f08c3bdfSopenharmony_ci .tv_sec = -1, 41f08c3bdfSopenharmony_ci .tv_nsec = 0, 42f08c3bdfSopenharmony_ci }, 43f08c3bdfSopenharmony_ci { /* case 03: REALTIME: tv_nsec = -1 */ 44f08c3bdfSopenharmony_ci .type = CLOCK_REALTIME, 45f08c3bdfSopenharmony_ci .exp_err = EINVAL, 46f08c3bdfSopenharmony_ci .replace = 1, 47f08c3bdfSopenharmony_ci .tv_sec = 0, 48f08c3bdfSopenharmony_ci .tv_nsec = -1, 49f08c3bdfSopenharmony_ci }, 50f08c3bdfSopenharmony_ci { /* case 04: REALTIME: tv_nsec = 1s+1 */ 51f08c3bdfSopenharmony_ci .type = CLOCK_REALTIME, 52f08c3bdfSopenharmony_ci .exp_err = EINVAL, 53f08c3bdfSopenharmony_ci .replace = 1, 54f08c3bdfSopenharmony_ci .tv_sec = 0, 55f08c3bdfSopenharmony_ci .tv_nsec = NSEC_PER_SEC + 1, 56f08c3bdfSopenharmony_ci }, 57f08c3bdfSopenharmony_ci { /* case 05: MONOTONIC */ 58f08c3bdfSopenharmony_ci .type = CLOCK_MONOTONIC, 59f08c3bdfSopenharmony_ci .exp_err = EINVAL, 60f08c3bdfSopenharmony_ci }, 61f08c3bdfSopenharmony_ci { /* case 06: MAXCLOCK */ 62f08c3bdfSopenharmony_ci .type = MAX_CLOCKS, 63f08c3bdfSopenharmony_ci .exp_err = EINVAL, 64f08c3bdfSopenharmony_ci }, 65f08c3bdfSopenharmony_ci { /* case 07: MAXCLOCK+1 */ 66f08c3bdfSopenharmony_ci .type = MAX_CLOCKS + 1, 67f08c3bdfSopenharmony_ci .exp_err = EINVAL, 68f08c3bdfSopenharmony_ci }, 69f08c3bdfSopenharmony_ci /* Linux specific */ 70f08c3bdfSopenharmony_ci { /* case 08: CLOCK_MONOTONIC_COARSE */ 71f08c3bdfSopenharmony_ci .type = CLOCK_MONOTONIC_COARSE, 72f08c3bdfSopenharmony_ci .exp_err = EINVAL, 73f08c3bdfSopenharmony_ci }, 74f08c3bdfSopenharmony_ci { /* case 09: CLOCK_MONOTONIC_RAW */ 75f08c3bdfSopenharmony_ci .type = CLOCK_MONOTONIC_RAW, 76f08c3bdfSopenharmony_ci .exp_err = EINVAL, 77f08c3bdfSopenharmony_ci }, 78f08c3bdfSopenharmony_ci { /* case 10: CLOCK_BOOTTIME */ 79f08c3bdfSopenharmony_ci .type = CLOCK_BOOTTIME, 80f08c3bdfSopenharmony_ci .exp_err = EINVAL, 81f08c3bdfSopenharmony_ci }, 82f08c3bdfSopenharmony_ci { /* case 11: CLOCK_PROCESS_CPUTIME_ID */ 83f08c3bdfSopenharmony_ci .type = CLOCK_PROCESS_CPUTIME_ID, 84f08c3bdfSopenharmony_ci .exp_err = EINVAL, 85f08c3bdfSopenharmony_ci }, 86f08c3bdfSopenharmony_ci { /* case 12: CLOCK_THREAD_CPUTIME_ID */ 87f08c3bdfSopenharmony_ci .type = CLOCK_THREAD_CPUTIME_ID, 88f08c3bdfSopenharmony_ci .exp_err = EINVAL, 89f08c3bdfSopenharmony_ci }, 90f08c3bdfSopenharmony_ci}; 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_cistatic struct tst_ts spec; 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_cistatic struct time64_variants variants[] = { 95f08c3bdfSopenharmony_ci#if (__NR_clock_settime != __LTP__NR_INVALID_SYSCALL) 96f08c3bdfSopenharmony_ci { .clock_gettime = sys_clock_gettime, .clock_settime = sys_clock_settime, .ts_type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"}, 97f08c3bdfSopenharmony_ci#endif 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_ci#if (__NR_clock_settime64 != __LTP__NR_INVALID_SYSCALL) 100f08c3bdfSopenharmony_ci { .clock_gettime = sys_clock_gettime64, .clock_settime = sys_clock_settime64, .ts_type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"}, 101f08c3bdfSopenharmony_ci#endif 102f08c3bdfSopenharmony_ci}; 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_cistatic void setup(void) 105f08c3bdfSopenharmony_ci{ 106f08c3bdfSopenharmony_ci tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc); 107f08c3bdfSopenharmony_ci 108f08c3bdfSopenharmony_ci bad_addr = tst_get_bad_addr(NULL); 109f08c3bdfSopenharmony_ci} 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_cistatic void verify_clock_settime(unsigned int i) 112f08c3bdfSopenharmony_ci{ 113f08c3bdfSopenharmony_ci struct time64_variants *tv = &variants[tst_variant]; 114f08c3bdfSopenharmony_ci void *ts; 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci spec.type = tv->ts_type; 117f08c3bdfSopenharmony_ci 118f08c3bdfSopenharmony_ci if (tc[i].replace == 0) { 119f08c3bdfSopenharmony_ci TEST(tv->clock_gettime(CLOCK_REALTIME, tst_ts_get(&spec))); 120f08c3bdfSopenharmony_ci if (TST_RET == -1) { 121f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "clock_gettime(2) failed for clock %s", 122f08c3bdfSopenharmony_ci tst_clock_name(CLOCK_REALTIME)); 123f08c3bdfSopenharmony_ci return; 124f08c3bdfSopenharmony_ci } 125f08c3bdfSopenharmony_ci 126f08c3bdfSopenharmony_ci /* add 1 sec to wall clock */ 127f08c3bdfSopenharmony_ci spec = tst_ts_add_us(spec, 1000000); 128f08c3bdfSopenharmony_ci } else { 129f08c3bdfSopenharmony_ci /* use given time spec */ 130f08c3bdfSopenharmony_ci tst_ts_set_sec(&spec, tc[i].tv_sec); 131f08c3bdfSopenharmony_ci tst_ts_set_nsec(&spec, tc[i].tv_nsec); 132f08c3bdfSopenharmony_ci } 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci /* bad pointer case */ 135f08c3bdfSopenharmony_ci if (tc[i].exp_err == EFAULT) 136f08c3bdfSopenharmony_ci ts = bad_addr; 137f08c3bdfSopenharmony_ci else 138f08c3bdfSopenharmony_ci ts = tst_ts_get(&spec); 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_ci TEST(tv->clock_settime(tc[i].type, ts)); 141f08c3bdfSopenharmony_ci 142f08c3bdfSopenharmony_ci if (TST_RET != -1) { 143f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "clock_settime(2): clock %s passed unexpectedly, expected %s", 144f08c3bdfSopenharmony_ci tst_clock_name(tc[i].type), 145f08c3bdfSopenharmony_ci tst_strerrno(tc[i].exp_err)); 146f08c3bdfSopenharmony_ci return; 147f08c3bdfSopenharmony_ci } 148f08c3bdfSopenharmony_ci 149f08c3bdfSopenharmony_ci if (tc[i].exp_err == TST_ERR) { 150f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, "clock_settime(%s): failed as expected", 151f08c3bdfSopenharmony_ci tst_clock_name(tc[i].type)); 152f08c3bdfSopenharmony_ci return; 153f08c3bdfSopenharmony_ci } 154f08c3bdfSopenharmony_ci 155f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "clock_settime(2): clock %s " "expected to fail with %s", 156f08c3bdfSopenharmony_ci tst_clock_name(tc[i].type), tst_strerrno(tc[i].exp_err)); 157f08c3bdfSopenharmony_ci} 158f08c3bdfSopenharmony_ci 159f08c3bdfSopenharmony_cistatic struct tst_test test = { 160f08c3bdfSopenharmony_ci .test = verify_clock_settime, 161f08c3bdfSopenharmony_ci .test_variants = ARRAY_SIZE(variants), 162f08c3bdfSopenharmony_ci .setup = setup, 163f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tc), 164f08c3bdfSopenharmony_ci .needs_root = 1, 165f08c3bdfSopenharmony_ci .restore_wallclock = 1, 166f08c3bdfSopenharmony_ci}; 167