Commit Graph

271 Commits

Author SHA1 Message Date
osm0sis
615ad0cc5a core: remove remaining legacy workarounds/leftovers 2020-01-10 23:31:43 +08:00
topjohnwu
2db1e5cb74 Minor module related fixes 2019-12-30 13:21:39 +08:00
topjohnwu
3beffd84d6 Copy sepolicy rules to persist every boot 2019-12-22 03:44:07 -05:00
topjohnwu
3b9f7885e0 Stop using chdir 2019-12-21 05:29:38 -05:00
topjohnwu
7668e45890 Cleanup legacy code 2019-12-17 17:15:31 -05:00
topjohnwu
695c8bc5d0 Detect package name for copying binaries
Close #2152
2019-12-17 16:38:12 -05:00
topjohnwu
af060b3132 General QoL changes 2019-12-13 00:37:06 -05:00
topjohnwu
e373e59661 Make sure file descriptors are setup properly 2019-11-25 19:07:06 -05:00
topjohnwu
fd72f658c0 Fix SQL command when creating magiskdb 2019-11-21 14:40:12 -05:00
topjohnwu
576efbdc1b Move su logs out of magiskdb 2019-11-14 00:01:06 -05:00
topjohnwu
25c557248c Use ContentProvider call method for communication
Previously, we use either BroadcastReceivers or Activities to receive
messages from our native daemon, but both have their own downsides.
Some OEMs blocks broadcasts if the app is not running in the background,
regardless of who the caller is. Activities on the other hand, despite
working 100% of the time, will steal the focus of the current foreground
app, even though we are just doing some logging and showing a toast.
In addition, since stubs for hiding Magisk Manager is introduced, our
only communication method is left with the broadcast option, as
only broadcasting allows targeting a specific package name, not a
component name (which will be obfuscated in the case of stubs).

To make sure root requests will work on all devices, Magisk had to do
some experiments every boot to test whether broadcast is deliverable or
not. This makes the whole thing even more complicated then ever.

So lets take a look at another kind of component in Android apps:
ContentProviders. It is a vital part of Android's ecosystem, and as far
as I know no OEMs will block requests to ContentProviders (or else
tons of functionality will break catastrophically). Starting at API 11,
the system supports calling a specific method in ContentProviders,
optionally sending extra data along with the method call. This is
perfect for the native daemon to start a communication with Magisk
Manager. Another cool thing is that we no longer need to know the
component name of the reciever, as ContentProviders identify themselves
with an "authority" name, which in Magisk Manager's case is tied to the
package name. We already have a mechanism to keep track of our current
manager package name, so this works out of the box.

So yay! No more flaky broadcast tests, no more stupid OEMs blocking
broadcasts for some bizzare reasons. This method should in theory
work on almost all devices and situations.
2019-11-04 14:32:28 -05:00
topjohnwu
8277896ca1 Make sure uninstall.sh is executed on remove 2019-11-01 03:07:12 -04:00
topjohnwu
493068c073 Attempt to rescan zygote multiple times
Close #1654
2019-11-01 02:12:28 -04:00
topjohnwu
e7155837d7 Make sure magisk daemon won't get killed by init
According to this comment in #1880:
https://github.com/topjohnwu/Magisk/issues/1880#issuecomment-546657588

If Linux recycled our PPID, and coincidentally the process that reused
the PPID is root, AND init wants to kill the whole process group,
magiskd will get killed as a result.

There is no real way to block a SIGKILL signal, so we simply make sure
our daemon PID is the process group leader by renaming the directory.

Close #1880
2019-10-31 01:57:47 -04:00
topjohnwu
0f74e89b44 Introduce component agnostic communication
Usually, the communication between native and the app is done via
sending intents to either broadcast or activity. These communication
channels are for launching root requests dialogs, sending root request
notifications (the toast you see when an app gained root access), and
root request logging.

Sending intents by am (activity manager) usually requires specifying
the component name in the format of <pkg>/<class name>. This means parts
of Magisk Manager cannot be randomized or else the native daemon is
unable to know where to send data to the app.

On modern Android (not sure which API is it introduced), it is possible
to send broadcasts to a package, not a specific component. Which
component will receive the intent depends on the intent filter declared
in AndroidManifest.xml. Since we already have a mechanism in native code
to keep track of the package name of Magisk Manager, this makes it
perfect to pass intents to Magisk Manager that have components being
randomly obfuscated (stub APKs).

