Skip to content

hugepages_pool_ceiling_mb accepts a bash-inevaluable value and then applies no ceiling at all — the #405 class in a new key #412

Description

@VijitSingh97

What

hugepages_pool_ceiling_mb (#398, new in v1.16.0) accepts a value with more digits than bash can
evaluate as an integer, and then silently applies no ceiling at all. The key exists to be a hard
cap; in this case it is a declaration that reads as a guard and enforces nothing.

This is the same defect class as #405[ "$X" -lt 1 ] returning 2 rather than false — in a new
key. v1.16.0 was tagged before #405's fix landed, so the lesson had not yet reached this code.

The chain, both halves

Validation accepts it. rigforge.sh, parse_config:

if ! [[ "$HUGEPAGES_POOL_CEILING_MB" =~ ^[0-9]+$ ]] || [ "$HUGEPAGES_POOL_CEILING_MB" -gt 65536 ]; then

An all-digits value passes the regex, so the || falls through to [ -gt 65536 ], which returns
2 — not false — on a value bash cannot evaluate. The if takes its else branch and no error
fires. The only tell is a raw [: 99999999999999999999: integer expression expected on stderr.

Then the cap is skipped, silently. _ensure_hugepages:

if [ "${HUGEPAGES_POOL_CEILING_MB:-0}" -gt 0 ] 2>/dev/null; then

The same evaluation fails the same way, and because this one does redirect stderr, the ceiling
block is skipped with no message whatsoever. The write proceeds at the uncapped
current + required - avail.

Reproduction

Executed against the exact predicate shapes, not inferred:

input: 65537                  -> REJECTED                     (correct)
input: 99999999999999999999   -> ACCEPTED                     (wrong; stderr: integer expression expected)
  then _ensure_hugepages:     -> ceiling block SKIPPED, no cap applied

Severity, stated honestly

Fail-open to today's behaviour, not to something new. A rig with a garbage ceiling reserves
exactly what it would have reserved with the key absent, so nothing regresses relative to v1.15.x,
and this does not block the appliance pin bump (pithead#1407).

What it costs is the key's whole purpose. The ceiling is the fix for a RAM-constrained co-resident
box that cannot absorb the over-reserve (#398 / pithead#1103, an ~12 GiB request on an 8 GiB box). An
operator who fat-fingers the value believes that box is capped and it is not.

Suggested fix

Bound the digit length before the numeric comparison, the way #406 fixed the port guard — key on
length first, so the comparison only ever sees a value bash can evaluate. 65536 is a five-digit
ceiling, so anything past six digits is out of range by inspection and needs no arithmetic.

Worth doing in the same pass: _ensure_hugepages's 2>/dev/null hides the second failure. Once
validation is airtight that guard can only see a validated value, but a defensive error there
rather than a silent skip would mean the cap can never be dropped in silence.

Coverage

An assertion that a too-long ceiling is REJECTED, plus a control asserting a valid ceiling is still
accepted and still caps. The existing #405/#408 pool-key assertions in tests/run.sh are the
pattern — each names its own kill so a mutation table stays readable.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions