"value":"In the Linux kernel, the following vulnerability has been resolved:\n\narm64: asm-bug: Add .align 2 to the end of __BUG_ENTRY\n\nWhen CONFIG_DEBUG_BUGVERBOSE=n, we fail to add necessary padding bytes\nto bug_table entries, and as a result the last entry in a bug table will\nbe ignored, potentially leading to an unexpected panic(). All prior\nentries in the table will be handled correctly.\n\nThe arm64 ABI requires that struct fields of up to 8 bytes are\nnaturally-aligned, with padding added within a struct such that struct\nare suitably aligned within arrays.\n\nWhen CONFIG_DEBUG_BUGVERPOSE=y, the layout of a bug_entry is:\n\n\tstruct bug_entry {\n\t\tsigned int bug_addr_disp;\t// 4 bytes\n\t\tsigned int file_disp;\t// 4 bytes\n\t\tunsigned short line;\t\t// 2 bytes\n\t\tunsigned short flags;\t\t// 2 bytes\n\t}\n\n... with 12 bytes total, requiring 4-byte alignment.\n\nWhen CONFIG_DEBUG_BUGVERBOSE=n, the layout of a bug_entry is:\n\n\tstruct bug_entry {\n\t\tsigned int bug_addr_disp;\t// 4 bytes\n\t\tunsigned short flags;\t\t// 2 bytes\n\t\t< implicit padding >\t\t// 2 bytes\n\t}\n\n... with 8 bytes total, with 6 bytes of data and 2 bytes of trailing\npadding, requiring 4-byte alginment.\n\nWhen we create a bug_entry in assembly, we align the start of the entry\nto 4 bytes, which implicitly handles padding for any prior entries.\nHowever, we do not align the end of the entry, and so when\nCONFIG_DEBUG_BUGVERBOSE=n, the final entry lacks the trailing padding\nbytes.\n\nFor the main kernel image this is not a problem as find_bug() doesn't\ndepend on the trailing padding bytes when searching for entries:\n\n\tfor (bug = __start___bug_table; bug < __stop___bug_table; ++bug)\n\t\tif (bugaddr == bug_addr(bug))\n\t\t\treturn bug;\n\nHowever for modules, module_bug_finalize() depends on the trailing\nbytes when calculating the number of entries:\n\n\tmod->num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry);\n\n... and as the last bug_entry lacks the necessary padding bytes, this entry\nwill not be counted, e.g. in the case of a single entry:\n\n\tsechdrs[i].sh_size == 6\n\tsizeof(struct bug_entry) == 8;\n\n\tsechdrs[i].sh_size / sizeof(struct bug_entry) == 0;\n\nConsequently module_find_bug() will miss the last bug_entry when it does:\n\n\tfor (i = 0; i < mod->num_bugs; ++i, ++bug)\n\t\tif (bugaddr == bug_addr(bug))\n\t\t\tgoto out;\n\n... which can lead to a kenrel panic due to an unhandled bug.\n\nThis can be demonstrated with the following module:\n\n\tstatic int __init buginit(void)\n\t{\n\t\tWARN(1, \"hello\\n\");\n\t\treturn 0;\n\t}\n\n\tstatic void __exit bugexit(void)\n\t{\n\t}\n\n\tmodule_init(buginit);\n\tmodule_exit(bugexit);\n\tMODULE_LICENSE(\"GPL\");\n\n...whichwilltriggerakernelpanicwhenloaded:\n\n\t------------[cuthere]------------\n\thello\n\tUnexpectedkernelBRKexceptionatEL1\n\tInternalerror:BRKhandler:00000000f2000800[#1]PREEMPTSMP\n\tModuleslinkedin:hello(O+)\n\tCPU:0PID:50Comm:insmodTainted:GO6.9.1#8\n\tHardwarename:linux,dummy-virt(DT)\n\tpstate:60400005(nZCvdaif+PAN-UAO-TCO-DIT-SSBSBTYPE=--)\n\tpc:buginit+0x18/0x1000[hello]\n\tlr:buginit+0x18/0x1000[hello]\n\tsp:ffff800080533ae0\n\tx29:ffff800080533ae0x28:0000000000000000x27:0000000000000000\n\tx26:ffffaba8c4e70510x25:ffff800080533c30x24:ffffaba8c4a28a58\n\tx23:0000000000000000x22:0000000000000000x21:ffff3947c0eab3c0\n\tx20:ffffaba8c4e3f000x19:ffffaba846464000x18:0000000000000006\n\tx17:0000000000000000x16:ffffaba8c2492834x15:0720072007200720\n\tx14:0720072007200720x13:ffffaba8c49b27c8x12:0000000000000312\n\tx11:0000000000000106x10:ffffaba8c4a0a7c8x9:ffffaba8c49b27c8\n\tx8:00000000ffffefffx7:ffffaba8c4a0a7c8x6:80000000fffff000\n\tx5:0000000000000107x4:0000000000000000x3:0000000000000000\n\tx2:0000000000000000x1:0000000000000000x0:ffff3947c0eab3c0\n\tCalltrace:\n\tbuginit+0x18/0x1000[hello]\n\tdo_one_initcall+0x80/0x1c8\n\tdo_init_module+0x60/0x218\n\tload_module+0x1ba4/0