Skip to content

pathd: prevent stack buffer overflow in path_zebra_add_sr_policy()#22441

Open
guoguojia2021 wants to merge 1 commit into
FRRouting:masterfrom
guoguojia2021:fix/pathd-sr-policy-label-overflow
Open

pathd: prevent stack buffer overflow in path_zebra_add_sr_policy()#22441
guoguojia2021 wants to merge 1 commit into
FRRouting:masterfrom
guoguojia2021:fix/pathd-sr-policy-label-overflow

Conversation

@guoguojia2021

Copy link
Copy Markdown
Contributor

path_zebra_add_sr_policy() iterates over all segment entries in a segment list and writes each SID label into zp.segment_list.labels[], which is a fixed-size array of MPLS_MAX_LABELS (16) elements on the stack. There is no bounds check on label_num before the write.

path_zebra_add_sr_policy() iterates over all segment entries in a
segment list and writes each SID label into zp.segment_list.labels[],
which is a fixed-size array of MPLS_MAX_LABELS (16) elements on the
stack. There is no bounds check on label_num before the write.

A segment list with more than 16 entries — which is legal per RFC 9256
— will write past the array boundary, corrupting adjacent stack memory.
This includes the policy name buffer, local_label, and potentially the
return address, leading to undefined behavior or exploitable code
execution.

The vulnerability is remotely triggerable: segment lists can be
originated via PCEP (RFC 8231/8281) from an external PCE, or via
BGP SR-TE policy SAFI (SAFI 73), neither of which require
authentication beyond the peer/PCE session itself.

Add a bounds check against MPLS_MAX_LABELS before each write. When the
limit is exceeded, log a warning identifying the offending policy and
truncate the segment list to the first 16 labels, preventing the
overflow while still installing a functional (truncated) policy.

Signed-off-by: guozhongfeng.gzf <guozhongfeng.gzf@alibaba-inc.com>
@greptile-apps

greptile-apps Bot commented Jun 22, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes a stack buffer overflow in path_zebra_add_sr_policy() by adding a bounds check before each write into the fixed-size zp.segment_list.labels[] array (size MPLS_MAX_LABELS = 16). Without the check, a segment list longer than 16 entries would silently overwrite stack memory.

  • A >= MPLS_MAX_LABELS guard is inserted at the top of the RB_FOREACH loop; when the limit is hit, a zlog_warn is emitted and the loop breaks. The bounds check arithmetic is correct and the warning fires only once per call.
  • After truncation, zebra_send_sr_policy() is still invoked with the partial label stack, which may install incorrect SR-TE forwarding state rather than failing safely.

Confidence Score: 3/5

The crash-causing overflow is prevented, but the truncation path still sends a partial label stack to Zebra, which can install forwarding state that misroutes or black-holes SR-TE traffic.

The bounds check is arithmetically correct and stops the overflow, which is the main goal. The residual concern is that after truncation the code continues to call zebra_send_sr_policy with an incomplete segment list, potentially pushing broken forwarding state to the data plane for any policy whose configured segment list exceeds 16 entries.

pathd/path_zebra.c — specifically the post-truncation flow that still invokes zebra_send_sr_policy.

Important Files Changed

Filename Overview
pathd/path_zebra.c Adds a bounds check before writing into the fixed-size labels[] array to prevent stack buffer overflow; however, on overflow it truncates and still sends the incomplete policy to Zebra, which can install incorrect SR-TE forwarding state.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[path_zebra_add_sr_policy called] --> B[Initialize zapi_sr_policy zp]
    B --> C{RB_FOREACH segment}
    C -->|next segment| D{label_num >= MPLS_MAX_LABELS?}
    D -->|Yes| E[zlog_warn: truncating]
    E --> F[break]
    D -->|No| G[Write label to array and increment label_num]
    G --> C
    C -->|done| H[policy status = GOING_UP]
    F --> H
    H --> I[zebra_send_sr_policy SET]
    I --> J{Was list truncated?}
    J -->|No - full list sent| K[Zebra installs correct policy]
    J -->|Yes - partial list sent| L[Zebra installs incomplete policy - potential misrouting]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[path_zebra_add_sr_policy called] --> B[Initialize zapi_sr_policy zp]
    B --> C{RB_FOREACH segment}
    C -->|next segment| D{label_num >= MPLS_MAX_LABELS?}
    D -->|Yes| E[zlog_warn: truncating]
    E --> F[break]
    D -->|No| G[Write label to array and increment label_num]
    G --> C
    C -->|done| H[policy status = GOING_UP]
    F --> H
    H --> I[zebra_send_sr_policy SET]
    I --> J{Was list truncated?}
    J -->|No - full list sent| K[Zebra installs correct policy]
    J -->|Yes - partial list sent| L[Zebra installs incomplete policy - potential misrouting]
Loading
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
pathd/path_zebra.c:188-198
**Truncated policy sent to Zebra with incomplete segment list**

When the segment list exceeds `MPLS_MAX_LABELS`, this code truncates the label stack and still calls `zebra_send_sr_policy()` with only the first 16 labels. Sending an incomplete segment list to the forwarding plane installs an SR-TE policy with a shorter stack than what was signaled, which will misroute or black-hole traffic at the first transit node that expects the full label stack. The original policy intent is not achievable with a partial label stack, so it may be safer to abort the install entirely (log the warning, skip the `zebra_send_sr_policy` call, and return) rather than silently forwarding with a truncated path.

Reviews (1): Last reviewed commit: "pathd: prevent stack buffer overflow in ..." | Re-trigger Greptile

Comment thread pathd/path_zebra.c
Comment on lines +188 to 198
if (zp.segment_list.label_num >= MPLS_MAX_LABELS) {
zlog_warn("SR-TE policy %s: segment list exceeds MPLS_MAX_LABELS (%d), truncating",
policy->name, MPLS_MAX_LABELS);
break;
}
zp.segment_list.labels[zp.segment_list.label_num++] =
segment->sid_value;
}
policy->status = SRTE_POLICY_STATUS_GOING_UP;

(void)zebra_send_sr_policy(pathd_zclient, ZEBRA_SR_POLICY_SET, &zp);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Truncated policy sent to Zebra with incomplete segment list

When the segment list exceeds MPLS_MAX_LABELS, this code truncates the label stack and still calls zebra_send_sr_policy() with only the first 16 labels. Sending an incomplete segment list to the forwarding plane installs an SR-TE policy with a shorter stack than what was signaled, which will misroute or black-hole traffic at the first transit node that expects the full label stack. The original policy intent is not achievable with a partial label stack, so it may be safer to abort the install entirely (log the warning, skip the zebra_send_sr_policy call, and return) rather than silently forwarding with a truncated path.

Prompt To Fix With AI
This is a comment left during a code review.
Path: pathd/path_zebra.c
Line: 188-198

Comment:
**Truncated policy sent to Zebra with incomplete segment list**

When the segment list exceeds `MPLS_MAX_LABELS`, this code truncates the label stack and still calls `zebra_send_sr_policy()` with only the first 16 labels. Sending an incomplete segment list to the forwarding plane installs an SR-TE policy with a shorter stack than what was signaled, which will misroute or black-hole traffic at the first transit node that expects the full label stack. The original policy intent is not achievable with a partial label stack, so it may be safer to abort the install entirely (log the warning, skip the `zebra_send_sr_policy` call, and return) rather than silently forwarding with a truncated path.

How can I resolve this? If you propose a fix, please make it concise.

@riw777 riw777 Jun 23, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks valid?

@riw777 riw777 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the one ai comment looks valid ?

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants