CVE-2024-41010 (GCVE-0-2024-41010)
Vulnerability from cvelistv5
Published
2024-07-17 06:10
Modified
2026-08-05 11:34
Summary
In the Linux kernel, the following vulnerability has been resolved: bpf: Fix too early release of tcx_entry Pedro Pinto and later independently also Hyunwoo Kim and Wongi Lee reported an issue that the tcx_entry can be released too early leading to a use after free (UAF) when an active old-style ingress or clsact qdisc with a shared tc block is later replaced by another ingress or clsact instance. Essentially, the sequence to trigger the UAF (one example) can be as follows: 1. A network namespace is created 2. An ingress qdisc is created. This allocates a tcx_entry, and &tcx_entry->miniq is stored in the qdisc's miniqp->p_miniq. At the same time, a tcf block with index 1 is created. 3. chain0 is attached to the tcf block. chain0 must be connected to the block linked to the ingress qdisc to later reach the function tcf_chain0_head_change_cb_del() which triggers the UAF. 4. Create and graft a clsact qdisc. This causes the ingress qdisc created in step 1 to be removed, thus freeing the previously linked tcx_entry: rtnetlink_rcv_msg() => tc_modify_qdisc() => qdisc_create() => clsact_init() [a] => qdisc_graft() => qdisc_destroy() => __qdisc_destroy() => ingress_destroy() [b] => tcx_entry_free() => kfree_rcu() // tcx_entry freed 5. Finally, the network namespace is closed. This registers the cleanup_net worker, and during the process of releasing the remaining clsact qdisc, it accesses the tcx_entry that was already freed in step 4, causing the UAF to occur: cleanup_net() => ops_exit_list() => default_device_exit_batch() => unregister_netdevice_many() => unregister_netdevice_many_notify() => dev_shutdown() => qdisc_put() => clsact_destroy() [c] => tcf_block_put_ext() => tcf_chain0_head_change_cb_del() => tcf_chain_head_change_item() => clsact_chain_head_change() => mini_qdisc_pair_swap() // UAF There are also other variants, the gist is to add an ingress (or clsact) qdisc with a specific shared block, then to replace that qdisc, waiting for the tcx_entry kfree_rcu() to be executed and subsequently accessing the current active qdisc's miniq one way or another. The correct fix is to turn the miniq_active boolean into a counter. What can be observed, at step 2 above, the counter transitions from 0->1, at step [a] from 1->2 (in order for the miniq object to remain active during the replacement), then in [b] from 2->1 and finally [c] 1->0 with the eventual release. The reference counter in general ranges from [0,2] and it does not need to be atomic since all access to the counter is protected by the rtnl mutex. With this in place, there is no longer a UAF happening and the tcx_entry is freed at the correct time.
Impacted products
Vendor Product Version
Linux Linux Version: e420bed025071a623d2720a92bc2245c84757ecb
Version: e420bed025071a623d2720a92bc2245c84757ecb
Version: e420bed025071a623d2720a92bc2245c84757ecb
Create a notification for this product.
Show details on NVD website


