1 /* 2 * Dummy stubs used when CONFIG_POSIX_TIMERS=n 3 * 4 * Created by: Nicolas Pitre, July 2016 5 * Copyright: (C) 2016 Linaro Limited 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 12 #include <linux/linkage.h> 13 #include <linux/kernel.h> 14 #include <linux/sched.h> 15 #include <linux/errno.h> 16 #include <linux/syscalls.h> 17 #include <linux/ktime.h> 18 #include <linux/timekeeping.h> 19 #include <linux/posix-timers.h> 20 #include <linux/compat.h> 21 22 asmlinkage long sys_ni_posix_timers(void) 23 { 24 pr_err_once("process %d (%s) attempted a POSIX timer syscall " 25 "while CONFIG_POSIX_TIMERS is not set\n", 26 current->pid, current->comm); 27 return -ENOSYS; 28 } 29 30 #define SYS_NI(name) SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers) 31 #define COMPAT_SYS_NI(name) SYSCALL_ALIAS(compat_sys_##name, sys_ni_posix_timers) 32 33 SYS_NI(timer_create); 34 SYS_NI(timer_gettime); 35 SYS_NI(timer_getoverrun); 36 SYS_NI(timer_settime); 37 SYS_NI(timer_delete); 38 SYS_NI(clock_adjtime); 39 SYS_NI(getitimer); 40 SYS_NI(setitimer); 41 #ifdef __ARCH_WANT_SYS_ALARM 42 SYS_NI(alarm); 43 #endif 44 COMPAT_SYS_NI(timer_create); 45 COMPAT_SYS_NI(clock_adjtime); 46 COMPAT_SYS_NI(timer_settime); 47 COMPAT_SYS_NI(timer_gettime); 48 COMPAT_SYS_NI(getitimer); 49 COMPAT_SYS_NI(setitimer); 50 51 /* 52 * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC 53 * as it is easy to remain compatible with little code. CLOCK_BOOTTIME 54 * is also included for convenience as at least systemd uses it. 55 */ 56 57 SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, 58 const struct timespec __user *, tp) 59 { 60 struct timespec64 new_tp64; 61 struct timespec new_tp; 62 63 if (which_clock != CLOCK_REALTIME) 64 return -EINVAL; 65 if (copy_from_user(&new_tp, tp, sizeof (*tp))) 66 return -EFAULT; 67 68 new_tp64 = timespec_to_timespec64(new_tp); 69 return do_sys_settimeofday64(&new_tp64, NULL); 70 } 71 72 SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, 73 struct timespec __user *,tp) 74 { 75 struct timespec64 kernel_tp64; 76 struct timespec kernel_tp; 77 78 switch (which_clock) { 79 case CLOCK_REALTIME: ktime_get_real_ts64(&kernel_tp64); break; 80 case CLOCK_MONOTONIC: ktime_get_ts64(&kernel_tp64); break; 81 case CLOCK_BOOTTIME: get_monotonic_boottime64(&kernel_tp64); break; 82 default: return -EINVAL; 83 } 84 85 kernel_tp = timespec64_to_timespec(kernel_tp64); 86 if (copy_to_user(tp, &kernel_tp, sizeof (kernel_tp))) 87 return -EFAULT; 88 return 0; 89 } 90 91 SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct timespec __user *, tp) 92 { 93 struct timespec rtn_tp = { 94 .tv_sec = 0, 95 .tv_nsec = hrtimer_resolution, 96 }; 97 98 switch (which_clock) { 99 case CLOCK_REALTIME: 100 case CLOCK_MONOTONIC: 101 case CLOCK_BOOTTIME: 102 if (copy_to_user(tp, &rtn_tp, sizeof(rtn_tp))) 103 return -EFAULT; 104 return 0; 105 default: 106 return -EINVAL; 107 } 108 } 109 110 SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags, 111 const struct timespec __user *, rqtp, 112 struct timespec __user *, rmtp) 113 { 114 struct timespec64 t64; 115 struct timespec t; 116 117 switch (which_clock) { 118 case CLOCK_REALTIME: 119 case CLOCK_MONOTONIC: 120 case CLOCK_BOOTTIME: 121 break; 122 default: 123 return -EINVAL; 124 } 125 126 if (copy_from_user(&t, rqtp, sizeof (struct timespec))) 127 return -EFAULT; 128 t64 = timespec_to_timespec64(t); 129 if (!timespec64_valid(&t64)) 130 return -EINVAL; 131 if (flags & TIMER_ABSTIME) 132 rmtp = NULL; 133 current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE; 134 current->restart_block.nanosleep.rmtp = rmtp; 135 return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ? 136 HRTIMER_MODE_ABS : HRTIMER_MODE_REL, 137 which_clock); 138 } 139 140 #ifdef CONFIG_COMPAT 141 COMPAT_SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, 142 struct compat_timespec __user *, tp) 143 { 144 struct timespec64 new_tp64; 145 struct timespec new_tp; 146 147 if (which_clock != CLOCK_REALTIME) 148 return -EINVAL; 149 if (compat_get_timespec(&new_tp, tp)) 150 return -EFAULT; 151 152 new_tp64 = timespec_to_timespec64(new_tp); 153 return do_sys_settimeofday64(&new_tp64, NULL); 154 } 155 156 COMPAT_SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, 157 struct compat_timespec __user *,tp) 158 { 159 struct timespec64 kernel_tp64; 160 struct timespec kernel_tp; 161 162 switch (which_clock) { 163 case CLOCK_REALTIME: ktime_get_real_ts64(&kernel_tp64); break; 164 case CLOCK_MONOTONIC: ktime_get_ts64(&kernel_tp64); break; 165 case CLOCK_BOOTTIME: get_monotonic_boottime64(&kernel_tp64); break; 166 default: return -EINVAL; 167 } 168 169 kernel_tp = timespec64_to_timespec(kernel_tp64); 170 if (compat_put_timespec(&kernel_tp, tp)) 171 return -EFAULT; 172 return 0; 173 } 174 175 COMPAT_SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, 176 struct compat_timespec __user *, tp) 177 { 178 struct timespec rtn_tp = { 179 .tv_sec = 0, 180 .tv_nsec = hrtimer_resolution, 181 }; 182 183 switch (which_clock) { 184 case CLOCK_REALTIME: 185 case CLOCK_MONOTONIC: 186 case CLOCK_BOOTTIME: 187 if (compat_put_timespec(&rtn_tp, tp)) 188 return -EFAULT; 189 return 0; 190 default: 191 return -EINVAL; 192 } 193 } 194 COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags, 195 struct compat_timespec __user *, rqtp, 196 struct compat_timespec __user *, rmtp) 197 { 198 struct timespec64 t64; 199 struct timespec t; 200 201 switch (which_clock) { 202 case CLOCK_REALTIME: 203 case CLOCK_MONOTONIC: 204 case CLOCK_BOOTTIME: 205 break; 206 default: 207 return -EINVAL; 208 } 209 210 if (compat_get_timespec(&t, rqtp)) 211 return -EFAULT; 212 t64 = timespec_to_timespec64(t); 213 if (!timespec64_valid(&t64)) 214 return -EINVAL; 215 if (flags & TIMER_ABSTIME) 216 rmtp = NULL; 217 current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE; 218 current->restart_block.nanosleep.compat_rmtp = rmtp; 219 return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ? 220 HRTIMER_MODE_ABS : HRTIMER_MODE_REL, 221 which_clock); 222 } 223 #endif 224