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>
