Nico Huber has submitted this change. ( https://review.coreboot.org/c/flashrom/+/61275 )
Change subject: hwaccess_x86_io: refactor rget_io_perms() ......................................................................
hwaccess_x86_io: refactor rget_io_perms()
Abstract the different I/O Port permission methods in own functions.
Change-Id: If4b2f8c2532f3732086ee1d479da6ae6693f9a42 Signed-off-by: Thomas Heijligen thomas.heijligen@secunet.com Reviewed-on: https://review.coreboot.org/c/flashrom/+/61275 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Edward O'Callaghan quasisec@chromium.org Reviewed-by: Nico Huber nico.h@gmx.de Reviewed-by: Angel Pons th3fanbus@gmail.com --- M hwaccess_x86_io.c 1 file changed, 98 insertions(+), 50 deletions(-)
Approvals: build bot (Jenkins): Verified Nico Huber: Looks good to me, approved Angel Pons: Looks good to me, but someone else must approve Edward O'Callaghan: Looks good to me, approved
diff --git a/hwaccess_x86_io.c b/hwaccess_x86_io.c index 635b27e..e891d98 100644 --- a/hwaccess_x86_io.c +++ b/hwaccess_x86_io.c @@ -2,6 +2,8 @@ * This file is part of the flashrom project. * * Copyright (C) 2009,2010 Carl-Daniel Hailfinger + * Copyright (C) 2022 secunet Security Networks AG + * (Written by Thomas Heijligen <thomas.heijligen@secunet.com) * * 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 @@ -14,70 +16,116 @@ * GNU General Public License for more details. */
+/* + * This file implements x86 I/O port permission handling. + * + * For this purpose the platform specific code is encapsuled in two functions + * and compiled only on the respective platform. `platform_get_io_perms()` is + * called to get the permissions and `platform_release_io_perms()` is called for + * releasing those. + */ + #include <errno.h> #include <string.h> -#if !defined (__DJGPP__) && !defined(__LIBPAYLOAD__) -/* No file access needed/possible to get hardware access permissions. */ -#include <unistd.h> -#include <fcntl.h> -#endif
-#include "hwaccess_x86_io.h" #include "flash.h" +#include "hwaccess_x86_io.h"
-#if USE_IOPERM -#include <sys/io.h> -#endif - -#if USE_DEV_IO -int io_fd; -#endif - -#if !(defined(__DJGPP__) || defined(__LIBPAYLOAD__)) -static int release_io_perms(void *p) +#if defined(__DJGPP__) || defined(__LIBPAYLOAD) /* DJGPP, libpayload */ +static int platform_get_io_perms(void) { -#if defined (__sun) + return 0; +} + +static int platform_release_io_perms(void *p) +{ + return 0; +} +#endif + +#if defined(__sun) /* SunOS */ +#include <sys/sysi86.h> + +static int platform_get_io_perms(void) +{ + return sysi86(SI86V86, V86SC_IOPL, PS_IOPL); +} + +static int platform_release_io_perms(void *p) +{ sysi86(SI86V86, V86SC_IOPL, 0); -#elif USE_DEV_IO + return 0; +} +#endif + +#if USE_DEV_IO /* FreeBSD, DragonFlyBSD */ +#include <fcntl.h> +#include <unistd.h> + +int io_fd; + +static int platform_get_io_perms(void) +{ + io_fd = open("/dev/io", O_RDWR); + return (io_fd >= 0 ? 0 : -1); +} + +static int platform_release_io_perms(void *p) +{ close(io_fd); -#elif USE_IOPERM + return 0; +} +#endif + +#if USE_IOPERM /* GNU Hurd */ +#include <sys/io.h> + +static int platform_get_io_perms(void) +{ + return ioperm(0, 65536, 1); +} + +static int platform_release_io_perms(void *p) +{ ioperm(0, 65536, 0); -#elif USE_IOPL + return 0; +} +#endif + +#if USE_IOPL /* Linux, Darwin, NetBSD, OpenBSD */ +static int platform_get_io_perms(void) +{ + return iopl(3); +} + +static int platform_release_io_perms(void *p) +{ iopl(0); -#endif return 0; } +#endif
-/* Get I/O permissions with automatic permission release on shutdown. */ +/** + * @brief Get access to the x86 I/O ports + * + * This function abstracts the platform dependent function to get access to the + * x86 I/O ports and musst be called before using IN[B/W/L] or OUT[B/W/L]. + * It registers a shutdown function to release those privileges. + * + * @return 0 on success, platform specific number on failure + */ int rget_io_perms(void) { - #if defined (__sun) - if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) { -#elif USE_DEV_IO - if ((io_fd = open("/dev/io", O_RDWR)) < 0) { -#elif USE_IOPERM - if (ioperm(0, 65536, 1) != 0) { -#elif USE_IOPL - if (iopl(3) != 0) { -#endif - msg_perr("ERROR: Could not get I/O privileges (%s).\n", strerror(errno)); - msg_perr("You need to be root.\n"); - msg_perr("On OpenBSD set securelevel=-1 in /etc/rc.securelevel and\n" - "reboot, or reboot into single user mode.\n"); - msg_perr("On NetBSD reboot into single user mode or make sure\n" - "that your kernel configuration has the option INSECURE enabled.\n"); - return 1; - } else { - register_shutdown(release_io_perms, NULL); + if (platform_get_io_perms() == 0) { + register_shutdown(platform_release_io_perms, NULL); + return 0; } - return 0; + msg_perr("ERROR: Could not get I/O privileges (%s).\n", strerror(errno)); + msg_perr("Make sure you are root. If you are root, your kernel may still\n" + "prevent access based on security policies.\n"); + msg_perr("On OpenBSD set securelevel=-1 in /etc/rc.securelevel and\n" + "reboot, or reboot into single user mode.\n"); + msg_perr("On NetBSD reboot into single user mode or make sure\n" + "that your kernel configuration has the option INSECURE enabled.\n"); + return 1; } - -#else - -/* DJGPP and libpayload environments have full PCI port I/O permissions by default. */ -int rget_io_perms(void) -{ - return 0; -} -#endif