changeset 19271:70ce0aa98662

12043 Streams ioctl for _I_CMD within kernel causes EFAULT Reviewed by: John Levon <john.levon@joyent.com> Reviewed by: Jason King <jason.king@joyent.com> Approved by: Robert Mustacchi <rm@fingolfin.org>
author Andy Fiddaman <omnios@citrus-it.co.uk>
date Fri, 29 Nov 2019 00:08:41 +0000
parents 1fc67d6c12d1
children 18c3b8d11ca1
files usr/src/uts/common/os/streamio.c
diffstat 1 files changed, 20 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/os/streamio.c	Thu Mar 01 10:18:07 2018 -0800
+++ b/usr/src/uts/common/os/streamio.c	Fri Nov 29 00:08:41 2019 +0000
@@ -3575,29 +3575,39 @@
 		if (stp->sd_flag & STRHUP)
 			return (ENXIO);
 
-		if ((scp = kmem_alloc(sizeof (strcmd_t), KM_NOSLEEP)) == NULL)
-			return (ENOMEM);
-
-		if (copyin((void *)arg, scp, sizeof (strcmd_t))) {
-			kmem_free(scp, sizeof (strcmd_t));
-			return (EFAULT);
+		if (copyflag == U_TO_K) {
+			if ((scp = kmem_alloc(sizeof (strcmd_t),
+			    KM_NOSLEEP)) == NULL) {
+				return (ENOMEM);
+			}
+
+			if (copyin((void *)arg, scp, sizeof (strcmd_t))) {
+				kmem_free(scp, sizeof (strcmd_t));
+				return (EFAULT);
+			}
+		} else {
+			scp = (strcmd_t *)arg;
 		}
 
 		access = job_control_type(scp->sc_cmd);
 		mutex_enter(&stp->sd_lock);
 		if (access != -1 && (error = i_straccess(stp, access)) != 0) {
 			mutex_exit(&stp->sd_lock);
-			kmem_free(scp, sizeof (strcmd_t));
+			if (copyflag == U_TO_K)
+				kmem_free(scp, sizeof (strcmd_t));
 			return (error);
 		}
 		mutex_exit(&stp->sd_lock);
 
 		*rvalp = 0;
 		if ((error = strdocmd(stp, scp, crp)) == 0) {
-			if (copyout(scp, (void *)arg, sizeof (strcmd_t)))
+			if (copyflag == U_TO_K &&
+			    copyout(scp, (void *)arg, sizeof (strcmd_t))) {
 				error = EFAULT;
-		}
-		kmem_free(scp, sizeof (strcmd_t));
+			}
+		}
+		if (copyflag == U_TO_K)
+			kmem_free(scp, sizeof (strcmd_t));
 		return (error);
 
 	case I_NREAD: