lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:	Sat,  4 Aug 2012 15:33:41 -0600
From:	Jan Ariyasu <jan.ariyasu@...il.com>
To:	Vlad Yasevich <vyasevich@...il.com>,
	"David S. Miller" <davem@...emloft.net>,
	linux-sctp@...r.kernel.org, netdev@...r.kernel.org,
	linux-kernel@...r.kernel.org
Cc:	Jan Ariyasu <jan.ariyasu@...com>
Subject: [PATCH 08/13] SCTP: Make associations use per-namespace configuration.

These changes make associations namespace aware, including
association ID lists and their associated locks.

Signed-off-by: Jan Ariyasu <jan.ariyasu@...com>
---
 include/net/sctp/sctp.h    |    3 ---
 include/net/sctp/structs.h |    3 ++-
 net/sctp/associola.c       |   37 ++++++++++++++++++++++++-------------
 net/sctp/input.c           |   25 +++++++++++++++----------
 net/sctp/sm_sideeffect.c   |    9 ++++-----
 5 files changed, 45 insertions(+), 32 deletions(-)

diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 8488d5e..363a786 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -601,9 +601,6 @@ extern struct proto sctp_prot;
 extern struct proto sctpv6_prot;
 void sctp_put_port(struct sock *sk);
 
-extern struct idr sctp_assocs_id;
-extern spinlock_t sctp_assocs_id_lock;
-
 /* Static inline functions. */
 
 /* Convert from an IP version number to an Address Family symbol.  */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 2034d53..72d473b 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -2153,7 +2153,8 @@ struct sctp_transport *sctp_assoc_is_match(struct sctp_association *,
 					   const union sctp_addr *,
 					   const union sctp_addr *);
 void sctp_assoc_migrate(struct sctp_association *, struct sock *);
-void sctp_assoc_update(struct sctp_association *old,
+void sctp_assoc_update(struct net *net,
+		       struct sctp_association *old,
 		       struct sctp_association *new);
 
 __u32 sctp_association_get_next_tsn(struct sctp_association *);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 1bd956b..5b4be66 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -86,6 +86,8 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
 	int i;
 	sctp_paramhdr_t *p;
 	int err;
+	struct sctp_net_params *net_params =
+			sctp_get_params(sock_net(sk));
 
 	/* Retrieve the SCTP per socket area.  */
 	sp = sctp_sk((struct sock *)sk);
@@ -124,7 +126,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
 	 * socket values.
 	 */
 	asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt;
-	asoc->pf_retrans  = sctp_pf_retrans;
+	asoc->pf_retrans  = net_params->pf_retrans;
 
 	asoc->rto_initial = msecs_to_jiffies(sp->rtoinfo.srto_initial);
 	asoc->rto_max = msecs_to_jiffies(sp->rtoinfo.srto_max);
@@ -175,7 +177,8 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
 	asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
 	asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
 	asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
-		min_t(unsigned long, sp->autoclose, sctp_max_autoclose) * HZ;
+		min_t(unsigned long, sp->autoclose,
+			net_params->max_autoclose) * HZ;
 
 	/* Initializes the timers */
 	for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i)
@@ -281,7 +284,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
 	 * and will revert old behavior.
 	 */
 	asoc->peer.asconf_capable = 0;
-	if (sctp_addip_noauth)
+	if (net_params->addip_noauth_enable)
 		asoc->peer.asconf_capable = 1;
 	asoc->asconf_addr_del_pending = NULL;
 	asoc->src_out_of_asoc_ok = 0;
@@ -468,15 +471,18 @@ void sctp_association_free(struct sctp_association *asoc)
 /* Cleanup and free up an association. */
 static void sctp_association_destroy(struct sctp_association *asoc)
 {
+	struct sctp_ns_globals *ns_globals =
+		sctp_get_ns_globals(sock_net(asoc->base.sk));
+
 	SCTP_ASSERT(asoc->base.dead, "Assoc is not dead", return);
 
 	sctp_endpoint_put(asoc->ep);
 	sock_put(asoc->base.sk);
 
 	if (asoc->assoc_id != 0) {
-		spin_lock_bh(&sctp_assocs_id_lock);
-		idr_remove(&sctp_assocs_id, asoc->assoc_id);
-		spin_unlock_bh(&sctp_assocs_id_lock);
+		spin_lock_bh(&ns_globals->assocs_id_lock);
+		idr_remove(&ns_globals->assocs_id, asoc->assoc_id);
+		spin_unlock_bh(&ns_globals->assocs_id_lock);
 	}
 
 	WARN_ON(atomic_read(&asoc->rmem_alloc));
@@ -1204,7 +1210,8 @@ void sctp_assoc_migrate(struct sctp_association *assoc, struct sock *newsk)
 }
 
 /* Update an association (possibly from unexpected COOKIE-ECHO processing).  */
