From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pf1-f182.google.com (mail-pf1-f182.google.com [209.85.210.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 246E8288B8 for ; Wed, 15 Apr 2026 03:17:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.182 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776223074; cv=none; b=AJM8Z6r6haDC6Q071TK4mVAQIb8cczYMcHkNIjbCGKmpWHwCdcGr49c5sZRJmqSTBLnFO4N2Ky7HFn/YpQeBG0hhHUtstZefzVw84y5gQiJ1EHIkWyWWvQtR5G601E81TkwBYctDXxUKXmmkX8CBPdB+H2yEJ/VU1yfYVk3qUoc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776223074; c=relaxed/simple; bh=T4Ghe2c7fSFbmSl2w/hfc5FFF+awiXu3PdaD4faJT7g=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=UTF+EaBjcswckApGAFCNR05+1fmWYtqFOPA5LUNZy504hLqu2V6pAe7weRygFfGt77jNFVLKGQuCL651eNBdgdF5YUB+R2BHHhS+n7u0AciZOVV2QCWj2AFfaYBoq969MkepmIADUgvWSKygee/7l+sHjIduRNhk0KRZyrfCtbw= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=MwDNx5so; arc=none smtp.client-ip=209.85.210.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="MwDNx5so" Received: by mail-pf1-f182.google.com with SMTP id d2e1a72fcca58-82418b0178cso3246368b3a.1 for ; Tue, 14 Apr 2026 20:17:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776223072; x=1776827872; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Bw6zrmhzVgl0erKx0cVU8q8Z5LVFJZ2NKhxP0jYrwQM=; b=MwDNx5soOkMqzlZ8mJ4VIyr3MeMR4FvG+wPhbXxHe68HaoIUwOsm4nlRj9tGJyNEb7 qExgijPUS0ArpZISSHrXB+AxVlQHIe5npWnkJgXBvEwebkojISpdaAfULFWvXnsP8ZT1 Uze1w5NWKc2RjSdY11UP7N8edY0UokgRRH32lXA64CghYAbm0gGipcnyw6NDdp4durxd HWz9hAxN87d9CvNYsy3EfqDFO36cudnhqKY14lVYOJBxMTcqjAELssovMCszwFuL4UNC /ZlHfWaFHoEjKtUifqA9Nzg3WogZZT8BoyUcyR0gVQkml6zCafEoK/oFTqdHQRPNOE5N wkrQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776223072; x=1776827872; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Bw6zrmhzVgl0erKx0cVU8q8Z5LVFJZ2NKhxP0jYrwQM=; b=JoHMgC6z8xzB6RMRFxqcWYVbI3l8nZxL0tB3/6MsRXzPH5khBi/TTTnIfiSPymi8hE nCRo0a2aSHhnFZa+kN+5xgg/Kgz9yWceigOiSOoN4lVW46bQplt4V67jvsRfuD9PsRrr 6vy+nerbA2rKQVmFzHiFJu+ji/KMvZY0EMqO19scJu2EAXD4RspHovZ+eDGOXeVafahW +uNjUdGic0iAjydDBT/sFheUC6mAkBJQ02Au4xPjXXo1PyUyHu/WOCtpT6Gf/FbDREON Ds9nsrIosSfPo2xkWpDUiVe+/RMubqZe7raQO+DsO7LllNoILDnbUHFP3UTraWVMOWde /l+A== X-Forwarded-Encrypted: i=1; AFNElJ9Mca7b3gxC3ML+HDdEF2UB556iFrFBh1xSu4uQuZS7r3Zn6QJ77SqFUwUhw0huOdVehhES+lFVdfZqE7Y=@vger.kernel.org X-Gm-Message-State: AOJu0Ywxf401o9ydD4XgmJoju1DIRRxQQkvQJdyTwiKIkgwrTYjCZSCV Z4KchTXZRO9vUrV9IHF2M52sdULHeVTSZnNVf6IsxAnqKxL8/XpRTCJz X-Gm-Gg: AeBDievWfJMqWA2XlIsF6bpeO9DD8KyRa7/lO/wpmNyavBsfT721J1bFMCC/z6bpWAD r2qdimC/tVEVAYKZ0n33jXy3LoS91gQ8vvchLkcvzayYhp6SqTvddFqYm0wcJVCAunU/+r0aG0B GrVpTVOMCGdM9ltxR67rNgYVXxZivT9bwkSLe9zqXECNDrDRJ9imyTsaMkYAMhuy9QWVExrZKuh Pn36W+NekAr9uFXZJbg6l/6z9O28srE1tQNzNE5fJILwg8ITNhACCM+yMned8Jx8rTZDeu57ypa 74ILigWc0UhJlOsma70ZvlzlBcS5M8dKUksUtOntwmaLF5NeOvbMBToruQqKGPCGuZg4ZX0gkIp 8946LytoX0ZdEK/zeWghrHWRVSssHPbpVD2cDC4dwJULq32U3vBkhJMOeytyzJF2oCBUfQ2RHeY yMgR+CacutkHJsP43g8XvnwTQYw8NelCJ+wdQ23zQyGh3qZD8= X-Received: by 2002:a05:6a00:3e07:b0:82f:33ed:88a7 with SMTP id d2e1a72fcca58-82f33ed8a79mr12518419b3a.2.1776223072281; Tue, 14 Apr 2026 20:17:52 -0700 (PDT) Received: from home-hyperv.mshome.net ([103.136.124.6]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f673e0ca3sm504273b3a.30.2026.04.14.20.17.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Apr 2026 20:17:51 -0700 (PDT) From: "Kito Xu (veritas501)" To: gregkh@linuxfoundation.org, jirislaby@kernel.org Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, "Kito Xu (veritas501)" Subject: [PATCH] tty: n_gsm: fix use-after-free in gsmtty_install Date: Wed, 15 Apr 2026 11:17:31 +0800 Message-Id: <20260415031731.107667-1-hxzene@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260415024846.2918702-1-hxzene@gmail.com> References: <20260415024846.2918702-1-hxzene@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit gsmtty_install() reads gsm_mux[] without holding gsm_mux_lock and defers mux_get() about 40 lines later. A concurrent gsmld_close() can free the mux through gsm_cleanup_mux() -> mux_put() -> kfree(gsm) in that window, leading to a use-after-free when gsmtty_install() later dereferences the stale pointer. race condition: cpu 0 | cpu 1 gsmtty_install() | gsmld_close() gsm = gsm_mux[mux] // no lock | // CFS preempts here | gsm_cleanup_mux(gsm) | gsm->dead = true | mux_put(gsm) | -> kfree(gsm) gsm->dead // UAF! | mutex_lock(&gsm->mutex) // UAF! | KASAN report: BUG: KASAN: slab-use-after-free in gsmtty_install+0x6cf/0x830 Read of size 1 at addr ffff88800fd440ac by task poc/170 CPU: 0 UID: 0 PID: 170 Comm: poc Not tainted 7.0.0-rc7-next-20260410+ #20 Call Trace: dump_stack_lvl+0x64/0x80 print_report+0xd0/0x5e0 kasan_report+0xce/0x100 gsmtty_install+0x6cf/0x830 tty_init_dev.part.0+0x92/0x4a0 tty_open+0x8ab/0x1050 chrdev_open+0x1ec/0x5e0 do_dentry_open+0x419/0x1260 vfs_open+0x79/0x350 path_openat+0x212c/0x3a70 do_file_open+0x1d2/0x400 do_sys_openat2+0xdc/0x170 __x64_sys_openat+0x122/0x1e0 do_syscall_64+0x64/0x680 entry_SYSCALL_64_after_hwframe+0x76/0x7e Allocated by task 169 on cpu 0 at 3.824684s: Freed by task 169 on cpu 0 at 3.892012s: The buggy address belongs to the object at ffff88800fd44000 which belongs to the cache kmalloc-1k of size 1024 The buggy address is located 172 bytes inside of freed 1024-byte region [ffff88800fd44000, ffff88800fd44400) Acquire gsm_mux_lock before reading gsm_mux[] and take the refcount via kref_get() while still holding the lock, so the mux cannot be freed between lookup and refcount increment. Fixes: 86176ed90545 ("TTY: n_gsm, use tty_port_install") Signed-off-by: Kito Xu (veritas501) --- drivers/tty/n_gsm.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index c13e050de83b..6519f1c92fc5 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -4288,14 +4288,20 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty) if (mux >= MAX_MUX) return -ENXIO; - /* FIXME: we need to lock gsm_mux for lifetimes of ttys eventually */ - if (gsm_mux[mux] == NULL) - return -EUNATCH; if (line == 0 || line > 61) /* 62/63 reserved */ return -ECHRNG; + + /* Acquire gsm_mux_lock to prevent concurrent gsmld_close() from + * freeing the mux between reading gsm_mux[] and taking a refcount. + */ + spin_lock(&gsm_mux_lock); gsm = gsm_mux[mux]; - if (gsm->dead) - return -EL2HLT; + if (!gsm || gsm->dead) { + spin_unlock(&gsm_mux_lock); + return gsm ? -EL2HLT : -EUNATCH; + } + kref_get(&gsm->ref); + spin_unlock(&gsm_mux_lock); /* If DLCI 0 is not yet fully open return an error. This is ok from a locking perspective as we don't have to worry about this @@ -4309,8 +4315,10 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty) if (dlci0->state == DLCI_OPENING) wait_event(gsm->event, dlci0->state != DLCI_OPENING); - if (dlci0->state != DLCI_OPEN) + if (dlci0->state != DLCI_OPEN) { + mux_put(gsm); return -EL2NSYNC; + } mutex_lock(&gsm->mutex); } @@ -4322,6 +4330,7 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty) } if (dlci == NULL) { mutex_unlock(&gsm->mutex); + mux_put(gsm); return -ENOMEM; } ret = tty_port_install(&dlci->port, driver, tty); @@ -4329,12 +4338,12 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty) if (alloc) dlci_put(dlci); mutex_unlock(&gsm->mutex); + mux_put(gsm); return ret; } dlci_get(dlci); dlci_get(gsm->dlci[0]); - mux_get(gsm); tty->driver_data = dlci; mutex_unlock(&gsm->mutex); -- 2.43.0