All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 5.10 0/3] tty: n_gsm: fix tty registration before control channel open
@ 2023-12-12 11:17 Gavrilov Ilia
  2023-12-12 11:17 ` [PATCH 5.10 2/3] tty: n_gsm, remove duplicates of parameters Gavrilov Ilia
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Gavrilov Ilia @ 2023-12-12 11:17 UTC (permalink / raw)
  To: stable, Greg Kroah-Hartman
  Cc: Daniel Starke, Jiri Slaby, Russ Gorby, linux-kernel, lvc-project

Syzkaller reports memory leak issue at gsmld_attach_gsm() in
5.10 stable releases. The reproducer injects the memory allocation
errors to tty_register_device(); as a result, tty_kref_get() isn't called
after this error, which leads to tty_struct leak.
The issue has been fixed by the following patches that can be cleanly
applied to the 5.10 branch.

Found by InfoTeCS on behalf of Linux Verification Center
(linuxtesting.org) with Syzkaller

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 5.10 1/3] tty: n_gsm: fix tty registration before control channel open
  2023-12-12 11:17 [PATCH 5.10 0/3] tty: n_gsm: fix tty registration before control channel open Gavrilov Ilia
  2023-12-12 11:17 ` [PATCH 5.10 2/3] tty: n_gsm, remove duplicates of parameters Gavrilov Ilia
