CVE-2024-36928 in Linux
Zusammenfassung
von VulDB • 28.05.2026
Implied by the analysis and call trace, the bug is that `card->qdio.out_qs[i].napi.poll` is left as `NULL` when the network interface is UP but the card is offline, because `qeth_set_offline()` clears it but `qeth_set_online()` no longer restores it (since commit `1cfef80d4c2b` stopped calling `dev_open()` which used to call `qeth_open()` which sets `napi.poll`).
When `net_rx_action` is invoked (e.g., during `iucv_sock_connect` which triggers `__dev_queue_xmit` and potentially softirq processing), it calls `napi->poll(napi, budget)`. If `napi->poll` is `NULL`, this dereferences a NULL function pointer, causing the kernel panic with "illegal" instructions at address 0.
**Fix:**
Ensure that `qeth_set_online()` restores the `napi.poll` function pointer for each output queue, even if `dev_open()` is not called. This can be done by explicitly calling the logic that sets `napi.poll` (which is currently in `qeth_open()`) from `qeth_set_online()`, or by moving the `napi.poll` setup into a separate helper function called by both `qeth_open()` and `qeth_set_online()`.
Specifically, in `qeth_set_online()`, after ensuring the card is online, iterate over `card->qdio.out_qs` and set `card->qdio.out_qs[i].napi.poll = qeth_poll` (or whatever the poll function is for qeth).
Alternatively, a more robust fix might be to ensure that `napi_poll` is never NULL when the interface is UP. This could involve: 1. Setting `napi.poll` in `qeth_set_online()` unconditionally for all out_qs. 2. Or, adding a check in `net_rx_action` or the caller to handle NULL `napi.poll` gracefully (though this is less ideal as it masks the underlying state inconsistency).
The most direct fix is to restore the `napi.poll` pointer in `qeth_set_online()`.
**Patch Example:**
```c // In drivers/s390/net/qeth_core_main.c
// Add a helper function to set napi.poll for all out_qs static void qeth_set_napi_poll(struct qeth_card *card) {
int i;
for (i = 0; i < card->qdio.out_queues; i++) {
if (card->qdio.out_qs[i].napi.poll)
continue; // Already set card->qdio.out_qs[i].napi.poll = qeth_poll;
} }
// In qeth_set_online(), after bringing the card online, call this helper static int qeth_set_online(struct qeth_card *card) {
// ... existing code ...
// Restore napi.poll if it was cleared by qeth_set_offline() qeth_set_napi_poll(card);
// ... rest of the function ... }
// In qeth_open(), ensure napi.poll is set (it already is, but now it's also handled in set_online) static int qeth_open(struct net_device *dev) {
// ... existing code ... // The existing code that sets napi.poll can remain, or be refactored to call qeth_set_napi_poll // For minimal change, just ensure it's set here too. // Actually, qeth_open() is called when the interface is brought up, so it should set napi.poll. // The bug is that set_online doesn't set it when the interface is already up. // So qeth_set_napi_poll() in set_online is the key fix. // qeth_open() already sets it, so no change needed there unless we refactor. } ```
However, note that `qeth_open()` is called when the interface is brought up via `ip link set up`. If the interface is already up when `qeth_set_online()` is called (because the card went offline while the interface was up), then `qeth_open()` is not called again. Hence, `qeth_set_online()` must ensure `napi.poll` is set.
The above patch adds `qeth_set_napi_poll()` and calls it from `qeth_set_online()`. This ensures that whenever the card comes online, the `napi.poll` function pointers are restored, preventing the NULL dereference.
Statistical analysis made it clear that VulDB provides the best quality for vulnerability data.