-void sctp_assoc_update(struct sctp_association *asoc,
+void sctp_assoc_update(struct net *net,
+		       struct sctp_association *asoc,
 		       struct sctp_association *new)
 {
 	struct sctp_transport *trans;
@@ -1416,6 +1423,8 @@ void sctp_assoc_sync_pmtu(struct sock *sk, struct sctp_association *asoc)
 /* Should we send a SACK to update our peer? */
 static inline int sctp_peer_needs_update(struct sctp_association *asoc)
 {
+	struct sctp_net_params *net_params =
+		sctp_get_params(sock_net(asoc->base.sk));
 	switch (asoc->state) {
 	case SCTP_STATE_ESTABLISHED:
 	case SCTP_STATE_SHUTDOWN_PENDING:
@@ -1423,8 +1432,8 @@ static inline int sctp_peer_needs_update(struct sctp_association *asoc)
 	case SCTP_STATE_SHUTDOWN_SENT:
 		if ((asoc->rwnd > asoc->a_rwnd) &&
 		    ((asoc->rwnd - asoc->a_rwnd) >= max_t(__u32,
-			   (asoc->base.sk->sk_rcvbuf >> sctp_rwnd_upd_shift),
-			   asoc->pathmtu)))
+			(asoc->base.sk->sk_rcvbuf >>
+			  net_params->rwnd_update_shift), asoc->pathmtu)))
 			return 1;
 		break;
 	default:
@@ -1582,23 +1591,25 @@ int sctp_assoc_set_id(struct sctp_association *asoc, gfp_t gfp)
 {
 	int assoc_id;
 	int error = 0;
+	struct sctp_ns_globals *ns_globals =
+		sctp_get_ns_globals(sock_net(asoc->base.sk));
 
 	/* If the id is already assigned, keep it. */
 	if (asoc->assoc_id)
 		return error;
 retry:
-	if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp)))
+	if (unlikely(!idr_pre_get(&ns_globals->assocs_id, gfp)))
 		return -ENOMEM;
 
-	spin_lock_bh(&sctp_assocs_id_lock);
-	error = idr_get_new_above(&sctp_assocs_id, (void *)asoc,
+	spin_lock_bh(&ns_globals->assocs_id_lock);
+	error = idr_get_new_above(&ns_globals->assocs_id, (void *)asoc,
 				    idr_low, &assoc_id);
 	if (!error) {
 		idr_low = assoc_id + 1;
 		if (idr_low == INT_MAX)
 			idr_low = 1;
 	}
-	spin_unlock_bh(&sctp_assocs_id_lock);
+	spin_unlock_bh(&ns_globals->assocs_id_lock);
 	if (error == -EAGAIN)
 		goto retry;
 	else if (error)
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 1b92da2..9b53b95 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -70,7 +70,8 @@ static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
 				      const union sctp_addr *laddr,
 				      const union sctp_addr *paddr,
 				      struct sctp_transport **transportp);
-static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr);
+static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
+					const union sctp_addr *laddr);
 static struct sctp_association *__sctp_lookup_association(
 					const union sctp_addr *local,
 					const union sctp_addr *peer,
@@ -129,6 +130,7 @@ int sctp_rcv(struct sk_buff *skb)
 	union sctp_addr dest;
 	int family;
 	struct sctp_af *af;
+	struct net *net = dev_net(skb->dev);
 
 	if (skb->pkt_type!=PACKET_HOST)
 		goto discard_it;
@@ -181,7 +183,7 @@ int sctp_rcv(struct sk_buff *skb)
 	asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
 
 	if (!asoc)
-		ep = __sctp_rcv_lookup_endpoint(&dest);
+		ep = __sctp_rcv_lookup_endpoint(net, &dest);
 
 	/* Retrieve the common input handling substructure. */
 	rcvr = asoc ? &asoc->base : &ep->base;
@@ -200,7 +202,7 @@ int sctp_rcv(struct sk_buff *skb)
 			sctp_endpoint_put(ep);
 			ep = NULL;
 		}