@ 2023-12-12 11:17 ` Gavrilov Ilia
  2023-12-12 11:17 ` [PATCH 5.10 3/3] tty: n_gsm: add sanity check for gsm->receive in gsm_receive_buf() Gavrilov Ilia
  2023-12-12 11:44 ` [PATCH 5.10 0/3] tty: n_gsm: fix tty registration before control channel open Greg Kroah-Hartman
  3 siblings, 0 replies; 7+ messages in thread
From: Gavrilov Ilia @ 2023-12-12 11:17 UTC (permalink / raw)
  To: stable, Greg Kroah-Hartman
  Cc: Daniel Starke, Jiri Slaby, Russ Gorby, linux-kernel, lvc-project

From: Daniel Starke <daniel.starke@siemens.com>

commit 01aecd917114577c423f07cec0d186ad007d76fc upstream.

The current implementation registers/deregisters the user ttys at mux
attach/detach. That means that the user devices are available before any
control channel is open. However, user channel initialization requires an
open control channel. Furthermore, the user is not informed if the mux
restarts due to configuration changes.
Put the registration/deregistration procedure into separate function to
improve readability.
Move registration to mux activation and deregistration to mux cleanup to
keep the user devices only open as long as a control channel exists. The
user will be informed via the device driver if the mux was reconfigured in
a way that required a mux re-activation.
This makes it necessary to add T2 initialization to gsmld_open() for the
ldisc open code path (not the reconfiguration code path) to avoid deletion
of an uninitialized T2 at mux cleanup.

Fixes: d50f6dcaf22a ("tty: n_gsm: expose gsmtty device nodes at ldisc open time")
Signed-off-by: Daniel Starke <daniel.starke@siemens.com>
Link: https://lore.kernel.org/r/20220701061652.39604-2-daniel.starke@siemens.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Gavrilov Ilia <Ilia.Gavrilov@infotecs.ru>
---
 drivers/tty/n_gsm.c | 117 ++++++++++++++++++++++++++++++--------------
 1 file changed, 79 insertions(+), 38 deletions(-)

diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 3693ad9f4521..7a883a2c0c50 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -235,6 +235,7 @@ struct gsm_mux {
 	struct gsm_dlci *dlci[NUM_DLCI];
 	int old_c_iflag;		/* termios c_iflag value before attach */
 	bool constipated;		/* Asked by remote to shut up */
+	bool has_devices;		/* Devices were registered */
 
 	spinlock_t tx_lock;
 	unsigned int tx_bytes;		/* TX data outstanding */
@@ -464,6 +465,68 @@ static u8 gsm_encode_modem(const struct gsm_dlci *dlci)
 	return modembits;
 }
 
+/**
+ *	gsm_register_devices	-	register all tty devices for a given mux index
+ *
+ *	@driver: the tty driver that describes the tty devices
+ *	@index:  the mux number is used to calculate the minor numbers of the
+ *	         ttys for this mux and may differ from the position in the
+ *	         mux array.
+ */
+static int gsm_register_devices(struct tty_driver *driver, unsigned int index)
+{
+	struct device *dev;
+	int i;
+	unsigned int base;
+
+	if (!driver || index >= MAX_MUX)
+		return -EINVAL;
+
+	base = index * NUM_DLCI; /* first minor for this index */
+	for (i = 1; i < NUM_DLCI; i++) {
+		/* Don't register device 0 - this is the control channel
+		 * and not a usable tty interface
+		 */
+		dev = tty_register_device(gsm_tty_driver, base + i, NULL);
+		if (IS_ERR(dev)) {
+			if (debug & 8)
+				pr_info("%s failed to register device minor %u",
+					__func__, base + i);
+			for (i--; i >= 1; i--)
+				tty_unregister_device(gsm_tty_driver, base + i);
+			return PTR_ERR(dev);
+		}
+	}
+
+	return 0;
+}
+
+/**
+ *	gsm_unregister_devices	-	unregister all tty devices for a given mux index
+ *
+ *	@driver: the tty driver that describes the tty devices
+ *	@index:  the mux number is used to calculate the minor numbers of the
+ *	         ttys for this mux and may differ from the position in the
+ *	         mux array.
+ */
+static void gsm_unregister_devices(struct tty_driver *driver,
+				   unsigned int index)
+{
+	int i;
+	unsigned int base;
+
+	if (!driver || index >= MAX_MUX)
+		return;
+
+	base = index * NUM_DLCI; /* first minor for this index */
+	for (i = 1; i < NUM_DLCI; i++) {
+		/* Don't unregister device 0 - this is the control
+		 * channel and not a usable tty interface
+		 */
+		tty_unregister_device(gsm_tty_driver, base + i);
+	}
+}
+
 /**
  *	gsm_print_packet	-	display a frame for debug
  *	@hdr: header to print before decode
@@ -2178,6 +2241,10 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
 	del_timer_sync(&gsm->t2_timer);
 
 	/* Free up any link layer users and finally the control channel */
+	if (gsm->has_devices) {
+		gsm_unregister_devices(gsm_tty_driver, gsm->num);
+		gsm->has_devices = false;
+	}
 	for (i = NUM_DLCI - 1; i >= 0; i--)
 		if (gsm->dlci[i])
 			gsm_dlci_release(gsm->dlci[i]);
@@ -2201,15 +2268,21 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
 static int gsm_activate_mux(struct gsm_mux *gsm)
 {
 	struct gsm_dlci *dlci;
+	int ret;
 
 	if (gsm->encoding == 0)
 		gsm->receive = gsm0_receive;
 	else
 		gsm->receive = gsm1_receive;
 
+	ret = gsm_register_devices(gsm_tty_driver, gsm->num);
+	if (ret)
+		return ret;
+
 	dlci = gsm_dlci_alloc(gsm, 0);
 	if (dlci == NULL)
 		return -ENOMEM;
+	gsm->has_devices = true;
 	gsm->dead = false;		/* Tty opens are now permissible */
 	return 0;
 }
@@ -2475,39 +2548,14 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len)
  *	will need moving to an ioctl path.
  */
 
-static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
+static void gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
 {
-	unsigned int base;
-	int ret, i;
-
 	gsm->tty = tty_kref_get(tty);
 	/* Turn off tty XON/XOFF handling to handle it explicitly. */
 	gsm->old_c_iflag = tty->termios.c_iflag;
 	tty->termios.c_iflag &= (IXON | IXOFF);
-	ret =  gsm_activate_mux(gsm);
-	if (ret != 0)
-		tty_kref_put(gsm->tty);
-	else {
-		/* Don't register device 0 - this is the control channel and not
-		   a usable tty interface */
-		base = mux_num_to_base(gsm); /* Base for this MUX */
-		for (i = 1; i < NUM_DLCI; i++) {
-			struct device *dev;
-
-			dev = tty_register_device(gsm_tty_driver,
-							base + i, NULL);
-			if (IS_ERR(dev)) {
-				for (i--; i >= 1; i--)
-					tty_unregister_device(gsm_tty_driver,
-								base + i);
-				return PTR_ERR(dev);
-			}
-		}
-	}
-	return ret;
 }
 
-
 /**
  *	gsmld_detach_gsm	-	stop doing 0710 mux
  *	@tty: tty attached to the mux
@@ -2518,12 +2566,7 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
 
 static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
 {
-	unsigned int base = mux_num_to_base(gsm); /* Base for this MUX */
-	int i;
-
 	WARN_ON(tty != gsm->tty);
-	for (i = 1; i < NUM_DLCI; i++)
-		tty_unregister_device(gsm_tty_driver, base + i);
 	/* Restore tty XON/XOFF handling. */
 	gsm->tty->termios.c_iflag = gsm->old_c_iflag;
 	tty_kref_put(gsm->tty);
@@ -2619,7 +2662,6 @@ static void gsmld_close(struct tty_struct *tty)
 static int gsmld_open(struct tty_struct *tty)
 {
 	struct gsm_mux *gsm;
-	int ret;
 
 	if (tty->ops->write == NULL)
 		return -EINVAL;
@@ -2635,12 +2677,11 @@ static int gsmld_open(struct tty_struct *tty)
 	/* Attach the initial passive connection */
 	gsm->encoding = 1;
 
-	ret = gsmld_attach_gsm(tty, gsm);
-	if (ret != 0) {
-		gsm_cleanup_mux(gsm, false);
-		mux_put(gsm);
-	}
-	return ret;
+	gsmld_attach_gsm(tty, gsm);
+
+	timer_setup(&gsm->t2_timer, gsm_control_retransmit, 0);
+
+	return 0;
 }
 
 /**
-- 
2.39.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5.10 3/3] tty: n_gsm: add sanity check for gsm->receive in gsm_receive_buf()
  2023-12-12 11:17 [PATCH 5.10 0/3] tty: n_gsm: fix tty registration before control channel open Gavrilov Ilia
  2023-12-12 11:17 ` [PATCH 5.10 2/3] tty: n_gsm, remove duplicates of parameters Gavrilov Ilia
  2023-12-12 11:17 ` [PATCH 5.10 1/3] tty: n_gsm: fix tty registration before control channel open Gavrilov Ilia
@ 2023-12-12 11:17 ` Gavrilov Ilia
  2023-12-12 15:20   ` [PATCH " kernel test robot
  2023-12-12 11:44 ` [PATCH 5.10 0/3] tty: n_gsm: fix tty registration before control channel open Greg Kroah-Hartman
  3 siblings, 1 reply; 7+ messages in thread
