summaryrefslogtreecommitdiffstats
path: root/net/sctp/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r--net/sctp/socket.c44
1 files changed, 29 insertions, 15 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 1b00a1e09b93..17841ab30798 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4658,29 +4658,39 @@ int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *),
EXPORT_SYMBOL_GPL(sctp_transport_lookup_process);
int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *),
- struct net *net, int pos, void *p) {
+ int (*cb_done)(struct sctp_transport *, void *),
+ struct net *net, int *pos, void *p) {
struct rhashtable_iter hti;
- void *obj;
- int err;
-
- err = sctp_transport_walk_start(&hti);
- if (err)
- return err;
+ struct sctp_transport *tsp;
+ int ret;
- obj = sctp_transport_get_idx(net, &hti, pos + 1);
- for (; !IS_ERR_OR_NULL(obj); obj = sctp_transport_get_next(net, &hti)) {
- struct sctp_transport *transport = obj;
+again:
+ ret = sctp_transport_walk_start(&hti);
+ if (ret)
+ return ret;
- if (!sctp_transport_hold(transport))
+ tsp = sctp_transport_get_idx(net, &hti, *pos + 1);
+ for (; !IS_ERR_OR_NULL(tsp); tsp = sctp_transport_get_next(net, &hti)) {
+ if (!sctp_transport_hold(tsp))
continue;
- err = cb(transport, p);
- sctp_transport_put(transport);
- if (err)
+ ret = cb(tsp, p);
+ if (ret)
break;
+ (*pos)++;
+ sctp_transport_put(tsp);
}
sctp_transport_walk_stop(&hti);
- return err;
+ if (ret) {
+ if (cb_done && !cb_done(tsp, p)) {
+ (*pos)++;
+ sctp_transport_put(tsp);
+ goto again;
+ }
+ sctp_transport_put(tsp);
+ }
+
+ return ret;
}
EXPORT_SYMBOL_GPL(sctp_for_each_transport);
@@ -4896,6 +4906,10 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
struct socket *sock;
int err = 0;
+ /* Do not peel off from one netns to another one. */
+ if (!net_eq(current->nsproxy->net_ns, sock_net(sk)))
+ return -EINVAL;
+
if (!asoc)
return -EINVAL;
OpenPOWER on IntegriCloud