From owner-freebsd-bugs Fri Oct 11 12:30:04 1996 Return-Path: owner-bugs Received: (from root@localhost) by freefall.freebsd.org (8.7.5/8.7.3) id MAA20241 for bugs-outgoing; Fri, 11 Oct 1996 12:30:04 -0700 (PDT) Received: (from gnats@localhost) by freefall.freebsd.org (8.7.5/8.7.3) id MAA20235; Fri, 11 Oct 1996 12:30:02 -0700 (PDT) Resent-Date: Fri, 11 Oct 1996 12:30:02 -0700 (PDT) Resent-Message-Id: <199610111930.MAA20235@freefall.freebsd.org> Resent-From: gnats (GNATS Management) Resent-To: freebsd-bugs Resent-Reply-To: FreeBSD-gnats@freefall.FreeBSD.org, fredriks@mcs.com Received: from fredriks-1.pr.mcs.net (fredriks-1.pr.mcs.net [205.164.50.241]) by freefall.freebsd.org (8.7.5/8.7.3) with ESMTP id MAA19888 for ; Fri, 11 Oct 1996 12:22:41 -0700 (PDT) Received: (from fredriks@localhost) by fredriks-1.pr.mcs.net (8.7.6/8.6.6) id LAA03741; Fri, 11 Oct 1996 11:07:27 -0500 (CDT) Message-Id: <199610111607.LAA03741@fredriks-1.pr.mcs.net> Date: Fri, 11 Oct 1996 11:07:27 -0500 (CDT) From: fredriks@mcs.com Reply-To: fredriks@mcs.com To: FreeBSD-gnats-submit@freebsd.org X-Send-Pr-Version: 3.2 Subject: kern/1775: accept does not preserve filedescriptor flags Sender: owner-bugs@freebsd.org X-Loop: FreeBSD.org Precedence: bulk >Number: 1775 >Category: kern >Synopsis: accept does not preserve file descriptor flags >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Oct 11 12:30:01 PDT 1996 >Last-Modified: >Originator: & Fredriksen >Organization: Flaaklypa Hackers >Release: FreeBSD 2.2-961004-SNAP i386 >Environment: FreeBSD. I think this bug has been around for a while. It is present in stable as well. >Description: accept1() in uipc_syscalls when it is cloning the listening socket does not preserve the filedescriptor flags, but sets them like this: fp->f_flag = FREAD|FWRITE; If you had turned on O_NONBLOCKING earlier on the listening socket, fcntl(newsocket, F_GETFL, 0) will not return the O_NONBLOCKING flag even though the flag is set in the socket itself. >How-To-Repeat: Included is a simple program that will print out what the flags on the accepted socket looks like. Just run it, and telnet lcoalhost 10000 to connect to it. #include #include #include #include #include #include #include #include #include #include #include int lsock; fd_set fm; procnewclient() { int msgsock = -1; int sock_flags; msgsock = accept(lsock, 0, 0); sock_flags = fcntl(msgsock, F_GETFL, 0); printf("Socket fcntl options are: %x\n", sock_flags); printf(" O_NONBLOCK = %d\n", sock_flags & O_NONBLOCK ? 1 : 0); printf(" O_APPEND = %d\n", sock_flags & O_APPEND ? 1 : 0); printf(" O_ASYNC = %d\n", sock_flags & O_ASYNC ? 1 : 0); close(msgsock); } main(int argc, char *argv[]) { int flag; struct timeval tv; struct sockaddr_in inaddr; /* * open our listener socket */ lsock = socket(PF_INET, SOCK_STREAM, 0); if (lsock < 0) { perror("cannot create socket"); exit(1); } bzero(&inaddr, sizeof(inaddr)); inaddr.sin_family = AF_INET; inaddr.sin_port = htons(10000); inaddr.sin_addr.s_addr = INADDR_ANY; flag = 1; setsockopt( lsock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof flag); if (bind (lsock, (struct sockaddr *)&inaddr, sizeof(inaddr)) < 0) { perror("bind failed"); exit(2); } listen (lsock, 5); fcntl(lsock, F_SETFL, O_NDELAY); while(1) { fflush(stdout); /* * add in our client log-in socket */ FD_SET(lsock, &fm); /* * wait for something to happen */ if( select( FD_SETSIZE, &fm, (fd_set *)0, (fd_set *)0, (struct timeval *) 0) >= 1) { /* * new client??? */ if( FD_ISSET( lsock, &fm)) { procnewclient(); } } } } >Fix: Here is a context diff: *** uipc_syscalls.c.orig Sun Sep 22 00:26:41 1996 --- uipc_syscalls.c Sun Sep 22 00:26:47 1996 *************** *** 164,170 **** int *retval; int compat; { ! struct file *fp; struct mbuf *nam; int namelen, error, s; struct socket *head, *so; --- 164,170 ---- int *retval; int compat; { ! struct file *fp, tfp; struct mbuf *nam; int namelen, error, s; struct socket *head, *so; *************** *** 206,211 **** --- 206,213 ---- splx(s); return (error); } + /* Keep a pointer to old file descriptor */ + tfp = fp; error = falloc(p, &fp, retval); if (error) { splx(s); *************** *** 221,229 **** head->so_qlen--; fp->f_type = DTYPE_SOCKET; ! fp->f_flag = FREAD|FWRITE; fp->f_ops = &socketops; fp->f_data = (caddr_t)so; nam = m_get(M_WAIT, MT_SONAME); (void) soaccept(so, nam); if (uap->name) { --- 223,232 ---- head->so_qlen--; fp->f_type = DTYPE_SOCKET; ! fp->f_flag = tfp->f_flag; fp->f_ops = &socketops; fp->f_data = (caddr_t)so; + tfp = NULL; nam = m_get(M_WAIT, MT_SONAME); (void) soaccept(so, nam); if (uap->name) { >Audit-Trail: >Unformatted: