Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 12 Oct 1998 18:04:22 +0900 (JST)
From:      Satosi KOBAYASI <kobayasi@north.ad.jp>
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   bin/8281: writev() in libc_r causes loop
Message-ID:  <199810120904.SAA17994@athena.nextech.co.jp>

next in thread | raw e-mail | index | archive | help

>Number:         8281
>Category:       bin
>Synopsis:       writev() in libc_r causes loop
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Oct 12 02:10:00 PDT 1998
>Last-Modified:
>Originator:     Satosi KOBAYASI
>Organization:
NORTH (Network Organization for Research and Technology in Hokkaido)
>Release:        FreeBSD 2.2.7-RELEASE i386
>Environment:

FreeBSD athena 2.2.7-RELEASE FreeBSD 2.2.7-RELEASE #0: Sun Oct  4 17:27:30 JST 1998     kobayasi@athena:/usr/local/src/remote/sys/compile/ASIX  i386

>Description:

writev() in libc_r causes loop when it's called with the following
arguments:
	* the iovcnt is more than 0
	* at the last member of the iovec array, the iov_len set to 0

(Detail)

writev() defined in /usr/src/lib/libc_r/uthread/uthread_writev.c, calls
_thread_sys_writev() in itself.

When _thread_sys_writev() returns 0, writev() does't increment the index 
of the iovec array. So if the index points to the last member of the 
array, writev() calls _thread_sys_writev() with the member whose iov_len
set to 0. Because there is nothing to write, _thread_sys_writev() returns
0, and writev() doesn't increment the index...

>How-To-Repeat:

Compile the following code with -lc_r, and run it.

#include <stdio.h>
#include <string.h>

#include <fcntl.h>
#include <sys/stat.h>

#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

static char	b1[] = "test";
static char	b2[] = "foo";

int main(int argc, char **argv)
{
  int	fd;
  struct iovec	buf[2];

  if (argc != 2) {
    fprintf(stderr, "Usage: %s <filename>\n", *argv);
    exit(1);
  }
  
  if ((fd = open(*(argv + 1), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
    perror("open");
    exit(1);
  }

  buf[0].iov_base = b1;
  buf[0].iov_len = strlen(b1);
  
  buf[1].iov_base = b2;
  buf[1].iov_len = 0;

  if (writev(fd, buf, 2) < 0) {
    perror("writev");
    exit(1);
  }
  
  close(fd);
  
  exit(0);
}

    
>Fix:

Apply the following patch or something like this.


--- uthread_writev.c.orig	Mon Oct 12 17:38:58 1998
+++ uthread_writev.c	Mon Oct 12 18:00:02 1998
@@ -83,6 +83,16 @@
 			/* Perform a non-blocking write syscall: */
 			n = _thread_sys_writev(fd, &p_iov[idx], iovcnt - idx);
 
+			/* To avoid loop */
+			if (n == 0) { 
+				while (idx < iovcnt && p_iov[idx].iov_len == 0)
+					idx++;
+				if (idx == iovcnt) {
+					ret = num;
+					break;
+				}
+			}
+			
 			/* Check if one or more bytes were written: */
 			if (n > 0) {
 				/*
>Audit-Trail:
>Unformatted:

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



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