diff --git a/man/systemd-bless-boot.service.xml b/man/systemd-bless-boot.service.xml index 86a3fac799..eb1d345fb8 100644 --- a/man/systemd-bless-boot.service.xml +++ b/man/systemd-bless-boot.service.xml @@ -57,13 +57,17 @@ - The current status of the boot loader entry file or unified kernel image file is shown. This - outputs one of good, bad, indeterminate, - clean, depending on the state and previous invocations of the command. The string - indeterminate is shown initially after boot, before it has been marked as "good" or - "bad". The string good is shown after the boot was marked as "good" with the - command below, and "bad" conversely after the command was - invoked. The string clean is returned when boot counting is currently not in effect. + The current status of the boot loader entry file or unified kernel image file is + shown. This outputs one of good, bad, + indeterminate, clean, dirty, depending on + the state and previous invocations of the command. The string indeterminate is + shown initially after boot, before it has been marked as "good" or "bad". The string + good is shown after the boot was marked as "good" with the + command below, and "bad" conversely after the command was invoked. The string + clean is returned when boot counting is currently not in effect (which includes + the case where the current entry was already marked as persistently good). The string + dirty is returned when the system is booted up with a known-bad kernel (i.e. one + where the tries left counter has previously reached zero already). This command is implied if no command argument is specified. @@ -96,9 +100,13 @@ - This command undoes any marking of the current boot loader entry file or unified kernel image - file as good or bad. This is implemented by renaming the boot loader entry file or unified kernel image file - back to the path encoded in the LoaderBootCountPath EFI variable. + This command undoes any marking of the current boot loader entry file or unified + kernel image file as good or bad. This is implemented by renaming the boot loader entry file or + unified kernel image file back to the path encoded in the LoaderBootCountPath EFI + variable. Note that operation will fail if the current kernel is not booted with boot counting + enabled (i.e. if the EFI variable is not set). If the boot counter already reached zero tries left on + a previous boot this operation will fail too: once an entry is marked it can + only be reset to again, but not to . diff --git a/src/bless-boot/bless-boot.c b/src/bless-boot/bless-boot.c index c41a948549..e0143d9734 100644 --- a/src/bless-boot/bless-boot.c +++ b/src/bless-boot/bless-boot.c @@ -372,7 +372,14 @@ static int verb_status(int argc, char *argv[], void *userdata) { } if (faccessat(fd, skip_leading_slash(path), F_OK, 0) >= 0) { - puts("indeterminate"); + /* If the item we booted with still exists under its name, it means we have not + * change the current boot's marking so far. This may have two reasons: because we + * simply didn't do that yet but still plan to, or because the left tries counter is + * already at zero, hence we cannot further decrease it to mark it even + * "worse"... Here we check the current counter to detect the latter case and return + * "dirty", since the item is already marked bad from a previous boot, but otherwise + * report "indeterminate" since we just didn't make a decision yet. */ + puts(left == 0 ? "dirty" : "indeterminate"); return 0; } if (errno != ENOENT) @@ -402,10 +409,10 @@ static int verb_status(int argc, char *argv[], void *userdata) { static int verb_set(int argc, char *argv[], void *userdata) { _cleanup_free_ char *path = NULL, *prefix = NULL, *suffix = NULL, *good = NULL, *bad = NULL; const char *target, *source1, *source2; - uint64_t done; + uint64_t left, done; int r; - r = acquire_boot_count_path(&path, &prefix, NULL, &done, &suffix); + r = acquire_boot_count_path(&path, &prefix, &left, &done, &suffix); if (r == -EUNATCH) /* acquire_boot_count_path() won't log on its own for this specific error */ return log_error_errno(r, "Not booted with boot counting in effect."); if (r < 0) @@ -434,6 +441,10 @@ static int verb_set(int argc, char *argv[], void *userdata) { source2 = good; /* Maybe this boot was previously marked as 'good'? */ } else { assert(streq(argv[0], "indeterminate")); + + if (left == 0) + return log_error_errno(r, "Current boot entry was already marked bad in a previous boot, cannot reset to indeterminate."); + target = path; source1 = good; source2 = bad;