netinet6: remove INP_DROPPED checks from setsockopt(2)

The INP_DROPPED is going to become an internal flag for inpcb.  As of now
it means a TCP pcb that is in TCPS_CLOSED.  There is nothing wrong with
calling setsockopt(2) on such socket, although has no practical use.

This deletes a piece of code from 56713d16a0 / D16201.  There is no
description of the panic fixed, but I will speculate that the panic was
about in6p->in6p_outputopts being NULL as the inpcb already went through
in_pcbfree_deferred().  This also can be related to compressed TIME-WAIT,
that is also gone now.

With current locking this shouldn't be possible.  An inpcb goes through
in_pcbfree() only with pr_detach method, which is called from sofree(),
and the latter is called on losing the very last socket reference.  So, at
the point when in_pcbfree() is called, the socket has lost its file
descriptor reference and there can not be any running setsockopt() on it.

Leave the call to ip6_pcbopt() still embraced with INP_WLOCK(), since we
are modifying inpcb contents.

NB: the IPv6 setsockopt(2) definitely has room for improvement.  Several
memory allocations should be moved out of lock and made M_WAITOK.
Covering large piece of setsockopt(2) code with epoch(9) just because
ip6_setpktopts() calls ifnet_byindex() isn't correct either.

Reviewed by:		markj
Differential Revision:	https://reviews.freebsd.org/D56169
This commit is contained in:
Gleb Smirnoff
2026-04-12 11:32:15 -07:00
parent 0ba87ded9d
commit ce283e115b
-17
View File
@@ -1698,10 +1698,6 @@ do { \
break;
}
INP_WLOCK(inp);
if (inp->inp_flags & INP_DROPPED) {
INP_WUNLOCK(inp);
return (ECONNRESET);
}
optp = &inp->in6p_outputopts;
error = ip6_pcbopt(IPV6_HOPLIMIT,
(u_char *)&optval, sizeof(optval),
@@ -1827,10 +1823,6 @@ do { \
{
struct ip6_pktopts **optp;
INP_WLOCK(inp);
if (inp->inp_flags & INP_DROPPED) {
INP_WUNLOCK(inp);
return (ECONNRESET);
}
optp = &inp->in6p_outputopts;
error = ip6_pcbopt(optname,
(u_char *)&optval, sizeof(optval),
@@ -1919,10 +1911,6 @@ do { \
optlen = sopt->sopt_valsize;
optbuf = optbuf_storage;
INP_WLOCK(inp);
if (inp->inp_flags & INP_DROPPED) {
INP_WUNLOCK(inp);
return (ECONNRESET);
}
optp = &inp->in6p_outputopts;
error = ip6_pcbopt(optname, optbuf, optlen,
optp, (td != NULL) ? td->td_ucred : NULL,
@@ -2410,11 +2398,6 @@ ip6_pcbopt(int optname, u_char *buf, int len, struct ip6_pktopts **pktopt,
optdata = malloc(sopt->sopt_valsize, M_TEMP, M_WAITOK); \
malloc_optdata = true; \
INP_RLOCK(inp); \
if (inp->inp_flags & INP_DROPPED) { \
INP_RUNLOCK(inp); \
free(optdata, M_TEMP); \
return (ECONNRESET); \
} \
pktopt = inp->in6p_outputopts; \
if (pktopt && pktopt->field) { \
optdatalen = min(lenexpr, sopt->sopt_valsize); \