Gestion des Permissions dans Android 11 : Réinitialisation Automatique et Accès Carte SD

Android 11 introduit des restrictions supplémentaires sur la gestion des permissions par les applications, notamment la possibilité d'accorder une autorisation unique et la réinitialisation automatique des permissions pour les applications peu utilisées.

Mécanisme de Réinitialisation Automatique des Permissions dans Android 11

Le système Android gère la réinitialisation automatique des permissions via le mécanisme AppOpsManager. Lorsqu'une application n'est pas utilisée pendant une période prolongée, ses permissions peuvent être automatiquement révoquées par le système.

Flux d'Activation/Désactivation de la Réinitialisation Automatique dans les Paramètres

L'intreface utilisateur des paramètres permet aux utilisateurs de contrôler cette fonctionnalité. Le code source suivant illustre le parcours, de l'activation du commutateur dans les Paramètres à la modification du mode de l'opération OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED dans AppOpsManager.


// Dans packages/apps/Settings/src/com/android/settings/applications/appinfo/AppPermissionPreferenceController.java
// ... L'intention ACTION_AUTO_REVOKE_PERMISSIONS est utilisée ...

// Dans packages/apps/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
private void addAutoRevokePreferences(PreferenceScreen screen) {
    // ... Création et ajout d'une catégorie pour les préférences de révocation automatique ...
    SwitchPreference autoRevokeSwitch = new SwitchPreference(context);
    autoRevokeSwitch.setOnPreferenceClickListener((preference) -> {
        mViewModel.setAutoRevoke(autoRevokeSwitch.isChecked());
        return true;
    });
    // ...
}

// Dans packages/apps/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionGroupsViewModel.kt
fun setAutoRevoke(enabled: Boolean) {
    // ... Utilisation de GlobalScope.launch pour opérer en arrière-plan ...
    val uid = ... // Récupération de l'UID de l'application
    if (uid != null) {
        val aom = app.getSystemService(AppOpsManager::class.java)!!
        Log.i(LOG_TAG, "Configuration de la révocation automatique activée à $enabled pour $packageName $user")
        // ... Enregistrement des statistiques ...
        val mode = if (enabled) MODE_ALLOWED else MODE_IGNORED
        aom.setUidMode(OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, uid, mode)
    }
    // ...
}

// Dans frameworks/base/core/java/android/app/AppOpsManager.java
@RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setUidMode(int code, int uid, @Mode int mode) {
    try {
        mService.setUidMode(code, uid, mode);
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

// Ou alternativement :
@RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setMode(int code, int uid, String packageName, @Mode int mode) {
    // ... Implémentation similaire ...
}

// Constante pour la révocation automatique :
public static final int OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED = AppProtoEnums.APP_OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED;

Utilisation de la commande adb shell appops

La commande appops disponible via adb shell permet de manipuler directement les opérations AppOps. Elle offre des sous-commandes pour démarrer, arrêter, définir, obtenir et interroger l'état des opérations.


// Exemple de définition du mode pour une opération :
adb shell appops set [--user <USER_ID>] <[--uid] PACKAGE | UID> <OP> <MODE>
// MODE peut être : allow, ignore, deny, ou default

// Exemple pour autoriser la permission REQUEST_INSTALL_PACKAGES pour l'application Settings :
adb shell appops set com.android.settings REQUEST_INSTALL_PACKAGES allow

Modification du Comportement de la Réinitialisation Automatique

Il est possible de modifier le comportement par défaut de la réinitialisation automatique des permissions pour des applications spécifiques en intervenant directement dans le code source du framework Android.

Option 1 : Modification des Modes par Défaut

En modifiant le tableau sOpDefaultMode dans AppOpsManager.java, on peut définir le comportement par défaut de certaines opérations. Par exemple, pour désactiver la révocation automatique par défaut pour OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED :


// Dans frameworks/base/core/java/android/app/AppOpsManager.java
private static int[] sOpDefaultMode = new int[] {
    // ... autres opérations ...
    // AppOpsManager.MODE_DEFAULT, // OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED (avant)
    AppOpsManager.MODE_IGNORED, // OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED (après modification)
    // ... autres opérations ...
};

Option 2 : Interception dans le Service Système

Il est possible d'intercepter les appels au niveau du service AppOpsService pour modifier le comportement d'une opération spécifique pour une application donnée.


// Dans frameworks/base/services/core/java/com/android/server/appop/AppOpsService.java
private Op getOpLocked(Ops ops, int code, int uid, boolean edit) {
    Op op = ops.get(code);
    if (op == null) {
        // ... création de l'opération si elle n'existe pas ...
        op = new Op(ops.uidState, ops.packageName, code, uid);
        ops.put(code, op);
    }
    // Logique personnalisée pour une application spécifique
    if (ops.packageName.equals("com.application.cible")) {
        Op autoRevokeOp = new Op(ops.uidState, ops.packageName, AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, uid);
        autoRevokeOp.mode = AppOpsManager.MODE_IGNORED; // Ou MODE_ALLOWED
        ops.put(autoRevokeOp.op, autoRevokeOp);
    }
    // ...
    return op;
}

Option 3 : Attribution Préférentielle des Permissions

Pour des applications système ou des cas spécifiques, il est possible d'attribuer directement des permissions via le service système.


// Méthode personnalisée pour accorder la permission
private void setAppPermissionPreference(Context context, String packageName) {
    AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
    // Par exemple, pour désactiver la révocation automatique pour une UID spécifique
    int targetUid = 10136; // Remplacez par l'UID réel
    appOpsManager.setUidMode(AppOpsManager.OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, targetUid, AppOpsManager.MODE_IGNORED);

    // Ou en utilisant le nom du package :
    // appOpsManager.setMode(AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, targetUid, packageName, AppOpsManager.MODE_IGNORED);
}

Accès Lecture/Écriture par défaut sur Carte SD (Android R)

Dans Android R (11), des modifications ont été apportées pour permettre au processus system_server d'accéder en lecture et écriture à la carte SD. Ceci implique l'ajout de capacités Linux spécifiques au processus.

Les capacités Linux comme CAP_CHOWN, CAP_DAC_OVERRIDE, et CAP_DAC_READ_SEARCH sont ajoutées à l'ensemble des capacités du processus system_server lors de son initialisation. Ces capacités accordent des privilèges étendus pour la manipulation des fichiers et des permissions.

Le code suivant montre l'ajout de ces capacités dans ZygoteInit.java, qui est responsable du démarrage des processus système.


// Dans frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
// ...
                OsConstants.CAP_WAKE_ALARM,
                OsConstants.CAP_BLOCK_SUSPEND,
// Ajout des capacités pour l'accès à la carte SD :
                OsConstants.CAP_CHOWN,
                OsConstants.CAP_DAC_OVERRIDE,
                OsConstants.CAP_DAC_READ_SEARCH
// ...
        String args[] = {
                "--setuid=1000",
                "--setgid=1000",
                // ... autres arguments ...
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                // ...
        };
// ...

Ces changements, couplés à des ajustements dans le noyau Linux (kernel/fs/namei.c), permettent au system_server de contourner certaines vérifications d'accès standard et d'effectuer des opérations de lecture/écriture sur la carte SD.

Étiquettes: android 11 permissions appops auto revoke sdcard access

Publié le 25 juillet à 19h15