Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --root option to bypass AID_SHELL secure display restriction starting in A12 #5014

Closed
wants to merge 17 commits into from

Conversation

Giantvince1
Copy link

Hello everyone! I am creating this pull request in hopes of merging this feature before the 2.5.x release window, as many would benefit from being able to use scrcpy with root access, without being able to run adb root since Android's new restrictions on the adbd daemon now being an APEX module. The initial idea and most of the groundwork was done by @RiggiG and I mainly just fixed up a few things that would have prevented it from merging with the current state of the dev branch, as well as a few things that caused other problems.

During testing, I have found that on an Android 14 AVD rooted with Magisk (instead of adb root), I was able to see bidirectional clipboard access working, along with display, audio, and even settings changes working without problems. The only thing that is somewhat janky about the settings changes is that since AID_SYSTEM does NOT have write access to the settings database, actual root access is required by AID_SYSTEM so the server-side executable can handle cleanup on exit properly. This was just rebased using git cherry-pick to be able to get the necessary changes pulled in, without having to see nearly 100 commits that duplicated the progress on the origin dev branch in the meantime.

Copy link

@diogotcorreia diogotcorreia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've left a few comments, mostly nitpicks and styling problems. Haven't actually tested the code.

PS: I haven't contributed to scrcpy before, but I've been following this issue for a while, so take my review with a grain of salt.

Signed-off-by: Giantvince1 <giantvince1@protonmail.com>
Signed-off-by: Giantvince1 <giantvince1@protonmail.com>
This reverts commit 5c29967.
I'm doing this as I initially did the revert because Ubuntu's packaged version of ```meson``` is 0.61.2.
Pip's version is 1.41, WAY more up-to-date. Un-reverting initial commit as this follows the new convention.
@Giantvince1
Copy link
Author

Giantvince1 commented Jun 26, 2024

Is there anyone able to test the --root option on real, rooted hardware running production builds of Android, and make sure things like bidirectional clipboard actually work, especially on Android 13 and lower? I know it works on an Android 14-based AVD patched to use Magisk as its root solution, but AVDs are always generated as either eng or userdebug builds, meaning they have less restriction than an actual user-release build of Android.

@diogotcorreia
Copy link

