[PATCH][V4] dmicheck: skip scanning smbios in /dev/mem on aarch64

Leif Lindholm leif at nuviainc.com
Thu Dec 16 16:49:32 UTC 2021


On Sat, Dec 11, 2021 at 17:32:02 -0700, Alex Hung wrote:
> Signed-off-by: Alex Hung <alex.hung at canonical.com>
> ---
>  src/dmi/dmicheck/dmicheck.c   |  14 ++++
>  src/lib/include/fwts.h        |   1 +
>  src/lib/include/fwts_fileio.h |   3 +
>  src/lib/include/fwts_kernel.h |  25 +++++++
>  src/lib/src/Makefile.am       |   1 +
>  src/lib/src/fwts_fileio.c     |  39 +++++++++++
>  src/lib/src/fwts_kernel.c     | 126 ++++++++++++++++++++++++++++++++++
>  7 files changed, 209 insertions(+)
>  create mode 100644 src/lib/include/fwts_kernel.h
>  create mode 100644 src/lib/src/fwts_kernel.c
> 
> diff --git a/src/dmi/dmicheck/dmicheck.c b/src/dmi/dmicheck/dmicheck.c
> index 7f6a90c4..3985b126 100644
> --- a/src/dmi/dmicheck/dmicheck.c
> +++ b/src/dmi/dmicheck/dmicheck.c
> @@ -381,6 +381,13 @@ static void* dmi_table_smbios(fwts_framework *fw, fwts_smbios_entry *entry)
>  		free(table);
>  	}
>  
> +#ifdef FWTS_ARCH_AARCH64
> +	if (fwts_kernel_config_set("CONFIG_STRICT_DEVMEM")) {
> +		fwts_warning(fw, "Skipping scanning SMBIOS table in memory for arm64 systems");

<broken record mode>
Scanning /dev/mem *ever* remains a trivial denial-of-service attack on
at least any ARM system and probably any non-PC system. And has not
been required for SMBIOS access since kernel v4.3 (released over 6
years ago).

Why still permit it at all in a tool created to help boost system
resilience?
</broken record mode>

/
    Leif

> +		return NULL;
> +	}
> +#endif
> +
>  	mem = fwts_mmap(addr, length);
>  	if (mem != FWTS_MAP_FAILED) {
>  		/* Can we safely copy the table? */
> @@ -429,6 +436,13 @@ static void* dmi_table_smbios30(fwts_framework *fw, fwts_smbios30_entry *entry)
>  		free(table);
>  	}
>  
> +#ifdef FWTS_ARCH_AARCH64
> +	if (fwts_kernel_config_set("CONFIG_STRICT_DEVMEM")) {
> +		fwts_warning(fw, "Skipping scanning SMBIOS3 table in memory for arm64 systems");
> +		return NULL;
> +	}
> +#endif
> +
>  	mem = fwts_mmap(addr, length);
>  	if (mem != FWTS_MAP_FAILED) {
>  		/* Can we safely copy the table? */
> diff --git a/src/lib/include/fwts.h b/src/lib/include/fwts.h
> index 551a4e09..be754a99 100644
> --- a/src/lib/include/fwts.h
> +++ b/src/lib/include/fwts.h
> @@ -185,6 +185,7 @@
>  #include "fwts_iasl.h"
>  #include "fwts_ipmi.h"
>  #include "fwts_klog.h"
> +#include "fwts_kernel.h"
>  #include "fwts_olog.h"
>  #include "fwts_pipeio.h"
>  #include "fwts_stringextras.h"
> diff --git a/src/lib/include/fwts_fileio.h b/src/lib/include/fwts_fileio.h
> index 99826491..108dae96 100644
> --- a/src/lib/include/fwts_fileio.h
> +++ b/src/lib/include/fwts_fileio.h
> @@ -21,8 +21,11 @@
>  #define __FWTS_FILEIO_H__
>  
>  #include <stdio.h>
> +#include <zlib.h>
>  
>  fwts_list* fwts_file_read(FILE *fp);
>  fwts_list* fwts_file_open_and_read(const char *file);
> +fwts_list* fwts_gzfile_read(gzFile *fp);
> +fwts_list* fwts_gzfile_open_and_read(const char *file);
>  
>  #endif
> diff --git a/src/lib/include/fwts_kernel.h b/src/lib/include/fwts_kernel.h
> new file mode 100644
> index 00000000..a89576ae
> --- /dev/null
> +++ b/src/lib/include/fwts_kernel.h
> @@ -0,0 +1,25 @@
> +/*
> + * Copyright (C) 2021 Canonical
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
> + *
> + */
> +
> +#ifndef __FWTS_KERNEL_H__
> +#define __FWTS_KERNEL_H__
> +
> +bool fwts_kernel_config_set(const char *config);
> +
> +#endif
> diff --git a/src/lib/src/Makefile.am b/src/lib/src/Makefile.am
> index 55c52b41..0a39882a 100644
> --- a/src/lib/src/Makefile.am
> +++ b/src/lib/src/Makefile.am
> @@ -83,6 +83,7 @@ libfwts_la_SOURCES = 		\
>  	fwts_ioport.c		\
>  	fwts_ipmi.c		\
>  	fwts_json.c		\
> +	fwts_kernel.c 		\
>  	fwts_keymap.c 		\
>  	fwts_klog.c 		\
>  	fwts_olog.c		\
> diff --git a/src/lib/src/fwts_fileio.c b/src/lib/src/fwts_fileio.c
> index 552fe993..6af6f00f 100644
> --- a/src/lib/src/fwts_fileio.c
> +++ b/src/lib/src/fwts_fileio.c
> @@ -21,6 +21,7 @@
>  #include <stdlib.h>
>  #include <string.h>
>  #include <unistd.h>
> +#include <zlib.h>
>  
>  #include "fwts.h"
>  
> @@ -61,3 +62,41 @@ fwts_list* fwts_file_open_and_read(const char *file)
>  
>  	return list;
>  }
> +
> +/*
> + *  fwts_gzfile_read()
> + *	read given gz file and return contents as a list of lines
> + */
> +fwts_list *fwts_gzfile_read(gzFile *fp)
> +{
> +	fwts_list *list;
> +	char buffer[8192];
> +
> +	if ((list = fwts_list_new()) == NULL)
> +		return NULL;
> +
> +	while (gzgets(*fp, buffer, sizeof(buffer)) != NULL) {
> +		buffer[strlen(buffer) - 1] = '\0';	/* Chop off "\n" */
> +		fwts_text_list_append(list, buffer);
> +	}
> +
> +	return list;
> +}
> +
> +/*
> + *  fwts_gzfile_open_and_read()
> + *	open and read gz file and return contents as a list of lines
> + */
> +fwts_list* fwts_gzfile_open_and_read(const char *file)
> +{
> +	gzFile fp;
> +	fwts_list *list;
> +
> +	if ((fp = gzopen(file, "r")) == Z_NULL)
> +		return NULL;
> +
> +	list = fwts_gzfile_read(&fp);
> +	(void)gzclose(fp);
> +
> +	return list;
> +}
> diff --git a/src/lib/src/fwts_kernel.c b/src/lib/src/fwts_kernel.c
> new file mode 100644
> index 00000000..f42e65bc
> --- /dev/null
> +++ b/src/lib/src/fwts_kernel.c
> @@ -0,0 +1,126 @@
> +/*
> + * Copyright (C) 2021 Canonical
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
> + *
> + */
> +
> +#include <sys/utsname.h>
> +
> +#include "fwts.h"
> +#include "fwts_kernel.h"
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <bsd/string.h>
> +
> +#define CONFIG_FILE_PREFIX	"/boot/config-"
> +#define CONFIG_FILE_PROC	"/proc/config.gz"
> +
> +/*
> + *  fwts_kernel_config_plain_set
> + *	 check whether a plain-text kernel config
> + */
> +bool fwts_kernel_config_plain_set(const char *config)
> +{
> +	const size_t config_str_len = strlen(config) + 3;
> +	char config_file[PATH_MAX];
> +	char config_str[255];
> +	size_t config_file_len;
> +	fwts_list* config_list;
> +	fwts_list_link *item;
> +	struct utsname buf;
> +
> +	/* get path of config file, i.e. /boot/config-5.11.0-38-generic */
> +	uname(&buf);
> +	config_file_len = strlen(CONFIG_FILE_PREFIX) + strlen(buf.release) + 1;
> +	(void)strlcpy(config_file, CONFIG_FILE_PREFIX, config_file_len);
> +	(void)strlcat(config_file, buf.release, config_file_len);
> +
> +	config_list = fwts_file_open_and_read(config_file);
> +	if (config_list == NULL)
> +		return false;
> +
> +	fwts_list_foreach(item, config_list) {
> +		/* check built-in, i.e. =y */
> +		(void)strlcpy(config_str, config, config_str_len);
> +		(void)strlcat(config_str, "=y", config_str_len);
> +		if (!strncmp(fwts_text_list_text(item), config_str, strlen(config_str))) {
> +			fwts_list_free(config_list, free);
> +			return true;
> +		}
> +
> +		/* check module, i.e. =m */
> +		config_str[strlen(config_str) - 1] = 'm';
> +		if (!strncmp(fwts_text_list_text(item), config_str, strlen(config_str))) {
> +			fwts_list_free(config_list, free);
> +			return true;
> +		}
> +	}
> +
> +	fwts_list_free(config_list, free);
> +	return false;
> +}
> +
> +/*
> + *  fwts_kernel_config_gz_set
> + *	 check whether a gz kernel config
> + */
> +bool fwts_kernel_config_gz_set(const char *config)
> +{
> +	const size_t config_str_len = strlen(config) + 3;
> +	char config_str[255];
> +	fwts_list* config_list;
> +	fwts_list_link *item;
> +
> +	config_list = fwts_gzfile_open_and_read(CONFIG_FILE_PROC);
> +	if (config_list == NULL)
> +		return false;
> +
> +	fwts_list_foreach(item, config_list) {
> +		/* check built-in, i.e. =y */
> +		(void)strlcpy(config_str, config, config_str_len);
> +		(void)strlcat(config_str, "=y", config_str_len);
> +		if (!strncmp(fwts_text_list_text(item), config_str, strlen(config_str))) {
> +			fwts_list_free(config_list, free);
> +			return true;
> +		}
> +
> +		/* check module, i.e. =m */
> +		config_str[strlen(config_str) - 1] = 'm';
> +		if (!strncmp(fwts_text_list_text(item), config_str, strlen(config_str))) {
> +			fwts_list_free(config_list, free);
> +			return true;
> +		}
> +	}
> +
> +	fwts_list_free(config_list, free);
> +	return false;
> +}
> +
> +/*
> + *  fwts_kernel_config_set
> + *	 check whether a kernel config is set, ex.
> + *	 true if CONFIG_XYZ=y or CONFIG_XYZ=m
> + */
> +bool fwts_kernel_config_set(const char *config)
> +{
> +	if (fwts_kernel_config_plain_set(config))
> +		return true;
> +
> +	if (fwts_kernel_config_gz_set(config))
> +		return true;
> +
> +	return false;
> +}
> -- 
> 2.34.1
> 
> 
> -- 
> fwts-devel mailing list
> fwts-devel at lists.ubuntu.com
> Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/fwts-devel



More information about the fwts-devel mailing list