-		sk = *(sctp_get_ctl_sock(&init_net));
+		sk = *(sctp_get_ctl_sock(net));
 		ep = sctp_sk(sk)->ep;
 		sctp_endpoint_hold(ep);
 		rcvr = &ep->base;
@@ -539,7 +541,7 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
 	 * servers this needs to be solved differently.
 	 */
 	if (sock_owned_by_user(sk))
-		NET_INC_STATS_BH(&init_net, LINUX_MIB_LOCKDROPPEDICMPS);
+		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LOCKDROPPEDICMPS);
 
 	*app = asoc;
 	*tpp = transport;
@@ -588,7 +590,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
 	int err;
 
 	if (skb->len < ihlen + 8) {
-		ICMP_INC_STATS_BH(&init_net, ICMP_MIB_INERRORS);
+		ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS);
 		return;
 	}
 
@@ -602,7 +604,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
 	skb->network_header = saveip;
 	skb->transport_header = savesctp;
 	if (!sk) {
-		ICMP_INC_STATS_BH(&init_net, ICMP_MIB_INERRORS);
+		ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS);
 		return;
 	}
 	/* Warning:  The sock lock is held.  Remember to call
@@ -770,7 +772,8 @@ void sctp_unhash_endpoint(struct sctp_endpoint *ep)
 }
 
 /* Look up an endpoint. */
-static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr)
+static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
+					const union sctp_addr *laddr)
 {
 	struct sctp_hashbucket *head;
 	struct sctp_ep_common *epb;
@@ -787,7 +790,7 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l
 			goto hit;
 	}
 
-	ep = sctp_sk(*(sctp_get_ctl_sock(&init_net)))->ep;
+	ep = sctp_sk(*(sctp_get_ctl_sock(net)))->ep;
 
 hit:
 	sctp_endpoint_hold(ep);
@@ -1042,6 +1045,8 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
 	int have_auth = 0;
 	unsigned int chunk_num = 1;
 	__u8 *ch_end;
+	struct sctp_net_params *net_params =
+			sctp_get_params(dev_net(skb->dev));
 
 	/* Walk through the chunks looking for AUTH or ASCONF chunks
 	 * to help us find the association.
@@ -1074,8 +1079,8 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
 			    break;
 
 		    case SCTP_CID_ASCONF:
-			    if (have_auth || sctp_addip_noauth)
-				    asoc = __sctp_rcv_asconf_lookup(ch, laddr,
+			    if (have_auth || net_params->addip_noauth_enable)
+				asoc = __sctp_rcv_asconf_lookup(ch, laddr,
 							sctp_hdr(skb)->source,
 							transportp);
 		    default:
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 2c895fd..35cbbe5 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1058,8 +1058,8 @@ static void sctp_cmd_send_asconf(struct sctp_association *asoc)
 
 		/* Hold the chunk until an ASCONF_ACK is received. */
 		sctp_chunk_hold(asconf);
-		if (sctp_primitive_ASCONF(sock_net(asoc->base.sk), asoc,
-					  asconf))
+		if (sctp_primitive_ASCONF(sock_net(asoc->base.sk),
+					  asoc, asconf))
 			sctp_chunk_free(asconf);
 		else
 			asoc->addip_last_asconf = asconf;
@@ -1277,7 +1277,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
 			break;
 
 		case SCTP_CMD_UPDATE_ASSOC:
-		       sctp_assoc_update(asoc, cmd->obj.ptr);
+		       sctp_assoc_update(net, asoc, cmd->obj.ptr);
 		       break;
 
 		case SCTP_CMD_PURGE_OUTQUEUE:
@@ -1354,8 +1354,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
 			 * layer which will bail.
 			 */
 			error = sctp_cmd_process_init(net, commands, asoc,
-						      chunk, cmd->obj.ptr,
-						      gfp);
+						      chunk, cmd->obj.ptr, gfp);
 			break;
 
 		case SCTP_CMD_GEN_COOKIE_ECHO:
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