summaryrefslogtreecommitdiff
path: root/src/boot
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2017-12-11 22:04:46 +0100
committerLennart Poettering <lennart@poettering.net>2017-12-11 23:18:56 +0100
commit5caa3167ff98a29c1ef9bbe9c4fddf6aa1cd8888 (patch)
tree78ad8a96b929bdb89fe58c18cf1eaf794fb0b34c /src/boot
parent4a0e9289bf443fec9fc56af25f90e2a100ba7a41 (diff)
downloadsystemd-5caa3167ff98a29c1ef9bbe9c4fddf6aa1cd8888.tar.gz
efi: rework find_esp() error propagation/logging a bit
This renames find_esp() to find_esp_and_warn() and tries to normalize its behaviour: 1. Change the error that is returned when we can't find the ESP to ENOKEY (from ENOENT). This way the error code can only mean one thing: that our search loop didn't find a good candidate. 2. Really log about all errors, except for ENOKEY and EACCES, and document the letter cases. 3. Normalize parameters to the call: separate out the path parameter in two: an input path and an output path. That way the memory management is clear: we will access the input parameter only for reading, and only write out the output parameter, using malloc() memory. Before the calling convention were quire surprising for internal API code, as the path parameter had to be malloc() memory and might and might not have changed. 4. Rename bootctl's find_esp_warn() to acquire_esp(), and make it a simple wrapper around find_esp_warn(), that basically just adds the friendly logging for the ENOKEY case. This rework removes double logging in a number of error cases, as we no longer log here in anything but ENOKEY, and leave that entirely to find_esp_warn(). 5. find_esp_and_warn() now takes a bool flag parameter "unprivileged_mode", which disables logging in the EACCES case, and skips privileged validation of the path. This makes the function less magic, and doesn't hide this internal silencing automatism from the caller anymore. With all that in place "bootctl list" and "bootctl status" work properly (or as good as they can) when I invoke the tools whithout privileges on my system where /boot is not world-readable
Diffstat (limited to 'src/boot')
-rw-r--r--src/boot/bootctl.c51
1 files changed, 38 insertions, 13 deletions
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index e733e206e4..52207661cf 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -61,19 +61,33 @@ static char *arg_path = NULL;
static bool arg_print_path = false;
static bool arg_touch_variables = true;
-static int find_esp_and_warn(uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) {
+static int acquire_esp(
+ bool unprivileged_mode,
+ uint32_t *ret_part,
+ uint64_t *ret_pstart,
+ uint64_t *ret_psize,
+ sd_id128_t *ret_uuid) {
+
+ char *np;
int r;
- r = find_esp(&arg_path, part, pstart, psize, uuid);
- if (r == -ENOENT)
+ /* Find the ESP, and log about errors. Note that find_esp_and_warn() will log in all error cases on its own,
+ * except for ENOKEY (which is good, we want to show our own message in that case, suggesting use of --path=)
+ * and EACCESS (only when we request unprivileged mode; in this case we simply eat up the error here, so that
+ * --list and --status work too, without noise about this). */
+
+ r = find_esp_and_warn(arg_path, unprivileged_mode, &np, ret_part, ret_pstart, ret_psize, ret_uuid);
+ if (r == -ENOKEY)
return log_error_errno(r,
- "Couldn't find EFI system partition. It is recommended to mount it to /boot.\n"
+ "Couldn't find EFI system partition. It is recommended to mount it to /boot or /efi.\n"
"Alternatively, use --path= to specify path to mount point.");
- else if (r < 0)
- return log_error_errno(r,
- "Couldn't find EFI system partition: %m");
+ if (r < 0)
+ return r;
+
+ free_and_replace(arg_path, np);
log_debug("Using EFI System Partition at %s.", arg_path);
+
return 0;
}
@@ -925,9 +939,12 @@ static int verb_status(int argc, char *argv[], void *userdata) {
sd_id128_t uuid = SD_ID128_NULL;
int r, k;
- r = find_esp_and_warn(NULL, NULL, NULL, &uuid);
+ r = acquire_esp(geteuid() != 0, NULL, NULL, NULL, &uuid);
if (arg_print_path) {
+ if (r == -EACCES) /* If we couldn't acquire the ESP path, log about access errors (which is the only
+ * error the find_esp_and_warn() won't log on its own) */
+ return log_error_errno(r, "Failed to determine ESP: %m");
if (r < 0)
return r;
@@ -935,6 +952,9 @@ static int verb_status(int argc, char *argv[], void *userdata) {
return 0;
}
+ r = 0; /* If we couldn't determine the path, then don't consider that a problem from here on, just show what we
+ * can show */
+
if (is_efi_boot()) {
_cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL;
sd_id128_t loader_part_uuid = SD_ID128_NULL;
@@ -997,13 +1017,18 @@ static int verb_status(int argc, char *argv[], void *userdata) {
}
static int verb_list(int argc, char *argv[], void *userdata) {
+ _cleanup_(boot_config_free) BootConfig config = {};
sd_id128_t uuid = SD_ID128_NULL;
- int r;
unsigned n;
+ int r;
- _cleanup_(boot_config_free) BootConfig config = {};
+ /* If we lack privileges we invoke find_esp_and_warn() in "unprivileged mode" here, which does two things: turn
+ * off logging about access errors and turn off potentially privileged device probing. Here we're interested in
+ * the latter but not the former, hence request the mode, and log about EACCES. */
- r = find_esp_and_warn(NULL, NULL, NULL, &uuid);
+ r = acquire_esp(geteuid() != 0, NULL, NULL, NULL, &uuid);
+ if (r == -EACCES) /* We really need the ESP path for this call, hence also log about access errors */
+ return log_error_errno(r, "Failed to determine ESP: %m");
if (r < 0)
return r;
@@ -1071,7 +1096,7 @@ static int verb_install(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
- r = find_esp_and_warn(&part, &pstart, &psize, &uuid);
+ r = acquire_esp(false, &part, &pstart, &psize, &uuid);
if (r < 0)
return r;
@@ -1106,7 +1131,7 @@ static int verb_remove(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
- r = find_esp_and_warn(NULL, NULL, NULL, &uuid);
+ r = acquire_esp(false, NULL, NULL, NULL, &uuid);
if (r < 0)
return r;