Skip to content

Commit 1f30edf

Browse files
committed
Merge release-20250820.0-36-g093d944ca (automated)
2 parents c958f00 + 093d944 commit 1f30edf

File tree

5 files changed

+79
-13
lines changed

5 files changed

+79
-13
lines changed

pkg/abi/linux/nf_tables.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,3 +462,14 @@ const (
462462
NFT_META_SDIFNAME // Slave device interface name
463463
NFT_META_BRI_BROUTE // Packet br_netfilter_broute bit
464464
)
465+
466+
// Nftables Generation Attributes
467+
// These correspond to values in include/uapi/linux/netfilter/nf_tables.h.
468+
const (
469+
NFTA_GEN_UNSPEC uint16 = iota
470+
NFTA_GEN_ID
471+
NFTA_GEN_PROC_PID
472+
NFTA_GEN_PROC_NAME
473+
__NFTA_GEN_MAX
474+
NFTA_GEN_MAX = __NFTA_GEN_MAX - 1
475+
)

pkg/sentry/platform/kvm/physical_map.go

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,20 @@ func fillAddressSpace() (specialRegions []specialVirtualRegion) {
107107
}
108108
required := uintptr(requiredAddr)
109109
current := required // Attempted mmap size.
110-
for filled := uintptr(0); filled < required && current > 0; {
111-
suggestedAddr := uintptr(0)
112-
if ring0.VirtualAddressBits > 48 {
113-
// Even though it's safe to pass a high hint address on older kernel or
114-
// older machine without 5-level paging support. We need to guard
115-
// passing the hint based on `ring0.VirtualAddressBits` because Sentry might
116-
// not support 5-level paging for the underlying CPU uarch i.e. arm64.
117-
suggestedAddr = uintptr(1 << ring0.PhysicalAddressBits)
118-
}
110+
filled := uintptr(0)
111+
suggestedAddr := uintptr(0)
112+
if ring0.VirtualAddressBits > 48 {
113+
// Pass a hint address above 47 bits to indicate to the kernel that
114+
// we can handle, and want, mappings above 47 bits:
115+
// https://docs.kernel.org/arch/x86/x86_64/5level-paging.html#user-space-and-large-virtual-address-space.
116+
// Even though it's safe to pass a high hint address on older kernel or
117+
// older machine without 5-level paging support. We need to guard
118+
// passing the hint based on `ring0.VirtualAddressBits` because Sentry might
119+
// not support 5-level paging for the underlying CPU uarch i.e. arm64.
120+
suggestedAddr = ring0.UserspaceSize - hostarch.PageSize
121+
}
122+
var lastMmapErrno unix.Errno
123+
for filled < required && current > 0 {
119124
addr, errno := hostsyscall.RawSyscall6(
120125
unix.SYS_MMAP,
121126
suggestedAddr,
@@ -128,6 +133,7 @@ func fillAddressSpace() (specialRegions []specialVirtualRegion) {
128133
// One page is the smallest mapping that can be allocated.
129134
if current == hostarch.PageSize {
130135
current = 0
136+
lastMmapErrno = errno
131137
break
132138
}
133139
// Attempt half the size; overflow not possible.
@@ -168,6 +174,17 @@ func fillAddressSpace() (specialRegions []specialVirtualRegion) {
168174
}
169175
}
170176
if current == 0 {
177+
log.Warningf("Filling address space failed (VirtualAddressBits=%d PhysicalAddressBits=%d vSize=%#x pSize=%#x faultBlockSize=%#x required=%#x filled=%#x); last mmap errno: %v; VMAs:", ring0.VirtualAddressBits, ring0.PhysicalAddressBits, vSize, pSize, faultBlockSize, required, filled, lastMmapErrno)
178+
err := applyVirtualRegions(func(vr virtualRegion) {
179+
ps := "p"
180+
if vr.shared {
181+
ps = "s"
182+
}
183+
log.Warningf("%x-%x %v%s %08x %s", vr.region.virtual, vr.region.virtual+vr.region.length, vr.accessType, ps, vr.offset, vr.filename)
184+
})
185+
if err != nil {
186+
log.Warningf("Failed to get all VMAs: %v", err)
187+
}
171188
panic("filling address space failed")
172189
}
173190
sort.Slice(specialRegions, func(i, j int) bool {

pkg/sentry/socket/netlink/netfilter/protocol.go

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,25 @@ func fillRuleInfo(rule *nftables.Rule, ms *nlmsg.MessageSet) *syserr.AnnotatedEr
11021102
return nil
11031103
}
11041104

1105+
// getGen returns the generation info for the current nftables instance.
1106+
func (p *Protocol) getGen(nft *nftables.NFTables, task *kernel.Task, attrs map[uint16]nlmsg.BytesView, family stack.AddressFamily, msgFlags uint16, ms *nlmsg.MessageSet) *syserr.AnnotatedError {
1107+
m := ms.AddMessage(linux.NetlinkMessageHeader{
1108+
Type: uint16(linux.NFNL_SUBSYS_NFTABLES)<<8 | uint16(linux.NFT_MSG_NEWGEN),
1109+
})
1110+
m.Put(&linux.NetFilterGenMsg{
1111+
Family: uint8(nftables.AfProtocol(stack.Unspec)),
1112+
Version: uint8(linux.NFNETLINK_V0),
1113+
// Unused, set to 0.
1114+
ResourceID: uint16(0),
1115+
})
1116+
1117+
m.PutAttr(linux.NFTA_GEN_ID, nlmsg.PutU32(nft.GetGenID()))
1118+
m.PutAttr(linux.NFTA_GEN_PROC_PID, nlmsg.PutU32(uint32(task.ThreadGroup().ID())))
1119+
// TODO - b/434244017: Add support for dumping the process name.
1120+
m.PutAttrString(linux.NFTA_GEN_PROC_NAME, "placeholder")
1121+
return nil
1122+
}
1123+
11051124
// isNetDevHook returns whether the given family and hook number represent a
11061125
// netdev hook, or if the family is inet and is attempting to attach to
11071126
// Ingress or Egress hooks.
@@ -1170,9 +1189,20 @@ func (p *Protocol) ProcessMessage(ctx context.Context, s *netlink.Socket, msg *n
11701189
}
11711190

11721191
return nil
1173-
case linux.NFT_MSG_GETRULE_RESET,
1174-
linux.NFT_MSG_GETSET, linux.NFT_MSG_GETSETELEM,
1175-
linux.NFT_MSG_GETSETELEM_RESET, linux.NFT_MSG_GETGEN,
1192+
case linux.NFT_MSG_GETGEN:
1193+
if err := p.getGen(nft, kernel.TaskFromContext(ctx), attrs, family, hdr.Flags, ms); err != nil {
1194+
log.Debugf("Nftables get gen error: %s", err)
1195+
return err.GetError()
1196+
}
1197+
return nil
1198+
case linux.NFT_MSG_GETSET:
1199+
// TODO - b/421437663: Implement sets for nftables. This skeleton is
1200+
// left here to satisfy auxiliary calls from the nft CLI not needed
1201+
// for packet filtering functionality.
1202+
ms.Multi = true
1203+
return nil
1204+
case linux.NFT_MSG_GETRULE_RESET, linux.NFT_MSG_GETSETELEM,
1205+
linux.NFT_MSG_GETSETELEM_RESET,
11761206
linux.NFT_MSG_GETOBJ, linux.NFT_MSG_GETOBJ_RESET,
11771207
linux.NFT_MSG_GETFLOWTABLE:
11781208

pkg/tcpip/nftables/nftables.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,12 @@ func NewNFTables(clock tcpip.Clock, rng rand.RNG) *NFTables {
243243
if rng.Reader == nil {
244244
panic("nftables state must be initialized with a non-nil random number generator")
245245
}
246-
return &NFTables{clock: clock, startTime: clock.Now(), rng: rng, tableHandleCounter: atomicbitops.Uint64{}}
246+
return &NFTables{clock: clock, startTime: clock.Now(), rng: rng, tableHandleCounter: atomicbitops.Uint64{}, genid: 1}
247+
}
248+
249+
// GetGenID returns the generation ID for the NFTables object.
250+
func (nf *NFTables) GetGenID() uint32 {
251+
return nf.genid
247252
}
248253

249254
// Flush clears entire ruleset and all data for all address families

pkg/tcpip/nftables/nftables_types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ const (
8787

8888
// addressFamilyProtocols maps address families to their protocol number.
8989
var addressFamilyProtocols = map[stack.AddressFamily]uint8{
90+
stack.Unspec: linux.NFPROTO_UNSPEC,
9091
stack.IP: linux.NFPROTO_IPV4,
9192
stack.IP6: linux.NFPROTO_IPV6,
9293
stack.Inet: linux.NFPROTO_INET,
@@ -243,6 +244,7 @@ type NFTables struct {
243244
rng rand.RNG // Random number generator.
244245
tableHandleCounter atomicbitops.Uint64 // Table handle counter.
245246
Mu nfTablesRWMutex // Mutex for tableHandles.
247+
genid uint32 // Generation ID for nftables.
246248
}
247249

248250
// Ensures NFTables implements the NFTablesInterface.
@@ -1260,4 +1262,5 @@ func (nf *NFTables) DeepCopy() *NFTables {
12601262
// with the tables of the passed in NFTables struct.
12611263
func (nf *NFTables) ReplaceNFTables(nftCopy *NFTables) {
12621264
nf.filters = nftCopy.filters
1265+
nf.genid++
12631266
}

0 commit comments

Comments
 (0)