github.com/coreos/mantle@v0.13.0/kola/tests/misc/grub.go (about) 1 // Copyright 2018 CoreOS, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package misc 16 17 import ( 18 "bytes" 19 "compress/gzip" 20 "crypto/sha512" 21 "encoding/hex" 22 "io/ioutil" 23 24 "github.com/coreos/go-semver/semver" 25 26 "github.com/coreos/mantle/kola/cluster" 27 "github.com/coreos/mantle/kola/register" 28 "github.com/coreos/mantle/platform/conf" 29 ) 30 31 type offsetValue struct { 32 offset int 33 value []byte 34 newHash string 35 } 36 37 var ( 38 grubUpdates = map[string]offsetValue{ 39 "1e11052c144ae483cba4f70efe278070c50daa80d1a5febe7c0d08e401baf0ab16a542b7a34da00d7aea1591238f01d9902ac6fbfcce8d82eebcf09d97d132cd": {3378, []byte{0x74, 2, 0, 0}, 40 "3e9cc58b60301637e37e504c6555f5758c79e3c5493478601ca3c77cc4b6186aa9d732de268a6feb7fcbb88190b46d186b3e3d2dec2ac418645dc1b86a026c0d"}, 41 "2fd5f0fade7c4c986259524f148f79ee1d1353d7ab83d1bdd0d50e52d393d8d896c32ab64eb714ba08861b8ba4f113d19f940a04889fa407784f010f119c8c19": {3378, []byte{0x88, 2, 0, 0}, 42 "5ce27d73800d4075e4fc48928d7caa11d070b50c4ff056fc56fa93102878cecafa68513a22b71c8e68c749f277d9004bb9e0b1d3394cdb78ea2383b0658e4a28"}, 43 "3c591be75a6aa903ee8deed5f8116e627f53738eb8a2ceb80aeaab08f485b405b87565148e482a7234138302eb900786d0e14939a3c3451d424052ca2bd73181": {3383, []byte{0x74, 2, 0, 0}, 44 "0a385b66953fe4125ba3e8761a718ce3874c7d63363c0f74c09f897af8971bdd67633921c11bf65d2c7e19346b176e6493726e58ad54b64d4c336529c6a34497"}, 45 "6d60e369c1b4b484c7221e91d80f03a782b5286137f8087b2bf22b9f54e3507c4947d2a456ba46a6ef3c0c7216dc8251c017e9122f44cba89e32f23a0542afd3": {3383, []byte{0x74, 2, 0, 0}, 46 "a70eb783b1f9d1b8d97dcee3f98787a57a9f49ceffa02abe7ab3ca296824f2f8b0db8f8646130a328ad5e2f11d5dd061e5a0d85d8390f722b5d573c62a1307b0"}, 47 "6e9e5ebb6cd1a15d5a570d9a06a56c9bf60cb047d858c7220dd9dcfd54ebb87c8e0ea4611ac98a0ab51fec9e87b265b2207973f3e4882d87f62d887da72f87ab": {3404, []byte{0x88, 2, 0, 0}, 48 "937e579767de1f9a7869fbe9b25e296349c4ad51dda30bfd98932e450ee52854a9019eeb75dea2a1f0eff6ba9f06bec794ff05c9e738c2ffd7d5f0eaa751eb9c"}, 49 "82b37fa4b305cab33277d2cf0249008731a69575b5689a47e72fe2a35be4440e0e116bc02191f9b0066ea3ae278327fe3409f28d25d13bae88c5f347dba6a254": {3383, []byte{0x74, 2, 0, 0}, 50 "a272cf4995e6406f3652be38aa8b971b928427bbe855f266585ddfe4e9c6e79c926a1665d1ec26ac83a0cefafc9f7c0fadbb433ed8748493df14b37174dde37b"}, 51 "8a7b03d92a8b115943e7f004820fadd2dc6ab125c077a48fb232a1e9ac77fdb27fbb01d52fd33a6ddf65a9f58ce981244c99bcca821030511caa277bc2f68239": {3378, []byte{0x74, 2, 0, 0}, 52 "e61536f2e47d95cc98cb37e955c8cb4b1afaa67f4705868e9f0f5f657370d2a01ea7cfe2733e0d7f0295e18282e24090f82fbbfa88abf6400f53ba476a567bdd"}, 53 "a3e9dadfe3cc34189b5fee83bfc01c3c5b42e04ba19cdcd84f8301c42566617b5916294e2414348139d8c5e557a7ccf6c0d3dca0661f2d10c0c0077345630b1d": {3298, []byte{0x74, 2, 0, 0}, 54 "c9be6791c064167d2b43ac71c2035a7501542901e0f1a4050466b016d2b85ea46da5780e5b9b61bb26e44ccb39e58fa461d1d9cc3ffb5be26aa35458adff542b"}, 55 "c127d7c1dbd5d11cf7af627e37808ea16166b6430ddd8e96111e503cc78ae1fd78083d474495951743fa1b489140be63178a4bb65dabb0d719c5d0ad9c57eb78": {3298, []byte{0x74, 2, 0, 0}, 56 "d7c74e09f7030ebcdcb0c4b5e99cb33fbab1138dd552ee194eb79f71cf5252ef4e169a366a160301fcf6a4e8265912c4b334019e47b74c7b2126a605a910eb6f"}, 57 "f1f9abefa49eeba6a3fe46ba3d254dfc3fa6e2cd8823835e2d982e9cbcd0d82c298e3896dc79d234305d2262a828a7398526906022f8ed7407368725d95e08d8": {3375, []byte{0x74, 2, 0, 0}, 58 "daf12ef71b17d7ddc8fb8419b19bbe2ffb61be9b5bd0d1ca320ac8a07fbfe49924a4b1167bd356d96218972b90b936ce0e508d3b08d470945866aa0c7e71510d"}, 59 } 60 grubUpdaterConf = conf.CloudConfig(`write_files: 61 - path: /opt/patch.sh 62 permissions: 0777 63 content: | 64 set -e 65 66 function patch_grub { 67 # See bug #2400 68 local file='/boot/coreos/grub/i386-pc/linux' 69 local tmpfile="$(mktemp)" 70 local escape_hatch='/boot/coreos/grub/skip-bug-2400-patch' 71 72 [[ -e "${escape_hatch}" ]] && return 73 [[ ! -e "${file}.mod" ]] && return 74 75 # Avoid writing to /boot if we don't need to 76 gunzip -c -S .mod "${file}.mod" > "${tmpfile}" 77 78 # Values derived from https://gist.github.com/ajeddeloh/365cfed1d3a326362e05f78720baf4df 79 declare -A offsets 80 offsets=( 81 [1e11052c144ae483cba4f70efe278070c50daa80d1a5febe7c0d08e401baf0ab16a542b7a34da00d7aea1591238f01d9902ac6fbfcce8d82eebcf09d97d132cd]='3378' 82 [2fd5f0fade7c4c986259524f148f79ee1d1353d7ab83d1bdd0d50e52d393d8d896c32ab64eb714ba08861b8ba4f113d19f940a04889fa407784f010f119c8c19]='3378' 83 [3c591be75a6aa903ee8deed5f8116e627f53738eb8a2ceb80aeaab08f485b405b87565148e482a7234138302eb900786d0e14939a3c3451d424052ca2bd73181]='3383' 84 [6d60e369c1b4b484c7221e91d80f03a782b5286137f8087b2bf22b9f54e3507c4947d2a456ba46a6ef3c0c7216dc8251c017e9122f44cba89e32f23a0542afd3]='3383' 85 [6e9e5ebb6cd1a15d5a570d9a06a56c9bf60cb047d858c7220dd9dcfd54ebb87c8e0ea4611ac98a0ab51fec9e87b265b2207973f3e4882d87f62d887da72f87ab]='3404' 86 [82b37fa4b305cab33277d2cf0249008731a69575b5689a47e72fe2a35be4440e0e116bc02191f9b0066ea3ae278327fe3409f28d25d13bae88c5f347dba6a254]='3383' 87 [8a7b03d92a8b115943e7f004820fadd2dc6ab125c077a48fb232a1e9ac77fdb27fbb01d52fd33a6ddf65a9f58ce981244c99bcca821030511caa277bc2f68239]='3378' 88 [a3e9dadfe3cc34189b5fee83bfc01c3c5b42e04ba19cdcd84f8301c42566617b5916294e2414348139d8c5e557a7ccf6c0d3dca0661f2d10c0c0077345630b1d]='3298' 89 [c127d7c1dbd5d11cf7af627e37808ea16166b6430ddd8e96111e503cc78ae1fd78083d474495951743fa1b489140be63178a4bb65dabb0d719c5d0ad9c57eb78]='3298' 90 [f1f9abefa49eeba6a3fe46ba3d254dfc3fa6e2cd8823835e2d982e9cbcd0d82c298e3896dc79d234305d2262a828a7398526906022f8ed7407368725d95e08d8]='3375' 91 ) 92 93 declare -A correctvals 94 correctvals=( 95 [1e11052c144ae483cba4f70efe278070c50daa80d1a5febe7c0d08e401baf0ab16a542b7a34da00d7aea1591238f01d9902ac6fbfcce8d82eebcf09d97d132cd]='\x74\x02\x00\x00' 96 [2fd5f0fade7c4c986259524f148f79ee1d1353d7ab83d1bdd0d50e52d393d8d896c32ab64eb714ba08861b8ba4f113d19f940a04889fa407784f010f119c8c19]='\x88\x02\x00\x00' 97 [3c591be75a6aa903ee8deed5f8116e627f53738eb8a2ceb80aeaab08f485b405b87565148e482a7234138302eb900786d0e14939a3c3451d424052ca2bd73181]='\x74\x02\x00\x00' 98 [6d60e369c1b4b484c7221e91d80f03a782b5286137f8087b2bf22b9f54e3507c4947d2a456ba46a6ef3c0c7216dc8251c017e9122f44cba89e32f23a0542afd3]='\x74\x02\x00\x00' 99 [6e9e5ebb6cd1a15d5a570d9a06a56c9bf60cb047d858c7220dd9dcfd54ebb87c8e0ea4611ac98a0ab51fec9e87b265b2207973f3e4882d87f62d887da72f87ab]='\x88\x02\x00\x00' 100 [82b37fa4b305cab33277d2cf0249008731a69575b5689a47e72fe2a35be4440e0e116bc02191f9b0066ea3ae278327fe3409f28d25d13bae88c5f347dba6a254]='\x74\x02\x00\x00' 101 [8a7b03d92a8b115943e7f004820fadd2dc6ab125c077a48fb232a1e9ac77fdb27fbb01d52fd33a6ddf65a9f58ce981244c99bcca821030511caa277bc2f68239]='\x74\x02\x00\x00' 102 [a3e9dadfe3cc34189b5fee83bfc01c3c5b42e04ba19cdcd84f8301c42566617b5916294e2414348139d8c5e557a7ccf6c0d3dca0661f2d10c0c0077345630b1d]='\x74\x02\x00\x00' 103 [c127d7c1dbd5d11cf7af627e37808ea16166b6430ddd8e96111e503cc78ae1fd78083d474495951743fa1b489140be63178a4bb65dabb0d719c5d0ad9c57eb78]='\x74\x02\x00\x00' 104 [f1f9abefa49eeba6a3fe46ba3d254dfc3fa6e2cd8823835e2d982e9cbcd0d82c298e3896dc79d234305d2262a828a7398526906022f8ed7407368725d95e08d8]='\x74\x02\x00\x00' 105 ) 106 107 filesum="$(sha512sum "${tmpfile}" | cut -d' ' -f1)" 108 if [[ -z "${offsets[$filesum]}" ]]; then 109 echo "Nothing to do" 110 rm "${tmpfile}" 111 touch "${escape_hatch}" 112 return 113 fi 114 115 printf "${correctvals[$filesum]}" | dd of="${tmpfile}" bs=1 seek="${offsets[$filesum]}" conv=notrunc status=none 116 117 # There's a lot of sync'ing going on. On remotely up to date systems (newer than 1109.1.0), sync can operate on 118 # individual files. On old systems it syncs everything which is slow, but we want to be as safe as possible. 119 # Since we write out the escape hatch after everything is done, this will only happen once. 120 121 # rezip onto /boot so ENOSPC can't cause problems 122 gzip -c "${tmpfile}" > "${file}.tmp" 123 rm "${tmpfile}" 124 125 # in case something goes horribly wrong. Do not use mv -b since it moves the original file to 126 # the backup name then moves the new file to the target, leaving a window with no file 127 cp -p "${file}.mod" "${file}.bak.bug2400" 128 sync "${file}.bak.bug2400" "${file}.tmp" 129 130 # use mv then sync to be as atomic as possible 131 mv "${file}.tmp" "${file}.mod" 132 sync '/boot/coreos/grub/i386-pc/' 133 134 touch "${escape_hatch}" 135 136 echo 'linux.mod updated successfully' 137 } 138 139 patch_grub 140 141 coreos: 142 units: 143 - name: update-engine.service 144 mask: true 145 `) 146 ) 147 148 func init() { 149 register.Register(®ister.Test{ 150 Run: UpdateGrubNop, 151 ClusterSize: 1, 152 Name: "cl.update.grubnop", 153 UserData: grubUpdaterConf, 154 MinVersion: semver.Version{Major: 1745}, 155 Distros: []string{"cl"}, 156 ExcludePlatforms: []string{"qemu-unpriv"}, 157 }) 158 } 159 160 func gunzipAndRead(comp []byte) ([]byte, error) { 161 fh := bytes.NewReader(comp) 162 163 uncomp, err := gzip.NewReader(fh) 164 if err != nil { 165 return nil, err 166 } 167 return ioutil.ReadAll(uncomp) 168 } 169 170 func UpdateGrubNop(c cluster.TestCluster) { 171 m := c.Machines()[0] 172 originalBytes, err := gunzipAndRead(c.MustSSH(m, "cat /boot/coreos/grub/i386-pc/linux.mod")) 173 if err != nil { 174 c.Fatalf("failed decompressing: %v", err) 175 } 176 sumAr := sha512.Sum512(originalBytes) 177 sum := hex.EncodeToString(sumAr[:]) 178 _, ok := grubUpdates[sum] 179 if ok { 180 c.Fatalf("Found bad linux.mod") 181 } 182 183 if msg := string(c.MustSSH(m, "sudo /opt/patch.sh")); msg != "Nothing to do" { 184 c.Fatalf("Unexpected output %v", msg) 185 } 186 if msg := string(c.MustSSH(m, "sudo /opt/patch.sh")); msg != "" { 187 c.Fatalf("Unexpected output %v", msg) 188 } 189 }