summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Svet Ganov <svetoslavganov@google.com> 2021-05-20 16:10:02 +0000
committer Svet Ganov <svetoslavganov@google.com> 2021-06-02 17:13:22 +0000
commitb1a9a9af09e4794ec1a112dc00f5efae2e2a1629 (patch)
treeca33371b4b6e62f68d88ff1c8462d37b77e872f9
parentf1804968780f975fa8fe361c480a15e8dd85d131 (diff)
Switch media fw permissions checks to AttributionSource (native)
Attribution source is the abstraction to capture the data flows for private data across apps. Checking permissions for an attribution source does this for all apps in the chain that would receive the data as well as the relevant app ops are checked/noted/started as needed. bug: 158792096 Test: atest CtsMediaTestCases atest CtsPermissionTestCases atest CtsPermission2TestCases atest CtsPermission3TestCases atest CtsPermission4TestCases atest CtsPermission5TestCases atest CtsAppOpsTestCases atest CtsAppOps2TestCases Merged-In: I918cc4dfa653f1e50b4fc71734a37d09b8ca24c4 Change-Id: I918cc4dfa653f1e50b4fc71734a37d09b8ca24c4
-rw-r--r--libs/permission/Android.bp21
-rw-r--r--libs/permission/aidl/android/content/AttributionSourceState.aidl6
-rw-r--r--libs/permission/aidl/android/permission/IPermissionChecker.aidl5
-rw-r--r--libs/permission/android/permission/PermissionChecker.cpp56
-rw-r--r--libs/permission/include/android/permission/PermissionChecker.h67
5 files changed, 111 insertions, 44 deletions
diff --git a/libs/permission/Android.bp b/libs/permission/Android.bp
index 3243a6b5f4..0eeca5469e 100644
--- a/libs/permission/Android.bp
+++ b/libs/permission/Android.bp
@@ -11,19 +11,24 @@ aidl_interface {
name: "framework-permission-aidl",
unstable: true,
local_include_dir: "aidl",
- backend: {
- ndk: {
- enabled: false
- }
- },
+ host_supported: true,
+ vendor_available: true,
+ double_loadable: true,
srcs: [
"aidl/android/content/AttributionSourceState.aidl",
"aidl/android/permission/IPermissionChecker.aidl",
],
}
-cc_library_shared {
+cc_library {
name: "libpermission",
+ host_supported: true,
+ double_loadable: true,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
cflags: [
"-Wall",
"-Wextra",
@@ -45,5 +50,7 @@ cc_library_shared {
static_libs: [
"framework-permission-aidl-cpp",
],
- export_static_lib_headers: ["framework-permission-aidl-cpp"],
+ export_static_lib_headers: [
+ "framework-permission-aidl-cpp"
+ ],
}
diff --git a/libs/permission/aidl/android/content/AttributionSourceState.aidl b/libs/permission/aidl/android/content/AttributionSourceState.aidl
index b6e54bf153..ed1b37dc0b 100644
--- a/libs/permission/aidl/android/content/AttributionSourceState.aidl
+++ b/libs/permission/aidl/android/content/AttributionSourceState.aidl
@@ -23,8 +23,10 @@ package android.content;
* {@hide}
*/
parcelable AttributionSourceState {
+ /** The PID that is accessing the permission protected data. */
+ int pid = -1;
/** The UID that is accessing the permission protected data. */
- int uid;
+ int uid = -1;
/** The package that is accessing the permission protected data. */
@nullable @utf8InCpp String packageName;
/** The attribution tag of the app accessing the permission protected data. */
@@ -36,5 +38,5 @@ parcelable AttributionSourceState {
/** The next app to receive the permission protected data. */
// TODO: We use an array as a workaround - the C++ backend doesn't
// support referring to the parcelable as it expects ctor/dtor
- @nullable AttributionSourceState[] next;
+ AttributionSourceState[] next;
}
diff --git a/libs/permission/aidl/android/permission/IPermissionChecker.aidl b/libs/permission/aidl/android/permission/IPermissionChecker.aidl
index 1f0e32d248..d3a331e1e2 100644
--- a/libs/permission/aidl/android/permission/IPermissionChecker.aidl
+++ b/libs/permission/aidl/android/permission/IPermissionChecker.aidl
@@ -28,9 +28,10 @@ interface IPermissionChecker {
int checkPermission(String permission, in AttributionSourceState attributionSource,
@nullable String message, boolean forDataDelivery, boolean startDataDelivery,
- boolean fromDatasource);
+ boolean fromDatasource, int attributedOp);
- void finishDataDelivery(String op, in AttributionSourceState attributionSource);
+ void finishDataDelivery(int op, in AttributionSourceState attributionSource,
+ boolean fromDatasource);
int checkOp(int op, in AttributionSourceState attributionSource,
String message, boolean forDataDelivery, boolean startDataDelivery);
diff --git a/libs/permission/android/permission/PermissionChecker.cpp b/libs/permission/android/permission/PermissionChecker.cpp
index a8083ee410..008afad607 100644
--- a/libs/permission/android/permission/PermissionChecker.cpp
+++ b/libs/permission/android/permission/PermissionChecker.cpp
@@ -29,7 +29,7 @@
#endif
#define LOG_TAG "PermissionChecker"
-namespace android {
+namespace android::permission {
using android::content::AttributionSourceState;
@@ -37,7 +37,7 @@ PermissionChecker::PermissionChecker()
{
}
-sp<IPermissionChecker> PermissionChecker::getService()
+sp<android::permission::IPermissionChecker> PermissionChecker::getService()
{
static String16 permission_checker("permission_checker");
@@ -59,56 +59,66 @@ sp<IPermissionChecker> PermissionChecker::getService()
sleep(1);
} else {
mService = interface_cast<IPermissionChecker>(binder);
+ break;
}
}
return mService;
}
-PermissionChecker::PermissionResult
- PermissionChecker::checkPermissionForDataDeliveryFromDatasource(
- const String16& permission, AttributionSourceState& attributionSource,
- const String16& message)
+PermissionChecker::PermissionResult PermissionChecker::checkPermissionForDataDeliveryFromDatasource(
+ const String16& permission, const AttributionSourceState& attributionSource,
+ const String16& message, int32_t attributedOpCode)
{
- return static_cast<PermissionResult>(checkPermission(permission, attributionSource, message,
- /*forDataDelivery*/ true, /*startDataDelivery*/ false,/*fromDatasource*/ true));
+ return checkPermission(permission, attributionSource, message, /*forDataDelivery*/ true,
+ /*startDataDelivery*/ false,/*fromDatasource*/ true, attributedOpCode);
}
PermissionChecker::PermissionResult
- PermissionChecker::checkPermissionForStartDataDeliveryFromDatasource(
- const String16& permission, AttributionSourceState& attributionSource,
- const String16& message)
+ PermissionChecker::checkPermissionForStartDataDeliveryFromDatasource(
+ const String16& permission, const AttributionSourceState& attributionSource,
+ const String16& message, int32_t attributedOpCode)
+{
+ return checkPermission(permission, attributionSource, message, /*forDataDelivery*/ true,
+ /*startDataDelivery*/ true, /*fromDatasource*/ true, attributedOpCode);
+}
+
+PermissionChecker::PermissionResult PermissionChecker::checkPermissionForPreflightFromDatasource(
+ const String16& permission, const AttributionSourceState& attributionSource,
+ const String16& message, int32_t attributedOpCode)
{
- return static_cast<PermissionResult>(checkPermission(permission, attributionSource, message,
- /*forDataDelivery*/ true, /*startDataDelivery*/ true, /*fromDatasource*/ true));
+ return checkPermission(permission, attributionSource, message, /*forDataDelivery*/ false,
+ /*startDataDelivery*/ false, /*fromDatasource*/ true, attributedOpCode);
}
-void PermissionChecker::finishDataDelivery(const String16& op,
- AttributionSourceState& attributionSource)
+void PermissionChecker::finishDataDeliveryFromDatasource(int32_t op,
+ const AttributionSourceState& attributionSource)
{
sp<IPermissionChecker> service = getService();
if (service != nullptr) {
- binder::Status status = service->finishDataDelivery(op, attributionSource);
+ binder::Status status = service->finishDataDelivery(op, attributionSource,
+ /*fromDatasource*/ true);
if (!status.isOk()) {
ALOGE("finishDataDelivery failed: %s", status.exceptionMessage().c_str());
}
}
}
-int32_t PermissionChecker::checkPermission(const String16& permission,
- AttributionSourceState& attributionSource, const String16& message,
- bool forDataDelivery, bool startDataDelivery, bool fromDatasource)
+PermissionChecker::PermissionResult PermissionChecker::checkPermission(const String16& permission,
+ const AttributionSourceState& attributionSource, const String16& message,
+ bool forDataDelivery, bool startDataDelivery, bool fromDatasource,
+ int32_t attributedOpCode)
{
sp<IPermissionChecker> service = getService();
if (service != nullptr) {
int32_t result;
binder::Status status = service->checkPermission(permission, attributionSource, message,
- forDataDelivery, startDataDelivery, fromDatasource, &result);
+ forDataDelivery, startDataDelivery, fromDatasource, attributedOpCode, &result);
if (status.isOk()) {
- return result;
+ return static_cast<PermissionResult>(result);
}
ALOGE("checkPermission failed: %s", status.exceptionMessage().c_str());
}
- return PERMISSION_DENIED;
+ return PERMISSION_HARD_DENIED;
}
-} // namespace android
+} // namespace android::permission
diff --git a/libs/permission/include/android/permission/PermissionChecker.h b/libs/permission/include/android/permission/PermissionChecker.h
index 20ab51fc8a..308d7942a4 100644
--- a/libs/permission/include/android/permission/PermissionChecker.h
+++ b/libs/permission/include/android/permission/PermissionChecker.h
@@ -30,6 +30,8 @@
// ---------------------------------------------------------------------------
namespace android {
+namespace permission {
+
using android::content::AttributionSourceState;
using android::permission::IPermissionChecker;
@@ -71,7 +73,8 @@ public:
* Checks whether a given data access chain described by the given attribution source
* has a given permission and whether the app op that corresponds to this permission
* is allowed. Call this method if you are the datasource which would not blame you for
- * access to the data since you are the data. Note that the attribution source chain
+ * access to the data since you are the data. Use this API if you are the datasource of
+ * the protected state.
*
* NOTE: The attribution source should be for yourself with its next attribution
* source being the app that would receive the data from you.
@@ -82,18 +85,49 @@ public:
* @param permission The permission to check.
* @param attributionSource The attribution chain to check.
* @param message A message describing the reason the permission was checked.
+ * @param attributedOpCode The op code towards which to blame the access. If this
+ * is a valid app op the op corresponding to the checked permission (if such)
+ * would only be checked to ensure it is allowed and if that succeeds the
+ * noting would be against the attributed op.
* @return The permission check result which is either PERMISSION_GRANTED,
* or PERMISSION_SOFT_DENIED or PERMISSION_HARD_DENIED.
*/
PermissionChecker::PermissionResult checkPermissionForDataDeliveryFromDatasource(
- const String16& permission, AttributionSourceState& attributionSource,
- const String16& message);
+ const String16& permission, const AttributionSourceState& attributionSource,
+ const String16& message, int32_t attributedOpCode);
+
+ /**
+ * Checks whether a given data access chain described by the given attribution source
+ * has a given permission and whether the app op that corresponds to this permission
+ * is allowed. The app ops are not noted/started.
+ *
+ * NOTE: The attribution source should be for yourself with its next attribution
+ * source being the app that would receive the data from you.
+ *
+ * NOTE: Use this method only for permission checks at the preflight point where you
+ * will not deliver the permission protected data to clients but schedule permission
+ * data delivery, apps register listeners, etc.
+ *
+ * @param permission The permission to check.
+ * @param attributionSource The attribution chain to check.
+ * @param message A message describing the reason the permission was checked.
+ * @param attributedOpCode The op code towards which to blame the access. If this
+ * is a valid app op the op corresponding to the checked permission (if such)
+ * would only be checked to ensure it is allowed and if that succeeds the
+ * starting would be against the attributed op.
+ * @return The permission check result which is either PERMISSION_GRANTED,
+ * or PERMISSION_SOFT_DENIED or PERMISSION_HARD_DENIED.
+ */
+ PermissionResult checkPermissionForPreflightFromDatasource(
+ const String16& permission, const AttributionSourceState& attributionSource,
+ const String16& message, int32_t attributedOpCode);
/**
* Checks whether a given data access chain described by the given attribution source
* has a given permission and whether the app op that corresponds to this permission
* is allowed. The app ops are also marked as started. This is useful for long running
- * permissions like camera and microphone.
+ * permissions like camera and microphone. Use this API if you are the datasource of
+ * the protected state.
*
* NOTE: The attribution source should be for yourself with its next attribution
* source being the app that would receive the data from you.
@@ -104,32 +138,45 @@ public:
* @param permission The permission to check.
* @param attributionSource The attribution chain to check.
* @param message A message describing the reason the permission was checked.
+ * @param attributedOpCode The op code towards which to blame the access. If this
+ * is a valid app op the op corresponding to the checked permission (if such)
+ * would only be checked to ensure it is allowed and if that succeeds the
+ * starting would be against the attributed op.
* @return The permission check result which is either PERMISSION_GRANTED,
* or PERMISSION_SOFT_DENIED or PERMISSION_HARD_DENIED.
*/
PermissionResult checkPermissionForStartDataDeliveryFromDatasource(
- const String16& permission, AttributionSourceState& attributionSource,
- const String16& message);
+ const String16& permission, const AttributionSourceState& attributionSource,
+ const String16& message, int32_t attributedOpCode);
/**
* Finishes an ongoing op for data access chain described by the given
- * attribution source.
+ * attribution source. Use this API if you are the datasource of the protected
+ * state. Use this API if you are the datasource of the protected state.
+ *
+ * NOTE: The attribution source should be for yourself with its next attribution
+ * source being the app that would receive the data from you.
*
* @param op The op to finish.
* @param attributionSource The attribution chain for which to finish data delivery.
+ * @param attributedOpCode The op code towards which to blame the access. If this
+ * is a valid app op it is the op that would be finished.
*/
- void finishDataDelivery(const String16& op, AttributionSourceState& attributionSource);
+ void finishDataDeliveryFromDatasource(int32_t op,
+ const AttributionSourceState& attributionSource);
private:
Mutex mLock;
sp<IPermissionChecker> mService;
sp<IPermissionChecker> getService();
- int32_t checkPermission(const String16& permission, AttributionSourceState& attributionSource,
+ PermissionResult checkPermission(const String16& permission,
+ const AttributionSourceState& attributionSource,
const String16& message, bool forDataDelivery, bool startDataDelivery,
- bool fromDatasource);
+ bool fromDatasource, int32_t attributedOpCode);
};
+} // namespace permission
} // namespace android