Skip site navigation (1)Skip section navigation (2)
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>