diff options
author | Robert Love <rlove@google.com> | 2011-05-05 10:45:50 +0800 |
---|---|---|
committer | Xinyu Chen <xinyu.chen@freescale.com> | 2011-05-05 10:50:59 +0800 |
commit | b57494019d277566f9bd0fbedb4aae50d4c479c3 (patch) | |
tree | a7fac5983ffaad194ca03a3cffdf70835028c64a /net | |
parent | dc22913757ba1a9ddd5ba98e1f8d5d1ea4b452b6 (diff) |
Paranoid network for android.
With CONFIG_ANDROID_PARANOID_NETWORK, require specific uids/gids to instantiate network sockets.
Signed-off-by: Robert Love <rlove@google.com>
paranoid networking: Use in_egroup_p() to check group membership
The previous group_search() caused trouble for partners with module builds.
in_egroup_p() is also cleaner.
Signed-off-by: Nick Pelly <npelly@google.com>
Signed-off-by: Arve Hjønnevåg <arve@android.com>
Signed-off-by: Steinar H. Gunderson <sesse@google.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/Kconfig | 6 | ||||
-rw-r--r-- | net/bluetooth/af_bluetooth.c | 38 | ||||
-rw-r--r-- | net/ipv4/af_inet.c | 31 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 32 |
4 files changed, 105 insertions, 2 deletions
diff --git a/net/Kconfig b/net/Kconfig index 0d68b40fc0e6..1cd9b6e756e3 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -79,6 +79,12 @@ source "net/netlabel/Kconfig" endif # if INET +config ANDROID_PARANOID_NETWORK + bool "Only allow certain groups to create sockets" + default y + help + none + config NETWORK_SECMARK bool "Security Marking" help diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 421c45bd1b95..9c60673842c1 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -40,6 +40,15 @@ #include <net/bluetooth/bluetooth.h> +#ifdef CONFIG_ANDROID_PARANOID_NETWORK +#include <linux/android_aid.h> +#endif + +#ifndef CONFIG_BT_SOCK_DEBUG +#undef BT_DBG +#define BT_DBG(D...) +#endif + #define VERSION "2.15" /* Bluetooth sockets */ @@ -125,11 +134,40 @@ int bt_sock_unregister(int proto) } EXPORT_SYMBOL(bt_sock_unregister); +#ifdef CONFIG_ANDROID_PARANOID_NETWORK +static inline int current_has_bt_admin(void) +{ + return (!current_euid() || in_egroup_p(AID_NET_BT_ADMIN)); +} + +static inline int current_has_bt(void) +{ + return (current_has_bt_admin() || in_egroup_p(AID_NET_BT)); +} +# else +static inline int current_has_bt_admin(void) +{ + return 1; +} + +static inline int current_has_bt(void) +{ + return 1; +} +#endif + static int bt_sock_create(struct net *net, struct socket *sock, int proto, int kern) { int err; + if (proto == BTPROTO_RFCOMM || proto == BTPROTO_SCO || + proto == BTPROTO_L2CAP) { + if (!current_has_bt()) + return -EPERM; + } else if (!current_has_bt_admin()) + return -EPERM; + if (net != &init_net) return -EAFNOSUPPORT; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 6dac2d9f35ef..8700d4968472 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -117,6 +117,9 @@ #include <linux/mroute.h> #endif +#ifdef CONFIG_ANDROID_PARANOID_NETWORK +#include <linux/android_aid.h> +#endif /* The inetsw table contains everything that inet_create needs to * build a new socket. @@ -259,6 +262,29 @@ static inline int inet_netns_ok(struct net *net, int protocol) return ipprot->netns_ok; } +#ifdef CONFIG_ANDROID_PARANOID_NETWORK +static inline int current_has_network(void) +{ + return (!current_euid() || in_egroup_p(AID_INET) || + in_egroup_p(AID_NET_RAW)); +} +static inline int current_has_cap(int cap) +{ + if (cap == CAP_NET_RAW && in_egroup_p(AID_NET_RAW)) + return 1; + return capable(cap); +} +# else +static inline int current_has_network(void) +{ + return 1; +} +static inline int current_has_cap(int cap) +{ + return capable(cap); +} +#endif + /* * Create an inet socket. */ @@ -275,6 +301,9 @@ static int inet_create(struct net *net, struct socket *sock, int protocol, int try_loading_module = 0; int err; + if (!current_has_network()) + return -EACCES; + if (unlikely(!inet_ehash_secret)) if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM) build_ehash_secret(); @@ -327,7 +356,7 @@ lookup_protocol: } err = -EPERM; - if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) + if (sock->type == SOCK_RAW && !kern && !current_has_cap(CAP_NET_RAW)) goto out_rcu_unlock; err = -EAFNOSUPPORT; diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index e733942dafe1..9eda08f5253e 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -63,6 +63,10 @@ #include <asm/system.h> #include <linux/mroute6.h> +#ifdef CONFIG_ANDROID_PARANOID_NETWORK +#include <linux/android_aid.h> +#endif + MODULE_AUTHOR("Cast of dozens"); MODULE_DESCRIPTION("IPv6 protocol stack for Linux"); MODULE_LICENSE("GPL"); @@ -96,6 +100,29 @@ static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk) return (struct ipv6_pinfo *)(((u8 *)sk) + offset); } +#ifdef CONFIG_ANDROID_PARANOID_NETWORK +static inline int current_has_network(void) +{ + return (!current_euid() || in_egroup_p(AID_INET) || + in_egroup_p(AID_NET_RAW)); +} +static inline int current_has_cap(int cap) +{ + if (cap == CAP_NET_RAW && in_egroup_p(AID_NET_RAW)) + return 1; + return capable(cap); +} +# else +static inline int current_has_network(void) +{ + return 1; +} +static inline int current_has_cap(int cap) +{ + return capable(cap); +} +#endif + static int inet6_create(struct net *net, struct socket *sock, int protocol, int kern) { @@ -109,6 +136,9 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol, int try_loading_module = 0; int err; + if (!current_has_network()) + return -EACCES; + if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM && !inet_ehash_secret) @@ -160,7 +190,7 @@ lookup_protocol: } err = -EPERM; - if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) + if (sock->type == SOCK_RAW && !kern && !current_has_cap(CAP_NET_RAW)) goto out_rcu_unlock; sock->ops = answer->ops; |