GHSA-M8CC-C87R-9QR2

Vulnerability from github – Published: 2025-10-01 09:30 – Updated: 2025-12-12 18:30
VLAI
Details

In the Linux kernel, the following vulnerability has been resolved:

net: phy: transfer phy_config_inband() locking responsibility to phylink

Problem description

Lockdep reports a possible circular locking dependency (AB/BA) between &pl->state_mutex and &phy->lock, as follows.

phylink_resolve() // acquires &pl->state_mutex -> phylink_major_config() -> phy_config_inband() // acquires &pl->phydev->lock

whereas all the other call sites where &pl->state_mutex and &pl->phydev->lock have the locking scheme reversed. Everywhere else, &pl->phydev->lock is acquired at the top level, and &pl->state_mutex at the lower level. A clear example is phylink_bringup_phy().

The outlier is the newly introduced phy_config_inband() and the existing lock order is the correct one. To understand why it cannot be the other way around, it is sufficient to consider phylink_phy_change(), phylink's callback from the PHY device's phy->phy_link_change() virtual method, invoked by the PHY state machine.

phy_link_up() and phy_link_down(), the (indirect) callers of phylink_phy_change(), are called with &phydev->lock acquired. Then phylink_phy_change() acquires its own &pl->state_mutex, to serialize changes made to its pl->phy_state and pl->link_config. So all other instances of &pl->state_mutex and &phydev->lock must be consistent with this order.

Problem impact

I think the kernel runs a serious deadlock risk if an existing phylink_resolve() thread, which results in a phy_config_inband() call, is concurrent with a phy_link_up() or phy_link_down() call, which will deadlock on &pl->state_mutex in phylink_phy_change(). Practically speaking, the impact may be limited by the slow speed of the medium auto-negotiation protocol, which makes it unlikely for the current state to still be unresolved when a new one is detected, but I think the problem is there. Nonetheless, the problem was discovered using lockdep.

Proposed solution

Practically speaking, the phy_config_inband() requirement of having phydev->lock acquired must transfer to the caller (phylink is the only caller). There, it must bubble up until immediately before &pl->state_mutex is acquired, for the cases where that takes place.

Solution details, considerations, notes

This is the phy_config_inband() call graph:

                      sfp_upstream_ops :: connect_phy()
                      |
                      v
                      phylink_sfp_connect_phy()
                      |
                      v
                      phylink_sfp_config_phy()
                      |
                      |   sfp_upstream_ops :: module_insert()
                      |   |
                      |   v
                      |   phylink_sfp_module_insert()
                      |   |
                      |   |   sfp_upstream_ops :: module_start()
                      |   |   |
                      |   |   v
                      |   |   phylink_sfp_module_start()
                      |   |   |
                      |   v   v
                      |   phylink_sfp_config_optical()

phylink_start() | | | phylink_resume() v v | | phylink_sfp_set_config() | | | v v v phylink_mac_initial_config() | phylink_resolve() | | phylink_ethtool_ksettings_set() v v v phylink_major_config() | v phy_config_inband()

phylink_major_config() caller #1, phylink_mac_initial_config(), does not acquire &pl->state_mutex nor do its callers. It must acquire &pl->phydev->lock prior to calling phylink_major_config().

phylink_major_config() caller #2, phylink_resolve() acquires &pl->state_mutex, thus also needs to acquire &pl->phydev->lock.

