- Make in6_pcbbind_{addr,port}() static
- Properly authorize port binding in in_pcbsetport() and in6_pcbsetport() - Pass struct sockaddr_in6 to in6_pcbsetport() instead of just the address, so that we have a more complete context - Adjust udp6_output() to craft a sockaddr_in6 as it calls in6_pcbsetport() - Fix an issue in in_pcbbind() where we used the "dom_sa_any" pointer and not a copy of it, pointed out by bouyer@, thanks! Mailing list reference: http://mail-index.netbsd.org/tech-net/2009/04/29/msg001259.html
This commit is contained in:
parent
76ac165302
commit
ddcbe0e1dd
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: in_pcb.c,v 1.133 2009/04/23 17:02:26 elad Exp $ */
|
||||
/* $NetBSD: in_pcb.c,v 1.134 2009/04/30 18:18:34 elad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
@ -91,7 +91,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.133 2009/04/23 17:02:26 elad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.134 2009/04/30 18:18:34 elad Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ipsec.h"
|
||||
@ -224,8 +224,7 @@ in_pcballoc(struct socket *so, void *v)
|
||||
}
|
||||
|
||||
static int
|
||||
in_pcbsetport(struct in_addr *laddr, struct inpcb *inp,
|
||||
struct sockaddr_in *sin, kauth_cred_t cred)
|
||||
in_pcbsetport(struct sockaddr_in *sin, struct inpcb *inp, kauth_cred_t cred)
|
||||
{
|
||||
struct inpcbtable *table = inp->inp_table;
|
||||
struct socket *so = inp->inp_socket;
|
||||
@ -233,23 +232,33 @@ in_pcbsetport(struct in_addr *laddr, struct inpcb *inp,
|
||||
u_int16_t mymin, mymax;
|
||||
u_int16_t *lastport;
|
||||
u_int16_t lport = 0;
|
||||
enum kauth_network_req req;
|
||||
int error;
|
||||
|
||||
if (inp->inp_flags & INP_LOWPORT) {
|
||||
#ifndef IPNOPRIVPORTS
|
||||
if (kauth_authorize_network(cred,
|
||||
KAUTH_NETWORK_BIND,
|
||||
KAUTH_REQ_NETWORK_BIND_PRIVPORT, so,
|
||||
sin, NULL))
|
||||
return (EACCES);
|
||||
req = KAUTH_REQ_NETWORK_BIND_PRIVPORT;
|
||||
#else
|
||||
req = KAUTH_REQ_NETWORK_BIND_PORT;
|
||||
#endif
|
||||
|
||||
mymin = lowportmin;
|
||||
mymax = lowportmax;
|
||||
lastport = &table->inpt_lastlow;
|
||||
} else {
|
||||
req = KAUTH_REQ_NETWORK_BIND_PORT;
|
||||
|
||||
mymin = anonportmin;
|
||||
mymax = anonportmax;
|
||||
lastport = &table->inpt_lastport;
|
||||
}
|
||||
|
||||
/* XXX-kauth: KAUTH_REQ_NETWORK_BIND_AUTOASSIGN_{,PRIV}PORT */
|
||||
error = kauth_authorize_network(cred, KAUTH_NETWORK_BIND, req, so, sin,
|
||||
NULL);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
if (mymin > mymax) { /* sanity check */
|
||||
u_int16_t swp;
|
||||
|
||||
@ -262,9 +271,17 @@ in_pcbsetport(struct in_addr *laddr, struct inpcb *inp,
|
||||
for (cnt = mymax - mymin + 1; cnt; cnt--, lport--) {
|
||||
if (lport < mymin || lport > mymax)
|
||||
lport = mymax;
|
||||
if (!in_pcblookup_port(table, inp->inp_laddr,
|
||||
htons(lport), 1))
|
||||
if (!in_pcblookup_port(table, sin->sin_addr, htons(lport), 1)) {
|
||||
/* We have a free port, check with the secmodel(s). */
|
||||
error = kauth_authorize_network(cred,
|
||||
KAUTH_NETWORK_BIND, req, so, sin, NULL);
|
||||
if (error) {
|
||||
/* Secmodel says no. Keep looking. */
|
||||
continue;
|
||||
}
|
||||
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
return (EAGAIN);
|
||||
@ -322,7 +339,7 @@ in_pcbbind_port(struct inpcb *inp, struct sockaddr_in *sin, kauth_cred_t cred)
|
||||
}
|
||||
|
||||
if (sin->sin_port == 0) {
|
||||
error = in_pcbsetport(&inp->inp_laddr, inp, sin, cred);
|
||||
error = in_pcbsetport(sin, inp, cred);
|
||||
if (error)
|
||||
return (error);
|
||||
} else {
|
||||
@ -394,6 +411,7 @@ in_pcbbind(void *v, struct mbuf *nam, struct lwp *l)
|
||||
{
|
||||
struct inpcb *inp = v;
|
||||
struct sockaddr_in *sin = NULL; /* XXXGCC */
|
||||
struct sockaddr_in lsin;
|
||||
int error;
|
||||
|
||||
if (inp->inp_af != AF_INET)
|
||||
@ -409,8 +427,9 @@ in_pcbbind(void *v, struct mbuf *nam, struct lwp *l)
|
||||
if (nam->m_len != sizeof (*sin))
|
||||
return (EINVAL);
|
||||
} else {
|
||||
sin = (struct sockaddr_in *)
|
||||
__UNCONST(inp->inp_socket->so_proto->pr_domain->dom_sa_any);
|
||||
lsin = *((const struct sockaddr_in *)
|
||||
inp->inp_socket->so_proto->pr_domain->dom_sa_any);
|
||||
sin = &lsin;
|
||||
}
|
||||
|
||||
/* Bind address. */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: in6_pcb.c,v 1.106 2009/04/22 18:35:01 elad Exp $ */
|
||||
/* $NetBSD: in6_pcb.c,v 1.107 2009/04/30 18:18:34 elad Exp $ */
|
||||
/* $KAME: in6_pcb.c,v 1.84 2001/02/08 18:02:08 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -62,7 +62,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.106 2009/04/22 18:35:01 elad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.107 2009/04/30 18:18:34 elad Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ipsec.h"
|
||||
@ -187,7 +187,7 @@ in6_pcballoc(struct socket *so, void *v)
|
||||
/*
|
||||
* Bind address from sin6 to in6p.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
in6_pcbbind_addr(struct in6pcb *in6p, struct sockaddr_in6 *sin6, struct lwp *l)
|
||||
{
|
||||
int error;
|
||||
@ -257,7 +257,7 @@ in6_pcbbind_addr(struct in6pcb *in6p, struct sockaddr_in6 *sin6, struct lwp *l)
|
||||
/*
|
||||
* Bind port from sin6 to in6p.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
in6_pcbbind_port(struct in6pcb *in6p, struct sockaddr_in6 *sin6, struct lwp *l)
|
||||
{
|
||||
struct inpcbtable *table = in6p->in6p_table;
|
||||
@ -325,7 +325,7 @@ in6_pcbbind_port(struct in6pcb *in6p, struct sockaddr_in6 *sin6, struct lwp *l)
|
||||
|
||||
if (sin6->sin6_port == 0) {
|
||||
int e;
|
||||
e = in6_pcbsetport(&in6p->in6p_laddr, in6p, l);
|
||||
e = in6_pcbsetport(sin6, in6p, l);
|
||||
if (e != 0)
|
||||
return (e);
|
||||
} else {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: in6_pcb.h,v 1.33 2009/04/20 18:14:30 elad Exp $ */
|
||||
/* $NetBSD: in6_pcb.h,v 1.34 2009/04/30 18:18:34 elad Exp $ */
|
||||
/* $KAME: in6_pcb.h,v 1.45 2001/02/09 05:59:46 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -153,8 +153,6 @@ void in6_losing(struct in6pcb *);
|
||||
void in6_pcbinit(struct inpcbtable *, int, int);
|
||||
int in6_pcballoc(struct socket *, void *);
|
||||
int in6_pcbbind(void *, struct mbuf *, struct lwp *);
|
||||
int in6_pcbbind_addr(struct in6pcb *, struct sockaddr_in6 *, struct lwp *);
|
||||
int in6_pcbbind_port(struct in6pcb *, struct sockaddr_in6 *, struct lwp *);
|
||||
int in6_pcbconnect(void *, struct mbuf *, struct lwp *);
|
||||
void in6_pcbdetach(struct in6pcb *);
|
||||
void in6_pcbdisconnect(struct in6pcb *);
|
||||
@ -172,7 +170,7 @@ void in6_setsockaddr(struct in6pcb *, struct mbuf *);
|
||||
|
||||
/* in in6_src.c */
|
||||
int in6_selecthlim(struct in6pcb *, struct ifnet *);
|
||||
int in6_pcbsetport(struct in6_addr *, struct in6pcb *, struct lwp *);
|
||||
int in6_pcbsetport(struct sockaddr_in6 *, struct in6pcb *, struct lwp *);
|
||||
|
||||
extern struct rtentry *
|
||||
in6_pcbrtentry(struct in6pcb *);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: udp6_output.c,v 1.37 2008/10/24 22:30:32 dyoung Exp $ */
|
||||
/* $NetBSD: udp6_output.c,v 1.38 2009/04/30 18:18:34 elad Exp $ */
|
||||
/* $KAME: udp6_output.c,v 1.43 2001/10/15 09:19:52 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -62,7 +62,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.37 2008/10/24 22:30:32 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.38 2009/04/30 18:18:34 elad Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
|
||||
@ -78,6 +78,7 @@ __KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.37 2008/10/24 22:30:32 dyoung Exp
|
||||
#include <sys/proc.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/kauth.h>
|
||||
#include <sys/domain.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
@ -283,9 +284,22 @@ udp6_output(struct in6pcb *in6p, struct mbuf *m, struct mbuf *addr6,
|
||||
error = EADDRNOTAVAIL;
|
||||
goto release;
|
||||
}
|
||||
if (in6p->in6p_lport == 0 &&
|
||||
(error = in6_pcbsetport(laddr, in6p, l)) != 0)
|
||||
goto release;
|
||||
if (in6p->in6p_lport == 0) {
|
||||
/*
|
||||
* Craft a sockaddr_in6 for the local endpoint. Use the
|
||||
* "any" as a base, set the address, and recover the
|
||||
* scope.
|
||||
*/
|
||||
struct sockaddr_in6 lsin6 =
|
||||
*((const struct sockaddr_in6 *)in6p->in6p_socket->so_proto->pr_domain->dom_sa_any);
|
||||
lsin6.sin6_addr = *laddr;
|
||||
error = sa6_recoverscope(&lsin6);
|
||||
if (error)
|
||||
goto release;
|
||||
error = in6_pcbsetport(&lsin6, in6p, l);
|
||||
if (error)
|
||||
goto release;
|
||||
}
|
||||
} else {
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
|
||||
error = ENOTCONN;
|
||||
|
Loading…
Reference in New Issue
Block a user