{"record":{"id":"678102ad07af152e","repo":"asLody/VirtualApp","slug":"you-need-manage-users-permission-to","errorCode":null,"errorMessage":"You need MANAGE_USERS permission to: ","messagePattern":"You need MANAGE_USERS permission to: ","errorType":"exception","errorClass":"SecurityException","httpStatus":null,"severity":"error","filePath":"VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VUserManagerService.java","lineNumber":168,"sourceCode":"\n    public static VUserManagerService get() {\n        synchronized (VUserManagerService.class) {\n            return sInstance;\n        }\n    }\n\n    /**\n     * Enforces that only the system UID or root's UID or apps that have the\n     * {android.Manifest.permission.MANAGE_USERS MANAGE_USERS}\n     * permission can make certain calls to the VUserManager.\n     *\n     * @param message used as message if SecurityException is thrown\n     * @throws SecurityException if the caller is not system or root\n     */\n    private static void checkManageUsersPermission(String message) {\n        final int uid = VBinder.getCallingUid();\n        if (uid != VirtualCore.get().myUid()) {\n            throw new SecurityException(\"You need MANAGE_USERS permission to: \" + message);\n        }\n    }\n\n    @Override\n    public List<VUserInfo> getUsers(boolean excludeDying) {\n        //checkManageUsersPermission(\"query users\");\n        synchronized (mPackagesLock) {\n            ArrayList<VUserInfo> users = new ArrayList<VUserInfo>(mUsers.size());\n            for (int i = 0; i < mUsers.size(); i++) {\n                VUserInfo ui = mUsers.valueAt(i);\n                if (ui.partial) {\n                    continue;\n                }\n                if (!excludeDying || !mRemovingUserIds.contains(ui.id)) {\n                    users.add(ui);\n                }\n            }\n            return users;","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/asLody/VirtualApp/blob/666fefcb5d3f39cc944001c3457c38ffd6544c87/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VUserManagerService.java#L150-L186","documentation":"checkManageUsersPermission in VUserManagerService guards user-management operations (rename, icon, guest mode, wipe, create user). It throws SecurityException unless the caller's UID equals VirtualCore's own UID. In other words, only the virtual engine process itself (system/root-equivalent inside the virtualized environment) may manage users; any outside binder caller is rejected.","triggerScenarios":"Calling setUserName, setUserIcon, setGuestEnabled, wipeUser, makeInitialized, or createUser via binder from a process whose VBinder.getCallingUid() != VirtualCore.get().myUid(). Any cross-process caller other than the engine's own process triggers it.","commonSituations":"Calling VUserManagerService directly from an app inside the virtual container instead of going through VirtualCore/IPackageManager on the engine side; re-implementing binder stubs that pass a foreign calling uid; testing user management from an external shell or another app.","solutions":["Invoke user management through the official VirtualCore facade from within the engine process, not via direct binder calls from a client process.","If you must call remotely, run the call inside the process that hosts VirtualCore so the calling uid matches myUid().","Wrap the call in try-catch for SecurityException and fall back to a request-passing mechanism (e.g. an intent/IPC to the engine) that executes the operation in-process.","Verify the client was properly installed/initialized by VirtualApp so its identity resolves to the engine uid."],"exampleFix":"// before\nVUserManagerService.get().createUser(\"name\", 0);\n// after\ntry {\n    VUserManagerService.get().createUser(\"name\", 0);\n} catch (SecurityException e) {\n    // route through the engine process instead\n    VirtualCore.get().createUser(\"name\", 0);\n}","handlingStrategy":"try-catch","validationCode":"boolean canManageUsers = VBinder.getCallingUid() == VirtualCore.get().myUid();\nif (!canManageUsers) { /* route request through the engine process instead */ }","typeGuard":"static boolean isEngineProcess() {\n    return VBinder.getCallingUid() == VirtualCore.get().myUid();\n}","tryCatchPattern":"try {\n    userManager.createUser(name, flags);\n} catch (SecurityException e) {\n    Log.w(TAG, \"MANAGE_USERS required, routing through engine\", e);\n    engineProxy.createUser(name, flags);\n}","preventionTips":["Only call VUserManagerService from within the VirtualApp engine process.","Expose user management through a single facade that already runs in-process.","Log the calling uid in dev builds to catch identity mismatches early."],"tags":["security","android","permission","binder"],"backgroundTag":"permission-denied","analyzedSha":"666fefcb5d3f39cc944001c3457c38ffd6544c87","analyzedAt":"2026-09-09T11:09:01.694Z","contentChangedAt":"2026-09-09T11:09:01.694Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}