Re: git: cfb1e92912b4 - main - sockets: don't malloc/free sockaddr memory on accept(2)

From: Mike Karels <mike_at_karels.net>
Date: Thu, 30 Nov 2023 16:56:23 UTC
On 30 Nov 2023, at 10:34, Gleb Smirnoff wrote:

> The branch main has been updated by glebius:
>
> URL: https://cgit.FreeBSD.org/src/commit/?id=cfb1e92912b4cf75360b7fbe86197cc29bc212c1
>
> commit cfb1e92912b4cf75360b7fbe86197cc29bc212c1
> Author:     Gleb Smirnoff <glebius@FreeBSD.org>
> AuthorDate: 2023-11-30 16:30:55 +0000
> Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
> CommitDate: 2023-11-30 16:30:55 +0000
>
>     sockets: don't malloc/free sockaddr memory on accept(2)
>
>     Let the accept functions provide stack memory for protocols to fill it in.
>     Generic code should provide sockaddr_storage, specialized code may provide
>     smaller structure.

Does this mean that families cannot support sockaddrs bigger than sockaddr_storage?
In particular, does local domain (aka unix domain)?  Did it before?

		Mike

>     While rewriting accept(2) make 'addrlen' a true in/out parameter, reporting
>     required length in case if provided length was insufficient.  Our manual
>     page accept(2) and POSIX don't explicitly require that, but one can read
>     the text as they do.  Linux also does that. Update tests accordingly.
>
>     Reviewed by:            rscheff, tuexen, zlei, dchagin
>     Differential Revision:  https://reviews.freebsd.org/D42635
> ---
>  sys/cam/ctl/ctl_ha.c                               |  9 +--
>  sys/compat/linux/linux_socket.c                    | 32 ++++-----
>  sys/dev/cxgbe/iw_cxgbe/cm.c                        |  7 +-
>  sys/dev/hyperv/hvsock/hv_sock.c                    |  7 +-
>  sys/dev/hyperv/hvsock/hv_sock.h                    |  2 +-
>  sys/dev/iscsi/icl_soft_proxy.c                     | 10 ++-
>  sys/kern/uipc_domain.c                             |  2 +-
>  sys/kern/uipc_socket.c                             |  9 ++-
>  sys/kern/uipc_syscalls.c                           | 67 +++++++-----------
>  sys/kern/uipc_usrreq.c                             | 10 +--
>  sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h |  2 +-
>  .../bluetooth/include/ng_btsocket_rfcomm.h         |  2 +-
>  sys/netgraph/bluetooth/include/ng_btsocket_sco.h   |  2 +-
>  sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c  | 72 +++++++++++--------
>  sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c | 62 ++++++++++-------
>  sys/netgraph/bluetooth/socket/ng_btsocket_sco.c    | 60 +++++++++-------
>  sys/netgraph/ng_ksocket.c                          | 12 ++--
>  sys/netinet/sctp_usrreq.c                          | 48 +++++--------
>  sys/netinet/sctp_var.h                             |  2 +-
>  sys/netinet/tcp_usrreq.c                           | 80 +++++++++-------------
>  sys/netinet6/in6_pcb.c                             | 19 -----
>  sys/netinet6/in6_pcb.h                             |  2 -
>  sys/ofed/drivers/infiniband/ulp/sdp/sdp_main.c     | 25 +++----
>  sys/rpc/svc_vc.c                                   | 12 ++--
>  sys/sys/protosw.h                                  |  2 +-
>  sys/sys/socketvar.h                                |  2 +-
>  sys/sys/syscallsubr.h                              |  8 +--
>  tests/sys/kern/socket_accept.c                     |  3 -
>  28 files changed, 261 insertions(+), 309 deletions(-)
>
> diff --git a/sys/cam/ctl/ctl_ha.c b/sys/cam/ctl/ctl_ha.c
> index 0828c46c8863..695006ed99e1 100644
> --- a/sys/cam/ctl/ctl_ha.c
> +++ b/sys/cam/ctl/ctl_ha.c
> @@ -397,7 +397,7 @@ static int
>  ctl_ha_accept(struct ha_softc *softc)
>  {
>  	struct socket *lso, *so;
> -	struct sockaddr *sap;
> +	struct sockaddr_in sin = { .sin_len = sizeof(sin) };
>  	int error;
>
>  	lso = softc->ha_lso;
> @@ -410,16 +410,11 @@ ctl_ha_accept(struct ha_softc *softc)
>  		goto out;
>  	}
>
> -	sap = NULL;
> -	error = soaccept(so, &sap);
> +	error = soaccept(so, (struct sockaddr *)&sin);
>  	if (error != 0) {
>  		printf("%s: soaccept() error %d\n", __func__, error);
> -		if (sap != NULL)
> -			free(sap, M_SONAME);
>  		goto out;
>  	}
> -	if (sap != NULL)
> -		free(sap, M_SONAME);
>  	softc->ha_so = so;
>  	ctl_ha_sock_setup(softc);
>  	return (0);
> diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
> index a5ed5c5c62db..2893e93bbcd7 100644
> --- a/sys/compat/linux/linux_socket.c
> +++ b/sys/compat/linux/linux_socket.c
> @@ -1017,31 +1017,29 @@ static int
>  linux_accept_common(struct thread *td, int s, l_uintptr_t addr,
>      l_uintptr_t namelen, int flags)
>  {
> -	struct sockaddr *sa;
> +	struct sockaddr_storage ss = { .ss_len = sizeof(ss) };
>  	struct file *fp, *fp1;
> -	int bflags, len;
>  	struct socket *so;
> -	int error, error1;
> +	socklen_t len;
> +	int bflags, error, error1;
>
>  	bflags = 0;
>  	fp = NULL;
> -	sa = NULL;
>
>  	error = linux_set_socket_flags(flags, &bflags);
>  	if (error != 0)
>  		return (error);
>
> -	if (PTRIN(addr) == NULL) {
> -		len = 0;
> -		error = kern_accept4(td, s, NULL, NULL, bflags, NULL);
> -	} else {
> +	if (PTRIN(addr) != NULL) {
>  		error = copyin(PTRIN(namelen), &len, sizeof(len));
>  		if (error != 0)
>  			return (error);
>  		if (len < 0)
>  			return (EINVAL);
> -		error = kern_accept4(td, s, &sa, &len, bflags, &fp);
> -	}
> +	} else
> +		len = 0;
> +
> +	error = kern_accept4(td, s, (struct sockaddr *)&ss, bflags, &fp);
>
>  	/*
>  	 * Translate errno values into ones used by Linux.
> @@ -1071,11 +1069,14 @@ linux_accept_common(struct thread *td, int s, l_uintptr_t addr,
>  		return (error);
>  	}
>
> -	if (len != 0) {
> -		error = linux_copyout_sockaddr(sa, PTRIN(addr), len);
> -		if (error == 0)
> -			error = copyout(&len, PTRIN(namelen),
> -			    sizeof(len));
> +	if (PTRIN(addr) != NULL) {
> +		len = min(ss.ss_len, len);
> +		error = linux_copyout_sockaddr((struct sockaddr *)&ss,
> +		    PTRIN(addr), len);
> +		if (error == 0) {
> +			len = ss.ss_len;
> +			error = copyout(&len, PTRIN(namelen), sizeof(len));
> +		}
>  		if (error != 0) {
>  			fdclose(td, fp, td->td_retval[0]);
>  			td->td_retval[0] = 0;
> @@ -1083,7 +1084,6 @@ linux_accept_common(struct thread *td, int s, l_uintptr_t addr,
>  	}
>  	if (fp != NULL)
>  		fdrop(fp, td);
> -	free(sa, M_SONAME);
>  	return (error);
>  }
>
> diff --git a/sys/dev/cxgbe/iw_cxgbe/cm.c b/sys/dev/cxgbe/iw_cxgbe/cm.c
> index 77158eb855df..84d6df3f2832 100644
> --- a/sys/dev/cxgbe/iw_cxgbe/cm.c
> +++ b/sys/dev/cxgbe/iw_cxgbe/cm.c
> @@ -974,7 +974,7 @@ process_newconn(struct c4iw_listen_ep *master_lep, struct socket *new_so)
>  {
>  	struct c4iw_listen_ep *real_lep = NULL;
>  	struct c4iw_ep *new_ep = NULL;
> -	struct sockaddr_in *remote = NULL;
> +	struct sockaddr_storage remote = { .ss_len = sizeof(remote) };
>  	int ret = 0;
>
>  	MPASS(new_so != NULL);
> @@ -1019,19 +1019,16 @@ process_newconn(struct c4iw_listen_ep *master_lep, struct socket *new_so)
>  	new_ep->com.state = MPA_REQ_WAIT;
>
>  	setiwsockopt(new_so);
> -	ret = soaccept(new_so, (struct sockaddr **)&remote);
> +	ret = soaccept(new_so, (struct sockaddr *)&remote);
>  	if (ret != 0) {
>  		CTR4(KTR_IW_CXGBE,
>  				"%s:listen sock:%p, new sock:%p, ret:%d",
>  				__func__, master_lep->com.so, new_so, ret);
> -		if (remote != NULL)
> -			free(remote, M_SONAME);
>  		soclose(new_so);
>  		c4iw_put_ep(&new_ep->com);
>  		c4iw_put_ep(&real_lep->com);
>  		return;
>  	}
> -	free(remote, M_SONAME);
>
>  	START_EP_TIMER(new_ep);
>
> diff --git a/sys/dev/hyperv/hvsock/hv_sock.c b/sys/dev/hyperv/hvsock/hv_sock.c
> index 60cdfecf3bee..655cc990876e 100644
> --- a/sys/dev/hyperv/hvsock/hv_sock.c
> +++ b/sys/dev/hyperv/hvsock/hv_sock.c
> @@ -478,7 +478,7 @@ hvs_trans_listen(struct socket *so, int backlog, struct thread *td)
>  }
>
>  int
> -hvs_trans_accept(struct socket *so, struct sockaddr **nam)
> +hvs_trans_accept(struct socket *so, struct sockaddr *sa)
>  {
>  	struct hvs_pcb *pcb = so2hvspcb(so);
>
> @@ -488,10 +488,9 @@ hvs_trans_accept(struct socket *so, struct sockaddr **nam)
>  	if (pcb == NULL)
>  		return (EINVAL);
>
> -	*nam = sodupsockaddr((struct sockaddr *) &pcb->remote_addr,
> -	    M_NOWAIT);
> +	memcpy(sa, &pcb->remote_addr, pcb->remote_addr.sa_len);
>
> -	return ((*nam == NULL) ? ENOMEM : 0);
> +	return (0);
>  }
>
>  int
> diff --git a/sys/dev/hyperv/hvsock/hv_sock.h b/sys/dev/hyperv/hvsock/hv_sock.h
> index 98a9afb747bf..ee6416a29662 100644
> --- a/sys/dev/hyperv/hvsock/hv_sock.h
> +++ b/sys/dev/hyperv/hvsock/hv_sock.h
> @@ -100,7 +100,7 @@ void	hvs_trans_abort(struct socket *);
>  int	hvs_trans_attach(struct socket *, int, struct thread *);
>  int	hvs_trans_bind(struct socket *, struct sockaddr *, struct thread *);
>  int	hvs_trans_listen(struct socket *, int, struct thread *);
> -int	hvs_trans_accept(struct socket *, struct sockaddr **);
> +int	hvs_trans_accept(struct socket *, struct sockaddr *);
>  int	hvs_trans_connect(struct socket *,
>  	    struct sockaddr *, struct thread *);
>  int	hvs_trans_peeraddr(struct socket *, struct sockaddr **);
> diff --git a/sys/dev/iscsi/icl_soft_proxy.c b/sys/dev/iscsi/icl_soft_proxy.c
> index ee448116b0e9..db9bf12a688c 100644
> --- a/sys/dev/iscsi/icl_soft_proxy.c
> +++ b/sys/dev/iscsi/icl_soft_proxy.c
> @@ -205,7 +205,7 @@ icl_accept_thread(void *arg)
>  {
>  	struct icl_listen_sock *ils;
>  	struct socket *head, *so;
> -	struct sockaddr *sa;
> +	struct sockaddr_storage ss = { .ss_len = sizeof(ss) };
>  	int error;
>
>  	ils = arg;
> @@ -231,17 +231,15 @@ icl_accept_thread(void *arg)
>  			continue;
>  		}
>
> -		sa = NULL;
> -		error = soaccept(so, &sa);
> +		error = soaccept(so, (struct sockaddr *)&ss);
>  		if (error != 0) {
>  			ICL_WARN("soaccept error %d", error);
> -			if (sa != NULL)
> -				free(sa, M_SONAME);
>  			soclose(so);
>  			continue;
>  		}
>
> -		(ils->ils_listen->il_accept)(so, sa, ils->ils_id);
> +		(ils->ils_listen->il_accept)(so, (struct sockaddr *)&ss,
> +		    ils->ils_id);
>  	}
>  }
>
> diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c
> index 03e6856b7750..cf9b91511574 100644
> --- a/sys/kern/uipc_domain.c
> +++ b/sys/kern/uipc_domain.c
> @@ -53,7 +53,7 @@ static struct mtx dom_mtx;		/* domain list lock */
>  MTX_SYSINIT(domain, &dom_mtx, "domain list", MTX_DEF);
>
>  static int
> -pr_accept_notsupp(struct socket *so, struct sockaddr **nam)
> +pr_accept_notsupp(struct socket *so, struct sockaddr *sa)
>  {
>  	return (EOPNOTSUPP);
>  }
> diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
> index b59051ae3350..d16c0049dc43 100644
> --- a/sys/kern/uipc_socket.c
> +++ b/sys/kern/uipc_socket.c
> @@ -1348,12 +1348,17 @@ soabort(struct socket *so)
>  }
>
>  int
> -soaccept(struct socket *so, struct sockaddr **nam)
> +soaccept(struct socket *so, struct sockaddr *sa)
>  {
> +#ifdef INVARIANTS
> +	u_char len = sa->sa_len;
> +#endif
>  	int error;
>
>  	CURVNET_SET(so->so_vnet);
> -	error = so->so_proto->pr_accept(so, nam);
> +	error = so->so_proto->pr_accept(so, sa);
> +	KASSERT(sa->sa_len <= len,
> +	    ("%s: protocol %p sockaddr overflow", __func__, so->so_proto));
>  	CURVNET_RESTORE();
>  	return (error);
>  }
> diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
> index a7ffb6ef3254..0361144f2763 100644
> --- a/sys/kern/uipc_syscalls.c
> +++ b/sys/kern/uipc_syscalls.c
> @@ -277,19 +277,18 @@ static int
>  accept1(struct thread *td, int s, struct sockaddr *uname, socklen_t *anamelen,
>      int flags)
>  {
> -	struct sockaddr *name;
> -	socklen_t namelen;
> +	struct sockaddr_storage ss = { .ss_len = sizeof(ss) };
> +	socklen_t addrlen;
>  	struct file *fp;
>  	int error;
>
> -	if (uname == NULL)
> -		return (kern_accept4(td, s, NULL, NULL, flags, NULL));
> -
> -	error = copyin(anamelen, &namelen, sizeof (namelen));
> -	if (error != 0)
> -		return (error);
> +	if (uname != NULL) {
> +		error = copyin(anamelen, &addrlen, sizeof(addrlen));
> +		if (error != 0)
> +			return (error);
> +	}
>
> -	error = kern_accept4(td, s, &name, &namelen, flags, &fp);
> +	error = kern_accept4(td, s, (struct sockaddr *)&ss, flags, &fp);
>
>  	if (error != 0)
>  		return (error);
> @@ -297,42 +296,40 @@ accept1(struct thread *td, int s, struct sockaddr *uname, socklen_t *anamelen,
>  #ifdef COMPAT_OLDSOCK
>  	if (SV_PROC_FLAG(td->td_proc, SV_AOUT) &&
>  	    (flags & ACCEPT4_COMPAT) != 0)
> -		((struct osockaddr *)name)->sa_family =
> -		    name->sa_family;
> +		((struct osockaddr *)&ss)->sa_family = ss.ss_family;
>  #endif
> -	error = copyout(name, uname, namelen);
> -	if (error == 0)
> -		error = copyout(&namelen, anamelen,
> -		    sizeof(namelen));
> +	if (uname != NULL) {
> +		addrlen = min(ss.ss_len, addrlen);
> +		error = copyout(&ss, uname, addrlen);
> +		if (error == 0) {
> +			addrlen = ss.ss_len;
> +			error = copyout(&addrlen, anamelen, sizeof(addrlen));
> +		}
> +	}
>  	if (error != 0)
>  		fdclose(td, fp, td->td_retval[0]);
>  	fdrop(fp, td);
> -	free(name, M_SONAME);
> +
>  	return (error);
>  }
>
>  int
> -kern_accept(struct thread *td, int s, struct sockaddr **name,
> -    socklen_t *namelen, struct file **fp)
> +kern_accept(struct thread *td, int s, struct sockaddr *sa, struct file **fp)
>  {
> -	return (kern_accept4(td, s, name, namelen, ACCEPT4_INHERIT, fp));
> +	return (kern_accept4(td, s, sa, ACCEPT4_INHERIT, fp));
>  }
>
>  int
> -kern_accept4(struct thread *td, int s, struct sockaddr **name,
> -    socklen_t *namelen, int flags, struct file **fp)
> +kern_accept4(struct thread *td, int s, struct sockaddr *sa, int flags,
> +    struct file **fp)
>  {
>  	struct file *headfp, *nfp = NULL;
> -	struct sockaddr *sa = NULL;
>  	struct socket *head, *so;
>  	struct filecaps fcaps;
>  	u_int fflag;
>  	pid_t pgid;
>  	int error, fd, tmp;
>
> -	if (name != NULL)
> -		*name = NULL;
> -
>  	AUDIT_ARG_FD(s);
>  	error = getsock_cap(td, s, &cap_accept_rights,
>  	    &headfp, &fcaps);
> @@ -386,29 +383,15 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name,
>  	(void) fo_ioctl(nfp, FIONBIO, &tmp, td->td_ucred, td);
>  	tmp = fflag & FASYNC;
>  	(void) fo_ioctl(nfp, FIOASYNC, &tmp, td->td_ucred, td);
> -	error = soaccept(so, &sa);
> -	if (error != 0)
> -		goto noconnection;
> -	if (sa == NULL) {
> -		if (name)
> -			*namelen = 0;
> -		goto done;
> -	}
> -	AUDIT_ARG_SOCKADDR(td, AT_FDCWD, sa);
> -	if (name) {
> -		/* check sa_len before it is destroyed */
> -		if (*namelen > sa->sa_len)
> -			*namelen = sa->sa_len;
> +
> +	if ((error = soaccept(so, sa)) == 0) {
> +		AUDIT_ARG_SOCKADDR(td, AT_FDCWD, sa);
>  #ifdef KTRACE
>  		if (KTRPOINT(td, KTR_STRUCT))
>  			ktrsockaddr(sa);
>  #endif
> -		*name = sa;
> -		sa = NULL;
>  	}
>  noconnection:
> -	free(sa, M_SONAME);
> -
>  	/*
>  	 * close the new descriptor, assuming someone hasn't ripped it
>  	 * out from under us.
> diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
> index 53a7c2b2915a..3071a5169b72 100644
> --- a/sys/kern/uipc_usrreq.c
> +++ b/sys/kern/uipc_usrreq.c
> @@ -120,7 +120,10 @@ struct unp_defer {
>  static SLIST_HEAD(, unp_defer) unp_defers;
>  static int unp_defers_count;
>
> -static const struct sockaddr	sun_noname = { sizeof(sun_noname), AF_LOCAL };
> +static const struct sockaddr	sun_noname = {
> +	.sa_len = sizeof(sun_noname),
> +	.sa_family = AF_LOCAL,
> +};
>
>  /*
>   * Garbage collection of cyclic file descriptor/socket references occurs
> @@ -434,7 +437,7 @@ uipc_abort(struct socket *so)
>  }
>
>  static int
> -uipc_accept(struct socket *so, struct sockaddr **nam)
> +uipc_accept(struct socket *so, struct sockaddr *ret)
>  {
>  	struct unpcb *unp, *unp2;
>  	const struct sockaddr *sa;
> @@ -446,14 +449,13 @@ uipc_accept(struct socket *so, struct sockaddr **nam)
>  	unp = sotounpcb(so);
>  	KASSERT(unp != NULL, ("uipc_accept: unp == NULL"));
>
> -	*nam = malloc(sizeof(struct sockaddr_un), M_SONAME, M_WAITOK);
>  	UNP_PCB_LOCK(unp);
>  	unp2 = unp_pcb_lock_peer(unp);
>  	if (unp2 != NULL && unp2->unp_addr != NULL)
>  		sa = (struct sockaddr *)unp2->unp_addr;
>  	else
>  		sa = &sun_noname;
> -	bcopy(sa, *nam, sa->sa_len);
> +	bcopy(sa, ret, sa->sa_len);
>  	if (unp2 != NULL)
>  		unp_pcb_unlock_pair(unp, unp2);
>  	else
> diff --git a/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h b/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h
> index baaef9abb736..b512112f8b7d 100644
> --- a/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h
> +++ b/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h
> @@ -191,7 +191,7 @@ typedef struct ng_btsocket_l2cap_pcb *	ng_btsocket_l2cap_pcb_p;
>
>  void ng_btsocket_l2cap_abort      (struct socket *);
>  void ng_btsocket_l2cap_close      (struct socket *);
> -int  ng_btsocket_l2cap_accept     (struct socket *, struct sockaddr **);
> +int  ng_btsocket_l2cap_accept     (struct socket *, struct sockaddr *);
>  int  ng_btsocket_l2cap_attach     (struct socket *, int, struct thread *);
>  int  ng_btsocket_l2cap_bind       (struct socket *, struct sockaddr *,
>                                     struct thread *);
> diff --git a/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h b/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h
> index 88c0f8988587..d40b694ece14 100644
> --- a/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h
> +++ b/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h
> @@ -316,7 +316,7 @@ typedef struct ng_btsocket_rfcomm_pcb *	ng_btsocket_rfcomm_pcb_p;
>
>  void ng_btsocket_rfcomm_abort      (struct socket *);
>  void ng_btsocket_rfcomm_close      (struct socket *);
> -int  ng_btsocket_rfcomm_accept     (struct socket *, struct sockaddr **);
> +int  ng_btsocket_rfcomm_accept     (struct socket *, struct sockaddr *);
>  int  ng_btsocket_rfcomm_attach     (struct socket *, int, struct thread *);
>  int  ng_btsocket_rfcomm_bind       (struct socket *, struct sockaddr *,
>                                      struct thread *);
> diff --git a/sys/netgraph/bluetooth/include/ng_btsocket_sco.h b/sys/netgraph/bluetooth/include/ng_btsocket_sco.h
> index 071ddb8d80ef..282980cce881 100644
> --- a/sys/netgraph/bluetooth/include/ng_btsocket_sco.h
> +++ b/sys/netgraph/bluetooth/include/ng_btsocket_sco.h
> @@ -106,7 +106,7 @@ typedef struct ng_btsocket_sco_pcb *	ng_btsocket_sco_pcb_p;
>
>  void ng_btsocket_sco_abort      (struct socket *);
>  void ng_btsocket_sco_close      (struct socket *);
> -int  ng_btsocket_sco_accept     (struct socket *, struct sockaddr **);
> +int  ng_btsocket_sco_accept     (struct socket *, struct sockaddr *);
>  int  ng_btsocket_sco_attach     (struct socket *, int, struct thread *);
>  int  ng_btsocket_sco_bind       (struct socket *, struct sockaddr *,
>                                     struct thread *);
> diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c
> index 8fc64bb70929..d221cc34d36a 100644
> --- a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c
> +++ b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c
> @@ -1967,20 +1967,6 @@ ng_btsocket_l2cap_close(struct socket *so)
>  	(void)ng_btsocket_l2cap_disconnect(so);
>  } /* ng_btsocket_l2cap_close */
>
> -/*
> - * Accept connection on socket. Nothing to do here, socket must be connected
> - * and ready, so just return peer address and be done with it.
> - */
> -
> -int
> -ng_btsocket_l2cap_accept(struct socket *so, struct sockaddr **nam)
> -{
> -	if (ng_btsocket_l2cap_node == NULL)
> -		return (EINVAL);
> -
> -	return (ng_btsocket_l2cap_peeraddr(so, nam));
> -} /* ng_btsocket_l2cap_accept */
> -
>  /*
>   * Create and attach new socket
>   */
> @@ -2523,41 +2509,67 @@ out:
>  	return (error);
>  } /* ng_btsocket_listen */
>
> -/*
> - * Get peer address
> - */
> -
> -int
> -ng_btsocket_l2cap_peeraddr(struct socket *so, struct sockaddr **nam)
> +static int
> +ng_btsocket_l2cap_peeraddr1(struct socket *so, struct sockaddr_l2cap *sa)
>  {
>  	ng_btsocket_l2cap_pcb_p	pcb = so2l2cap_pcb(so);
> -	struct sockaddr_l2cap	sa;
>
>  	if (pcb == NULL)
>  		return (EINVAL);
>  	if (ng_btsocket_l2cap_node == NULL)
>  		return (EINVAL);
>
> -	bcopy(&pcb->dst, &sa.l2cap_bdaddr, sizeof(sa.l2cap_bdaddr));
> -	sa.l2cap_psm = htole16(pcb->psm);
> -	sa.l2cap_len = sizeof(sa);
> -	sa.l2cap_family = AF_BLUETOOTH;
> +	*sa = (struct sockaddr_l2cap ){
> +		.l2cap_len = sizeof(struct sockaddr_l2cap),
> +		.l2cap_family = AF_BLUETOOTH,
> +		.l2cap_psm = htole16(pcb->psm),
> +	};
> +	bcopy(&pcb->dst, &sa->l2cap_bdaddr, sizeof(sa->l2cap_bdaddr));
>  	switch(pcb->idtype){
>  	case NG_L2CAP_L2CA_IDTYPE_ATT:
> -		sa.l2cap_cid = NG_L2CAP_ATT_CID;
> +		sa->l2cap_cid = NG_L2CAP_ATT_CID;
>  		break;
>  	case NG_L2CAP_L2CA_IDTYPE_SMP:
> -		sa.l2cap_cid = NG_L2CAP_SMP_CID;
> +		sa->l2cap_cid = NG_L2CAP_SMP_CID;
>  		break;
>  	default:
> -		sa.l2cap_cid = 0;
> +		sa->l2cap_cid = 0;
>  		break;
>  	}
> -	sa.l2cap_bdaddr_type = pcb->dsttype;
> +	sa->l2cap_bdaddr_type = pcb->dsttype;
> +
> +	return (0);
> +}
> +
> +/*
> + * Get peer address
> + */
> +int
> +ng_btsocket_l2cap_peeraddr(struct socket *so, struct sockaddr **nam)
> +{
> +	struct sockaddr_l2cap sa;
> +	int error;
> +
> +	error = ng_btsocket_l2cap_peeraddr1(so, &sa);
> +	if (error != 0)
> +		return (error);
>  	*nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
>
>  	return ((*nam == NULL)? ENOMEM : 0);
> -} /* ng_btsocket_l2cap_peeraddr */
> +}
> +
> +/*
> + * Accept connection on socket. Nothing to do here, socket must be connected
> + * and ready, so just return peer address and be done with it.
> + */
> +int
> +ng_btsocket_l2cap_accept(struct socket *so, struct sockaddr *sa)
> +{
> +	if (ng_btsocket_l2cap_node == NULL)
> +		return (EINVAL);
> +
> +	return (ng_btsocket_l2cap_peeraddr1(so, (struct sockaddr_l2cap *)sa));
> +}
>
>  /*
>   * Send data to socket
> diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
> index 00225f8240e9..af542f3c258b 100644
> --- a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
> +++ b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
> @@ -370,17 +370,6 @@ ng_btsocket_rfcomm_close(struct socket *so)
>  	(void)ng_btsocket_rfcomm_disconnect(so);
>  } /* ng_btsocket_rfcomm_close */
>
> -/*
> - * Accept connection on socket. Nothing to do here, socket must be connected
> - * and ready, so just return peer address and be done with it.
> - */
> -
> -int
> -ng_btsocket_rfcomm_accept(struct socket *so, struct sockaddr **nam)
> -{
> -	return (ng_btsocket_rfcomm_peeraddr(so, nam));
> -} /* ng_btsocket_rfcomm_accept */
> -
>  /*
>   * Create and attach new socket
>   */
> @@ -925,28 +914,51 @@ out:
>  	return (error);
>  } /* ng_btsocket_listen */
>
> -/*
> - * Get peer address
> - */
> -
> -int
> -ng_btsocket_rfcomm_peeraddr(struct socket *so, struct sockaddr **nam)
> +static int
> +ng_btsocket_rfcomm_peeraddr1(struct socket *so, struct sockaddr_rfcomm *sa)
>  {
>  	ng_btsocket_rfcomm_pcb_p	pcb = so2rfcomm_pcb(so);
> -	struct sockaddr_rfcomm		sa;
>
>  	if (pcb == NULL)
>  		return (EINVAL);
>
> -	bcopy(&pcb->dst, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr));
> -	sa.rfcomm_channel = pcb->channel;
> -	sa.rfcomm_len = sizeof(sa);
> -	sa.rfcomm_family = AF_BLUETOOTH;
> +	*sa = (struct sockaddr_rfcomm ){
> +		.rfcomm_len = sizeof(struct sockaddr_rfcomm),
> +		.rfcomm_family = AF_BLUETOOTH,
> +		.rfcomm_channel = pcb->channel,
> +	};
> +	bcopy(&pcb->dst, &sa->rfcomm_bdaddr, sizeof(sa->rfcomm_bdaddr));
>
> +	return (0);
> +}
> +
> +/*
> + * Get peer address
> + */
> +int
> +ng_btsocket_rfcomm_peeraddr(struct socket *so, struct sockaddr **nam)
> +{
> +	struct sockaddr_rfcomm sa;
> +	int error;
> +
> +	error = ng_btsocket_rfcomm_peeraddr1(so, &sa);
> +	if (error != 0)
> +		return (error);
>  	*nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
>
>  	return ((*nam == NULL)? ENOMEM : 0);
> -} /* ng_btsocket_rfcomm_peeraddr */
> +}
> +
> +/*
> + * Accept connection on socket. Nothing to do here, socket must be connected
> + * and ready, so just return peer address and be done with it.
> + */
> +int
> +ng_btsocket_rfcomm_accept(struct socket *so, struct sockaddr *sa)
> +{
> +
> +	return (ng_btsocket_rfcomm_peeraddr1(so, (struct sockaddr_rfcomm *)sa));
> +}
>
>  /*
>   * Send data to socket
> @@ -1407,7 +1419,7 @@ static int
>  ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0)
>  {
>  	struct socket			*l2so;
> -	struct sockaddr_l2cap		*l2sa = NULL;
> +	struct sockaddr_l2cap		l2sa = { .l2cap_len = sizeof(l2sa) };
>  	ng_btsocket_l2cap_pcb_t		*l2pcb = NULL;
>  	ng_btsocket_rfcomm_session_p	 s = NULL;
>  	int				 error;
> @@ -1425,7 +1437,7 @@ ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0)
>  		return (error);
>  	}
>
> -	error = soaccept(l2so, (struct sockaddr **) &l2sa);
> +	error = soaccept(l2so, (struct sockaddr *)&l2sa);
>  	if (error != 0) {
>  		NG_BTSOCKET_RFCOMM_ERR(
>  "%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error);
> diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_sco.c b/sys/netgraph/bluetooth/socket/ng_btsocket_sco.c
> index 5e198956a829..d9700f91c132 100644
> --- a/sys/netgraph/bluetooth/socket/ng_btsocket_sco.c
> +++ b/sys/netgraph/bluetooth/socket/ng_btsocket_sco.c
> @@ -1176,20 +1176,6 @@ ng_btsocket_sco_close(struct socket *so)
>  	(void) ng_btsocket_sco_disconnect(so);
>  } /* ng_btsocket_sco_close */
>
> -/*
> - * Accept connection on socket. Nothing to do here, socket must be connected
> - * and ready, so just return peer address and be done with it.
> - */
> -
> -int
> -ng_btsocket_sco_accept(struct socket *so, struct sockaddr **nam)
> -{
> -	if (ng_btsocket_sco_node == NULL)
> -		return (EINVAL);
> -
> -	return (ng_btsocket_sco_peeraddr(so, nam));
> -} /* ng_btsocket_sco_accept */
> -
>  /*
>   * Create and attach new socket
>   */
> @@ -1623,32 +1609,56 @@ out:
>  	return (error);
>  } /* ng_btsocket_listen */
>
> -/*
> - * Get peer address
> - */
> -
> -int
> -ng_btsocket_sco_peeraddr(struct socket *so, struct sockaddr **nam)
> +static int
> +ng_btsocket_sco_peeraddr1(struct socket *so, struct sockaddr_sco *sa)
>  {
>  	ng_btsocket_sco_pcb_p	pcb = so2sco_pcb(so);
> -	struct sockaddr_sco	sa;
>
>  	if (pcb == NULL)
>  		return (EINVAL);
>  	if (ng_btsocket_sco_node == NULL)
>  		return (EINVAL);
>
> +	*sa = (struct sockaddr_sco ){
> +		.sco_len = sizeof(struct sockaddr_sco),
> +		.sco_family = AF_BLUETOOTH,
> +	};
>  	mtx_lock(&pcb->pcb_mtx);
> -	bcopy(&pcb->dst, &sa.sco_bdaddr, sizeof(sa.sco_bdaddr));
> +	bcopy(&pcb->dst, &sa->sco_bdaddr, sizeof(sa->sco_bdaddr));
>  	mtx_unlock(&pcb->pcb_mtx);
>
> -	sa.sco_len = sizeof(sa);
> -	sa.sco_family = AF_BLUETOOTH;
> +	return (0);
> +}
> +
> +/*
> + * Get peer address
> + */
> +int
> +ng_btsocket_sco_peeraddr(struct socket *so, struct sockaddr **nam)
> +{
> +	struct sockaddr_sco sa;
> +	int error;
>
> +	error = ng_btsocket_sco_peeraddr1(so, &sa);
> +	if (error != 0)
> +		return (error);
>  	*nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
>
>  	return ((*nam == NULL)? ENOMEM : 0);
> -} /* ng_btsocket_sco_peeraddr */
> +}
> +
> +/*
> + * Accept connection on socket. Nothing to do here, socket must be connected
> + * and ready, so just return peer address and be done with it.
> + */
> +int
> +ng_btsocket_sco_accept(struct socket *so, struct sockaddr *sa)
> +{
> +	if (ng_btsocket_sco_node == NULL)
> +		return (EINVAL);
> +
> +	return (ng_btsocket_sco_peeraddr1(so, (struct sockaddr_sco *)sa));
> +}
>
>  /*
>   * Send data to socket
> diff --git a/sys/netgraph/ng_ksocket.c b/sys/netgraph/ng_ksocket.c
> index 777f3261356d..23a53528833f 100644
> --- a/sys/netgraph/ng_ksocket.c
> +++ b/sys/netgraph/ng_ksocket.c
> @@ -1178,7 +1178,7 @@ ng_ksocket_accept(priv_p priv)
>  {
>  	struct socket *const head = priv->so;
>  	struct socket *so;
> -	struct sockaddr *sa = NULL;
> +	struct sockaddr_storage ss = { .ss_len = sizeof(ss) };
>  	struct ng_mesg *resp;
>  	struct ng_ksocket_accept *resp_data;
>  	node_p node;
> @@ -1196,12 +1196,11 @@ ng_ksocket_accept(priv_p priv)
>  	if (error)
>  		return (error);
>
> -	if ((error = soaccept(so, &sa)) != 0)
> +	if ((error = soaccept(so, (struct sockaddr *)&ss)) != 0)
>  		return (error);
>
>  	len = OFFSETOF(struct ng_ksocket_accept, addr);
> -	if (sa != NULL)
> -		len += sa->sa_len;
> +	len += ss.ss_len;
>
>  	NG_MKMESSAGE(resp, NGM_KSOCKET_COOKIE, NGM_KSOCKET_ACCEPT, len,
>  	    M_NOWAIT);
> @@ -1249,13 +1248,10 @@ ng_ksocket_accept(priv_p priv)
>  	/* Fill in the response data and send it or return it to the caller */
>  	resp_data = (struct ng_ksocket_accept *)resp->data;
>  	resp_data->nodeid = NG_NODE_ID(node);
> -	if (sa != NULL)
> -		bcopy(sa, &resp_data->addr, sa->sa_len);
> +	bcopy(&ss, &resp_data->addr, ss.ss_len);
>  	NG_SEND_MSG_ID(error, node, resp, priv->response_addr, 0);
>
>  out:
> -	if (sa != NULL)
> -		free(sa, M_SONAME);
>
>  	return (0);
>  }
> diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
> index 29d63f989e79..8fb96db84f95 100644
> --- a/sys/netinet/sctp_usrreq.c
> +++ b/sys/netinet/sctp_usrreq.c
> @@ -7271,7 +7271,7 @@ out:
>  static int sctp_defered_wakeup_cnt = 0;
>
>  int
> -sctp_accept(struct socket *so, struct sockaddr **addr)
> +sctp_accept(struct socket *so, struct sockaddr *sa)
>  {
>  	struct sctp_tcb *stcb;
>  	struct sctp_inpcb *inp;
> @@ -7338,39 +7338,25 @@ sctp_accept(struct socket *so, struct sockaddr **addr)
>  	switch (store.sa.sa_family) {
>  #ifdef INET
>  	case AF_INET:
> -		{
> -			struct sockaddr_in *sin;
> -
> -			SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
> -			if (sin == NULL)
> -				return (ENOMEM);
> -			sin->sin_family = AF_INET;
> -			sin->sin_len = sizeof(*sin);
> -			sin->sin_port = store.sin.sin_port;
> -			sin->sin_addr = store.sin.sin_addr;
> -			*addr = (struct sockaddr *)sin;
> -			break;
> -		}
> +		*(struct sockaddr_in *)sa = (struct sockaddr_in ){
> +			.sin_family = AF_INET,
> +			.sin_len = sizeof(struct sockaddr_in),
> +			.sin_port = store.sin.sin_port,
> +			.sin_addr = store.sin.sin_addr,
> +		};
> +		break;
>  #endif
>  #ifdef INET6
>  	case AF_INET6:
> -		{
> -			struct sockaddr_in6 *sin6;
> -
> -			SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
> -			if (sin6 == NULL)
> -				return (ENOMEM);
> -			sin6->sin6_family = AF_INET6;
> -			sin6->sin6_len = sizeof(*sin6);
> -			sin6->sin6_port = store.sin6.sin6_port;
> -			sin6->sin6_addr = store.sin6.sin6_addr;
> -			if ((error = sa6_recoverscope(sin6)) != 0) {
> -				SCTP_FREE_SONAME(sin6);
> -				return (error);
> -			}
> -			*addr = (struct sockaddr *)sin6;
> -			break;
> -		}
> +		*(struct sockaddr_in6 *)sa = (struct sockaddr_in6 ){
> +			.sin6_family = AF_INET6,
> +			.sin6_len = sizeof(struct sockaddr_in6),
> +			.sin6_port = store.sin6.sin6_port,
> +			.sin6_addr = store.sin6.sin6_addr,
> +		};
> +		if ((error = sa6_recoverscope((struct sockaddr_in6 *)sa)) != 0)
> +			return (error);
> +		break;
>  #endif
>  	default:
>  		/* TSNH */
> diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h
> index 3a649a1860e2..ff6672bd0248 100644
> --- a/sys/netinet/sctp_var.h
> +++ b/sys/netinet/sctp_var.h
> @@ -341,7 +341,7 @@ int sctp_peeloff(struct socket *, struct socket *, int, caddr_t, int *);
>  int sctp_ingetaddr(struct socket *, struct sockaddr **);
>  int sctp_peeraddr(struct socket *, struct sockaddr **);
>  int sctp_listen(struct socket *, int, struct thread *);
> -int sctp_accept(struct socket *, struct sockaddr **);
> +int sctp_accept(struct socket *, struct sockaddr *);
>
>  #endif				/* _KERNEL */
>
> diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
> index f89e60cce8cd..14e0b814dec9 100644
> --- a/sys/netinet/tcp_usrreq.c
> +++ b/sys/netinet/tcp_usrreq.c
> @@ -717,13 +717,11 @@ out:
>   * just return the address of the peer, storing through addr.
>   */
>  static int
> -tcp_usr_accept(struct socket *so, struct sockaddr **nam)
> +tcp_usr_accept(struct socket *so, struct sockaddr *sa)
>  {
> -	int error = 0;
>  	struct inpcb *inp;
>  	struct tcpcb *tp;
> -	struct in_addr addr;
> -	in_port_t port = 0;
> +	int error = 0;
>
>  	inp = sotoinpcb(so);
>  	KASSERT(inp != NULL, ("tcp_usr_accept: inp == NULL"));
> @@ -734,39 +732,30 @@ tcp_usr_accept(struct socket *so, struct sockaddr **nam)
>  	}
>  	tp = intotcpcb(inp);
>
> -	if (so->so_state & SS_ISDISCONNECTED) {
> +	if (so->so_state & SS_ISDISCONNECTED)
>  		error = ECONNABORTED;
> -		goto out;
> -	}
> -	/*
> -	 * We inline in_getpeeraddr and COMMON_END here, so that we can
> -	 * copy the data of interest and defer the malloc until after we
> -	 * release the lock.
> -	 */
> -	port = inp->inp_fport;
> -	addr = inp->inp_faddr;
> -
> -out:
> +	else
> +		*(struct sockaddr_in *)sa = (struct sockaddr_in ){
> +			.sin_family = AF_INET,
> +			.sin_len = sizeof(struct sockaddr_in),
> +			.sin_port = inp->inp_fport,
> +			.sin_addr = inp->inp_faddr,
> +		};
>  	tcp_bblog_pru(tp, PRU_ACCEPT, error);
>  	TCP_PROBE2(debug__user, tp, PRU_ACCEPT);
>  	INP_WUNLOCK(inp);
> -	if (error == 0)
> -		*nam = in_sockaddr(port, &addr);
> -	return error;
> +
> *** 273 LINES SKIPPED ***