5

我有一个使用 JNI 库的 Android 活动,该库使用 netlink 命令配置网络接口(在本例中为 socketcan 接口)。如果我运行该活动,网络接口配置将失败,并出现来自 RTNETLINK的EPERM错误。失败的命令需要CAP_NET_ADMIN功能才能成功完成。因此,以 root 身份运行代码成功,并且以 root 身份运行,然后使用capset将功能限制为仅CAP_NET_ADMIN

我在应用程序清单中添加了以下权限,这给我的印象是我的进程将获得 NET_ADMIN 功能:

<uses-permission android:name="android.permission.INTERNET" />    
<uses-permission android:name="android.permission.NET_ADMIN" />

这会将进程置于inetnet_admin组中,但该进程没有收到 CAP_NET_ADMIN 功能,导致 netlink 命令失败并显示 EPERM。

在我对该主题进行的各种搜索中,我发现了应该应用该功能的提示。例如,来自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 

不幸的是,这似乎不适用于我的系统。

注意:我正在使用由芯片组供应商修改的系统和内核运行,因此可能已经修改了某些内容,使其无法正常工作。

有人知道吗

  • 如果这应该工作
  • 将功能添加到流程还需要哪些其他步骤?
  • 是否有可能?
4

2 回答 2

4

原来Android修改了内核能力体系,允许基于group-id验证特定能力。不幸的是,所做的修改似乎并未涵盖所有情况。为了解决我遇到的问题,我修改了cap_netlink_recv检查以使用 Android 修改后的cap_capability调用。这允许 net_link 组中的用户获得CAP_NET_LINK功能。

此更改似乎符合对 Android 内核所做修改的精神,并且适用于我的情况。

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
于 2012-10-26T19:46:14.733 回答
3

实际上,在 netlink 路径中,对于v3.1-18-gfd77846之前的内核版本没有额外的权限检查。

最初完全替换似乎不是一个好主意cap_raised,所以这里我选择在前面加上一个与cap_capable. 其他可能cap的 s 是CAP_SYS_ADMIN,CAP_AUDIT_CONTROLCAP_AUDIT_WRITE,但这些与网络无关。请注意,由于上述提交,它最终会调用cap_capable(via capable)。

补丁:

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;

对于那些正在看的人CAP_NET_RAW,为此你需要在net_raw小组中。将该组添加到现有android.permission.NET_ADMIN权限或应用以下框架补丁:

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" >
于 2013-11-25T23:56:35.597 回答