]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/sleep-util.c
seccomp: add arm_fadvise64_64 to system-service group
[thirdparty/systemd.git] / src / shared / sleep-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /***
3 Copyright © 2018 Dell Inc.
4 ***/
5
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <linux/fs.h>
9 #include <linux/magic.h>
10 #include <stdbool.h>
11 #include <stddef.h>
12 #include <sys/ioctl.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15 #include <syslog.h>
16 #include <unistd.h>
17
18 #include "sd-device.h"
19
20 #include "alloc-util.h"
21 #include "battery-util.h"
22 #include "blockdev-util.h"
23 #include "btrfs-util.h"
24 #include "conf-parser.h"
25 #include "constants.h"
26 #include "device-private.h"
27 #include "device-util.h"
28 #include "devnum-util.h"
29 #include "env-util.h"
30 #include "errno-util.h"
31 #include "fd-util.h"
32 #include "fileio.h"
33 #include "hexdecoct.h"
34 #include "id128-util.h"
35 #include "log.h"
36 #include "macro.h"
37 #include "path-util.h"
38 #include "siphash24.h"
39 #include "sleep-util.h"
40 #include "stat-util.h"
41 #include "stdio-util.h"
42 #include "string-table.h"
43 #include "string-util.h"
44 #include "strv.h"
45 #include "time-util.h"
46
47 #define DISCHARGE_RATE_FILEPATH "/var/lib/systemd/sleep/battery_discharge_percentage_rate_per_hour"
48 #define BATTERY_DISCHARGE_RATE_HASH_KEY SD_ID128_MAKE(5f,9a,20,18,38,76,46,07,8d,36,58,0b,bb,c4,e0,63)
49
50 static void *CAPACITY_TO_PTR(int capacity) {
51 assert(capacity >= 0);
52 assert(capacity <= 100);
53 return INT_TO_PTR(capacity + 1);
54 }
55
56 static int PTR_TO_CAPACITY(void *p) {
57 int capacity = PTR_TO_INT(p) - 1;
58 assert(capacity >= 0);
59 assert(capacity <= 100);
60 return capacity;
61 }
62
63 int parse_sleep_config(SleepConfig **ret_sleep_config) {
64 _cleanup_(free_sleep_configp) SleepConfig *sc = NULL;
65 int allow_suspend = -1, allow_hibernate = -1,
66 allow_s2h = -1, allow_hybrid_sleep = -1;
67
68 sc = new(SleepConfig, 1);
69 if (!sc)
70 return log_oom();
71
72 *sc = (SleepConfig) {
73 .hibernate_delay_usec = USEC_INFINITY,
74 };
75
76 const ConfigTableItem items[] = {
77 { "Sleep", "AllowSuspend", config_parse_tristate, 0, &allow_suspend },
78 { "Sleep", "AllowHibernation", config_parse_tristate, 0, &allow_hibernate },
79 { "Sleep", "AllowSuspendThenHibernate", config_parse_tristate, 0, &allow_s2h },
80 { "Sleep", "AllowHybridSleep", config_parse_tristate, 0, &allow_hybrid_sleep },
81
82 { "Sleep", "SuspendMode", config_parse_strv, 0, sc->modes + SLEEP_SUSPEND },
83 { "Sleep", "SuspendState", config_parse_strv, 0, sc->states + SLEEP_SUSPEND },
84 { "Sleep", "HibernateMode", config_parse_strv, 0, sc->modes + SLEEP_HIBERNATE },
85 { "Sleep", "HibernateState", config_parse_strv, 0, sc->states + SLEEP_HIBERNATE },
86 { "Sleep", "HybridSleepMode", config_parse_strv, 0, sc->modes + SLEEP_HYBRID_SLEEP },
87 { "Sleep", "HybridSleepState", config_parse_strv, 0, sc->states + SLEEP_HYBRID_SLEEP },
88
89 { "Sleep", "HibernateDelaySec", config_parse_sec, 0, &sc->hibernate_delay_usec },
90 { "Sleep", "SuspendEstimationSec", config_parse_sec, 0, &sc->suspend_estimation_usec },
91 {}
92 };
93
94 (void) config_parse_config_file("sleep.conf", "Sleep\0",
95 config_item_table_lookup, items,
96 CONFIG_PARSE_WARN, NULL);
97
98 /* use default values unless set */
99 sc->allow[SLEEP_SUSPEND] = allow_suspend != 0;
100 sc->allow[SLEEP_HIBERNATE] = allow_hibernate != 0;
101 sc->allow[SLEEP_HYBRID_SLEEP] = allow_hybrid_sleep >= 0 ? allow_hybrid_sleep
102 : (allow_suspend != 0 && allow_hibernate != 0);
103 sc->allow[SLEEP_SUSPEND_THEN_HIBERNATE] = allow_s2h >= 0 ? allow_s2h
104 : (allow_suspend != 0 && allow_hibernate != 0);
105
106 if (!sc->states[SLEEP_SUSPEND])
107 sc->states[SLEEP_SUSPEND] = strv_new("mem", "standby", "freeze");
108 if (!sc->modes[SLEEP_HIBERNATE])
109 sc->modes[SLEEP_HIBERNATE] = strv_new("platform", "shutdown");
110 if (!sc->states[SLEEP_HIBERNATE])
111 sc->states[SLEEP_HIBERNATE] = strv_new("disk");
112 if (!sc->modes[SLEEP_HYBRID_SLEEP])
113 sc->modes[SLEEP_HYBRID_SLEEP] = strv_new("suspend", "platform", "shutdown");
114 if (!sc->states[SLEEP_HYBRID_SLEEP])
115 sc->states[SLEEP_HYBRID_SLEEP] = strv_new("disk");
116 if (sc->suspend_estimation_usec == 0)
117 sc->suspend_estimation_usec = DEFAULT_SUSPEND_ESTIMATION_USEC;
118
119 /* Ensure values set for all required fields */
120 if (!sc->states[SLEEP_SUSPEND] || !sc->modes[SLEEP_HIBERNATE]
121 || !sc->states[SLEEP_HIBERNATE] || !sc->modes[SLEEP_HYBRID_SLEEP] || !sc->states[SLEEP_HYBRID_SLEEP])
122 return log_oom();
123
124 *ret_sleep_config = TAKE_PTR(sc);
125
126 return 0;
127 }
128
129 int get_capacity_by_name(Hashmap *capacities_by_name, const char *name) {
130 void *p;
131
132 assert(capacities_by_name);
133 assert(name);
134
135 p = hashmap_get(capacities_by_name, name);
136 if (!p)
137 return -ENOENT;
138
139 return PTR_TO_CAPACITY(p);
140 }
141
142 /* Store current capacity of each battery before suspension and timestamp */
143 int fetch_batteries_capacity_by_name(Hashmap **ret) {
144 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
145 _cleanup_hashmap_free_ Hashmap *batteries_capacity_by_name = NULL;
146 sd_device *dev;
147 int r;
148
149 assert(ret);
150
151 batteries_capacity_by_name = hashmap_new(&string_hash_ops_free);
152 if (!batteries_capacity_by_name)
153 return log_oom_debug();
154
155 r = battery_enumerator_new(&e);
156 if (r < 0)
157 return log_debug_errno(r, "Failed to initialize battery enumerator: %m");
158
159 FOREACH_DEVICE(e, dev) {
160 _cleanup_free_ char *battery_name_copy = NULL;
161 const char *battery_name;
162 int battery_capacity;
163
164 battery_capacity = r = battery_read_capacity_percentage(dev);
165 if (r < 0)
166 continue;
167
168 r = sd_device_get_property_value(dev, "POWER_SUPPLY_NAME", &battery_name);
169 if (r < 0) {
170 log_device_debug_errno(dev, r, "Failed to get POWER_SUPPLY_NAME property, ignoring: %m");
171 continue;
172 }
173
174 battery_name_copy = strdup(battery_name);
175 if (!battery_name_copy)
176 return log_oom_debug();
177
178 r = hashmap_put(batteries_capacity_by_name, battery_name_copy, CAPACITY_TO_PTR(battery_capacity));
179 if (r < 0)
180 return log_device_debug_errno(dev, r, "Failed to store battery capacity: %m");
181
182 TAKE_PTR(battery_name_copy);
183 }
184
185 *ret = TAKE_PTR(batteries_capacity_by_name);
186
187 return 0;
188 }
189
190 static int siphash24_compress_device_sysattr(sd_device *dev, const char *attr, struct siphash *state) {
191 const char *x;
192 int r;
193
194 assert(dev);
195 assert(attr);
196 assert(state);
197
198 r = sd_device_get_sysattr_value(dev, attr, &x);
199 if (r < 0)
200 return log_device_debug_errno(dev, r, "Failed to read '%s' attribute: %m", attr);
201
202 if (!isempty(x))
203 siphash24_compress_string(x, state);
204
205 return 0;
206 }
207
208 static int siphash24_compress_id128(int (*getter)(sd_id128_t*), const char *name, struct siphash *state) {
209 sd_id128_t id;
210 int r;
211
212 assert(getter);
213 assert(state);
214
215 r = getter(&id);
216 if (r < 0)
217 return log_debug_errno(r, "Failed to get %s ID: %m", name);
218
219 siphash24_compress(&id, sizeof(sd_id128_t), state);
220 return 0;
221 }
222
223 /* Read system and battery identifier from specific location and generate hash of it */
224 static int get_system_battery_identifier_hash(sd_device *dev, uint64_t *ret) {
225 struct siphash state;
226
227 assert(ret);
228 assert(dev);
229
230 siphash24_init(&state, BATTERY_DISCHARGE_RATE_HASH_KEY.bytes);
231
232 (void) siphash24_compress_device_sysattr(dev, "manufacturer", &state);
233 (void) siphash24_compress_device_sysattr(dev, "model_name", &state);
234 (void) siphash24_compress_device_sysattr(dev, "serial_number", &state);
235 (void) siphash24_compress_id128(sd_id128_get_machine, "machine", &state);
236 (void) siphash24_compress_id128(id128_get_product, "product", &state);
237
238 *ret = siphash24_finalize(&state);
239 return 0;
240 }
241
242 /* Return success if battery percentage discharge rate per hour is in the range 1–199 */
243 static bool battery_discharge_rate_is_valid(int battery_discharge_rate) {
244 return battery_discharge_rate > 0 && battery_discharge_rate < 200;
245 }
246
247 /* Battery percentage discharge rate per hour is read from specific file. It is stored along with system
248 * and battery identifier hash to maintain the integrity of discharge rate value */
249 static int get_battery_discharge_rate(sd_device *dev, int *ret) {
250 _cleanup_fclose_ FILE *f = NULL;
251 uint64_t current_hash_id;
252 const char *p;
253 int r;
254
255 assert(dev);
256 assert(ret);
257
258 f = fopen(DISCHARGE_RATE_FILEPATH, "re");
259 if (!f)
260 return log_debug_errno(errno, "Failed to read discharge rate from " DISCHARGE_RATE_FILEPATH ": %m");
261
262 r = get_system_battery_identifier_hash(dev, &current_hash_id);
263 if (r < 0)
264 return log_device_debug_errno(dev, r, "Failed to generate system battery identifier hash: %m");
265
266 for (;;) {
267 _cleanup_free_ char *stored_hash_id = NULL, *stored_discharge_rate = NULL, *line = NULL;
268 uint64_t hash_id;
269 int discharge_rate;
270
271 r = read_line(f, LONG_LINE_MAX, &line);
272 if (r < 0)
273 return log_debug_errno(r, "Failed to read discharge rate from " DISCHARGE_RATE_FILEPATH ": %m");
274 if (r == 0)
275 break;
276
277 p = line;
278 r = extract_many_words(&p, NULL, 0, &stored_hash_id, &stored_discharge_rate, NULL);
279 if (r < 0)
280 return log_debug_errno(r, "Failed to parse hash_id and discharge_rate read from " DISCHARGE_RATE_FILEPATH ": %m");
281 if (r != 2)
282 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid number of items fetched from " DISCHARGE_RATE_FILEPATH);
283
284 r = safe_atou64(stored_hash_id, &hash_id);
285 if (r < 0)
286 return log_debug_errno(r, "Failed to parse hash ID read from " DISCHARGE_RATE_FILEPATH " location: %m");
287
288 if (current_hash_id != hash_id)
289 /* matching device not found, move to next line */
290 continue;
291
292 r = safe_atoi(stored_discharge_rate, &discharge_rate);
293 if (r < 0)
294 return log_device_debug_errno(dev, r, "Failed to parse discharge rate read from " DISCHARGE_RATE_FILEPATH ": %m");
295
296 if (!battery_discharge_rate_is_valid(discharge_rate))
297 return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ERANGE), "Invalid battery discharge percentage rate per hour: %m");
298
299 *ret = discharge_rate;
300 return 0; /* matching device found, exit iteration */
301 }
302
303 return -ENOENT;
304 }
305
306 /* Write battery percentage discharge rate per hour along with system and battery identifier hash to file */
307 static int put_battery_discharge_rate(int estimated_battery_discharge_rate, uint64_t system_hash_id, bool trunc) {
308 int r;
309
310 if (!battery_discharge_rate_is_valid(estimated_battery_discharge_rate))
311 return log_debug_errno(SYNTHETIC_ERRNO(ERANGE),
312 "Invalid battery discharge rate %d%% per hour: %m",
313 estimated_battery_discharge_rate);
314
315 r = write_string_filef(
316 DISCHARGE_RATE_FILEPATH,
317 WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_MKDIR_0755 | (trunc ? WRITE_STRING_FILE_TRUNCATE : 0),
318 "%"PRIu64" %d",
319 system_hash_id,
320 estimated_battery_discharge_rate);
321 if (r < 0)
322 return log_debug_errno(r, "Failed to update %s: %m", DISCHARGE_RATE_FILEPATH);
323
324 log_debug("Estimated discharge rate %d%% per hour successfully saved to %s", estimated_battery_discharge_rate, DISCHARGE_RATE_FILEPATH);
325
326 return 0;
327 }
328
329 /* Estimate battery discharge rate using stored previous and current capacity over timestamp difference */
330 int estimate_battery_discharge_rate_per_hour(
331 Hashmap *last_capacity,
332 Hashmap *current_capacity,
333 usec_t before_timestamp,
334 usec_t after_timestamp) {
335
336 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
337 sd_device *dev;
338 bool trunc = true;
339 int r;
340
341 assert(last_capacity);
342 assert(current_capacity);
343 assert(before_timestamp < after_timestamp);
344
345 r = battery_enumerator_new(&e);
346 if (r < 0)
347 return log_debug_errno(r, "Failed to initialize battery enumerator: %m");
348
349 FOREACH_DEVICE(e, dev) {
350 int battery_last_capacity, battery_current_capacity, battery_discharge_rate;
351 const char *battery_name;
352 uint64_t system_hash_id;
353
354 r = sd_device_get_property_value(dev, "POWER_SUPPLY_NAME", &battery_name);
355 if (r < 0) {
356 log_device_debug_errno(dev, r, "Failed to read battery name, ignoring: %m");
357 continue;
358 }
359
360 battery_last_capacity = get_capacity_by_name(last_capacity, battery_name);
361 if (battery_last_capacity < 0)
362 continue;
363
364 battery_current_capacity = get_capacity_by_name(current_capacity, battery_name);
365 if (battery_current_capacity < 0)
366 continue;
367
368 if (battery_current_capacity >= battery_last_capacity) {
369 log_device_debug(dev, "Battery was not discharged during suspension");
370 continue;
371 }
372
373 r = get_system_battery_identifier_hash(dev, &system_hash_id);
374 if (r < 0)
375 return log_device_debug_errno(dev, r, "Failed to generate system battery identifier hash: %m");
376
377 log_device_debug(dev,
378 "%d%% was discharged in %s. Estimating discharge rate...",
379 battery_last_capacity - battery_current_capacity,
380 FORMAT_TIMESPAN(after_timestamp - before_timestamp, USEC_PER_SEC));
381
382 battery_discharge_rate = (battery_last_capacity - battery_current_capacity) * USEC_PER_HOUR / (after_timestamp - before_timestamp);
383 r = put_battery_discharge_rate(battery_discharge_rate, system_hash_id, trunc);
384 if (r < 0)
385 log_device_warning_errno(dev, r, "Failed to update battery discharge rate, ignoring: %m");
386 else
387 trunc = false;
388 }
389
390 return 0;
391 }
392
393 /* Calculate the suspend interval for each battery and then return their sum */
394 int get_total_suspend_interval(Hashmap *last_capacity, usec_t *ret) {
395 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
396 usec_t total_suspend_interval = 0;
397 sd_device *dev;
398 int r;
399
400 assert(last_capacity);
401 assert(ret);
402
403 r = battery_enumerator_new(&e);
404 if (r < 0)
405 return log_debug_errno(r, "Failed to initialize battery enumerator: %m");
406
407 FOREACH_DEVICE(e, dev) {
408 int battery_last_capacity, previous_discharge_rate = 0;
409 const char *battery_name;
410 usec_t suspend_interval;
411
412 r = sd_device_get_property_value(dev, "POWER_SUPPLY_NAME", &battery_name);
413 if (r < 0) {
414 log_device_debug_errno(dev, r, "Failed to read battery name, ignoring: %m");
415 continue;
416 }
417
418 battery_last_capacity = get_capacity_by_name(last_capacity, battery_name);
419 if (battery_last_capacity <= 0)
420 continue;
421
422 r = get_battery_discharge_rate(dev, &previous_discharge_rate);
423 if (r < 0) {
424 log_device_debug_errno(dev, r, "Failed to get discharge rate, ignoring: %m");
425 continue;
426 }
427
428 if (previous_discharge_rate == 0)
429 continue;
430
431 if (battery_last_capacity * 2 <= previous_discharge_rate) {
432 log_device_debug(dev, "Current battery capacity percentage too low compared to discharge rate");
433 continue;
434 }
435 suspend_interval = battery_last_capacity * USEC_PER_HOUR / previous_discharge_rate;
436
437 total_suspend_interval = usec_add(total_suspend_interval, suspend_interval);
438 }
439 /* Previous discharge rate is stored in per hour basis converted to usec.
440 * Subtract 30 minutes from the result to keep a buffer of 30 minutes before battery gets critical */
441 total_suspend_interval = usec_sub_unsigned(total_suspend_interval, 30 * USEC_PER_MINUTE);
442 if (total_suspend_interval == 0)
443 return -ENOENT;
444
445 *ret = total_suspend_interval;
446
447 return 0;
448 }
449
450 /* Return true if all batteries have acpi_btp support */
451 int battery_trip_point_alarm_exists(void) {
452 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
453 sd_device *dev;
454 int r;
455
456 r = battery_enumerator_new(&e);
457 if (r < 0)
458 return log_debug_errno(r, "Failed to initialize battery enumerator: %m");
459
460 FOREACH_DEVICE(e, dev) {
461 int battery_alarm;
462 const char *s;
463
464 r = sd_device_get_sysattr_value(dev, "alarm", &s);
465 if (r < 0)
466 return log_device_debug_errno(dev, r, "Failed to read battery alarm: %m");
467
468 r = safe_atoi(s, &battery_alarm);
469 if (r < 0)
470 return log_device_debug_errno(dev, r, "Failed to parse battery alarm: %m");
471 if (battery_alarm <= 0)
472 return false;
473 }
474
475 return true;
476 }
477
478 /* Return true if wakeup type is APM timer */
479 int check_wakeup_type(void) {
480 static const char dmi_object_path[] = "/sys/firmware/dmi/entries/1-0/raw";
481 uint8_t wakeup_type_byte, tablesize;
482 _cleanup_free_ char *buf = NULL;
483 size_t bufsize;
484 int r;
485
486 /* implementation via dmi/entries */
487 r = read_full_virtual_file(dmi_object_path, &buf, &bufsize);
488 if (r < 0)
489 return log_debug_errno(r, "Unable to read %s: %m", dmi_object_path);
490 if (bufsize < 25)
491 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Only read %zu bytes from %s (expected 25)", bufsize, dmi_object_path);
492
493 /* index 1 stores the size of table */
494 tablesize = (uint8_t) buf[1];
495 if (tablesize < 25)
496 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Table size lesser than the index[0x18] where waketype byte is available.");
497
498 wakeup_type_byte = (uint8_t) buf[24];
499 /* 0 is Reserved and 8 is AC Power Restored. As per table 12 in
500 * https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.4.0.pdf */
501 if (wakeup_type_byte >= 128)
502 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Expected value in range 0-127");
503
504 if (wakeup_type_byte == 3) {
505 log_debug("DMI BIOS System Information indicates wakeup type is APM Timer");
506 return true;
507 }
508
509 return false;
510 }
511
512 int can_sleep_state(char **requested_types) {
513 _cleanup_free_ char *text = NULL;
514 int r;
515
516 if (strv_isempty(requested_types))
517 return true;
518
519 /* If /sys is read-only we cannot sleep */
520 if (access("/sys/power/state", W_OK) < 0) {
521 log_debug_errno(errno, "/sys/power/state is not writable, cannot sleep: %m");
522 return false;
523 }
524
525 r = read_one_line_file("/sys/power/state", &text);
526 if (r < 0) {
527 log_debug_errno(r, "Failed to read /sys/power/state, cannot sleep: %m");
528 return false;
529 }
530
531 const char *found;
532 r = string_contains_word_strv(text, NULL, requested_types, &found);
533 if (r < 0)
534 return log_debug_errno(r, "Failed to parse /sys/power/state: %m");
535 if (r > 0)
536 log_debug("Sleep mode \"%s\" is supported by the kernel.", found);
537 else if (DEBUG_LOGGING) {
538 _cleanup_free_ char *t = strv_join(requested_types, "/");
539 log_debug("Sleep mode %s not supported by the kernel, sorry.", strnull(t));
540 }
541 return r;
542 }
543
544 int can_sleep_disk(char **types) {
545 _cleanup_free_ char *text = NULL;
546 int r;
547
548 if (strv_isempty(types))
549 return true;
550
551 /* If /sys is read-only we cannot sleep */
552 if (access("/sys/power/disk", W_OK) < 0) {
553 log_debug_errno(errno, "/sys/power/disk is not writable: %m");
554 return false;
555 }
556
557 r = read_one_line_file("/sys/power/disk", &text);
558 if (r < 0) {
559 log_debug_errno(r, "Couldn't read /sys/power/disk: %m");
560 return false;
561 }
562
563 for (const char *p = text;;) {
564 _cleanup_free_ char *word = NULL;
565
566 r = extract_first_word(&p, &word, NULL, 0);
567 if (r < 0)
568 return log_debug_errno(r, "Failed to parse /sys/power/disk: %m");
569 if (r == 0)
570 break;
571
572 char *s = word;
573 size_t l = strlen(s);
574 if (s[0] == '[' && s[l-1] == ']') {
575 s[l-1] = '\0';
576 s++;
577 }
578
579 if (strv_contains(types, s)) {
580 log_debug("Disk sleep mode \"%s\" is supported by the kernel.", s);
581 return true;
582 }
583 }
584
585 if (DEBUG_LOGGING) {
586 _cleanup_free_ char *t = strv_join(types, "/");
587 log_debug("Disk sleep mode %s not supported by the kernel, sorry.", strnull(t));
588 }
589 return false;
590 }
591
592 #define HIBERNATION_SWAP_THRESHOLD 0.98
593
594 SwapEntry* swap_entry_free(SwapEntry *se) {
595 if (!se)
596 return NULL;
597
598 free(se->path);
599
600 return mfree(se);
601 }
602
603 HibernateLocation* hibernate_location_free(HibernateLocation *hl) {
604 if (!hl)
605 return NULL;
606
607 swap_entry_free(hl->swap);
608
609 return mfree(hl);
610 }
611
612 static int swap_device_to_devnum(const SwapEntry *swap, dev_t *ret_dev) {
613 _cleanup_close_ int fd = -EBADF;
614 struct stat sb;
615 int r;
616
617 assert(swap);
618 assert(swap->path);
619
620 fd = open(swap->path, O_CLOEXEC|O_PATH);
621 if (fd < 0)
622 return -errno;
623
624 if (fstat(fd, &sb) < 0)
625 return -errno;
626
627 if (swap->type == SWAP_BLOCK) {
628 if (!S_ISBLK(sb.st_mode))
629 return -ENOTBLK;
630
631 *ret_dev = sb.st_rdev;
632 return 0;
633 }
634
635 r = stat_verify_regular(&sb);
636 if (r < 0)
637 return r;
638
639 return get_block_device_fd(fd, ret_dev);
640 }
641
642 /*
643 * Attempt to calculate the swap file offset on supported filesystems. On unsupported
644 * filesystems, a debug message is logged and ret_offset is set to UINT64_MAX.
645 */
646 static int calculate_swap_file_offset(const SwapEntry *swap, uint64_t *ret_offset) {
647 _cleanup_close_ int fd = -EBADF;
648 _cleanup_free_ struct fiemap *fiemap = NULL;
649 int r;
650
651 assert(swap);
652 assert(swap->path);
653 assert(swap->type == SWAP_FILE);
654 assert(ret_offset);
655
656 fd = open(swap->path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
657 if (fd < 0)
658 return log_debug_errno(errno, "Failed to open swap file %s to determine on-disk offset: %m", swap->path);
659
660 r = fd_verify_regular(fd);
661 if (r < 0)
662 return log_debug_errno(r, "Selected swap file is not a regular file.");
663
664 r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
665 if (r < 0)
666 return log_debug_errno(r, "Error checking %s for Btrfs filesystem: %m", swap->path);
667 if (r > 0) {
668 log_debug("%s: detection of swap file offset on Btrfs is not supported", swap->path);
669 *ret_offset = UINT64_MAX;
670 return 0;
671 }
672
673 r = read_fiemap(fd, &fiemap);
674 if (r < 0)
675 return log_debug_errno(r, "Unable to read extent map for '%s': %m", swap->path);
676
677 *ret_offset = fiemap->fm_extents[0].fe_physical / page_size();
678 return 0;
679 }
680
681 static int read_resume_files(dev_t *ret_resume, uint64_t *ret_resume_offset) {
682 _cleanup_free_ char *resume_str = NULL, *resume_offset_str = NULL;
683 uint64_t resume_offset;
684 dev_t resume;
685 int r;
686
687 assert(ret_resume);
688 assert(ret_resume_offset);
689
690 r = read_one_line_file("/sys/power/resume", &resume_str);
691 if (r < 0)
692 return log_debug_errno(r, "Error reading /sys/power/resume: %m");
693
694 r = parse_devnum(resume_str, &resume);
695 if (r < 0)
696 return log_debug_errno(r, "Error parsing /sys/power/resume device: %s: %m", resume_str);
697
698 r = read_one_line_file("/sys/power/resume_offset", &resume_offset_str);
699 if (r == -ENOENT) {
700 log_debug_errno(r, "Kernel does not support resume_offset; swap file offset detection will be skipped.");
701 resume_offset = 0;
702 } else if (r < 0)
703 return log_debug_errno(r, "Error reading /sys/power/resume_offset: %m");
704 else {
705 r = safe_atou64(resume_offset_str, &resume_offset);
706 if (r < 0)
707 return log_debug_errno(r, "Failed to parse value in /sys/power/resume_offset \"%s\": %m", resume_offset_str);
708 }
709
710 if (resume_offset > 0 && resume == 0)
711 log_debug("Warning: found /sys/power/resume_offset==%" PRIu64 ", but /sys/power/resume unset. Misconfiguration?",
712 resume_offset);
713
714 *ret_resume = resume;
715 *ret_resume_offset = resume_offset;
716 return 0;
717 }
718
719 /*
720 * Determine if the HibernateLocation matches the resume= (device) and resume_offset= (file).
721 */
722 static bool location_is_resume_device(const HibernateLocation *location, dev_t sys_resume, uint64_t sys_offset) {
723 if (!location)
724 return false;
725
726 return sys_resume > 0 &&
727 sys_resume == location->devno &&
728 (sys_offset == location->offset || (sys_offset > 0 && location->offset == UINT64_MAX));
729 }
730
731 /*
732 * Attempt to find the hibernation location by parsing /proc/swaps, /sys/power/resume, and
733 * /sys/power/resume_offset.
734 *
735 * Beware:
736 * Never use a device or file as location that hasn't been somehow specified by a user that would also be
737 * entrusted with full system memory access (for example via /sys/power/resume) or that isn't an already
738 * active swap area!
739 * Otherwise various security attacks might become possible, for example an attacker could silently attach
740 * such a device and circumvent full disk encryption when it would be automatically used for hibernation.
741 * Also, having a swap area on top of encryption is not per se enough to protect from all such attacks.
742 *
743 * Returns:
744 * 1 - Values are set in /sys/power/resume and /sys/power/resume_offset.
745 * ret_hibernate_location will represent matching /proc/swap entry if identified or NULL if not.
746 *
747 * 0 - No values are set in /sys/power/resume and /sys/power/resume_offset.
748 ret_hibernate_location will represent the highest priority swap with most remaining space discovered in /proc/swaps.
749 *
750 * Negative value in the case of error.
751 */
752 int find_hibernate_location(HibernateLocation **ret_hibernate_location) {
753 _cleanup_fclose_ FILE *f = NULL;
754 _cleanup_(hibernate_location_freep) HibernateLocation *hibernate_location = NULL;
755 dev_t sys_resume = 0; /* Unnecessary initialization to appease gcc */
756 uint64_t sys_offset = 0;
757 bool resume_match = false;
758 int r;
759
760 /* read the /sys/power/resume & /sys/power/resume_offset values */
761 r = read_resume_files(&sys_resume, &sys_offset);
762 if (r < 0)
763 return r;
764
765 f = fopen("/proc/swaps", "re");
766 if (!f) {
767 log_debug_errno(errno, "Failed to open /proc/swaps: %m");
768 return errno == ENOENT ? -EOPNOTSUPP : -errno; /* Convert swap not supported to a recognizable error */
769 }
770
771 (void) fscanf(f, "%*s %*s %*s %*s %*s\n");
772 for (unsigned i = 1;; i++) {
773 _cleanup_(swap_entry_freep) SwapEntry *swap = NULL;
774 _cleanup_free_ char *type = NULL;
775 uint64_t swap_offset = 0;
776 int k;
777
778 swap = new(SwapEntry, 1);
779 if (!swap)
780 return -ENOMEM;
781
782 *swap = (SwapEntry) {
783 .type = _SWAP_TYPE_INVALID,
784 };
785
786 k = fscanf(f,
787 "%ms " /* device/file path */
788 "%ms " /* type of swap */
789 "%" PRIu64 /* swap size */
790 "%" PRIu64 /* used */
791 "%i\n", /* priority */
792 &swap->path, &type, &swap->size, &swap->used, &swap->priority);
793 if (k == EOF)
794 break;
795 if (k != 5) {
796 log_debug("Failed to parse /proc/swaps:%u, ignoring", i);
797 continue;
798 }
799
800 if (streq(type, "file")) {
801
802 if (endswith(swap->path, "\\040(deleted)")) {
803 log_debug("Ignoring deleted swap file '%s'.", swap->path);
804 continue;
805 }
806
807 swap->type = SWAP_FILE;
808
809 r = calculate_swap_file_offset(swap, &swap_offset);
810 if (r < 0)
811 return r;
812
813 } else if (streq(type, "partition")) {
814 const char *fn;
815
816 fn = path_startswith(swap->path, "/dev/");
817 if (fn && startswith(fn, "zram")) {
818 log_debug("%s: ignoring zram swap", swap->path);
819 continue;
820 }
821
822 swap->type = SWAP_BLOCK;
823
824 } else {
825 log_debug("%s: swap type %s is unsupported for hibernation, ignoring", swap->path, type);
826 continue;
827 }
828
829 /* prefer resume device or highest priority swap with most remaining space */
830 if (sys_resume == 0) {
831 if (hibernate_location && swap->priority < hibernate_location->swap->priority) {
832 log_debug("%s: ignoring device with lower priority", swap->path);
833 continue;
834 }
835 if (hibernate_location &&
836 (swap->priority == hibernate_location->swap->priority
837 && swap->size - swap->used < hibernate_location->swap->size - hibernate_location->swap->used)) {
838 log_debug("%s: ignoring device with lower usable space", swap->path);
839 continue;
840 }
841 }
842
843 dev_t swap_devno;
844 r = swap_device_to_devnum(swap, &swap_devno);
845 if (r < 0)
846 return log_debug_errno(r, "%s: failed to query device number: %m", swap->path);
847 if (swap_devno == 0)
848 return log_debug_errno(SYNTHETIC_ERRNO(ENODEV), "%s: not backed by block device.", swap->path);
849
850 hibernate_location = hibernate_location_free(hibernate_location);
851 hibernate_location = new(HibernateLocation, 1);
852 if (!hibernate_location)
853 return -ENOMEM;
854
855 *hibernate_location = (HibernateLocation) {
856 .devno = swap_devno,
857 .offset = swap_offset,
858 .swap = TAKE_PTR(swap),
859 };
860
861 /* if the swap is the resume device, stop the loop */
862 if (location_is_resume_device(hibernate_location, sys_resume, sys_offset)) {
863 log_debug("%s: device matches configured resume settings.", hibernate_location->swap->path);
864 resume_match = true;
865 break;
866 }
867
868 log_debug("%s: is a candidate device.", hibernate_location->swap->path);
869 }
870
871 /* We found nothing at all */
872 if (!hibernate_location)
873 return log_debug_errno(SYNTHETIC_ERRNO(ENOSYS),
874 "No possible swap partitions or files suitable for hibernation were found in /proc/swaps.");
875
876 /* resume= is set but a matching /proc/swaps entry was not found */
877 if (sys_resume != 0 && !resume_match)
878 return log_debug_errno(SYNTHETIC_ERRNO(ENOSYS),
879 "No swap partitions or files matching resume config were found in /proc/swaps.");
880
881 if (hibernate_location->offset == UINT64_MAX) {
882 if (sys_offset == 0)
883 return log_debug_errno(SYNTHETIC_ERRNO(ENOSYS), "Offset detection failed and /sys/power/resume_offset is not set.");
884
885 hibernate_location->offset = sys_offset;
886 }
887
888 if (resume_match)
889 log_debug("Hibernation will attempt to use swap entry with path: %s, device: %u:%u, offset: %" PRIu64 ", priority: %i",
890 hibernate_location->swap->path, major(hibernate_location->devno), minor(hibernate_location->devno),
891 hibernate_location->offset, hibernate_location->swap->priority);
892 else
893 log_debug("/sys/power/resume is not configured; attempting to hibernate with path: %s, device: %u:%u, offset: %" PRIu64 ", priority: %i",
894 hibernate_location->swap->path, major(hibernate_location->devno), minor(hibernate_location->devno),
895 hibernate_location->offset, hibernate_location->swap->priority);
896
897 *ret_hibernate_location = TAKE_PTR(hibernate_location);
898
899 if (resume_match)
900 return 1;
901
902 return 0;
903 }
904
905 static bool enough_swap_for_hibernation(void) {
906 _cleanup_free_ char *active = NULL;
907 _cleanup_(hibernate_location_freep) HibernateLocation *hibernate_location = NULL;
908 unsigned long long act = 0;
909 int r;
910
911 if (getenv_bool("SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK") > 0)
912 return true;
913
914 r = find_hibernate_location(&hibernate_location);
915 if (r < 0)
916 return false;
917
918 /* If /sys/power/{resume,resume_offset} is configured but a matching entry
919 * could not be identified in /proc/swaps, user is likely using Btrfs with a swapfile;
920 * return true and let the system attempt hibernation.
921 */
922 if (r > 0 && !hibernate_location) {
923 log_debug("Unable to determine remaining swap space; hibernation may fail");
924 return true;
925 }
926
927 if (!hibernate_location)
928 return false;
929
930 r = get_proc_field("/proc/meminfo", "Active(anon)", WHITESPACE, &active);
931 if (r < 0) {
932 log_debug_errno(r, "Failed to retrieve Active(anon) from /proc/meminfo: %m");
933 return false;
934 }
935
936 r = safe_atollu(active, &act);
937 if (r < 0) {
938 log_debug_errno(r, "Failed to parse Active(anon) from /proc/meminfo: %s: %m", active);
939 return false;
940 }
941
942 r = act <= (hibernate_location->swap->size - hibernate_location->swap->used) * HIBERNATION_SWAP_THRESHOLD;
943 log_debug("%s swap for hibernation, Active(anon)=%llu kB, size=%" PRIu64 " kB, used=%" PRIu64 " kB, threshold=%.2g%%",
944 r ? "Enough" : "Not enough", act, hibernate_location->swap->size, hibernate_location->swap->used, 100*HIBERNATION_SWAP_THRESHOLD);
945
946 return r;
947 }
948
949 int read_fiemap(int fd, struct fiemap **ret) {
950 _cleanup_free_ struct fiemap *fiemap = NULL, *result_fiemap = NULL;
951 struct stat statinfo;
952 uint32_t result_extents = 0;
953 uint64_t fiemap_start = 0, fiemap_length;
954 const size_t n_extra = DIV_ROUND_UP(sizeof(struct fiemap), sizeof(struct fiemap_extent));
955
956 if (fstat(fd, &statinfo) < 0)
957 return log_debug_errno(errno, "Cannot determine file size: %m");
958 if (!S_ISREG(statinfo.st_mode))
959 return -ENOTTY;
960 fiemap_length = statinfo.st_size;
961
962 /* Zero this out in case we run on a file with no extents */
963 fiemap = calloc(n_extra, sizeof(struct fiemap_extent));
964 if (!fiemap)
965 return -ENOMEM;
966
967 result_fiemap = malloc_multiply(n_extra, sizeof(struct fiemap_extent));
968 if (!result_fiemap)
969 return -ENOMEM;
970
971 /* XFS filesystem has incorrect implementation of fiemap ioctl and
972 * returns extents for only one block-group at a time, so we need
973 * to handle it manually, starting the next fiemap call from the end
974 * of the last extent
975 */
976 while (fiemap_start < fiemap_length) {
977 *fiemap = (struct fiemap) {
978 .fm_start = fiemap_start,
979 .fm_length = fiemap_length,
980 .fm_flags = FIEMAP_FLAG_SYNC,
981 };
982
983 /* Find out how many extents there are */
984 if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0)
985 return log_debug_errno(errno, "Failed to read extents: %m");
986
987 /* Nothing to process */
988 if (fiemap->fm_mapped_extents == 0)
989 break;
990
991 /* Resize fiemap to allow us to read in the extents, result fiemap has to hold all
992 * the extents for the whole file. Add space for the initial struct fiemap. */
993 if (!greedy_realloc0((void**) &fiemap, n_extra + fiemap->fm_mapped_extents, sizeof(struct fiemap_extent)))
994 return -ENOMEM;
995
996 fiemap->fm_extent_count = fiemap->fm_mapped_extents;
997 fiemap->fm_mapped_extents = 0;
998
999 if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0)
1000 return log_debug_errno(errno, "Failed to read extents: %m");
1001
1002 /* Resize result_fiemap to allow us to copy in the extents */
1003 if (!greedy_realloc((void**) &result_fiemap,
1004 n_extra + result_extents + fiemap->fm_mapped_extents, sizeof(struct fiemap_extent)))
1005 return -ENOMEM;
1006
1007 memcpy(result_fiemap->fm_extents + result_extents,
1008 fiemap->fm_extents,
1009 sizeof(struct fiemap_extent) * fiemap->fm_mapped_extents);
1010
1011 result_extents += fiemap->fm_mapped_extents;
1012
1013 /* Highly unlikely that it is zero */
1014 if (_likely_(fiemap->fm_mapped_extents > 0)) {
1015 uint32_t i = fiemap->fm_mapped_extents - 1;
1016
1017 fiemap_start = fiemap->fm_extents[i].fe_logical +
1018 fiemap->fm_extents[i].fe_length;
1019
1020 if (fiemap->fm_extents[i].fe_flags & FIEMAP_EXTENT_LAST)
1021 break;
1022 }
1023 }
1024
1025 memcpy(result_fiemap, fiemap, sizeof(struct fiemap));
1026 result_fiemap->fm_mapped_extents = result_extents;
1027 *ret = TAKE_PTR(result_fiemap);
1028 return 0;
1029 }
1030
1031 int write_resume_config(dev_t devno, uint64_t offset, const char *device) {
1032 char offset_str[DECIMAL_STR_MAX(uint64_t)];
1033 _cleanup_free_ char *path = NULL;
1034 const char *devno_str;
1035 int r;
1036
1037 devno_str = FORMAT_DEVNUM(devno);
1038 xsprintf(offset_str, "%" PRIu64, offset);
1039
1040 if (!device) {
1041 r = device_path_make_canonical(S_IFBLK, devno, &path);
1042 if (r < 0)
1043 return log_error_errno(r,
1044 "Failed to format canonical device path for devno '" DEVNUM_FORMAT_STR "': %m",
1045 DEVNUM_FORMAT_VAL(devno));
1046 device = path;
1047 }
1048
1049 /* We write the offset first since it's safer. Note that this file is only available in 4.17+, so
1050 * fail gracefully if it doesn't exist and we're only overwriting it with 0. */
1051 r = write_string_file("/sys/power/resume_offset", offset_str, WRITE_STRING_FILE_DISABLE_BUFFER);
1052 if (r == -ENOENT) {
1053 if (offset != 0)
1054 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
1055 "Can't configure hibernation offset %" PRIu64 ", kernel does not support /sys/power/resume_offset. Refusing.",
1056 offset);
1057
1058 log_warning_errno(r, "/sys/power/resume_offset is unavailable, skipping writing swap file offset.");
1059 } else if (r < 0)
1060 return log_error_errno(r,
1061 "Failed to write swap file offset %s to /sys/power/resume_offset for device '%s': %m",
1062 offset_str, device);
1063 else
1064 log_debug("Wrote resume_offset=%s for device '%s' to /sys/power/resume_offset.",
1065 offset_str, device);
1066
1067 r = write_string_file("/sys/power/resume", devno_str, WRITE_STRING_FILE_DISABLE_BUFFER);
1068 if (r < 0)
1069 return log_error_errno(r,
1070 "Failed to write device '%s' (%s) to /sys/power/resume: %m",
1071 device, devno_str);
1072 log_debug("Wrote resume=%s for device '%s' to /sys/power/resume.", devno_str, device);
1073
1074 return 0;
1075 }
1076
1077 static int can_sleep_internal(const SleepConfig *sleep_config, SleepOperation operation, bool check_allowed);
1078
1079 static bool can_s2h(const SleepConfig *sleep_config) {
1080
1081 static const SleepOperation operations[] = {
1082 SLEEP_SUSPEND,
1083 SLEEP_HIBERNATE,
1084 };
1085
1086 int r;
1087
1088 if (!clock_supported(CLOCK_BOOTTIME_ALARM)) {
1089 log_debug("CLOCK_BOOTTIME_ALARM is not supported.");
1090 return false;
1091 }
1092
1093 for (size_t i = 0; i < ELEMENTSOF(operations); i++) {
1094 r = can_sleep_internal(sleep_config, operations[i], false);
1095 if (IN_SET(r, 0, -ENOSPC)) {
1096 log_debug("Unable to %s system.", sleep_operation_to_string(operations[i]));
1097 return false;
1098 }
1099 if (r < 0)
1100 return log_debug_errno(r, "Failed to check if %s is possible: %m", sleep_operation_to_string(operations[i]));
1101 }
1102
1103 return true;
1104 }
1105
1106 static int can_sleep_internal(
1107 const SleepConfig *sleep_config,
1108 SleepOperation operation,
1109 bool check_allowed) {
1110
1111 assert(operation >= 0);
1112 assert(operation < _SLEEP_OPERATION_MAX);
1113
1114 if (check_allowed && !sleep_config->allow[operation]) {
1115 log_debug("Sleep mode \"%s\" is disabled by configuration.", sleep_operation_to_string(operation));
1116 return false;
1117 }
1118
1119 if (operation == SLEEP_SUSPEND_THEN_HIBERNATE)
1120 return can_s2h(sleep_config);
1121
1122 if (can_sleep_state(sleep_config->states[operation]) <= 0 ||
1123 can_sleep_disk(sleep_config->modes[operation]) <= 0)
1124 return false;
1125
1126 if (operation == SLEEP_SUSPEND)
1127 return true;
1128
1129 if (!enough_swap_for_hibernation())
1130 return -ENOSPC;
1131
1132 return true;
1133 }
1134
1135 int can_sleep(SleepOperation operation) {
1136 _cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL;
1137 int r;
1138
1139 r = parse_sleep_config(&sleep_config);
1140 if (r < 0)
1141 return r;
1142
1143 return can_sleep_internal(sleep_config, operation, true);
1144 }
1145
1146 SleepConfig* free_sleep_config(SleepConfig *sc) {
1147 if (!sc)
1148 return NULL;
1149
1150 for (SleepOperation i = 0; i < _SLEEP_OPERATION_MAX; i++) {
1151 strv_free(sc->modes[i]);
1152 strv_free(sc->states[i]);
1153 }
1154
1155 return mfree(sc);
1156 }
1157
1158 static const char* const sleep_operation_table[_SLEEP_OPERATION_MAX] = {
1159 [SLEEP_SUSPEND] = "suspend",
1160 [SLEEP_HIBERNATE] = "hibernate",
1161 [SLEEP_HYBRID_SLEEP] = "hybrid-sleep",
1162 [SLEEP_SUSPEND_THEN_HIBERNATE] = "suspend-then-hibernate",
1163 };
1164
1165 DEFINE_STRING_TABLE_LOOKUP(sleep_operation, SleepOperation);