diff mbox series

[SRU,Focal,1/1] vt: drop old FONT ioctls

Message ID 20220803042030.179067-3-cengiz.can@canonical.com
State New
Headers show
Series [SRU,Focal,1/1] vt: drop old FONT ioctls | expand

Commit Message

Cengiz Can Aug. 3, 2022, 4:20 a.m. UTC
From: Jiri Slaby <jslaby@suse.cz>

commit ff2047fb755d4415ec3c70ac799889371151796d upstream.

Drop support for these ioctls:
* PIO_FONT, PIO_FONTX
* GIO_FONT, GIO_FONTX
* PIO_FONTRESET

As was demonstrated by commit 90bfdeef83f1 (tty: make FONTX ioctl use
the tty pointer they were actually passed), these ioctls are not used
from userspace, as:
1) they used to be broken (set up font on current console, not the open
   one) and racy (before the commit above)
2) KDFONTOP ioctl is used for years instead

Note that PIO_FONTRESET is defunct on most systems as VGA_CONSOLE is set
on them for ages. That turns on BROKEN_GRAPHICS_PROGRAMS which makes
PIO_FONTRESET just return an error.

We are removing KD_FONT_FLAG_OLD here as it was used only by these
removed ioctls. kd.h header exists both in kernel and uapi headers, so
we can remove the kernel one completely. Everyone includeing kd.h will
now automatically get the uapi one.

There are now unused definitions of the ioctl numbers and "struct
consolefontdesc" in kd.h, but as it is a uapi header, I am not touching
these.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Link: https://lore.kernel.org/r/20210105120239.28031-8-jslaby@suse.cz
Cc: guodaxing <guodaxing@huawei.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CVE-2021-33656
(cherry picked from commit c87e851b23e5cb2ba90a3049ef38340ed7d5746f linux-5.4.y)
Signed-off-by: Cengiz Can <cengiz.can@canonical.com>
---
 drivers/tty/vt/vt.c       |  39 +---------
 drivers/tty/vt/vt_ioctl.c | 147 --------------------------------------
 include/linux/kd.h        |   8 ---
 3 files changed, 3 insertions(+), 191 deletions(-)
 delete mode 100644 include/linux/kd.h

Comments

Stefan Bader Aug. 8, 2022, 9:29 a.m. UTC | #1
On 03.08.22 06:20, Cengiz Can wrote:
> From: Jiri Slaby <jslaby@suse.cz>
> 
> commit ff2047fb755d4415ec3c70ac799889371151796d upstream.
> 
> Drop support for these ioctls:
> * PIO_FONT, PIO_FONTX
> * GIO_FONT, GIO_FONTX
> * PIO_FONTRESET
> 
> As was demonstrated by commit 90bfdeef83f1 (tty: make FONTX ioctl use
> the tty pointer they were actually passed), these ioctls are not used
> from userspace, as:
> 1) they used to be broken (set up font on current console, not the open
>     one) and racy (before the commit above)
> 2) KDFONTOP ioctl is used for years instead
> 
> Note that PIO_FONTRESET is defunct on most systems as VGA_CONSOLE is set
> on them for ages. That turns on BROKEN_GRAPHICS_PROGRAMS which makes
> PIO_FONTRESET just return an error.
> 
> We are removing KD_FONT_FLAG_OLD here as it was used only by these
> removed ioctls. kd.h header exists both in kernel and uapi headers, so
> we can remove the kernel one completely. Everyone includeing kd.h will
> now automatically get the uapi one.
> 
> There are now unused definitions of the ioctl numbers and "struct
> consolefontdesc" in kd.h, but as it is a uapi header, I am not touching
> these.
> 
> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
> Link: https://lore.kernel.org/r/20210105120239.28031-8-jslaby@suse.cz
> Cc: guodaxing <guodaxing@huawei.com>
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> CVE-2021-33656
> (cherry picked from commit c87e851b23e5cb2ba90a3049ef38340ed7d5746f linux-5.4.y)
> Signed-off-by: Cengiz Can <cengiz.can@canonical.com>
> ---

Applied to focal:linux/master-next. Thanks.

-Stefan

