| /* |
| * Check decoding of setitimer and getitimer syscalls. |
| * |
| * Copyright (c) 2015-2017 Dmitry V. Levin <[email protected]> |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "tests.h" |
| #include <stdio.h> |
| #include <stdint.h> |
| #include <sys/time.h> |
| #include <unistd.h> |
| #include <asm/unistd.h> |
| |
| int |
| main(void) |
| { |
| static const struct itimerval new = { |
| .it_interval = { 0xc0de1, 0xc0de2 }, |
| .it_value = { 0xc0de3, 0xc0de4 } |
| }; |
| static const kernel_ulong_t long_timer = |
| F8ILL_KULONG_MASK | ITIMER_REAL; |
| static const kernel_ulong_t bogus_timer = |
| (kernel_ulong_t) 0xfacefeeddeadbeefULL; |
| |
| TAIL_ALLOC_OBJECT_CONST_PTR(struct itimerval, p_old); |
| struct itimerval *const p_new = tail_memdup(&new, sizeof(new)); |
| void *const efault = tail_alloc(sizeof(new) - 8); |
| long rc; |
| |
| if (setitimer(ITIMER_REAL, p_new, NULL)) |
| perror_msg_and_skip("setitimer"); |
| printf("setitimer(ITIMER_REAL" |
| ", {it_interval={tv_sec=%lld, tv_usec=%llu}" |
| ", it_value={tv_sec=%lld, tv_usec=%llu}}" |
| ", NULL) = 0\n", |
| (long long) new.it_interval.tv_sec, |
| zero_extend_signed_to_ull(new.it_interval.tv_usec), |
| (long long) new.it_value.tv_sec, |
| zero_extend_signed_to_ull(new.it_value.tv_usec)); |
| |
| fill_memory(p_old, sizeof(*p_old)); |
| if (getitimer(ITIMER_REAL, p_old)) |
| perror_msg_and_skip("getitimer"); |
| printf("getitimer(ITIMER_REAL" |
| ", {it_interval={tv_sec=%lld, tv_usec=%llu}" |
| ", it_value={tv_sec=%lld, tv_usec=%llu}}) = 0\n", |
| (long long) p_old->it_interval.tv_sec, |
| zero_extend_signed_to_ull(p_old->it_interval.tv_usec), |
| (long long) p_old->it_value.tv_sec, |
| zero_extend_signed_to_ull(p_old->it_value.tv_usec)); |
| |
| fill_memory(p_old, sizeof(*p_old)); |
| setitimer(ITIMER_REAL, p_new, p_old); |
| printf("setitimer(ITIMER_REAL" |
| ", {it_interval={tv_sec=%lld, tv_usec=%llu}" |
| ", it_value={tv_sec=%lld, tv_usec=%llu}}" |
| ", {it_interval={tv_sec=%lld, tv_usec=%llu}" |
| ", it_value={tv_sec=%lld, tv_usec=%llu}}) = 0\n", |
| (long long) new.it_interval.tv_sec, |
| zero_extend_signed_to_ull(new.it_interval.tv_usec), |
| (long long) new.it_value.tv_sec, |
| zero_extend_signed_to_ull(new.it_value.tv_usec), |
| (long long) p_old->it_interval.tv_sec, |
| zero_extend_signed_to_ull(p_old->it_interval.tv_usec), |
| (long long) p_old->it_value.tv_sec, |
| zero_extend_signed_to_ull(p_old->it_value.tv_usec)); |
| |
| rc = getitimer(ITIMER_REAL, efault); |
| printf("getitimer(ITIMER_REAL, %p) = %s\n", efault, sprintrc(rc)); |
| |
| rc = setitimer(ITIMER_REAL, p_new, efault); |
| printf("setitimer(ITIMER_REAL" |
| ", {it_interval={tv_sec=%lld, tv_usec=%llu}" |
| ", it_value={tv_sec=%lld, tv_usec=%llu}}, %p) = %s\n", |
| (long long) new.it_interval.tv_sec, |
| zero_extend_signed_to_ull(new.it_interval.tv_usec), |
| (long long) new.it_value.tv_sec, |
| zero_extend_signed_to_ull(new.it_value.tv_usec), |
| efault, sprintrc(rc)); |
| |
| rc = setitimer(ITIMER_REAL, efault, p_old); |
| printf("setitimer(ITIMER_REAL, %p, %p) = %s\n", |
| efault, p_old, sprintrc(rc)); |
| |
| fill_memory(p_old, sizeof(*p_old)); |
| rc = syscall(__NR_setitimer, long_timer, p_new, p_old); |
| printf("setitimer(ITIMER_REAL" |
| ", {it_interval={tv_sec=%lld, tv_usec=%llu}" |
| ", it_value={tv_sec=%lld, tv_usec=%llu}}" |
| ", {it_interval={tv_sec=%lld, tv_usec=%llu}" |
| ", it_value={tv_sec=%lld, tv_usec=%llu}}) = %s\n", |
| (long long) new.it_interval.tv_sec, |
| zero_extend_signed_to_ull(new.it_interval.tv_usec), |
| (long long) new.it_value.tv_sec, |
| zero_extend_signed_to_ull(new.it_value.tv_usec), |
| (long long) p_old->it_interval.tv_sec, |
| zero_extend_signed_to_ull(p_old->it_interval.tv_usec), |
| (long long) p_old->it_value.tv_sec, |
| zero_extend_signed_to_ull(p_old->it_value.tv_usec), |
| sprintrc(rc)); |
| |
| fill_memory(p_old, sizeof(*p_old)); |
| rc = syscall(__NR_getitimer, long_timer, p_old); |
| printf("getitimer(ITIMER_REAL" |
| ", {it_interval={tv_sec=%lld, tv_usec=%llu}" |
| ", it_value={tv_sec=%lld, tv_usec=%llu}}) = %s\n", |
| (long long) p_old->it_interval.tv_sec, |
| zero_extend_signed_to_ull(p_old->it_interval.tv_usec), |
| (long long) p_old->it_value.tv_sec, |
| zero_extend_signed_to_ull(p_old->it_value.tv_usec), |
| sprintrc(rc)); |
| |
| rc = syscall(__NR_setitimer, bogus_timer, p_new, p_old); |
| printf("setitimer(%#x /* ITIMER_??? */" |
| ", {it_interval={tv_sec=%lld, tv_usec=%llu}" |
| ", it_value={tv_sec=%lld, tv_usec=%llu}}, %p) = %s\n", |
| (int) bogus_timer, |
| (long long) new.it_interval.tv_sec, |
| zero_extend_signed_to_ull(new.it_interval.tv_usec), |
| (long long) new.it_value.tv_sec, |
| zero_extend_signed_to_ull(new.it_value.tv_usec), |
| p_old, sprintrc(rc)); |
| |
| rc = syscall(__NR_getitimer, bogus_timer, p_old); |
| printf("getitimer(%#x /* ITIMER_??? */, %p) = %s\n", |
| (int) bogus_timer, p_old, sprintrc(rc)); |
| |
| if (F8ILL_KULONG_SUPPORTED) { |
| const kernel_ulong_t ill_new = f8ill_ptr_to_kulong(p_new); |
| const kernel_ulong_t ill_old = f8ill_ptr_to_kulong(p_old); |
| |
| rc = syscall(__NR_setitimer, long_timer, ill_new, ill_old); |
| printf("setitimer(ITIMER_REAL, %#llx, %#llx) = %s\n", |
| (unsigned long long) ill_new, |
| (unsigned long long) ill_old, |
| sprintrc(rc)); |
| |
| rc = syscall(__NR_getitimer, long_timer, ill_old); |
| printf("getitimer(ITIMER_REAL, %#llx) = %s\n", |
| (unsigned long long) ill_old, sprintrc(rc)); |
| } |
| |
| p_new->it_interval.tv_sec = 0xdeadbeefU; |
| p_new->it_interval.tv_usec = 0xfacefeedU; |
| p_new->it_value.tv_sec = (time_t) 0xcafef00ddeadbeefLL; |
| p_new->it_value.tv_usec = (suseconds_t) 0xbadc0dedfacefeedLL; |
| |
| rc = setitimer(ITIMER_REAL, p_new, p_old); |
| printf("setitimer(ITIMER_REAL" |
| ", {it_interval={tv_sec=%lld, tv_usec=%llu}" |
| ", it_value={tv_sec=%lld, tv_usec=%llu}}, %p) = %s\n", |
| (long long) p_new->it_interval.tv_sec, |
| zero_extend_signed_to_ull(p_new->it_interval.tv_usec), |
| (long long) p_new->it_value.tv_sec, |
| zero_extend_signed_to_ull(p_new->it_value.tv_usec), |
| p_old, sprintrc(rc)); |
| |
| puts("+++ exited with 0 +++"); |
| return 0; |
| } |