mirror of
https://github.com/apple/container.git
synced 2026-09-27 17:36:08 -04:00
Fix potential integer math crash on PublishPort. (#1612)
- Closes #1610. - Discovered, and originally filed as a security advisory, by: PresidentL <131139636+liyander@users.noreply.github.com>. - `PublishPort` currently can store invalid combinations of starting port and range that can overflow UInt16 values when summed, crashing the process. - Updates `PublishPort` to validate inputs on initialization.
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
// limitations under the License.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import ContainerizationError
|
||||
import ContainerizationExtras
|
||||
|
||||
/// The network protocols available for port forwarding.
|
||||
@@ -54,12 +55,20 @@ public struct PublishPort: Sendable, Codable {
|
||||
public let count: UInt16
|
||||
|
||||
/// Creates a new port forwarding specification.
|
||||
public init(hostAddress: IPAddress, hostPort: UInt16, containerPort: UInt16, proto: PublishProtocol, count: UInt16) {
|
||||
public init(
|
||||
hostAddress: IPAddress,
|
||||
hostPort: UInt16,
|
||||
containerPort: UInt16,
|
||||
proto: PublishProtocol,
|
||||
count: UInt16
|
||||
) throws {
|
||||
self.hostAddress = hostAddress
|
||||
self.hostPort = hostPort
|
||||
self.containerPort = containerPort
|
||||
self.proto = proto
|
||||
self.count = count
|
||||
try validatePortRange(port: hostPort, count: count)
|
||||
try validatePortRange(port: containerPort, count: count)
|
||||
}
|
||||
|
||||
/// Create a configuration from the supplied Decoder, initializing missing
|
||||
@@ -72,6 +81,14 @@ public struct PublishPort: Sendable, Codable {
|
||||
containerPort = try container.decode(UInt16.self, forKey: .containerPort)
|
||||
proto = try container.decode(PublishProtocol.self, forKey: .proto)
|
||||
count = try container.decodeIfPresent(UInt16.self, forKey: .count) ?? 1
|
||||
try validatePortRange(port: hostPort, count: count)
|
||||
try validatePortRange(port: containerPort, count: count)
|
||||
}
|
||||
|
||||
private func validatePortRange(port: UInt16, count: UInt16) throws {
|
||||
guard count > 0, UInt16.max - port >= count - 1 else {
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid port and count: \(port), \(count)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,8 +96,8 @@ extension [PublishPort] {
|
||||
public func hasOverlaps() -> Bool {
|
||||
var hostPorts = Set<String>()
|
||||
for publishPort in self {
|
||||
for index in publishPort.hostPort..<(publishPort.hostPort + publishPort.count) {
|
||||
let hostPortKey = "\(index)/\(publishPort.proto.rawValue)"
|
||||
for offset in 0..<publishPort.count {
|
||||
let hostPortKey = "\(publishPort.hostPort + offset)/\(publishPort.proto.rawValue)"
|
||||
guard !hostPorts.contains(hostPortKey) else {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -701,7 +701,7 @@ public struct Parser {
|
||||
throw ContainerizationError(.invalidArgument, message: "publish host and container port counts are not equal: \(hostPortText):\(containerPortText)")
|
||||
}
|
||||
|
||||
return PublishPort(
|
||||
return try PublishPort(
|
||||
hostAddress: hostAddress,
|
||||
hostPort: hostPortRangeStart,
|
||||
containerPort: containerPortRangeStart,
|
||||
|
||||
Reference in New Issue
Block a user