Subject: Re: gethostname and getdomainname
To: Christos Zoulas <christos@zoulas.com>
From: Ignatios Souvatzis <is@jocelyn.rhein.de>
List: tech-userlevel
Date: 11/17/1999 23:36:47
--u3/rZRmxL6MmkK24
Content-Type: text/plain; charset=us-ascii

Hi,

here is my new kern_sysctl.c diff for review.

I'm running a kernel with this right now, so it can't be too bad.

To summarize, changes from old:

- strings handled by the common functions sysctl_string() and sysctl_rdstring()
  are handled as arrays; that is, a truncated old value is returned, alongside
  with ENOMEM, if the buffer is too small.

- in all int, quad, and single struct cases, and all specials handled inside
  this file, oldlenp semantics are now as documented in the manual page, that
  is, a NULL oldp, but non-NULL oldlenp returns the needed size

[I had to change the oldlenp handling, so I thought I should make it as 
 advertized. Formerly, the subroutines would not know when a NULL oldlenp
 was passed, do the work anyway, and the value would be thrown away.]

Regards,
	Ignatios

--u3/rZRmxL6MmkK24
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="kern_sysctl.c.diffs"

--- kern_sysctl.c.orig	Wed Nov 17 23:14:20 1999
+++ kern_sysctl.c	Wed Nov 17 23:01:07 1999
@@ -104,6 +104,7 @@
 	size_t savelen = 0, oldlen = 0;
 	sysctlfn *fn;
 	int name[CTL_MAXNAME];
+	size_t *koldlenp;
 
 	/*
 	 * all top-level sysctl names are non-terminal
@@ -162,9 +163,12 @@
 		return (EOPNOTSUPP);
 	}
 
-	if (SCARG(uap, oldlenp) &&
-	    (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen))))
-		return (error);
+	koldlenp = SCARG(uap, oldlenp);
+	if (koldlenp) {
+		if ((error = copyin(koldlenp, &oldlen, sizeof(oldlen))))
+			return (error);
+		koldlenp = &oldlen;
+	}
 	if (SCARG(uap, old) != NULL) {
 		if (!uvm_useracc(SCARG(uap, old), oldlen, B_WRITE))
 			return (EFAULT);
@@ -192,7 +196,7 @@
 		savelen = oldlen;
 	}
 	error = (*fn)(name + 1, SCARG(uap, namelen) - 1, SCARG(uap, old),
-	    &oldlen, SCARG(uap, new), SCARG(uap, newlen), p);
+	    koldlenp, SCARG(uap, new), SCARG(uap, newlen), p);
 	if (SCARG(uap, old) != NULL) {
 		if (dolock)
 			uvm_vsunlock(p, SCARG(uap, old), savelen);
@@ -574,8 +578,11 @@
 		 * area during the process, so we have to do it by hand.
 		 */
 		curlen = strlen(ptmp->p_limit->pl_corename) + 1;
-		if (oldp && *oldlenp < curlen)
+		if (oldlenp  && *oldlenp < curlen) {
+			if (!oldp)
+				*oldlenp = curlen;
 			return (ENOMEM);
+		}
 		if (newp) {
 			if (securelevel > 2)
 				return EPERM;
@@ -606,7 +613,7 @@
 				goto cleanup;
 			}
 		}
-		if (oldp) {
+		if (oldp && oldlenp) {
 			*oldlenp = curlen;
 			error = copyout(ptmp->p_limit->pl_corename, oldp,
 			    curlen);
@@ -658,6 +665,39 @@
 }
 
 /*
+ * Convenience macros.
+ */
+
+#define SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, valp, len) 		\
+	if (oldlenp) {							\
+		if (!oldp)						\
+			*oldlenp = len;					\
+		else {							\
+			if (*oldlenp < len)				\
+				return(ENOMEM);				\
+			*oldlenp = len;					\
+			error = copyout((caddr_t)valp, oldp, len);	\
+		}							\
+	}
+
+#define SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, valp, typ) \
+	SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, valp, sizeof(typ))
+
+#define SYSCTL_SCALAR_NEWPCHECK_LEN(newp, newlen, len)	\
+	if (newp && newlen != len)			\
+		return (EINVAL);
+
+#define SYSCTL_SCALAR_NEWPCHECK_TYP(newp, newlen, typ)	\
+	SYSCTL_SCALAR_NEWPCHECK_LEN(newp, newlen, sizeof(typ))
+
+#define SYSCTL_SCALAR_NEWPCOP_LEN(newp, valp, len)	\
+	if (error == 0 && newp)				\
+		error = copyin(newp, valp, len);
+
+#define SYSCTL_SCALAR_NEWPCOP_TYP(newp, valp, typ)      \
+	SYSCTL_SCALAR_NEWPCOP_LEN(newp, valp, sizeof(typ))
+
+/*
  * Validate parameters and get old / set new parameters
  * for an integer-valued sysctl function.
  */
