Skip to content

[dhcp_devman] Ignore duplicate -i* arguments instead of crashing/leaking#76

Open
Xichen96 wants to merge 1 commit into
sonic-net:masterfrom
Xichen96:dev/xichenlin/reject-duplicate-intf
Open

[dhcp_devman] Ignore duplicate -i* arguments instead of crashing/leaking#76
Xichen96 wants to merge 1 commit into
sonic-net:masterfrom
Xichen96:dev/xichenlin/reject-duplicate-intf

Conversation

@Xichen96
Copy link
Copy Markdown
Contributor

Defense in depth for the duplicate--i* case discussed in sonic-net/sonic-buildimage#27277.

dhcp_devman_add_intf() is called once per -id/-iu/-im flag from main.cpp. There is no check that the same interface name has not already been registered. If the supervisor template (dhcp-relay.monitors.j2) emits the same upstream interface twice — which happens today when an interface has two IP prefixes (e.g. a Vlan with secondary subnets, or a dual-stack PortChannel after the v4-or-v6 expansion) — the second call:

  1. Increments the per-type counter again. For -id/-im that immediately trips assert(dhcp_num_south_intf <= 1) / assert(dhcp_num_mgmt_intf <= 1) and aborts. For -iu it just leaves the counter wrong.
  2. Overwrites intfs[name] with a fresh dhcp_device_context_t *, leaking the earlier context (and its sockets) because nothing calls dhcp_device_shutdown() on it.

The supervisor template is being fixed (sonic-net/sonic-buildimage#27277), but dhcpmon should also be defensive: any future template regression or operator-supplied invocation that happens to repeat an -i* flag should fail closed.

This PR adds an early-return guard at the top of dhcp_devman_add_intf() that uses intfs.find(name) to detect an already-registered name. On a hit it logs INFO and returns 0 (so main.cpp:142 does not exit). The check runs before any state mutation — counter, asserts, downstream_ifname/mgmt_ifname assignment, dhcp_device_init, and the intfs[] write.

How to test

  • With current dhcpmon: run /usr/sbin/dhcpmon -id Vlan1000 -id Vlan1000 → asserts and aborts (or registers garbage in non-debug builds).
  • With this PR: same command → first -id Vlan1000 registers normally; second logs Ignoring duplicate -id for interface Vlan1000 (already registered) and returns 0; daemon proceeds.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

`dhcp_devman_add_intf()` is called once per `-id`/`-iu`/`-im` flag from
`main.cpp`, with no check that the same interface name has not already
been registered. If the supervisor template (for example
`dhcp-relay.monitors.j2` in sonic-buildimage) emits the same upstream
interface twice -- which can happen when an interface has two IP
prefixes and the template iterates over `pfx_filter` -- the second
call has two undesirable effects:

1. The per-type counter (`dhcp_num_north_intf`, `dhcp_num_south_intf`
   or `dhcp_num_mgmt_intf`) is incremented again. For `-id` and `-im`
   that immediately trips `assert(dhcp_num_south_intf <= 1)` /
   `assert(dhcp_num_mgmt_intf <= 1)` and aborts the daemon (in debug
   builds; in release builds the counter is just wrong).
2. `intfs[name] = context;` overwrites the previously-stored
   `dhcp_device_context_t *` for the same interface key. The earlier
   context, including its socket and helper state, is leaked because
   nothing calls `dhcp_device_shutdown()` on it.

The supervisor template is being fixed in sonic-buildimage to dedup
the rendered argument list, but dhcpmon should also be defensive at
its own boundary so any future template regression -- or any other
operator-supplied invocation that happens to repeat an `-i*` flag --
fails closed without crashing or leaking.

Add an early-return guard at the top of `dhcp_devman_add_intf()`
that uses `intfs.find(name)` to detect a name that is already
registered. On a hit, log at INFO and return 0 so the caller's error
path in `main.cpp` does not exit; treat the duplicate as a benign
no-op. The check runs before any state mutation (counter, asserts,
`downstream_ifname`/`mgmt_ifname` assignment, `dhcp_device_init`,
and the `intfs[]` write).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Xichen96 <lukelin0907@gmail.com>
@mssonicbld
Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants