diff --git a/update/_apply/main.go b/update/_apply/main.go index de22f3a5a..70f72bf7d 100644 --- a/update/_apply/main.go +++ b/update/_apply/main.go @@ -10,6 +10,7 @@ import ( func main() { u := update.Updater{ DstPartition: "out", + DstKernel: "vmlinuz", } if err := u.OpenPayload(os.Args[1]); err != nil { diff --git a/update/_gen/main.go b/update/_gen/main.go new file mode 100644 index 000000000..1f86bdf30 --- /dev/null +++ b/update/_gen/main.go @@ -0,0 +1,41 @@ +package main + +import ( + "fmt" + "os" + + "github.com/coreos/mantle/update/generator" +) + +func main() { + var g generator.Generator + + part, err := generator.FullUpdate(os.Args[1]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + if err := g.Partition(part); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + if len(os.Args) > 2 { + kern, err := generator.FullUpdate(os.Args[2]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + if err := g.Kernel(kern); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + } + + if err := g.Write("out.gz"); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} diff --git a/update/generator/full.go b/update/generator/full.go index 68090ee29..c68b7fc7e 100644 --- a/update/generator/full.go +++ b/update/generator/full.go @@ -16,8 +16,6 @@ package generator import ( "crypto/sha256" - "errors" - "fmt" "io" "os" @@ -27,10 +25,6 @@ import ( "github.com/coreos/mantle/update/metadata" ) -var ( - errShortRead = errors.New("read an incomplete block") -) - // FullUpdate generates an update Procedure for the given file, embedding its // entire contents in the payload so it does not depend any previous state. func FullUpdate(path string) (*Procedure, error) { @@ -56,9 +50,6 @@ func FullUpdate(path string) (*Procedure, error) { } if err != nil && err != io.EOF { payload.Close() - if err == errShortRead { - err = fmt.Errorf("%s: %v", path, err) - } return nil, err } @@ -80,13 +71,18 @@ type fullScanner struct { payload io.Writer source io.Reader offset uint64 + eof error operations []*metadata.InstallOperation } func (f *fullScanner) readChunk() ([]byte, error) { + if f.eof != nil { + return nil, f.eof + } chunk := make([]byte, ChunkSize) n, err := io.ReadFull(f.source, chunk) - if (err == io.EOF || err == io.ErrUnexpectedEOF) && n != 0 { + if err == io.ErrUnexpectedEOF { + f.eof = io.EOF err = nil } return chunk[:n], err @@ -97,12 +93,9 @@ func (f *fullScanner) Scan() error { if err != nil { return err } - if len(chunk)%BlockSize != 0 { - return errShortRead - } startBlock := uint64(f.offset) / BlockSize - numBlocks := uint64(len(chunk)) / BlockSize + numBlocks := (uint64(len(chunk)) + BlockSize - 1) / BlockSize f.offset += uint64(len(chunk)) // Try bzip2 compressing the data, hopefully it will shrink! diff --git a/update/generator/full_test.go b/update/generator/full_test.go index f59fccc6b..3d3a4b6bd 100644 --- a/update/generator/full_test.go +++ b/update/generator/full_test.go @@ -149,8 +149,13 @@ func TestFullUpdateScanUnaligned(t *testing.T) { source: bytes.NewReader(testUnaligned), } - if err := scanner.Scan(); err != errShortRead { - t.Fatalf("expected errShortRead, got %v", err) + if err := scanner.Scan(); err != nil { + t.Fatalf("expected nil, got %v", err) + } + + const expect = BlockSize + 1 + if scanner.offset != expect { + t.Errorf("expected %d bytes, got %d", expect, scanner.offset) } } diff --git a/update/generator/generator.go b/update/generator/generator.go index c19ca75ef..544974157 100644 --- a/update/generator/generator.go +++ b/update/generator/generator.go @@ -17,7 +17,9 @@ package generator import ( "encoding/binary" "errors" + "fmt" "io" + "math" "os" "github.com/coreos/pkg/capnslog" @@ -65,6 +67,10 @@ func (g *Generator) Partition(proc *Procedure) error { return ErrProcedureExists } + if err := checkBlockAlignment(proc); err != nil { + return err + } + g.AddCloser(proc) g.manifest.PartitionOperations = proc.Operations g.manifest.OldPartitionInfo = proc.OldInfo @@ -73,12 +79,50 @@ func (g *Generator) Partition(proc *Procedure) error { return nil } +// sanity check for block alignment in partitions. +func checkBlockAlignment(proc *Procedure) error { + if proc.OldInfo.GetSize()%BlockSize != 0 { + return fmt.Errorf("generator: old size %d not divisble by %d", + proc.OldInfo.Size, BlockSize) + } + if proc.NewInfo.GetSize()%BlockSize != 0 { + return fmt.Errorf("generator: new size %d not divisble by %d", + proc.NewInfo.Size, BlockSize) + } + return nil +} + +func (g *Generator) Kernel(proc *Procedure) error { + proc.Type = metadata.InstallProcedure_KERNEL.Enum() + return g.addProc(proc) +} + +func (g *Generator) addProc(proc *Procedure) error { + for _, other := range g.manifest.Procedures { + if *other.Type == *proc.Type { + return ErrProcedureExists + } + } + + g.AddCloser(proc) + g.manifest.Procedures = append(g.manifest.Procedures, + &proc.InstallProcedure) + g.payloads = append(g.payloads, proc) + + return nil +} + // Write finalizes the payload, writing it out to the given file path. func (g *Generator) Write(path string) (err error) { + g.manifest.BlockSize = proto.Uint32(BlockSize) + if err = g.updateOffsets(); err != nil { return } + // for compatibility with old update_engine versions + g.addNoops() + plog.Infof("Writing payload to %s", path) f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) @@ -138,6 +182,61 @@ func (g *Generator) updateOffsets() error { return err } +// The sparse hole was a feature of update_engine, it is not used +// in this new code outside of the noop compatibility goo. +const sparseHole = math.MaxUint64 + +// Translate a normal install operation to a dummy that discards data. +func opToNoop(op *metadata.InstallOperation) *metadata.InstallOperation { + blocks := (uint64(*op.DataLength) + BlockSize - 1) / BlockSize + sum := make([]byte, len(op.DataSha256Hash)) + copy(sum, op.DataSha256Hash) + + return &metadata.InstallOperation{ + Type: metadata.InstallOperation_REPLACE.Enum(), + DataOffset: proto.Uint32(*op.DataOffset), + DataLength: proto.Uint32(*op.DataLength), + DataSha256Hash: sum, + DstExtents: []*metadata.Extent{&metadata.Extent{ + StartBlock: proto.Uint64(sparseHole), + NumBlocks: proto.Uint64(blocks), + }}, + } +} + +// Fill in the dummy noop_operations list for compatibility with old +// update_engine versions that didn't support procedures and handled +// signature data weirdly. +func (g *Generator) addNoops() { + // Translate the new procedures list to noop operations. + for _, proc := range g.manifest.Procedures { + for _, op := range proc.Operations { + if op.GetDataLength() == 0 { + continue + } + + g.manifest.NoopOperations = append( + g.manifest.NoopOperations, opToNoop(op)) + } + } + + // Create a dummy noop operation to cover trailing signature data. + // Yes, the manifest inconsistently uses 32 and 64 bit values... + offset := uint32(*g.manifest.SignaturesOffset) + length := uint32(*g.manifest.SignaturesSize) + blocks := (*g.manifest.SignaturesSize + BlockSize - 1) / BlockSize + g.manifest.NoopOperations = append(g.manifest.NoopOperations, + &metadata.InstallOperation{ + Type: metadata.InstallOperation_REPLACE.Enum(), + DataOffset: proto.Uint32(offset), + DataLength: proto.Uint32(length), + DstExtents: []*metadata.Extent{&metadata.Extent{ + StartBlock: proto.Uint64(sparseHole), + NumBlocks: proto.Uint64(blocks), + }}, + }) +} + func (g *Generator) writeHeader(w io.Writer) error { manifestSize := proto.Size(&g.manifest) header := metadata.DeltaArchiveHeader{ diff --git a/update/metadata/update_metadata.pb.go b/update/metadata/update_metadata.pb.go index 70f1cb3db..94e6cc581 100644 --- a/update/metadata/update_metadata.pb.go +++ b/update/metadata/update_metadata.pb.go @@ -74,14 +74,17 @@ func (InstallOperation_Type) EnumDescriptor() ([]byte, []int) { return fileDescr type InstallProcedure_Type int32 const ( - InstallProcedure_KERNEL InstallProcedure_Type = 0 + InstallProcedure_KERNEL InstallProcedure_Type = 0 + InstallProcedure_PCR_POLICY InstallProcedure_Type = 1 ) var InstallProcedure_Type_name = map[int32]string{ 0: "KERNEL", + 1: "PCR_POLICY", } var InstallProcedure_Type_value = map[string]int32{ - "KERNEL": 0, + "KERNEL": 0, + "PCR_POLICY": 1, } func (x InstallProcedure_Type) Enum() *InstallProcedure_Type { @@ -133,7 +136,7 @@ type InstallOperation struct { // BSDIFF, because we need to fill in the rest of the last block // that bsdiff writes with '\0' bytes. DstLength *uint64 `protobuf:"varint,7,opt,name=dst_length" json:"dst_length,omitempty"` - // Optional SHA 256 hash of the blob associated with this operation. + // Required SHA 256 hash of the blob associated with this operation. // This is used as a primary validation for http-based downloads and // as a defense-in-depth validation for https-based downloads. If // the operation doesn't refer to any blob, this field will have @@ -321,7 +324,7 @@ func (m *InstallInfo) GetHash() []byte { // InstallProcedure defines the update procedure for a single file or block // device (except for /usr which is in DeltaArchiveManifest). type InstallProcedure struct { - Type *InstallProcedure_Type `protobuf:"varint,1,req,name=type,enum=chromeos_update_engine.InstallProcedure_Type" json:"type,omitempty"` + Type *InstallProcedure_Type `protobuf:"varint,1,opt,name=type,enum=chromeos_update_engine.InstallProcedure_Type" json:"type,omitempty"` Operations []*InstallOperation `protobuf:"bytes,2,rep,name=operations" json:"operations,omitempty"` OldInfo *InstallInfo `protobuf:"bytes,3,opt,name=old_info" json:"old_info,omitempty"` NewInfo *InstallInfo `protobuf:"bytes,4,opt,name=new_info" json:"new_info,omitempty"` @@ -484,40 +487,41 @@ func init() { } var fileDescriptor0 = []byte{ - // 560 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x53, 0x5d, 0x6f, 0xd3, 0x30, - 0x14, 0x5d, 0xdb, 0xd0, 0x76, 0x37, 0xdd, 0x1a, 0xcc, 0x80, 0xc0, 0x03, 0xaa, 0xc2, 0x4b, 0x41, - 0x50, 0x41, 0x61, 0x93, 0x06, 0x48, 0xd0, 0xb1, 0x54, 0xaa, 0xd8, 0xd8, 0xb4, 0x21, 0x1e, 0x78, - 0xb1, 0x42, 0xeb, 0x2e, 0x11, 0xa9, 0x1d, 0xc5, 0xee, 0x80, 0xfd, 0x09, 0x7e, 0x0a, 0x7f, 0x89, - 0x9f, 0xc2, 0xb5, 0x9b, 0x26, 0xd3, 0xc4, 0x44, 0xa6, 0xbd, 0xf9, 0xeb, 0x9c, 0x7b, 0xcf, 0xb9, - 0xc7, 0x70, 0x7b, 0x9e, 0x4c, 0x02, 0xc5, 0xe8, 0x8c, 0xa9, 0x00, 0x17, 0x41, 0x2f, 0x49, 0x85, - 0x12, 0xe4, 0xce, 0x38, 0x4c, 0xc5, 0x8c, 0x09, 0x49, 0xb3, 0x7b, 0xc6, 0x4f, 0x22, 0xce, 0xbc, - 0x3f, 0x55, 0x70, 0x46, 0x5c, 0xaa, 0x20, 0x8e, 0x0f, 0x12, 0x96, 0x06, 0x2a, 0x12, 0x9c, 0xbc, - 0x06, 0x4b, 0xfd, 0x4c, 0x98, 0x5b, 0xe9, 0x54, 0xbb, 0xeb, 0xfd, 0xa7, 0xbd, 0x7f, 0x63, 0x7b, - 0x17, 0x71, 0xbd, 0x4f, 0x08, 0x22, 0xb7, 0xc0, 0xd6, 0x75, 0xa9, 0x98, 0x4e, 0x25, 0x53, 0x6e, - 0xb5, 0x53, 0xe9, 0xae, 0xe5, 0x87, 0x31, 0x42, 0x55, 0xe8, 0xd6, 0xcc, 0xe1, 0x0b, 0xb0, 0x65, - 0x3a, 0xa6, 0xec, 0x87, 0x62, 0x5c, 0x49, 0xd7, 0xea, 0xd4, 0xba, 0x76, 0xff, 0xc1, 0x65, 0xd5, - 0x7c, 0xf3, 0x8c, 0x10, 0x00, 0x0d, 0xca, 0x88, 0x6e, 0x20, 0x91, 0xa5, 0x89, 0x26, 0x52, 0xe5, - 0x44, 0xf5, 0xb2, 0x44, 0x1a, 0x94, 0x11, 0x35, 0x0c, 0x91, 0x0b, 0x8e, 0x69, 0x53, 0x86, 0x41, - 0x7f, 0x73, 0x8b, 0x86, 0x81, 0x0c, 0xdd, 0x26, 0xde, 0xb4, 0xbc, 0x6d, 0xb0, 0x8c, 0x3a, 0x1b, - 0x1a, 0x47, 0xfe, 0xe1, 0xde, 0xe0, 0xbd, 0xef, 0xac, 0x90, 0x75, 0x80, 0x6c, 0x43, 0x77, 0xbe, - 0x38, 0x15, 0xd2, 0x04, 0x6b, 0xff, 0xe0, 0xb3, 0xef, 0x54, 0x91, 0xbb, 0xbe, 0x73, 0xbc, 0x3b, - 0x1a, 0x0e, 0x9d, 0x9a, 0xf7, 0x1c, 0xea, 0x59, 0x49, 0x74, 0x01, 0x1d, 0x4b, 0x15, 0xfd, 0x1a, - 0x8b, 0xf1, 0x37, 0xb4, 0x57, 0xd7, 0xc4, 0xb7, 0x7c, 0x3e, 0x5b, 0x1c, 0x49, 0x63, 0x97, 0xe5, - 0x9d, 0x01, 0x1c, 0x47, 0x27, 0x3c, 0x50, 0xf3, 0x94, 0x49, 0xf2, 0x0e, 0x25, 0xe7, 0x3b, 0x44, - 0x69, 0x75, 0x4f, 0x2e, 0x53, 0x57, 0xe0, 0x8a, 0xe5, 0xfd, 0xc7, 0xb0, 0x9a, 0x6f, 0x48, 0x1b, - 0x1a, 0xa7, 0x2c, 0x95, 0x38, 0x30, 0xd3, 0xc1, 0x1a, 0x69, 0x81, 0xa5, 0x55, 0x9b, 0xda, 0x2d, - 0xef, 0x11, 0xd8, 0xd9, 0x60, 0x47, 0x7c, 0x2a, 0xf4, 0xa5, 0x8c, 0xce, 0x58, 0xd6, 0x2c, 0xee, - 0x8c, 0x29, 0x8b, 0xa7, 0xbf, 0x8a, 0xf0, 0x1c, 0xa6, 0x62, 0xcc, 0x26, 0x9a, 0xfe, 0x6a, 0xe1, - 0xc9, 0x71, 0x8b, 0xf0, 0xbc, 0x01, 0x10, 0xcb, 0x38, 0x69, 0x33, 0xb4, 0xd4, 0x6e, 0xd9, 0xfc, - 0x91, 0x4d, 0x68, 0x8a, 0x78, 0x42, 0x23, 0xec, 0xdb, 0x44, 0xcc, 0xee, 0x3f, 0xfc, 0x0f, 0xd6, - 0x48, 0x44, 0x18, 0x67, 0xdf, 0x17, 0x30, 0xab, 0x34, 0xcc, 0x23, 0x59, 0x24, 0x70, 0xd6, 0x1f, - 0xfc, 0xa3, 0x8f, 0xfe, 0x9e, 0xb3, 0xe2, 0xfd, 0xae, 0xc1, 0xc6, 0x2e, 0x8b, 0x55, 0x30, 0x48, - 0xc7, 0x61, 0x74, 0xca, 0xf6, 0x03, 0x1e, 0x4d, 0x99, 0x54, 0x64, 0x08, 0x1b, 0x09, 0x4e, 0x3e, - 0xd2, 0x7d, 0xd2, 0x73, 0x12, 0x2b, 0x57, 0x94, 0x38, 0x80, 0x36, 0x17, 0x22, 0xa1, 0xd7, 0x70, - 0xc9, 0x05, 0x30, 0x61, 0xa3, 0x66, 0xae, 0xe6, 0x2b, 0xbe, 0xb2, 0x5e, 0x3e, 0xdb, 0xde, 0x22, - 0xf7, 0xe0, 0x66, 0x11, 0xb4, 0xe5, 0x07, 0xb6, 0xcc, 0xe0, 0xef, 0x42, 0xfb, 0xdc, 0x95, 0x41, - 0x2e, 0xfe, 0xde, 0x5b, 0x20, 0xda, 0xf3, 0x42, 0x9c, 0xb1, 0xb1, 0x59, 0xde, 0x7d, 0x24, 0xd0, - 0xee, 0x5f, 0x20, 0x58, 0x2d, 0x4f, 0x80, 0x99, 0x49, 0x96, 0x29, 0x92, 0x2e, 0x94, 0x72, 0x23, - 0x8f, 0xdd, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x53, 0xd4, 0x06, 0x13, 0x30, 0x05, 0x00, 0x00, + // 575 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x53, 0xdf, 0x6e, 0xd3, 0x3e, + 0x18, 0xfd, 0xa5, 0xcd, 0xaf, 0xed, 0xbe, 0x74, 0x6b, 0x30, 0x03, 0x02, 0x17, 0xa8, 0x0a, 0x37, + 0x05, 0x41, 0x05, 0x85, 0x4d, 0x1a, 0x20, 0x41, 0xd7, 0xa5, 0x52, 0x45, 0x47, 0xab, 0x0e, 0x21, + 0xc1, 0x8d, 0x15, 0x5a, 0x77, 0x89, 0x48, 0xed, 0x28, 0x76, 0x07, 0xec, 0x65, 0x78, 0x04, 0x5e, + 0x89, 0x47, 0xc1, 0x76, 0xd2, 0x64, 0x9a, 0x98, 0x08, 0xe2, 0xce, 0xff, 0xce, 0xf9, 0xbe, 0x73, + 0xbe, 0x63, 0xb8, 0xb1, 0x8e, 0x17, 0xbe, 0x20, 0x78, 0x45, 0x84, 0x2f, 0x17, 0x7e, 0x37, 0x4e, + 0x98, 0x60, 0xe8, 0xe6, 0x3c, 0x48, 0xd8, 0x8a, 0x30, 0x8e, 0xb3, 0x7b, 0x42, 0x4f, 0x43, 0x4a, + 0xdc, 0x9f, 0x15, 0xb0, 0x47, 0x94, 0x0b, 0x3f, 0x8a, 0x26, 0x31, 0x49, 0x7c, 0x11, 0x32, 0x8a, + 0x5e, 0x80, 0x29, 0xbe, 0xc5, 0xc4, 0x31, 0xda, 0x95, 0xce, 0x4e, 0xef, 0x51, 0xf7, 0xf7, 0xd8, + 0xee, 0x65, 0x5c, 0xf7, 0x9d, 0x04, 0xa1, 0xeb, 0x60, 0xa9, 0xba, 0x98, 0x2d, 0x97, 0x9c, 0x08, + 0xa7, 0xd2, 0x36, 0x3a, 0xdb, 0xf9, 0x61, 0x24, 0xa1, 0x22, 0x70, 0xaa, 0xfa, 0xf0, 0x29, 0x58, + 0x3c, 0x99, 0x63, 0xf2, 0x55, 0x10, 0x2a, 0xb8, 0x63, 0xb6, 0xab, 0x1d, 0xab, 0x77, 0xf7, 0xaa, + 0x6a, 0x9e, 0x7e, 0x86, 0x10, 0x80, 0x02, 0x65, 0x44, 0xff, 0x4b, 0x22, 0x53, 0x11, 0x2d, 0xb8, + 0xc8, 0x89, 0x6a, 0x65, 0x89, 0x14, 0x28, 0x23, 0xaa, 0x6b, 0x22, 0x07, 0x6c, 0xdd, 0x26, 0x0f, + 0xfc, 0xde, 0xde, 0x3e, 0x0e, 0x7c, 0x1e, 0x38, 0x0d, 0x79, 0xd3, 0x74, 0x0f, 0xc0, 0xd4, 0xea, + 0x2c, 0xa8, 0xcf, 0xbc, 0xe9, 0xb8, 0x3f, 0xf0, 0xec, 0xff, 0xd0, 0x0e, 0x40, 0xb6, 0xc1, 0x87, + 0x1f, 0x6d, 0x03, 0x35, 0xc0, 0x3c, 0x9e, 0xbc, 0xf7, 0xec, 0x8a, 0xe4, 0xae, 0x1d, 0x9e, 0x1c, + 0x8d, 0x86, 0x43, 0xbb, 0xea, 0x3e, 0x81, 0x5a, 0x56, 0x52, 0xba, 0x20, 0x1d, 0x4b, 0x04, 0xfe, + 0x14, 0xb1, 0xf9, 0x67, 0x69, 0xaf, 0xaa, 0x29, 0xdf, 0xd2, 0xf5, 0x2a, 0x3d, 0xe2, 0xda, 0x2e, + 0xd3, 0x3d, 0x07, 0x38, 0x09, 0x4f, 0xa9, 0x2f, 0xd6, 0x09, 0xe1, 0xe8, 0xb5, 0x94, 0x9c, 0xef, + 0x24, 0x4a, 0xa9, 0x7b, 0x78, 0x95, 0xba, 0x02, 0x57, 0x2c, 0xef, 0x3c, 0x80, 0xad, 0x7c, 0x83, + 0x5a, 0x50, 0x3f, 0x23, 0x09, 0x97, 0x03, 0xd3, 0x1d, 0x6c, 0xa3, 0x26, 0x98, 0x4a, 0xb5, 0xae, + 0xdd, 0x74, 0xef, 0x83, 0x95, 0x0d, 0x76, 0x44, 0x97, 0x4c, 0x5d, 0xf2, 0xf0, 0x9c, 0x64, 0xcd, + 0xca, 0x9d, 0x36, 0x25, 0x7d, 0xfa, 0xbd, 0x08, 0xcf, 0x34, 0x61, 0x73, 0xb2, 0x50, 0xf4, 0x45, + 0x78, 0x8c, 0x12, 0xe1, 0xc9, 0x71, 0x69, 0x78, 0x5e, 0x02, 0xb0, 0x4d, 0x9c, 0x94, 0x19, 0x4a, + 0x6a, 0xa7, 0x6c, 0xfe, 0xd0, 0x1e, 0x34, 0x58, 0xb4, 0xc0, 0xa1, 0xec, 0x5b, 0x47, 0xcc, 0xea, + 0xdd, 0xfb, 0x03, 0x56, 0x4b, 0x94, 0x30, 0x4a, 0xbe, 0xa4, 0x30, 0xb3, 0x34, 0xcc, 0x75, 0xb3, + 0x48, 0xc8, 0x59, 0xbf, 0xf1, 0x66, 0x6f, 0xbd, 0x71, 0x9a, 0x88, 0xe9, 0x60, 0x86, 0xa7, 0x93, + 0xf1, 0x68, 0xf0, 0xc1, 0x36, 0xdc, 0x1f, 0x55, 0xd8, 0x3d, 0x22, 0x91, 0xf0, 0xfb, 0xc9, 0x3c, + 0x08, 0xcf, 0xc8, 0xb1, 0x4f, 0xc3, 0x25, 0xe1, 0x02, 0x0d, 0x61, 0x37, 0x96, 0x49, 0x08, 0x55, + 0xdf, 0xf8, 0x82, 0x64, 0xe3, 0x2f, 0x25, 0xf7, 0xa1, 0x45, 0x19, 0x8b, 0xf1, 0x3f, 0xb8, 0xe6, + 0x00, 0xe8, 0xf0, 0x61, 0x3d, 0x67, 0xfd, 0x35, 0x9f, 0x9b, 0xcf, 0x1e, 0x1f, 0xec, 0xa3, 0xdb, + 0x70, 0xad, 0x08, 0xde, 0xe6, 0x43, 0x9b, 0x3a, 0x08, 0xb7, 0xa0, 0x75, 0xe1, 0x4a, 0x23, 0xd3, + 0xbf, 0xf8, 0x0a, 0x90, 0x9a, 0x41, 0x21, 0x4e, 0xdb, 0xda, 0x28, 0x3f, 0x0d, 0x49, 0xa0, 0xa6, + 0x71, 0x89, 0x60, 0xab, 0x3c, 0x81, 0xcc, 0x50, 0xbc, 0x49, 0x15, 0x77, 0xa0, 0x94, 0x1b, 0x79, + 0x0c, 0x7f, 0x05, 0x00, 0x00, 0xff, 0xff, 0xee, 0x46, 0xa1, 0x2a, 0x40, 0x05, 0x00, 0x00, } diff --git a/update/metadata/update_metadata.proto b/update/metadata/update_metadata.proto index 85d966458..6527ae50a 100644 --- a/update/metadata/update_metadata.proto +++ b/update/metadata/update_metadata.proto @@ -20,8 +20,8 @@ package chromeos_update_engine; // char data[]; // } blobs[]; // -// // These two are not signed: -// uint64 signatures_message_size; +// // The signature covers all preceding data. Size and location are +// // specified inside the manifest. // char signatures_message[]; // // }; @@ -73,7 +73,7 @@ message InstallOperation { // that bsdiff writes with '\0' bytes. optional uint64 dst_length = 7; - // Optional SHA 256 hash of the blob associated with this operation. + // Required SHA 256 hash of the blob associated with this operation. // This is used as a primary validation for http-based downloads and // as a defense-in-depth validation for https-based downloads. If // the operation doesn't refer to any blob, this field will have @@ -130,8 +130,9 @@ message InstallInfo { message InstallProcedure { enum Type { KERNEL = 0; // A kernel image to install to the boot partition. + PCR_POLICY = 1; // A zip file containing TPM PCR data. } - required Type type = 1; + optional Type type = 1; repeated InstallOperation operations = 2; diff --git a/update/operation.go b/update/operation.go index a6cfd1e98..ec5c4662e 100644 --- a/update/operation.go +++ b/update/operation.go @@ -126,14 +126,23 @@ func (op *Operation) replace(dst *os.File, src io.Reader) error { offset := int64(extent.GetStartBlock()) * bs length := int64(extent.GetNumBlocks()) * bs - // BUG: update_engine only writes as much of an extent as it - // has data for, allowing extents to be defined larger than - // they actually should be. So far this only appears to happen - // to the very last destination extent in a full update. + // update_engine only writes as much of an extent as it has + // data for, allowing extents to be defined larger than they + // actually should be. For files this is normal for the final + // block to be partially complete since block alignment is not + // required and the extent can't represent partial blocks. + // + // BUG: For partitions block alignment is required so the + // extent size should be correct but payloads created by + // update_engine always set num_blocks to the chunk size, 256. + // payloads generated by update/generator shouldn't do this. if offset+length > maxSize { excess := (offset + length) - maxSize - plog.Warningf("extent excedes destination bounds by %d bytes!", excess) length -= excess + + if excess >= bs { + plog.Warningf("extent excedes destination bounds by %d bytes!", excess) + } } if _, err := dst.Seek(offset, os.SEEK_SET); err != nil { diff --git a/update/updater.go b/update/updater.go index 37ac779bb..2dd036d51 100644 --- a/update/updater.go +++ b/update/updater.go @@ -34,6 +34,8 @@ var ( type Updater struct { SrcPartition string DstPartition string + SrcKernel string + DstKernel string payload *Payload } @@ -62,6 +64,8 @@ func (u *Updater) Update() error { err = u.UpdatePartition(proc) case metadata.InstallProcedure_KERNEL: err = u.UpdateKernel(proc) + case metadata.InstallProcedure_PCR_POLICY: + err = fmt.Errorf("hanlding PCR policy data not implemented") default: err = fmt.Errorf("unknown procedure type %s", proc.GetType()) } @@ -77,7 +81,7 @@ func (u *Updater) UpdatePartition(proc *metadata.InstallProcedure) error { } func (u *Updater) UpdateKernel(proc *metadata.InstallProcedure) error { - return fmt.Errorf("KERNEL") + return u.updateCommon(proc, "kernel", u.SrcKernel, u.DstKernel) } func (u *Updater) updateCommon(proc *metadata.InstallProcedure, procName, srcPath, dstPath string) (err error) { @@ -93,7 +97,7 @@ func (u *Updater) updateCommon(proc *metadata.InstallProcedure, procName, srcPat } } - dstFile, err = os.OpenFile(u.DstPartition, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) + dstFile, err = os.OpenFile(dstPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { return err }