Skip to content

Commit

Permalink
fix: blockdevice reset should read partition table from disk
Browse files Browse the repository at this point in the history
The problem was that partition table was never read from disk, so header
was written uninitialized (with zeroes). That leads to `header.Size`
being zero which in turns leads to panic in `DeserializeCRC` which
doesn't do any bounds checking before accessing the slice.

Signed-off-by: Andrey Smirnov <[email protected]>
  • Loading branch information
smira authored and talos-bot committed Dec 4, 2020
1 parent 5b4ee44 commit 943b08b
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 4 deletions.
13 changes: 9 additions & 4 deletions blockdevice/blockdevice_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,17 @@ func (bd *BlockDevice) WipeRange(start, length uint64) (string, error) {

// Reset will reset a block device given a device name.
// Simply deletes partition table on device.
func (bd *BlockDevice) Reset() (err error) {
for _, p := range bd.g.Partitions().Items() {
if err = bd.g.Delete(p); err != nil {
func (bd *BlockDevice) Reset() error {
g, err := bd.PartitionTable()
if err != nil {
return err
}

for _, p := range g.Partitions().Items() {
if err = g.Delete(p); err != nil {
return fmt.Errorf("failed to delete partition: %w", err)
}
}

return bd.g.Write()
return g.Write()
}
2 changes: 2 additions & 0 deletions blockdevice/lba/lba_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ func (l *LBA) ReadAt(lba, off, length int64) (b []byte, err error) {

off = lba*l.LogicalBlockSize + off

// TODO: this should either use a loop or ReadFull, as Read() is not guaranteed
// to read full buffer
n, err := l.f.ReadAt(b, off)
if err != nil {
return nil, err
Expand Down
38 changes: 38 additions & 0 deletions blockdevice/partition/gpt/gpt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,44 @@ func (suite *GPTSuite) TearDownTest() {
suite.Assert().NoError(os.Remove(suite.f.Name()))
}

func (suite *GPTSuite) TestEmpty() {
_, err := gpt.Open(suite.dev)
suite.Require().Error(err)
}

func (suite *GPTSuite) TestReset() {
g, err := gpt.New(suite.dev)
suite.Require().NoError(err)

_, err = g.Add(1048576, gpt.WithPartitionName("boot"))
suite.Require().NoError(err)

_, err = g.Add(1048576, gpt.WithPartitionName("efi"))
suite.Require().NoError(err)

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

// re-read the partition table
g, err = gpt.Open(suite.dev)
suite.Require().NoError(err)

suite.Require().NoError(g.Read())

for _, p := range g.Partitions().Items() {
suite.Require().NoError(g.Delete(p))
}

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

// re-read the partition table
g, err = gpt.Open(suite.dev)
suite.Require().NoError(err)

suite.Require().NoError(g.Read())

suite.Assert().Empty(g.Partitions().Items())
}

func (suite *GPTSuite) TestPartitionAdd() {
g, err := gpt.New(suite.dev)
suite.Require().NoError(err)
Expand Down
4 changes: 4 additions & 0 deletions blockdevice/partition/gpt/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,10 @@ func (h *Header) DeserializeSize() (err error) {

h.Size = binary.LittleEndian.Uint32(data)

if h.Size < HeaderSize {
return fmt.Errorf("header size too small: %d", h.Size)
}

return nil
}

Expand Down

0 comments on commit 943b08b

Please sign in to comment.