如我们在第1.2节中所描述的那样,应用程序框架级别上的安全性由 IPC 引用监视器实现。 在 4.1 节中,我们以 Android 中使用的进程间通信系统的描述开始,讲解这个级别上的安全机制。 之后,我们在 4.2 节中引入权限,而在 4.3 节中,我们描述了在此级别上实现的权限实施系统。
如 2.1 节所述,所有 Android 应用程序都在应用程序沙箱中运行。粗略地说,应用程序的沙箱通过在带有不同 Linux 身份的不同进程中运行所有应用程序来保证。此外,系统服务也在具有更多特权身份的单独进程中运行,允许它们使用 Linux Kernel DAC 功能,访问受保护的系统不同部分(参见第 2.1, 2.2 和 1.2 节)。因此,需要进程间通信(IPC)框架来管理不同进程之间的数据和信号交换。在 Android 中,一个称为 Binder 的特殊框架用于进程间通信[12]。标准的 Posix System V IPC 框架不支持由 Android 实现的 Bionic libc 库(参见[这里](https://android.googlesource.com/platform/ndk/+/android-4.2.2_r1.2/docs/system/ libc/SYSV-IPC.html))。此外,除了用于一些特殊情况的 Binder 框架,也会使用 Unix 域套接字(例如,用于与 Zygote 守护进程的通信),但是这些机制不在本文的考虑范围之内。
Binder 框架被特地重新开发来在 Android 中使用。 它提供了管理此操作系统中的进程之间的所有类型的通信所需的功能。 基本上,甚至应用程序开发人员熟知的机制,例如Intents
和ContentProvider
,都建立在 Binder 框架之上。 这个框架提供了多种功能,例如可以调用远程对象上的方法,就像本地对象那样,以及同步和异步方法调用,Link to Death(某个进程的 Binder 终止时的自动通知),跨进程发送文件描述符的能力等等[12,16] 。
根据由客户端 - 服务器同步模型组织的进程之间的通信。客户端发起连接并等待来自服务端的回复。 因此,客户端和服务器之间的通信可以被想象为在相同的进程线程中执行。 这为开发人员提供了调用远程对象上的方法的可能性,就像它们是本地的一样。 通过 Binder 的通信模型如图 4.1 所示。 在这个图中,客户端进程 A 中的应用程序想要使用进程 B [12]中运行的服务的公开行为。
使用 Binder 框架的客户端和服务之间的所有通信,都通过 Linux 内核驱动程序/dev/binder
进行。此设备驱动程序的权限设置为全局可读和可写(见 3.1 节中的清单 3.3 中的第 3 行)。因此,任何应用程序可以写入和读取此设备。为了隐藏 Binder 通信协议的特性,libbinder
库在 Android 中使用。它提供了一种功能,使内核驱动程序的交互过程对应用程序开发人员透明。尤其是,客户端和服务器之间的所有通信通过客户端侧的代理和服务器侧的桩进行。代理和桩负责编码和解码数据和通过 Binder 驱动程序发送的命令。为了使用代理和桩,开发人员只需定义一个 AIDL 接口,在编译应用程序期间将其转换为代理和桩。在服务端,调用单独的 Binder 线程来处理客户端请求。
从技术上讲,使用Binder机制的每个公开服务(有时称为 Binder 服务)都分配有标识。内核驱动程序确保此 32 位值在系统中的所有进程中是唯一的。因此,此标识用作 Binder 服务的句柄。拥有此句柄可以与服务交互。然而,为了开始使用服务,客户端首先必须找到这个值。服务句柄的发现通过 Binder 的上下文管理器(servicemanager
是 Android Binder 的上下文管理器的实现,在这里我们互换使用这些概念)来完成。上下文管理器是一个特殊的 Binder 服务,其预定义的句柄值等于 0(指代清单 4.1 的第 8 行中获得的东西)。因为它有一个固定的句柄值,任何一方都可以找到它并调用其方法。基本上,上下文管理器充当名称服务,通过服务的名称提供服务句柄。为了实现这个目的,每个服务必须注册上下文管理器(例如,使用第 26 行中的ServiceManager
类的addService
方法)。因此,客户端可以仅知道与其通信的服务名称。使用上下文管理器来解析此名称(请参阅getService
第 12 行),客户端将收到稍后用于与服务交互的标识。 Binder 驱动程序只允许注册单个上下文管理器。因此,servicemanager
是由 Android 启动的第一个服务之一(见第 3.1 节)。servicemanager
组件确保了只允许特权系统标识注册服务。
Binder 框架本身不实施任何安全性。 同时,它提供了在 Android 中实施安全性的设施。 Binder 驱动程序将发送者进程的 UID 和 PID 添加到每个事务。 因此,由于系统中的每个应用具有其自己的 UID,所以该值可以用于识别调用方。 调用的接收者可以检查所获得的值并且决定是否应该完成事务。 接收者可以调用android.os.Binder.getCallingUid()
和android.os.Binder.getCallingPid()
[12]来获得发送者的 UID 和 PID。 另外,由于 Binder 句柄在所有进程中的唯一性和其值的模糊性[14],它也可以用作安全标识。
1 public final class ServiceManager {
2 ...
3 private static IServiceManager getIServiceManager() {
4 if ( sServiceManager != null ) {
5 return sServiceManager ;
6 }
7 // Find the service manager
8 sServiceManager = ServiceManagerNative.asInterface( BinderInternal.getContextObject() );
9 return sServiceManager ;
10 }
11
12 public static IBinder getService ( String name) {
13 try {
14 IBinder service = sCache . get (name) ;
15 if ( service != null ) {
16 return service ;
17 } else {
18 return getIServiceManager().getService(name);
19 }
20 } catch (RemoteException e) {
21 Log.e(TAG, "error in getService", e);
22 }
23 return null;
24 }
25
26 public static void addService( String name, IBinder service, boolean allowIsolated ) {
27 try {
28 getIServiceManager().addService(name, service, allowIsolated );
29 } catch (RemoteException e) {
30 Log.e(TAG, "error in addService" , e);
31 }
32 }
33 ...
34 }
代码 4.1:ServiceManager
的源码
如我们在 2.1 节中所设计的那样,在 Android 中,每个应用程序默认获得其自己的 UID 和 GID 系统标识。 此外,在操作系统中还有一些硬编码的标识(参见清单 3.5)。 这些身份用于使用在 Linux 内核级别上实施的 DAC,分离 Android 操作系统的组件,从而提高操作系统的整体安全性。 在这些身份中,AID SYSTEM
最为显著。 此 UID 用于运行系统服务器(system server
),这个组件统一了由 Android 操作系统提供的服务。 系统服务器具有访问操作系统资源,以及在系统服务器内运行的每个服务的特权,这些服务提供对其他 OS 组件和应用的特定功能的受控访问。 此受控访问基于权限系统。
正如我们在 4.1 节中所提及的,Binder 框架向接收方提供了获得发送方 UID 和 PID 的能力。在一般情况下,该功能可以由服务利用来限制想要连接到服务的消费者。这可以通过将消费者的 UID 和 PID 与服务所允许的 UID 列表进行比较来实现。然而,在 Android 中,这种功能以略微不同的方式来实现。服务的每个关键功能(或简单来说是服务的方法)被称为权限的特殊标签保护。粗略地说,在执行这样的方法之前,会检查调用进程是否被分配了权限。如果调用进程具有所需权限,则允许调用服务。否则,将抛出安全检查异常(通常,SecurityException
)。例如,如果开发者想要向其应用程序提供发送短信的功能,则必须将以下行添加到应用程序的AndroidManifest.xml
文件中:<uses-permission android:name ="android.permission.SEND_SMS"/>
。Android 还提供了一组特殊调用,允许在运行时检查服务使用者是否已分配权限。
到目前为止所描述的权限模型提供了一种强化安全性的有效方法。 同时,这个模型是无效的,因为它认为所有的权限是相等的。 在移动操作系统的情况下,所提供的功能在安全意义上并不总是相等。 例如,安装应用程序的功能比发送 SMS 的功能更重要,相反,发送 SMS 的功能比设置警告或振动更危险。
这个问题在 Android 中通过引入权限的安全级别来解决。有四个可能的权限级别:normal
,dangerous
,signature
和signatureOrSystem
。权限级别要么硬编码到 Android 操作系统(对于系统权限),要么由自定义权限声明中的第三方应用程序的开发者分配。此级别影响是否决定向请求的应用程序授予权限。为了被授予权限,正常的权限可以只在应用程序的AndroidManifest.xml
文件中请求。危险权限除了在清单文件中请求之外,还必须由用户批准。在这种情况下,安装应用程序期间,安装包所请求的权限集会显示给用户。如果用户批准它们,则安装应用程序。否则,安装将被取消。如果请求权限的应用与声明它的应用拥有相同签名,(6.1 中提到了 Android 中的应用程序签名的用法),系统将授予signature
权限。如果请求的权限应用和声明权限的使用相同证书签名,或请求应用位于系统映像上,则授予signatureOrSystem
权限。因此,对于我们的示例,振动功能被正常级别的权限保护,发送 SMS 的功能被危险级别的权限保护,以及软件包安装功能被signatureOrSystem
权限级别保护。
用于保护 Android 操作系统功能的系统权限在框架的AndroidManifest.xml
文件中定义,位于 Android 源的frameworks/base/core/res
文件夹中。 这个文件的一个摘录包含一些权限定义的例子,如代码清单 4.2 所示。 在这些示例中,展示了用于保护发送 SMS,振动器和包安装功能的权限声明。
<manifest xmlns:android=" http://schemas.android.com/apk/res/android"
package="android" coreApp="true" android:sharedUserId="android.uid.system"
android:sharedUserLabel="@string/android_system_label ">
...
<!−− Allows an application to send SMS messages. −−>
<permission android:name="android.permission.SEND_SMS"
android:permissionGroup="android.permission−group.MESSAGES"
android:protectionLevel="dangerous"
android:permissionFlags="costsMoney"
android:label="@string/permlab_sendSms"
android:description="@string/permdesc _sendSms" />
...
<!−− Allows access to the vibrator −−>
<permission android:name="android.permission.VIBRATE"
android:permissionGroup="android.permission−group.AFFECTS_BATTERY"
android:protectionLevel="normal"
android:label="@string/permlab_vibrate"
android:description="@string/permdesc_vibrate" />
...
<!−− Allows an application to install packages. −−>
<permission android:name="android.permission.INSTALL_PACKAGES"
android:label="@string/permlab_installPackages"
android:description="@string/permdesc_installPackages"
android:protectionLevel="signature|system" />
...
</manifest>
代码 4.2:系统权限的定义
默认情况下,第三方应用程序的开发人员无法访问受signature
和signatureOrSystem
级别的系统权限保护的功能。 这种行为以以下方式来保证:应用程序框架包使用平台证书签名。 因此,需要使用这些级别的权限保护的功能的应用程序必须使用相同的平台证书进行签名。 然而,仅有操作系统的构建者才可以访问该证书的私钥,通常是硬件生产者(他们自己定制 Android)或电信运营商(使用其修改的操作系统映像来分发设备)。
系统服务PackageManagerService
负责 Android 中的应用程序管理。 此服务有助于在操作系统中安装,卸载和更新应用程序。 此服务的另一个重要作用是权限管理。 基本上,它可以被认为是一个策略管理的要素。 它存储了用于检查 Android 包是否分配了特定权限的信息。 此外,在应用程序安装和升级期间,它执行一堆检查,来确保在这些过程中不违反权限模型的完整性。 此外,它还作为一个策略判定的要素。 此服务的方法(我们将在后面展示)是权限检查链中的最后一个元素。 我们不会在这里考虑PackageManagerService
的操作。 然而,感兴趣的读者可以参考[15,19]来获得如何执行应用安装的更多细节。
PackageManagerService
将所有第三方应用程序的权限的相关信息存储在/data/system/packages.xml
[7]中。 该文件用作系统重新启动之间的永久存储器。 但是,在运行时,所有有关权限的信息都保存在 RAM 中,从而提高系统的响应速度。 在启动期间,此信息使用存储在用于第三方应用程序的packages.xml
文件中的数据,以及通过解析系统应用程序来收集。
为了了解 Android 如何在应用程序框架层强制实施权限,我们考虑 Vibrator 服务用法。 在清单 4.3 的第 6 行中,展示了振动器服务如何保护其方法vibrate
的示例。 这一行检查了调用组件是否分配有由常量android.Manifest.permission.VIBRATE
定义的标签android.permission.VIBRATE
。 Android 提供了几种方法来检查发送者(或服务使用者)是否已被分配了权限。 在我们这个库,这些设施由方法checkCallingOrSelfPermission
表示。 除了这种方法,还有许多其他方法可以用于检查服务调用者的权限。
public class VibratorService extends IVibratorService.Stub
implements InputManager.InputDeviceListener {
...
public void vibrate ( long milliseconds, IBinder token ) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires VIBRATE permission");
}
...
}
...
}
代码 4.3:权限的检查
方法checkCallingOrSelfPermission
的实现如清单 4.4 所示。 在第 24 行中,方法checkPermission
被调用。 它接收uid
和pid
作为 Binder 框架提供的参数。
class ContextImpl extends Context {
...
@Override
public int checkPermission ( String permission, int pid, int uid ) {
if ( permission == null ) {
throw new IllegalArgumentException ("permission is null ") ;
}
try {
return ActivityManagerNative.getDefault().checkPermission(
permission, pid, uid );
} catch (RemoteException e) {
return PackageManager.PERMISSION_DENIED;
}
}
@Override
public int checkCallingOrSelfPermission ( String permission ) {
if ( permission == null ) {
throw new IllegalArgumentException("permission is null");
}
return checkPermission( permission, Binder. getCallingPid(),
Binder.getCallingUid() );
}
...
}
代码 4.4:ContextImpl
类的摘录
在第 11 行中,检查被重定向到ActivityManagerService
类,继而在ActivityManager
组件的方法checkComponentPermission
中执行实际检查。 此方法的代码如清单 4.5 所示。 在第 4 行中它检查调用者 UID 是否拥有特权。 具有 root 和系统 UID 的组件由具有所有权限的系统授予。
public static int checkComponentPermission ( String permission, int uid,
int owningUid, boolean exported ) {
// Root , system server get to do everything .
if ( uid == 0 || uid == Process.SYSTEM_UID) {
return PackageManager.PERMISSION_GRANTED;
}
// Isolated processes don ’ t get any permissions .
if ( UserId.isIsolated ( uid ) ) {
return PackageManager.PERMISSION_DENIED;
}
// If there is a uid that owns whatever is being accessed , it has
// blanket access to it regardless of the permissions it requires .
if (owningUid >= 0 && UserId.isSameApp(uid, owningUid) ) {
return PackageManager.PERMISSION_GRANTED;
}
// If the target is not exported , then nobody else can get to it .
if (!exported) {
Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid) ;
return PackageManager.PERMISSION_DENIED;
}
if ( permission == null ) {
return PackageManager.PERMISSION_GRANTED;
}
try {
return AppGlobals.getPackageManager()
.checkUidPermission ( permission , uid ) ;
} catch (RemoteException e) {
// Should never happen , but if it does . . . deny !
Slog.e(TAG, "PackageManager is dead ?!?" , e) ;
}
return PackageManager.PERMISSION_DENIED;
}
代码 4.5:ActivityManager
的checkComponentPermission
方法。
在清单 4.5 的第 26 行中,权限检查被重定向到包管理器,将其转发到PackageManagerService
。 正如我们前面解释的,这个服务知道分配给 Android 包的权限。 执行权限检查的PackageManagerService
方法如清单 4.6 所示。 在第 7 行中,如果将权限授予由其 UID 定义的 Android 应用程序,则会执行精确检查。
public int checkUidPermission ( String permName, int uid ) {
final boolean enforcedDefault = isPermissionEnforcedDefault(permName);
synchronized (mPackages) {
Object obj = mSettings.getUserIdLPr( UserHandle.getAppId( uid ) );
if ( obj != null ) {
GrantedPermissions gp = ( GrantedPermissions ) obj ;
if (gp.grantedPermissions.contains (permName) ) {
return PackageManager.PERMISSION_GRANTED;
}
} else {
HashSet<String> perms = mSystemPermissions.get ( uid ) ;
if (perms != null && perms.contains (permName) ) {
return PackageManager.PERMISSION_GRANTED;
}
}
if (!isPermissionEnforcedLocked (permName, enforcedDefault ) ) {
return PackageManager.PERMISSION_GRANTED;
}
}
return PackageManager .PERMISSION DENIED;
}
代码 4.6:PackageManagerService
的checkUidPermission
方法
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。