diff options
| author | Denys Fedoryshchenko <denys.f@collabora.com> | 2026-08-08 17:20:32 +0300 |
|---|---|---|
| committer | Denys Fedoryshchenko <denys.f@collabora.com> | 2026-08-08 17:20:32 +0300 |
| commit | 59124bbc26bf0211723b3eb5b5186d3dc7b72b0c (patch) | |
| tree | b31edd0945c4783ae8569e33a43b648f5564c153 /docs | |
| parent | 11271e9019ef1511b127b75e1c69e9c57f9cba49 (diff) | |
| download | accel-ppp-59124bbc26bf0211723b3eb5b5186d3dc7b72b0c.tar.gz accel-ppp-59124bbc26bf0211723b3eb5b5186d3dc7b72b0c.zip | |
ipoe: fix ipoe_wlock double release in IPOE_CMD_DELETE
ipoe_nl_cmd_delete() drops ipoe_wlock before sleeping in
synchronize_rcu() and taking rtnl via unregister_netdev(), then falls
through into the out_unlock label and releases it a second time. Every
successful session delete therefore increments the semaphore count by
one.
Since the count only ever grows, ipoe_wlock stops providing mutual
exclusion after a handful of teardowns: with the count at N, up to N+1
writers may hold it simultaneously. This is currently masked because
ipoe_nl_family does not set parallel_ops, so genetlink serialises every
.doit/.dumpit under genl_mutex and no two writers can overlap in
practice. It turns into a real race on the session hash lists as soon as
that changes, or as soon as a writer is introduced outside the genl
handlers.
It also silently defeats the barrier in ipoe_fini(): the down()/up()
pair meant to wait for an in-flight writer is satisfied immediately by
the leaked count and waits for nothing.
Return directly after unregister_netdev() so the success path releases
the lock exactly once. The early up() is deliberate and stays where it
is - holding a sleeping semaphore across unregister_netdev() would nest
ipoe_wlock inside rtnl, while ipoe_create() takes rtnl first and
ipoe_wlock afterwards. Error paths, return values and lock ordering are
unchanged.
Diffstat (limited to 'docs')
0 files changed, 0 insertions, 0 deletions
