git: e452fa70d507 - main - hid: Handle errors from copyin() in ioctl handlers

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Tue, 26 Dec 2023 02:04:13 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=e452fa70d50761b5fe5f19c3c93c107be116728c

commit e452fa70d50761b5fe5f19c3c93c107be116728c
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2023-12-26 01:37:49 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2023-12-26 02:04:00 +0000

    hid: Handle errors from copyin() in ioctl handlers
    
    If copyin() fails, the driver will proceed blindly with a zeroed buffer,
    which is not what we want.  In preparation for annotating copyin() with
    __result_use_check, start checking for errors.
    
    Reviewed by:    wulf
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D43102
---
 sys/dev/hid/hidraw.c | 32 ++++++++++++++++++++------------
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/sys/dev/hid/hidraw.c b/sys/dev/hid/hidraw.c
index fbc75aaa4e79..6a05b633cfc8 100644
--- a/sys/dev/hid/hidraw.c
+++ b/sys/dev/hid/hidraw.c
@@ -674,13 +674,16 @@ hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
 			sc->sc_state.quiet = true;
 		mtx_unlock(&sc->sc_mtx);
 		if (error != 0)
-			return(error);
+			return (error);
 
 		buf = HIDRAW_LOCAL_ALLOC(local_buf, hgd->hgd_maxlen);
-		copyin(hgd->hgd_data, buf, hgd->hgd_maxlen);
-		bus_topo_lock();
-		error = hid_set_report_descr(sc->sc_dev, buf, hgd->hgd_maxlen);
-		bus_topo_unlock();
+		error = copyin(hgd->hgd_data, buf, hgd->hgd_maxlen);
+		if (error == 0) {
+			bus_topo_lock();
+			error = hid_set_report_descr(sc->sc_dev, buf,
+			    hgd->hgd_maxlen);
+			bus_topo_unlock();
+		}
 		HIDRAW_LOCAL_FREE(local_buf, buf);
 
 		/* Realloc hidraw input queue */
@@ -737,8 +740,11 @@ hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
 		default:
 			return (EINVAL);
 		}
-		if (id != 0)
-			copyin(hgd->hgd_data, &id, 1);
+		if (id != 0) {
+			error = copyin(hgd->hgd_data, &id, 1);
+			if (error != 0)
+				return (error);
+		}
 		size = MIN(hgd->hgd_maxlen, size);
 		buf = HIDRAW_LOCAL_ALLOC(local_buf, size);
 		error = hid_get_report(sc->sc_dev, buf, size, NULL,
@@ -775,11 +781,13 @@ hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
 		}
 		size = MIN(hgd->hgd_maxlen, size);
 		buf = HIDRAW_LOCAL_ALLOC(local_buf, size);
-		copyin(hgd->hgd_data, buf, size);
-		if (id != 0)
-			id = *(uint8_t *)buf;
-		error = hid_set_report(sc->sc_dev, buf, size,
-		    hgd->hgd_report_type, id);
+		error = copyin(hgd->hgd_data, buf, size);
+		if (error == 0) {
+			if (id != 0)
+				id = *(uint8_t *)buf;
+			error = hid_set_report(sc->sc_dev, buf, size,
+			    hgd->hgd_report_type, id);
+		}
 		HIDRAW_LOCAL_FREE(local_buf, buf);
 		return (error);