Received: by 2002:a05:6a10:5bc5:0:0:0:0 with SMTP id os5csp4264884pxb; Thu, 14 Oct 2021 01:49:04 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw4h9dle1cyFWXPuLQ2yE6KGEY3hiDoRqvftqUa6WmZnt8vopNRTYqOD73gvDK1sn7Gew2P X-Received: by 2002:a17:90b:4a05:: with SMTP id kk5mr4856493pjb.25.1634201344193; Thu, 14 Oct 2021 01:49:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1634201344; cv=none; d=google.com; s=arc-20160816; b=C9OwjQBrgVBT8EldDri6yyQIhJQDVSeQ0Q704DZtmfBwAXDn6NlUQSmOFw2+hxTBiF 6cHSEZDUFuZKugcJ5IEAS/2UaDqDnHW8u786NQbkqSTub5au0ujy+6KvaaachL5fkxIB 46wgASlIyS3+V2Ise10YTjei/2cS4BLL9GY1Mbg+W75nEZw2i2+dDr+RHkkd1eDL8lUP fVMBk+jAh8W0alat2BnLi3fMmHlaFaaaSKaJ08tFUlZFg1vipJJuNkBmMi6SiYVy5K+U 2OMa+T/xPQ78c+AI+zdKAJ8ODR5BLVACxmo2rECYp948UibftSQQ7HTFXOOZw1V3V5Pj SZQQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from; bh=RuQfY84JiUHeB6iOu1Bwgh1aQ5L2OoXngamitTFEg7Q=; b=zrzMeko86OFJRmQmNC9qZArnS3ukjTdi4apYXpdqJ973m7YGykyyxxaPbUV6HcWmeH wg0JTlic5Z4NHs5KbhRpBySF6XGDIXORxAineKc08MPZirCKMhx2ELbdWw6aQ8lbOVI3 f2m5YLvpuia3EozaQbdBokWVALTrVHhx5i6gNO9trUuJ2EXOLq4RR37eXk4RJxPny590 oQLsEfbG7kgRWqUIAc+AY0wLVE86xAgYCzGhsRLRz+Kp/fav/ZhmANqZZON7XIgHMrwW f7pf/TVG3m2OxhzriOOPJyGUZBbOHNvjwWgSWuR0RMzst7rKe0IREMOSM9Z5wTYK5Ke+ r35w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=huawei.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id u1si2906180pfl.167.2021.10.14.01.48.51; Thu, 14 Oct 2021 01:49:04 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=huawei.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229912AbhJNIuC (ORCPT + 99 others); Thu, 14 Oct 2021 04:50:02 -0400 Received: from szxga02-in.huawei.com ([45.249.212.188]:14351 "EHLO szxga02-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229551AbhJNIuB (ORCPT ); Thu, 14 Oct 2021 04:50:01 -0400 Received: from dggeml757-chm.china.huawei.com (unknown [172.30.72.55]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4HVNG029Sfz8yqy; Thu, 14 Oct 2021 16:43:04 +0800 (CST) Received: from localhost.localdomain (10.175.104.82) by dggeml757-chm.china.huawei.com (10.1.199.137) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2308.8; Thu, 14 Oct 2021 16:47:54 +0800 From: Ziyang Xuan To: , CC: , , Subject: [PATCH] thermal/core: fix a UAF bug in __thermal_cooling_device_register() Date: Thu, 14 Oct 2021 16:47:00 +0800 Message-ID: <20211014084700.202420-1-william.xuanziyang@huawei.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Content-Transfer-Encoding: 7BIT Content-Type: text/plain; charset=US-ASCII X-Originating-IP: [10.175.104.82] X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) To dggeml757-chm.china.huawei.com (10.1.199.137) X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When device_register() return failed, program will goto out_kfree_type to release 'cdev->device' by put_device(). That will call thermal_release() to free 'cdev'. But the follow-up processes access 'cdev' continually. That trggers the UAF bug. ==================================================================== BUG: KASAN: use-after-free in __thermal_cooling_device_register+0x75b/0xa90 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014 Call Trace: dump_stack_lvl+0xe2/0x152 print_address_description.constprop.0+0x21/0x140 ? __thermal_cooling_device_register+0x75b/0xa90 kasan_report.cold+0x7f/0x11b ? __thermal_cooling_device_register+0x75b/0xa90 __thermal_cooling_device_register+0x75b/0xa90 ? memset+0x20/0x40 ? __sanitizer_cov_trace_pc+0x1d/0x50 ? __devres_alloc_node+0x130/0x180 devm_thermal_of_cooling_device_register+0x67/0xf0 max6650_probe.cold+0x557/0x6aa ...... Freed by task 258: kasan_save_stack+0x1b/0x40 kasan_set_track+0x1c/0x30 kasan_set_free_info+0x20/0x30 __kasan_slab_free+0x109/0x140 kfree+0x117/0x4c0 thermal_release+0xa0/0x110 device_release+0xa7/0x240 kobject_put+0x1ce/0x540 put_device+0x20/0x30 __thermal_cooling_device_register+0x731/0xa90 devm_thermal_of_cooling_device_register+0x67/0xf0 max6650_probe.cold+0x557/0x6aa [max6650] Do not use 'cdev' again after put_device() to fix the problem like doing in thermal_zone_device_register(). Fixes: 584837618100 ("thermal/drivers/core: Use a char pointer for the cooling device name") Signed-off-by: Ziyang Xuan --- drivers/thermal/thermal_core.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 97ef9b040b84..ee7453944ccb 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -888,7 +888,7 @@ __thermal_cooling_device_register(struct device_node *np, { struct thermal_cooling_device *cdev; struct thermal_zone_device *pos = NULL; - int ret; + int id, ret; if (!ops || !ops->get_max_state || !ops->get_cur_state || !ops->set_cur_state) @@ -898,10 +898,10 @@ __thermal_cooling_device_register(struct device_node *np, if (!cdev) return ERR_PTR(-ENOMEM); - ret = ida_simple_get(&thermal_cdev_ida, 0, 0, GFP_KERNEL); - if (ret < 0) + id = ida_simple_get(&thermal_cdev_ida, 0, 0, GFP_KERNEL); + if (id < 0) goto out_kfree_cdev; - cdev->id = ret; + cdev->id = id; cdev->type = kstrdup(type ? type : "", GFP_KERNEL); if (!cdev->type) { @@ -942,8 +942,9 @@ __thermal_cooling_device_register(struct device_node *np, out_kfree_type: kfree(cdev->type); put_device(&cdev->device); + cdev = NULL; out_ida_remove: - ida_simple_remove(&thermal_cdev_ida, cdev->id); + ida_simple_remove(&thermal_cdev_ida, id); out_kfree_cdev: kfree(cdev); return ERR_PTR(ret); -- 2.25.1