{
   "containers": {
      "cna": {
         "providerMetadata": {
            "orgId": "f4215fc3-5b6b-47ff-a258-f7189bd81038"
         },
         "descriptions": [
            {
               "lang": "en",
               "value": "In the Linux kernel, the following vulnerability has been resolved:\n\npowerpc/qspinlock: Fix deadlock in MCS queue\n\nIf an interrupt occurs in queued_spin_lock_slowpath() after we increment\nqnodesp->count and before node->lock is initialized, another CPU might\nsee stale lock values in get_tail_qnode(). If the stale lock value happens\nto match the lock on that CPU, then we write to the \"next\" pointer of\nthe wrong qnode. This causes a deadlock as the former CPU, once it becomes\nthe head of the MCS queue, will spin indefinitely until it's \"next\" pointer\nis set by its successor in the queue.\n\nRunning stress-ng on a 16 core (16EC/16VP) shared LPAR, results in\noccasional lockups similar to the following:\n\n   $ stress-ng --all 128 --vm-bytes 80% --aggressive \\\n               --maximize --oomable --verify  --syslog \\\n               --metrics  --times  --timeout 5m\n\n   watchdog: CPU 15 Hard LOCKUP\n   ......\n   NIP [c0000000000b78f4] queued_spin_lock_slowpath+0x1184/0x1490\n   LR [c000000001037c5c] _raw_spin_lock+0x6c/0x90\n   Call Trace:\n    0xc000002cfffa3bf0 (unreliable)\n    _raw_spin_lock+0x6c/0x90\n    raw_spin_rq_lock_nested.part.135+0x4c/0xd0\n    sched_ttwu_pending+0x60/0x1f0\n    __flush_smp_call_function_queue+0x1dc/0x670\n    smp_ipi_demux_relaxed+0xa4/0x100\n    xive_muxed_ipi_action+0x20/0x40\n    __handle_irq_event_percpu+0x80/0x240\n    handle_irq_event_percpu+0x2c/0x80\n    handle_percpu_irq+0x84/0xd0\n    generic_handle_irq+0x54/0x80\n    __do_irq+0xac/0x210\n    __do_IRQ+0x74/0xd0\n    0x0\n    do_IRQ+0x8c/0x170\n    hardware_interrupt_common_virt+0x29c/0x2a0\n   --- interrupt: 500 at queued_spin_lock_slowpath+0x4b8/0x1490\n   ......\n   NIP [c0000000000b6c28] queued_spin_lock_slowpath+0x4b8/0x1490\n   LR [c000000001037c5c] _raw_spin_lock+0x6c/0x90\n   --- interrupt: 500\n    0xc0000029c1a41d00 (unreliable)\n    _raw_spin_lock+0x6c/0x90\n    futex_wake+0x100/0x260\n    do_futex+0x21c/0x2a0\n    sys_futex+0x98/0x270\n    system_call_exception+0x14c/0x2f0\n    system_call_vectored_common+0x15c/0x2ec\n\nThe following code flow illustrates how the deadlock occurs.\nFor the sake of brevity, assume that both locks (A and B) are\ncontended and we call the queued_spin_lock_slowpath() function.\n\n        CPU0                                   CPU1\n        ----                                   ----\n  spin_lock_irqsave(A)                          |\n  spin_unlock_irqrestore(A)                     |\n    spin_lock(B)                                |\n         |                                      |\n         ▼                                      |\n   id = qnodesp->count++;                       |\n  (Note that nodes[0].lock == A)                |\n         |                                      |\n         ▼                                      |\n      Interrupt                                 |\n  (happens before \"nodes[0].lock = B\")          |\n         |                                      |\n         ▼                                      |\n  spin_lock_irqsave(A)                          |\n         |                                      |\n         ▼                                      |\n   id = qnodesp->count++                        |\n   nodes[1].lock = A                            |\n         |                                      |\n         ▼                                      |\n  Tail of MCS queue                             |\n         |                             spin_lock_irqsave(A)\n         ▼                                      |\n  Head of MCS queue                             ▼\n         |                             CPU0 is previous tail\n         ▼                                      |\n   Spin indefinitely                            ▼\n  (until \"nodes[1].next != NULL\")      prev = get_tail_qnode(A, CPU0)\n                                                |\n                                                ▼\n                                       prev == &qnodes[CPU0].nodes[0]\n                                     (as qnodes\n---truncated---"
            }
         ],
         "affected": [
            {
               "product": "Linux",
               "vendor": "Linux",
               "defaultStatus": "unaffected",
               "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
               "programFiles": [
                  "arch/powerpc/lib/qspinlock.c"
               ],
               "versions": [
                  {
                     "version": "84990b169557",
                     "lessThan": "d84ab6661e8d",
                     "status": "affected",
                     "versionType": "git"
                  },
                  {
                     "version": "84990b169557",
                     "lessThan": "f06af737e4be",
                     "status": "affected",
                     "versionType": "git"
                  },
                  {
                     "version": "84990b169557",
                     "lessThan": "734ad0af3609",
                     "status": "affected",
                     "versionType": "git"
                  }
               ]
            },
            {
               "product": "Linux",
               "vendor": "Linux",
               "defaultStatus": "affected",
               "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
               "programFiles": [
                  "arch/powerpc/lib/qspinlock.c"
               ],
               "versions": [
                  {
                     "version": "6.2",
                     "status": "affected"
                  },
                  {
                     "version": "0",
                     "lessThan": "6.2",
                     "status": "unaffected",
                     "versionType": "custom"
                  },
                  {
                     "version": "6.6.51",
                     "lessThanOrEqual": "6.6.*",
                     "status": "unaffected",
                     "versionType": "custom"
                  },
                  {
                     "version": "6.10.10",
                     "lessThanOrEqual": "6.10.*",
                     "status": "unaffected",
                     "versionType": "custom"
                  },
                  {
                     "version": "6.11",
                     "lessThanOrEqual": "*",
                     "status": "unaffected",
                     "versionType": "original_commit_for_fix"
                  }
               ]
            }
         ],
         "references": [
            {
               "url": "https://git.kernel.org/stable/c/d84ab6661e8d09092de9b034b016515ef9b66085"
            },
            {
               "url": "https://git.kernel.org/stable/c/f06af737e4be28c0e926dc25d5f0a111da4e2987"
            },
            {
               "url": "https://git.kernel.org/stable/c/734ad0af3609464f8f93e00b6c0de1e112f44559"
            }
         ],
         "title": "powerpc/qspinlock: Fix deadlock in MCS queue",
         "x_generator": {
            "engine": "bippy-c9c4e1df01b2"
         }
      }
   },
   "cveMetadata": {
      "assignerOrgId": "f4215fc3-5b6b-47ff-a258-f7189bd81038",
      "cveID": "CVE-2024-46797",
      "requesterUserId": "gregkh@kernel.org",
      "serial": "1",
      "state": "PUBLISHED"
   },
   "dataType": "CVE_RECORD",
   "dataVersion": "5.0"
}
