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>
index | next in thread | raw e-mail
>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:
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199610111607.LAA03741>
