summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--pkg/sentry/fs/ext4/disklayout/BUILD11
-rw-r--r--pkg/sentry/fs/ext4/disklayout/block_group_test.go16
-rw-r--r--pkg/sentry/fs/ext4/disklayout/superblock_32.go76
-rw-r--r--pkg/sentry/fs/ext4/disklayout/superblock_64.go94
-rw-r--r--pkg/sentry/fs/ext4/disklayout/superblock_old.go108
-rw-r--r--pkg/sentry/fs/ext4/disklayout/superblock_test.go27
-rw-r--r--pkg/sentry/fs/ext4/disklayout/test_utils.go30
7 files changed, 348 insertions, 14 deletions
diff --git a/pkg/sentry/fs/ext4/disklayout/BUILD b/pkg/sentry/fs/ext4/disklayout/BUILD
index be637bcbb..cdac63655 100644
--- a/pkg/sentry/fs/ext4/disklayout/BUILD
+++ b/pkg/sentry/fs/ext4/disklayout/BUILD
@@ -9,14 +9,21 @@ go_library(
"block_group_32.go",
"block_group_64.go",
"superblock.go",
+ "superblock_32.go",
+ "superblock_64.go",
+ "superblock_old.go",
+ "test_utils.go",
],
importpath = "gvisor.dev/gvisor/pkg/sentry/fs/ext4/disklayout",
+ deps = ["//pkg/binary"],
)
go_test(
name = "disklayout_test",
size = "small",
- srcs = ["block_group_test.go"],
+ srcs = [
+ "block_group_test.go",
+ "superblock_test.go",
+ ],
embed = [":disklayout"],
- deps = ["//pkg/binary"],
)
diff --git a/pkg/sentry/fs/ext4/disklayout/block_group_test.go b/pkg/sentry/fs/ext4/disklayout/block_group_test.go
index 794ae99cc..0ef4294c0 100644
--- a/pkg/sentry/fs/ext4/disklayout/block_group_test.go
+++ b/pkg/sentry/fs/ext4/disklayout/block_group_test.go
@@ -16,19 +16,11 @@ package disklayout
import (
"testing"
-
- "gvisor.dev/gvisor/pkg/binary"
)
-// TestBlockGroupSize tests the fact that the block group struct for
-// 32-bit ext filesystems should be exactly 32 bytes big and for 64-bit fs it
-// should be 64 bytes.
+// TestBlockGroupSize tests that the block group descriptor structs are of the
+// correct size.
func TestBlockGroupSize(t *testing.T) {
- if got, want := int(binary.Size(BlockGroup32Bit{})), 32; got != want {
- t.Errorf("BlockGroup32Bit should be exactly 32 bytes but is %d bytes", got)
- }
-
- if got, want := int(binary.Size(BlockGroup64Bit{})), 64; got != want {
- t.Errorf("BlockGroup64Bit should be exactly 64 bytes but is %d bytes", got)
- }
+ assertSize(t, BlockGroup32Bit{}, 32)
+ assertSize(t, BlockGroup64Bit{}, 64)
}
diff --git a/pkg/sentry/fs/ext4/disklayout/superblock_32.go b/pkg/sentry/fs/ext4/disklayout/superblock_32.go
new file mode 100644
index 000000000..4c3233eed
--- /dev/null
+++ b/pkg/sentry/fs/ext4/disklayout/superblock_32.go
@@ -0,0 +1,76 @@
+// Copyright 2019 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package disklayout
+
+// SuperBlock32Bit implements SuperBlock and represents the 32-bit version of
+// the ext4_super_block struct in fs/ext4/ext4.h.
+//
+// The suffix `Raw` has been added to indicate that the field does not have a
+// counterpart in the 64-bit version and to resolve name collision with the
+// interface.
+type SuperBlock32Bit struct {
+ // We embed the old superblock struct here because the 32-bit version is just
+ // an extension of the old version.
+ SuperBlockOld
+
+ FirstInode uint32
+ InodeSizeRaw uint16
+ BlockGroupNumber uint16
+ FeatureCompat uint32
+ FeatureIncompat uint32
+ FeatureRoCompat uint32
+ UUID [16]byte
+ VolumeName [16]byte
+ LastMounted [64]byte
+ AlgoUsageBitmap uint32
+ PreallocBlocks uint8
+ PreallocDirBlocks uint8
+ ReservedGdtBlocks uint16
+ JournalUUID [16]byte
+ JournalInum uint32
+ JournalDev uint32
+ LastOrphan uint32
+ HashSeed [4]uint32
+ DefaultHashVersion uint8
+ JnlBackupType uint8
+ BgDescSizeRaw uint16
+ DefaultMountOpts uint32
+ FirstMetaBg uint32
+ MkfsTime uint32
+ JnlBlocks [17]uint32
+}
+
+// Only override methods which change based on the additional fields above.
+// Not overriding SuperBlock.BgDescSize because it would still return 32 here.
+
+// InodeSize implements SuperBlock.InodeSize.
+func (sb *SuperBlock32Bit) InodeSize() uint16 {
+ return sb.InodeSizeRaw
+}
+
+// CompatibleFeatures implements SuperBlock.CompatibleFeatures.
+func (sb *SuperBlock32Bit) CompatibleFeatures() CompatFeatures {
+ return CompatFeaturesFromInt(sb.FeatureCompat)
+}
+
+// IncompatibleFeatures implements SuperBlock.IncompatibleFeatures.
+func (sb *SuperBlock32Bit) IncompatibleFeatures() IncompatFeatures {
+ return IncompatFeaturesFromInt(sb.FeatureIncompat)
+}
+
+// ReadOnlyCompatibleFeatures implements SuperBlock.ReadOnlyCompatibleFeatures.
+func (sb *SuperBlock32Bit) ReadOnlyCompatibleFeatures() RoCompatFeatures {
+ return RoCompatFeaturesFromInt(sb.FeatureRoCompat)
+}
diff --git a/pkg/sentry/fs/ext4/disklayout/superblock_64.go b/pkg/sentry/fs/ext4/disklayout/superblock_64.go
new file mode 100644
index 000000000..2e945a7c7
--- /dev/null
+++ b/pkg/sentry/fs/ext4/disklayout/superblock_64.go
@@ -0,0 +1,94 @@
+// Copyright 2019 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package disklayout
+
+// SuperBlock64Bit implements SuperBlock and represents the 64-bit version of
+// the ext4_super_block struct in fs/ext4/ext4.h. This sums up to be exactly
+// 1024 bytes (smallest possible block size) and hence the superblock always
+// fits in no more than one data block.
+//
+// The suffix `Hi` here stands for upper bits because they represent the upper
+// half of the fields.
+type SuperBlock64Bit struct {
+ // We embed the 32-bit struct here because 64-bit version is just an extension
+ // of the 32-bit version.
+ SuperBlock32Bit
+
+ BlocksCountHi uint32
+ ReservedBlocksCountHi uint32
+ FreeBlocksCountHi uint32
+ MinInodeSize uint16
+ WantInodeSize uint16
+ Flags uint32
+ RaidStride uint16
+ MmpInterval uint16
+ MmpBlock uint64
+ RaidStripeWidth uint32
+ LogGroupsPerFlex uint8
+ ChecksumType uint8
+ _ uint16
+ KbytesWritten uint64
+ SnapshotInum uint32
+ SnapshotID uint32
+ SnapshotRsrvBlocksCount uint64
+ SnapshotList uint32
+ ErrorCount uint32
+ FirstErrorTime uint32
+ FirstErrorInode uint32
+ FirstErrorBlock uint64
+ FirstErrorFunction [32]byte
+ FirstErrorLine uint32
+ LastErrorTime uint32
+ LastErrorInode uint32
+ LastErrorLine uint32
+ LastErrorBlock uint64
+ LastErrorFunction [32]byte
+ MountOpts [64]byte
+ UserQuotaInum uint32
+ GroupQuotaInum uint32
+ OverheadBlocks uint32
+ BackupBgs [2]uint32
+ EncryptAlgos [4]uint8
+ EncryptPwSalt [16]uint8
+ LostFoundInode uint32
+ ProjectQuotaInode uint32
+ ChecksumSeed uint32
+ WtimeHi uint8
+ MtimeHi uint8
+ MkfsTimeHi uint8
+ LastCheckHi uint8
+ FirstErrorTimeHi uint8
+ LastErrorTimeHi uint8
+ _ [2]uint8
+ Encoding uint16
+ EncodingFlags uint16
+ _ [95]uint32
+ Checksum uint32
+}
+
+// Only override methods which change based on the 64-bit feature.
+
+// BlocksCount implements SuperBlock.BlocksCount.
+func (sb *SuperBlock64Bit) BlocksCount() uint64 {
+ return (uint64(sb.BlocksCountHi) << 32) | uint64(sb.BlocksCountLo)
+}
+
+// FreeBlocksCount implements SuperBlock.FreeBlocksCount.
+func (sb *SuperBlock64Bit) FreeBlocksCount() uint64 {
+ return (uint64(sb.FreeBlocksCountHi) << 32) | uint64(sb.FreeBlocksCountLo)
+}
+
+// BgDescSize implements SuperBlock.BgDescSize.
+func (sb *SuperBlock64Bit) BgDescSize() uint16 { return sb.BgDescSizeRaw }
diff --git a/pkg/sentry/fs/ext4/disklayout/superblock_old.go b/pkg/sentry/fs/ext4/disklayout/superblock_old.go
new file mode 100644
index 000000000..1f7425ba3
--- /dev/null
+++ b/pkg/sentry/fs/ext4/disklayout/superblock_old.go
@@ -0,0 +1,108 @@
+// Copyright 2019 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package disklayout
+
+// SuperBlockOld implements SuperBlock and represents the old version of the
+// superblock struct in ext2 and ext3 systems.
+//
+// The suffix `Lo` here stands for lower bits because this is also used in the
+// 64-bit version where these fields represent the lower half of the fields.
+// The suffix `Raw` has been added to indicate that the field does not have a
+// counterpart in the 64-bit version and to resolve name collision with the
+// interface.
+type SuperBlockOld struct {
+ InodesCountRaw uint32
+ BlocksCountLo uint32
+ ReservedBlocksCount uint32
+ FreeBlocksCountLo uint32
+ FreeInodesCountRaw uint32
+ FirstDataBlockRaw uint32
+ LogBlockSize uint32
+ LogClusterSize uint32
+ BlocksPerGroupRaw uint32
+ ClustersPerGroupRaw uint32
+ InodesPerGroupRaw uint32
+ Mtime uint32
+ Wtime uint32
+ MountCountRaw uint16
+ MaxMountCountRaw uint16
+ MagicRaw uint16
+ State uint16
+ Errors uint16
+ MinorRevLevel uint16
+ LastCheck uint32
+ CheckInterval uint32
+ CreatorOS uint32
+ RevLevel uint32
+ DefResUID uint16
+ DefResGID uint16
+}
+
+// InodesCount implements SuperBlock.InodesCount.
+func (sb *SuperBlockOld) InodesCount() uint32 { return sb.InodesCountRaw }
+
+// BlocksCount implements SuperBlock.BlocksCount.
+func (sb *SuperBlockOld) BlocksCount() uint64 { return uint64(sb.BlocksCountLo) }
+
+// FreeBlocksCount implements SuperBlock.FreeBlocksCount.
+func (sb *SuperBlockOld) FreeBlocksCount() uint64 { return uint64(sb.FreeBlocksCountLo) }
+
+// FreeInodesCount implements SuperBlock.FreeInodesCount.
+func (sb *SuperBlockOld) FreeInodesCount() uint32 { return sb.FreeInodesCountRaw }
+
+// MountCount implements SuperBlock.MountCount.
+func (sb *SuperBlockOld) MountCount() uint16 { return sb.MountCountRaw }
+
+// MaxMountCount implements SuperBlock.MaxMountCount.
+func (sb *SuperBlockOld) MaxMountCount() uint16 { return sb.MaxMountCountRaw }
+
+// FirstDataBlock implements SuperBlock.FirstDataBlock.
+func (sb *SuperBlockOld) FirstDataBlock() uint32 { return sb.FirstDataBlockRaw }
+
+// BlockSize implements SuperBlock.BlockSize.
+func (sb *SuperBlockOld) BlockSize() uint64 { return 1 << (10 + sb.LogBlockSize) }
+
+// BlocksPerGroup implements SuperBlock.BlocksPerGroup.
+func (sb *SuperBlockOld) BlocksPerGroup() uint32 { return sb.BlocksPerGroupRaw }
+
+// ClusterSize implements SuperBlock.ClusterSize.
+func (sb *SuperBlockOld) ClusterSize() uint64 { return 1 << (10 + sb.LogClusterSize) }
+
+// ClustersPerGroup implements SuperBlock.ClustersPerGroup.
+func (sb *SuperBlockOld) ClustersPerGroup() uint32 { return sb.ClustersPerGroupRaw }
+
+// InodeSize implements SuperBlock.InodeSize.
+func (sb *SuperBlockOld) InodeSize() uint16 { return 128 }
+
+// InodesPerGroup implements SuperBlock.InodesPerGroup.
+func (sb *SuperBlockOld) InodesPerGroup() uint32 { return sb.InodesPerGroupRaw }
+
+// BgDescSize implements SuperBlock.BgDescSize.
+func (sb *SuperBlockOld) BgDescSize() uint16 { return 32 }
+
+// CompatibleFeatures implements SuperBlock.CompatibleFeatures.
+func (sb *SuperBlockOld) CompatibleFeatures() CompatFeatures { return CompatFeatures{} }
+
+// IncompatibleFeatures implements SuperBlock.IncompatibleFeatures.
+func (sb *SuperBlockOld) IncompatibleFeatures() IncompatFeatures { return IncompatFeatures{} }
+
+// ReadOnlyCompatibleFeatures implements SuperBlock.ReadOnlyCompatibleFeatures.
+func (sb *SuperBlockOld) ReadOnlyCompatibleFeatures() RoCompatFeatures { return RoCompatFeatures{} }
+
+// Magic implements SuperBlock.Magic.
+func (sb *SuperBlockOld) Magic() uint16 { return sb.MagicRaw }
+
+// Revision implements SuperBlock.Revision.
+func (sb *SuperBlockOld) Revision() SbRevision { return SbRevision(sb.RevLevel) }
diff --git a/pkg/sentry/fs/ext4/disklayout/superblock_test.go b/pkg/sentry/fs/ext4/disklayout/superblock_test.go
new file mode 100644
index 000000000..463b5ba21
--- /dev/null
+++ b/pkg/sentry/fs/ext4/disklayout/superblock_test.go
@@ -0,0 +1,27 @@
+// Copyright 2019 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package disklayout
+
+import (
+ "testing"
+)
+
+// TestSuperBlockSize tests that the superblock structs are of the correct
+// size.
+func TestSuperBlockSize(t *testing.T) {
+ assertSize(t, SuperBlockOld{}, 84)
+ assertSize(t, SuperBlock32Bit{}, 336)
+ assertSize(t, SuperBlock64Bit{}, 1024)
+}
diff --git a/pkg/sentry/fs/ext4/disklayout/test_utils.go b/pkg/sentry/fs/ext4/disklayout/test_utils.go
new file mode 100644
index 000000000..9c63f04c0
--- /dev/null
+++ b/pkg/sentry/fs/ext4/disklayout/test_utils.go
@@ -0,0 +1,30 @@
+// Copyright 2019 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package disklayout
+
+import (
+ "reflect"
+ "testing"
+
+ "gvisor.dev/gvisor/pkg/binary"
+)
+
+func assertSize(t *testing.T, v interface{}, want uintptr) {
+ t.Helper()
+
+ if got := binary.Size(v); got != want {
+ t.Errorf("struct %s should be exactly %d bytes but is %d bytes", reflect.TypeOf(v).Name(), want, got)
+ }
+}