Files
snapd/boot/errors.go
Ian Johnson 473bcaa3d0 boot/bootstate20: reboot to rollback to previous kernel
We currently have a bug where we when we go to try a kernel snap revision that
was booted, if it fails verification somehow in the initramfs, we decide to
mount the old kernel snap even though we are running the new kernel snap. This
is problematic for things like kernel modules and firmware which are not
guaranteed to be compatible across kernel snap revisions.

The correct thing to do, which this commit implements, is to request a reboot
from the initramfs when we encounter this situation, as this will indicate to
the bootloader that the boot of the new kernel snap failed and that it should
rollback and boot the old kernel, in which case we will make the correct and
obvious choice in the initramfs to mount/use the old kernel, which fixes the
bug.

We simulate the reboot in tests with a panic.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>
2020-08-24 12:29:49 -05:00

50 lines
1.4 KiB
Go

// -*- Mode: Go; indent-tabs-mode: t -*-
/*
* Copyright (C) 2020 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package boot
import (
"errors"
"fmt"
)
// trySnapError is an error that only applies to the try snaps where multiple
// snaps are returned, this is mainly and primarily used in revisions().
type trySnapError string
func (sre trySnapError) Error() string {
return string(sre)
}
func newTrySnapErrorf(format string, args ...interface{}) error {
return trySnapError(fmt.Sprintf(format, args...))
}
// isTrySnapError returns true if the given error is an error resulting from
// accessing information about the try snap or the trying status.
func isTrySnapError(err error) bool {
switch err.(type) {
case trySnapError:
return true
}
return false
}
var errTrySnapFallback = errors.New("fallback to original snap")