There are a few caveats though. Although this broadcasting method works
perfectly fine on AOSP and most systems, there are OEMs out there
shipping ROMs blocking broadcasts unexpectedly. In order to make sure
Magisk works in all kinds of scenarios, we run actual tests every boot
to determine which communication method should be used.

We have 3 methods in total, ordered in preference:
1. Broadcasting to a package
2. Broadcasting to a specific component
3. Starting a specific activity component

Method 3 will always work on any device, but the downside is anytime
a communication happens, Magisk Manager will steal foreground focus
regardless of whether UI is drawn. Method 1 is the only way to support
obfuscated stub APKs. The communication test will test method 1 and 2,
and if Magisk Manager is able to receive the messages, it will then
update the daemon configuration to use whichever is preferable. If none
of the broadcasts can be delivered, then the fallback method 3 will be
used.
2019-10-21 13:59:04 -04:00
topjohnwu
75306f658f Revert "Drop API 17 (Android 4.2) support"
Turns out that we cannot use AndroidKeystore anyways, so we don't
actually need to drop API 17. Revert this change.
2019-10-20 07:13:03 -04:00
topjohnwu
9c27d691dd Drop API 17 (Android 4.2) support 2019-10-19 03:11:54 -04:00
Simon Shi
f3d7f85063 Fix incorrect link path for /sbin/.core 2019-10-12 01:00:15 -04:00
topjohnwu
5e44b0b9d5 Use raw literals for scripts 2019-10-09 17:38:45 -04:00
topjohnwu
695e7e6da0 Create product mirror if /system/product exist 2019-09-23 06:52:24 -04:00
topjohnwu
b44f5122fd Pass int directly as pointer 2019-09-19 00:13:42 -04:00
topjohnwu
fe644e10d0 Make sure post-fs-data is first ran
Close #1601
2019-09-17 00:21:07 -04:00
topjohnwu
e31e687602 Allow ADB shell to remove modules and reboot 2019-09-13 03:14:21 -04:00
topjohnwu
86bfb22d4c Override module when .replace is found 2019-09-12 16:08:30 -04:00
topjohnwu
dd35224f92 Minor adjustments to exec_sql 2019-09-01 13:58:50 +08:00
topjohnwu
64ebc977e9 Small magic mount adjustments 2019-08-31 21:53:47 +08:00
topjohnwu
e89c50d934 Support /system/product wihtout /product
Fix #1676
2019-08-29 22:56:34 +08:00
topjohnwu
736729f5ef Maintain a list of pre-init mounts
Keep track of everything to unmount
2019-07-16 23:54:52 -07:00
topjohnwu
41045b62dc Introduce more randomness
- Use C++ random generator instead of old and broken rand()
- Randomize string length to piss off stupid detectors
2019-07-14 17:42:49 -07:00
topjohnwu
7233285437 Use relative symbolic links 2019-07-04 17:58:46 -07:00
topjohnwu
ff3710de66 Minor code changes across all sources 2019-06-30 19:09:31 -07:00
topjohnwu
e8b73ba6d1 Add separate product partition support 2019-06-29 14:19:10 -07:00
topjohnwu
1e94517a72 MagiskHide is coming back strong 2019-06-27 00:28:34 -07:00
topjohnwu
98f60216ac Temporary disable MagiskHide by default
Latest Android Q beta does not like when zygote is ptraced on
boot. Disable it for now until further investigation.
2019-06-25 23:32:07 -07:00
topjohnwu
e29b712108 Start Magisk in SAR 2019-06-25 23:31:59 -07:00
topjohnwu
4cc7aced15 Add new util function 2019-06-23 03:53:41 -07:00
topjohnwu
cfec0db947 Delay mounting sbin overlay 2019-06-22 03:14:33 -07:00
nonnymoose
8ebd9c8927 Use original file type when creating device nodes 2019-06-10 21:41:17 -07:00
topjohnwu
4fcdcd9a8a Detect UID from data directories 2019-06-03 23:32:49 -07:00
topjohnwu
7918fc3528 Support building individual applets 2019-05-30 21:17:58 -07:00
vvb2060
76c88913f9 Ensure Magisk environment normal 2019-05-27 16:29:54 -07:00
topjohnwu
845d1e02b0 Separate magiskinit components 2019-05-27 00:29:43 -07:00
topjohnwu
23d3e56967 Add new util function 2019-05-25 21:42:51 -07:00
topjohnwu
80cd85b061 Try to use broadcast for su logging and notify
In commit 8d4c407, native Magisk always launches an activity for
communicating with Magisk Manager. While this works extremely well,
since it also workaround stupid OEMs that blocks broadcasts, it has a
problem: launching an activity will claim the focus of the device,
which could be super annoying in some circumstances.

