isisd: improve validation of flex-algo decoder#21314
Conversation
Greptile SummaryThis PR hardens the flex-algo sub-TLV decoder in
The stream accounting and
Confidence Score: 4/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Receive ISIS_SUBTLV_FAD] --> B{length < FAD_MIN_SIZE?}
B -- Yes --> C[stream_forward_getp length\nbreak case]
B -- No --> D[Read 4 fixed bytes\nalgorithm/metric/calc/priority\nAlloc & init fad struct]
D --> E[subsubtlvs_len = length - 4]
E --> F{subsubtlvs_len > 2?}
F -- No --> Z[break case]
F -- Yes --> G[Read subsubtlv_type + subsubtlv_len\n2 bytes]
G --> H{subsubtlv_len >\nsubsubtlvs_len - 2?}
H -- Yes\noverrun --> I[stream_forward_getp\nsubsubtlvs_len - 2\nbreak while loop]
I --> Z
H -- No --> J{subsubtlv_type?}
J -- EXCAG/INCANYAG/INCALLAG --> K{len < 4 or\nnot multiple of 4?}
K -- Yes --> L[stream_forward_getp subsubtlv_len\nbreak switch]
K -- No --> M[Read n_ag × uint32_t values\ninto admin_group]
M --> N[break switch]
L --> N
J -- FLAGS --> O[Read flags byte +\nskip remaining]
O --> N
J -- ESRLG --> P[stream_forward_getp subsubtlv_len]
P --> N
J -- default --> Q[Log unsupported\nstream_forward_getp subsubtlv_len]
Q --> N
N --> R[subsubtlvs_len -= 2 + subsubtlv_len]
R --> F
Prompt To Fix All With AIThis is a comment left during a code review.
Path: isisd/isis_tlvs.c
Line: 5197
Comment:
**Typo in log message: "INCANYG" should be "INCANYAG"**
The error message is missing the letter `A`, making it inconsistent with the sub-TLV name `ISIS_SUBTLV_FAD_SUBSUBTLV_INCANYAG` and the surrounding messages which correctly spell out "EXCAG" and "INCALLAG".
```suggestion
"Received an invalid Flex-Algo INCANYAG sub-TLV\n");
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (3): Last reviewed commit: "isisd: improve validation of flex-algo d..." | Re-trigger Greptile |
| sbuf_push(log, indent, | ||
| "Received an invalid Flex-Algo sub-TLV type %u\n", | ||
| subsubtlv_type); | ||
| stream_forward_getp(s, subsubtlvs_len); |
There was a problem hiding this comment.
Off-by-two overread in
stream_forward_getp
At this point in the loop, 2 bytes have already been consumed from the stream (subsubtlv_type on line 5164 and subsubtlv_len on line 5165). The number of bytes remaining in the subsubtlvs region is subsubtlvs_len - 2, not subsubtlvs_len. Forwarding subsubtlvs_len bytes will overread 2 bytes past the subsubtlvs boundary and corrupt the outer sub-TLV parser's stream position.
The exact same issue exists in the inner switch-case error paths:
isisd/isis_tlvs.c:5182(EXCAG invalid length)isisd/isis_tlvs.c:5198(INCANYAG invalid length)isisd/isis_tlvs.c:5214(INCALLAG invalid length)
All four should use subsubtlvs_len - 2:
| stream_forward_getp(s, subsubtlvs_len); | |
| stream_forward_getp(s, subsubtlvs_len - 2); |
Prompt To Fix With AI
This is a comment left during a code review.
Path: isisd/isis_tlvs.c
Line: 5172
Comment:
**Off-by-two overread in `stream_forward_getp`**
At this point in the loop, 2 bytes have already been consumed from the stream (`subsubtlv_type` on line 5164 and `subsubtlv_len` on line 5165). The number of bytes remaining in the subsubtlvs region is `subsubtlvs_len - 2`, not `subsubtlvs_len`. Forwarding `subsubtlvs_len` bytes will overread 2 bytes past the subsubtlvs boundary and corrupt the outer sub-TLV parser's stream position.
The exact same issue exists in the inner switch-case error paths:
- `isisd/isis_tlvs.c:5182` (EXCAG invalid length)
- `isisd/isis_tlvs.c:5198` (INCANYAG invalid length)
- `isisd/isis_tlvs.c:5214` (INCALLAG invalid length)
All four should use `subsubtlvs_len - 2`:
```suggestion
stream_forward_getp(s, subsubtlvs_len - 2);
```
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
yes, this is valid - confused "subsubtlv" and "subsubtlvs" variables...
| stream_forward_getp(s, subsubtlvs_len); | ||
| break; |
There was a problem hiding this comment.
break exits switch, not the enclosing while loop
This break (and the identical ones at isisd/isis_tlvs.c:5198-5199 and isisd/isis_tlvs.c:5214-5215) only exits the switch statement. After the break, execution continues at line 5245:
subsubtlvs_len -= 2 + subsubtlv_len;This decrements subsubtlvs_len further, and if the new value is still > 2, the while loop continues to read from the stream—past the region that was already skipped by stream_forward_getp. This causes reads from beyond the subsubtlvs region (or potentially past the entire sub-TLV).
A goto is the idiomatic fix in this style of C code:
/* at the error site: */
stream_forward_getp(s, subsubtlvs_len - 2);
goto done_subsubtlvs;/* after the while loop (line 5246): */
done_subsubtlvs:
break; /* breaks the outer switch (case ISIS_SUBTLV_FAD) */Alternatively, set a flag before the inner break and check it after the switch to exit the while.
Prompt To Fix With AI
This is a comment left during a code review.
Path: isisd/isis_tlvs.c
Line: 5182-5183
Comment:
**`break` exits `switch`, not the enclosing `while` loop**
This `break` (and the identical ones at `isisd/isis_tlvs.c:5198-5199` and `isisd/isis_tlvs.c:5214-5215`) only exits the `switch` statement. After the `break`, execution continues at line 5245:
```c
subsubtlvs_len -= 2 + subsubtlv_len;
```
This decrements `subsubtlvs_len` further, and if the new value is still `> 2`, the `while` loop continues to read from the stream—past the region that was already skipped by `stream_forward_getp`. This causes reads from beyond the subsubtlvs region (or potentially past the entire sub-TLV).
A `goto` is the idiomatic fix in this style of C code:
```c
/* at the error site: */
stream_forward_getp(s, subsubtlvs_len - 2);
goto done_subsubtlvs;
```
```c
/* after the while loop (line 5246): */
done_subsubtlvs:
break; /* breaks the outer switch (case ISIS_SUBTLV_FAD) */
```
Alternatively, set a flag before the inner `break` and check it after the `switch` to exit the `while`.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
I think this will be fixed when I fix the preceding stream_forward_getp() calls.
067844d to
4ff5470
Compare
|
Pushed a fix for greptile comments |
|
@greptileai review |
4ff5470 to
9009a88
Compare
|
... and pushed one more time to include reported-by commit comment |
|
@Mergifyio backport stable/10.6 stable/10.5 stable/10.4 stable/10.3 stable/10.2 |
✅ Backports have been createdDetails
Cherry-pick of 42c6dd7 has failed: To fix up this pull request, you can check it out locally. See documentation: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally
Cherry-pick of 42c6dd7 has failed: To fix up this pull request, you can check it out locally. See documentation: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally
Cherry-pick of 42c6dd7 has failed: To fix up this pull request, you can check it out locally. See documentation: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally
Cherry-pick of 42c6dd7 has failed: To fix up this pull request, you can check it out locally. See documentation: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally |
|
@greptile review |
Validate flex-algo sub-TLV before accessing data; validate embedded sub-sub-TLVs before accessing them; avoid length wrap-around. Reported-by: Haruto Kimura (Stella) <harutokimura0608@gmail.com> Signed-off-by: Mark Stapp <mjs@cisco.com>
9009a88 to
42c6dd7
Compare
|
CI:rerun |
isisd: improve validation of flex-algo decoder (backport #21314)
Validate flex-algo sub-TLV before accessing data; validate embedded sub-sub-TLVs before accessing them; avoid length wrap-around.