1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <sys/ioctl.h>
6 #include <syslog.h>
7 #include <unistd.h>
8 #include <linux/watchdog.h>
9 
10 #include "errno-util.h"
11 #include "fd-util.h"
12 #include "fileio.h"
13 #include "log.h"
14 #include "path-util.h"
15 #include "string-util.h"
16 #include "time-util.h"
17 #include "watchdog.h"
18 
19 static int watchdog_fd = -1;
20 static char *watchdog_device;
21 static usec_t watchdog_timeout; /* 0 → close device and USEC_INFINITY → don't change timeout */
22 static usec_t watchdog_pretimeout; /* 0 → disable pretimeout and USEC_INFINITY → don't change pretimeout */
23 static usec_t watchdog_last_ping = USEC_INFINITY;
24 static bool watchdog_supports_pretimeout = false; /* Depends on kernel state that might change at runtime */
25 static char *watchdog_pretimeout_governor = NULL;
26 
27 /* Starting from kernel version 4.5, the maximum allowable watchdog timeout is
28  * UINT_MAX/1000U seconds (since internal calculations are done in milliseconds
29  * using unsigned integers. However, the kernel's userspace API for the watchdog
30  * uses signed integers for its ioctl parameters (even for timeout values and
31  * bit flags) so this is why we must consider the maximum signed integer value
32  * as well.
33  */
34 #define WATCHDOG_TIMEOUT_MAX_SEC (CONST_MIN(UINT_MAX/1000U, (unsigned)INT_MAX))
35 
36 #define WATCHDOG_GOV_NAME_MAXLEN 20 /* From the kernel watchdog driver */
37 
saturated_usec_to_sec(usec_t val)38 static int saturated_usec_to_sec(usec_t val) {
39         usec_t t = DIV_ROUND_UP(val, USEC_PER_SEC);
40         return MIN(t, (usec_t) WATCHDOG_TIMEOUT_MAX_SEC); /* Saturate to watchdog max */
41 }
42 
get_watchdog_sysfs_path(const char * filename,char ** ret_path)43 static int get_watchdog_sysfs_path(const char *filename, char **ret_path) {
44         struct stat st;
45 
46         if (watchdog_fd < 0)
47                 return -EBADF;
48 
49         if (fstat(watchdog_fd, &st))
50                 return -errno;
51 
52         if (!S_ISCHR(st.st_mode))
53                 return -EBADF;
54 
55         if (asprintf(ret_path, "/sys/dev/char/%d:%d/%s", major(st.st_rdev), minor(st.st_rdev), filename) < 0)
56                 return -ENOMEM;
57 
58         return 0;
59 }
60 
get_pretimeout_governor(char ** ret_gov)61 static int get_pretimeout_governor(char **ret_gov) {
62         _cleanup_free_ char *sys_fn = NULL;
63         int r;
64 
65         r = get_watchdog_sysfs_path("pretimeout_governor", &sys_fn);
66         if (r < 0)
67                 return r;
68 
69         log_info("Watchdog: reading from %s", sys_fn);
70 
71         r = read_virtual_file(sys_fn, WATCHDOG_GOV_NAME_MAXLEN - 1, ret_gov, NULL);
72         if (r < 0)
73                 return r;
74 
75         delete_trailing_chars(*ret_gov, WHITESPACE);
76 
77         return 0;
78 }
79 
set_pretimeout_governor(const char * governor)80 static int set_pretimeout_governor(const char *governor) {
81         _cleanup_free_ char *sys_fn = NULL;
82         int r;
83 
84         if (isempty(governor))
85                 return 0; /* Nothing to do */
86 
87         r = get_watchdog_sysfs_path("pretimeout_governor", &sys_fn);
88         if (r < 0)
89                 return r;
90 
91         log_info("Watchdog: setting pretimeout_governor to '%s' via '%s'", governor, sys_fn);
92 
93         r = write_string_file(sys_fn,
94                               governor,
95                               WRITE_STRING_FILE_DISABLE_BUFFER | WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE);
96         if (r < 0)
97                 return log_error_errno(r, "Failed to set pretimeout_governor to '%s': %m", governor);
98 
99         return r;
100 }
101 
watchdog_set_enable(bool enable)102 static int watchdog_set_enable(bool enable) {
103         int flags = enable ? WDIOS_ENABLECARD : WDIOS_DISABLECARD;
104 
105         assert(watchdog_fd >= 0);
106 
107         if (ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags) < 0) {
108                 if (!enable)
109                         return log_warning_errno(errno, "Failed to disable hardware watchdog, ignoring: %m");
110 
111                 /* ENOTTY means the watchdog is always enabled so we're fine */
112                 log_full_errno(ERRNO_IS_NOT_SUPPORTED(errno) ? LOG_DEBUG : LOG_WARNING, errno,
113                                "Failed to enable hardware watchdog, ignoring: %m");
114                 if (!ERRNO_IS_NOT_SUPPORTED(errno))
115                         return -errno;
116         }
117 
118         return 0;
119 }
120 
watchdog_get_timeout(void)121 static int watchdog_get_timeout(void) {
122         int sec = 0;
123 
124         assert(watchdog_fd >= 0);
125 
126         if (ioctl(watchdog_fd, WDIOC_GETTIMEOUT, &sec) < 0)
127                 return -errno;
128 
129         assert(sec > 0);
130         watchdog_timeout = sec * USEC_PER_SEC;
131 
132         return 0;
133 }
134 
watchdog_set_timeout(void)135 static int watchdog_set_timeout(void) {
136         int sec;
137 
138         assert(watchdog_fd >= 0);
139         assert(timestamp_is_set(watchdog_timeout));
140 
141         sec = saturated_usec_to_sec(watchdog_timeout);
142 
143         if (ioctl(watchdog_fd, WDIOC_SETTIMEOUT, &sec) < 0)
144                 return -errno;
145 
146         assert(sec > 0); /* buggy driver ? */
147         watchdog_timeout = sec * USEC_PER_SEC;
148 
149         return 0;
150 }
151 
watchdog_get_pretimeout(void)152 static int watchdog_get_pretimeout(void) {
153         int sec = 0;
154 
155         assert(watchdog_fd >= 0);
156 
157         if (ioctl(watchdog_fd, WDIOC_GETPRETIMEOUT, &sec) < 0) {
158                 watchdog_pretimeout = 0;
159                 return log_full_errno(ERRNO_IS_NOT_SUPPORTED(errno) ? LOG_DEBUG : LOG_WARNING, errno, "Failed to get pretimeout value, ignoring: %m");
160         }
161 
162         watchdog_pretimeout = sec * USEC_PER_SEC;
163 
164         return 0;
165 }
166 
watchdog_set_pretimeout(void)167 static int watchdog_set_pretimeout(void) {
168         int sec;
169 
170         assert(watchdog_fd >= 0);
171         assert(watchdog_pretimeout != USEC_INFINITY);
172 
173         sec = saturated_usec_to_sec(watchdog_pretimeout);
174 
175         if (ioctl(watchdog_fd, WDIOC_SETPRETIMEOUT, &sec) < 0) {
176                 watchdog_pretimeout = 0;
177 
178                 if (ERRNO_IS_NOT_SUPPORTED(errno)) {
179                         log_info("Watchdog does not support pretimeouts.");
180                         return 0;
181                 }
182 
183                 return log_error_errno(errno, "Failed to set pretimeout to %s: %m", FORMAT_TIMESPAN(sec, USEC_PER_SEC));
184         }
185 
186         /* The set ioctl does not return the actual value set so get it now. */
187         (void) watchdog_get_pretimeout();
188 
189         return 0;
190 }
191 
watchdog_ping_now(void)192 static int watchdog_ping_now(void) {
193         assert(watchdog_fd >= 0);
194 
195         if (ioctl(watchdog_fd, WDIOC_KEEPALIVE, 0) < 0)
196                 return log_warning_errno(errno, "Failed to ping hardware watchdog, ignoring: %m");
197 
198         watchdog_last_ping = now(CLOCK_BOOTTIME);
199 
200         return 0;
201 }
202 
update_pretimeout(void)203 static int update_pretimeout(void) {
204         _cleanup_free_ char *governor = NULL;
205         int r, t_sec, pt_sec;
206 
207         if (watchdog_fd < 0)
208                 return 0;
209 
210         if (watchdog_timeout == USEC_INFINITY || watchdog_pretimeout == USEC_INFINITY)
211                 return 0;
212 
213         if (!watchdog_supports_pretimeout && watchdog_pretimeout == 0)
214                 return 0; /* Nothing to do */
215 
216         /* The configuration changed, do not assume it can still work, as the module(s)
217          * might have been unloaded. */
218         watchdog_supports_pretimeout = false;
219 
220         /* Update the pretimeout governor as well */
221         (void) set_pretimeout_governor(watchdog_pretimeout_governor);
222 
223         r = get_pretimeout_governor(&governor);
224         if (r < 0)
225                 return log_warning_errno(r, "Watchdog: failed to read pretimeout governor: %m");
226         if (isempty(governor))
227                 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
228                                          "Watchdog: no pretimeout governor detected - is the required kernel module loaded?");
229 
230         /* If we have a pretimeout governor, then pretimeout is supported. Without a governor
231          * pretimeout does not work at all.
232          * Note that this might require a kernel module that is not autoloaded, so we don't
233          * cache this, but we check every time the configuration changes. */
234         watchdog_supports_pretimeout = true;
235 
236         /* Determine if the pretimeout is valid for the current watchdog timeout. */
237         t_sec = saturated_usec_to_sec(watchdog_timeout);
238         pt_sec = saturated_usec_to_sec(watchdog_pretimeout);
239         if (pt_sec >= t_sec) {
240                 r = log_error_errno(SYNTHETIC_ERRNO(EINVAL),
241                                     "Cannot set watchdog pretimeout to %is (%s watchdog timeout of %is)",
242                                     pt_sec, pt_sec == t_sec ? "same as" : "longer than", t_sec);
243                 (void) watchdog_get_pretimeout();
244         } else
245                 r = watchdog_set_pretimeout();
246 
247         if (watchdog_pretimeout == 0)
248                 log_info("Watchdog pretimeout is disabled.");
249         else
250                 log_info("Watchdog running with a pretimeout of %s with governor '%s'.",
251                          FORMAT_TIMESPAN(watchdog_pretimeout, 0),
252                          governor);
253 
254         return r;
255 }
256 
update_timeout(void)257 static int update_timeout(void) {
258         int r;
259 
260         assert(watchdog_timeout > 0);
261 
262         if (watchdog_fd < 0)
263                 return 0;
264 
265         if (watchdog_timeout != USEC_INFINITY) {
266                 r = watchdog_set_timeout();
267                 if (r < 0) {
268                         if (!ERRNO_IS_NOT_SUPPORTED(r))
269                                 return log_error_errno(r, "Failed to set timeout to %s: %m",
270                                                        FORMAT_TIMESPAN(watchdog_timeout, 0));
271 
272                         log_info("Modifying watchdog timeout is not supported, reusing the programmed timeout.");
273                         watchdog_timeout = USEC_INFINITY;
274                 }
275         }
276 
277         if (watchdog_timeout == USEC_INFINITY) {
278                 r = watchdog_get_timeout();
279                 if (r < 0)
280                         return log_error_errno(r, "Failed to query watchdog HW timeout: %m");
281         }
282 
283         /* If the watchdog timeout was changed, the pretimeout could have been
284          * changed as well by the driver or the kernel so we need to update the
285          * pretimeout now. Or if the watchdog is being configured for the first
286          * time, we want to configure the pretimeout before it is enabled. */
287         (void) update_pretimeout();
288 
289         r = watchdog_set_enable(true);
290         if (r < 0)
291                 return r;
292 
293         log_info("Watchdog running with a timeout of %s.", FORMAT_TIMESPAN(watchdog_timeout, 0));
294 
295         return watchdog_ping_now();
296 }
297 
open_watchdog(void)298 static int open_watchdog(void) {
299         struct watchdog_info ident;
300         const char *fn;
301         int r;
302 
303         if (watchdog_fd >= 0)
304                 return 0;
305 
306         /* Let's prefer new-style /dev/watchdog0 (i.e. kernel 3.5+) over classic /dev/watchdog. The former
307          * has the benefit that we can easily find the matching directory in sysfs from it, as the relevant
308          * sysfs attributes can only be found via /sys/dev/char/<major>:<minor> if the new-style device
309          * major/minor is used, not the old-style. */
310         fn = !watchdog_device || path_equal(watchdog_device, "/dev/watchdog") ?
311                 "/dev/watchdog0" : watchdog_device;
312 
313         r = free_and_strdup(&watchdog_device, fn);
314         if (r < 0)
315                 return log_oom_debug();
316 
317         watchdog_fd = open(watchdog_device, O_WRONLY|O_CLOEXEC);
318         if (watchdog_fd < 0)
319                 return log_debug_errno(errno, "Failed to open watchdog device %s, ignoring: %m", watchdog_device);
320 
321         if (ioctl(watchdog_fd, WDIOC_GETSUPPORT, &ident) < 0)
322                 log_debug_errno(errno, "Hardware watchdog %s does not support WDIOC_GETSUPPORT ioctl, ignoring: %m", watchdog_device);
323         else
324                 log_info("Using hardware watchdog '%s', version %x, device %s",
325                          ident.identity,
326                          ident.firmware_version,
327                          watchdog_device);
328 
329         r = update_timeout();
330         if (r < 0)
331                 watchdog_close(true);
332 
333         return r;
334 }
335 
watchdog_set_device(const char * path)336 int watchdog_set_device(const char *path) {
337         int r;
338 
339         r = free_and_strdup(&watchdog_device, path);
340         if (r > 0) /* watchdog_device changed */
341                 watchdog_fd = safe_close(watchdog_fd);
342 
343         return r;
344 }
345 
watchdog_setup(usec_t timeout)346 int watchdog_setup(usec_t timeout) {
347         usec_t previous_timeout;
348         int r;
349 
350         /* timeout=0 closes the device whereas passing timeout=USEC_INFINITY opens it (if needed)
351          * without configuring any particular timeout and thus reuses the programmed value (therefore
352          * it's a nop if the device is already opened). */
353 
354         if (timeout == 0) {
355                 watchdog_close(true);
356                 return 0;
357         }
358 
359         /* Let's shortcut duplicated requests */
360         if (watchdog_fd >= 0 && (timeout == watchdog_timeout || timeout == USEC_INFINITY))
361                 return 0;
362 
363         /* Initialize the watchdog timeout with the caller value. This value is going to be updated by
364          * update_timeout() with the closest value supported by the driver */
365         previous_timeout = watchdog_timeout;
366         watchdog_timeout = timeout;
367 
368         if (watchdog_fd < 0)
369                 return open_watchdog();
370 
371         r = update_timeout();
372         if (r < 0)
373                 watchdog_timeout = previous_timeout;
374 
375         return r;
376 }
377 
watchdog_setup_pretimeout(usec_t timeout)378 int watchdog_setup_pretimeout(usec_t timeout) {
379         /* timeout=0 disables the pretimeout whereas timeout=USEC_INFINITY is a nop. */
380         if ((watchdog_fd >= 0 && timeout == watchdog_pretimeout) || timeout == USEC_INFINITY)
381                 return 0;
382 
383         /* Initialize the watchdog timeout with the caller value. This value is
384          * going to be updated by update_pretimeout() with the running value,
385          * even if it fails to update the timeout. */
386         watchdog_pretimeout = timeout;
387 
388         return update_pretimeout();
389 }
390 
watchdog_setup_pretimeout_governor(const char * governor)391 int watchdog_setup_pretimeout_governor(const char *governor) {
392         if (free_and_strdup(&watchdog_pretimeout_governor, governor) < 0)
393                 return -ENOMEM;
394 
395         return set_pretimeout_governor(watchdog_pretimeout_governor);
396 }
397 
calc_timeout(void)398 static usec_t calc_timeout(void) {
399         /* Calculate the effective timeout which accounts for the watchdog
400          * pretimeout if configured and supported. */
401         if (watchdog_supports_pretimeout && timestamp_is_set(watchdog_pretimeout) && watchdog_timeout >= watchdog_pretimeout)
402                 return watchdog_timeout - watchdog_pretimeout;
403         else
404                 return watchdog_timeout;
405 }
406 
watchdog_runtime_wait(void)407 usec_t watchdog_runtime_wait(void) {
408         usec_t timeout = calc_timeout();
409         if (!timestamp_is_set(timeout))
410                 return USEC_INFINITY;
411 
412         /* Sleep half the watchdog timeout since the last successful ping at most */
413         if (timestamp_is_set(watchdog_last_ping)) {
414                 usec_t ntime = now(CLOCK_BOOTTIME);
415 
416                 assert(ntime >= watchdog_last_ping);
417                 return usec_sub_unsigned(watchdog_last_ping + (timeout / 2), ntime);
418         }
419 
420         return timeout / 2;
421 }
422 
watchdog_ping(void)423 int watchdog_ping(void) {
424         usec_t ntime, timeout;
425 
426         if (watchdog_timeout == 0)
427                 return 0;
428 
429         if (watchdog_fd < 0)
430                 /* open_watchdog() will automatically ping the device for us if necessary */
431                 return open_watchdog();
432 
433         ntime = now(CLOCK_BOOTTIME);
434         timeout = calc_timeout();
435 
436         /* Never ping earlier than watchdog_timeout/4 and try to ping
437          * by watchdog_timeout/2 plus scheduling latencies at the latest */
438         if (timestamp_is_set(watchdog_last_ping)) {
439                 assert(ntime >= watchdog_last_ping);
440                 if ((ntime - watchdog_last_ping) < (timeout / 4))
441                         return 0;
442         }
443 
444         return watchdog_ping_now();
445 }
446 
watchdog_close(bool disarm)447 void watchdog_close(bool disarm) {
448 
449         /* Once closed, pinging the device becomes a NOP and we request a new
450          * call to watchdog_setup() to open the device again. */
451         watchdog_timeout = 0;
452 
453         if (watchdog_fd < 0)
454                 return;
455 
456         if (disarm) {
457                 (void) watchdog_set_enable(false);
458 
459                 /* To be sure, use magic close logic, too */
460                 for (;;) {
461                         static const char v = 'V';
462 
463                         if (write(watchdog_fd, &v, 1) > 0)
464                                 break;
465 
466                         if (errno != EINTR) {
467                                 log_warning_errno(errno, "Failed to disarm watchdog timer, ignoring: %m");
468                                 break;
469                         }
470                 }
471         }
472 
473         watchdog_fd = safe_close(watchdog_fd);
474 }
475