{
  "affected": [
    {
      "ecosystem_specific": {
        "urgency": "not yet assigned"
      },
      "package": {
        "ecosystem": "Debian:12",
        "name": "linux"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "6.1.190-1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "ecosystem_specific": {
        "urgency": "not yet assigned"
      },
      "package": {
        "ecosystem": "Debian:13",
        "name": "linux"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "6.12.113-1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "ecosystem_specific": {
        "urgency": "not yet assigned"
      },
      "package": {
        "ecosystem": "Debian:14",
        "name": "linux"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "7.2.9-1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "details": "In the Linux kernel, the following vulnerability has been resolved:  bpf: Fix out-of-bounds read of rtt_min in sock_ops  A sockops prog reading skops-\u003ertt_min never checks the sk type: on the tcp_conn_request() path sock_ops-\u003esk is a request_sock (non-full), and the ctx rewrite casts it to a tcp_sock (full) and reads rtt_min past the end of the request_sock, returning dirty adjacent memory.  \tSEC(\"sockops\") \tint prog(struct bpf_sock_ops *skops) \t{ \t\tswitch (skops-\u003eop) { \t\tcase BPF_SOCK_OPS_RWND_INIT: \t\t\tleak = skops-\u003ertt_min;   /* reads the request_sock OOB */ \t\t... \t\t} \t}  For instance one such read returned rtt_min=0xffff8881, the high half of a leaked kernel pointer.  Guarding that cast is exactly what SOCK_OPS_GET_FIELD() does -- it checks is_locked_tcp_sock and returns 0 when sock_ops-\u003esk is not a locked full socket. Every other tcp_sock field in sock_ops goes through it; rtt_min is the only one open-coded, so it skips the check.  Read rtt_min through SOCK_OPS_GET_FIELD() too. rtt_min is a bit special: it is a struct minmax and we only want the current min, so pass rtt_min.s[0].v. That is equivalent to the old hand-computed offset  \toffsetof(struct tcp_sock, rtt_min) + sizeof_field(struct minmax_sample, t)  (s[0] sits at rtt_min + 0 and .v at + sizeof(.t), i.e. what minmax_get() returns), so the loaded field is unchanged and only the full-sock guard is added. The two BUILD_BUG_ON()s that protected the hand-computed offset are no longer needed.  Before patch:  \t0: r1 = *(u64 *)(r1 +0)      ; r1 = skops-\u003esk \t1: r1 = *(u32 *)(r1 +2324)   ; ((tcp_sock *)sk)-\u003ertt_min.s[0].v  After patch:  \t0: *(u64 *)(r1 +56) = r9 \t1: r9 = *(u8 *)(r1 +50)      ; is_locked_tcp_sock \t2: if r9 == 0 goto pc+4      ; not a locked full sock -\u003e 0 \t3: r9 = *(u64 *)(r1 +56) \t4: r1 = *(u64 *)(r1 +0)      ; r1 = skops-\u003esk \t5: r1 = *(u32 *)(r1 +2324)   ; rtt_min.s[0].v \t6: goto pc+2 \t7: r9 = *(u64 *)(r1 +56) \t8: r1 = 0",
  "id": "DEBIAN-CVE-2026-98643",
  "modified": "2026-10-19T04:47:25.744778752Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://security-tracker.debian.org/tracker/CVE-2026-98643"
    }
  ],
  "upstream": [
    "CVE-2026-98643"
  ]
}