phylink_major_config() caller #3, phylink_ethtool_ksettings_set(), is completely uninteresting, because it only call ---truncated---

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-39915"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-667"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-10-01T08:15:34Z",
    "severity": "MODERATE"
  },
  "details": "In the Linux kernel, the following vulnerability has been resolved:\n\nnet: phy: transfer phy_config_inband() locking responsibility to phylink\n\nProblem description\n===================\n\nLockdep reports a possible circular locking dependency (AB/BA) between\n\u0026pl-\u003estate_mutex and \u0026phy-\u003elock, as follows.\n\nphylink_resolve() // acquires \u0026pl-\u003estate_mutex\n-\u003e phylink_major_config()\n   -\u003e phy_config_inband() // acquires \u0026pl-\u003ephydev-\u003elock\n\nwhereas all the other call sites where \u0026pl-\u003estate_mutex and\n\u0026pl-\u003ephydev-\u003elock have the locking scheme reversed. Everywhere else,\n\u0026pl-\u003ephydev-\u003elock is acquired at the top level, and \u0026pl-\u003estate_mutex at\nthe lower level. A clear example is phylink_bringup_phy().\n\nThe outlier is the newly introduced phy_config_inband() and the existing\nlock order is the correct one. To understand why it cannot be the other\nway around, it is sufficient to consider phylink_phy_change(), phylink\u0027s\ncallback from the PHY device\u0027s phy-\u003ephy_link_change() virtual method,\ninvoked by the PHY state machine.\n\nphy_link_up() and phy_link_down(), the (indirect) callers of\nphylink_phy_change(), are called with \u0026phydev-\u003elock acquired.\nThen phylink_phy_change() acquires its own \u0026pl-\u003estate_mutex, to\nserialize changes made to its pl-\u003ephy_state and pl-\u003elink_config.\nSo all other instances of \u0026pl-\u003estate_mutex and \u0026phydev-\u003elock must be\nconsistent with this order.\n\nProblem impact\n==============\n\nI think the kernel runs a serious deadlock risk if an existing\nphylink_resolve() thread, which results in a phy_config_inband() call,\nis concurrent with a phy_link_up() or phy_link_down() call, which will\ndeadlock on \u0026pl-\u003estate_mutex in phylink_phy_change(). Practically\nspeaking, the impact may be limited by the slow speed of the medium\nauto-negotiation protocol, which makes it unlikely for the current state\nto still be unresolved when a new one is detected, but I think the\nproblem is there. Nonetheless, the problem was discovered using lockdep.\n\nProposed solution\n=================\n\nPractically speaking, the phy_config_inband() requirement of having\nphydev-\u003elock acquired must transfer to the caller (phylink is the only\ncaller). There, it must bubble up until immediately before\n\u0026pl-\u003estate_mutex is acquired, for the cases where that takes place.\n\nSolution details, considerations, notes\n=======================================\n\nThis is the phy_config_inband() call graph:\n\n                          sfp_upstream_ops :: connect_phy()\n                          |\n                          v\n                          phylink_sfp_connect_phy()\n                          |\n                          v\n                          phylink_sfp_config_phy()\n                          |\n                          |   sfp_upstream_ops :: module_insert()\n                          |   |\n                          |   v\n                          |   phylink_sfp_module_insert()\n                          |   |\n                          |   |   sfp_upstream_ops :: module_start()\n                          |   |   |\n                          |   |   v\n                          |   |   phylink_sfp_module_start()\n                          |   |   |\n                          |   v   v\n                          |   phylink_sfp_config_optical()\n phylink_start()          |   |\n   |   phylink_resume()   v   v\n   |   |  phylink_sfp_set_config()\n   |   |  |\n   v   v  v\n phylink_mac_initial_config()\n   |   phylink_resolve()\n   |   |  phylink_ethtool_ksettings_set()\n   v   v  v\n   phylink_major_config()\n            |\n            v\n    phy_config_inband()\n\nphylink_major_config() caller #1, phylink_mac_initial_config(), does not\nacquire \u0026pl-\u003estate_mutex nor do its callers. It must acquire\n\u0026pl-\u003ephydev-\u003elock prior to calling phylink_major_config().\n\nphylink_major_config() caller #2, phylink_resolve() acquires\n\u0026pl-\u003estate_mutex, thus also needs to acquire \u0026pl-\u003ephydev-\u003elock.\n\nphylink_major_config() caller #3, phylink_ethtool_ksettings_set(), is\ncompletely uninteresting, because it only call\n---truncated---",
  "id": "GHSA-m8cc-c87r-9qr2",
  "modified": "2025-12-12T18:30:28Z",
  "published": "2025-10-01T09:30:25Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-39915"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/052ac41c379c8b87629808be612a482b2d0ae283"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/e2a10daba84968f6b5777d150985fd7d6abc9c84"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…