net: disable capability check for net_bind_service
Xiao Bo Zhao [Wed, 27 Apr 2016 22:26:54 +0000 (15:26 -0700)]
If group id matches, then skip capability and selinux check for capability
CAP_NET_BIND_SERVICE

Bug 200227789
Bug 1763043

Change-Id: I5935860c016d0f76b874595e83f2fd918f3fa36d
Signed-off-by: Xiao Bo Zhao <xiaoboz@nvidia.com>
Reviewed-on: http://git-master/r/1133850
Reviewed-by: Toby Butzon <tbutzon@nvidia.com>
Reviewed-by: Nitin Kumbhar <nkumbhar@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Inamdar Sharif <isharif@nvidia.com>
Reviewed-by: Raymond Poudrier <rapoudrier@nvidia.com>
Reviewed-on: http://git-master/r/1177256
Reviewed-by: Vinayak Pane <vpane@nvidia.com>
Reviewed-on: http://git-master/r/1207320
Tested-by: Patrick Horng <phorng@nvidia.com>

include/linux/android_aid.h
net/ipv4/af_inet.c
net/ipv6/af_inet6.c

index 06264b8..36d8ee3 100644 (file)
 #define _LINUX_ANDROID_AID_H
 
 /* AIDs that the kernel treats differently */
+/* OEM AIDs */
+#define AID_NET_BIND_SERVICE  2901  /* allow binding to privileged ports */
+
+/* AOSP AIDs */
 #define AID_OBSOLETE_000 3001  /* was NET_BT_ADMIN */
 #define AID_OBSOLETE_001 3002  /* was NET_BT */
 #define AID_INET         3003
index 14ad21e..dffdaef 100644 (file)
@@ -126,11 +126,22 @@ static inline int current_has_network(void)
 {
        return in_egroup_p(AID_INET) || capable(CAP_NET_RAW);
 }
+
+static inline int net_bind_service_capable(struct user_namespace *ns)
+{
+       return in_egroup_p(AID_NET_BIND_SERVICE) ||
+                       ns_capable(ns, CAP_NET_BIND_SERVICE);
+}
 #else
 static inline int current_has_network(void)
 {
        return 1;
 }
+
+static inline int net_bind_service_capable(struct user_namespace *ns)
+{
+       return ns_capable(ns, CAP_NET_BIND_SERVICE);
+}
 #endif
 
 /* The inetsw table contains everything that inet_create needs to
@@ -522,8 +533,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 
        snum = ntohs(addr->sin_port);
        err = -EACCES;
-       if (snum && snum < PROT_SOCK &&
-           !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
+       if (snum && snum < PROT_SOCK && !net_bind_service_capable(net->user_ns))
                goto out;
 
        /*      We keep a pair of addresses. rcv_saddr is the one
index 9a932cc..671c41b 100644 (file)
@@ -70,11 +70,22 @@ static inline int current_has_network(void)
 {
        return in_egroup_p(AID_INET) || capable(CAP_NET_RAW);
 }
+
+static inline int net_bind_service_capable(struct user_namespace *ns)
+{
+       return in_egroup_p(AID_NET_BIND_SERVICE) ||
+                       ns_capable(ns, CAP_NET_BIND_SERVICE);
+}
 #else
 static inline int current_has_network(void)
 {
        return 1;
 }
+
+static inline int net_bind_service_capable(struct user_namespace *ns)
+{
+       return ns_capable(ns, CAP_NET_BIND_SERVICE);
+}
 #endif
 
 MODULE_AUTHOR("Cast of dozens");
@@ -302,7 +313,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                return -EINVAL;
 
        snum = ntohs(addr->sin6_port);
-       if (snum && snum < PROT_SOCK && !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
+       if (snum && snum < PROT_SOCK && !net_bind_service_capable(net->user_ns))
                return -EACCES;
 
        lock_sock(sk);