Skip to content

subnetMaskToCIDR() accepts non-contiguous netmasks, silently producing a wrong CIDR #909

Description

@ArkVex

Summary

subnetMaskToCIDR() in pkg/unikontainers/unikernels/utils.go computes the
prefix length by counting the number of 1 bits in the mask, without checking
that those bits are contiguous. As a result, structurally-invalid netmasks
(where the set bits are not left-aligned) are accepted and mapped to a
plausible-but-wrong CIDR instead of being rejected.

Steps to reproduce

Feeding a few masks through the current logic:

Input mask Returned Correct behavior
255.0.255.0 /16 error (invalid mask)
0.255.255.255 /24 error (invalid mask)
255.255.1.0 /17 error (invalid mask)

A valid IPv4 mask must be a contiguous run of 1s followed by 0s
(e.g. 255.255.255.0). The current implementation only counts bits, so
255.0.255.0 (16 set bits) is accepted as /16.

Impact

Low severity this is an input-validation gap, not a crash. But the resulting
CIDR is used to build the guest's network configuration, so a malformed mask
propagates silently into wrong guest networking rather than failing fast with a
clear error.

Suggested fix

After parsing the four octets into a uint32 mask value v, reject any mask
whose inverse is not a contiguous low-bit block:

inv := ^v
if inv&(inv+1) != 0 {
    return 0, fmt.Errorf("invalid (non-contiguous) subnet mask: %s", subnetMask)
}

I verified this guard accepts all 33 canonical masks (/0/32) with the
correct CIDR and rejects the non-contiguous cases above.

How this was found

Surfaced while adding fuzz coverage for the unikernel parsers (relates to #852).
A FuzzSubnetMaskToCIDR target with a contiguity oracle fails on the seed
corpus immediately. Happy to open a PR adding both the validation and the fuzz
target if that's useful.

CC @ananos @cmainas

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions