Re: [BUG] [BISECTED] [CORRECTION] systemd-devd triggers kernel memleak apparently in drivers/core/dd.c: driver_register()
From: Hans de Goede
Date: Wed Mar 29 2023 - 11:46:58 EST
Hi,
On 3/29/23 16:18, Mirsad Goran Todorovac wrote:
> On 29.3.2023. 15:35, Thomas Weißschuh wrote:
>>
>> Mar 29, 2023 08:31:31 Mirsad Goran Todorovac <mirsad.todorovac@xxxxxxxxxxxx>:
>>
>>> Hi, again,
>>>
>>> NOTE: I forgot to rewind to the first bad commit. So please ignore
>>> the previous email.
>>>
>>> On 29.3.2023. 15:22, Mirsad Goran Todorovac wrote:
>>>> Hi, Armin, Mr. Greg,
>>>> On 29.3.2023. 10:13, Mirsad Goran Todorovac wrote:
>>>>> On 28.3.2023. 21:55, Armin Wolf wrote:
>>>>>> Am 28.03.23 um 21:06 schrieb Mirsad Goran Todorovac:
>>>>>>
>>>>>>> On 3/28/2023 6:53 PM, Armin Wolf wrote:
>>>>>>>> …
>>>>>>>
>>>>>>> Hi Armin,
>>>>>>>
>>>>>>> I tried your suggestion, and though it is an obvious improvement and a
>>>>>>> leak fix, this
>>>>>>> was not the one we were searching for.
>>>>>>>
>>>>>>> I tested the following patch:
>>>>>>>
>>>>>>> diff --git a/drivers/platform/x86/think-lmi.c
>>>>>>> b/drivers/platform/x86/think-lmi.c
>>>>>>> index c816646eb661..1e77ecb0cba8 100644
>>>>>>> --- a/drivers/platform/x86/think-lmi.c
>>>>>>> +++ b/drivers/platform/x86/think-lmi.c
>>>>>>> @@ -929,8 +929,10 @@ static ssize_t current_value_show(struct kobject
>>>>>>> *kobj, struct kobj_attribute *a
>>>>>>>
>>>>>>> /* validate and split from `item,value` -> `value` */
>>>>>>> value = strpbrk(item, ",");
>>>>>>> - if (!value || value == item || !strlen(value + 1))
>>>>>>> + if (!value || value == item || !strlen(value + 1)) {
>>>>>>> + kfree(item);
>>>>>>> return -EINVAL;
>>>>>>> + }
>>>>>>>
>>>>>>> ret = sysfs_emit(buf, "%s\n", value + 1);
>>>>>>> kfree(item);
>>>>>>>
>>>>>>> (I would also object to the use of strlen() here, for it is inherently
>>>>>>> insecure
>>>>>>> against SEGFAULT in kernel space.)
>>>>>>>
>>>>>>> I still get:
>>>>>>> [root@pc-mtodorov marvin]# uname -rms
>>>>>>> Linux 6.3.0-rc4-armin-patch-00025-g3a93e40326c8-dirty x86_64
>>>>>>> [root@pc-mtodorov marvin]# cat /sys/kernel/debug/kmemleak [edited]
>>>>>>> unreferenced object 0xffff8eb008ef9260 (size 96):
>>>>>>> comm "systemd-udevd", pid 771, jiffies 4294896499 (age 74.880s)
>>>>>>> hex dump (first 32 bytes):
>>>>>>> 53 65 72 69 61 6c 50 6f 72 74 31 41 64 64 72 65 SerialPort1Addre
>>>>>>> 73 73 2c 33 46 38 2f 49 52 51 34 3b 5b 4f 70 74 ss,3F8/IRQ4;[Opt
>>>>>>> backtrace:
>>>>>>> [<ffffffff9eafb26c>] slab_post_alloc_hook+0x8c/0x3e0
>>>>>>> [<ffffffff9eb02b49>] __kmem_cache_alloc_node+0x1d9/0x2a0
>>>>>>> [<ffffffff9ea773c9>] __kmalloc_node_track_caller+0x59/0x180
>>>>>>> [<ffffffff9ea66a1a>] kstrdup+0x3a/0x70
>>>>>>> [<ffffffffc0eef9aa>] tlmi_extract_output_string.isra.0+0x2a/0x60
>>>>>>> [think_lmi]
>>>>>>> [<ffffffffc0eefb64>] tlmi_setting.constprop.4+0x54/0x90 [think_lmi]
>>>>>>> [<ffffffffc0ef02c1>] tlmi_probe+0x591/0xba0 [think_lmi]
>>>>>>> [<ffffffffc0629c53>] wmi_dev_probe+0x163/0x230 [wmi]
>>>>>>> [<ffffffff9f1987eb>] really_probe+0x17b/0x3d0
>>>>>>> [<ffffffff9f198ad4>] __driver_probe_device+0x84/0x190
>>>>>>> [<ffffffff9f198c14>] driver_probe_device+0x24/0xc0
>>>>>>> [<ffffffff9f198ed2>] __driver_attach+0xc2/0x190
>>>>>>> [<ffffffff9f195ab1>] bus_for_each_dev+0x81/0xd0
>>>>>>> [<ffffffff9f197c62>] driver_attach+0x22/0x30
>>>>>>> [<ffffffff9f197354>] bus_add_driver+0x1b4/0x240
>>>>>>> [<ffffffff9f19a0a2>] driver_register+0x62/0x120
>>>>>>> unreferenced object 0xffff8eb018ddbb40 (size 64):
>>>>>>> comm "systemd-udevd", pid 771, jiffies 4294896528 (age 74.780s)
>>>>>>> hex dump (first 32 bytes):
>>>>>>> 55 53 42 50 6f 72 74 41 63 63 65 73 73 2c 45 6e USBPortAccess,En
>>>>>>> 61 62 6c 65 64 3b 5b 4f 70 74 69 6f 6e 61 6c 3a abled;[Optional:
>>>>>>> backtrace:
>>>>>>> [<ffffffff9eafb26c>] slab_post_alloc_hook+0x8c/0x3e0
>>>>>>> [<ffffffff9eb02b49>] __kmem_cache_alloc_node+0x1d9/0x2a0
>>>>>>> [<ffffffff9ea773c9>] __kmalloc_node_track_caller+0x59/0x180
>>>>>>> [<ffffffff9ea66a1a>] kstrdup+0x3a/0x70
>>>>>>> [<ffffffffc0eef9aa>] tlmi_extract_output_string.isra.0+0x2a/0x60
>>>>>>> [think_lmi]
>>>>>>> [<ffffffffc0eefb64>] tlmi_setting.constprop.4+0x54/0x90 [think_lmi]
>>>>>>> [<ffffffffc0ef02c1>] tlmi_probe+0x591/0xba0 [think_lmi]
>>>>>>> [<ffffffffc0629c53>] wmi_dev_probe+0x163/0x230 [wmi]
>>>>>>> [<ffffffff9f1987eb>] really_probe+0x17b/0x3d0
>>>>>>> [<ffffffff9f198ad4>] __driver_probe_device+0x84/0x190
>>>>>>> [<ffffffff9f198c14>] driver_probe_device+0x24/0xc0
>>>>>>> [<ffffffff9f198ed2>] __driver_attach+0xc2/0x190
>>>>>>> [<ffffffff9f195ab1>] bus_for_each_dev+0x81/0xd0
>>>>>>> [<ffffffff9f197c62>] driver_attach+0x22/0x30
>>>>>>> [<ffffffff9f197354>] bus_add_driver+0x1b4/0x240
>>>>>>> [<ffffffff9f19a0a2>] driver_register+0x62/0x120
>>>>>>> unreferenced object 0xffff8eb006fe2b40 (size 64):
>>>>>>> comm "systemd-udevd", pid 771, jiffies 4294896542 (age 74.724s)
>>>>>>> hex dump (first 32 bytes):
>>>>>>> 55 53 42 42 49 4f 53 53 75 70 70 6f 72 74 2c 45 USBBIOSSupport,E
>>>>>>> 6e 61 62 6c 65 64 3b 5b 4f 70 74 69 6f 6e 61 6c nabled;[Optional
>>>>>>> backtrace:
>>>>>>> [<ffffffff9eafb26c>] slab_post_alloc_hook+0x8c/0x3e0
>>>>>>> [<ffffffff9eb02b49>] __kmem_cache_alloc_node+0x1d9/0x2a0
>>>>>>> [<ffffffff9ea773c9>] __kmalloc_node_track_caller+0x59/0x180
>>>>>>> [<ffffffff9ea66a1a>] kstrdup+0x3a/0x70
>>>>>>> [<ffffffffc0eef9aa>] tlmi_extract_output_string.isra.0+0x2a/0x60
>>>>>>> [think_lmi]
>>>>>>> [<ffffffffc0eefb64>] tlmi_setting.constprop.4+0x54/0x90 [think_lmi]
>>>>>>> [<ffffffffc0ef02c1>] tlmi_probe+0x591/0xba0 [think_lmi]
>>>>>>> [<ffffffffc0629c53>] wmi_dev_probe+0x163/0x230 [wmi]
>>>>>>> [<ffffffff9f1987eb>] really_probe+0x17b/0x3d0
>>>>>>> [<ffffffff9f198ad4>] __driver_probe_device+0x84/0x190
>>>>>>> [<ffffffff9f198c14>] driver_probe_device+0x24/0xc0
>>>>>>> [<ffffffff9f198ed2>] __driver_attach+0xc2/0x190
>>>>>>> [<ffffffff9f195ab1>] bus_for_each_dev+0x81/0xd0
>>>>>>> [<ffffffff9f197c62>] driver_attach+0x22/0x30
>>>>>>> [<ffffffff9f197354>] bus_add_driver+0x1b4/0x240
>>>>>>> [<ffffffff9f19a0a2>] driver_register+0x62/0x120
>>>>>>>
>>>>>>> There are currently 84 wmi_dev_probe leaks, sized mostly 64 bytes, and
>>>>>>> one 96 and two 192 bytes.
>>>>>>>
>>>>>>> I also cannot figure out the mechanism by which current_value_show()
>>>>>>> is called, when it is static?
>>>>>>>
>>>>>>> Any idea?
>>>>>>>
>>>>>>> Thanks.
>>>>>>>
>>>>>>> Best regards,
>>>>>>> Mirsad
>>>>>>>
>>>>>> Can you tell me how many BIOS settings think-lmi provides on your machine? Because according to the stacktrace,
>>>>>> the other place where the leak could have occurred is inside tlmi_analyze(), which calls tlmi_setting().
>>>>>
>>>>> Yes, Sir!
>>>>>
>>>>> I think these could be the ones you need (totaling 83, which is close to 82 systemd-udevd leaks):
>>>>>
>>>>> [root@pc-mtodorov marvin]# ls -l /sys/devices/virtual/firmware-attributes/thinklmi/attributes | grep ^d
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 AfterPowerLoss
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 AlarmDate(MM\DD\YYYY)
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 AlarmDayofWeek
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 AlarmTime(HH:MM:SS)
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 ASPMSupport
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 AutomaticBootSequence
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 BIOSPasswordAtBootDeviceList
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 BIOSPasswordAtReboot
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 BIOSPasswordAtUnattendedBoot
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 BootMode
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 BootPriority
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 BootUpNum-LockStatus
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 C1ESupport
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 CardReader
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 ClearTCGSecurityFeature
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 ComputraceModuleActivation
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 ConfigurationChangeDetection
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 ConfigureSATAas
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 CoreMulti-Processing
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 CoverTamperDetected
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 CSM
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 CStateSupport
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 DeviceGuard
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 DustShieldAlert
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 EISTSupport
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 EnhancedPowerSavingMode
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 ErrorBootSequence
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 Friday
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 FrontUSBPorts
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 HardDiskPre-delay
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 Intel(R)SGXControl
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 InternalSpeaker
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 Monday
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 OnboardAudioController
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 OnboardEthernetController
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 OptionKeysDisplay
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 OptionKeysDisplayStyle
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 OSOptimizedDefaults
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 PasswordCountExceededError
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 PCIe16xSlotSpeed
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 PCIe1xSlot1Speed
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 PrimaryBootSequence
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 PXEIPV4NetworkStack
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 PXEIPV6NetworkStack
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 PXEOptionROM
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 RearUSBPorts
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 RequireAdmin.Pass.whenFlashing
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 RequireHDPonSystemBoot
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 SATAController
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 SATADrive1
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 SATADrive2
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 Saturday
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 SecureBoot
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 SecureRollBackPrevention
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 SecurityChip
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 SelectActiveVideo
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 SerialPort1Address
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 SmartUSBProtection
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 StartupDeviceMenuPrompt
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 StartupSequence
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 Sunday
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 Thursday
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 Tuesday
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 TurboMode
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 USBBIOSSupport
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 USBEnumerationDelay
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 USBPort1
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 USBPort2
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 USBPort3
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 USBPort4
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 USBPort5
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 USBPort6
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 USBPort7
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 USBPort8
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 USBPortAccess
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 UserDefinedAlarmTime(HH:MM:SS)
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 VirtualizationTechnology
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 VTdFeature
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 WakefromSerialPortRing
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 WakeOnLAN
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 WakeUponAlarm
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 Wednesday
>>>>> drwxr-xr-x 2 root root 0 Mar 29 08:24 WindowsUEFIFirmwareUpdate
>>>>> [root@pc-mtodorov marvin]# ls -l /sys/devices/virtual/firmware-attributes/thinklmi/attributes | grep ^d | wc -l
>>>>> 83
>>>>> [root@pc-mtodorov marvin]#
>>>>>
>>>>>> However, i have no idea on how *info is somehow leaked, it has to happen inside the for-loop tween the call
>>>>>> to tlmi_setting() and strreplace(), because otherwise the strings would not contain the "/" character.
>>>>>
>>>>> I see. It is the line 1404.
>>>>>
>>>>>> Can you check if the problem is somehow solved by applying the following commit from the platform-drivers-x86
>>>>>> for-next branch:
>>>>>> da62908efe80 ("platform/x86: think-lmi: Properly interpret return value of tlmi_setting")
>>>>>
>>>>> It could possibly be that. But I do not recall seeing these messages in 6.3-rc3 ...
>>>>>
>>>>> ...
>>>>>
>>>>> Unfortunately, the build with Thomas' patch you referred to did not work:
>>>>>
>>>>> unreferenced object 0xffff9dff4d28bbc8 (size 192):
>>>>> comm "systemd-udevd", pid 769, jiffies 4294897473 (age 85.700s)
>>>>> hex dump (first 32 bytes):
>>>>> 50 72 69 6d 61 72 79 42 6f 6f 74 53 65 71 75 65 PrimaryBootSeque
>>>>> 6e 63 65 2c 4d 2e 32 20 44 72 69 76 65 20 31 3a nce,M.2 Drive 1:
>>>>> backtrace:
>>>>> [<ffffffffa48fb26c>] slab_post_alloc_hook+0x8c/0x3e0
>>>>> [<ffffffffa4902b49>] __kmem_cache_alloc_node+0x1d9/0x2a0
>>>>> [<ffffffffa48773c9>] __kmalloc_node_track_caller+0x59/0x180
>>>>> [<ffffffffa4866a1a>] kstrdup+0x3a/0x70
>>>>> [<ffffffffc0c7f9aa>] tlmi_extract_output_string.isra.0+0x2a/0x60 [think_lmi]
>>>>> [<ffffffffc0c7fb64>] tlmi_setting.constprop.4+0x54/0x90 [think_lmi]
>>>>> [<ffffffffc0c802c1>] tlmi_probe+0x591/0xba0 [think_lmi]
>>>>> [<ffffffffc03c9c53>] wmi_dev_probe+0x163/0x230 [wmi]
>>>>> [<ffffffffa4f987eb>] really_probe+0x17b/0x3d0
>>>>> [<ffffffffa4f98ad4>] __driver_probe_device+0x84/0x190
>>>>> [<ffffffffa4f98c14>] driver_probe_device+0x24/0xc0
>>>>> [<ffffffffa4f98ed2>] __driver_attach+0xc2/0x190
>>>>> [<ffffffffa4f95ab1>] bus_for_each_dev+0x81/0xd0
>>>>> [<ffffffffa4f97c62>] driver_attach+0x22/0x30
>>>>> [<ffffffffa4f97354>] bus_add_driver+0x1b4/0x240
>>>>> [<ffffffffa4f9a0a2>] driver_register+0x62/0x120
>>>>> unreferenced object 0xffff9dff4d28a008 (size 192):
>>>>> comm "systemd-udevd", pid 769, jiffies 4294897517 (age 85.540s)
>>>>> hex dump (first 32 bytes):
>>>>> 45 72 72 6f 72 42 6f 6f 74 53 65 71 75 65 6e 63 ErrorBootSequenc
>>>>> 65 2c 4e 65 74 77 6f 72 6b 20 31 3a 4d 2e 32 20 e,Network 1:M.2
>>>>> backtrace:
>>>>> [<ffffffffa48fb26c>] slab_post_alloc_hook+0x8c/0x3e0
>>>>> [<ffffffffa4902b49>] __kmem_cache_alloc_node+0x1d9/0x2a0
>>>>> [<ffffffffa48773c9>] __kmalloc_node_track_caller+0x59/0x180
>>>>> [<ffffffffa4866a1a>] kstrdup+0x3a/0x70
>>>>> [<ffffffffc0c7f9aa>] tlmi_extract_output_string.isra.0+0x2a/0x60 [think_lmi]
>>>>> [<ffffffffc0c7fb64>] tlmi_setting.constprop.4+0x54/0x90 [think_lmi]
>>>>> [<ffffffffc0c802c1>] tlmi_probe+0x591/0xba0 [think_lmi]
>>>>> [<ffffffffc03c9c53>] wmi_dev_probe+0x163/0x230 [wmi]
>>>>> [<ffffffffa4f987eb>] really_probe+0x17b/0x3d0
>>>>> [<ffffffffa4f98ad4>] __driver_probe_device+0x84/0x190
>>>>> [<ffffffffa4f98c14>] driver_probe_device+0x24/0xc0
>>>>> [<ffffffffa4f98ed2>] __driver_attach+0xc2/0x190
>>>>> [<ffffffffa4f95ab1>] bus_for_each_dev+0x81/0xd0
>>>>> [<ffffffffa4f97c62>] driver_attach+0x22/0x30
>>>>> [<ffffffffa4f97354>] bus_add_driver+0x1b4/0x240
>>>>> [<ffffffffa4f9a0a2>] driver_register+0x62/0x120
>>>>> [root@pc-mtodorov marvin]# uname -rms
>>>>> Linux 6.3.0-rc4-armin+tw-patch-00025-g3a93e40326c8-dirty x86_64
>>>>> [root@pc-mtodorov marvin]#
>>>>>
>>>>> What was applied is:
>>>>>
>>>>> mtodorov@domac:~/linux/kernel/linux_torvalds$ git diff
>>>>> diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c
>>>>> index c816646eb661..9a3015f43aaf 100644
>>>>> --- a/drivers/platform/x86/think-lmi.c
>>>>> +++ b/drivers/platform/x86/think-lmi.c
>>>>> @@ -929,8 +929,10 @@ static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *a
>>>>>
>>>>> /* validate and split from `item,value` -> `value` */
>>>>> value = strpbrk(item, ",");
>>>>> - if (!value || value == item || !strlen(value + 1))
>>>>> + if (!value || value == item || !strlen(value + 1)) {
>>>>> + kfree(item);
>>>>> return -EINVAL;
>>>>> + }
>>>>>
>>>>> ret = sysfs_emit(buf, "%s\n", value + 1);
>>>>> kfree(item);
>>>>> @@ -1380,7 +1382,6 @@ static struct tlmi_pwd_setting *tlmi_create_auth(const char *pwd_type,
>>>>>
>>>>> static int tlmi_analyze(void)
>>>>> {
>>>>> - acpi_status status;
>>>>> int i, ret;
>>>>>
>>>>> if (wmi_has_guid(LENOVO_SET_BIOS_SETTINGS_GUID) &&
>>>>> @@ -1417,8 +1418,8 @@ static int tlmi_analyze(void)
>>>>> char *p;
>>>>>
>>>>> tlmi_priv.setting[i] = NULL;
>>>>> - status = tlmi_setting(i, &item, LENOVO_BIOS_SETTING_GUID);
>>>>> - if (ACPI_FAILURE(status))
>>>>> + ret = tlmi_setting(i, &item, LENOVO_BIOS_SETTING_GUID);
>>>>> + if (ret)
>>>>> break;
>>>>> if (!item)
>>>>> break;
>>>>>
>>>>>
>>>>>> Also current_value_show() is used by attr_current_val, the __ATTR_RW_MODE() macro arranges for that.
>>>>>
>>>>> Thanks.
>>>>>
>>>>> In this build:
>>>>>
>>>>> [root@pc-mtodorov marvin]# uname -rms
>>>>> Linux 6.3.0-rc34tests-00001-g6981739a967c x86_64
>>>>> [root@pc-mtodorov marvin]#
>>>>>
>>>>> ... the bug isn't present, so it might be something added recently:
>>>>>
>>>>> commit 8a02d70679fc1c434401863333c8ea7dbf201494
>>>>> Author: Mark Pearson <mpearson-lenovo@xxxxxxxxx>
>>>>> Date: Sun Mar 19 20:32:21 2023 -0400
>>>>>
>>>>> platform/x86: think-lmi: Add possible_values for ThinkStation
>>>>>
>>>>> commit cf337f27f3bfc4aeab4954c468239fd6233c7638
>>>>> Author: Mark Pearson <mpearson-lenovo@xxxxxxxxx>
>>>>> Date: Sun Mar 19 20:32:20 2023 -0400
>>>>>
>>>>> platform/x86: think-lmi: only display possible_values if available
>>>>>
>>>>> commit 45e21289bfc6e257885514790a8a8887da822d40
>>>>> Author: Mark Pearson <mpearson-lenovo@xxxxxxxxx>
>>>>> Date: Sun Mar 19 20:32:19 2023 -0400
>>>>>
>>>>> platform/x86: think-lmi: use correct possible_values delimiters
>>>>>
>>>>> commit 583329dcf22e568a328a944f20427ccfc95dce01
>>>>> Author: Mark Pearson <mpearson-lenovo@xxxxxxxxx>
>>>>> Date: Sun Mar 19 20:32:18 2023 -0400
>>>>>
>>>>> platform/x86: think-lmi: add missing type attribute
>>>>>
>>>>> I have CC:-ed the author of the commits.
>>>>>
>>>>> I can try bisect, but only after my day job.
>>>> I seem to have been right about the culprit commit.
>>>> Here is the bisect log:
>>>> mtodorov@domac:~/linux/kernel/linux_torvalds$ git bisect log
>>>> git bisect start '--' './drivers/platform/x86'
>>>> # good: [caa0708a81d6a2217c942959ef40d515ec1d3108] bootconfig: Change message if no bootconfig with CONFIG_BOOT_CONFIG_FORCE=y
>>>> git bisect good caa0708a81d6a2217c942959ef40d515ec1d3108
>>>> # bad: [8a02d70679fc1c434401863333c8ea7dbf201494] platform/x86: think-lmi: Add possible_values for ThinkStation
>>>> git bisect bad 8a02d70679fc1c434401863333c8ea7dbf201494
>>>> # good: [1a0009abfa7893b9cfcd3884658af1cbee6b26ce] platform: mellanox: mlx-platform: Initialize shift variable to 0
>>>> git bisect good 1a0009abfa7893b9cfcd3884658af1cbee6b26ce
>>>> # good: [b7c994f8c35e916e27c60803bb21457bc1373500] platform/x86 (gigabyte-wmi): Add support for A320M-S2H V2
>>>> git bisect good b7c994f8c35e916e27c60803bb21457bc1373500
>>>> # good: [45e21289bfc6e257885514790a8a8887da822d40] platform/x86: think-lmi: use correct possible_values delimiters
>>>> git bisect good 45e21289bfc6e257885514790a8a8887da822d40
>>>> # good: [cf337f27f3bfc4aeab4954c468239fd6233c7638] platform/x86: think-lmi: only display possible_values if available
>>>> git bisect good cf337f27f3bfc4aeab4954c468239fd6233c7638
>>>> # first bad commit: [8a02d70679fc1c434401863333c8ea7dbf201494] platform/x86: think-lmi: Add possible_values for ThinkStation
>>>> mtodorov@domac:~/linux/kernel/linux_torvalds$
>>>> Please see below.
>>>> Apparently, this commit broke something on my Lenovo box:
>>>> diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c
>>>> index e190fec26021..3f0641360251 100644
>>>> --- a/drivers/platform/x86/think-lmi.c
>>>> +++ b/drivers/platform/x86/think-lmi.c
>>>> @@ -941,9 +941,6 @@ static ssize_t possible_values_show(struct kobject *kobj, struct kobj_attribute
>>>> {
>>>> struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
>>>> - if (!tlmi_priv.can_get_bios_selections)
>>>> - return -EOPNOTSUPP;
>>>> -
>>>> return sysfs_emit(buf, "%s\n", setting->possible_values);
>>>> }
>>>> @@ -1052,6 +1049,18 @@ static struct kobj_attribute attr_current_val = __ATTR_RW_MODE(current_value, 06
>>>> static struct kobj_attribute attr_type = __ATTR_RO(type);
>>>> +static umode_t attr_is_visible(struct kobject *kobj,
>>>> + struct attribute *attr, int n)
>>>> +{
>>>> + struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
>>>> +
>>>> + /* We don't want to display possible_values attributes if not available */
>>>> + if ((attr == &attr_possible_values.attr) && (!setting->possible_values))
>>>> + return 0;
>>>> +
>>>> + return attr->mode;
>>>> +}
>>>> +
>>>> static struct attribute *tlmi_attrs[] = {
>>>> &attr_displ_name.attr,
>>>> &attr_current_val.attr,
>>>> @@ -1061,6 +1070,7 @@ static struct attribute *tlmi_attrs[] = {
>>>> };
>>>> static const struct attribute_group tlmi_attr_group = {
>>>> + .is_visible = attr_is_visible,
>>>> .attrs = tlmi_attrs,
>>>> };
>>>> Hope this helps narrow down the problem.
>>>> Best regards,
>>>> Mirsad
>>>> Why aren't you looking at the wmi.c driver? That should be
>>>>>>>> …
>>>
>>> mtodorov@domac:~/linux/kernel/linux_torvalds$ git bisect log
>>> git bisect start '--' './drivers/platform/x86'
>>> # good: [caa0708a81d6a2217c942959ef40d515ec1d3108] bootconfig: Change message if no bootconfig with CONFIG_BOOT_CONFIG_FORCE=y
>>> git bisect good caa0708a81d6a2217c942959ef40d515ec1d3108
>>> # bad: [8a02d70679fc1c434401863333c8ea7dbf201494] platform/x86: think-lmi: Add possible_values for ThinkStation
>>> git bisect bad 8a02d70679fc1c434401863333c8ea7dbf201494
>>> # good: [1a0009abfa7893b9cfcd3884658af1cbee6b26ce] platform: mellanox: mlx-platform: Initialize shift variable to 0
>>> git bisect good 1a0009abfa7893b9cfcd3884658af1cbee6b26ce
>>> # good: [b7c994f8c35e916e27c60803bb21457bc1373500] platform/x86 (gigabyte-wmi): Add support for A320M-S2H V2
>>> git bisect good b7c994f8c35e916e27c60803bb21457bc1373500
>>> # good: [45e21289bfc6e257885514790a8a8887da822d40] platform/x86: think-lmi: use correct possible_values delimiters
>>> git bisect good 45e21289bfc6e257885514790a8a8887da822d40
>>> # good: [cf337f27f3bfc4aeab4954c468239fd6233c7638] platform/x86: think-lmi: only display possible_values if available
>>> git bisect good cf337f27f3bfc4aeab4954c468239fd6233c7638
>>> # first bad commit: [8a02d70679fc1c434401863333c8ea7dbf201494] platform/x86: think-lmi: Add possible_values for ThinkStation
>>> mtodorov@domac:~/linux/kernel/linux_torvalds$
>>>
>>> So the commit that triggered the bug on the Lenovo desktop box was:
>>>
>>> diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c
>>> index 3f0641360251..c816646eb661 100644
>>> --- a/drivers/platform/x86/think-lmi.c
>>> +++ b/drivers/platform/x86/think-lmi.c
>>> @@ -1450,6 +1450,26 @@ static int tlmi_analyze(void)
>>> if (ret || !setting->possible_values)
>>> pr_info("Error retrieving possible values for %d : %s\n",
>>> i, setting->display_name);
>>> + } else {
>>> + /*
>>> + * Older Thinkstations don't support the bios_selections API.
>>> + * Instead they store this as a [Optional:Option1,Option2] section of the
>>> + * name string.
>>> + * Try and pull that out if it's available.
>>> + */
>>> + char *item, *optstart, *optend;
>>> +
>>> + if (!tlmi_setting(setting->index, &item, LENOVO_BIOS_SETTING_GUID)) {
>>> + optstart = strstr(item, "[Optional:");
>>> + if (optstart) {
>>> + optstart += strlen("[Optional:");
>>> + optend = strstr(optstart, "]");
>>> + if (optend)
>>> + setting->possible_values =
>>> + kstrndup(optstart, optend - optstart,
>>> + GFP_KERNEL);
>>
>> I guess item needs to be freed here.
>>
>> (Next week I have access to my Lenovo machine again.
>> I'll look at it then if it's not solved.)
>
> Yes, thank you, Thomas, I am just building with the following patch:
>
> diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c
> index c816646eb661..e8c28f4f5a71 100644
> --- a/drivers/platform/x86/think-lmi.c
> +++ b/drivers/platform/x86/think-lmi.c
> @@ -1469,6 +1469,7 @@ static int tlmi_analyze(void)
> kstrndup(optstart, optend - optstart,
> GFP_KERNEL);
> }
> + kfree(item);
> }
> }
> /*
>
> You were 3 minutes faster ;-)
>
> The build with this patch is finished. Apparently, that was the culprit, for now
> I get:
>
> [root@pc-mtodorov marvin]# cat /sys/kernel/debug/kmemleak
> unreferenced object 0xffff8fa859c89f10 (size 16):
> comm "kworker/u12:5", pid 369, jiffies 4294897651 (age 91.724s)
> hex dump (first 16 bytes):
> 6d 65 6d 73 74 69 63 6b 30 00 cc cc cc cc cc cc memstick0.......
> backtrace:
> [<ffffffff8ef0a8fc>] slab_post_alloc_hook+0x8c/0x3e0
> [<ffffffff8ef12289>] __kmem_cache_alloc_node+0x1d9/0x2a0
> [<ffffffff8ee85719>] __kmalloc_node_track_caller+0x59/0x1f0
> [<ffffffff8ee749da>] kstrdup+0x3a/0x70
> [<ffffffff8ee74a4c>] kstrdup_const+0x2c/0x40
> [<ffffffff8f2c0a3c>] kvasprintf_const+0x7c/0xb0
> [<ffffffff8fc5f427>] kobject_set_name_vargs+0x27/0xa0
> [<ffffffff8f5a79f7>] dev_set_name+0x57/0x80
> [<ffffffffc0cd2f0f>] memstick_check+0x10f/0x3b0 [memstick]
> [<ffffffff8ebd41d0>] process_one_work+0x250/0x600
> [<ffffffff8ebd45d8>] worker_thread+0x48/0x3a0
> [<ffffffff8ebdfdef>] kthread+0x10f/0x140
> [<ffffffff8ea03089>] ret_from_fork+0x29/0x50
> unreferenced object 0xffff8fa859c89d90 (size 16):
> comm "kworker/u12:5", pid 369, jiffies 4294897656 (age 91.704s)
> hex dump (first 16 bytes):
> 6d 65 6d 73 74 69 63 6b 30 00 cc cc cc cc cc cc memstick0.......
> backtrace:
> [<ffffffff8ef0a8fc>] slab_post_alloc_hook+0x8c/0x3e0
> [<ffffffff8ef12289>] __kmem_cache_alloc_node+0x1d9/0x2a0
> [<ffffffff8ee85719>] __kmalloc_node_track_caller+0x59/0x1f0
> [<ffffffff8ee749da>] kstrdup+0x3a/0x70
> [<ffffffff8ee74a4c>] kstrdup_const+0x2c/0x40
> [<ffffffff8f2c0a3c>] kvasprintf_const+0x7c/0xb0
> [<ffffffff8fc5f427>] kobject_set_name_vargs+0x27/0xa0
> [<ffffffff8f5a79f7>] dev_set_name+0x57/0x80
> [<ffffffffc0cd2f0f>] memstick_check+0x10f/0x3b0 [memstick]
> [<ffffffff8ebd41d0>] process_one_work+0x250/0x600
> [<ffffffff8ebd45d8>] worker_thread+0x48/0x3a0
> [<ffffffff8ebdfdef>] kthread+0x10f/0x140
> [<ffffffff8ea03089>] ret_from_fork+0x29/0x50
> [root@pc-mtodorov marvin]#
>
> So, the "tlmi_setting" memory leak appears to be fixed by this diff.
>
> The next step is to add Armin-suggested patch:
>
> diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c
> index c816646eb661..1e77ecb0cba8 100644
> --- a/drivers/platform/x86/think-lmi.c
> +++ b/drivers/platform/x86/think-lmi.c
> @@ -929,8 +929,10 @@ static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *a
>
> /* validate and split from `item,value` -> `value` */
> value = strpbrk(item, ",");
> - if (!value || value == item || !strlen(value + 1))
> + if (!value || value == item || !strlen(value + 1)) {
> + kfree(item);
> return -EINVAL;
> + }
>
> ret = sysfs_emit(buf, "%s\n", value + 1);
> kfree(item);
>
> and Thomas' correction for the return type of the tlmi_setting() function:
>
> diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c
> index 86b33b74519be..c924e9e4a6a5b 100644
> --- a/drivers/platform/x86/think-lmi.c
> +++ b/drivers/platform/x86/think-lmi.c
> @@ -1353,7 +1353,6 @@ static struct tlmi_pwd_setting *tlmi_create_auth(const char *pwd_type,
>
> static int tlmi_analyze(void)
> {
> - acpi_status status;
> int i, ret;
>
> if (wmi_has_guid(LENOVO_SET_BIOS_SETTINGS_GUID) &&
> @@ -1390,8 +1389,8 @@ static int tlmi_analyze(void)
> char *p;
>
> tlmi_priv.setting[i] = NULL;
> - status = tlmi_setting(i, &item, LENOVO_BIOS_SETTING_GUID);
> - if (ACPI_FAILURE(status))
> + ret = tlmi_setting(i, &item, LENOVO_BIOS_SETTING_GUID);
> + if (ret)
> break;
> if (!item)
> break;
>
> A build on top of 6.3-rc4+ fcd476ea6a88 commit is on the way, with all three included.
Good work on catching these issues, thank you all for your work on this.
I assume that these fixes will be posted as a proper 3 patch
patch-series (one patch per fix) once you are done testing?
Regards,
Hans