cve-2022-48644
Vulnerability from cvelistv5
Published
2024-04-28 13:00
Modified
2024-09-11 17:33
Severity
Summary
net/sched: taprio: avoid disabling offload when it was never enabled
Impacted products
VendorProduct
LinuxLinux
LinuxLinux
Show details on NVD website


{
  "containers": {
    "adp": [
      {
        "providerMetadata": {
          "dateUpdated": "2024-08-03T15:17:55.454Z",
          "orgId": "af854a3a-2127-422b-91ae-364da2661108",
          "shortName": "CVE"
        },
        "references": [
          {
            "tags": [
              "x_transferred"
            ],
            "url": "https://git.kernel.org/stable/c/d12a1eb07003e597077329767c6aa86a7e972c76"
          },
          {
            "tags": [
              "x_transferred"
            ],
            "url": "https://git.kernel.org/stable/c/586def6ebed195f3594a4884f7c5334d0e1ad1bb"
          },
          {
            "tags": [
              "x_transferred"
            ],
            "url": "https://git.kernel.org/stable/c/f58e43184226e5e9662088ccf1389e424a3a4cbd"
          },
          {
            "tags": [
              "x_transferred"
            ],
            "url": "https://git.kernel.org/stable/c/c7c9c7eb305ab8b4e93e4e4e1b78d8cfcbc26323"
          },
          {
            "tags": [
              "x_transferred"
            ],
            "url": "https://git.kernel.org/stable/c/db46e3a88a09c5cf7e505664d01da7238cd56c92"
          }
        ],
        "title": "CVE Program Container"
      },
      {
        "metrics": [
          {
            "other": {
              "content": {
                "id": "CVE-2022-48644",
                "options": [
                  {
                    "Exploitation": "none"
                  },
                  {
                    "Automatable": "no"
                  },
                  {
                    "Technical Impact": "partial"
                  }
                ],
                "role": "CISA Coordinator",
                "timestamp": "2024-09-10T15:46:17.630673Z",
                "version": "2.0.3"
              },
              "type": "ssvc"
            }
          }
        ],
        "providerMetadata": {
          "dateUpdated": "2024-09-11T17:33:11.100Z",
          "orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
          "shortName": "CISA-ADP"
        },
        "title": "CISA ADP Vulnrichment"
      }
    ],
    "cna": {
      "affected": [
        {
          "defaultStatus": "unaffected",
          "product": "Linux",
          "programFiles": [
            "net/sched/sch_taprio.c"
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "vendor": "Linux",
          "versions": [
            {
              "lessThan": "d12a1eb07003",
              "status": "affected",
              "version": "9c66d1564676",
              "versionType": "git"
            },
            {
              "lessThan": "586def6ebed1",
              "status": "affected",
              "version": "9c66d1564676",
              "versionType": "git"
            },
            {
              "lessThan": "f58e43184226",
              "status": "affected",
              "version": "9c66d1564676",
              "versionType": "git"
            },
            {
              "lessThan": "c7c9c7eb305a",
              "status": "affected",
              "version": "9c66d1564676",
              "versionType": "git"
            },
            {
              "lessThan": "db46e3a88a09",
              "status": "affected",
              "version": "9c66d1564676",
              "versionType": "git"
            }
          ]
        },
        {
          "defaultStatus": "affected",
          "product": "Linux",
          "programFiles": [
            "net/sched/sch_taprio.c"
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "vendor": "Linux",
          "versions": [
            {
              "status": "affected",
              "version": "5.4"
            },
            {
              "lessThan": "5.4",
              "status": "unaffected",
              "version": "0",
              "versionType": "custom"
            },
            {
              "lessThanOrEqual": "5.4.*",
              "status": "unaffected",
              "version": "5.4.215",
              "versionType": "custom"
            },
            {
              "lessThanOrEqual": "5.10.*",
              "status": "unaffected",
              "version": "5.10.146",
              "versionType": "custom"
            },
            {
              "lessThanOrEqual": "5.15.*",
              "status": "unaffected",
              "version": "5.15.71",
              "versionType": "custom"
            },
            {
              "lessThanOrEqual": "5.19.*",
              "status": "unaffected",
              "version": "5.19.12",
              "versionType": "custom"
            },
            {
              "lessThanOrEqual": "*",
              "status": "unaffected",
              "version": "6.0",
              "versionType": "original_commit_for_fix"
            }
          ]
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nnet/sched: taprio: avoid disabling offload when it was never enabled\n\nIn an incredibly strange API design decision, qdisc-\u003edestroy() gets\ncalled even if qdisc-\u003einit() never succeeded, not exclusively since\ncommit 87b60cfacf9f (\"net_sched: fix error recovery at qdisc creation\"),\nbut apparently also earlier (in the case of qdisc_create_dflt()).\n\nThe taprio qdisc does not fully acknowledge this when it attempts full\noffload, because it starts off with q-\u003eflags = TAPRIO_FLAGS_INVALID in\ntaprio_init(), then it replaces q-\u003eflags with TCA_TAPRIO_ATTR_FLAGS\nparsed from netlink (in taprio_change(), tail called from taprio_init()).\n\nBut in taprio_destroy(), we call taprio_disable_offload(), and this\ndetermines what to do based on FULL_OFFLOAD_IS_ENABLED(q-\u003eflags).\n\nBut looking at the implementation of FULL_OFFLOAD_IS_ENABLED()\n(a bitwise check of bit 1 in q-\u003eflags), it is invalid to call this macro\non q-\u003eflags when it contains TAPRIO_FLAGS_INVALID, because that is set\nto U32_MAX, and therefore FULL_OFFLOAD_IS_ENABLED() will return true on\nan invalid set of flags.\n\nAs a result, it is possible to crash the kernel if user space forces an\nerror between setting q-\u003eflags = TAPRIO_FLAGS_INVALID, and the calling\nof taprio_enable_offload(). This is because drivers do not expect the\noffload to be disabled when it was never enabled.\n\nThe error that we force here is to attach taprio as a non-root qdisc,\nbut instead as child of an mqprio root qdisc:\n\n$ tc qdisc add dev swp0 root handle 1: \\\n\tmqprio num_tc 8 map 0 1 2 3 4 5 6 7 \\\n\tqueues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 hw 0\n$ tc qdisc replace dev swp0 parent 1:1 \\\n\ttaprio num_tc 8 map 0 1 2 3 4 5 6 7 \\\n\tqueues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 base-time 0 \\\n\tsched-entry S 0x7f 990000 sched-entry S 0x80 100000 \\\n\tflags 0x0 clockid CLOCK_TAI\nUnable to handle kernel paging request at virtual address fffffffffffffff8\n[fffffffffffffff8] pgd=0000000000000000, p4d=0000000000000000\nInternal error: Oops: 96000004 [#1] PREEMPT SMP\nCall trace:\n taprio_dump+0x27c/0x310\n vsc9959_port_setup_tc+0x1f4/0x460\n felix_port_setup_tc+0x24/0x3c\n dsa_slave_setup_tc+0x54/0x27c\n taprio_disable_offload.isra.0+0x58/0xe0\n taprio_destroy+0x80/0x104\n qdisc_create+0x240/0x470\n tc_modify_qdisc+0x1fc/0x6b0\n rtnetlink_rcv_msg+0x12c/0x390\n netlink_rcv_skb+0x5c/0x130\n rtnetlink_rcv+0x1c/0x2c\n\nFix this by keeping track of the operations we made, and undo the\noffload only if we actually did it.\n\nI\u0027ve added \"bool offloaded\" inside a 4 byte hole between \"int clockid\"\nand \"atomic64_t picos_per_byte\". Now the first cache line looks like\nbelow:\n\n$ pahole -C taprio_sched net/sched/sch_taprio.o\nstruct taprio_sched {\n        struct Qdisc * *           qdiscs;               /*     0     8 */\n        struct Qdisc *             root;                 /*     8     8 */\n        u32                        flags;                /*    16     4 */\n        enum tk_offsets            tk_offset;            /*    20     4 */\n        int                        clockid;              /*    24     4 */\n        bool                       offloaded;            /*    28     1 */\n\n        /* XXX 3 bytes hole, try to pack */\n\n        atomic64_t                 picos_per_byte;       /*    32     0 */\n\n        /* XXX 8 bytes hole, try to pack */\n\n        spinlock_t                 current_entry_lock;   /*    40     0 */\n\n        /* XXX 8 bytes hole, try to pack */\n\n        struct sched_entry *       current_entry;        /*    48     8 */\n        struct sched_gate_list *   oper_sched;           /*    56     8 */\n        /* --- cacheline 1 boundary (64 bytes) --- */"
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2024-05-29T05:10:45.691Z",
        "orgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
        "shortName": "Linux"
      },
      "references": [
        {
          "url": "https://git.kernel.org/stable/c/d12a1eb07003e597077329767c6aa86a7e972c76"
        },
        {
          "url": "https://git.kernel.org/stable/c/586def6ebed195f3594a4884f7c5334d0e1ad1bb"
        },
        {
          "url": "https://git.kernel.org/stable/c/f58e43184226e5e9662088ccf1389e424a3a4cbd"
        },
        {
          "url": "https://git.kernel.org/stable/c/c7c9c7eb305ab8b4e93e4e4e1b78d8cfcbc26323"
        },
        {
          "url": "https://git.kernel.org/stable/c/db46e3a88a09c5cf7e505664d01da7238cd56c92"
        }
      ],
      "title": "net/sched: taprio: avoid disabling offload when it was never enabled",
      "x_generator": {
        "engine": "bippy-a5840b7849dd"
      }
    }
  },
  "cveMetadata": {
    "assignerOrgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
    "assignerShortName": "Linux",
    "cveId": "CVE-2022-48644",
    "datePublished": "2024-04-28T13:00:07.584Z",
    "dateReserved": "2024-02-25T13:44:28.316Z",
    "dateUpdated": "2024-09-11T17:33:11.100Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.1",
  "meta": {
    "nvd": "{\"cve\":{\"id\":\"CVE-2022-48644\",\"sourceIdentifier\":\"416baaa9-dc9f-4396-8d5f-8c081fb06d67\",\"published\":\"2024-04-28T13:15:07.087\",\"lastModified\":\"2024-04-29T12:42:03.667\",\"vulnStatus\":\"Awaiting Analysis\",\"descriptions\":[{\"lang\":\"en\",\"value\":\"In the Linux kernel, the following vulnerability has been resolved:\\n\\nnet/sched: taprio: avoid disabling offload when it was never enabled\\n\\nIn an incredibly strange API design decision, qdisc-\u003edestroy() gets\\ncalled even if qdisc-\u003einit() never succeeded, not exclusively since\\ncommit 87b60cfacf9f (\\\"net_sched: fix error recovery at qdisc creation\\\"),\\nbut apparently also earlier (in the case of qdisc_create_dflt()).\\n\\nThe taprio qdisc does not fully acknowledge this when it attempts full\\noffload, because it starts off with q-\u003eflags = TAPRIO_FLAGS_INVALID in\\ntaprio_init(), then it replaces q-\u003eflags with TCA_TAPRIO_ATTR_FLAGS\\nparsed from netlink (in taprio_change(), tail called from taprio_init()).\\n\\nBut in taprio_destroy(), we call taprio_disable_offload(), and this\\ndetermines what to do based on FULL_OFFLOAD_IS_ENABLED(q-\u003eflags).\\n\\nBut looking at the implementation of FULL_OFFLOAD_IS_ENABLED()\\n(a bitwise check of bit 1 in q-\u003eflags), it is invalid to call this macro\\non q-\u003eflags when it contains TAPRIO_FLAGS_INVALID, because that is set\\nto U32_MAX, and therefore FULL_OFFLOAD_IS_ENABLED() will return true on\\nan invalid set of flags.\\n\\nAs a result, it is possible to crash the kernel if user space forces an\\nerror between setting q-\u003eflags = TAPRIO_FLAGS_INVALID, and the calling\\nof taprio_enable_offload(). This is because drivers do not expect the\\noffload to be disabled when it was never enabled.\\n\\nThe error that we force here is to attach taprio as a non-root qdisc,\\nbut instead as child of an mqprio root qdisc:\\n\\n$ tc qdisc add dev swp0 root handle 1: \\\\\\n\\tmqprio num_tc 8 map 0 1 2 3 4 5 6 7 \\\\\\n\\tqueues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 hw 0\\n$ tc qdisc replace dev swp0 parent 1:1 \\\\\\n\\ttaprio num_tc 8 map 0 1 2 3 4 5 6 7 \\\\\\n\\tqueues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 base-time 0 \\\\\\n\\tsched-entry S 0x7f 990000 sched-entry S 0x80 100000 \\\\\\n\\tflags 0x0 clockid CLOCK_TAI\\nUnable to handle kernel paging request at virtual address fffffffffffffff8\\n[fffffffffffffff8] pgd=0000000000000000, p4d=0000000000000000\\nInternal error: Oops: 96000004 [#1] PREEMPT SMP\\nCall trace:\\n taprio_dump+0x27c/0x310\\n vsc9959_port_setup_tc+0x1f4/0x460\\n felix_port_setup_tc+0x24/0x3c\\n dsa_slave_setup_tc+0x54/0x27c\\n taprio_disable_offload.isra.0+0x58/0xe0\\n taprio_destroy+0x80/0x104\\n qdisc_create+0x240/0x470\\n tc_modify_qdisc+0x1fc/0x6b0\\n rtnetlink_rcv_msg+0x12c/0x390\\n netlink_rcv_skb+0x5c/0x130\\n rtnetlink_rcv+0x1c/0x2c\\n\\nFix this by keeping track of the operations we made, and undo the\\noffload only if we actually did it.\\n\\nI\u0027ve added \\\"bool offloaded\\\" inside a 4 byte hole between \\\"int clockid\\\"\\nand \\\"atomic64_t picos_per_byte\\\". Now the first cache line looks like\\nbelow:\\n\\n$ pahole -C taprio_sched net/sched/sch_taprio.o\\nstruct taprio_sched {\\n        struct Qdisc * *           qdiscs;               /*     0     8 */\\n        struct Qdisc *             root;                 /*     8     8 */\\n        u32                        flags;                /*    16     4 */\\n        enum tk_offsets            tk_offset;            /*    20     4 */\\n        int                        clockid;              /*    24     4 */\\n        bool                       offloaded;            /*    28     1 */\\n\\n        /* XXX 3 bytes hole, try to pack */\\n\\n        atomic64_t                 picos_per_byte;       /*    32     0 */\\n\\n        /* XXX 8 bytes hole, try to pack */\\n\\n        spinlock_t                 current_entry_lock;   /*    40     0 */\\n\\n        /* XXX 8 bytes hole, try to pack */\\n\\n        struct sched_entry *       current_entry;        /*    48     8 */\\n        struct sched_gate_list *   oper_sched;           /*    56     8 */\\n        /* --- cacheline 1 boundary (64 bytes) --- */\"},{\"lang\":\"es\",\"value\":\"En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad: net/sched: taprio: evita deshabilitar la descarga cuando nunca estuvo habilitada. En una decisi\u00f3n de dise\u00f1o de API incre\u00edblemente extra\u00f1a, se llama a qdisc-\u0026gt;destroy() incluso si qdisc-\u0026gt;init() nunca tuvo \u00e9xito, no exclusivamente desde el commit 87b60cfacf9f (\\\"net_sched: corregir recuperaci\u00f3n de error en la creaci\u00f3n de qdisc\\\"), sino aparentemente tambi\u00e9n antes (en el caso de qdisc_create_dflt()). La qdisc taprio no reconoce completamente esto cuando intenta una descarga completa, porque comienza con q-\u0026gt;flags = TAPRIO_FLAGS_INVALID en taprio_init(), luego reemplaza q-\u0026gt;flags con TCA_TAPRIO_ATTR_FLAGS analizado desde netlink (en taprio_change(), cola llamada de taprio_init()). Pero en taprio_destroy(), llamamos a taprio_disable_offload(), y esto determina qu\u00e9 hacer en funci\u00f3n de FULL_OFFLOAD_IS_ENABLED(q-\u0026gt;flags). Pero al observar la implementaci\u00f3n de FULL_OFFLOAD_IS_ENABLED() (una verificaci\u00f3n bit a bit del bit 1 en q-\u0026gt;flags), no es v\u00e1lido llamar a esta macro en q-\u0026gt;flags cuando contiene TAPRIO_FLAGS_INVALID, porque est\u00e1 configurado en U32_MAX y, por lo tanto, FULL_OFFLOAD_IS_ENABLED () devolver\u00e1 verdadero en un conjunto de indicadores no v\u00e1lido. Como resultado, es posible bloquear el kernel si el espacio del usuario fuerza un error entre configurar q-\u0026gt;flags = TAPRIO_FLAGS_INVALID y la llamada de taprio_enable_offload(). Esto se debe a que los conductores no esperan que se deshabilite la descarga cuando nunca estuvo habilitada. El error que forzamos aqu\u00ed es adjuntar taprio como una qdisc no ra\u00edz, sino como hija de una qdisc ra\u00edz mqprio: $ tc qdisc add dev swp0 root handle 1: \\\\ mqprio num_tc 8 map 0 1 2 3 4 5 6 7 \\\\ colas 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 hw 0 $ tc qdisc reemplazar dev swp0 padre 1:1 \\\\ taprio num_tc 8 map 0 1 2 3 4 5 6 7 \\\\ colas 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 tiempo base 0 \\\\ entrada programada S 0x7f 990000 entrada programada S 0x80 100000 \\\\ banderas 0x0 clockid CLOCK_TAI No se puede para manejar la solicitud de paginaci\u00f3n del kernel en la direcci\u00f3n virtual ffffffffffffffff8 [ffffffffffffffff8] pgd=0000000000000000, p4d=0000000000000000 Error interno: Vaya: 96000004 [#1] Seguimiento de llamada SMP PREEMPT: taprio_dump+0x27c/0x310 vsc9959_port _setup_tc+0x1f4/0x460 felix_port_setup_tc+0x24/0x3c dsa_slave_setup_tc +0x54/0x27c taprio_disable_offload.isra.0+0x58/0xe0 taprio_destroy+0x80/0x104 qdisc_create+0x240/0x470 tc_modify_qdisc+0x1fc/0x6b0 rtnetlink_rcv_msg+0x12c/0x390 x5c/0x130 rtnetlink_rcv+0x1c/0x2c Solucione este problema manteniendo un registro de operaciones que hicimos, y deshacer la descarga solo si realmente lo hicimos. Agregu\u00e9 \\\"bool descargado\\\" dentro de un hueco de 4 bytes entre \\\"int clockid\\\" y \\\"atomic64_t picos_per_byte\\\". Ahora la primera l\u00ednea de cach\u00e9 se ve as\u00ed: $ pahole -C taprio_sched net/sched/sch_taprio.o struct taprio_sched { struct Qdisc * * qdiscs; /* 0 8 */ struct Qdisc * ra\u00edz; /* 8 8 */ u32 banderas; /* 16 4 */ enum tk_offsets tk_offset; /* 20 4 */ int relojid; /* 24 4 */ bool descargado; /* 28 1 */ /* XXX agujero de 3 bytes, intenta empaquetar */ atomic64_t picos_per_byte; /* 32 0 */ /* XXX agujero de 8 bytes, intenta empaquetar */ spinlock_t current_entry_lock; /* 40 0 */ /* XXX agujero de 8 bytes, intenta empaquetar */ struct sched_entry * current_entry; /* 48 8 */ struct sched_gate_list * oper_sched; /* 56 8 */ /* --- l\u00edmite de l\u00ednea de cach\u00e9 1 (64 bytes) --- */\"}],\"metrics\":{},\"references\":[{\"url\":\"https://git.kernel.org/stable/c/586def6ebed195f3594a4884f7c5334d0e1ad1bb\",\"source\":\"416baaa9-dc9f-4396-8d5f-8c081fb06d67\"},{\"url\":\"https://git.kernel.org/stable/c/c7c9c7eb305ab8b4e93e4e4e1b78d8cfcbc26323\",\"source\":\"416baaa9-dc9f-4396-8d5f-8c081fb06d67\"},{\"url\":\"https://git.kernel.org/stable/c/d12a1eb07003e597077329767c6aa86a7e972c76\",\"source\":\"416baaa9-dc9f-4396-8d5f-8c081fb06d67\"},{\"url\":\"https://git.kernel.org/stable/c/db46e3a88a09c5cf7e505664d01da7238cd56c92\",\"source\":\"416baaa9-dc9f-4396-8d5f-8c081fb06d67\"},{\"url\":\"https://git.kernel.org/stable/c/f58e43184226e5e9662088ccf1389e424a3a4cbd\",\"source\":\"416baaa9-dc9f-4396-8d5f-8c081fb06d67\"}]}}"
  }
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading...

Loading...