Date: Fri, 11 Oct 1996 11:07:27 -0500 (CDT) From: fredriks@mcs.com To: FreeBSD-gnats-submit@freebsd.org Subject: kern/1775: accept does not preserve filedescriptor flags Message-ID: <199610111607.LAA03741@fredriks-1.pr.mcs.net> Resent-Message-ID: <199610111930.MAA20235@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>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 <stdlib.h> #include <unistd.h> #include <stdio.h> #include <sys/time.h> #include <signal.h> #include <sys/types.h> #include <sys/socket.h> #include <syslog.h> #include <netinet/in.h> #include <netdb.h> #include <sys/fcntl.h> 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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199610111607.LAA03741>