>   drivers/tty/vt/vt.c       |  39 +---------
>   drivers/tty/vt/vt_ioctl.c | 147 --------------------------------------
>   include/linux/kd.h        |   8 ---
>   3 files changed, 3 insertions(+), 191 deletions(-)
>   delete mode 100644 include/linux/kd.h
> 
> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
> index da2344e5ec340..c28e976a835d6 100644
> --- a/drivers/tty/vt/vt.c
> +++ b/drivers/tty/vt/vt.c
> @@ -4568,16 +4568,8 @@ static int con_font_get(struct vc_data *vc, struct console_font_op *op)
>   
>   	if (op->data && font.charcount > op->charcount)
>   		rc = -ENOSPC;
> -	if (!(op->flags & KD_FONT_FLAG_OLD)) {
> -		if (font.width > op->width || font.height > op->height)
> -			rc = -ENOSPC;
> -	} else {
> -		if (font.width != 8)
> -			rc = -EIO;
> -		else if ((op->height && font.height > op->height) ||
> -			 font.height > 32)
> -			rc = -ENOSPC;
> -	}
> +	if (font.width > op->width || font.height > op->height)
> +		rc = -ENOSPC;
>   	if (rc)
>   		goto out;
>   
> @@ -4605,7 +4597,7 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op)
>   		return -EINVAL;
>   	if (op->charcount > 512)
>   		return -EINVAL;
> -	if (op->width <= 0 || op->width > 32 || op->height > 32)
> +	if (op->width <= 0 || op->width > 32 || !op->height || op->height > 32)
>   		return -EINVAL;
>   	size = (op->width+7)/8 * 32 * op->charcount;
>   	if (size > max_font_size)
> @@ -4615,31 +4607,6 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op)
>   	if (IS_ERR(font.data))
>   		return PTR_ERR(font.data);
>   
> -	if (!op->height) {		/* Need to guess font height [compat] */
> -		int h, i;
> -		u8 *charmap = font.data;
> -
> -		/*
> -		 * If from KDFONTOP ioctl, don't allow things which can be done
> -		 * in userland,so that we can get rid of this soon
> -		 */
> -		if (!(op->flags & KD_FONT_FLAG_OLD)) {
> -			kfree(font.data);
> -			return -EINVAL;
> -		}
> -
> -		for (h = 32; h > 0; h--)
> -			for (i = 0; i < op->charcount; i++)
> -				if (charmap[32*i+h-1])
> -					goto nonzero;
> -
> -		kfree(font.data);
> -		return -EINVAL;
> -
> -	nonzero:
> -		op->height = h;
> -	}
> -
>   	font.charcount = op->charcount;
>   	font.width = op->width;
>   	font.height = op->height;
> diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
> index 9db03dc7eeb99..38cc69477eecc 100644
> --- a/drivers/tty/vt/vt_ioctl.c
> +++ b/drivers/tty/vt/vt_ioctl.c
> @@ -241,48 +241,6 @@ int vt_waitactive(int n)
>   #define GPLAST 0x3df
>   #define GPNUM (GPLAST - GPFIRST + 1)
>   
> -
> -
> -static inline int
> -do_fontx_ioctl(struct vc_data *vc, int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op)
> -{
> -	struct consolefontdesc cfdarg;
> -	int i;
> -
> -	if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc)))
> -		return -EFAULT;
> - 	
> -	switch (cmd) {
> -	case PIO_FONTX:
> -		if (!perm)
> -			return -EPERM;
> -		op->op = KD_FONT_OP_SET;
> -		op->flags = KD_FONT_FLAG_OLD;
> -		op->width = 8;
> -		op->height = cfdarg.charheight;
> -		op->charcount = cfdarg.charcount;
> -		op->data = cfdarg.chardata;
> -		return con_font_op(vc, op);
> -
> -	case GIO_FONTX:
> -		op->op = KD_FONT_OP_GET;
> -		op->flags = KD_FONT_FLAG_OLD;
> -		op->width = 8;
> -		op->height = cfdarg.charheight;
> -		op->charcount = cfdarg.charcount;
> -		op->data = cfdarg.chardata;
> -		i = con_font_op(vc, op);
> -		if (i)
> -			return i;
> -		cfdarg.charheight = op->height;
> -		cfdarg.charcount = op->charcount;
> -		if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc)))
> -			return -EFAULT;
> -		return 0;
> -	}
> -	return -EINVAL;
> -}
> -
>   static inline int
>   do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc)
>   {
> @@ -919,30 +877,6 @@ int vt_ioctl(struct tty_struct *tty,
>   		break;
>   	}
>   
> -	case PIO_FONT: {
> -		if (!perm)
> -			return -EPERM;
> -		op.op = KD_FONT_OP_SET;
> -		op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC;	/* Compatibility */
> -		op.width = 8;
> -		op.height = 0;
> -		op.charcount = 256;
> -		op.data = up;
> -		ret = con_font_op(vc, &op);
> -		break;
> -	}
> -
> -	case GIO_FONT: {
> -		op.op = KD_FONT_OP_GET;
> -		op.flags = KD_FONT_FLAG_OLD;
> -		op.width = 8;
> -		op.height = 32;
> -		op.charcount = 256;
> -		op.data = up;
> -		ret = con_font_op(vc, &op);
> -		break;
> -	}
> -
>   	case PIO_CMAP:
>                   if (!perm)
>   			ret = -EPERM;
> @@ -954,36 +888,6 @@ int vt_ioctl(struct tty_struct *tty,
>                   ret = con_get_cmap(up);
>   		break;
>   
> -	case PIO_FONTX:
> -	case GIO_FONTX:
> -		ret = do_fontx_ioctl(vc, cmd, up, perm, &op);
> -		break;
> -
> -	case PIO_FONTRESET:
> -	{
> -		if (!perm)
> -			return -EPERM;
> -
> -#ifdef BROKEN_GRAPHICS_PROGRAMS
> -		/* With BROKEN_GRAPHICS_PROGRAMS defined, the default
> -		   font is not saved. */
> -		ret = -ENOSYS;
> -		break;
> -#else
> -		{
> -		op.op = KD_FONT_OP_SET_DEFAULT;
> -		op.data = NULL;
> -		ret = con_font_op(vc, &op);
> -		if (ret)
> -			break;
> -		console_lock();
> -		con_set_default_unimap(vc);
> -		console_unlock();
> -		break;
> -		}
> -#endif
> -	}
> -
>   	case KDFONTOP: {
>   		if (copy_from_user(&op, up, sizeof(op))) {
>   			ret = -EFAULT;
> @@ -1097,54 +1001,6 @@ void vc_SAK(struct work_struct *work)
>   
>   #ifdef CONFIG_COMPAT
>   
> -struct compat_consolefontdesc {
> -	unsigned short charcount;       /* characters in font (256 or 512) */
> -	unsigned short charheight;      /* scan lines per character (1-32) */
> -	compat_caddr_t chardata;	/* font data in expanded form */
> -};
> -
> -static inline int
> -compat_fontx_ioctl(struct vc_data *vc, int cmd,
> -		   struct compat_consolefontdesc __user *user_cfd,
> -		   int perm, struct console_font_op *op)
> -{
> -	struct compat_consolefontdesc cfdarg;
> -	int i;
> -
> -	if (copy_from_user(&cfdarg, user_cfd, sizeof(struct compat_consolefontdesc)))
> -		return -EFAULT;
> -
> -	switch (cmd) {
> -	case PIO_FONTX:
> -		if (!perm)
> -			return -EPERM;
> -		op->op = KD_FONT_OP_SET;
> -		op->flags = KD_FONT_FLAG_OLD;
> -		op->width = 8;
> -		op->height = cfdarg.charheight;
> -		op->charcount = cfdarg.charcount;
> -		op->data = compat_ptr(cfdarg.chardata);
> -		return con_font_op(vc, op);
> -
> -	case GIO_FONTX:
> -		op->op = KD_FONT_OP_GET;
> -		op->flags = KD_FONT_FLAG_OLD;
> -		op->width = 8;
> -		op->height = cfdarg.charheight;
> -		op->charcount = cfdarg.charcount;
> -		op->data = compat_ptr(cfdarg.chardata);
> -		i = con_font_op(vc, op);
> -		if (i)
> -			return i;
> -		cfdarg.charheight = op->height;
> -		cfdarg.charcount = op->charcount;
> -		if (copy_to_user(user_cfd, &cfdarg, sizeof(struct compat_consolefontdesc)))
> -			return -EFAULT;
> -		return 0;
> -	}
> -	return -EINVAL;
> -}
> -
>   struct compat_console_font_op {
>   	compat_uint_t op;        /* operation code KD_FONT_OP_* */
>   	compat_uint_t flags;     /* KD_FONT_FLAG_* */
> @@ -1221,9 +1077,6 @@ long vt_compat_ioctl(struct tty_struct *tty,
>   	/*
>   	 * these need special handlers for incompatible data structures
>   	 */
> -	case PIO_FONTX:
> -	case GIO_FONTX:
> -		return compat_fontx_ioctl(vc, cmd, up, perm, &op);
>   
>   	case KDFONTOP:
>   		return compat_kdfontop_ioctl(up, perm, &op, vc);
> diff --git a/include/linux/kd.h b/include/linux/kd.h
> deleted file mode 100644
> index b130a18f860f0..0000000000000
> --- a/include/linux/kd.h
> +++ /dev/null
> @@ -1,8 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0 */
> -#ifndef _LINUX_KD_H
> -#define _LINUX_KD_H
> -
> -#include <uapi/linux/kd.h>
> -
> -#define KD_FONT_FLAG_OLD		0x80000000	/* Invoked via old interface [compat] */
> -#endif /* _LINUX_KD_H */
diff mbox series

Patch

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index da2344e5ec340..c28e976a835d6 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -4568,16 +4568,8 @@  static int con_font_get(struct vc_data *vc, struct console_font_op *op)
 
 	if (op->data && font.charcount > op->charcount)
 		rc = -ENOSPC;
-	if (!(op->flags & KD_FONT_FLAG_OLD)) {
-		if (font.width > op->width || font.height > op->height) 
-			rc = -ENOSPC;
-	} else {
-		if (font.width != 8)
-			rc = -EIO;
-		else if ((op->height && font.height > op->height) ||
-			 font.height > 32)
-			rc = -ENOSPC;
-	}
+	if (font.width > op->width || font.height > op->height)
+		rc = -ENOSPC;
 	if (rc)
 		goto out;
 
@@ -4605,7 +4597,7 @@  static int con_font_set(struct vc_data *vc, struct console_font_op *op)
 		return -EINVAL;
 	if (op->charcount > 512)
 		return -EINVAL;
-	if (op->width <= 0 || op->width > 32 || op->height > 32)
+	if (op->width <= 0 || op->width > 32 || !op->height || op->height > 32)
 		return -EINVAL;
 	size = (op->width+7)/8 * 32 * op->charcount;
 	if (size > max_font_size)
@@ -4615,31 +4607,6 @@  static int con_font_set(struct vc_data *vc, struct console_font_op *op)
 	if (IS_ERR(font.data))
 		return PTR_ERR(font.data);
 
-	if (!op->height) {		/* Need to guess font height [compat] */
-		int h, i;
-		u8 *charmap = font.data;
-
-		/*
-		 * If from KDFONTOP ioctl, don't allow things which can be done
-		 * in userland,so that we can get rid of this soon
-		 */
-		if (!(op->flags & KD_FONT_FLAG_OLD)) {
-			kfree(font.data);
-			return -EINVAL;
-		}
-
-		for (h = 32; h > 0; h--)
-			for (i = 0; i < op->charcount; i++)
-				if (charmap[32*i+h-1])
-					goto nonzero;
-
-		kfree(font.data);
-		return -EINVAL;
-
-	nonzero:
-		op->height = h;
-	}
-
 	font.charcount = op->charcount;
 	font.width = op->width;
 	font.height = op->height;
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index 9db03dc7eeb99..38cc69477eecc 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -241,48 +241,6 @@  int vt_waitactive(int n)
 #define GPLAST 0x3df
 #define GPNUM (GPLAST - GPFIRST + 1)
 
-
-
-static inline int 
-do_fontx_ioctl(struct vc_data *vc, int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op)
-{
-	struct consolefontdesc cfdarg;
-	int i;
-
-	if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc))) 
-		return -EFAULT;
- 	
-	switch (cmd) {
-	case PIO_FONTX:
-		if (!perm)
-			return -EPERM;
-		op->op = KD_FONT_OP_SET;
-		op->flags = KD_FONT_FLAG_OLD;
-		op->width = 8;
-		op->height = cfdarg.charheight;
-		op->charcount = cfdarg.charcount;
-		op->data = cfdarg.chardata;
-		return con_font_op(vc, op);
-
-	case GIO_FONTX:
-		op->op = KD_FONT_OP_GET;
-		op->flags = KD_FONT_FLAG_OLD;
-		op->width = 8;
-		op->height = cfdarg.charheight;
-		op->charcount = cfdarg.charcount;
-		op->data = cfdarg.chardata;
-		i = con_font_op(vc, op);
-		if (i)
-			return i;
-		cfdarg.charheight = op->height;
-		cfdarg.charcount = op->charcount;
-		if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc)))
-			return -EFAULT;
-		return 0;
-	}
-	return -EINVAL;
-}
-
 static inline int 
 do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc)
 {
@@ -919,30 +877,6 @@  int vt_ioctl(struct tty_struct *tty,
 		break;
 	}
 
-	case PIO_FONT: {
-		if (!perm)
-			return -EPERM;
-		op.op = KD_FONT_OP_SET;
-		op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC;	/* Compatibility */
-		op.width = 8;
-		op.height = 0;
-		op.charcount = 256;
-		op.data = up;
-		ret = con_font_op(vc, &op);
-		break;
-	}
-
-	case GIO_FONT: {
-		op.op = KD_FONT_OP_GET;
-		op.flags = KD_FONT_FLAG_OLD;
-		op.width = 8;
-		op.height = 32;
-		op.charcount = 256;
-		op.data = up;
-		ret = con_font_op(vc, &op);
-		break;
-	}
-
 	case PIO_CMAP:
                 if (!perm)
 			ret = -EPERM;
@@ -954,36 +888,6 @@  int vt_ioctl(struct tty_struct *tty,
                 ret = con_get_cmap(up);
 		break;
 
-	case PIO_FONTX:
-	case GIO_FONTX:
-		ret = do_fontx_ioctl(vc, cmd, up, perm, &op);
-		break;
-
-	case PIO_FONTRESET:
-	{
-		if (!perm)
-			return -EPERM;
-
-#ifdef BROKEN_GRAPHICS_PROGRAMS
-		/* With BROKEN_GRAPHICS_PROGRAMS defined, the default
-		   font is not saved. */
-		ret = -ENOSYS;
-		break;
-#else
-		{
-		op.op = KD_FONT_OP_SET_DEFAULT;
-		op.data = NULL;
-		ret = con_font_op(vc, &op);
-		if (ret)
-			break;
-		console_lock();
-		con_set_default_unimap(vc);
-		console_unlock();
-		break;
-		}
-#endif
-	}
-
 	case KDFONTOP: {
 		if (copy_from_user(&op, up, sizeof(op))) {
 			ret = -EFAULT;
@@ -1097,54 +1001,6 @@  void vc_SAK(struct work_struct *work)
 
 #ifdef CONFIG_COMPAT
 
-struct compat_consolefontdesc {
-	unsigned short charcount;       /* characters in font (256 or 512) */
-	unsigned short charheight;      /* scan lines per character (1-32) */
-	compat_caddr_t chardata;	/* font data in expanded form */
-};
-
-static inline int
-compat_fontx_ioctl(struct vc_data *vc, int cmd,
-		   struct compat_consolefontdesc __user *user_cfd,
-		   int perm, struct console_font_op *op)
-{
-	struct compat_consolefontdesc cfdarg;
-	int i;
-
-	if (copy_from_user(&cfdarg, user_cfd, sizeof(struct compat_consolefontdesc)))
-		return -EFAULT;
-
-	switch (cmd) {
-	case PIO_FONTX:
-		if (!perm)
-			return -EPERM;
-		op->op = KD_FONT_OP_SET;
-		op->flags = KD_FONT_FLAG_OLD;
-		op->width = 8;
-		op->height = cfdarg.charheight;
-		op->charcount = cfdarg.charcount;
-		op->data = compat_ptr(cfdarg.chardata);
-		return con_font_op(vc, op);
-
-	case GIO_FONTX:
-		op->op = KD_FONT_OP_GET;
-		op->flags = KD_FONT_FLAG_OLD;
-		op->width = 8;
-		op->height = cfdarg.charheight;
-		op->charcount = cfdarg.charcount;
-		op->data = compat_ptr(cfdarg.chardata);
-		i = con_font_op(vc, op);
-		if (i)
-			return i;
-		cfdarg.charheight = op->height;
-		cfdarg.charcount = op->charcount;
-		if (copy_to_user(user_cfd, &cfdarg, sizeof(struct compat_consolefontdesc)))
-			return -EFAULT;
-		return 0;
-	}
-	return -EINVAL;
-}
-
 struct compat_console_font_op {
 	compat_uint_t op;        /* operation code KD_FONT_OP_* */
 	compat_uint_t flags;     /* KD_FONT_FLAG_* */
@@ -1221,9 +1077,6 @@  long vt_compat_ioctl(struct tty_struct *tty,
 	/*
 	 * these need special handlers for incompatible data structures
 	 */
-	case PIO_FONTX:
-	case GIO_FONTX:
-		return compat_fontx_ioctl(vc, cmd, up, perm, &op);
 
 	case KDFONTOP:
 		return compat_kdfontop_ioctl(up, perm, &op, vc);
diff --git a/include/linux/kd.h b/include/linux/kd.h
deleted file mode 100644
index b130a18f860f0..0000000000000
--- a/include/linux/kd.h
+++ /dev/null
@@ -1,8 +0,0 @@ 
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _LINUX_KD_H
-#define _LINUX_KD_H
-
-#include <uapi/linux/kd.h>
-
-#define KD_FONT_FLAG_OLD		0x80000000	/* Invoked via old interface [compat] */
-#endif /* _LINUX_KD_H */