I've tested this on Android 14 rooted (real hardware), but it doesn't seem to work (apps with the secure flag are still black).
However, my ROM (DerpFest) already has a flag to ignore the secure flag (I've disabled it to test), so it might be interfering. I know that the previous PR trying to implement this also did not work.

@Giantvince1
Copy link
Author

Giantvince1 commented Jun 28, 2024

That's strange. I had used the previous PR made by RiggiG to workaround FLAG_SECURE on a Pixel 7 Pro running LineageOS 21, which is also A14, rooted via Magisk, and it worked perfectly; the easiest way to test this is to try to open your phone's settings screen while making sure the Allow overlays on Settings app toggle is off in Developer Options. If it's off, Settings will require a display with FLAG_SECURE, but if the toggle is ON, the Settings app ignores the flag. I can confirm from previous experience that the Settings app did in fact black out when scrcpy wasn't run in AID_SYSTEM context with the toggle off on my device, and that it showed without issue with the ability to gain AID_SYSTEM permissions (which can create secure displays).

My PR is just a cleanup and rework of some things based on his PR, which is why I credited him both in the git cherry-picks and in the initial posting of the PR.

Edit: I plan on going back and testing this myself in my rooted A14 AVD, just to double-check that FLAG_SECURE is in fact bypassed. Some ROMs will perform HDCP checks for any FLAG_SECURE app, but others will only do so for apps that actually flag that DRM is involved as well.

@Giantvince1
Copy link
Author

Giantvince1 commented Jun 28, 2024

I'm gonna try to see if I can find the capabilities of different system-level users (UIDs below 10000), and compare them from stock AOSP and/or LineageOS to DerpFest's own code. Maybe they stripped the perms for creating a FLAG_SECURE display from UID 1000? Maybe UID 1000 isn't AID_SYSTEM on DerpFest, and instead got renumbered? I can't know yet, but I'm trying to sift through the Android source trees.

Edit: Also, the main reason we can't use UID 0 (acutal root) for this is due to ART and SEPolicy limitations. For one, the clipboard will refuse to work, as no Android package is registered with UID 0, at all, ever. Next is the fact that most system services don't treat UID 0 specially, but will treat UID 1000 specially, but only because it's supposed to represent AID_SYSTEM by default. SEPolicy restrictions can only be lifted so far by a root solution before Anroid gets triggered into realizing it's been tampered with, and that's completely undesirable on production HW, especially with how Play Integrity has been cracking down lately. Oh, did I mention that UID 0 can't even create an Android virtual display, let alone one with FLAG_SECURE, on its own, and requires another user to do so?

@RiggiG
Copy link

RiggiG commented Jun 29, 2024

I can't know yet, but I'm trying to sift through the Android source trees.
It's only AID_GRAPHICS and AID_SYSTEM, and AID_GRAPHICS is not sufficient for any other scrcpy functionality.

The relevant code is in SurfaceFlinger, and has not changed in 4 years.

the Allow overlays on Settings app toggle is off in Developer Options. If it's off, Settings will require a display with FLAG_SECURE, but if the toggle is ON, the Settings app ignores the flag

This is not accurate, this setting toggles HIDE_OVERLAY_WINDOWS to prevent overlays being drawn over the application, as it describes.

Image using latest win64 release of scrcpy 2.4 (no root):

image

Props for picking this up, I haven't been able to prioritize any effort on this for a long while. I haven't tested this build, but my original build (with --root) does not display apps with FLAG_SECURE on a rooted, stock A14 Pixel 5.

@Giantvince1
Copy link
Author

Giantvince1 commented Jun 29, 2024

@RiggiG thank you for providing that info, that's actually really helpful. However, I'm not sure what you mean by "stock A14 Pixel 5", do you mean no root access, or do you mean it's running the stock ROM with Magisk installed? Either way, I'll try out a different app to test FLAG_SECURE capability with.

However, with the Settings part, it would actually black out on A14 without --root passed to enable FLAG_SECURE on the display on LineageOS, but with your patchset (and providing --root on the commandline), it no longer blacked out, at least based on my experience with it. Either way, I plan to test it in more detail as it should be able to instantiate a secure display without restrictions with AID_SYSTEM permissions, and it should produce visible results. I'll be doing testing tonight, and hopefully I can have some conclusive results tomorrow.

@RiggiG
Copy link

RiggiG commented Jun 29, 2024

dumpsys display:

Pixel 5 A14 scrcpy with --root:
DisplayDeviceInfo{"Built-in Screen": uniqueId="local:4630946523002478721", 1080 x 2340, modeId 2, renderFrameRate 90.0, defaultModeId 2, supportedModes [{id=1, width=1080, height=2340, fps=60.000004, alternativeRefreshRates=[90.0], supportedHdrTypes=[2, 3]}, {id=2, width=1080, height=2340, fps=90.0, alternativeRefreshRates=[60.000004], supportedHdrTypes=[2, 3]}], colorMode 0, supportedColorModes [0, 7, 9], hdrCapabilities HdrCapabilities{mSupportedHdrTypes=[2, 3], mMaxLuminance=500.0, mMaxAverageLuminance=500.0, mMinLuminance=0.0}, allmSupported false, gameContentTypeSupported false, density 440, 435.428 x 433.839 dpi, appVsyncOff 2333333, presDeadline 11500000, cutout DisplayCutout{insets=Rect(0, 136 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 145, 136), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]} cutoutPathParserInfo={CutoutPathParserInfo{displayWidth=1080 displayHeight=2340 physicalDisplayWidth=1080 physicalDisplayHeight=2340 density={2.75} cutoutSpec={M 41,77 a 40,40 0 1 0 80,0 40,40 0 1 0 -80,0 Z @left} rotation={0} scale={1.0} physicalPixelDisplaySizeRatio={1.0}}}}, touch INTERNAL, rotation 0, type INTERNAL, address {port=129, model=0x40446d53ad64a0}, deviceProductInfo DeviceProductInfo{name=, manufacturerPnpId=QCM, productId=1, modelYear=null, manufactureDate=ManufactureDate{week=27, year=2006}, connectionToSinkType=0}, state ON, committedState ON, frameRateOverride , brightnessMinimum 0.0, brightnessMaximum 1.0, brightnessDefault 0.2901961, hdrSdrRatio NaN, roundedCorners RoundedCorners{[RoundedCorner{position=TopLeft, radius=108, center=Point(108, 108)}, RoundedCorner{position=TopRight, radius=108, center=Point(972, 108)}, RoundedCorner{position=BottomRight, radius=108, center=Point(972, 2232)}, RoundedCorner{position=BottomLeft, radius=108, center=Point(108, 2232)}]}, FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY, FLAG_ROTATES_WITH_CONTENT, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS, FLAG_TRUSTED, installOrientation 0, displayShape DisplayShape{ spec=784481599 displayWidth=1080 displayHeight=2340 physicalPixelDisplaySizeRatio=1.0 rotation=0 offsetX=0 offsetY=0 scale=1.0}}
DisplayDeviceInfo{"scrcpy": uniqueId="virtual:com.google.SSRestartDetector,1000,scrcpy,0", 1080 x 2340, modeId 56, renderFrameRate 60.0, defaultModeId 56, supportedModes [{id=56, width=1080, height=2340, fps=60.0, alternativeRefreshRates=[], supportedHdrTypes=[]}], colorMode 0, supportedColorModes [0], hdrCapabilities null, allmSupported false, gameContentTypeSupported false, density 1, 1.0 x 1.0 dpi, appVsyncOff 0, presDeadline 16666666, touch NONE, rotation 0, type VIRTUAL, deviceProductInfo null, state ON, committedState UNKNOWN, owner com.google.SSRestartDetector (uid 1000), frameRateOverride , brightnessMinimum 0.0, brightnessMaximum 0.0, brightnessDefault 0.0, hdrSdrRatio NaN, FLAG_PRIVATE, installOrientation 0, displayShape DisplayShape{ spec=-1084927657 displayWidth=1080 displayHeight=2340 physicalPixelDisplaySizeRatio=1.0 rotation=0 offsetX=0 offsetY=0 scale=1.0}}