@@ -671,18 +711,14 @@
 {
 	int error = 0;
 
-	if (oldp && *oldlenp < sizeof(int))
-		return (ENOMEM);
-	if (newp && newlen != sizeof(int))
-		return (EINVAL);
-	*oldlenp = sizeof(int);
-	if (oldp)
-		error = copyout(valp, oldp, sizeof(int));
-	if (error == 0 && newp)
-		error = copyin(newp, valp, sizeof(int));
+	SYSCTL_SCALAR_NEWPCHECK_TYP(newp, newlen, int)
+	SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, valp, int)
+	SYSCTL_SCALAR_NEWPCOP_TYP(newp, valp, int)
+
 	return (error);
 }
 
+
 /*
  * As above, but read-only.
  */
@@ -695,13 +731,11 @@
 {
 	int error = 0;
 
-	if (oldp && *oldlenp < sizeof(int))
-		return (ENOMEM);
 	if (newp)
 		return (EPERM);
-	*oldlenp = sizeof(int);
-	if (oldp)
-		error = copyout((caddr_t)&val, oldp, sizeof(int));
+
+	SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, &val, int)
+
 	return (error);
 }
 
@@ -719,15 +753,10 @@
 {
 	int error = 0;
 
-	if (oldp && *oldlenp < sizeof(quad_t))
-		return (ENOMEM);
-	if (newp && newlen != sizeof(quad_t))
-		return (EINVAL);
-	*oldlenp = sizeof(quad_t);
-	if (oldp)
-		error = copyout(valp, oldp, sizeof(quad_t));
-	if (error == 0 && newp)
-		error = copyin(newp, valp, sizeof(quad_t));
+	SYSCTL_SCALAR_NEWPCHECK_TYP(newp, newlen, quad_t)
+	SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, valp, quad_t)
+	SYSCTL_SCALAR_NEWPCOP_TYP(newp, valp, quad_t)
+
 	return (error);
 }
 
@@ -743,16 +772,30 @@
 {
 	int error = 0;
 
-	if (oldp && *oldlenp < sizeof(quad_t))
-		return (ENOMEM);
 	if (newp)
 		return (EPERM);
-	*oldlenp = sizeof(quad_t);
-	if (oldp)
-		error = copyout((caddr_t)&val, oldp, sizeof(quad_t));
+
+	SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, &val, quad_t)
+
 	return (error);
 }
 
+#define SYSCTL_STRING_CORE(oldp, oldlenp, str)		\
+	if (oldlenp) {					\
+		len = strlen(str) + 1;			\
+		if (!oldp)				\
+			*oldlenp = len;			\
+		else {					\
+			if (*oldlenp < len) {		\
+				err2 = ENOMEM;		\
+				len = *oldlenp;		\
+			} else				\
+				*oldlenp = len;		\
+			error = copyout(str, oldp, len);\
+			if (error == 0)			\
+				error = err2;		\
+		}					\
+	}
 
 /*
  * Validate parameters and get old / set new parameters
@@ -767,16 +810,13 @@
 	char *str;
 	int maxlen;
 {
-	int len, error = 0;
+	int len, error = 0, err2 = 0;
 
-	len = strlen(str) + 1;
-	if (oldp && *oldlenp < len)
-		return (ENOMEM);
 	if (newp && newlen >= maxlen)
 		return (EINVAL);
-	*oldlenp = len;
-	if (oldp)
-		error = copyout(str, oldp, len);
+
+	SYSCTL_STRING_CORE(oldp, oldlenp, str);
+
 	if (error == 0 && newp) {
 		error = copyin(newp, str, newlen);
 		str[newlen] = 0;
@@ -794,16 +834,13 @@
 	void *newp;
 	char *str;
 {
-	int len, error = 0;
+	int len, error = 0, err2 = 0;
 
-	len = strlen(str) + 1;
-	if (oldp && *oldlenp < len)
-		return (ENOMEM);
 	if (newp)
 		return (EPERM);
-	*oldlenp = len;
-	if (oldp)
-		error = copyout(str, oldp, len);
+
+	SYSCTL_STRING_CORE(oldp, oldlenp, str);
+
 	return (error);
 }
 
@@ -822,16 +859,10 @@
 {
 	int error = 0;
 
-	if (oldp && *oldlenp < len)
-		return (ENOMEM);
-	if (newp && newlen > len)
-		return (EINVAL);
-	if (oldp) {
-		*oldlenp = len;
-		error = copyout(sp, oldp, len);
-	}
-	if (error == 0 && newp)
-		error = copyin(newp, sp, len);
+	SYSCTL_SCALAR_NEWPCHECK_LEN(newp, newlen, len)
+	SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, sp, len)
+	SYSCTL_SCALAR_NEWPCOP_LEN(newp, sp, len)
+
 	return (error);
 }
 
@@ -848,13 +879,11 @@
 {
 	int error = 0;
 
-	if (oldp && *oldlenp < len)
-		return (ENOMEM);
 	if (newp)
 		return (EPERM);
-	*oldlenp = len;
-	if (oldp)
-		error = copyout(sp, oldp, len);
+
+	SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, sp, len)
+
 	return (error);
 }
 

--u3/rZRmxL6MmkK24--