This commit adds a new feature to run a broadcast test on boot complete.
If Magisk Manager successfully receives the broadcast, it will toggle
a setting in magiskd so all future su loggings and notifies will always
use broadcasts instead of launching activities.

Fix #1412
2019-05-13 02:01:10 -07:00
Shaka Huang
415ff23be5 Fix error mounting /data partition
For devices come with two /data mount points, magisk will bind the one in tmpfs and failed to load modules since this partition is empty.

Signed-off-by: Shaka Huang <shakalaca@gmail.com>
2019-05-09 20:29:10 -07:00
Alexander Pohl
61ebc335c4 Add hi6250 support
not only hi3660 and kirin970,980 need this, also kirin 659 does
2019-05-05 11:45:21 -07:00
topjohnwu
781ec810d9 Remove unnecessary applets of MagiskInit 2019-05-01 13:55:59 -04:00
topjohnwu
00a9f18a1e Build with -Wall 2019-04-29 21:26:43 -04:00
topjohnwu
a2fa8d8be1 Stop fdsan complains 2019-04-29 20:04:39 -04:00
topjohnwu
70a3c78ebb Simplify magiskinit logging 2019-04-29 19:53:22 -04:00
topjohnwu
003e44fb84 Remove requirement to use early-init daemon
We used to construct /sbin tmpfs overlay in early-init stage after
SELinux is properly initialized. However the way it is implemented
(forking daemon from magiskinit with complicated file waiting triggers)
is extremely complicated and error prone.

This commit moves the construction of the sbin overlay to pre-init
stage. The catch is that since SELinux is not present at that point,
proper selabel has to be reconstructed afterwards. Some additional
SEPolicy rules are added to make sure init can access magisk binaries,
and the secontext relabeling task is assigned to the main Magisk daemon.
2019-04-24 00:13:48 -04:00
topjohnwu
f2b52755d6 Track all input devices with KEY_VOLUMEUP
This should in theory should support more devices for detecting the
volume up press on boot.

Close #1346
2019-04-21 19:09:08 -04:00
topjohnwu
f24df4f43d Don't allow cloning root nodes
The root nodes are /system and /vendor. Adding new files into these
directories, although works on some devices, mostly bootloops on many
devices out there. So don't allow it, which also makes the whole magic
mounting logic much easier and extensible.
2019-04-08 12:30:57 -04:00
topjohnwu
dab32e1599 Use our own device nodes for mirrors 2019-04-08 01:40:04 -04:00
topjohnwu
befe1a83b5 Use real system_root mirror 2019-04-07 14:22:45 -04:00
topjohnwu
82ea9db9fd Don't override arguments 2019-04-06 17:19:47 -04:00
topjohnwu
24f5bc98d8 Add boot_complete trigger back
Samsung does not like running cmd before system services are started.
Instead of failing, it will enter an infinite wait on binder.
Move APK installation to boot complete to make sure pm can be run
without blocking process.
2019-04-05 07:00:30 -04:00
topjohnwu
86789a8694 Add logging in magiskinit 2019-04-04 00:26:16 -04:00
topjohnwu
a385e5cd92 Use wrapper script on system with APEX
Thanks to moving libandroidicu.so to APEX runtime linker namespace,
we need a wrapper to link against libsqlite.so on Q
2019-04-03 17:25:47 -04:00
topjohnwu
cc77a24502 Prevent accidental magiskinit execution
Close #1281
2019-04-01 17:14:18 -04:00
topjohnwu
71a91ac7a7 Boot to recovery if volume up key is held
Forseeing the future that more and more A only system-as-root devices
would have similar bootloader behavior as the latest Samsung devices
(that is, no ramdisk will be loaded into memory when booting from
the boot partition), a solution/workaround has to be made when Magisk
is installed to the recovery partition, making custom recoveries
unable to co-exist with Magisk.

