GNU Linux-libre 4.14.290-gnu1
[releases.git] / kernel / time / posix-stubs.c
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
45 /*
46  * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
47  * as it is easy to remain compatible with little code. CLOCK_BOOTTIME
48  * is also included for convenience as at least systemd uses it.
49  */
50
51 SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
52                 const struct timespec __user *, tp)
53 {
54         struct timespec64 new_tp;
55
56         if (which_clock != CLOCK_REALTIME)
57                 return -EINVAL;
58         if (get_timespec64(&new_tp, tp))
59                 return -EFAULT;
60
61         return do_sys_settimeofday64(&new_tp, NULL);
62 }
63
64 int do_clock_gettime(clockid_t which_clock, struct timespec64 *tp)
65 {
66         switch (which_clock) {
67         case CLOCK_REALTIME:
68                 ktime_get_real_ts64(tp);
69                 break;
70         case CLOCK_MONOTONIC:
71                 ktime_get_ts64(tp);
72                 break;
73         case CLOCK_BOOTTIME:
74                 get_monotonic_boottime64(tp);
75                 break;
76         default:
77                 return -EINVAL;
78         }
79
80         return 0;
81 }
82 SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
83                 struct timespec __user *, tp)
84 {
85         int ret;
86         struct timespec64 kernel_tp;
87
88         ret = do_clock_gettime(which_clock, &kernel_tp);
89         if (ret)
90                 return ret;
91
92         if (put_timespec64(&kernel_tp, tp))
93                 return -EFAULT;
94         return 0;
95 }
96
97 SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct timespec __user *, tp)
98 {
99         struct timespec64 rtn_tp = {
100                 .tv_sec = 0,
101                 .tv_nsec = hrtimer_resolution,
102         };
103
104         switch (which_clock) {
105         case CLOCK_REALTIME:
106         case CLOCK_MONOTONIC:
107         case CLOCK_BOOTTIME:
108                 if (put_timespec64(&rtn_tp, tp))
109                         return -EFAULT;
110                 return 0;
111         default:
112                 return -EINVAL;
113         }
114 }
115
116 SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
117                 const struct timespec __user *, rqtp,
118                 struct timespec __user *, rmtp)
119 {
120         struct timespec64 t64;
121         struct timespec t;
122
123         switch (which_clock) {
124         case CLOCK_REALTIME:
125         case CLOCK_MONOTONIC:
126         case CLOCK_BOOTTIME:
127                 break;
128         default:
129                 return -EINVAL;
130         }
131
132         if (copy_from_user(&t, rqtp, sizeof (struct timespec)))
133                 return -EFAULT;
134         t64 = timespec_to_timespec64(t);
135         if (!timespec64_valid(&t64))
136                 return -EINVAL;
137         if (flags & TIMER_ABSTIME)
138                 rmtp = NULL;
139         current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE;
140         current->restart_block.nanosleep.rmtp = rmtp;
141         return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ?
142                                  HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
143                                  which_clock);
144 }
145
146 #ifdef CONFIG_COMPAT
147 COMPAT_SYS_NI(timer_create);
148 COMPAT_SYS_NI(clock_adjtime);
149 COMPAT_SYS_NI(timer_settime);
150 COMPAT_SYS_NI(timer_gettime);
151 COMPAT_SYS_NI(getitimer);
152 COMPAT_SYS_NI(setitimer);
153
154 COMPAT_SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
155                        struct compat_timespec __user *, tp)
156 {
157         struct timespec64 new_tp;
158
159         if (which_clock != CLOCK_REALTIME)
160                 return -EINVAL;
161         if (compat_get_timespec64(&new_tp, tp))
162                 return -EFAULT;
163
164         return do_sys_settimeofday64(&new_tp, NULL);
165 }
166
167 COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
168                        struct compat_timespec __user *, tp)
169 {
170         int ret;
171         struct timespec64 kernel_tp;
172
173         ret = do_clock_gettime(which_clock, &kernel_tp);
174         if (ret)
175                 return ret;
176
177         if (compat_put_timespec64(&kernel_tp, tp))
178                 return -EFAULT;
179         return 0;
180 }
181
182 COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
183                        struct compat_timespec __user *, tp)
184 {
185         struct timespec64 rtn_tp = {
186                 .tv_sec = 0,
187                 .tv_nsec = hrtimer_resolution,
188         };
189
190         switch (which_clock) {
191         case CLOCK_REALTIME:
192         case CLOCK_MONOTONIC:
193         case CLOCK_BOOTTIME:
194                 if (compat_put_timespec64(&rtn_tp, tp))
195                         return -EFAULT;
196                 return 0;
197         default:
198                 return -EINVAL;
199         }
200 }
201
202 COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
203                        struct compat_timespec __user *, rqtp,
204                        struct compat_timespec __user *, rmtp)
205 {
206         struct timespec64 t64;
207         struct timespec t;
208
209         switch (which_clock) {
210         case CLOCK_REALTIME:
211         case CLOCK_MONOTONIC:
212         case CLOCK_BOOTTIME:
213                 break;
214         default:
215                 return -EINVAL;
216         }
217
218         if (compat_get_timespec(&t, rqtp))
219                 return -EFAULT;
220         t64 = timespec_to_timespec64(t);
221         if (!timespec64_valid(&t64))
222                 return -EINVAL;
223         if (flags & TIMER_ABSTIME)
224                 rmtp = NULL;
225         current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE;
226         current->restart_block.nanosleep.compat_rmtp = rmtp;
227         return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ?
228                                  HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
229                                  which_clock);
230 }
231 #endif