Hi,

Let me update "diff #2".

On Fri, 26 Feb 2021 13:42:32 +0900 (JST)
YASUOKA Masahiko <yasu...@openbsd.org> wrote:
> My vaio repeatedly crashed by "Data modified on freelist"(*1) or other
> memory corruptions.  After my long time debug, I found the route cause
> is a handling of references of LocalX, like the following:
> 
>                     If ((SMRW (0x0B, 0x16, 0x21, RefOf (Local0)) == Zero))
> 
> In the called control method, "RefOf (Local1)" is referred as Arg3, is
> stored a value like the following:
> 
>                         Arg3 = \_SB.PCI0.LPCB.EC0.SMD0
> 
> In aml_store(), lvalue is reset if lvalue is a LocalX.  But since that
> was done before resolving the reference, lvalue was not reset if
> lvalue is a reference of LocalX.
> 
> diff #1 fixes that problem.  It resets lvalue after resolving
> references.
> 
> ok?
> 
> diff #2 adds aml_die() if any memory corruption occurs when creating
> field in a buffer.  This actually happens on my vaio (pro pk 14) if
> diff #1 is not applied.
> 
> ok?
> 
> diff #1
> 
> Index: sys/dev/acpi/dsdt.c
> ===================================================================
> RCS file: /var/cvs/openbsd/src/sys/dev/acpi/dsdt.c,v
> retrieving revision 1.257
> diff -u -p -r1.257 dsdt.c
> --- sys/dev/acpi/dsdt.c       17 Dec 2020 17:57:19 -0000      1.257
> +++ sys/dev/acpi/dsdt.c       26 Feb 2021 04:12:03 -0000
> @@ -2961,11 +2961,11 @@ aml_store(struct aml_scope *scope, struc
>               aml_rwfield(rhs, 0, rhs->v_field.bitlen, &tmp, ACPI_IOREAD);
>               rhs = &tmp;
>       }
> +
> +     lhs = aml_gettgt(lhs, AMLOP_STORE);
>       /* Store to LocalX: free value */
>       if (lhs->stack >= AMLOP_LOCAL0 && lhs->stack <= AMLOP_LOCAL7)
>               aml_freevalue(lhs);
> -
> -     lhs = aml_gettgt(lhs, AMLOP_STORE);
>       switch (lhs->type) {
>       case AML_OBJTYPE_UNINITIALIZED:
>               aml_copyvalue(lhs, rhs);
> 
> diff #2
> 
> Index: sys/dev/acpi/dsdt.c
> ===================================================================
> RCS file: /var/cvs/openbsd/src/sys/dev/acpi/dsdt.c,v
> retrieving revision 1.257
> diff -u -p -r1.257 dsdt.c
> --- sys/dev/acpi/dsdt.c       17 Dec 2020 17:57:19 -0000      1.257
> +++ sys/dev/acpi/dsdt.c       26 Feb 2021 04:33:21 -0000
> @@ -2742,11 +2742,17 @@ aml_rwfield(struct aml_value *fld, int b
>       } else if (mode == ACPI_IOREAD) {
>               /* bufferfield:read */
>               _aml_setvalue(val, AML_OBJTYPE_INTEGER, 0, 0);
> +             if (ref1->length < aml_bytepos(fld->v_field.bitpos) +
> +                 aml_bytelen(fld->v_field.bitlen))
> +                     aml_die("bufferfield:read out of range");
>               aml_bufcpy(&val->v_integer, 0, ref1->v_buffer,
>                   fld->v_field.bitpos, fld->v_field.bitlen);
>       } else {
>               /* bufferfield:write */
>               val = aml_convert(val, AML_OBJTYPE_INTEGER, -1);
> +             if (ref1->length < aml_bytepos(fld->v_field.bitpos) +
> +                 aml_bytelen(fld->v_field.bitlen))
> +                     aml_die("bufferfield:write out of range");
>               aml_bufcpy(ref1->v_buffer, fld->v_field.bitpos, &val->v_integer,
>                   0, fld->v_field.bitlen);
>               aml_delref(&val, "wrbuffld");

It's better to die when creating a field which refers out of range
memory.

ok?

Index: sys/dev/acpi/dsdt.c
===================================================================
RCS file: /disk/cvs/openbsd/src/sys/dev/acpi/dsdt.c,v
retrieving revision 1.257
diff -u -p -r1.257 dsdt.c
--- sys/dev/acpi/dsdt.c 17 Dec 2020 17:57:19 -0000      1.257
+++ sys/dev/acpi/dsdt.c 27 Feb 2021 09:58:31 -0000
@@ -2790,6 +2790,11 @@ aml_createfield(struct aml_value *field,
            data->type != AML_OBJTYPE_BUFFER)
                data = aml_convert(data, AML_OBJTYPE_BUFFER, -1);
 
+       if (field->type == AML_OBJTYPE_BUFFERFIELD &&
+           data->length < aml_bytepos(bpos) + aml_bytelen(blen))
+               aml_die("%s(%s) out of range\n", aml_mnem(opcode, 0),
+                   aml_nodename(field->node));
+
        field->v_field.type = opcode;
        field->v_field.bitpos = bpos;
        field->v_field.bitlen = blen;

Reply via email to