This commit allows magiskinit to read input device events from the
kernel to detect when a user holds volume key up to toggle whether
system-as-root mode is enabled. When system-as-root mode is disabled,
magiskinit will boot with ramdisk instead of cloning rootfs from system,
which in this case will boot to the recovery.
2019-04-01 03:01:05 -04:00
topjohnwu
1b0c36dbd5 Remove outdated comments 2019-03-31 15:40:55 -04:00
topjohnwu
c577a9525d Remove simple mount mode
This mode is proven to have no difference than normal post-fs-data
module mounting. No reason to keep this code in the sources.
2019-03-31 15:10:01 -04:00
topjohnwu
0149b1368d Several improvements 2019-03-31 06:32:33 -04:00
topjohnwu
cd6bcb97ef Cleanup stuffs 2019-03-31 00:48:22 -04:00
topjohnwu
df4161ffcc Reboot to recovery when running as recovery 2019-03-30 06:49:29 -04:00
topjohnwu
7a133eaf03 Block vaultkeeper and flash_recovery service 2019-03-30 04:13:45 -04:00
topjohnwu
1cd45b53b1 Support recovery based Magisk
Some devices (mainly new Samsung phones we're talking here...) using
A only system-as-root refuse to load ramdisk when booted with boot
no matter what we do. With many A only system-as-root devices, even
though their boot image is kernel only, we can still be able to add
a ramdisk section into the image and force the kernel to use it as
rootfs. However the bootloader on devices like the S10 simply does
not load anything within boot image into memory other than the kernel.
This gives as the only option is to install Magisk on the recovery
partition. This commits adds proper support for these kind of scenarios.
2019-03-30 00:49:48 -04:00
topjohnwu
8de03eef3f Allow modules to have custom uninstaller script 2019-03-23 03:50:55 -04:00
topjohnwu
8df942f96e Adjust scripting 2019-03-23 03:36:35 -04:00
topjohnwu
9bb2243b56 Switch to skip_mount instead of auto_mount
95%+ of existing modules enables auto mount (obviously).
Switching auto mount to opt-out makes more sense than opt-in as
in previous module format. The file 'auto_mount' will be ignored, and
the file 'skip_mount' will be checked to toggle the mounting behavior.

After scanning through the current Magisk Module Repo modules, no
modules are using custom bind mounting; all modules with auto mount
disabled have empty system folder, which means this change will not
affect any existing module.
2019-03-23 03:05:38 -04:00
topjohnwu
eae1c17738 Remove features before aborting 2019-03-22 02:01:36 -04:00
topjohnwu
ea55532e33 Copy busybox instead of bind mounting 2019-03-22 01:52:13 -04:00
topjohnwu
2a40cb60a9 Behave more sane in extreme conditions 2019-03-22 01:50:33 -04:00
topjohnwu
945f88105f Support system-as-root devices with monolithic sepolicy 2019-03-18 04:54:15 -04:00
topjohnwu
957feca626 Limit sepolicy load to Android Q only
It seems both Android cancers, Samsung and Huawei devices, don't
like preloading sepolicy. For a temporary solution now is to limit
the sepolicy loading to Android Q only.
2019-03-16 17:15:48 -04:00
topjohnwu
c0447009db Allow entrypoint for rootfs construction simulation 2019-03-16 04:45:56 -04:00
topjohnwu
8893cbd64a Modularize MagiskInit 2019-03-15 14:46:30 -04:00
topjohnwu
f0240b1f06 Support Android Q new split sepolicy setup 2019-03-15 06:17:37 -04:00
topjohnwu
e476c18c99 Don't load sepolicy on Huawei devices
Of course, the cancer of Android, Huawei, has to do some f**king weird
modifications to the Linux kernel. Its kernel only accepts 1 single
policy load in its lifetime, a second load will result in ENOMEM error.
Since Huawei devices always use their own stupid ramdisk setup and not
system-as-root, not loading sepolicy is not a concern (for now).
2019-03-14 22:48:23 -04:00
topjohnwu
a1b5185ecb Make sure rootfs file selabels are correct
Android Q init assumes rootfs to always be on EXT4 images, thus
never runs restorecon on the whole root directory. This is an issue
because some folders in rootfs were set with special selabels in
the system partition, but when copying over to initramfs by magiskinit,
these labels will not be preserved.

So the solution is to relabel the files in rootfs with the original
context right? Yes, but rootfs does not allow security xattr to be set
on files before the kernel SELinux initializes with genfs_contexts.
We have to load our sepolicy to the kernel before we clone the root
directory from system partition, which we will also restore the selabel
in the meantime.

Unfortunately this means that for each reboot, the exact same policy
will be loaded to the kernel twice: once in magiskinit so we can label
rootfs properly, and once by the original init, which is part of the
boot procedure. There is no easy way to prevent init from loading
sepolicy, as init will refuse to continue if policy loading has failed.
2019-03-14 22:27:29 -04:00
topjohnwu
70efddb90f Only use SELinux if necessary in init 2019-03-09 05:30:42 -05:00
topjohnwu
0204d05316 Remove Zygote notifier
Temporary trigger process scan on packages.xml updates, will find better methods
2019-03-08 03:35:17 -05:00
topjohnwu
d2cb638fcd Use our own function to parse int 2019-03-07 20:31:35 -05:00
topjohnwu
82c864d57e Make zygote notifier more reliable 2019-03-06 18:22:04 -05:00
topjohnwu
6226f875ff Make db settings constructor more readable 2019-03-06 08:21:23 -05:00
topjohnwu
370015a853 Modernize database code (again) 2019-03-06 08:16:12 -05:00
topjohnwu
4e53ebfe44 Use both package name and process name as key
Different packages could potentially use the same process name,
and they shouldn't conflict with each other.
2019-03-06 05:40:52 -05:00
topjohnwu
04ef1e6405 Make parse prop file a util function 2019-03-05 20:27:09 -05:00
topjohnwu
b278d07b05 Switch to Zygote ptrace-ing
No matter if we use the old, buggy, error prone am_proc_start monitoring,
or the new APK inotify method, both methods rely on MagiskHide 'reacting'
fast enough to hijack the process before any detection has been done.

However, this is not reliable and practical. There are apps that utilize
native libraries to start detects and register SIGCONT signal handlers
to mitigate all existing MagiskHide process monitoring mechanism. So
our only solution is to hijack an app BEFORE it is started.

All Android apps' process is forked from zygote, so it is easily the
target to be monitored. All forks will be notified, and subsequent
thread spawning (Android apps are heaviliy multithreaded) from children
are also closely monitored to find the earliest possible point to
identify what the process will eventually be (before am_proc_bound).

ptrace is extremely complicated and very difficult to get right. The
current code is heaviliy tested on a stock Android 9.0 Pixel system,
so in theory it should work fine on most devices, but more tests and
potentially fixes are expected to follow this commit.
2019-03-05 20:23:27 -05:00
topjohnwu
6c3896079d Add zygote server notifier 2019-03-05 20:23:27 -05:00
topjohnwu
eaa9c7e2a0 Android Q init is not always a symlink 2019-03-03 14:56:36 -05:00
topjohnwu
14ae29d907 Support Android Q new init setup 2019-03-03 06:35:25 -05:00
topjohnwu
b1afd554fc Application Component Granularity MagiskHide
Before switching to the new MagiskHide implementation (APK inotify),
logcat parsing provides us lots of information to target a process.
We were targeting components so that apps with multi-processes
can still be hidden properly.

After switching to the new implementation, our granularity is limited
to the UID of the process. This is especially dangerous since Android
allow apps signed with the same signature to share UIDs, and many system
apps utilize this for elevated permissions for some services.

This commit introduces process name matching. We could not blanketly
target an UID, so the workaround is to verify its process name before
unmounting.

The tricky thing is that any app developer is allowed to name the
process of its component to whatever they want; there is no 'one
rule to catch them all' to target a specific package. As a result,
Magisk Manager is updated to scan through all components of all apps,
and show different processes of the same app, each as a separate
hide target in the list.

The hide target database also has to be updated accordingly.
Each hide target is now a <package name, process name> pair. The
magiskhide CLI and Magisk Manager is updated to support this new
target format.
2019-03-01 17:08:08 -05:00
vvb2060
f152bea8d8 Trim dev name 2019-02-26 03:04:17 -05:00
topjohnwu
8032bd0bac Introduce /data mirror
Since we switched to imageless Magisk, module files are directly
stored in /data. However, /data is mounted with nosuid, which also
prevents SELinux typetransition to work (auto transition from one
domain to another when executing files with specific context).
This could cause serious issues when we are replacing system critical
components (e.g. app_process for Xposed), because most of them
are daemons that run in special process domains.

This commit introduced /data mirror. Using similar mirroring technique
we used for system and vendor, we mount another mirror that mounts
/data without nosuid flag. All module files are then mounted from this
mirror mountpoint instead of directly from /data.

Close #1080
2019-02-25 06:13:42 -05:00
topjohnwu
0c227f2917 Always clone attribute from existing files to module files
This makes sure no weird permission/SELinux issues shall happen
2019-02-25 05:17:08 -05:00
topjohnwu
c9fa8118d1 Some code adjustments 2019-02-24 23:09:34 -05:00
topjohnwu
63b18246d8 Add compressed ramdisk support 2019-02-24 20:39:01 -05:00
topjohnwu
bd4e5bfc1a Some minor optmizations 2019-02-24 17:45:08 -05:00