From: Gavrilov Ilia @ 2023-12-12 11:17 UTC (permalink / raw)
  To: stable, Greg Kroah-Hartman
  Cc: Daniel Starke, Jiri Slaby, Russ Gorby, linux-kernel, lvc-project,
	syzbot+e3563f0c94e188366dbb, Mazin Al Haddad

From: Mazin Al Haddad <mazinalhaddad05@gmail.com>

commit f16c6d2e58a4c2b972efcf9eb12390ee0ba3befb upstream

A null pointer dereference can happen when attempting to access the
"gsm->receive()" function in gsmld_receive_buf(). Currently, the code
assumes that gsm->receive is only called after MUX activation.
Since the gsmld_receive_buf() function can be accessed without the need to
initialize the MUX, the gsm->receive() function will not be set and a
NULL pointer dereference will occur.

Fix this by avoiding the call to "gsm->receive()" in case the function is
not initialized by adding a sanity check.

Call Trace:
 <TASK>
 gsmld_receive_buf+0x1c2/0x2f0 drivers/tty/n_gsm.c:2861
 tiocsti drivers/tty/tty_io.c:2293 [inline]
 tty_ioctl+0xa75/0x15d0 drivers/tty/tty_io.c:2692
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:870 [inline]
 __se_sys_ioctl fs/ioctl.c:856 [inline]
 __x64_sys_ioctl+0x193/0x200 fs/ioctl.c:856
 do_syscall_x64 arch/x86/entry/common.c:50 [inline]
 do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80
 entry_SYSCALL_64_after_hwframe+0x63/0xcd

