diff options
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r-- | net/ipv4/udp.c | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 7ea1b67b6de1..049e92519616 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1512,10 +1512,13 @@ static struct sock *udp_get_first(struct seq_file *seq) | |||
1512 | { | 1512 | { |
1513 | struct sock *sk; | 1513 | struct sock *sk; |
1514 | struct udp_iter_state *state = seq->private; | 1514 | struct udp_iter_state *state = seq->private; |
1515 | struct net *net = state->net; | ||
1515 | 1516 | ||
1516 | for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) { | 1517 | for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) { |
1517 | struct hlist_node *node; | 1518 | struct hlist_node *node; |
1518 | sk_for_each(sk, node, state->hashtable + state->bucket) { | 1519 | sk_for_each(sk, node, state->hashtable + state->bucket) { |
1520 | if (sk->sk_net != net) | ||
1521 | continue; | ||
1519 | if (sk->sk_family == state->family) | 1522 | if (sk->sk_family == state->family) |
1520 | goto found; | 1523 | goto found; |
1521 | } | 1524 | } |
@@ -1528,12 +1531,13 @@ found: | |||
1528 | static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk) | 1531 | static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk) |
1529 | { | 1532 | { |
1530 | struct udp_iter_state *state = seq->private; | 1533 | struct udp_iter_state *state = seq->private; |
1534 | struct net *net = state->net; | ||
1531 | 1535 | ||
1532 | do { | 1536 | do { |
1533 | sk = sk_next(sk); | 1537 | sk = sk_next(sk); |
1534 | try_again: | 1538 | try_again: |
1535 | ; | 1539 | ; |
1536 | } while (sk && sk->sk_family != state->family); | 1540 | } while (sk && sk->sk_net != net && sk->sk_family != state->family); |
1537 | 1541 | ||
1538 | if (!sk && ++state->bucket < UDP_HTABLE_SIZE) { | 1542 | if (!sk && ++state->bucket < UDP_HTABLE_SIZE) { |
1539 | sk = sk_head(state->hashtable + state->bucket); | 1543 | sk = sk_head(state->hashtable + state->bucket); |
@@ -1582,31 +1586,51 @@ static int udp_seq_open(struct inode *inode, struct file *file) | |||
1582 | { | 1586 | { |
1583 | struct udp_seq_afinfo *afinfo = PDE(inode)->data; | 1587 | struct udp_seq_afinfo *afinfo = PDE(inode)->data; |
1584 | struct seq_file *seq; | 1588 | struct seq_file *seq; |
1589 | struct net *net; | ||
1585 | int rc = -ENOMEM; | 1590 | int rc = -ENOMEM; |
1586 | struct udp_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL); | 1591 | struct udp_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL); |
1587 | 1592 | ||
1588 | if (!s) | 1593 | if (!s) |
1589 | goto out; | 1594 | goto out; |
1595 | |||
1596 | rc = -ENXIO; | ||
1597 | net = get_proc_net(inode); | ||
1598 | if (!net) | ||
1599 | goto out_kfree; | ||
1600 | |||
1590 | s->family = afinfo->family; | 1601 | s->family = afinfo->family; |
1591 | s->hashtable = afinfo->hashtable; | 1602 | s->hashtable = afinfo->hashtable; |
1592 | s->seq_ops.start = udp_seq_start; | 1603 | s->seq_ops.start = udp_seq_start; |
1593 | s->seq_ops.next = udp_seq_next; | 1604 | s->seq_ops.next = udp_seq_next; |
1594 | s->seq_ops.show = afinfo->seq_show; | 1605 | s->seq_ops.show = afinfo->seq_show; |
1595 | s->seq_ops.stop = udp_seq_stop; | 1606 | s->seq_ops.stop = udp_seq_stop; |
1607 | s->net = net; | ||
1596 | 1608 | ||
1597 | rc = seq_open(file, &s->seq_ops); | 1609 | rc = seq_open(file, &s->seq_ops); |
1598 | if (rc) | 1610 | if (rc) |
1599 | goto out_kfree; | 1611 | goto out_put_net; |
1600 | 1612 | ||
1601 | seq = file->private_data; | 1613 | seq = file->private_data; |
1602 | seq->private = s; | 1614 | seq->private = s; |
1603 | out: | 1615 | out: |
1604 | return rc; | 1616 | return rc; |
1617 | out_put_net: | ||
1618 | put_net(net); | ||
1605 | out_kfree: | 1619 | out_kfree: |
1606 | kfree(s); | 1620 | kfree(s); |
1607 | goto out; | 1621 | goto out; |
1608 | } | 1622 | } |
1609 | 1623 | ||
1624 | static int udp_seq_release(struct inode *inode, struct file *file) | ||
1625 | { | ||
1626 | struct seq_file *seq = file->private_data; | ||
1627 | struct udp_iter_state *s = seq->private; | ||
1628 | |||
1629 | put_net(s->net); | ||
1630 | seq_release_private(inode, file); | ||
1631 | return 0; | ||
1632 | } | ||
1633 | |||
1610 | /* ------------------------------------------------------------------------ */ | 1634 | /* ------------------------------------------------------------------------ */ |
1611 | int udp_proc_register(struct udp_seq_afinfo *afinfo) | 1635 | int udp_proc_register(struct udp_seq_afinfo *afinfo) |
1612 | { | 1636 | { |
@@ -1619,7 +1643,7 @@ int udp_proc_register(struct udp_seq_afinfo *afinfo) | |||
1619 | afinfo->seq_fops->open = udp_seq_open; | 1643 | afinfo->seq_fops->open = udp_seq_open; |
1620 | afinfo->seq_fops->read = seq_read; | 1644 | afinfo->seq_fops->read = seq_read; |
1621 | afinfo->seq_fops->llseek = seq_lseek; | 1645 | afinfo->seq_fops->llseek = seq_lseek; |
1622 | afinfo->seq_fops->release = seq_release_private; | 1646 | afinfo->seq_fops->release = udp_seq_release; |
1623 | 1647 | ||
1624 | p = proc_net_fops_create(&init_net, afinfo->name, S_IRUGO, afinfo->seq_fops); | 1648 | p = proc_net_fops_create(&init_net, afinfo->name, S_IRUGO, afinfo->seq_fops); |
1625 | if (p) | 1649 | if (p) |