OLD | NEW |
1 #!/bin/sh -x | 1 #!/bin/sh -x |
2 | 2 |
3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 # | 6 # |
7 # /init script for use in factory install shim. Requires busybox in | 7 # /init script for use in factory install shim. Requires busybox in |
8 # /bin/busybox, and a symlink from /bin/sh -> busybox. | 8 # /bin/busybox, and a symlink from /bin/sh -> busybox. |
9 | 9 |
10 # USB card partition and mount point. | 10 # USB card partition and mount point. |
11 USB_DEVS="sdb3 sdc3 mmcblk1p3" | 11 USB_DEVS="sdb3 sdc3 mmcblk1p3" |
12 USB_SHIM_DEVS="sdb1 sdc1 mmcblk1p1" | |
13 USB_MNT=/usb | 12 USB_MNT=/usb |
14 REAL_USB_DEV= | 13 REAL_USB_DEV= |
15 DM_NAME= | 14 DM_NAME= |
16 | 15 |
17 DST= | 16 DST= |
18 | 17 |
19 STATEFUL_MNT=/stateful | 18 STATEFUL_MNT=/stateful |
20 STATE_DEV= | 19 STATE_DEV= |
21 | 20 |
22 LOG_DEV= | 21 LOG_DEV= |
23 LOG_FILE="/log/recovery.log" | 22 LOG_FILE="/log/recovery.log" |
24 | 23 |
25 TPM_B_LOCKED= | 24 TPM_B_LOCKED= |
26 TPM_PP_LOCKED= | 25 TPM_PP_LOCKED= |
27 | 26 |
28 # Developer script to run | |
29 SHIM_SCRIPT="$STATEFUL_MNT/userdir/runme" | |
30 SHIM_VBLOCK="$STATEFUL_MNT/userdir/runme.vblock" | |
31 | |
32 KERN_B_VBLOCK="$STATEFUL_MNT/vmlinuz_hd.vblock" | 27 KERN_B_VBLOCK="$STATEFUL_MNT/vmlinuz_hd.vblock" |
33 REAL_KERN_B_HASH= | 28 REAL_KERN_B_HASH= |
34 | 29 |
35 MOVE_MOUNTS="/sys /proc /dev" | 30 MOVE_MOUNTS="/sys /proc /dev" |
36 | 31 |
37 # To be updated to keep logging after move_mounts. | 32 # To be updated to keep logging after move_mounts. |
38 TTY_PATH="/dev/tty" | 33 TTY_PATH="/dev/tty" |
39 TAIL_PID= | 34 TAIL_PID= |
40 | 35 |
41 # Used to ensure the factory check only occurs with | 36 # Used to ensure the factory check only occurs with |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 dmsetup remove "$DM_NAME" | 163 dmsetup remove "$DM_NAME" |
169 | 164 |
170 # If we found a valid rootfs earlier, then we're done. | 165 # If we found a valid rootfs earlier, then we're done. |
171 USB_DEV="$REAL_USB_DEV" | 166 USB_DEV="$REAL_USB_DEV" |
172 [ -z "$USB_DEV" ] && return 1 | 167 [ -z "$USB_DEV" ] && return 1 |
173 set_unofficial_root || return 1 | 168 set_unofficial_root || return 1 |
174 mount_usb || return 1 | 169 mount_usb || return 1 |
175 return 0 | 170 return 0 |
176 } | 171 } |
177 | 172 |
178 # If this kernel image has been placed on a drive with only a | |
179 # stateful partition, root detection will rightly fail. However, | |
180 # we can still run a developer supplied script so we will pretend | |
181 # stateful is the root (USB_DEV). | |
182 find_shim_root() { | |
183 # Lock the TPM prior to using an untrusted root. | |
184 lock_tpm || return 1 | |
185 plog "\nSearching for an alternate recovery image . . ." | |
186 dlog -n "Waiting for $USB_SHIM_DEVS to appear" | |
187 for try in $(seq 20); do | |
188 plog " ." | |
189 for dev in $USB_SHIM_DEVS; do | |
190 if [ -b "/dev/${dev}" ]; then | |
191 USB_DEV="/dev/${dev}" | |
192 REAL_USB_DEV="$USB_DEV" | |
193 dlog "Found $USB_DEV" | |
194 set_unofficial_root || on_error | |
195 mount_usb || return 1 | |
196 return 0 | |
197 fi | |
198 done | |
199 sleep 1 | |
200 done | |
201 return 1 | |
202 } | |
203 | |
204 # If we have a verified recovery root, ensure all blocks are valid before | 173 # If we have a verified recovery root, ensure all blocks are valid before |
205 # handing it off to the installer. | 174 # handing it off to the installer. |
206 validate_recovery_root() { | 175 validate_recovery_root() { |
207 # Allow test recovery roots that are unverified. | 176 # Allow test recovery roots that are unverified. |
208 [ "$USB_DEV" = "/dev/dm-0" ] || return 0 | 177 [ "$USB_DEV" = "/dev/dm-0" ] || return 0 |
209 is_unofficial_root && return 0 | 178 is_unofficial_root && return 0 |
210 | 179 |
211 plog "Validating official recovery image . . . " | 180 plog "Validating official recovery image . . . " |
212 # Ensure the verified rootfs is fully intact or fail with no USB_DEV. | 181 # Ensure the verified rootfs is fully intact or fail with no USB_DEV. |
213 # REAL_USB_DEV is left intact. | 182 # REAL_USB_DEV is left intact. |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 verify_kernel_signature "$kdev" "/tmp/kern.keyblock" || continue | 391 verify_kernel_signature "$kdev" "/tmp/kern.keyblock" || continue |
423 log " done." | 392 log " done." |
424 return 0 | 393 return 0 |
425 done | 394 done |
426 | 395 |
427 log " failed." | 396 log " failed." |
428 dev_wait_or_error | 397 dev_wait_or_error |
429 return 0 | 398 return 0 |
430 } | 399 } |
431 | 400 |
432 # Never returns on success. | |
433 attempt_shim_script() { | |
434 # TODO(wad) Add static root of trust validation then remove the next line. | |
435 # http://crosbug/8390 | |
436 is_developer_mode || return 1 | |
437 | |
438 # Now we will either install a colocated Chromium OS image by | |
439 # checking the keys on KERN-B against any on disk (KERN-[ABC]) | |
440 # or by checking a signed script on stateful. | |
441 dlog "Checking for a shim script . . ." | |
442 [ -x "$SHIM_SCRIPT" ] || return 1 | |
443 [ -f "$SHIM_VBLOCK" ] || return 1 | |
444 log "Shim script and signing file found!" | |
445 | |
446 plog "Verifying the signature on the script . . ." | |
447 # Extract pubkey and check signature | |
448 if ! dev_sign_file --verify "$SHIM_SCRIPT" \ | |
449 --vblock "$SHIM_VBLOCK" \ | |
450 --keyblock /tmp/shim.keyblock; then | |
451 log " failed." | |
452 fi | |
453 log " done." | |
454 | |
455 # If we're not in developer mode, this will be terminal on failure. | |
456 check_key_or_wait /tmp/shim.keyblock | |
457 | |
458 # Run the user supplied script. It is done in the current environment | |
459 # to avoid needing anything other than the script/program on the partition. | |
460 log "Executing shim script . . ." | |
461 | |
462 dlog "calling $SHIM_SCRIPT with exec" | |
463 # Fix up the input/output | |
464 stop_log_file | |
465 set +x | |
466 exec &> "$TTY_PATH"1 | |
467 exec < "$TTY_PATH"1 | |
468 # Call the script! | |
469 exec "$SHIM_SCRIPT" | |
470 | |
471 # Never reached. | |
472 save_log_file | |
473 return 0 | |
474 } | |
475 | |
476 get_kern_b_device() { | 401 get_kern_b_device() { |
477 # TODO(wad) By changing boot priority, could we end up | 402 # TODO(wad) By changing boot priority, could we end up |
478 # checking the recovery image or the recovery image could not | 403 # checking the recovery image or the recovery image could not |
479 # be in slot A. In that case, it should fail in normal mode. | 404 # be in slot A. In that case, it should fail in normal mode. |
480 KERN_B_DEV=${REAL_USB_DEV%[0-9]*}4 | 405 KERN_B_DEV=${REAL_USB_DEV%[0-9]*}4 |
481 if [ ! -b "${KERN_B_DEV}" ]; then | 406 if [ ! -b "${KERN_B_DEV}" ]; then |
482 return 1 | 407 return 1 |
483 fi | 408 fi |
484 return 0 | 409 return 0 |
485 } | 410 } |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 set_unofficial_root() { | 534 set_unofficial_root() { |
610 UNOFFICIAL_ROOT=1 | 535 UNOFFICIAL_ROOT=1 |
611 return 0 | 536 return 0 |
612 } | 537 } |
613 | 538 |
614 recover_system() { | 539 recover_system() { |
615 local source=$(strip_partition "$REAL_USB_DEV") | 540 local source=$(strip_partition "$REAL_USB_DEV") |
616 dlog "Beginning system recovery from $source" | 541 dlog "Beginning system recovery from $source" |
617 | 542 |
618 recovery_wait | 543 recovery_wait |
619 | 544 |
620 if is_unofficial_root; then | |
621 dlog "Attempting to use shim . . ." | |
622 # Mounting read only so a journal is not needed. | |
623 # If it fails, we can still proceed on a normal recovery path. | |
624 mount -n -o ro -t ext2 "$STATE_DEV" "$STATEFUL_MNT" | |
625 attempt_shim_script # never returns on success. | |
626 umount "$STATEFUL_MNT" | |
627 fi | |
628 | |
629 # If we're not running a developer script then we're either | 545 # If we're not running a developer script then we're either |
630 # installing a developer image or an official one. If we're | 546 # installing a developer image or an official one. If we're |
631 # in normal recovery mode, then we require that the KERN-B | 547 # in normal recovery mode, then we require that the KERN-B |
632 # on the recovery image matches the hash on the command line. | 548 # on the recovery image matches the hash on the command line. |
633 # In developer mode, we will just check the keys. | 549 # In developer mode, we will just check the keys. |
634 verify_install_kernel || return 1 | 550 verify_install_kernel || return 1 |
635 | 551 |
636 # Only clear on full installs. Shim scripts can call tpmc if they | 552 # Only clear on full installs. Shim scripts can call tpmc if they |
637 # like. Only bGlobalLock will be in place in advance. | 553 # like. Only bGlobalLock will be in place in advance. |
638 clear_tpm || return 1 | 554 clear_tpm || return 1 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
739 export_args $(cat /proc/cmdline | sed -e 's/"[^"]*"/DROPPED/g') | 655 export_args $(cat /proc/cmdline | sed -e 's/"[^"]*"/DROPPED/g') |
740 | 656 |
741 if is_developer_mode; then | 657 if is_developer_mode; then |
742 log "! Your computer's developer mode switch is in the ENABLED position." | 658 log "! Your computer's developer mode switch is in the ENABLED position." |
743 log "!" | 659 log "!" |
744 log "! If this is unintentional, you should power off and toggle it back " | 660 log "! If this is unintentional, you should power off and toggle it back " |
745 log "! after recovery is completed." | 661 log "! after recovery is completed." |
746 log "" | 662 log "" |
747 fi | 663 fi |
748 | 664 |
749 if find_official_root || find_developer_root || find_shim_root; then | 665 if find_official_root || find_developer_root; then |
750 log " found." | 666 log " found." |
751 else | 667 else |
752 log " not found." | 668 log " not found." |
753 on_error | 669 on_error |
754 fi | 670 fi |
755 | 671 |
756 # Extract the real boot source which may be masked by dm-verity. | 672 # Extract the real boot source which may be masked by dm-verity. |
757 get_stateful_dev || on_error | 673 get_stateful_dev || on_error |
758 | 674 |
759 # Check if we want to run from RAM, in the factory. | 675 # Check if we want to run from RAM, in the factory. |
(...skipping 16 matching lines...) Expand all Loading... |
776 | 692 |
777 # Always lock the TPM. If a NVRAM reset is ever needed, we can change it. | 693 # Always lock the TPM. If a NVRAM reset is ever needed, we can change it. |
778 lock_tpm || on_error | 694 lock_tpm || on_error |
779 | 695 |
780 # Perform a full device mapper root validation to avoid any unexpected | 696 # Perform a full device mapper root validation to avoid any unexpected |
781 # failures during postinst. It also allows us to detect if the root is | 697 # failures during postinst. It also allows us to detect if the root is |
782 # intentionally mismatched - such as during Chromium OS recovery with a | 698 # intentionally mismatched - such as during Chromium OS recovery with a |
783 # Chrome OS recovery kernel. | 699 # Chrome OS recovery kernel. |
784 if ! validate_recovery_root; then | 700 if ! validate_recovery_root; then |
785 is_developer_mode || on_error | 701 is_developer_mode || on_error |
786 find_developer_root || find_shim_root || on_error | 702 find_developer_root || on_error |
787 log " found." | 703 log " found." |
788 # This logic is duplicated to avoid double validating factory media. It | 704 # This logic is duplicated to avoid double validating factory media. It |
789 # will only be hit if a verified root can be mounted but is actually not | 705 # will only be hit if a verified root can be mounted but is actually not |
790 # intact. | 706 # intact. |
791 get_stateful_dev || on_error | 707 get_stateful_dev || on_error |
792 fi | 708 fi |
793 | 709 |
794 get_dst || on_error | 710 get_dst || on_error |
795 | 711 |
796 recover_system || on_error | 712 recover_system || on_error |
(...skipping 16 matching lines...) Expand all Loading... |
813 exit 0 | 729 exit 0 |
814 } | 730 } |
815 | 731 |
816 # Make this source-able for testing. | 732 # Make this source-able for testing. |
817 if [ "$0" = "/init" ]; then | 733 if [ "$0" = "/init" ]; then |
818 main "$@" | 734 main "$@" |
819 # Should never reach here. | 735 # Should never reach here. |
820 exit 1 | 736 exit 1 |
821 fi | 737 fi |
822 | 738 |
OLD | NEW |