I have an Android activity utilizing a JNI library that uses netlink commands to configure a network interface (in this case a socketcan interface). If I run the activity, the network interface configuration fails with an EPERM error from RTNETLINK. The commands that are failing require the CAP_NET_ADMIN capability in order to successfully complete. As such running the code as root succeeds, and also running as root and then limiting the capabilities to only CAP_NET_ADMIN using capset.
I added the following permissions to the applications manifest that gave me the impression that my process would be given the NET_ADMIN capabilities:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NET_ADMIN" />
This put the process in the inet and net_admin groups, but the process did not receive the CAP_NET_ADMIN capability resulting in the netlink commands failing with EPERM.
In various searches I have made on this topic I have found hints that the capability should be applied. eg, from http://elinux.org/Android_Security
#define GID Capability
AID_NET_BT_ADMIN 3001 Can create an RFCOMM, SCO, or L2CAPP Bluetooth socket
AID_NET_BT 3002 Can create a Bluetooth socket
AID_INET 3003 Can create IPv4 or IPv6 socket
AID_NET_RAW 3004 Can create certain kinds of IPv4 sockets??
AID_NET_ADMIN* 3005 Allow CAP_NET_ADMIN permissions for process
Unfortunately, this doesn't seem to apply to my system.
NOTE: I am running with a system and kernel modified by a chipset vendor, so it is possible that something has been modified that stops this from working.
Does anyone know
It turns out that Android modifies the kernel capability system to allow verification of specific capabilities based on group-id. Unfortunately the modifications made don't seem to cover all cases. To resolve the problem I was having, I modified the cap_netlink_recv check to use the Android modified cap_capability call. This allows users in the net_link group to obtain CAP_NET_LINK capabilities.
This change seems to be within the spirit of the modifications made to the Android kernel, and works for my situation.
diff --git a/security/commoncap.c b/security/commoncap.c
index ccfe568..f069f8d 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -56,21 +56,23 @@
}
}
int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
{
» return 0;
}
int cap_netlink_recv(struct sk_buff *skb, int cap)
{
-» if (!cap_raised(current_cap(), cap))
+» if (cap_capable(current, current_cred(),
+» » » current_cred()->user->user_ns, cap,
+» » » SECURITY_CAP_NOAUDIT) != 0)
» » return -EPERM;
» return 0;
}
EXPORT_SYMBOL(cap_netlink_recv);
/**
* cap_capable - Determine whether a task has a particular effective capability
* @tsk: The task to query
* @cred: The credentials to use
* @ns: The user namespace in which we need the capability
Indeed, in the netlink path, there is no check for additional permissions for kernel versions before v3.1-18-gfd77846.
Originally it did not seem to be a good idea to replace cap_raised
completely, so here I chose to prepend a similar check as the one in cap_capable
. Other possible cap
s are CAP_SYS_ADMIN
, CAP_AUDIT_CONTROL
and CAP_AUDIT_WRITE
, but these are not relevant to networking. Note that since the above commit, it ultimately ends up calling cap_capable
(via capable
).
The patch:
diff --git a/security/commoncap.c b/security/commoncap.c
index 8bfbd13..485245a 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -63,6 +63,10 @@ int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
int cap_netlink_recv(struct sk_buff *skb, int cap)
{
+#ifdef CONFIG_ANDROID_PARANOID_NETWORK
+ if (cap == CAP_NET_ADMIN && in_egroup_p(AID_NET_ADMIN))
+ return 0;
+#endif
if (!cap_raised(current_cap(), cap))
return -EPERM;
return 0;
For those looking at CAP_NET_RAW
, for that you need to be in the net_raw
group. Either add that group to the existing android.permission.NET_ADMIN
permission or apply the following framework patch:
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 1e7dcf7..07f5d94 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -927,6 +927,12 @@
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="signature" />
+ <!-- Allows access to raw sockets, allowing full network access and spoofing.
+ @hide -->
+ <permission android:name="android.permission.NET_RAW"
+ android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+ android:protectionLevel="signature" />
+
<!-- Allows registration for remote audio playback. @hide -->
<permission android:name="android.permission.REMOTE_AUDIO_PLAYBACK"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 47cb7ab..9c209c3 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -82,6 +82,10 @@
<group gid="net_admin" />
</permission>
+ <permission name="android.permission.NET_RAW" >
+ <group gid="net_raw" />
+ </permission>
+
<!-- The group that /cache belongs to, linked to the permission
set on the applications that can access /cache -->
<permission name="android.permission.ACCESS_CACHE_FILESYSTEM" >
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With