Re: acpi_call crash fix

Aaron LI <[email protected]> Thu, 12 Dec 2019 21:49:38 +0800
Newsgroups gmane.os.dragonfly-bsd.kernel
Message-ID <[email protected]>
On December 12, 2019 4:42:18 AM GMT+08:00, K Staring <qdk@quickdekay=2Enet>=
 wrote:
>Hi,
>
>Another one=2E=2E While using acpi_call to disable the dGPU on my Dell XP=
S
>9560,
>I experienced a crash=2E FreeBSD had fixed this exact crash some months
>prior;
>included is a patch which imports the fix=2E
>
>
>Regards,
>
>Khamba
>
>
>--- a/sys/dev/acpica/acpi=2Ec
>+++ b/sys/dev/acpica/acpi=2Ec
>@@ -300,7 +300,7 @@ SYSCTL_INT(_debug_acpi, OID_AUTO, do_powerstate,
>CTLFLAG_RW,
> TUNABLE_INT("debug=2Eacpi=2Equirks", &acpi_quirks);
>=20
> /* Allow to call ACPI methods from userland=2E */
>-static int acpi_allow_mcall;
>+static int acpi_allow_mcall =3D 0;
> TUNABLE_INT("debug=2Eacpi=2Eallow_method_calls", &acpi_allow_mcall);
>=20
> static int acpi_susp_bounce;
>@@ -3230,6 +3230,136 @@ acpiclose(struct dev_close_args *ap)
>     return (0);
> }
>=20
>+//----------------------------------------------------------------------=
----
>+void acpi_call_fixup_pointers(ACPI_OBJECT *p, UINT8 *orig);
>+
>+static void
>+free_acpi_object_list(ACPI_OBJECT_LIST *list)
>+{
>+	for (int i =3D 0; i < list->Count; i++) {
>+		switch (list->Pointer[i]=2EType) {
>+		case ACPI_TYPE_STRING:
>+			AcpiOsFree(list->Pointer[i]=2EString=2EPointer);
>+			break;
>+		case ACPI_TYPE_BUFFER:
>+			AcpiOsFree(list->Pointer[i]=2EBuffer=2EPointer);
>+			break;
>+		default:
>+			break;
>+		}
>+	}
>+	AcpiOsFree(list);
>+}
>+
>+static ACPI_OBJECT_LIST *
>+copyin_acpi_object_list(ACPI_OBJECT_LIST *src)
>+{
>+	ACPI_OBJECT_LIST *dest;
>+	bool failed;
>+
>+	if (src->Count > 7)
>+		return NULL;
>+
>+	dest =3D AcpiOsAllocate(sizeof(ACPI_OBJECT_LIST) + sizeof(ACPI_OBJECT)
>* src->Count);
>+	if (!dest)
>+		return NULL;
>+
>+	dest->Count =3D src->Count;
>+	dest->Pointer =3D (ACPI_OBJECT *)(dest + 1);
>+	if (copyin(src->Pointer, dest->Pointer, sizeof(ACPI_OBJECT) *
>dest->Count)) {
>+		AcpiOsFree(dest);
>+		return NULL;
>+	}
>+
>+	failed =3D false;
>+
>+	for (int i =3D 0; i < dest->Count; i++) {
>+		switch (dest->Pointer[i]=2EType) {
>+		case ACPI_TYPE_INTEGER:
>+			break;
>+		case ACPI_TYPE_STRING: {
>+			void *v =3D AcpiOsAllocate(dest->Pointer[i]=2EString=2ELength);
>+			if (!v || copyin(dest->Pointer[i]=2EString=2EPointer, v,
>dest->Pointer[i]=2EString=2ELength))
>+				failed =3D true;
>+			dest->Pointer[i]=2EString=2EPointer =3D v;
>+			break;
>+		}
>+		case ACPI_TYPE_BUFFER: {
>+			void *v =3D AcpiOsAllocate(dest->Pointer[i]=2EBuffer=2ELength);
>+			if (!v || copyin(dest->Pointer[i]=2EBuffer=2EPointer, v,
>dest->Pointer[i]=2EBuffer=2ELength))
>+				failed =3D true;
>+			dest->Pointer[i]=2EString=2EPointer =3D v;
>+			break;
>+		}
>+		default:
>+			failed =3D true;
>+			break;
>+		}
>+	}
>+
>+	if (failed) {
>+		free_acpi_object_list(dest);
>+		dest =3D NULL;
>+	}
>+
>+	return dest;
>+}
>+
>+static int
>+acpi_call_ioctl(caddr_t addr)
>+{
>+	struct acpi_mcall_ioctl_arg *params;
>+	ACPI_OBJECT_LIST	*args;
>+	ACPI_BUFFER	result;
>+	char		path[256];
>+
>+	result=2ELength =3D ACPI_ALLOCATE_BUFFER;
>+	result=2EPointer =3D NULL;
>+
>+	params =3D (struct acpi_mcall_ioctl_arg*)addr;
>+	args =3D copyin_acpi_object_list(&params->args);
>+	if (!args)
>+		return EINVAL;
>+	if (copyinstr(params->path, path, sizeof(path), NULL))
>+			return EINVAL;
>+	params->retval =3D AcpiEvaluateObject(NULL, path, args, &result);
>+	if (ACPI_SUCCESS(params->retval))
>+	{
>+		if (result=2EPointer !=3D NULL)
>+		{
>+			if (params->result=2EPointer !=3D NULL)
>+			{=09
>+				params->result=2ELength =3D min(params->result=2ELength, result=2ELe=
ngth);
>+				if (result=2ELength >=3D sizeof(ACPI_OBJECT))
>+					acpi_call_fixup_pointers((ACPI_OBJECT*)result=2EPointer,
>params->result=2EPointer);
>+				copyout(result=2EPointer, params->result=2EPointer,
>+						params->result=2ELength);
>+				params->reslen =3D result=2ELength;
>+			}
>+			AcpiOsFree(result=2EPointer);
>+		}
>+	}
>+	free_acpi_object_list(args);
>+
>+	return (0);
>+}
>+
>+void
>+acpi_call_fixup_pointers(ACPI_OBJECT *p, UINT8 *dest)
>+{
>+	switch (p->Type)
>+	{
>+	case ACPI_TYPE_STRING:
>+		p->String=2EPointer +=3D dest - (UINT8*)p;
>+		break;
>+	case ACPI_TYPE_BUFFER:
>+		p->Buffer=2EPointer +=3D dest - (UINT8*)p;
>+		break;
>+	}
>+}
>+
>+//----------------------------------------------------------------------=
----
>+
> static int
> acpiioctl(struct dev_ioctl_args *ap)
> {
>@@ -3297,40 +3427,7 @@ acpiioctl(struct dev_ioctl_args *ap)
> 	break;
>     case ACPIIO_DO_MCALL:
> 	if (acpi_allow_mcall =3D=3D 1) {
>-	    struct acpi_mcall_ioctl_arg *params;
>-	    ACPI_BUFFER result =3D { ACPI_ALLOCATE_BUFFER, NULL };
>-	    ACPI_OBJECT *resobj;
>-
>-	    error =3D EINVAL;
>-	    params =3D (struct acpi_mcall_ioctl_arg *)ap->a_data;
>-	    params->retval =3D AcpiEvaluateObject(NULL, params->path,
>-		&params->args, &result);
>-	    if (ACPI_SUCCESS(params->retval) && result=2EPointer !=3D NULL &&
>-		params->result=2EPointer !=3D NULL) {
>-		params->result=2ELength =3D min(params->result=2ELength,
>-		    result=2ELength);
>-		copyout(result=2EPointer, params->result=2EPointer,
>-		    params->result=2ELength);
>-		params->reslen =3D result=2ELength;
>-		if (result=2ELength >=3D sizeof(ACPI_OBJECT)) {
>-		    resobj =3D (ACPI_OBJECT *)params->result=2EPointer;
>-		    switch (resobj->Type) {
>-		    case ACPI_TYPE_STRING:
>-			resobj->String=2EPointer =3D (char *)
>-			    ((UINT8 *)(resobj->String=2EPointer) -
>-				(UINT8 *)result=2EPointer +
>-				(UINT8 *)resobj);
>-			break;
>-		    case ACPI_TYPE_BUFFER:
>-			resobj->Buffer=2EPointer -=3D (UINT8 *)result=2EPointer -
>-			    (UINT8 *)resobj;
>-			break;
>-		    }
>-		}
>-		error =3D 0;
>-	    }
>-	    if (result=2EPointer !=3D NULL)
>-		AcpiOsFree(result=2EPointer);
>+            error =3D acpi_call_ioctl(ap->a_data);
> 	} else {
> 		device_printf(sc->acpi_dev,
> 		    "debug=2Eacpi=2Eallow_method_calls must be set\n");

Hi, thank you very much for providing the nice patch=2E We've merged it in=
to the master and release branches=2E

Regards,
--=20
Aaron