Link: https://syzkaller.appspot.com/bug?id=bdf035c61447f8c6e0e6920315d577cb5cc35ac5
Fixes: 01aecd917114 ("tty: n_gsm: fix tty registration before control channel open")
Reported-and-tested-by: syzbot+e3563f0c94e188366dbb@syzkaller.appspotmail.com
Signed-off-by: Mazin Al Haddad <mazinalhaddad05@gmail.com>
Link: https://lore.kernel.org/r/20220814015211.84180-1-mazinalhaddad05@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Gavrilov Ilia <Ilia.Gavrilov@infotecs.ru>
---
 drivers/tty/n_gsm.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 2455f952e0aa..fa49529682ce 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -2588,7 +2588,8 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 			flags = *fp++;
 		switch (flags) {
 		case TTY_NORMAL:
-			gsm->receive(gsm, *cp);
+			if (gsm->receive)
+				gsm->receive(gsm, *cp);
 			break;
 		case TTY_OVERRUN:
 		case TTY_BREAK:
-- 
2.39.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5.10 2/3] tty: n_gsm, remove duplicates of parameters
  2023-12-12 11:17 [PATCH 5.10 0/3] tty: n_gsm: fix tty registration before control channel open Gavrilov Ilia
@ 2023-12-12 11:17 ` Gavrilov Ilia
  2023-12-12 11:17 ` [PATCH 5.10 1/3] tty: n_gsm: fix tty registration before control channel open Gavrilov Ilia
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Gavrilov Ilia @ 2023-12-12 11:17 UTC (permalink / raw)
  To: stable, Greg Kroah-Hartman
  Cc: Daniel Starke, Jiri Slaby, Russ Gorby, linux-kernel, lvc-project,
	Jiri Slaby

From: Jiri Slaby <jslaby@suse.cz>

commit b93db97e1ca08e500305bc46b08c72e2232c4be1 upstream.

