Module Name: src Committed By: martin Date: Sun Apr 12 08:48:57 UTC 2020
Modified Files: src/sys/dev/acpi [netbsd-9]: acpi_ec.c Log Message: Pull up following revision(s) (requested by riastradh in ticket #829): sys/dev/acpi/acpi_ec.c: revision 1.78 sys/dev/acpi/acpi_ec.c: revision 1.79 sys/dev/acpi/acpi_ec.c: revision 1.80 sys/dev/acpi/acpi_ec.c: revision 1.81 Revert acpi_ec.c 1.77. We will do this another way. ok msaitoh Revert acpi_ec.c 1.76. We will do this another way, and separate KNF fixes from the critical functional change. ok msaitoh KNF Reject overly large widths, from mlelstv. We are returning an ACPI_INTEGER (= uint64_t), so it doesn't make sense to handle more than 64 bits. Apparently there are some ACPIs out there that ask for unreasonably large widths here. Just reject those requests, rather than writing past the caller's stack buffer. Previously we attempted to fix this by copying byte by byte as large as the caller asked, in order to avoid the undefined behaviour of shifting past the size of ACPI_INTEGER, but that just turned a shift (which might have been harmless on real machines) into a stack buffer overflow (!). ok msaitoh To generate a diff of this commit: cvs rdiff -u -r1.75.20.1 -r1.75.20.2 src/sys/dev/acpi/acpi_ec.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/acpi/acpi_ec.c diff -u src/sys/dev/acpi/acpi_ec.c:1.75.20.1 src/sys/dev/acpi/acpi_ec.c:1.75.20.2 --- src/sys/dev/acpi/acpi_ec.c:1.75.20.1 Fri Aug 9 16:13:35 2019 +++ src/sys/dev/acpi/acpi_ec.c Sun Apr 12 08:48:56 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_ec.c,v 1.75.20.1 2019/08/09 16:13:35 martin Exp $ */ +/* $NetBSD: acpi_ec.c,v 1.75.20.2 2020/04/12 08:48:56 martin Exp $ */ /*- * Copyright (c) 2007 Joerg Sonnenberger <jo...@netbsd.org>. @@ -59,7 +59,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_ec.c,v 1.75.20.1 2019/08/09 16:13:35 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_ec.c,v 1.75.20.2 2020/04/12 08:48:56 martin Exp $"); #include <sys/param.h> #include <sys/callout.h> @@ -657,36 +657,42 @@ static ACPI_STATUS acpiec_space_handler(uint32_t func, ACPI_PHYSICAL_ADDRESS paddr, uint32_t width, ACPI_INTEGER *value, void *arg, void *region_arg) { - device_t dv = arg; + device_t dv; ACPI_STATUS rv; - uint8_t addr; - uint8_t *reg; + uint8_t addr, reg; + unsigned int i; - if ((func != ACPI_READ) && (func != ACPI_WRITE)) { - aprint_error("%s: invalid Address Space function called: %x\n", - device_xname(dv), (unsigned int)func); - return AE_BAD_PARAMETER; - } - if (paddr > 0xff || width % 8 != 0 || value == NULL || arg == NULL || - paddr + width / 8 > 0x100) + if (paddr > 0xff || width % 8 != 0 || width > sizeof(ACPI_INTEGER)*8 || + value == NULL || arg == NULL || paddr + width / 8 > 0x100) return AE_BAD_PARAMETER; addr = paddr; - reg = (uint8_t *)value; + dv = arg; rv = AE_OK; - if (func == ACPI_READ) + switch (func) { + case ACPI_READ: *value = 0; - - for (addr = paddr; addr < (paddr + width / 8); addr++, reg++) { - if (func == ACPI_READ) - rv = acpiec_read(dv, addr, reg); - else - rv = acpiec_write(dv, addr, *reg); - - if (rv != AE_OK) - break; + for (i = 0; i < width; i += 8, ++addr) { + rv = acpiec_read(dv, addr, ®); + if (rv != AE_OK) + break; + *value |= (ACPI_INTEGER)reg << i; + } + break; + case ACPI_WRITE: + for (i = 0; i < width; i += 8, ++addr) { + reg = (*value >> i) & 0xff; + rv = acpiec_write(dv, addr, reg); + if (rv != AE_OK) + break; + } + break; + default: + aprint_error("%s: invalid Address Space function called: %x\n", + device_xname(dv), (unsigned int)func); + return AE_BAD_PARAMETER; } return rv;