Re: git: cfb1e92912b4 - main - sockets: don't malloc/free sockaddr memory on accept(2)
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 ***