xref: /linux/kernel/time/posix-stubs.c (revision 69fb09f6ccdb2f070557fd1f4c56c4d646694c8e)
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