git: 7db5449ec5b1 - stable/13 - hid: Handle errors from copyin() in ioctl handlers

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Tue, 02 Jan 2024 01:12:55 UTC
The branch stable/13 has been updated by markj:

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

commit 7db5449ec5b176036b28c9b91a91ea2d09f37566
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2023-12-26 01:37:49 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-01-02 01:12:44 +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
    
    (cherry picked from commit e452fa70d50761b5fe5f19c3c93c107be116728c)
---
 sys/dev/hid/hidraw.c | 34 +++++++++++++++++++++-------------
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/sys/dev/hid/hidraw.c b/sys/dev/hid/hidraw.c
index 103f73bb3750..c47a1445f7af 100644
--- a/sys/dev/hid/hidraw.c
+++ b/sys/dev/hid/hidraw.c
@@ -673,14 +673,17 @@ 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);
-		/* Lock newbus around set_report_descr call */
-		mtx_lock(&Giant);
-		error = hid_set_report_descr(sc->sc_dev, buf, hgd->hgd_maxlen);
-		mtx_unlock(&Giant);
+		error = copyin(hgd->hgd_data, buf, hgd->hgd_maxlen);
+		if (error == 0) {
+			/* Lock newbus around set_report_descr call */
+			mtx_lock(&Giant);
+			error = hid_set_report_descr(sc->sc_dev, buf,
+			    hgd->hgd_maxlen);
+			mtx_unlock(&Giant);
+		}
 		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);