Pixel 5 A13 AVD (Magisk): scrcpy does not appear

dumpsys SurfaceFlinger:

Pixel 5 A14 scrcpy with --root:
Display 4630946523002478721 (physical, "")
   Composition Display State:
   isEnabled=true isSecure=true usesDeviceComposition=true
Display 11529215050129715134 (virtual, "scrcpy")
   Composition Display State:
   isEnabled=true isSecure=false usesDeviceComposition=false
...
Layer Display 40 name="scrcpy"#82010 pid:2094 uid:1000 handleAlive
Pixel 5 A13 AVD (Magisk):
Display 4619827259835644672 (physical, "EMU_display_0")
   Composition Display State:
   isEnabled=true isSecure=true usesDeviceComposition=true
Display 11529215050238090333 (virtual, "scrcpy")
   Composition Display State:
   isEnabled=true isSecure=true usesDeviceComposition=false

@Giantvince1
Copy link
Author

Giantvince1 commented Jun 29, 2024

That explains it; the display is not being marked with FLAG_SECURE. However AID_SYSTEM DOES own the screen, which means we just have to figure out HOW to specify the flag we need. Most likely we would also need to specify the display to be public instead of containing FLAG_PRIVATE, so that Android will just mirror to it on its own, but that's just speculation on my part.

It's gonna take some extra testing to see what happens with which changes; I already tried overriding the secure bool the same way you did during testing inside ScreenCapture.java, but to no avail; it still would not create a secure display. My best guess is that we have to either manually specify the flags we want using AOSP's docs as a base, or we have to manually figure out the positions of the flags we need on, and force those exact bits to 1 manually. Either way, it HAS to happen during instantiation, it's not changeable after the fact.

At least, that's what I gathered from the AOSP docs on the whole bit when I tried to make sense of them.
Also, I have read that SurfaceFlinger will always report the display as "secure" when it's not true; the part we have to rely on for accurate information is dumpsys display, as the FLAG_SECURE flag should always be present during --root operation, or on devices running A11 or lower.

@Giantvince1
Copy link
Author

Unless someone can take the time to figure out how to specify the desired display flag(s) needed for this to work, I'm gonna close this PR before it gets to be far too outdated and nothing more than a cumbersome patch set for a feature few would use. I will still keep my repo open to the public in case anyone wants to create a PR against it, but as it stands, it's already a fair bit behind upstream, and a rebase isn't in my immediate plans, especially considering only half the FLAG_SECURE puzzle has been solved (getting system rights rather than shell).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants