This is the first of three patches to set authentication by namespace. In this patch, the relevant routines in auth.c now check to see if auth_enable is set as a namespace parameter instead of checking the global parameter sctp_auth_enable. Signed-off-by: Jan Ariyasu <jan.ariyasu@xxxxxx> --- include/net/sctp/auth.h | 14 +++++++++----- include/net/sctp/structs.h | 3 ++- net/sctp/associola.c | 7 ++++--- net/sctp/auth.c | 29 +++++++++++++++++++---------- net/sctp/chunk.c | 5 +++-- net/sctp/endpointola.c | 6 ++++-- net/sctp/sm_make_chunk.c | 2 +- net/sctp/sm_sideeffect.c | 2 +- net/sctp/sm_statefuns.c | 16 ++++++++-------- net/sctp/socket.c | 10 ++++++---- 10 files changed, 57 insertions(+), 37 deletions(-) diff --git a/include/net/sctp/auth.h b/include/net/sctp/auth.h index 49bc957..e4e88cb 100644 --- a/include/net/sctp/auth.h +++ b/include/net/sctp/auth.h @@ -89,14 +89,15 @@ static inline void sctp_auth_key_hold(struct sctp_auth_bytes *key) void sctp_auth_key_put(struct sctp_auth_bytes *key); struct sctp_shared_key *sctp_auth_shkey_create(__u16 key_id, gfp_t gfp); void sctp_auth_destroy_keys(struct list_head *keys); -int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp); +int sctp_auth_asoc_init_active_key(struct net *net, + struct sctp_association *asoc, gfp_t gfp); struct sctp_shared_key *sctp_auth_get_shkey( const struct sctp_association *asoc, __u16 key_id); int sctp_auth_asoc_copy_shkeys(const struct sctp_endpoint *ep, struct sctp_association *asoc, gfp_t gfp); -int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp); +int sctp_auth_init_hmacs(struct net *net, struct sctp_endpoint *ep, gfp_t gfp); void sctp_auth_destroy_hmacs(struct crypto_hash *auth_hmacs[]); struct sctp_hmac *sctp_auth_get_hmac(__u16 hmac_id); struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc); @@ -104,8 +105,10 @@ void sctp_auth_asoc_set_default_hmac(struct sctp_association *asoc, struct sctp_hmac_algo_param *hmacs); int sctp_auth_asoc_verify_hmac_id(const struct sctp_association *asoc, __be16 hmac_id); -int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc); -int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc); +int sctp_auth_send_cid(struct net *net, + sctp_cid_t chunk, const struct sctp_association *asoc); +int sctp_auth_recv_cid(struct net *net, + sctp_cid_t chunk, const struct sctp_association *asoc); void sctp_auth_calculate_hmac(const struct sctp_association *asoc, struct sk_buff *skb, struct sctp_auth_chunk *auth, gfp_t gfp); @@ -117,7 +120,8 @@ int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep, int sctp_auth_set_key(struct sctp_endpoint *ep, struct sctp_association *asoc, struct sctp_authkey *auth_key); -int sctp_auth_set_active_key(struct sctp_endpoint *ep, +int sctp_auth_set_active_key(struct net *net, + struct sctp_endpoint *ep, struct sctp_association *asoc, __u16 key_id); int sctp_auth_del_key_id(struct sctp_endpoint *ep, diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index b016da6..dc2998a 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -805,7 +805,8 @@ struct sctp_datamsg { can_delay; /* should this message be Nagle delayed */ }; -struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *, +struct sctp_datamsg *sctp_datamsg_from_user(struct net *, + struct sctp_association *, struct sctp_sndrcvinfo *, struct msghdr *, int len); void sctp_datamsg_free(struct sctp_datamsg *); diff --git a/net/sctp/associola.c b/net/sctp/associola.c index b778eba..b640162 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1147,8 +1147,9 @@ static void sctp_assoc_bh_rcv(struct work_struct *work) * MUST silently discard these chunks if they are not placed * after an AUTH chunk in the packet. */ - if (sctp_auth_recv_cid(subtype.chunk, asoc) && !chunk->auth) - continue; + if (sctp_auth_recv_cid(net, subtype.chunk, asoc) && + !chunk->auth) + continue; /* Remember where the last DATA chunk came from so we * know where to send the SACK. @@ -1305,7 +1306,7 @@ void sctp_assoc_update(struct net *net, new->peer.peer_hmacs = NULL; sctp_auth_key_put(asoc->asoc_shared_key); - sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC); + sctp_auth_asoc_init_active_key(net, asoc, GFP_ATOMIC); } /* Update the retran path for sending a retransmitted packet. diff --git a/net/sctp/auth.c b/net/sctp/auth.c index bf81204..36d8059 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -390,15 +390,18 @@ nomem: /* Public interface to creat the association shared key. * See code above for the algorithm. */ -int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp) +int sctp_auth_asoc_init_active_key(struct net *net, + struct sctp_association *asoc, + gfp_t gfp) { struct sctp_auth_bytes *secret; struct sctp_shared_key *ep_key; + struct sctp_net_params *net_params = sctp_get_params(net); /* If we don't support AUTH, or peer is not capable * we don't need to do anything. */ - if (!sctp_auth_enable || !asoc->peer.auth_capable) + if (!net_params->auth_enable || !asoc->peer.auth_capable) return 0; /* If the key_id is non-zero and we couldn't find an @@ -443,13 +446,14 @@ struct sctp_shared_key *sctp_auth_get_shkey( * user context. This forces us to pre-allocated all possible transforms * at the endpoint init time. */ -int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) +int sctp_auth_init_hmacs(struct net *net, struct sctp_endpoint *ep, gfp_t gfp) { struct crypto_hash *tfm = NULL; __u16 id; + struct sctp_net_params *net_params = sctp_get_params(net); /* if the transforms are already allocted, we are done */ - if (!sctp_auth_enable) { + if (!net_params->auth_enable) { ep->auth_hmacs = NULL; return 0; } @@ -672,18 +676,22 @@ static int __sctp_auth_cid(sctp_cid_t chunk, struct sctp_chunks_param *param) } /* Check if peer requested that this chunk is authenticated */ -int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc) +int sctp_auth_send_cid(struct net *net, sctp_cid_t chunk, + const struct sctp_association *asoc) { - if (!sctp_auth_enable || !asoc || !asoc->peer.auth_capable) + struct sctp_net_params *net_params = sctp_get_params(net); + if (!net_params->auth_enable || !asoc || !asoc->peer.auth_capable) return 0; return __sctp_auth_cid(chunk, asoc->peer.peer_chunks); } /* Check if we requested that peer authenticate this chunk. */ -int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc) +int sctp_auth_recv_cid(struct net *net, sctp_cid_t chunk, + const struct sctp_association *asoc) { - if (!sctp_auth_enable || !asoc) + struct sctp_net_params *net_params = sctp_get_params(net); + if (!net_params->auth_enable || !asoc) return 0; return __sctp_auth_cid(chunk, @@ -876,7 +884,8 @@ nomem: return -ENOMEM; } -int sctp_auth_set_active_key(struct sctp_endpoint *ep, +int sctp_auth_set_active_key(struct net *net, + struct sctp_endpoint *ep, struct sctp_association *asoc, __u16 key_id) { @@ -902,7 +911,7 @@ int sctp_auth_set_active_key(struct sctp_endpoint *ep, if (asoc) { asoc->active_key_id = key_id; - sctp_auth_asoc_init_active_key(asoc, GFP_KERNEL); + sctp_auth_asoc_init_active_key(net, asoc, GFP_KERNEL); } else ep->active_key_id = key_id; diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index 6c85564..5211278 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c @@ -169,7 +169,8 @@ static void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk *chu * with a reasonable guess than always doing our fragmentation on the * soft-interrupt. */ -struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, +struct sctp_datamsg *sctp_datamsg_from_user(struct net *net, + struct sctp_association *asoc, struct sctp_sndrcvinfo *sinfo, struct msghdr *msgh, int msg_len) { @@ -209,7 +210,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, * we need to accound for bundling of the AUTH chunks along with * DATA. */ - if (sctp_auth_send_cid(SCTP_CID_DATA, asoc)) { + if (sctp_auth_send_cid(net, SCTP_CID_DATA, asoc)) { struct sctp_hmac *hmac_desc = sctp_auth_asoc_get_hmac(asoc); if (hmac_desc) diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index de42bd4..750df47 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -69,6 +69,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, struct sctp_chunks_param *auth_chunks = NULL; struct sctp_shared_key *null_key; int err; + struct net *net = sock_net(sk); ep->digest = kzalloc(SCTP_SIGNATURE_SIZE, gfp); if (!ep->digest) @@ -163,7 +164,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, list_add(&null_key->key_list, &ep->endpoint_shared_keys); /* Allocate and initialize transorms arrays for suported HMACs. */ - err = sctp_auth_init_hmacs(ep, gfp); + err = sctp_auth_init_hmacs(net, ep, gfp); if (err) goto nomem_hmacs; @@ -465,7 +466,8 @@ normal: } state = asoc ? asoc->state : SCTP_STATE_CLOSED; - if (sctp_auth_recv_cid(subtype.chunk, asoc) && !chunk->auth) + if (sctp_auth_recv_cid(sock_net(sk), subtype.chunk, asoc) + && !chunk->auth) continue; /* Remember where the last DATA chunk came from so we diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index af02b44..1d6c8b6 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1365,7 +1365,7 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(struct sctp_chunkhdr); /* Determine if the chunk needs to be authenticated */ - if (sctp_auth_send_cid(type, asoc)) + if (sctp_auth_send_cid(&init_net, type, asoc)) retval->auth = 1; /* Set the skb to the belonging sock for accounting. */ diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index c683d88..7bd2d6d 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1711,7 +1711,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, break; case SCTP_CMD_ASSOC_SHKEY: - error = sctp_auth_asoc_init_active_key(asoc, + error = sctp_auth_asoc_init_active_key(net, asoc, GFP_ATOMIC); break; case SCTP_CMD_UPDATE_INITTAG: diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 0d4aaa9..4cd027a 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -572,14 +572,14 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(struct net *net, * can't destroy this association just because the packet * was malformed. */ - if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) - return sctp_sf_pdiscard(net, ep, asoc, type, arg, - commands); + if (sctp_auth_recv_cid(net, SCTP_CID_ABORT, asoc)) + return sctp_sf_pdiscard(net, ep, asoc, type, + arg, commands); SCTP_INC_STATS(SCTP_MIB_ABORTEDS); return sctp_stop_t1_and_abort(net, commands, error, - ECONNREFUSED, asoc, - chunk->transport); + ECONNREFUSED, + asoc, chunk->transport); } /* Tag the variable length parameters. Note that we never @@ -757,7 +757,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net, * sctp_process_init, set up the assocaition shared keys as * necessary so that we can potentially authenticate the ACK */ - error = sctp_auth_asoc_init_active_key(new_asoc, GFP_ATOMIC); + error = sctp_auth_asoc_init_active_key(net, new_asoc, GFP_ATOMIC); if (error) goto nomem_init; @@ -4364,7 +4364,7 @@ static sctp_disposition_t sctp_sf_abort_violation( * can't destroy this association just because the packet * was malformed. */ - if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) + if (sctp_auth_recv_cid(net, SCTP_CID_ABORT, asoc)) goto discard; /* Make the abort chunk. */ @@ -4490,7 +4490,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen( struct sctp_paramhdr *param = ext; struct sctp_chunk *abort = NULL; - if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) + if (sctp_auth_recv_cid(net, SCTP_CID_ABORT, asoc)) goto discard; /* Make the abort chunk. */ diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 78e4576..d14ac7d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -101,9 +101,9 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt, union sctp_addr *addr, int len); static int sctp_bindx_add(struct sock *, struct sockaddr *, int); static int sctp_bindx_rem(struct sock *, struct sockaddr *, int); -static int sctp_send_asconf_add_ip(struct net*, struct sock *, +static int sctp_send_asconf_add_ip(struct net *, struct sock *, struct sockaddr *, int); -static int sctp_send_asconf_del_ip(struct net*, struct sock *, +static int sctp_send_asconf_del_ip(struct net *, struct sock *, struct sockaddr *, int); static int sctp_send_asconf(struct sctp_association *asoc, struct sctp_chunk *chunk); @@ -1599,6 +1599,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, __u16 sinfo_flags = 0; struct sctp_datamsg *datamsg; int msg_flags = msg->msg_flags; + struct net *net = sock_net(sk); SCTP_DEBUG_PRINTK("sctp_sendmsg(sk: %p, msg: %p, msg_len: %zu)\n", sk, msg, msg_len); @@ -1920,7 +1921,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, } /* Break the message into multiple chunks of maximum size. */ - datamsg = sctp_datamsg_from_user(asoc, sinfo, msg, msg_len); + datamsg = sctp_datamsg_from_user(net, asoc, sinfo, msg, msg_len); if (!datamsg) { err = -ENOMEM; goto out_free; @@ -3409,6 +3410,7 @@ static int sctp_setsockopt_active_key(struct sock *sk, { struct sctp_authkeyid val; struct sctp_association *asoc; + struct net *net = sock_net(sk); if (!sctp_auth_enable) return -EACCES; @@ -3422,7 +3424,7 @@ static int sctp_setsockopt_active_key(struct sock *sk, if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) return -EINVAL; - return sctp_auth_set_active_key(sctp_sk(sk)->ep, asoc, + return sctp_auth_set_active_key(net, sctp_sk(sk)->ep, asoc, val.scact_keynumber); } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-sctp" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html