{
  "containers": {
    "adp": [
      {
        "providerMetadata": {
          "dateUpdated": "2024-08-02T04:39:55.990Z",
          "orgId": "af854a3a-2127-422b-91ae-364da2661108",
          "shortName": "CVE"
        },
        "references": [
          {
            "tags": [
              "x_transferred"
            ],
            "url": "https://git.kernel.org/stable/c/230bb13650b0f186f540500fd5f5f7096a822a2a"
          },
          {
            "tags": [
              "x_transferred"
            ],
            "url": "https://git.kernel.org/stable/c/f61ecf1bd5b562ebfd7d430ccb31619857e80857"
          },
          {
            "tags": [
              "x_transferred"
            ],
            "url": "https://git.kernel.org/stable/c/1cb6f0bae50441f4b4b32a28315853b279c7404e"
          }
        ],
        "title": "CVE Program Container"
      },
      {
        "metrics": [
          {
            "other": {
              "content": {
                "id": "CVE-2024-41010",
                "options": [
                  {
                    "Exploitation": "none"
                  },
                  {
                    "Automatable": "no"
                  },
                  {
                    "Technical Impact": "partial"
                  }
                ],
                "role": "CISA Coordinator",
                "timestamp": "2024-09-10T16:25:09.492833Z",
                "version": "2.0.3"
              },
              "type": "ssvc"
            }
          }
        ],
        "providerMetadata": {
          "dateUpdated": "2024-09-11T17:34:06.652Z",
          "orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
          "shortName": "CISA-ADP"
        },
        "title": "CISA ADP Vulnrichment"
      }
    ],
    "cna": {
      "affected": [
        {
          "defaultStatus": "unaffected",
          "product": "Linux",
          "programFiles": [
            "include/net/tcx.h",
            "net/sched/sch_ingress.c"
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "vendor": "Linux",
          "versions": [
            {
              "lessThan": "230bb13650b0f186f540500fd5f5f7096a822a2a",
              "status": "affected",
              "version": "e420bed025071a623d2720a92bc2245c84757ecb",
              "versionType": "git"
            },
            {
              "lessThan": "f61ecf1bd5b562ebfd7d430ccb31619857e80857",
              "status": "affected",
              "version": "e420bed025071a623d2720a92bc2245c84757ecb",
              "versionType": "git"
            },
            {
              "lessThan": "1cb6f0bae50441f4b4b32a28315853b279c7404e",
              "status": "affected",
              "version": "e420bed025071a623d2720a92bc2245c84757ecb",
              "versionType": "git"
            }
          ]
        },
        {
          "defaultStatus": "affected",
          "product": "Linux",
          "programFiles": [
            "include/net/tcx.h",
            "net/sched/sch_ingress.c"
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "vendor": "Linux",
          "versions": [
            {
              "status": "affected",
              "version": "6.6"
            },
            {
              "lessThan": "6.6",
              "status": "unaffected",
              "version": "0",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "6.6.*",
              "status": "unaffected",
              "version": "6.6.41",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "6.9.*",
              "status": "unaffected",
              "version": "6.9.10",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "*",
              "status": "unaffected",
              "version": "6.10",
              "versionType": "original_commit_for_fix"
            }
          ]
        }
      ],
      "cpeApplicability": [
        {
          "nodes": [
            {
              "cpeMatch": [
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "6.6.41",
                  "versionStartIncluding": "6.6",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "6.9.10",
                  "versionStartIncluding": "6.6",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "6.10",
                  "versionStartIncluding": "6.6",
                  "vulnerable": true
                }
              ],
              "negate": false,
              "operator": "OR"
            }
          ]
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nbpf: Fix too early release of tcx_entry\n\nPedro Pinto and later independently also Hyunwoo Kim and Wongi Lee reported\nan issue that the tcx_entry can be released too early leading to a use\nafter free (UAF) when an active old-style ingress or clsact qdisc with a\nshared tc block is later replaced by another ingress or clsact instance.\n\nEssentially, the sequence to trigger the UAF (one example) can be as follows:\n\n  1. A network namespace is created\n  2. An ingress qdisc is created. This allocates a tcx_entry, and\n     \u0026tcx_entry-\u003eminiq is stored in the qdisc\u0027s miniqp-\u003ep_miniq. At the\n     same time, a tcf block with index 1 is created.\n  3. chain0 is attached to the tcf block. chain0 must be connected to\n     the block linked to the ingress qdisc to later reach the function\n     tcf_chain0_head_change_cb_del() which triggers the UAF.\n  4. Create and graft a clsact qdisc. This causes the ingress qdisc\n     created in step 1 to be removed, thus freeing the previously linked\n     tcx_entry:\n\n     rtnetlink_rcv_msg()\n       =\u003e tc_modify_qdisc()\n         =\u003e qdisc_create()\n           =\u003e clsact_init() [a]\n         =\u003e qdisc_graft()\n           =\u003e qdisc_destroy()\n             =\u003e __qdisc_destroy()\n               =\u003e ingress_destroy() [b]\n                 =\u003e tcx_entry_free()\n                   =\u003e kfree_rcu() // tcx_entry freed\n\n  5. Finally, the network namespace is closed. This registers the\n     cleanup_net worker, and during the process of releasing the\n     remaining clsact qdisc, it accesses the tcx_entry that was\n     already freed in step 4, causing the UAF to occur:\n\n     cleanup_net()\n       =\u003e ops_exit_list()\n         =\u003e default_device_exit_batch()\n           =\u003e unregister_netdevice_many()\n             =\u003e unregister_netdevice_many_notify()\n               =\u003e dev_shutdown()\n                 =\u003e qdisc_put()\n                   =\u003e clsact_destroy() [c]\n                     =\u003e tcf_block_put_ext()\n                       =\u003e tcf_chain0_head_change_cb_del()\n                         =\u003e tcf_chain_head_change_item()\n                           =\u003e clsact_chain_head_change()\n                             =\u003e mini_qdisc_pair_swap() // UAF\n\nThere are also other variants, the gist is to add an ingress (or clsact)\nqdisc with a specific shared block, then to replace that qdisc, waiting\nfor the tcx_entry kfree_rcu() to be executed and subsequently accessing\nthe current active qdisc\u0027s miniq one way or another.\n\nThe correct fix is to turn the miniq_active boolean into a counter. What\ncan be observed, at step 2 above, the counter transitions from 0-\u003e1, at\nstep [a] from 1-\u003e2 (in order for the miniq object to remain active during\nthe replacement), then in [b] from 2-\u003e1 and finally [c] 1-\u003e0 with the\neventual release. The reference counter in general ranges from [0,2] and\nit does not need to be atomic since all access to the counter is protected\nby the rtnl mutex. With this in place, there is no longer a UAF happening\nand the tcx_entry is freed at the correct time."
        }
      ],
      "metrics": [
        {
          "cvssV3_1": {
            "baseScore": 7.8,
            "baseSeverity": "HIGH",
            "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
            "version": "3.1"
          },
          "scenarios": [
            {
              "lang": "en",
              "value": "AV:L - The vulnerability is reached through rtnetlink `RTM_NEWQDISC`/`RTM_NEWTFILTER` messages (`tc_modify_qdisc()` \u2192 `ingress_init`/`clsact_init`/`*_destroy`) and network-namespace teardown, all of which require local access via a netlink socket and syscalls. No remote packet can drive the qdisc configuration path.\nAC:L - The attacker deterministically controls every step \u2014 create netns, create ingress qdisc with a shared block, attach chain0, graft a clsact qdisc to free the tcx_entry, then close the netns \u2014 with all mutations serialized under the rtnl mutex, so there is no race to win, only an RCU grace period to wait out. Heap grooming of the kmalloc-2048 slot is entirely under attacker control.\nPR:L - `rtnetlink_rcv_msg()` gates qdisc creation on `netlink_net_capable(skb, CAP_NET_ADMIN)` evaluated against the netns owner\u0027s user namespace, so an unprivileged local user obtains it with `unshare -Urn` \u2014 the published trigger sequence itself begins by creating a network namespace. No real root or init-namespace privilege is needed.\nUI:N - The entire sequence is performed by the attacker\u0027s own process; the final UAF fires from the `cleanup_net` worker triggered by the attacker closing its own network namespace. No victim action of any kind is involved.\nS:U - The corruption occurs in kernel heap memory and the impact stays within the same kernel security authority (local privilege escalation). No hypervisor, IOMMU, or other security-authority boundary is crossed.\nC:H - This is a use-after-free with an attacker-timed read of the freed `tcx_entry-\u003eminiq` slot, and the reclaimed ~1.6 KB kmalloc-2048 object can be sprayed with attacker-chosen structures, giving a path to disclose kernel heap pointers and read arbitrary kernel memory via a corrupted `mini_Qdisc`/`filter_list` chain.\nI:H - `mini_qdisc_pair_swap()` writes a kernel pointer (or NULL) into offset 0 of the freed object, corrupting whatever object was reallocated there, and the write can be repeated on demand by adding/removing filters on the shared block. Combined with the RX path\u0027s indirect call through `miniq-\u003efilter_list` in `tcf_classify()`, this yields a control-flow hijack primitive suitable for full privilege escalation.\nA:H - Even without successful exploitation, the use-after-free write into freed slab memory reliably corrupts unrelated kernel objects and panics the machine (KASAN-detected UAF, oops in `mini_qdisc_pair_swap`/`cleanup_net`). It can be triggered repeatedly by any unprivileged local user."
            }
          ]
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-08-05T11:34:36.731Z",
        "orgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
        "shortName": "Linux"
      },
      "references": [
        {
          "url": "https://git.kernel.org/stable/c/230bb13650b0f186f540500fd5f5f7096a822a2a"
        },
        {
          "url": "https://git.kernel.org/stable/c/f61ecf1bd5b562ebfd7d430ccb31619857e80857"
        },
        {
          "url": "https://git.kernel.org/stable/c/1cb6f0bae50441f4b4b32a28315853b279c7404e"
        }
      ],
      "title": "bpf: Fix too early release of tcx_entry",
      "x_generator": {
        "engine": "bippy-1.2.0"
      }
    }
  },
  "cveMetadata": {
    "assignerOrgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
    "assignerShortName": "Linux",
    "cveId": "CVE-2024-41010",
    "datePublished": "2024-07-17T06:10:12.051Z",
    "dateReserved": "2024-07-12T12:17:45.610Z",
    "dateUpdated": "2026-08-05T11:34:36.731Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2",
  "vulnerability-lookup:meta": {
    "vulnrichment": {
      "containers": "{\"adp\": [{\"title\": \"CVE Program Container\", \"references\": [{\"url\": \"https://git.kernel.org/stable/c/230bb13650b0f186f540500fd5f5f7096a822a2a\", \"tags\": [\"x_transferred\"]}, {\"url\": \"https://git.kernel.org/stable/c/f61ecf1bd5b562ebfd7d430ccb31619857e80857\", \"tags\": [\"x_transferred\"]}, {\"url\": \"https://git.kernel.org/stable/c/1cb6f0bae50441f4b4b32a28315853b279c7404e\", \"tags\": [\"x_transferred\"]}], \"providerMetadata\": {\"orgId\": \"af854a3a-2127-422b-91ae-364da2661108\", \"shortName\": \"CVE\", \"dateUpdated\": \"2024-08-02T04:39:55.990Z\"}}, {\"title\": \"CISA ADP Vulnrichment\", \"metrics\": [{\"other\": {\"type\": \"ssvc\", \"content\": {\"id\": \"CVE-2024-41010\", \"role\": \"CISA Coordinator\", \"options\": [{\"Exploitation\": \"none\"}, {\"Automatable\": \"no\"}, {\"Technical Impact\": \"partial\"}], \"version\": \"2.0.3\", \"timestamp\": \"2024-09-10T16:25:09.492833Z\"}}}], \"providerMetadata\": {\"orgId\": \"134c704f-9b21-4f2e-91b3-4a467353bcc0\", \"shortName\": \"CISA-ADP\", \"dateUpdated\": \"2024-09-11T12:42:20.714Z\"}}], \"cna\": {\"title\": \"bpf: Fix too early release of tcx_entry\", \"affected\": [{\"repo\": \"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git\", \"vendor\": \"Linux\", \"product\": \"Linux\", \"versions\": [{\"status\": \"affected\", \"version\": \"e420bed025071a623d2720a92bc2245c84757ecb\", \"lessThan\": \"230bb13650b0f186f540500fd5f5f7096a822a2a\", \"versionType\": \"git\"}, {\"status\": \"affected\", \"version\": \"e420bed025071a623d2720a92bc2245c84757ecb\", \"lessThan\": \"f61ecf1bd5b562ebfd7d430ccb31619857e80857\", \"versionType\": \"git\"}, {\"status\": \"affected\", \"version\": \"e420bed025071a623d2720a92bc2245c84757ecb\", \"lessThan\": \"1cb6f0bae50441f4b4b32a28315853b279c7404e\", \"versionType\": \"git\"}], \"programFiles\": [\"include/net/tcx.h\", \"net/sched/sch_ingress.c\"], \"defaultStatus\": \"unaffected\"}, {\"repo\": \"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git\", \"vendor\": \"Linux\", \"product\": \"Linux\", \"versions\": [{\"status\": \"affected\", \"version\": \"6.6\"}, {\"status\": \"unaffected\", \"version\": \"0\", \"lessThan\": \"6.6\", \"versionType\": \"semver\"}, {\"status\": \"unaffected\", \"version\": \"6.6.41\", \"versionType\": \"semver\", \"lessThanOrEqual\": \"6.6.*\"}, {\"status\": \"unaffected\", \"version\": \"6.9.10\", \"versionType\": \"semver\", \"lessThanOrEqual\": \"6.9.*\"}, {\"status\": \"unaffected\", \"version\": \"6.10\", \"versionType\": \"original_commit_for_fix\", \"lessThanOrEqual\": \"*\"}], \"programFiles\": [\"include/net/tcx.h\", \"net/sched/sch_ingress.c\"], \"defaultStatus\": \"affected\"}], \"references\": [{\"url\": \"https://git.kernel.org/stable/c/230bb13650b0f186f540500fd5f5f7096a822a2a\"}, {\"url\": \"https://git.kernel.org/stable/c/f61ecf1bd5b562ebfd7d430ccb31619857e80857\"}, {\"url\": \"https://git.kernel.org/stable/c/1cb6f0bae50441f4b4b32a28315853b279c7404e\"}], \"x_generator\": {\"engine\": \"bippy-1.2.0\"}, \"descriptions\": [{\"lang\": \"en\", \"value\": \"In the Linux kernel, the following vulnerability has been resolved:\\n\\nbpf: Fix too early release of tcx_entry\\n\\nPedro Pinto and later independently also Hyunwoo Kim and Wongi Lee reported\\nan issue that the tcx_entry can be released too early leading to a use\\nafter free (UAF) when an active old-style ingress or clsact qdisc with a\\nshared tc block is later replaced by another ingress or clsact instance.\\n\\nEssentially, the sequence to trigger the UAF (one example) can be as follows:\\n\\n  1. A network namespace is created\\n  2. An ingress qdisc is created. This allocates a tcx_entry, and\\n     \u0026tcx_entry-\u003eminiq is stored in the qdisc\u0027s miniqp-\u003ep_miniq. At the\\n     same time, a tcf block with index 1 is created.\\n  3. chain0 is attached to the tcf block. chain0 must be connected to\\n     the block linked to the ingress qdisc to later reach the function\\n     tcf_chain0_head_change_cb_del() which triggers the UAF.\\n  4. Create and graft a clsact qdisc. This causes the ingress qdisc\\n     created in step 1 to be removed, thus freeing the previously linked\\n     tcx_entry:\\n\\n     rtnetlink_rcv_msg()\\n       =\u003e tc_modify_qdisc()\\n         =\u003e qdisc_create()\\n           =\u003e clsact_init() [a]\\n         =\u003e qdisc_graft()\\n           =\u003e qdisc_destroy()\\n             =\u003e __qdisc_destroy()\\n               =\u003e ingress_destroy() [b]\\n                 =\u003e tcx_entry_free()\\n                   =\u003e kfree_rcu() // tcx_entry freed\\n\\n  5. Finally, the network namespace is closed. This registers the\\n     cleanup_net worker, and during the process of releasing the\\n     remaining clsact qdisc, it accesses the tcx_entry that was\\n     already freed in step 4, causing the UAF to occur:\\n\\n     cleanup_net()\\n       =\u003e ops_exit_list()\\n         =\u003e default_device_exit_batch()\\n           =\u003e unregister_netdevice_many()\\n             =\u003e unregister_netdevice_many_notify()\\n               =\u003e dev_shutdown()\\n                 =\u003e qdisc_put()\\n                   =\u003e clsact_destroy() [c]\\n                     =\u003e tcf_block_put_ext()\\n                       =\u003e tcf_chain0_head_change_cb_del()\\n                         =\u003e tcf_chain_head_change_item()\\n                           =\u003e clsact_chain_head_change()\\n                             =\u003e mini_qdisc_pair_swap() // UAF\\n\\nThere are also other variants, the gist is to add an ingress (or clsact)\\nqdisc with a specific shared block, then to replace that qdisc, waiting\\nfor the tcx_entry kfree_rcu() to be executed and subsequently accessing\\nthe current active qdisc\u0027s miniq one way or another.\\n\\nThe correct fix is to turn the miniq_active boolean into a counter. What\\ncan be observed, at step 2 above, the counter transitions from 0-\u003e1, at\\nstep [a] from 1-\u003e2 (in order for the miniq object to remain active during\\nthe replacement), then in [b] from 2-\u003e1 and finally [c] 1-\u003e0 with the\\neventual release. The reference counter in general ranges from [0,2] and\\nit does not need to be atomic since all access to the counter is protected\\nby the rtnl mutex. With this in place, there is no longer a UAF happening\\nand the tcx_entry is freed at the correct time.\"}], \"cpeApplicability\": [{\"nodes\": [{\"negate\": false, \"cpeMatch\": [{\"criteria\": \"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*\", \"vulnerable\": true, \"versionEndExcluding\": \"6.6.41\", \"versionStartIncluding\": \"6.6\"}, {\"criteria\": \"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*\", \"vulnerable\": true, \"versionEndExcluding\": \"6.9.10\", \"versionStartIncluding\": \"6.6\"}, {\"criteria\": \"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*\", \"vulnerable\": true, \"versionEndExcluding\": \"6.10\", \"versionStartIncluding\": \"6.6\"}], \"operator\": \"OR\"}]}], \"providerMetadata\": {\"orgId\": \"416baaa9-dc9f-4396-8d5f-8c081fb06d67\", \"shortName\": \"Linux\", \"dateUpdated\": \"2026-05-11T20:24:17.338Z\"}}}",
      "cveMetadata": "{\"cveId\": \"CVE-2024-41010\", \"state\": \"PUBLISHED\", \"dateUpdated\": \"2026-05-11T20:24:17.338Z\", \"dateReserved\": \"2024-07-12T12:17:45.610Z\", \"assignerOrgId\": \"416baaa9-dc9f-4396-8d5f-8c081fb06d67\", \"datePublished\": \"2024-07-17T06:10:12.051Z\", \"assignerShortName\": \"Linux\"}",
      "dataType": "CVE_RECORD",
      "dataVersion": "5.2"
    }
  }
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
  • Confirmed: The vulnerability is confirmed from an analyst perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
  • Patched: This vulnerability was successfully patched by the user reporting the sighting.
  • Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
  • Not confirmed: The user expresses doubt about the veracity of the vulnerability.
  • Not patched: This vulnerability was not successfully patched by the user reporting the sighting.


Loading…

Loading…