Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/bin/sh | 1 #!/bin/sh |
| 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 # This script can change key (usually developer keys) and kernel config | 7 # This script can change key (usually developer keys) and kernel config |
| 8 # of a kernels on SSD. | 8 # of a kernels on SSD. |
| 9 | 9 |
| 10 SCRIPT_BASE="$(dirname "$0")" | 10 SCRIPT_BASE="$(dirname "$0")" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 52 # Prints messages (in parameters) in debug mode | 52 # Prints messages (in parameters) in debug mode |
| 53 debug_msg() { | 53 debug_msg() { |
| 54 if is_debug_mode; then | 54 if is_debug_mode; then |
| 55 echo "DEBUG: $*" 1>&2 | 55 echo "DEBUG: $*" 1>&2 |
| 56 fi | 56 fi |
| 57 } | 57 } |
| 58 | 58 |
| 59 # Removes rootfs verification from kernel boot parameter | 59 # Removes rootfs verification from kernel boot parameter |
| 60 remove_rootfs_verification() { | 60 remove_rootfs_verification() { |
| 61 echo "$*" | sed ' | 61 echo "$*" | sed ' |
| 62 s|dm_verity[^ ]\+||g | |
| 63 s| ro | rw | | |
| 64 s|verity /dev/sd%D%P /dev/sd%D%P || | |
| 65 s| root=/dev/dm-0 | root=/dev/sd%D%P | | 62 s| root=/dev/dm-0 | root=/dev/sd%D%P | |
| 66 s|dm="[^"]\+" ||' | 63 s| dm_verity[^=]*=[-0-9]*||g |
| 64 s| dm="[^"]*"|| | |
| 65 s| ro | rw |' | |
| 66 } | |
| 67 | |
| 68 # Checks if rootfs verification is enabled from kernel boot parameter | |
| 69 is_rootfs_verification_enabled() { | |
| 70 echo "$*" | grep -q 'root=/dev/dm-0' | |
|
gauravsh
2010/11/05 20:20:02
is looking for dm_verity a more robust test for th
Hung-Te
2010/11/06 07:40:55
Images built with --noenable_rootfs_verification w
| |
| 67 } | 71 } |
| 68 | 72 |
| 69 # Wrapped version of dd | 73 # Wrapped version of dd |
| 70 mydd() { | 74 mydd() { |
| 71 # oflag=sync is safer, but since we need bs=512, syncing every block would be | 75 # oflag=sync is safer, but since we need bs=512, syncing every block would be |
| 72 # very slow. | 76 # very slow. |
| 73 dd "$@" >"$EXEC_LOG" 2>&1 || | 77 dd "$@" >"$EXEC_LOG" 2>&1 || |
| 74 err_die "Failed in [dd $@], Message: $(cat "$EXEC_LOG")" | 78 err_die "Failed in [dd $@], Message: $(cat "$EXEC_LOG")" |
| 75 } | 79 } |
| 76 | 80 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 96 | 100 |
| 97 # reasonable size for current kernel partition | 101 # reasonable size for current kernel partition |
| 98 local min_kernel_size=32000 | 102 local min_kernel_size=32000 |
| 99 local max_kernel_size=65536 | 103 local max_kernel_size=65536 |
| 100 local resigned_kernels=0 | 104 local resigned_kernels=0 |
| 101 | 105 |
| 102 for kernel_index in 2 4; do | 106 for kernel_index in 2 4; do |
| 103 local old_blob="$(make_temp_file)" | 107 local old_blob="$(make_temp_file)" |
| 104 local new_blob="$(make_temp_file)" | 108 local new_blob="$(make_temp_file)" |
| 105 local name="$(cros_kernel_name $kernel_index)" | 109 local name="$(cros_kernel_name $kernel_index)" |
| 110 local rootfs_index="$(($kernel_index + 1))" | |
| 106 | 111 |
| 107 debug_msg "Probing $name information" | 112 debug_msg "Probing $name information" |
| 108 local offset size | 113 local offset size |
| 109 offset="$(partoffset "$ssd_device" "$kernel_index")" || | 114 offset="$(partoffset "$ssd_device" "$kernel_index")" || |
| 110 err_die "Failed to get partition $kernel_index offset from $ssd_device" | 115 err_die "Failed to get partition $kernel_index offset from $ssd_device" |
| 111 size="$(partsize "$ssd_device" "$kernel_index")" || | 116 size="$(partsize "$ssd_device" "$kernel_index")" || |
| 112 err_die "Failed to get partition $kernel_index size from $ssd_device" | 117 err_die "Failed to get partition $kernel_index size from $ssd_device" |
| 113 if [ ! $size -gt $min_kernel_size ]; then | 118 if [ ! $size -gt $min_kernel_size ]; then |
| 114 echo "WARNING: $name seems too small ($size), ignored." | 119 echo "INFO: $name seems too small ($size), ignored." |
| 115 continue | 120 continue |
| 116 fi | 121 fi |
| 117 if [ ! $size -le $max_kernel_size ]; then | 122 if [ ! $size -le $max_kernel_size ]; then |
| 118 echo "WARNING: $name seems too large ($size), ignored." | 123 echo "INFO: $name seems too large ($size), ignored." |
| 119 continue | 124 continue |
| 120 fi | 125 fi |
| 121 | 126 |
| 122 debug_msg "Reading $name from partition $kernel_index" | 127 debug_msg "Reading $name from partition $kernel_index" |
| 123 mydd if="$ssd_device" of="$old_blob" bs=$bs skip=$offset count=$size | 128 mydd if="$ssd_device" of="$old_blob" bs=$bs skip=$offset count=$size |
| 124 | 129 |
| 125 debug_msg "Checking if $name is valid" | 130 debug_msg "Checking if $name is valid" |
| 126 local old_kernel_config | 131 local old_kernel_config |
| 127 if ! old_kernel_config="$(dump_kernel_config "$old_blob" 2>"$EXEC_LOG")" | 132 if ! old_kernel_config="$(dump_kernel_config "$old_blob" 2>"$EXEC_LOG")" |
| 128 then | 133 then |
| 129 debug_msg "dump_kernel_config error message: $(cat "$EXEC_LOG")" | 134 debug_msg "dump_kernel_config error message: $(cat "$EXEC_LOG")" |
| 130 echo "WARNING: $name: no kernel boot information, ignored." | 135 echo "INFO: $name: no kernel boot information, ignored." |
| 131 continue | 136 continue |
| 132 fi | 137 fi |
| 133 | 138 |
| 134 debug_msg "Decide and prepare signing parameters" | 139 debug_msg "Re-signing $name from $old_blob to $new_blob" |
| 135 local resign_command | 140 debug_msg "Using key: $KERNEL_DATAKEY" |
| 136 # TODO(hungte) $KERNEL_KEYBLOCK and $new_kernel_config should also be | |
| 137 # quoted, but quoting inside would cause extra quote... We should find some | |
| 138 # better way to do this, for example using eval. | |
| 139 if [ ${FLAGS_remove_rootfs_verification} = $FLAGS_TRUE ]; then | |
| 140 local new_kernel_config_file="$(make_temp_file)" | |
| 141 remove_rootfs_verification "$old_kernel_config" >"$new_kernel_config_file" | |
| 142 resign_command="--config $new_kernel_config_file" | |
| 143 debug_msg "New kernel config: $(cat $new_kernel_config_file)" | |
| 144 echo "$name: Disabled rootfs verification." | |
| 145 else | |
| 146 resign_command="--vblockonly --keyblock $KERNEL_KEYBLOCK" | |
| 147 fi | |
| 148 | 141 |
| 149 debug_msg "Re-signing $name from $old_blob to $new_blob" | |
| 150 debug_msg "Using key: $KERNEL_DATAKEY, command: $resign_command" | |
| 151 vbutil_kernel \ | 142 vbutil_kernel \ |
| 152 --repack "$new_blob" \ | 143 --repack "$new_blob" \ |
| 153 $resign_command \ | 144 --vblockonly --keyblock "$KERNEL_KEYBLOCK" \ |
| 154 --signprivate "$KERNEL_DATAKEY" \ | 145 --signprivate "$KERNEL_DATAKEY" \ |
| 155 --oldblob "$old_blob" >"$EXEC_LOG" 2>&1 || | 146 --oldblob "$old_blob" >"$EXEC_LOG" 2>&1 || |
| 156 err_die "Failed to resign $name. Message: $(cat "$EXEC_LOG")" | 147 err_die "Failed to resign $name. Message: $(cat "$EXEC_LOG")" |
| 157 | 148 |
| 158 debug_msg "Creating new kernel image (vboot+code+config)" | 149 debug_msg "Creating new kernel image (vboot+code+config)" |
| 159 local new_kern="$(make_temp_file)" | 150 local new_kern="$(make_temp_file)" |
| 160 cp "$old_blob" "$new_kern" | 151 cp "$old_blob" "$new_kern" |
| 161 mydd if="$new_blob" of="$new_kern" conv=notrunc | 152 mydd if="$new_blob" of="$new_kern" conv=notrunc |
| 162 | 153 |
| 154 if [ ${FLAGS_remove_rootfs_verification} = $FLAGS_FALSE ]; then | |
| 155 debug_msg "Bypassing rootfs verification check" | |
| 156 elif ! is_rootfs_verification_enabled "$old_kernel_config"; then | |
| 157 echo "INFO: $name: rootfs verification was not enabled." | |
| 158 else | |
| 159 debug_msg "Changing boot parameter to remove rootfs verification" | |
| 160 local new_kernel_config_file="$(make_temp_file)" | |
| 161 remove_rootfs_verification "$old_kernel_config" >"$new_kernel_config_file" | |
| 162 debug_msg "New kernel config: $(cat $new_kernel_config_file)" | |
| 163 vbutil_kernel \ | |
| 164 --repack "$new_blob" \ | |
| 165 --config "$new_kernel_config_file" \ | |
| 166 --signprivate "$KERNEL_DATAKEY" \ | |
| 167 --oldblob "$new_kern" >"$EXEC_LOG" 2>&1 || | |
| 168 err_die "Failed to resign $name. Message: $(cat "$EXEC_LOG")" | |
| 169 echo "$name: Disabled rootfs verification." | |
| 170 mydd if="$new_blob" of="$new_kern" conv=notrunc | |
| 171 fi | |
| 172 | |
| 163 if is_debug_mode; then | 173 if is_debug_mode; then |
| 164 debug_msg "for debug purposes, check *.dbgbin" | 174 debug_msg "for debug purposes, check *.dbgbin" |
| 165 cp "$old_blob" old_blob.dbgbin | 175 cp "$old_blob" old_blob.dbgbin |
| 166 cp "$new_blob" new_blob.dbgbin | 176 cp "$new_blob" new_blob.dbgbin |
| 167 cp "$new_kern" new_kern.dbgbin | 177 cp "$new_kern" new_kern.dbgbin |
| 168 fi | 178 fi |
| 169 | 179 |
| 170 debug_msg "Verifying new kernel and keys" | 180 debug_msg "Verifying new kernel and keys" |
| 171 vbutil_kernel \ | 181 vbutil_kernel \ |
| 172 --verify "$new_kern" \ | 182 --verify "$new_kern" \ |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 188 debug_msg "Writing $name to partition $kernel_index" | 198 debug_msg "Writing $name to partition $kernel_index" |
| 189 mydd \ | 199 mydd \ |
| 190 if="$new_kern" \ | 200 if="$new_kern" \ |
| 191 of="$ssd_device" \ | 201 of="$ssd_device" \ |
| 192 seek=$offset \ | 202 seek=$offset \ |
| 193 bs=$bs \ | 203 bs=$bs \ |
| 194 count=$size \ | 204 count=$size \ |
| 195 conv=notrunc | 205 conv=notrunc |
| 196 resigned_kernels=$(($resigned_kernels + 1)) | 206 resigned_kernels=$(($resigned_kernels + 1)) |
| 197 | 207 |
| 208 debug_msg "Make the root filesystem writable if needed." | |
| 209 # TODO(hungte) for safety concern, a more robust way would be to: | |
| 210 # (1) change kernel config to ro | |
| 211 # (2) check if we can enable rw mount | |
| 212 # (3) change kernel config to rw | |
| 213 if [ ${FLAGS_remove_rootfs_verification} = $FLAGS_TRUE ]; then | |
| 214 local root_offset_sector=$(partoffset "$ssd_device" $rootfs_index) | |
| 215 local root_offset_bytes=$((root_offset_sector * 512)) | |
| 216 if ! is_ext2 "$ssd_device" "$root_offset_bytes"; then | |
| 217 debug_msg "Non-ext2 partition: $ssd_device$rootfs_index, skip." | |
| 218 elif ! rw_mount_disabled "$ssd_device" "$root_offset_bytes"; then | |
| 219 debug_msg "Root file system is writable. No need to modify." | |
| 220 else | |
| 221 # disable the RO ext2 hack | |
| 222 debug_msg "Disabling rootfs ext2 RO bit hack" | |
| 223 enable_rw_mount "$ssd_device" "$root_offset_bytes" >"$EXEC_LOG" 2>&1 || | |
| 224 err_die "Failed turning off rootfs RO bit. OS may be corrupted. " \ | |
| 225 "Message: $(cat "$EXEC_LOG")" | |
| 226 fi | |
| 227 fi | |
| 228 | |
| 198 # Sometimes doing "dump_kernel_config" or other I/O now (or after return to | 229 # Sometimes doing "dump_kernel_config" or other I/O now (or after return to |
| 199 # shell) will get the data before modification. Not a problem now, but for | 230 # shell) will get the data before modification. Not a problem now, but for |
| 200 # safety, let's try to sync more. | 231 # safety, let's try to sync more. |
| 201 sync; sync; sync | 232 sync; sync; sync |
| 202 | 233 |
| 203 echo "$name: Re-signed with developer keys successfully." | 234 echo "$name: Re-signed with developer keys successfully." |
| 204 done | 235 done |
| 205 return $resigned_kernels | 236 return $resigned_kernels |
| 206 } | 237 } |
| 207 | 238 |
| 208 # Main | 239 # Main |
| 209 # ---------------------------------------------------------------------------- | 240 # ---------------------------------------------------------------------------- |
| 210 main() { | 241 main() { |
| 211 local num_signed=0 | 242 local num_signed=0 |
| 212 # Check parameters | 243 # Check parameters |
| 213 KERNEL_KEYBLOCK="$FLAGS_keys/kernel.keyblock" | 244 KERNEL_KEYBLOCK="$FLAGS_keys/kernel.keyblock" |
| 214 KERNEL_DATAKEY="$FLAGS_keys/kernel_data_key.vbprivk" | 245 KERNEL_DATAKEY="$FLAGS_keys/kernel_data_key.vbprivk" |
| 215 KERNEL_PUBKEY="$FLAGS_keys/kernel_subkey.vbpubk" | 246 KERNEL_PUBKEY="$FLAGS_keys/kernel_subkey.vbpubk" |
| 216 | 247 |
| 217 debug_msg "Prerequisite check" | 248 debug_msg "Prerequisite check" |
| 218 ensure_files_exist \ | 249 ensure_files_exist \ |
| 219 "$KERNEL_KEYBLOCK" \ | 250 "$KERNEL_KEYBLOCK" \ |
| 220 "$KERNEL_DATAKEY" \ | 251 "$KERNEL_DATAKEY" \ |
| 221 "$KERNEL_PUBKEY" \ | 252 "$KERNEL_PUBKEY" \ |
| 222 "$FLAGS_image" || | 253 "$FLAGS_image" || |
| 223 exit 1 | 254 exit 1 |
| 224 | 255 |
| 225 # Make the root filesystem remountable if needed. | |
| 226 if [ ${FLAGS_remove_rootfs_verification} = $FLAGS_TRUE ]; then | |
| 227 local root_offset=$(partoffset "$FLAGS_image" 3) | |
| 228 enable_rw_mount "$FLAGS_image" "$((root_offset * 512))" | |
| 229 fi | |
| 230 | |
| 231 resign_ssd_kernel "$FLAGS_image" || num_signed=$? | 256 resign_ssd_kernel "$FLAGS_image" || num_signed=$? |
| 232 | 257 |
| 233 debug_msg "Complete." | 258 debug_msg "Complete." |
| 234 if [ $num_signed -gt 0 -a $num_signed -le 2 ]; then | 259 if [ $num_signed -gt 0 -a $num_signed -le 2 ]; then |
| 235 # signed 1 or two kernels | 260 # signed 1 or two kernels |
| 236 echo "Successfully re-signed $num_signed kernel(s) on device $FLAGS_image". | 261 echo "Successfully re-signed $num_signed kernel(s) on device $FLAGS_image". |
| 237 else | 262 else |
| 238 err_die "Failed re-signing kernels." | 263 err_die "Failed re-signing kernels." |
| 239 fi | 264 fi |
| 240 } | 265 } |
| 241 | 266 |
| 242 main | 267 main |
| OLD | NEW |