Domain简介
在adb shell中输入命令ps-Z可查看到类似如下形式的信息,其中,第一栏第二个冒号后的内容(如system_app)即为domain,这些domain可用于通过定义.te文件中的权限控制属于该domain的应用的权限(如/external/sepolicy/system_app.te中的allowsystem_app system_data_file:dir create_dir_ perms;).
SContext user
u:r:untrusted_app:s0 u0_a2 7373 341 com.uip.start:chat
u:r:system_app:s0 system 7423 341 com.qualcomm.telephony
u:r:kernel:s0 root 7804 2 kworker/1:3
u:r:radio:s0 radio 8090 341 com.qualcomm.qcrilmsgtunnel
Domain的声明
1./external/sepolicy/seapp_contexts
isSystemServer=truedomain=system_server
user=systemdomain=system_app type=system_app_data_file
user=bluetoothdomain=bluetooth type=bluetooth_data_file
user=nfcdomain=nfc type=nfc_data_file
user=radiodomain=radio type=radio_data_file
user=shared_relrodomain=shared_relro
user=shelldomain=shell type=shell_data_file
user=_isolateddomain=isolated_app
user=_appseinfo=platform domain=platform_app type=app_data_file
user=_appdomain=untrusted_app type=app_data_file
本文主要想将自定义的Domain应用于APP上.系统自带的SEAndroidapp分三类:1)untrusted_app(大多数第三方app均为这一类);2)platform_app;3)system_app.
从上面的文件中的domain即可看出这三种APP.user由UID确定,seinfo用于获取系统签名(下面介绍).这两个属性可定义domain和type.
2.UID相关
/Framework/base/services/core/java/com/android/oserver/pm/PackageManagerService.java中有如下代码:
mContext= context;
mFactoryTest= factoryTest;
mOnlyCore= onlyCore;
mLazyDexOpt= "eng".equals(SystemProperties.get("ro.build.type"));
mMetrics= new DisplayMetrics();
mSettings= new Settings(context);
mSettings.addSharedUserLPw("android.uid.system",Process.SYSTEM_UID,
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.phone",RADIO_UID,
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.log",LOG_UID,
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.nfc",NFC_UID,
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.bluetooth",BLUETOOTH_UID,
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
跟随到/Framework/base/services/core/java/com/android/oserver/pm/Setting.java中:
SharedUserSettingaddSharedUserLPw(String name, int uid, int pkgFlags) {
SharedUserSettings = mSharedUsers.get(name);
...
...
...
if(addUserIdLPw(uid, s, name)) {//为用户分配进程
mSharedUsers.put(name,s);
returns;
}
returnnull;
}
private boolean addUserIdLPw(int uid, Object obj, Object name) {
if(uid > Process.LAST_APPLICATION_UID) {
returnfalse;
}
if(uid >= Process.FIRST_APPLICATION_UID){//Process.FIRST_APPLICATION_UID为10000
...
...
...
}else {
if(mOtherUserIds.get(uid) != null) {
PackageManagerService.reportSettingsProblem(Log.ERROR,
"Addingduplicate shared id: " + uid
+" name=" + name);
returnfalse;
}
mOtherUserIds.put(uid,obj);//重点***
}
returntrue;
}
位于PackageManagerService的构造函数中的mSettings.addSharedUserLPw在Android系统起来时便为这
些用户(android:sharedUserId="android.uid.system/phone"等用户,AndroidManifest.xml中定义)申请了进
程号,如Process.SYSTEM_UID,这些进程号是系统中写的进程号,user类似u0_a2形式同样不固定。
进程号与user的对应关系在/system/core/include/private/android_filesystem_config.h中:
#define AID_SYSTEM 1000 /* system server */ //与上面的Process.SYSTEM_UID对应
#define AID_RADIO 1001 /* telephony subsystem, RIL */
#define AID_BLUETOOTH 1002
...
...
...
static const struct android_id_info android_ids[] = {
{"root", AID_ROOT, },
{"system", AID_SYSTEM, },
{"radio", AID_RADIO, },
{"bluetooth", AID_BLUETOOTH, },
...
...
...
}
3.seinfo相关
/external/sepolicy/mac_permissions.xml有如下代码:
<!--Platform dev key in AOSP -->
<signersignature="@PLATFORM" >
<seinfovalue="platform" />
</signer>
<!--All other keys -->
<default>
<seinfovalue="default" />
</default>
如果签名是platform, seinfo就是platform,其它的seinfo就是default.
Domain的自定义步骤
1. /external/sepolicy/seapp_contexts中添加:
user=myuserseinfo=platform domain=mydomain (seinfo根据需要可不定义)
2. /Framework/base/services/core/java/com/android/oserver/pm/PackageManagerService.java中添加:
mSettings.addSharedUserLPw("android.uid.myname",Process.MYUSER _UID,
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
3. /Framework/base/core/java/android/os/Process,java中添加:
MYUSER_UID=10**; (大于1000小于10000,且与其它UID不重复)
4./system/core/include/private/android_filesystem_config.h中添加:
#defineAID_ MYUSER 10**
staticconst struct android_id_info android_ids[] = {
...
{"myusername", AID_MYUSER, },
...
}
5.APP的AndroidManifest.xml中添加:
android”sharedUserId="android.uid.myname".
domain的seinfo为platform的,还应在APP的Android.mk中添加:
LOCAL_CERTIFICATE:=platform
6. 现在可对自定义的domain设置权限.
/external/sepolicy/下新建自己的mydomain.te,内容:
typemydomain, domain;
app_domain(mydomain)
net_domain(mydomain)
该domain的权限设置可接着以上内容写在这里,也可在/device/qcom/sepolicy/下的common或自己的版本中新建mydomain.te写权限.
另:
我的APP中应用到了与底层通过LocalSocket通信,通信服务需要在init.rc中定义,起初用的是system_app并为其增设了部分权限:
servicemyserver /system/bin/ myserver
socketmyserver stream 0660 system system
这里socket<type> <name> <perm> <user><group>含义为:创建一个名字为/dev/socket/<name>的unixdomain socket,并把它的fd传递给加载的进程,<type>的值是dgram或stream。因此当把domain改为自顶的my_app时,这里需要更改<user>为对应的user。