sctp: process sk_reuseport in sctp_get_port_local
When socks' sk_reuseport is set, the same port and address are allowed to be bound into these socks who have the same uid. Note that the difference from sk_reuse is that it allows multiple socks to listen on the same port and address. Acked-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: Xin Long <lucien.xin@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
76c6d988ae
commit
6ba8457402
2 changed files with 36 additions and 14 deletions
|
@ -96,7 +96,9 @@ struct sctp_stream;
|
||||||
|
|
||||||
struct sctp_bind_bucket {
|
struct sctp_bind_bucket {
|
||||||
unsigned short port;
|
unsigned short port;
|
||||||
unsigned short fastreuse;
|
signed char fastreuse;
|
||||||
|
signed char fastreuseport;
|
||||||
|
kuid_t fastuid;
|
||||||
struct hlist_node node;
|
struct hlist_node node;
|
||||||
struct hlist_head owner;
|
struct hlist_head owner;
|
||||||
struct net *net;
|
struct net *net;
|
||||||
|
|
|
@ -7644,8 +7644,10 @@ static struct sctp_bind_bucket *sctp_bucket_create(
|
||||||
|
|
||||||
static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
|
static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
|
||||||
{
|
{
|
||||||
bool reuse = (sk->sk_reuse || sctp_sk(sk)->reuse);
|
struct sctp_sock *sp = sctp_sk(sk);
|
||||||
|
bool reuse = (sk->sk_reuse || sp->reuse);
|
||||||
struct sctp_bind_hashbucket *head; /* hash list */
|
struct sctp_bind_hashbucket *head; /* hash list */
|
||||||
|
kuid_t uid = sock_i_uid(sk);
|
||||||
struct sctp_bind_bucket *pp;
|
struct sctp_bind_bucket *pp;
|
||||||
unsigned short snum;
|
unsigned short snum;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -7721,7 +7723,10 @@ pp_found:
|
||||||
|
|
||||||
pr_debug("%s: found a possible match\n", __func__);
|
pr_debug("%s: found a possible match\n", __func__);
|
||||||
|
|
||||||
if (pp->fastreuse && reuse && sk->sk_state != SCTP_SS_LISTENING)
|
if ((pp->fastreuse && reuse &&
|
||||||
|
sk->sk_state != SCTP_SS_LISTENING) ||
|
||||||
|
(pp->fastreuseport && sk->sk_reuseport &&
|
||||||
|
uid_eq(pp->fastuid, uid)))
|
||||||
goto success;
|
goto success;
|
||||||
|
|
||||||
/* Run through the list of sockets bound to the port
|
/* Run through the list of sockets bound to the port
|
||||||
|
@ -7735,16 +7740,18 @@ pp_found:
|
||||||
* in an endpoint.
|
* in an endpoint.
|
||||||
*/
|
*/
|
||||||
sk_for_each_bound(sk2, &pp->owner) {
|
sk_for_each_bound(sk2, &pp->owner) {
|
||||||
struct sctp_endpoint *ep2;
|
struct sctp_sock *sp2 = sctp_sk(sk2);
|
||||||
ep2 = sctp_sk(sk2)->ep;
|
struct sctp_endpoint *ep2 = sp2->ep;
|
||||||
|
|
||||||
if (sk == sk2 ||
|
if (sk == sk2 ||
|
||||||
(reuse && (sk2->sk_reuse || sctp_sk(sk2)->reuse) &&
|
(reuse && (sk2->sk_reuse || sp2->reuse) &&
|
||||||
sk2->sk_state != SCTP_SS_LISTENING))
|
sk2->sk_state != SCTP_SS_LISTENING) ||
|
||||||
|
(sk->sk_reuseport && sk2->sk_reuseport &&
|
||||||
|
uid_eq(uid, sock_i_uid(sk2))))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (sctp_bind_addr_conflict(&ep2->base.bind_addr, addr,
|
if (sctp_bind_addr_conflict(&ep2->base.bind_addr,
|
||||||
sctp_sk(sk2), sctp_sk(sk))) {
|
addr, sp2, sp)) {
|
||||||
ret = (long)sk2;
|
ret = (long)sk2;
|
||||||
goto fail_unlock;
|
goto fail_unlock;
|
||||||
}
|
}
|
||||||
|
@ -7767,19 +7774,32 @@ pp_not_found:
|
||||||
pp->fastreuse = 1;
|
pp->fastreuse = 1;
|
||||||
else
|
else
|
||||||
pp->fastreuse = 0;
|
pp->fastreuse = 0;
|
||||||
} else if (pp->fastreuse &&
|
|
||||||
|
if (sk->sk_reuseport) {
|
||||||
|
pp->fastreuseport = 1;
|
||||||
|
pp->fastuid = uid;
|
||||||
|
} else {
|
||||||
|
pp->fastreuseport = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pp->fastreuse &&
|
||||||
(!reuse || sk->sk_state == SCTP_SS_LISTENING))
|
(!reuse || sk->sk_state == SCTP_SS_LISTENING))
|
||||||
pp->fastreuse = 0;
|
pp->fastreuse = 0;
|
||||||
|
|
||||||
|
if (pp->fastreuseport &&
|
||||||
|
(!sk->sk_reuseport || !uid_eq(pp->fastuid, uid)))
|
||||||
|
pp->fastreuseport = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* We are set, so fill up all the data in the hash table
|
/* We are set, so fill up all the data in the hash table
|
||||||
* entry, tie the socket list information with the rest of the
|
* entry, tie the socket list information with the rest of the
|
||||||
* sockets FIXME: Blurry, NPI (ipg).
|
* sockets FIXME: Blurry, NPI (ipg).
|
||||||
*/
|
*/
|
||||||
success:
|
success:
|
||||||
if (!sctp_sk(sk)->bind_hash) {
|
if (!sp->bind_hash) {
|
||||||
inet_sk(sk)->inet_num = snum;
|
inet_sk(sk)->inet_num = snum;
|
||||||
sk_add_bind_node(sk, &pp->owner);
|
sk_add_bind_node(sk, &pp->owner);
|
||||||
sctp_sk(sk)->bind_hash = pp;
|
sp->bind_hash = pp;
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue