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;
}
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;
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;
}
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;
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;
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;
/********************************************************************************/
static int verify_esp(
- bool searching,
const char *p,
+ bool searching,
+ bool unprivileged_mode,
uint32_t *ret_part,
uint64_t *ret_pstart,
uint64_t *ret_psize,
struct statfs sfs;
sd_id128_t uuid = SD_ID128_NULL;
uint32_t part = 0;
- bool quiet;
int r;
assert(p);
- /* Non-root user can only check the status, so if an error occured in the following,
- * it does not cause any issues. Let's silence the error messages. */
- quiet = geteuid() != 0;
+ /* Non-root user can only check the status, so if an error occured in the following, it does not cause any
+ * issues. Let's also, silence the error messages. */
if (statfs(p, &sfs) < 0) {
/* If we are searching for the mount point, don't generate a log message if we can't find the path */
if (errno == ENOENT && searching)
return -ENOENT;
- return log_full_errno(quiet && errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,
+ return log_full_errno(unprivileged_mode && errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,
"Failed to check file system type of \"%s\": %m", p);
}
}
if (stat(p, &st) < 0)
- return log_full_errno(quiet && errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,
+ return log_full_errno(unprivileged_mode && errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,
"Failed to determine block device node of \"%s\": %m", p);
if (major(st.st_dev) == 0) {
t2 = strjoina(p, "/..");
r = stat(t2, &st2);
if (r < 0)
- return log_full_errno(quiet && errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,
+ return log_full_errno(unprivileged_mode && errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,
"Failed to determine block device node of parent of \"%s\": %m", p);
if (st.st_dev == st2.st_dev) {
/* In a container we don't have access to block devices, skip this part of the verification, we trust the
* container manager set everything up correctly on its own. Also skip the following verification for non-root user. */
- if (detect_container() > 0 || geteuid() != 0)
+ if (detect_container() > 0 || unprivileged_mode)
goto finish;
#if HAVE_BLKID
return 0;
}
-int find_esp(char **path,
- uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) {
+int find_esp_and_warn(
+ const char *path,
+ bool unprivileged_mode,
+ char **ret_path,
+ uint32_t *ret_part,
+ uint64_t *ret_pstart,
+ uint64_t *ret_psize,
+ sd_id128_t *ret_uuid) {
- const char *p;
int r;
- if (*path)
- return verify_esp(false, *path, part, pstart, psize, uuid);
-
- FOREACH_STRING(p, "/efi", "/boot", "/boot/efi") {
+ /* This logs about all errors except:
+ *
+ * -ENOKEY → when we can't find the partition
+ * -EACCESS → when unprivileged_mode is true, and we can't access something
+ */
- r = verify_esp(true, p, part, pstart, psize, uuid);
- if (IN_SET(r, -ENOENT, -EADDRNOTAVAIL)) /* This one is not it */
- continue;
+ if (path) {
+ r = verify_esp(path, false, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid);
if (r < 0)
return r;
- *path = strdup(p);
- if (!*path)
+ goto found;
+ }
+
+ FOREACH_STRING(path, "/efi", "/boot", "/boot/efi") {
+
+ r = verify_esp(path, true, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid);
+ if (r >= 0)
+ goto found;
+ if (!IN_SET(r, -ENOENT, -EADDRNOTAVAIL)) /* This one is not it */
+ return r;
+ }
+
+ /* No logging here */
+ return -ENOKEY;
+
+found:
+ if (ret_path) {
+ char *c;
+
+ c = strdup(path);
+ if (!c)
return log_oom();
- return 0;
+ *ret_path = c;
}
- return -ENOENT;
+ return 0;
}
return entry->show_title ?: entry->title ?: entry->filename;
}
-int find_esp(char **path,
- uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid);
+int find_esp_and_warn(const char *path, bool unprivileged_mode, char **ret_path, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid);
static int load_kexec_kernel(void) {
_cleanup_(boot_config_free) BootConfig config = {};
- _cleanup_free_ char *kernel = NULL, *initrd = NULL, *options = NULL;
+ _cleanup_free_ char *where = NULL, *kernel = NULL, *initrd = NULL, *options = NULL;
const BootEntry *e;
pid_t pid;
int r;
return 0;
}
- r = find_esp(&arg_esp_path, NULL, NULL, NULL, NULL);
- if (r < 0)
- return log_error_errno(r, "Cannot find the ESP partition mount point: %m");
+ r = find_esp_and_warn(arg_esp_path, false, &where, NULL, NULL, NULL, NULL);
+ if (r == -ENOKEY) /* find_esp_and_warn() doesn't warn about this case */
+ return log_error_errno(r, "Cannot find the ESP partition mount point.");
+ if (r < 0) /* But it logs about all these cases, hence don't log here again */
+ return r;
- r = boot_entries_load_config(arg_esp_path, &config);
+ r = boot_entries_load_config(where, &config);
if (r < 0)
- return log_error_errno(r, "Failed to load bootspec config from \"%s/loader\": %m",
- arg_esp_path);
+ return log_error_errno(r, "Failed to load bootspec config from \"%s/loader\": %m", where);
if (config.default_entry < 0) {
log_error("No entry suitable as default, refusing to guess.");
return -EINVAL;
}
- kernel = path_join(NULL, arg_esp_path, e->kernel);
+ kernel = path_join(NULL, where, e->kernel);
if (!strv_isempty(e->initrd))
- initrd = path_join(NULL, arg_esp_path, *e->initrd);
+ initrd = path_join(NULL, where, *e->initrd);
options = strv_join(e->options, " ");
if (!options)
return log_oom();