Android Gid定义
作者:互联网
环境
AOSP 10
文件:
- PackageParser.java#parseBaseApkCommon
private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
IOException {
// 此处省略...
if (tagName.equals(TAG_PERMISSION_TREE)) {
if (!parsePermissionTree(pkg, res, parser, outError)) {
return null;
}
} else if (tagName.equals(TAG_USES_PERMISSION)) {
/* TAG_USES_PERMISSION = "uses-permission";
* parseUsesPermission() 解析权限
**/
if (!parseUsesPermission(pkg, res, parser)) {
return null;
}
} else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
|| tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
if (!parseUsesPermission(pkg, res, parser)) {
return null;
}
}
.....
}
- PackageParser.java#parseUsesPermission
private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
throws XmlPullParserException, IOException {
//省略...
XmlUtils.skipCurrentTag(parser);
if (name == null) {
return true;
}
if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) {
return true;
}
// Only allow requesting this permission if the platform supports the given feature.
if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(requiredFeature)) {
return true;
}
// Only allow requesting this permission if the platform doesn't support the given feature.
if (requiredNotfeature != null && mCallback != null
&& mCallback.hasFeature(requiredNotfeature)) {
return true;
}
int index = pkg.requestedPermissions.indexOf(name);
if (index == -1) {
// 添加权限:
// PackageParser.Package.requestedPermissions
// ArrayList<String> requestedPermissions = new ArrayList<String>();
pkg.requestedPermissions.add(name.intern());
} else {
Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
+ name + " in package: " + pkg.packageName + " at: "
+ parser.getPositionDescription());
}
return true;
}
- SystemConfig.java#readPermissions
这里主要三个方法调用流程大概如下:
readPermissions(); ->readPermissionsFromXml()->readPermission()
/* 构造函数读取vendor odm product odm下
* 的/etc/sysconfig /etc/permissions下的xml文件
**/
SystemConfig() {
// Read configuration from system
readPermissions(Environment.buildPath(
Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
// Read configuration from the old permissions dir
readPermissions(Environment.buildPath(
Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
...
readPermissions(Environment.buildPath(
Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getVendorDirectory(), "etc", "permissions"),
// 省略....
}
void readPermissions(File libraryDir, int permissionFlag) {
// 省略...
// Iterate over the files in the directory and scan .xml files
File platformFile = null;
for (File f : libraryDir.listFiles()) {
if (!f.isFile()) {
continue;
}
// We'll read platform.xml last
if (f.getPath().endsWith("etc/permissions/platform.xml")) {
platformFile = f;
continue;
}
if (!f.getPath().endsWith(".xml")) {
Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
continue;
}
if (!f.canRead()) {
Slog.w(TAG, "Permissions library file " + f + " cannot be read");
continue;
}
// 解析xml函数
readPermissionsFromXml(f, permissionFlag);
}
// Read platform permissions last so it will take precedence
if (platformFile != null) {
readPermissionsFromXml(platformFile, permissionFlag);
}
}
- SystemConfig.java#readPermissionsFromXml
下面我们以
/etc/permissions/platform.xml
为例,先看xml内容
<permissions>
<permission name="android.permission.BLUETOOTH_ADMIN" >
<group gid="net_bt_admin" />
</permission>
<permission name="android.permission.BLUETOOTH" >
<group gid="net_bt" />
</permission>
<permission name="android.permission.BLUETOOTH_STACK" >
<group gid="bluetooth" />
<group gid="wakelock" />
<group gid="uhid" />
</permission>
// 省略....
</permissions>
private void readPermissionsFromXml(File permFile, int permissionFlag) {
// 省略...
final boolean allowAll = permissionFlag == ALLOW_ALL;
final boolean allowLibs = (permissionFlag & ALLOW_LIBS) != 0;
// 权限处理
while (true) {
XmlUtils.nextElement(parser);
if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
break;
}
String name = parser.getName();
if (name == null) {
XmlUtils.skipCurrentTag(parser);
continue;
}
switch (name) {
case "group": {
if (allowAll) {
String gidStr = parser.getAttributeValue(null, "gid");
if (gidStr != null) {
int gid = android.os.Process.getGidForName(gidStr);
mGlobalGids = appendInt(mGlobalGids, gid);
} else {
Slog.w(TAG, "<" + name + "> without gid in " + permFile + " at "
+ parser.getPositionDescription());
}
} else {
logNotAllowedInPartition(name, permFile, parser);
}
XmlUtils.skipCurrentTag(parser);
} break;
case "permission": {
//对应上面的上面xml的permission 节点
if (allowPermissions) {
String perm = parser.getAttributeValue(null, "name");
if (perm == null) {
Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
+ parser.getPositionDescription());
XmlUtils.skipCurrentTag(parser);
break;
}
perm = perm.intern();
// perm = "android.permission.BLUETOOTH"
readPermission(parser, perm);
} else {
logNotAllowedInPartition(name, permFile, parser);
XmlUtils.skipCurrentTag(parser);
}
} break;
// 太多标签了,此处省略部分...
default: {
Slog.w(TAG, "Tag " + name + " is unknown in "
+ permFile + " at " + parser.getPositionDescription());
XmlUtils.skipCurrentTag(parser);
} break;
}
}
} catch (XmlPullParserException e) {
Slog.w(TAG, "Got exception parsing permissions.", e);
} catch (IOException e) {
Slog.w(TAG, "Got exception parsing permissions.", e);
} finally {
IoUtils.closeQuietly(permReader);
}
// Some devices can be field-converted to FBE, so offer to splice in
// those features if not already defined by the static config
if (StorageManager.isFileEncryptedNativeOnly()) {
addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0);
addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0);
}
// Help legacy devices that may not have updated their static config
if (StorageManager.hasAdoptable()) {
addFeature(PackageManager.FEATURE_ADOPTABLE_STORAGE, 0);
}
if (ActivityManager.isLowRamDeviceStatic()) {
addFeature(PackageManager.FEATURE_RAM_LOW, 0);
} else {
addFeature(PackageManager.FEATURE_RAM_NORMAL, 0);
}
for (String featureName : mUnavailableFeatures) {
removeFeature(featureName);
}
}
- SystemConfig.java#readPermission
void readPermission(XmlPullParser parser, String name)
throws IOException, XmlPullParserException {
if (mPermissions.containsKey(name)) {
throw new IllegalStateException("Duplicate permission definition for " + name);
}
final boolean perUser = XmlUtils.readBooleanAttribute(parser, "perUser", false);
final PermissionEntry perm = new PermissionEntry(name, perUser);
// 添加权限 perm
mPermissions.put(name, perm);
int outerDepth = parser.getDepth();
int type;
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG
|| parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG
|| type == XmlPullParser.TEXT) {
continue;
}
String tagName = parser.getName();
if ("group".equals(tagName)) {
String gidStr = parser.getAttributeValue(null, "gid");
if (gidStr != null) {
//通过name获取gid,设置perm.gid
int gid = Process.getGidForName(gidStr);
perm.gids = appendInt(perm.gids, gid);
} else {
Slog.w(TAG, "<group> without gid at "
+ parser.getPositionDescription());
}
}
XmlUtils.skipCurrentTag(parser);
}
}
jint android_os_Process_getGidForName(JNIEnv* env, jobject clazz, jstring name)
{
if (name == NULL) {
jniThrowNullPointerException(env, NULL);
return -1;
}
const jchar* str16 = env->GetStringCritical(name, 0);
String8 name8;
if (str16) {
name8 = String8(reinterpret_cast<const char16_t*>(str16),
env->GetStringLength(name));
env->ReleaseStringCritical(name, str16);
}
const size_t N = name8.size();
if (N > 0) {
const char* str = name8.string();
for (size_t i=0; i<N; i++) {
if (str[i] < '0' || str[i] > '9') {// 不是数字
struct group* grp = getgrnam(str);
if (grp == NULL) {
return -1;
}
return grp->gr_gid;
}
}
//name是数字,直接转换
return atoi(str);
}
return -1;
}
- bionic/libc/bionic/grp_pwd.cpp
static group* getgrnam_internal(const char* name, group_state_t* state) {
group* grp = android_name_to_group(state, name);
if (grp != nullptr) {
return grp;
}
// /vendor/etc/passwd中查找
if (vendor_group.FindByName(name, state)) {
if (is_oem_id(state->group_.gr_gid)) {
return &state->group_;
}
}
// Handle OEM range.
grp = oem_id_to_group(oem_id_from_name(name), state);
if (grp != nullptr) {
return grp;
}
// app id 转换成 gid
return app_id_to_group(app_id_from_name(name, true), state);
}
static group* android_name_to_group(group_state_t* state, const char* name) {
for (size_t n = 0; n < android_id_count; ++n) {
if (!strcmp(android_ids[n].name, name)) {
/*
* android_ids数组定义在generated_android_ids.h
* generated_android_ids.h是编译产物,路径在
* ./out/soong/.intermediates/bionic/libc/generated_android_ids/gen/generated_android_ids.h
* 由 system/core/libcutils/include/private/android_filesystem_config.h生成
**/
return android_iinfo_to_group(state, android_ids + n);
}
}
return nullptr;
}
static group* android_iinfo_to_group(group_state_t* state,
const android_id_info* iinfo) {
snprintf(state->group_name_buffer_, sizeof(state->group_name_buffer_), "%s", iinfo->name);
group* gr = &state->group_;
gr->gr_name = state->group_name_buffer_;
gr->gr_gid = iinfo->aid;
gr->gr_mem[0] = gr->gr_name;
return gr;
}
总结:
1.在 system/core/libcutils/include/private/android_filesystem_config.h中已经定义好预设关系
#define AID_SYSTEM 1000 /* system server */
#define AID_RADIO 1001 /* telephony subsystem, RIL */
#define AID_BLUETOOTH 1002 /* bluetooth subsystem */
#define AID_GRAPHICS 1003 /* graphics devices */
#define AID_INPUT 1004 /* input devices */
2.SystemConfig初始化中读取vedor,odm,product,根目录/etc/permissions/下的xml中的节点, 通过gid名字,例如bluetooth
查询gid
,并保存在mPermissions变量中
3.最后在安装APP中通过解析apk中的manifest来添加用户组
总结
如果大家想添加自己的AID,我建议还是参考google的文档:
Android 自主访问控制
而不是直接去system/core/libcutils/include/private/android_filesystem_config.h中添加定义.虽然这样也可以,但是不建议.
操作如下:
在frameworks/base/data/etc/platform.xml
添加:
+ <permission name="android.permission.xx_SERVICE" >
+ <group gid="vendor_xx" />
+ </permission>
在frameworks/base/core/res/AndroidManifest.xml
中添加:
+ <permission android:name="android.permission.MCI_SERVICE"
+ android:protectionLevel="normal" />
在device/xxx/xxx/config.fs
中添加AID_${gid}
+++ b/device/mci/cutefish_k6/config.fs
@@ -19,6 +19,9 @@ value:2906
[AID_VENDOR_THERMAL]
value:2907
+[AID_VENDOR_XX]
+value:2908
+
重新编译就会系统就有VENDOR_XX这个gid组了
测试代码:
+ PackageInfo pi= mPm.getPackageInfo(packageName,PackageManager.GET_PERMISSIONS);
+ for (String permission : pi.requestedPermissions) {
+ if (permission == android.Manifest.permission.xx_SERVICE) {
+ logd("nopd", "access " + packageName + " xx service");
+ return true;
+ }
+ }
标签:group,定义,parser,Gid,gid,return,Android,android,name 来源: https://www.cnblogs.com/tangshunhui/p/16194052.html