efi_loader: NULL dereference in EFI console

Even if CONFIG_DM_VIDEO=y and stdout="vidconsole", a video device may not
be available. Check the return values of the relevant functions.

If no video output device is available, assume that the serial console is
in use.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
Heinrich Schuchardt 2021-03-16 12:56:57 +01:00
parent e3310c21a4
commit a95f4c8859

View file

@ -254,7 +254,7 @@ static bool cout_mode_matches(struct cout_mode *mode, int rows, int cols)
} }
/** /**
* query_console_serial() - query console size * query_console_serial() - query serial console size
* *
* When using a serial console or the net console we can only devise the * When using a serial console or the net console we can only devise the
* terminal size by querying the terminal using ECMA-48 control sequences. * terminal size by querying the terminal using ECMA-48 control sequences.
@ -299,6 +299,37 @@ out:
return ret; return ret;
} }
/**
* query_vidconsole() - query video console size
*
*
* @rows: pointer to return number of rows
* @cols: pointer to return number of columns
* Returns: 0 on success
*/
static int __maybe_unused query_vidconsole(int *rows, int *cols)
{
const char *stdout_name = env_get("stdout");
struct stdio_dev *stdout_dev;
struct udevice *dev;
struct vidconsole_priv *priv;
if (!stdout_name || strncmp(stdout_name, "vidconsole", 10))
return -ENODEV;
stdout_dev = stdio_get_by_name("vidconsole");
if (!stdout_dev)
return -ENODEV;
dev = stdout_dev->priv;
if (!dev)
return -ENODEV;
priv = dev_get_uclass_priv(dev);
if (!priv)
return -ENODEV;
*rows = priv->rows;
*cols = priv->cols;
return 0;
}
/** /**
* query_console_size() - update the mode table. * query_console_size() - update the mode table.
* *
@ -308,21 +339,15 @@ out:
*/ */
static void query_console_size(void) static void query_console_size(void)
{ {
const char *stdout_name = env_get("stdout");
int rows = 25, cols = 80; int rows = 25, cols = 80;
int ret = -ENODEV;
if (stdout_name && !strncmp(stdout_name, "vidconsole", 10) && if IS_ENABLED(CONFIG_DM_VIDEO)
IS_ENABLED(CONFIG_DM_VIDEO)) { ret = query_vidconsole(&rows, &cols);
struct stdio_dev *stdout_dev = if (ret)
stdio_get_by_name("vidconsole"); ret = query_console_serial(&rows, &cols);
struct udevice *dev = stdout_dev->priv; if (ret)
struct vidconsole_priv *priv =
dev_get_uclass_priv(dev);
rows = priv->rows;
cols = priv->cols;
} else if (query_console_serial(&rows, &cols)) {
return; return;
}
/* Test if we can have Mode 1 */ /* Test if we can have Mode 1 */
if (cols >= 80 && rows >= 50) { if (cols >= 80 && rows >= 50) {