Skip to content

Commit fe24303

Browse files
smiratalos-bot
authored andcommitted
fix: perform correct PMBR partition calculations
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>
1 parent 2ec0c3c commit fe24303

File tree

2 files changed

+32
-9
lines changed

2 files changed

+32
-9
lines changed

blockdevice/partition/gpt/gpt.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"encoding/binary"
99
"errors"
1010
"fmt"
11+
"math"
1112
"os"
1213

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

380+
// CHS for the start of the partition
381+
copy(b[1:4], []byte{0x00, 0x02, 0x00})
382+
383+
// CHS for the end of the partition
384+
copy(b[5:8], []byte{0xff, 0xff, 0xff})
385+
379386
// Partition start LBA.
380387
binary.LittleEndian.PutUint32(b[8:12], 1)
381388

382389
// Partition length in sectors.
383-
binary.LittleEndian.PutUint32(b[12:16], uint32(h.BackupLBA))
390+
// This might overflow uint32, so check accordingly
391+
if h.BackupLBA > math.MaxUint32 {
392+
binary.LittleEndian.PutUint32(b[12:16], uint32(math.MaxUint32))
393+
} else {
394+
binary.LittleEndian.PutUint32(b[12:16], uint32(h.BackupLBA))
395+
}
384396

385397
return p, nil
386398
}

blockdevice/partition/gpt/gpt_test.go

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package gpt_test
66

77
import (
8+
"encoding/binary"
89
"os"
910
"testing"
1011

@@ -49,7 +50,7 @@ func (suite *GPTSuite) TestReset() {
4950

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

52-
suite.checkMBRFlag(0x00)
53+
suite.validatePMBR(0x00)
5354

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

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

66-
suite.checkMBRFlag(0x00)
67+
suite.validatePMBR(0x00)
6768

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

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

443-
suite.checkMBRFlag(0x80)
444+
suite.validatePMBR(0x80)
444445

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

452-
suite.checkMBRFlag(0x80)
453+
suite.validatePMBR(0x80)
453454
}
454455

455-
func (suite *GPTSuite) checkMBRFlag(flag byte) {
456-
buf := make([]byte, 1)
456+
func (suite *GPTSuite) validatePMBR(flag byte) {
457+
buf := make([]byte, 512)
457458

458-
_, err := suite.Dev.ReadAt(buf, 446)
459+
n, err := suite.Dev.ReadAt(buf, 0)
459460
suite.Require().NoError(err)
461+
suite.Require().EqualValues(512, n)
460462

461-
suite.Assert().Equal(flag, buf[0])
463+
partition := buf[446:460]
464+
465+
suite.Assert().Equal(flag, partition[0]) // active flag
466+
suite.Assert().Equal([]byte{0x00, 0x02, 0x00}, partition[1:4]) // CHS start
467+
suite.Assert().Equal(byte(0xee), partition[4]) // partition type
468+
suite.Assert().Equal([]byte{0xff, 0xff, 0xff}, partition[5:8]) // CHS end
469+
suite.Assert().Equal(uint32(1), binary.LittleEndian.Uint32(partition[8:12])) // LBA start
470+
suite.Assert().Equal(uint32(size/blockSize-1), binary.LittleEndian.Uint32(partition[12:16])) // length in sectors
471+
472+
suite.Assert().Equal([]byte{0x55, 0xaa}, buf[510:512]) // boot signature
462473
}
463474

464475
func TestGPTSuite(t *testing.T) {

0 commit comments

Comments
 (0)