[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1370685275-22059-1-git-send-email-amwang@redhat.com>
Date: Sat, 8 Jun 2013 17:54:35 +0800
From: Cong Wang <amwang@...hat.com>
To: netdev@...r.kernel.org
Cc: Lorenzo Colitti <lorenzo@...gle.com>,
"David S. Miller" <davem@...emloft.net>,
Cong Wang <amwang@...hat.com>
Subject: [Patch net-next] ipv6: add missing /proc/sys/net/ipv6/ping_group_range
From: Cong Wang <amwang@...hat.com>
commit 6d0bfe22611602f366 (net: ipv6: Add IPv6 support to the ping socket.)
adds IPv6 ping socket support, but forgot to create
/proc/sys/net/ipv6/ping_group_range, therefore it wrongly shares
/proc/sys/net/ipv4/ping_group_range with IPv4.
This patch adds the missing /proc/sys/net/ipv6/ping_group_range interface.
Cc: Lorenzo Colitti <lorenzo@...gle.com>
Cc: David S. Miller <davem@...emloft.net>
Signed-off-by: Cong Wang <amwang@...hat.com>
---
include/net/netns/ipv6.h | 1 +
include/net/ping.h | 2 +-
net/ipv4/ping.c | 5 +--
net/ipv6/ping.c | 29 +++++++++++++++++-
net/ipv6/sysctl_net_ipv6.c | 70 ++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 102 insertions(+), 5 deletions(-)
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 005e2c2..ede6ffd 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -28,6 +28,7 @@ struct netns_sysctl_ipv6 {
int ip6_rt_mtu_expires;
int ip6_rt_min_advmss;
int icmpv6_time;
+ kgid_t ping_group_range[2];
};
struct netns_ipv6 {
diff --git a/include/net/ping.h b/include/net/ping.h
index 5db0224..3201acc 100644
--- a/include/net/ping.h
+++ b/include/net/ping.h
@@ -69,7 +69,6 @@ int ping_get_port(struct sock *sk, unsigned short ident);
void ping_hash(struct sock *sk);
void ping_unhash(struct sock *sk);
-int ping_init_sock(struct sock *sk);
void ping_close(struct sock *sk, long timeout);
int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len);
void ping_err(struct sk_buff *skb, int offset, u32 info);
@@ -110,5 +109,6 @@ extern void ping_proc_exit(void);
void __init ping_init(void);
int __init pingv6_init(void);
void pingv6_exit(void);
+void inet6_get_ping_group_range(kgid_t *data, kgid_t *low, kgid_t *high);
#endif /* _PING_H */
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 1f1b2dd..73c6482 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -245,7 +245,7 @@ static void inet_get_ping_group_range_net(struct net *net, kgid_t *low,
}
-int ping_init_sock(struct sock *sk)
+static int ping_v4_init_sock(struct sock *sk)
{
struct net *net = sock_net(sk);
kgid_t group = current_egid();
@@ -270,7 +270,6 @@ int ping_init_sock(struct sock *sk)
return -EACCES;
}
-EXPORT_SYMBOL_GPL(ping_init_sock);
void ping_close(struct sock *sk, long timeout)
{
@@ -964,7 +963,7 @@ EXPORT_SYMBOL_GPL(ping_rcv);
struct proto ping_prot = {
.name = "PING",
.owner = THIS_MODULE,
- .init = ping_init_sock,
+ .init = ping_v4_init_sock,
.close = ping_close,
.connect = ip4_datagram_connect,
.disconnect = udp_disconnect,
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c
index a431103..e6c1953 100644
--- a/net/ipv6/ping.c
+++ b/net/ipv6/ping.c
@@ -26,10 +26,37 @@
#include <net/transp_v6.h>
#include <net/ping.h>
+static int ping_v6_init_sock(struct sock *sk)
+{
+ struct net *net = sock_net(sk);
+ kgid_t group = current_egid();
+ struct group_info *group_info = get_current_groups();
+ int i, j, count = group_info->ngroups;
+ kgid_t low, high;
+
+ inet6_get_ping_group_range(net->ipv6.sysctl.ping_group_range,
+ &low, &high);
+ if (gid_lte(low, group) && gid_lte(group, high))
+ return 0;
+
+ for (i = 0; i < group_info->nblocks; i++) {
+ int cp_count = min_t(int, NGROUPS_PER_BLOCK, count);
+ for (j = 0; j < cp_count; j++) {
+ kgid_t gid = group_info->blocks[i][j];
+ if (gid_lte(low, gid) && gid_lte(gid, high))
+ return 0;
+ }
+
+ count -= cp_count;
+ }
+
+ return -EACCES;
+}
+
struct proto pingv6_prot = {
.name = "PINGv6",
.owner = THIS_MODULE,
- .init = ping_init_sock,
+ .init = ping_v6_init_sock,
.close = ping_close,
.connect = ip6_datagram_connect,
.disconnect = udp_disconnect,
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index e85c48b..3fc4ff9 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -15,6 +15,67 @@
#include <net/ipv6.h>
#include <net/addrconf.h>
#include <net/inet_frag.h>
+#include <net/ping.h>
+
+static DEFINE_SEQLOCK(sysctl_ping_group_range);
+static int ip6_ping_group_range_min[] = { 0, 0 };
+static int ip6_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX };
+
+void inet6_get_ping_group_range(kgid_t *data, kgid_t *low, kgid_t *high)
+{
+ unsigned int seq;
+ do {
+ seq = read_seqbegin(&sysctl_ping_group_range);
+
+ *low = data[0];
+ *high = data[1];
+ } while (read_seqretry(&sysctl_ping_group_range, seq));
+}
+
+static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t high)
+{
+ kgid_t *data = table->data;
+ write_seqlock(&sysctl_ping_group_range);
+ data[0] = low;
+ data[1] = high;
+ write_sequnlock(&sysctl_ping_group_range);
+}
+
+/* Validate changes from /proc interface. */
+static int ipv6_ping_group_range(ctl_table *table, int write,
+ void __user *buffer,
+ size_t *lenp, loff_t *ppos)
+{
+ struct user_namespace *user_ns = current_user_ns();
+ int ret;
+ gid_t urange[2];
+ kgid_t low, high;
+ ctl_table tmp = {
+ .data = &urange,
+ .maxlen = sizeof(urange),
+ .mode = table->mode,
+ .extra1 = &ip6_ping_group_range_min,
+ .extra2 = &ip6_ping_group_range_max,
+ };
+
+ inet6_get_ping_group_range(table->data, &low, &high);
+ urange[0] = from_kgid_munged(user_ns, low);
+ urange[1] = from_kgid_munged(user_ns, high);
+ ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
+
+ if (write && ret == 0) {
+ low = make_kgid(user_ns, urange[0]);
+ high = make_kgid(user_ns, urange[1]);
+ if (!gid_valid(low) || !gid_valid(high) ||
+ (urange[1] < urange[0]) || gid_lt(high, low)) {
+ low = make_kgid(&init_user_ns, 1);
+ high = make_kgid(&init_user_ns, 0);
+ }
+ set_ping_group_range(table, low, high);
+ }
+
+ return ret;
+}
static ctl_table ipv6_table_template[] = {
{
@@ -24,6 +85,13 @@ static ctl_table ipv6_table_template[] = {
.mode = 0644,
.proc_handler = proc_dointvec
},
+ {
+ .procname = "ping_group_range",
+ .data = &init_net.ipv6.sysctl.ping_group_range,
+ .maxlen = sizeof(gid_t)*2,
+ .mode = 0644,
+ .proc_handler = ipv6_ping_group_range,
+ },
{ }
};
@@ -51,6 +119,8 @@ static int __net_init ipv6_sysctl_net_init(struct net *net)
if (!ipv6_table)
goto out;
ipv6_table[0].data = &net->ipv6.sysctl.bindv6only;
+ net->ipv6.sysctl.ping_group_range[0] = make_kgid(&init_user_ns, 1);
+ net->ipv6.sysctl.ping_group_range[1] = make_kgid(&init_user_ns, 0);
ipv6_route_table = ipv6_route_sysctl_init(net);
if (!ipv6_route_table)
--
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