aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorChristopher Kenna <cjk@cs.unc.edu>2012-09-28 13:46:28 -0400
committerChristopher Kenna <cjk@cs.unc.edu>2012-09-28 14:50:15 -0400
commitdaa22703f14c007e93b464c45fa60019a36f546d (patch)
treea1a130b6e128dc9d57c35c026977e1b4953105e1 /net/ipv4
parent5aa287dcf1b5879aa0150b0511833c52885f5b4c (diff)
Apply k4412 kernel from HardKernel for ODROID-X.
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/Makefile1
-rw-r--r--net/ipv4/af_inet.c18
-rw-r--r--net/ipv4/devinet.c8
-rw-r--r--net/ipv4/netfilter/Kconfig12
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c8
-rw-r--r--net/ipv4/sysfs_net_ipv4.c88
-rw-r--r--net/ipv4/tcp.c121
7 files changed, 254 insertions, 2 deletions
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index f2dc69cffb5..681084d76a9 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -14,6 +14,7 @@ obj-y := route.o inetpeer.o protocol.o \
14 inet_fragment.o ping.o 14 inet_fragment.o ping.o
15 15
16obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o 16obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o
17obj-$(CONFIG_SYSFS) += sysfs_net_ipv4.o
17obj-$(CONFIG_PROC_FS) += proc.o 18obj-$(CONFIG_PROC_FS) += proc.o
18obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o 19obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
19obj-$(CONFIG_IP_MROUTE) += ipmr.o 20obj-$(CONFIG_IP_MROUTE) += ipmr.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index ef1528af7ab..4d60f12c7b6 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -118,6 +118,19 @@
118#include <linux/mroute.h> 118#include <linux/mroute.h>
119#endif 119#endif
120 120
121#ifdef CONFIG_ANDROID_PARANOID_NETWORK
122#include <linux/android_aid.h>
123
124static inline int current_has_network(void)
125{
126 return in_egroup_p(AID_INET) || capable(CAP_NET_RAW);
127}
128#else
129static inline int current_has_network(void)
130{
131 return 1;
132}
133#endif
121 134
122/* The inetsw table contains everything that inet_create needs to 135/* The inetsw table contains everything that inet_create needs to
123 * build a new socket. 136 * build a new socket.
@@ -258,6 +271,7 @@ static inline int inet_netns_ok(struct net *net, int protocol)
258 return ipprot->netns_ok; 271 return ipprot->netns_ok;
259} 272}
260 273
274
261/* 275/*
262 * Create an inet socket. 276 * Create an inet socket.
263 */ 277 */
@@ -274,6 +288,9 @@ static int inet_create(struct net *net, struct socket *sock, int protocol,
274 int try_loading_module = 0; 288 int try_loading_module = 0;
275 int err; 289 int err;
276 290
291 if (!current_has_network())
292 return -EACCES;
293
277 if (unlikely(!inet_ehash_secret)) 294 if (unlikely(!inet_ehash_secret))
278 if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM) 295 if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
279 build_ehash_secret(); 296 build_ehash_secret();
@@ -874,6 +891,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
874 case SIOCSIFPFLAGS: 891 case SIOCSIFPFLAGS:
875 case SIOCGIFPFLAGS: 892 case SIOCGIFPFLAGS:
876 case SIOCSIFFLAGS: 893 case SIOCSIFFLAGS:
894 case SIOCKILLADDR:
877 err = devinet_ioctl(net, cmd, (void __user *)arg); 895 err = devinet_ioctl(net, cmd, (void __user *)arg);
878 break; 896 break;
879 default: 897 default:
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 7d7fb20b0a1..c48323ad268 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -59,6 +59,7 @@
59 59
60#include <net/arp.h> 60#include <net/arp.h>
61#include <net/ip.h> 61#include <net/ip.h>
62#include <net/tcp.h>
62#include <net/route.h> 63#include <net/route.h>
63#include <net/ip_fib.h> 64#include <net/ip_fib.h>
64#include <net/rtnetlink.h> 65#include <net/rtnetlink.h>
@@ -735,6 +736,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
735 case SIOCSIFBRDADDR: /* Set the broadcast address */ 736 case SIOCSIFBRDADDR: /* Set the broadcast address */
736 case SIOCSIFDSTADDR: /* Set the destination address */ 737 case SIOCSIFDSTADDR: /* Set the destination address */
737 case SIOCSIFNETMASK: /* Set the netmask for the interface */ 738 case SIOCSIFNETMASK: /* Set the netmask for the interface */
739 case SIOCKILLADDR: /* Nuke all sockets on this address */
738 ret = -EACCES; 740 ret = -EACCES;
739 if (!capable(CAP_NET_ADMIN)) 741 if (!capable(CAP_NET_ADMIN))
740 goto out; 742 goto out;
@@ -786,7 +788,8 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
786 } 788 }
787 789
788 ret = -EADDRNOTAVAIL; 790 ret = -EADDRNOTAVAIL;
789 if (!ifa && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS) 791 if (!ifa && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS
792 && cmd != SIOCKILLADDR)
790 goto done; 793 goto done;
791 794
792 switch (cmd) { 795 switch (cmd) {
@@ -912,6 +915,9 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
912 inet_insert_ifa(ifa); 915 inet_insert_ifa(ifa);
913 } 916 }
914 break; 917 break;
918 case SIOCKILLADDR: /* Nuke all connections on this address */
919 ret = tcp_nuke_addr(net, (struct sockaddr *) sin);
920 break;
915 } 921 }
916done: 922done:
917 rtnl_unlock(); 923 rtnl_unlock();
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 1dfc18a03fd..73b4e91a87e 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -113,6 +113,18 @@ config IP_NF_TARGET_REJECT
113 113
114 To compile it as a module, choose M here. If unsure, say N. 114 To compile it as a module, choose M here. If unsure, say N.
115 115
116config IP_NF_TARGET_REJECT_SKERR
117 bool "Force socket error when rejecting with icmp*"
118 depends on IP_NF_TARGET_REJECT
119 default n
120 help
121 This option enables turning a "--reject-with icmp*" into a matching
122 socket error also.
123 The REJECT target normally allows sending an ICMP message. But it
124 leaves the local socket unaware of any ingress rejects.
125
126 If unsure, say N.
127
116config IP_NF_TARGET_LOG 128config IP_NF_TARGET_LOG
117 tristate "LOG target support" 129 tristate "LOG target support"
118 default m if NETFILTER_ADVANCED=n 130 default m if NETFILTER_ADVANCED=n
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 51f13f8ec72..9dd754c7f2b 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -128,6 +128,14 @@ static void send_reset(struct sk_buff *oldskb, int hook)
128static inline void send_unreach(struct sk_buff *skb_in, int code) 128static inline void send_unreach(struct sk_buff *skb_in, int code)
129{ 129{
130 icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); 130 icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
131#ifdef CONFIG_IP_NF_TARGET_REJECT_SKERR
132 if (skb_in->sk) {
133 skb_in->sk->sk_err = icmp_err_convert[code].errno;
134 skb_in->sk->sk_error_report(skb_in->sk);
135 pr_debug("ipt_REJECT: sk_err=%d for skb=%p sk=%p\n",
136 skb_in->sk->sk_err, skb_in, skb_in->sk);
137 }
138#endif
131} 139}
132 140
133static unsigned int 141static unsigned int
diff --git a/net/ipv4/sysfs_net_ipv4.c b/net/ipv4/sysfs_net_ipv4.c
new file mode 100644
index 00000000000..0cbbf10026a
--- /dev/null
+++ b/net/ipv4/sysfs_net_ipv4.c
@@ -0,0 +1,88 @@
1/*
2 * net/ipv4/sysfs_net_ipv4.c
3 *
4 * sysfs-based networking knobs (so we can, unlike with sysctl, control perms)
5 *
6 * Copyright (C) 2008 Google, Inc.
7 *
8 * Robert Love <rlove@google.com>
9 *
10 * This software is licensed under the terms of the GNU General Public
11 * License version 2, as published by the Free Software Foundation, and
12 * may be copied, distributed, and modified under those terms.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20#include <linux/kobject.h>
21#include <linux/string.h>
22#include <linux/sysfs.h>
23#include <linux/init.h>
24#include <net/tcp.h>
25
26#define CREATE_IPV4_FILE(_name, _var) \
27static ssize_t _name##_show(struct kobject *kobj, \
28 struct kobj_attribute *attr, char *buf) \
29{ \
30 return sprintf(buf, "%d\n", _var); \
31} \
32static ssize_t _name##_store(struct kobject *kobj, \
33 struct kobj_attribute *attr, \
34 const char *buf, size_t count) \
35{ \
36 int val, ret; \
37 ret = sscanf(buf, "%d", &val); \
38 if (ret != 1) \
39 return -EINVAL; \
40 if (val < 0) \
41 return -EINVAL; \
42 _var = val; \
43 return count; \
44} \
45static struct kobj_attribute _name##_attr = \
46 __ATTR(_name, 0644, _name##_show, _name##_store)
47
48CREATE_IPV4_FILE(tcp_wmem_min, sysctl_tcp_wmem[0]);
49CREATE_IPV4_FILE(tcp_wmem_def, sysctl_tcp_wmem[1]);
50CREATE_IPV4_FILE(tcp_wmem_max, sysctl_tcp_wmem[2]);
51
52CREATE_IPV4_FILE(tcp_rmem_min, sysctl_tcp_rmem[0]);
53CREATE_IPV4_FILE(tcp_rmem_def, sysctl_tcp_rmem[1]);
54CREATE_IPV4_FILE(tcp_rmem_max, sysctl_tcp_rmem[2]);
55
56static struct attribute *ipv4_attrs[] = {
57 &tcp_wmem_min_attr.attr,
58 &tcp_wmem_def_attr.attr,
59 &tcp_wmem_max_attr.attr,
60 &tcp_rmem_min_attr.attr,
61 &tcp_rmem_def_attr.attr,
62 &tcp_rmem_max_attr.attr,
63 NULL
64};
65
66static struct attribute_group ipv4_attr_group = {
67 .attrs = ipv4_attrs,
68};
69
70static __init int sysfs_ipv4_init(void)
71{
72 struct kobject *ipv4_kobject;
73 int ret;
74
75 ipv4_kobject = kobject_create_and_add("ipv4", kernel_kobj);
76 if (!ipv4_kobject)
77 return -ENOMEM;
78
79 ret = sysfs_create_group(ipv4_kobject, &ipv4_attr_group);
80 if (ret) {
81 kobject_put(ipv4_kobject);
82 return ret;
83 }
84
85 return 0;
86}
87
88subsys_initcall(sysfs_ipv4_init);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index b6ec23c7ffc..31741cf9bb6 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -266,11 +266,15 @@
266#include <linux/crypto.h> 266#include <linux/crypto.h>
267#include <linux/time.h> 267#include <linux/time.h>
268#include <linux/slab.h> 268#include <linux/slab.h>
269#include <linux/uid_stat.h>
269 270
270#include <net/icmp.h> 271#include <net/icmp.h>
271#include <net/tcp.h> 272#include <net/tcp.h>
272#include <net/xfrm.h> 273#include <net/xfrm.h>
273#include <net/ip.h> 274#include <net/ip.h>
275#include <net/ip6_route.h>
276#include <net/ipv6.h>
277#include <net/transp_v6.h>
274#include <net/netdma.h> 278#include <net/netdma.h>
275#include <net/sock.h> 279#include <net/sock.h>
276 280
@@ -1111,6 +1115,9 @@ out:
1111 if (copied) 1115 if (copied)
1112 tcp_push(sk, flags, mss_now, tp->nonagle); 1116 tcp_push(sk, flags, mss_now, tp->nonagle);
1113 release_sock(sk); 1117 release_sock(sk);
1118
1119 if (copied > 0)
1120 uid_stat_tcp_snd(current_uid(), copied);
1114 return copied; 1121 return copied;
1115 1122
1116do_fault: 1123do_fault:
@@ -1387,8 +1394,11 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
1387 tcp_rcv_space_adjust(sk); 1394 tcp_rcv_space_adjust(sk);
1388 1395
1389 /* Clean up data we have read: This will do ACK frames. */ 1396 /* Clean up data we have read: This will do ACK frames. */
1390 if (copied > 0) 1397 if (copied > 0) {
1391 tcp_cleanup_rbuf(sk, copied); 1398 tcp_cleanup_rbuf(sk, copied);
1399 uid_stat_tcp_rcv(current_uid(), copied);
1400 }
1401
1392 return copied; 1402 return copied;
1393} 1403}
1394EXPORT_SYMBOL(tcp_read_sock); 1404EXPORT_SYMBOL(tcp_read_sock);
@@ -1770,6 +1780,9 @@ skip_copy:
1770 tcp_cleanup_rbuf(sk, copied); 1780 tcp_cleanup_rbuf(sk, copied);
1771 1781
1772 release_sock(sk); 1782 release_sock(sk);
1783
1784 if (copied > 0)
1785 uid_stat_tcp_rcv(current_uid(), copied);
1773 return copied; 1786 return copied;
1774 1787
1775out: 1788out:
@@ -1778,6 +1791,8 @@ out:
1778 1791
1779recv_urg: 1792recv_urg:
1780 err = tcp_recv_urg(sk, msg, len, flags); 1793 err = tcp_recv_urg(sk, msg, len, flags);
1794 if (err > 0)
1795 uid_stat_tcp_rcv(current_uid(), err);
1781 goto out; 1796 goto out;
1782} 1797}
1783EXPORT_SYMBOL(tcp_recvmsg); 1798EXPORT_SYMBOL(tcp_recvmsg);
@@ -3313,3 +3328,107 @@ void __init tcp_init(void)
3313 tcp_secret_retiring = &tcp_secret_two; 3328 tcp_secret_retiring = &tcp_secret_two;
3314 tcp_secret_secondary = &tcp_secret_two; 3329 tcp_secret_secondary = &tcp_secret_two;
3315} 3330}
3331
3332static int tcp_is_local(struct net *net, __be32 addr) {
3333 struct rtable *rt;
3334 struct flowi4 fl4 = { .daddr = addr };
3335 rt = ip_route_output_key(net, &fl4);
3336 if (IS_ERR_OR_NULL(rt))
3337 return 0;
3338 return rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK);
3339}
3340
3341#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3342static int tcp_is_local6(struct net *net, struct in6_addr *addr) {
3343 struct rt6_info *rt6 = rt6_lookup(net, addr, addr, 0, 0);
3344 return rt6 && rt6->rt6i_dev && (rt6->rt6i_dev->flags & IFF_LOOPBACK);
3345}
3346#endif
3347
3348/*
3349 * tcp_nuke_addr - destroy all sockets on the given local address
3350 * if local address is the unspecified address (0.0.0.0 or ::), destroy all
3351 * sockets with local addresses that are not configured.
3352 */
3353int tcp_nuke_addr(struct net *net, struct sockaddr *addr)
3354{
3355 int family = addr->sa_family;
3356 unsigned int bucket;
3357
3358 struct in_addr *in;
3359#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3360 struct in6_addr *in6;
3361#endif
3362 if (family == AF_INET) {
3363 in = &((struct sockaddr_in *)addr)->sin_addr;
3364#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3365 } else if (family == AF_INET6) {
3366 in6 = &((struct sockaddr_in6 *)addr)->sin6_addr;
3367#endif
3368 } else {
3369 return -EAFNOSUPPORT;
3370 }
3371
3372 for (bucket = 0; bucket < tcp_hashinfo.ehash_mask; bucket++) {
3373 struct hlist_nulls_node *node;
3374 struct sock *sk;
3375 spinlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, bucket);
3376
3377restart:
3378 spin_lock_bh(lock);
3379 sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[bucket].chain) {
3380 struct inet_sock *inet = inet_sk(sk);
3381
3382 if (sysctl_ip_dynaddr && sk->sk_state == TCP_SYN_SENT)
3383 continue;
3384 if (sock_flag(sk, SOCK_DEAD))
3385 continue;
3386
3387 if (family == AF_INET) {
3388 __be32 s4 = inet->inet_rcv_saddr;
3389 if (s4 == LOOPBACK4_IPV6)
3390 continue;
3391
3392 if (in->s_addr != s4 &&
3393 !(in->s_addr == INADDR_ANY &&
3394 !tcp_is_local(net, s4)))
3395 continue;
3396 }
3397
3398#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3399 if (family == AF_INET6) {
3400 struct in6_addr *s6;
3401 if (!inet->pinet6)
3402 continue;
3403
3404 s6 = &inet->pinet6->rcv_saddr;
3405 if (ipv6_addr_type(s6) == IPV6_ADDR_MAPPED)
3406 continue;
3407
3408 if (!ipv6_addr_equal(in6, s6) &&
3409 !(ipv6_addr_equal(in6, &in6addr_any) &&
3410 !tcp_is_local6(net, s6)))
3411 continue;
3412 }
3413#endif
3414
3415 sock_hold(sk);
3416 spin_unlock_bh(lock);
3417
3418 local_bh_disable();
3419 bh_lock_sock(sk);
3420 sk->sk_err = ETIMEDOUT;
3421 sk->sk_error_report(sk);
3422
3423 tcp_done(sk);
3424 bh_unlock_sock(sk);
3425 local_bh_enable();
3426 sock_put(sk);
3427
3428 goto restart;
3429 }
3430 spin_unlock_bh(lock);
3431 }
3432
3433 return 0;
3434}