{
  "schema_version": "1.6.1",
  "id": "RPI-CVE-2026-63803",
  "modified": "2026-10-09T11:39:44Z",
  "upstream": [
    "CVE-2026-63803"
  ],
  "published": "2026-07-19T12:02:32Z",
  "summary": "hdlc_ppp: sync per-proto timers before freeing hdlc state",
  "details": "In the Linux kernel, the following vulnerability has been resolved:\n\nhdlc_ppp: sync per-proto timers before freeing hdlc state\n\nEach PPP control protocol (LCP/IPCP/IPV6CP) embedded in struct ppp\nregisters a timer via timer_setup(). That struct ppp is the\nhdlc->state allocation, which detach_hdlc_protocol() frees with kfree()\nin both teardown paths: unregister_hdlc_device() and the re-attach inside\nattach_hdlc_protocol().\n\nThe ppp proto never registered a .detach callback, so\ndetach_hdlc_protocol() performs no timer synchronization before the\nkfree(). The only cancel, timer_delete(&proto->timer) in ppp_cp_event(),\nis partial (it does not wait for a running callback) and only runs on the\n->CLOSED transition; ppp_stop()/ppp_close() do not sync either. A\nppp_timer callback already executing (blocked on ppp->lock) survives the\nkfree and then dereferences proto->state / ppp->lock in freed memory,\nleading to a use-after-free.\n\nFix this by adding a .detach helper that calls timer_shutdown_sync() on\nevery per-proto timer. detach_hdlc_protocol() invokes proto->detach(dev)\nbefore kfree(hdlc->state), so timer_shutdown_sync()\nnow runs on both free paths.\ntimer_shutdown_sync() is used instead of timer_delete_sync() because the\nkeepalive path re-arms the timer through add_timer()/mod_timer() and\nshutdown blocks any re-activation during teardown.\n\nInitialize the per-protocol timers in ppp_ioctl() when the protocol is\nattached, and remove the now-redundant timer_setup() from ppp_start(), so\nthat the timers are initialized exactly once at attach time and\nppp_timer_release() never operates on uninitialized timer_list\nstructures. attach_hdlc_protocol() uses kmalloc() (not kzalloc), so\nstruct ppp's protos[i].timer is uninitialized garbage until the first\ntimer_setup(); without this init-at-attach, attaching the PPP protocol\nwithout ever bringing the device up would leave timer_shutdown_sync()\noperating on uninitialized memory in .detach. Moving the init out of\nppp_start() (which only runs on NETDEV_UP) into the attach path makes the\ninitialization unconditional and avoids initializing the same timer_list\ntwice.\n\nThis bug was found by static analysis.",
  "severity": [
    {
      "type": "CVSS_V3",
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"
    }
  ],
  "affected": [
    {
      "package": {
        "ecosystem": "Raspberry Pi OS:12",
        "name": "linux"
      },
      "versions": [
        "1:6.1.47-1+rpt4"
      ],
      "ecosystem_specific": {
        "binaries": [
          {
            "binary_name": "linux-image-6.1.0-rpi3-rpi-2712",
            "binary_version": "1:6.1.47-1+rpt4"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi3-rpi-v6",
            "binary_version": "1:6.1.47-1+rpt4"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi3-rpi-v7",
            "binary_version": "1:6.1.47-1+rpt4"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi3-rpi-v7l",
            "binary_version": "1:6.1.47-1+rpt4"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi3-rpi-v8",
            "binary_version": "1:6.1.47-1+rpt4"
          }
        ]
      },
      "database_specific": {
        "per_version": {
          "1:6.1.47-1+rpt4": {
            "linux_commit": "655fc658a15ae7a6f37103754adb39ba52a9a14e",
            "upstream_version": "6.1.47",
            "assessment": "commit ancestry (strak rule)",
            "upstream_fixed": "6.1.177",
            "compiled_filter": false
          }
        }
      }
    }
  ],
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://www.cve.org/CVERecord?id=CVE-2026-63803"
    },
    {
      "type": "FIX",
      "url": "https://git.kernel.org/stable/c/86d80a231bde4cfb64bfbfbfffd83056fc93628f"
    },
    {
      "type": "FIX",
      "url": "https://git.kernel.org/stable/c/8308122bc9c065b1f376e081ed300129a2ac9545"
    },
    {
      "type": "FIX",
      "url": "https://git.kernel.org/stable/c/ce8f9ddca0c9f217342a8b49efd309aa35b81a36"
    },
    {
      "type": "FIX",
      "url": "https://git.kernel.org/stable/c/508a0139d3bf60f6a03d2fbfb63a89a9463d983a"
    },
    {
      "type": "FIX",
      "url": "https://git.kernel.org/stable/c/c64dbef1c0fbd36f9530aa75112acdf6a6d3cfd8"
    },
    {
      "type": "FIX",
      "url": "https://git.kernel.org/stable/c/5a84398101bf9f11e84b176343e4e3ba83e668c0"
    },
    {
      "type": "FIX",
      "url": "https://git.kernel.org/stable/c/a594debfd4e7ec39413647458907f689ef57fd2f"
    },
    {
      "type": "FIX",
      "url": "https://git.kernel.org/stable/c/c78a4e41ab5ead6193ad8a2dd92e8906bae659fa"
    }
  ],
  "database_specific": {
    "source": "https://git.kernel.org/pub/scm/linux/security/vulns.git",
    "upstream_modified": "2026-08-17T05:24:08Z",
    "severity": {
      "source": "kernel CNA",
      "cvss_v3_score": 7.8,
      "cvss_v3_severity": "High",
      "scenario": "AV:L - The UAF occurs in detach_hdlc_protocol() during protocol teardown via SIOCWANDEV ioctl or driver unregister, not during packet receive. Remote PPP peers can influence timers but cannot reach the kfree() path without local CAP_NET_ADMIN configuration actions.\nAC:L - An attacker with CAP_NET_ADMIN can reliably trigger the bug by bringing a PPP HDLC interface up (arming timers via ppp_start/LCP), then tearing down or re-attaching the protocol while timers are pending or a ppp_timer callback is blocked on ppp->lock, controlling both sides of the race.\nPR:L - Exploitation requires CAP_NET_ADMIN to attach/detach the PPP protocol via SIOCWANDEV (ppp_ioctl checks capable(CAP_NET_ADMIN)), which is reachable by unprivileged users who create user namespaces with CAP_NET_ADMIN per kernel CVSS guidance.\nUI:N - No victim interaction is required once the attacker has network administration capability on a system with an HDLC WAN device; exploitation is fully attacker-driven through ioctl and interface up/down operations.\nS:U - The use-after-free corrupts kernel heap memory within the same kernel security boundary, enabling local privilege escalation rather than crossing a VM, container, or IOMMU security boundary.\nC:H - Use-after-free of struct ppp and its embedded spinlock_t allows dereferencing attacker-influenced freed heap memory, which can be leveraged for arbitrary kernel memory read via heap grooming and controlled reuse of the freed slab object.\nI:H - The UAF on struct ppp and ppp->lock provides a standard kernel heap corruption primitive that can be developed into arbitrary write and local privilege escalation through control of reallocated object contents and spinlock corruption.\nA:H - The freed-memory dereference in ppp_timer() causes kernel oops or panic during protocol teardown, and repeated triggering during interface reconfiguration can cause sustained denial of service on WAN router systems."
    }
  }
}
