[英]what can cause a socket() “Permission denied” error?
Under Android 4, the following simple native C code line fails with an Permission denied
error when not run as root
: 下的Android 4,以下简单原生的C代码行失败,并
Permission denied
时不运行错误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. 我有
root
的设备访问,但要运行的过程,非特权用户。
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?
谁能告诉我在哪里看?
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). 在这种情况下,O / S实际上是Android,但我猜这个问题确实与Linux有关(因为Android基于Linux内核)。
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 4环境中运行的完整(
debootstrap
ped)Debian Jessie安装。
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. 我了解到Android内核有一个特殊的
CONFIG_ANDROID_PARANOID_NETWORK
扩展,它允许仅对AID_INET
和AID_NET_RAW
组中的用户进行网络访问。
However, even after adding the user to these groups, socket()
is still rejected (and ping
appears to have the same problem, BTW). 但是,即使将用户添加到这些组后,仍然拒绝
socket()
(并且ping
似乎也有同样的问题,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)
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. 我无法判断是否在此特定内核中设置了
CONFIG_ANDROID_PARANOID_NETWORK
标志,因为我无权访问配置文件。
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
和我的非特权用户imp
实际上可以成功调用socket()
- 至少使用上面描述的组设置。
However, calling the same process as root
and then switching to imp
using the seteuid()
system call prevents socket()
from succeeding. 但是,调用与
root
相同的进程然后使用seteuid()
系统调用切换到imp
阻止socket()
成功。 Any ideas? 有任何想法吗?
As it turns out, Android uses a special Kernel patch that's activated with CONFIG_ANDROID_PARANOID_NETWORK
. 事实证明,Android使用了一个使用
CONFIG_ANDROID_PARANOID_NETWORK
激活的特殊内核补丁。 This patch allows network access to system users that belong to certain special groups with hardcoded IDs. 此修补程序允许网络访问属于具有硬编码ID的特定特殊组的系统用户。
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
That's because Android normally adds users (ie apps) to these groups only when the specific app has networking permissions. 这是因为Android通常仅在特定应用具有网络权限时才将用户(即应用)添加到这些组。
Adding a user to these groups gives it permission to use socket()
as described in the question: 将用户添加到这些组允许它使用
socket()
,如问题中所述:
usermod -a -G aid_bt,aid_bt_net,aid_inet,aid_net_raw,aid_admin someuser
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. 但是 ,当进程使用
seteuid()
从root
用户切换到非特权用户(例如someuser
)时,这个有效用户具有aid_*
组成员资格是不够的(或者可能无关紧要 )。 Instead, the root
user must explicitly be a member of these groups: 相反,
root
用户必须明确地是这些组的成员:
usermod -a -G aid_bt,aid_bt_net,aid_inet,aid_net_raw,aid_admin root
This solved the problem for me. 这解决了我的问题。
Note that I've also tried to play with setegid()
and similar as an alternative, but none of that helped... 请注意,我也尝试使用
setegid()
和类似的替代方案,但没有一个帮助...
Those who struggle with the apt-get
on Android (with the CONFIG_ANDROID_PARANOID_NETWORK
enabled which restricts network access to users who are member of specific groups) there are two workaround: 那些在Android上使用
apt-get
(启用了CONFIG_ANDROID_PARANOID_NETWORK
,限制对特定组成员用户的网络访问)的人有两种解决方法:
groupadd -g 3003 aid_inet && usermod -G nogroup -g aid_inet _apt
echo 'APT::Sandbox::User "root";' > /etc/apt/apt.conf.d/01-android-nosandbox
This is because apt-get is running http/https/gpgv methods under a sandboxed user, which is _apt
by default: 这是因为apt-get在沙盒用户下运行http / https / gpgv方法,默认情况下为
_apt
:
root 1465 0.0 0.0 31408 4956 pts/0 S 11:48 0:00 | | \_ -bash
root 23814 0.1 0.1 65300 10124 pts/0 T 18:58 0:00 | | \_ apt-get update
_apt 23818 0.0 0.1 90208 8852 pts/0 T 18:58 0:00 | | | \_ /usr/lib/apt/methods/http
_apt 23819 0.0 0.1 90208 8828 pts/0 T 18:58 0:00 | | | \_ /usr/lib/apt/methods/https
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.