Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 Jan 2016 23:20:15 +0000
From:      "Mathur, Vedant" <Vedant.Mathur@netapp.com>
To:        "freebsd-net@freebsd.org" <freebsd-net@freebsd.org>
Subject:   Performing a socket accept in listen sockets' upcall - Yes or No?
Message-ID:  <D2C42EDD.3FEBE%vedant@netapp.com>

next in thread | raw e-mail | index | archive | help
Hi all,

I am working with FreeBSD in an environment where majority of my applicatio=
ns run in the kernel and are heavily relying on the socket upcall mechanism=
. All of these kernel applications use the socket upcall mechanism for sock=
et I/O.

These applications also use the upcall mechanism to accept incoming TCP con=
nections.  How the applications do so is by registering a receive upcall on=
 the head socket and waiting for the upcall. When the stack makes the recei=
ve upcall on the listen socket, most of the applications defer the actual a=
ccept to a different thread using a queueing mechanism and return from the =
upcall.

However, I have some applications which instead of deferring the socket acc=
ept operation to a different thread want to perform the socket accept opera=
tion inline. In other words the application wants to accept the child socke=
t in the context of the listen sockets' upcall. My questions are regarding =
this behavior and are as follows:

A) First and foremost, does the FreeBSD socket upcall framework even suppor=
t such kind of an accept operation? Does this conceptually break FreeBSD so=
cket accept and upcall semantics? Is the upcall mechanism to be ONLY used f=
or socket I/O?

B) If the accept operation is supported in the context of the head sockets'=
 upcall then, how do we handle the use after free cases where issuing a hea=
d sockets upcall can potentially make the application accept and then close=
 the child socket which we access after the upcall returns. To be more spec=
ific, in FreeBSD 11.x the syncache_socket() code calls sonewconn() and then=
 connects the child socket to the peer. Later it calls soisconnected() whic=
h places the child socket in head's so_comp queue and makes an upcall which=
 can potentially free the child socket. Once syncache_socket() returns, the=
 call stack eventually returns until tcp_input() for TCP sockets. tcp_input=
() now calls tcp_do_segment() which accesses the child socket and its inpcb=
 and tcpcb which can potentially be freed memory.

If A) is possible then, I can see that commit r261242 modified the code  su=
ch that we deferred placing the child socket on the so_comp queue until the=
 connect was complete. I believe this change is still susceptible to the us=
e after free case described above.  If we agree then what are the potential=
 solutions?

Thanks!
Vedant Mathur



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?D2C42EDD.3FEBE%vedant>