dp, f, and i are only duplicates of gsmld_receive_buf's parameters. Use
the parameters directly (cp, fp, and count) and delete these local
variables.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Link: https://lore.kernel.org/r/20210302062214.29627-41-jslaby@suse.cz
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Gavrilov Ilia <Ilia.Gavrilov@infotecs.ru>
---
 drivers/tty/n_gsm.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 7a883a2c0c50..2455f952e0aa 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -2577,27 +2577,24 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 			      char *fp, int count)
 {
 	struct gsm_mux *gsm = tty->disc_data;
-	const unsigned char *dp;
-	char *f;
-	int i;
 	char flags = TTY_NORMAL;
 
 	if (debug & 4)
 		print_hex_dump_bytes("gsmld_receive: ", DUMP_PREFIX_OFFSET,
 				     cp, count);
 
-	for (i = count, dp = cp, f = fp; i; i--, dp++) {
-		if (f)
-			flags = *f++;
+	for (; count; count--, cp++) {
+		if (fp)
+			flags = *fp++;
 		switch (flags) {
 		case TTY_NORMAL:
-			gsm->receive(gsm, *dp);
+			gsm->receive(gsm, *cp);
 			break;
 		case TTY_OVERRUN:
 		case TTY_BREAK:
 		case TTY_PARITY:
 		case TTY_FRAME:
-			gsm_error(gsm, *dp, flags);
+			gsm_error(gsm, *cp, flags);
 			break;
 		default:
 			WARN_ONCE(1, "%s: unknown flag %d\n",
-- 
2.39.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 5.10 0/3] tty: n_gsm: fix tty registration before control channel open
  2023-12-12 11:17 [PATCH 5.10 0/3] tty: n_gsm: fix tty registration before control channel open Gavrilov Ilia
                   ` (2 preceding siblings ...)
  2023-12-12 11:17 ` [PATCH 5.10 3/3] tty: n_gsm: add sanity check for gsm->receive in gsm_receive_buf() Gavrilov Ilia
@ 2023-12-12 11:44 ` Greg Kroah-Hartman
  2023-12-12 12:25   ` Gavrilov Ilia
  3 siblings, 1 reply; 7+ messages in thread
From: Greg Kroah-Hartman @ 2023-12-12 11:44 UTC (permalink / raw)
  To: Gavrilov Ilia
  Cc: stable, Daniel Starke, Jiri Slaby, Russ Gorby, linux-kernel, lvc-project

On Tue, Dec 12, 2023 at 11:17:21AM +0000, Gavrilov Ilia wrote:
> Syzkaller reports memory leak issue at gsmld_attach_gsm() in
> 5.10 stable releases. The reproducer injects the memory allocation
> errors to tty_register_device(); as a result, tty_kref_get() isn't called
> after this error, which leads to tty_struct leak.
> The issue has been fixed by the following patches that can be cleanly
> applied to the 5.10 branch.
> 
> Found by InfoTeCS on behalf of Linux Verification Center
> (linuxtesting.org) with Syzkaller

Do you actually have any hardware for this protocol running on the
5.10.y kernel?  How was this tested?  Why was just this specific set of
patches picked to be backported?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 5.10 0/3] tty: n_gsm: fix tty registration before control channel open
  2023-12-12 11:44 ` [PATCH 5.10 0/3] tty: n_gsm: fix tty registration before control channel open Greg Kroah-Hartman
@ 2023-12-12 12:25   ` Gavrilov Ilia
  0 siblings, 0 replies; 7+ messages in thread
From: Gavrilov Ilia @ 2023-12-12 12:25 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: stable, Daniel Starke, Jiri Slaby, Russ Gorby, linux-kernel, lvc-project

On 12/12/23 14:44, Greg Kroah-Hartman wrote:
> On Tue, Dec 12, 2023 at 11:17:21AM +0000, Gavrilov Ilia wrote:
>> Syzkaller reports memory leak issue at gsmld_attach_gsm() in
>> 5.10 stable releases. The reproducer injects the memory allocation
>> errors to tty_register_device(); as a result, tty_kref_get() isn't called
>> after this error, which leads to tty_struct leak.
>> The issue has been fixed by the following patches that can be cleanly
>> applied to the 5.10 branch.
>>
>> Found by InfoTeCS on behalf of Linux Verification Center
>> (linuxtesting.org) with Syzkaller
> 
> Do you actually have any hardware for this protocol running on the
> 5.10.y kernel?  How was this tested?  Why was just this specific set of
> patches picked to be backported?
> 

No, I don't have any hardware for this protocol. I tested this manually 
on virtual machines and using a reproducer (generated by syzkaller).
The first patch fixes the main problem(memory leak). The third patch 
fixes the problem with а null pointer dereference. I added this patch 
because it has a "fixes" tag that references to the first patch. The 
third patch can't be applied cleanly without the second patch.

> thanks,
> 
> greg k-h


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 3/3] tty: n_gsm: add sanity check for gsm->receive in gsm_receive_buf()
  2023-12-12 11:17 ` [PATCH 5.10 3/3] tty: n_gsm: add sanity check for gsm->receive in gsm_receive_buf() Gavrilov Ilia
@ 2023-12-12 15:20   ` kernel test robot
  0 siblings, 0 replies; 7+ messages in thread
From: kernel test robot @ 2023-12-12 15:20 UTC (permalink / raw)
  To: Gavrilov Ilia; +Cc: stable, oe-kbuild-all

Hi,

Thanks for your patch.

FYI: kernel test robot notices the stable kernel rule is not satisfied.

The check is based on https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html#option-1

Rule: add the tag "Cc: stable@vger.kernel.org" in the sign-off area to have the patch automatically included in the stable tree.
Subject: [PATCH 3/3] tty: n_gsm: add sanity check for gsm->receive in gsm_receive_buf()
Link: https://lore.kernel.org/stable/20231212111431.4064760-4-Ilia.Gavrilov%40infotecs.ru

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki




^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-12-12 15:24 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-12 11:17 [PATCH 5.10 0/3] tty: n_gsm: fix tty registration before control channel open Gavrilov Ilia
2023-12-12 11:17 ` [PATCH 5.10 2/3] tty: n_gsm, remove duplicates of parameters Gavrilov Ilia
2023-12-12 11:17 ` [PATCH 5.10 1/3] tty: n_gsm: fix tty registration before control channel open Gavrilov Ilia
2023-12-12 11:17 ` [PATCH 5.10 3/3] tty: n_gsm: add sanity check for gsm->receive in gsm_receive_buf() Gavrilov Ilia
2023-12-12 15:20   ` [PATCH " kernel test robot
2023-12-12 11:44 ` [PATCH 5.10 0/3] tty: n_gsm: fix tty registration before control channel open Greg Kroah-Hartman
2023-12-12 12:25   ` Gavrilov Ilia

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.