问题描述
在Android 4下,当 not 以root
运行时,以下简单的本机C代码行失败,并出现 Permission denied
错误:
Under Android 4, the following simple native C code line fails with an Permission denied
error when not run as root
:
online_socket = socket(AF_INET, SOCK_DGRAM, 0);
我可以可以访问该设备,但想以非特权用户身份运行该进程.
I do have root
access to the device, but want to run the process as non-privileged user.
请注意,即使在绑定套接字之前,也会发生错误.
Note that the error happens even before binding the socket.
我猜有一些安全设置需要调整吗?有人可以告诉我去哪里看看吗?
I guess there is some security setting that needs to be tweaked? Anyone can tell me where to look?
在这种情况下,操作系统确实是Android,但是我想问题确实与Linux有关(因为Android基于Linux内核).
The O/S is really Android in this case, but I guess the problem is really Linux-related (since Android is based on a Linux Kernel).
对于那些好奇的人:这是一个自定义程序,可以在运行于Android 4环境中的完整(按debootstrap
ped)Debian Jessie安装程序中运行.
For those wondering: This is a custom program that runs in a full (debootstrap
ped) Debian Jessie installation running in an Android 4 environment.
我了解到Android内核具有特殊的CONFIG_ANDROID_PARANOID_NETWORK
扩展名,该扩展名仅允许AID_INET
和AID_NET_RAW
组中的用户访问网络.
I've learned that the Android Kernel has a special CONFIG_ANDROID_PARANOID_NETWORK
extension that allows network access only to users in AID_INET
and AID_NET_RAW
groups.
但是,即使将用户添加到这些组中,socket()
仍然会被拒绝(并且ping
似乎有相同的问题,顺便说一句).
However, even after adding the user to these groups, socket()
is still rejected (and ping
appears to have the same problem, BTW).
uid=5(imp) gid=51(imp) groups=51(imp),3003(aid_inet),3004(aid_net_raw),3005(aid_admin),3001(aid_bt),3002(aid_bt_net)
由于我无权访问配置文件,因此我无法确定在此特定内核中是否设置了CONFIG_ANDROID_PARANOID_NETWORK
标志.
I can't tell if that CONFIG_ANDROID_PARANOID_NETWORK
flag is set in this particular Kernel, as I don't have access to the config file.
我发现root
和以及我的非特权用户imp
实际上都可以成功调用socket()
-至少使用上述的组设置.
I found out that both root
and also my unprivileged user imp
can in fact successfully call socket()
- at least with the groups setup described above.
但是,调用与root
相同的进程,然后使用 seteuid()
系统调用切换到imp
会阻止socket()
成功.有什么想法吗?
However, calling the same process as root
and then switching to imp
using the seteuid()
system call prevents socket()
from succeeding. Any ideas?
推荐答案
事实证明,Android使用由CONFIG_ANDROID_PARANOID_NETWORK
激活的特殊内核补丁.此修补程序允许通过网络访问属于具有硬编码ID的某些特殊组的系统用户.
As it turns out, Android uses a special Kernel patch that's activated with CONFIG_ANDROID_PARANOID_NETWORK
. This patch allows network access to system users that belong to certain special groups with hardcoded IDs.
groupadd -g 3001 aid_bt
groupadd -g 3002 aid_bt_net
groupadd -g 3003 aid_inet
groupadd -g 3004 aid_net_raw
groupadd -g 3005 aid_admin
这是因为Android通常仅在特定应用具有联网权限时才将用户(即应用)添加到这些组中.
That's because Android normally adds users (i.e. apps) to these groups only when the specific app has networking permissions.
将用户添加到这些组中可授予其使用socket()
的权限,如问题所述:
Adding a user to these groups gives it permission to use socket()
as described in the question:
usermod -a -G aid_bt,aid_bt_net,aid_inet,aid_net_raw,aid_admin someuser
但是,当进程使用seteuid()
从root
切换到非特权用户(例如someuser
)时,这还不够(或者可能是不相关),表明此有效用户具有aid_*
组成员身份.相反,root
用户必须明确地是以下组的成员:
However, when a process uses seteuid()
to switch from root
to a unprivileged user (for example someuser
), then it's not enough (or probably irrelevant) that this effective user has aid_*
group membership. Instead, the root
user must explicitly be a member of these groups:
usermod -a -G aid_bt,aid_bt_net,aid_inet,aid_net_raw,aid_admin root
这为我解决了问题.
请注意,我也尝试过使用setegid()
和类似的替代方法,但是这些都没有帮助...
Note that I've also tried to play with setegid()
and similar as an alternative, but none of that helped...
这篇关于什么会导致socket()“权限被拒绝"?错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!