Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 14 Aug 2002 18:46:10 -0700 (PDT)
From:      Peter Wemm <peter@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 15992 for review
Message-ID:  <200208150146.g7F1kA20095454@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://people.freebsd.org/~peter/p4db/chv.cgi?CH=15992

Change 15992 by peter@peter_daintree on 2002/08/14 18:45:14

	Hmm. Another freshly spammed file. :-(

Affected files ...

.. //depot/projects/ia64/sys/kern/uipc_syscalls.c#17 integrate

Differences ...

==== //depot/projects/ia64/sys/kern/uipc_syscalls.c#17 (text+ko) ====

@@ -937,170 +937,213 @@
 			len = MIN(len, fromsa->sa_len);
 #ifdef COMPAT_OLDSOCK
 			if (mp->msg_flags & MSG_COMPAT)
-				((struct osockaddr *)fromsa)->sa_famil Initial pass thru sops to see what permissions are needed.
-	 * Also perform any checks that don't need repeating on each
-	 * attempt to satisfy the request vector.
-	 */
-	j = 0;		/* permission needed */
-	do_undos = 0;
-	for (i = 0; i < nsops; i++) {
-		sopptr = &sops[i];
-		if (sopptr->sem_num >= semaptr->sem_nsems) {
-			error = EFBIG;
-			goto done2;
+				((struct osockaddr *)fromsa)->sa_family =
+				    fromsa->sa_family;
+#endif
+			error = copyout(fromsa, mp->msg_name, (unsigned)len);
+			if (error)
+				goto out;
+		}
+		mp->msg_namelen = len;
+		if (namelenp &&
+		    (error = copyout(&len, namelenp, sizeof (int)))) {
+#ifdef COMPAT_OLDSOCK
+			if (mp->msg_flags & MSG_COMPAT)
+				error = 0;	/* old recvfrom didn't check */
+			else
+#endif
+			goto out;
 		}
-		if (sopptr->sem_flg & SEM_UNDO && sopptr->sem_op != 0)
-			do_undos = 1;
-		j |= (sopptr->sem_op == 0) ? SEM_R : SEM_A;
 	}
+	if (mp->msg_control) {
+#ifdef COMPAT_OLDSOCK
+		/*
+		 * We assume that old recvmsg calls won't receive access
+		 * rights and other control info, esp. as control info
+		 * is always optional and those options didn't exist in 4.3.
+		 * If we receive rights, trim the cmsghdr; anything else
+		 * is tossed.
+		 */
+		if (control && mp->msg_flags & MSG_COMPAT) {
+			if (mtod(control, struct cmsghdr *)->cmsg_level !=
+			    SOL_SOCKET ||
+			    mtod(control, struct cmsghdr *)->cmsg_type !=
+			    SCM_RIGHTS) {
+				mp->msg_controllen = 0;
+				goto out;
+			}
+			control->m_len -= sizeof (struct cmsghdr);
+			control->m_data += sizeof (struct cmsghdr);
+		}
+#endif
+		len = mp->msg_controllen;
+		m = control;
+		mp->msg_controllen = 0;
+		ctlbuf = mp->msg_control;
 
-	if ((error = ipcperm(td, &semaptr->sem_perm, j))) {
-		DPRINTF(("error = %d from ipaccess\n", error));
-		goto done2;
-	}
+		while (m && len > 0) {
+			unsigned int tocopy;
 
-	/*
-	 * Loop trying to satisfy the vector of requests.
-	 * If we reach a point where we must wait, any requests already
-	 * performed are rolled back and we go to sleep until some other
-	 * process wakes us up.  At this point, we start all over again.
-	 *
-	 * This ensures that from the perspective of other tasks, a set
-	 * of requests is atomic (never partially satisfied).
-	 */
-	for (;;) {
-		do_wakeup = 0;
-		error = 0;	/* error return if necessary */
+			if (len >= m->m_len) 
+				tocopy = m->m_len;
+			else {
+				mp->msg_flags |= MSG_CTRUNC;
+				tocopy = len;
+			}
+		
+			if ((error = copyout(mtod(m, caddr_t),
+					ctlbuf, tocopy)) != 0)
+				goto out;
 
-		for (i = 0; i < nsops; i++) {
-			sopptr = &sops[i];
-			semptr = &semaptr->sem_base[sopptr->sem_num];
+			ctlbuf += tocopy;
+			len -= tocopy;
+			m = m->m_next;
+		}
+		mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
+	}
+out:
+	fputsock(so);
+	if (fromsa)
+		FREE(fromsa, M_SONAME);
+	if (control)
+		m_freem(control);
+	return (error);
+}
 
-			DPRINTF((
-			    "semop:  semaptr=%x, sem_base=%x, "
-			    "semptr=%x, sem[%d]=%d : op=%d, flag=%s\n",
-			    semaptr, semaptr->sem_base, semptr,
-			    sopptr->sem_num, semptr->semval, sopptr->sem_op,
-			    (sopptr->sem_flg & IPC_NOWAIT) ?
-			    "nowait" : "wait"));
+/*
+ * MPSAFE
+ */
+int
+recvfrom(td, uap)
+	struct thread *td;
+	register struct recvfrom_args /* {
+		int	s;
+		caddr_t	buf;
+		size_t	len;
+		int	flags;
+		caddr_t	from;
+		int	*fromlenaddr;
+	} */ *uap;
+{
+	struct msghdr msg;
+	struct iovec aiov;
+	int error;
 
-			if (sopptr->sem_op < 0) {
-				if (semptr->semval + sopptr->sem_op < 0) {
-					DPRINTF(("semop:  can't do it now\n"));
-					break;
-				} else {
-					semptr->semval += sopptr->sem_op;
-					if (semptr->semval == 0 &&
-					    semptr->semzcnt > 0)
-						do_wakeup = 1;
-				}
-			} else if (sopptr->sem_op == 0) {
-				if (semptr->semval != 0) {
-					DPRINTF(("semop:  not zero now\n"));
-					break;
-				}
-			} else if (semptr->semval + sopptr->sem_op >
-			    seminfo.semvmx) {
-				error = ERANGE;
-				break;
-			} else {
-				if (semptr->semncnt > 0)
-					do_wakeup = 1;
-				semptr->semval += sopptr->sem_op;
-			}
-		}
+	mtx_lock(&Giant);
+	if (uap->fromlenaddr) {
+		error = copyin(uap->fromlenaddr,
+		    &msg.msg_namelen, sizeof (msg.msg_namelen));
+		if (error)
+			goto done2;
+	} else {
+		msg.msg_namelen = 0;
+	}
+	msg.msg_name = uap->from;
+	msg.msg_iov = &aiov;
+	msg.msg_iovlen = 1;
+	aiov.iov_base = uap->buf;
+	aiov.iov_len = uap->len;
+	msg.msg_control = 0;
+	msg.msg_flags = uap->flags;
+	error = recvit(td, uap->s, &msg, uap->fromlenaddr);
+done2:
+	mtx_unlock(&Giant);
+	return(error);
+}
 
-		/*
-		 * Did we get through the entire vector?
-		 */
-		if (i >= nsops)
-			goto done;
+#ifdef COMPAT_OLDSOCK
+/*
+ * MPSAFE
+ */
+int
+orecvfrom(td, uap)
+	struct thread *td;
+	struct recvfrom_args *uap;
+{
 
-		/*
-		 * No ... rollback anything that we've already done
-		 */
-		DPRINTF(("semop:  rollback 0 through %d\n", i-1));
-		for (j = 0; j < i; j++)
-			semaptr->sem_base[sops[j].sem_num].semval -=
-			    sops[j].sem_op;
+	uap->flags |= MSG_COMPAT;
+	return (recvfrom(td, uap));
+}
+#endif
 
-		/* If we detected an error, return it */
-		if (error != 0)
-			goto done2;
 
-		/*
-		 * If the request that we couldn't satisfy has the
-		 * NOWAIT flag set then return with EAGAIN.
-		 */
-		if (sopptr->sem_flg & IPC_NOWAIT) {
-			error = EAGAIN;
-			goto done2;
-		}
+#ifdef COMPAT_OLDSOCK
+/*
+ * MPSAFE
+ */
+int
+orecv(td, uap)
+	struct thread *td;
+	register struct orecv_args /* {
+		int	s;
+		caddr_t	buf;
+		int	len;
+		int	flags;
+	} */ *uap;
+{
+	struct msghdr msg;
+	struct iovec aiov;
+	int error;
 
-		if (sopptr->sem_op == 0)
-			semptr->semzcnt++;
-		else
-			semptr->semncnt++;
+	mtx_lock(&Giant);
+	msg.msg_name = 0;
+	msg.msg_namelen = 0;
+	msg.msg_iov = &aiov;
+	msg.msg_iovlen = 1;
+	aiov.iov_base = uap->buf;
+	aiov.iov_len = uap->len;
+	msg.msg_control = 0;
+	msg.msg_flags = uap->flags;
+	error = recvit(td, uap->s, &msg, NULL);
+	mtx_unlock(&Giant);
+	return (error);
+}
 
-		DPRINTF(("semop:  good night!\n"));
-		error = tsleep(semaptr, (PZERO - 4) | PCATCH, "semwait", 0);
-		DPRINTF(("semop:  good morning (error=%d)!\n", error));
+/*
+ * Old recvmsg.  This code takes advantage of the fact that the old msghdr
+ * overlays the new one, missing only the flags, and with the (old) access
+ * rights where the control fields are now.
+ *
+ * MPSAFE
+ */
+int
+orecvmsg(td, uap)
+	struct thread *td;
+	register struct orecvmsg_args /* {
+		int	s;
+		struct	omsghdr *msg;
+		int	flags;
+	} */ *uap;
+{
+	struct msghdr msg;
+	struct iovec aiov[UIO_SMALLIOV], *iov;
+	int error;
 
-		if (error != 0) {
-			error = EINTR;
-			goto done2;
-		}
-		DPRINTF(("semop:  good morning!\n"));
+	error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
+	if (error)
+		return (error);
 
-		/*
-		 * Make sure that the semaphore still exists
-		 */
-		if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 ||
-		    semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) {
-			error = EIDRM;
+	mtx_lock(&Giant);
+	if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
+		if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) {
+			error = EMSGSIZE;
 			goto done2;
 		}
-
-		/*
-		 * The semaphore is still alive.  Readjust the count of
-		 * waiting processes.
-		 */
-		if (sopptr->sem_op == 0)
-			semptr->semzcnt--;
-		else
-			semptr->semncnt--;
+		MALLOC(iov, struct iovec *,
+		      sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
+		      M_WAITOK);
+	} else {
+		iov = aiov;
 	}
