Skip to content

Commit

Permalink
fix: perform correct PMBR partition calculations
Browse files Browse the repository at this point in the history
My biggest concern is that the end of the partition was incorrectly
calculated for disk > 2TiB.

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
  • Loading branch information
smira authored and talos-bot committed Aug 6, 2021
1 parent 2ec0c3c commit fe24303
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 9 deletions.
14 changes: 13 additions & 1 deletion blockdevice/partition/gpt/gpt.go
Expand Up @@ -8,6 +8,7 @@ import (
"encoding/binary"
"errors"
"fmt"
"math"
"os"

"github.com/google/uuid"
Expand Down Expand Up @@ -376,11 +377,22 @@ func (g *GPT) newPMBR(h *Header) ([]byte, error) {
// Partition type: EFI data partition.
b[4] = 0xee

// CHS for the start of the partition
copy(b[1:4], []byte{0x00, 0x02, 0x00})

// CHS for the end of the partition
copy(b[5:8], []byte{0xff, 0xff, 0xff})

// Partition start LBA.
binary.LittleEndian.PutUint32(b[8:12], 1)

// Partition length in sectors.
binary.LittleEndian.PutUint32(b[12:16], uint32(h.BackupLBA))
// This might overflow uint32, so check accordingly
if h.BackupLBA > math.MaxUint32 {
binary.LittleEndian.PutUint32(b[12:16], uint32(math.MaxUint32))
} else {
binary.LittleEndian.PutUint32(b[12:16], uint32(h.BackupLBA))
}

return p, nil
}
Expand Down
27 changes: 19 additions & 8 deletions blockdevice/partition/gpt/gpt_test.go
Expand Up @@ -5,6 +5,7 @@
package gpt_test

import (
"encoding/binary"
"os"
"testing"

Expand Down Expand Up @@ -49,7 +50,7 @@ func (suite *GPTSuite) TestReset() {

suite.Require().NoError(g.Write())

suite.checkMBRFlag(0x00)
suite.validatePMBR(0x00)

// re-read the partition table
g, err = gpt.Open(suite.Dev)
Expand All @@ -63,7 +64,7 @@ func (suite *GPTSuite) TestReset() {

suite.Require().NoError(g.Write())

suite.checkMBRFlag(0x00)
suite.validatePMBR(0x00)

// re-read the partition table
g, err = gpt.Open(suite.Dev)
Expand Down Expand Up @@ -440,7 +441,7 @@ func (suite *GPTSuite) TestMarkPMBRBootable() {

suite.Require().NoError(g.Write())

suite.checkMBRFlag(0x80)
suite.validatePMBR(0x80)

// re-read the partition table
g, err = gpt.Open(suite.Dev)
Expand All @@ -449,16 +450,26 @@ func (suite *GPTSuite) TestMarkPMBRBootable() {
suite.Require().NoError(g.Read())
suite.Require().NoError(g.Write())

suite.checkMBRFlag(0x80)
suite.validatePMBR(0x80)
}

func (suite *GPTSuite) checkMBRFlag(flag byte) {
buf := make([]byte, 1)
func (suite *GPTSuite) validatePMBR(flag byte) {
buf := make([]byte, 512)

_, err := suite.Dev.ReadAt(buf, 446)
n, err := suite.Dev.ReadAt(buf, 0)
suite.Require().NoError(err)
suite.Require().EqualValues(512, n)

suite.Assert().Equal(flag, buf[0])
partition := buf[446:460]

suite.Assert().Equal(flag, partition[0]) // active flag
suite.Assert().Equal([]byte{0x00, 0x02, 0x00}, partition[1:4]) // CHS start
suite.Assert().Equal(byte(0xee), partition[4]) // partition type
suite.Assert().Equal([]byte{0xff, 0xff, 0xff}, partition[5:8]) // CHS end
suite.Assert().Equal(uint32(1), binary.LittleEndian.Uint32(partition[8:12])) // LBA start
suite.Assert().Equal(uint32(size/blockSize-1), binary.LittleEndian.Uint32(partition[12:16])) // length in sectors

suite.Assert().Equal([]byte{0x55, 0xaa}, buf[510:512]) // boot signature
}

func TestGPTSuite(t *testing.T) {
Expand Down

0 comments on commit fe24303

Please sign in to comment.