+	msg.msg_flags = uap->flags | MSG_COMPAT;
+	error = copyin(msg.msg_iov, iov,
+	    (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
+	if (error)
+		goto done;
+	msg.msg_iov = iov;
+	error = recvit(td, uap->s, &msg, &uap->msg->msg_namelen);
 
-done:
-	/*
-	 * Process any SEM_UNDO requests.
-	 */
-	if (do_undos) {
-		suptr = NULL;
-		for (i = 0; i < nsops; i++) {
-			/*
-			 * We only need to deal with SEM_UNDO's for non-zero
-			 * op's.
-			 */
-			int adjval;
-
-			if ((sops[i].sem_flg & SEM_UNDO) == 0)
-				continue;
-			adjval = sops[i].sem_op;
-			if (adjval == 0)
-				continue;
-			error = semundo_adjust(td, &suptr, semid,
-			    sops[i].sem_num, -adjval);
-			if (error == 0)
-				continue;
-
-			/*
-			 * Oh-Oh!  We ran out of either sem_undo's or undo's.
-			 * Rollback the adjustments to this point and then
-			 * rollback the semaphore ups and down so we can return
-			 * with an error with all structures restored.  We
-			 * rollback the undo's in the exact reverse order that
-			 * we applied them.  This gu0)
+	if (msg.msg_controllen && error == 0)
 		error = copyout(&msg.msg_controllen,
 		    &uap->msg->msg_accrightslen, sizeof (int));
 done:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe p4-projects" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200208150146.g7F1kA20095454>