Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
M
Magisk
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Magisk
Commits
bec5edca
Commit
bec5edca
authored
Jan 29, 2021
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Avoiding using shell I/O
parent
6fb20b3e
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
192 additions
and
132 deletions
+192
-132
App.kt
app/src/main/java/com/topjohnwu/magisk/core/App.kt
+3
-2
Info.kt
app/src/main/java/com/topjohnwu/magisk/core/Info.kt
+3
-1
MagiskInstaller.kt
...n/java/com/topjohnwu/magisk/core/tasks/MagiskInstaller.kt
+127
-104
ShellInit.kt
...rc/main/java/com/topjohnwu/magisk/core/utils/ShellInit.kt
+46
-17
manager.sh
app/src/main/res/raw/manager.sh
+12
-7
gradle.properties
gradle.properties
+1
-1
No files found.
app/src/main/java/com/topjohnwu/magisk/core/App.kt
View file @
bec5edca
...
@@ -10,8 +10,9 @@ import androidx.multidex.MultiDex
...
@@ -10,8 +10,9 @@ import androidx.multidex.MultiDex
import
androidx.work.WorkManager
import
androidx.work.WorkManager
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.DynAPK
import
com.topjohnwu.magisk.DynAPK
import
com.topjohnwu.magisk.core.utils.AppShellInit
import
com.topjohnwu.magisk.core.utils.BusyBoxInit
import
com.topjohnwu.magisk.core.utils.IODispatcherExecutor
import
com.topjohnwu.magisk.core.utils.IODispatcherExecutor
import
com.topjohnwu.magisk.core.utils.RootInit
import
com.topjohnwu.magisk.core.utils.updateConfig
import
com.topjohnwu.magisk.core.utils.updateConfig
import
com.topjohnwu.magisk.di.koinModules
import
com.topjohnwu.magisk.di.koinModules
import
com.topjohnwu.magisk.ktx.unwrap
import
com.topjohnwu.magisk.ktx.unwrap
...
@@ -32,7 +33,7 @@ open class App() : Application() {
...
@@ -32,7 +33,7 @@ open class App() : Application() {
AppCompatDelegate
.
setCompatVectorFromResourcesEnabled
(
true
)
AppCompatDelegate
.
setCompatVectorFromResourcesEnabled
(
true
)
Shell
.
setDefaultBuilder
(
Shell
.
Builder
.
create
()
Shell
.
setDefaultBuilder
(
Shell
.
Builder
.
create
()
.
setFlags
(
Shell
.
FLAG_MOUNT_MASTER
)
.
setFlags
(
Shell
.
FLAG_MOUNT_MASTER
)
.
setInitializers
(
Root
Init
::
class
.
java
)
.
setInitializers
(
BusyBoxInit
::
class
.
java
,
AppShell
Init
::
class
.
java
)
.
setTimeout
(
2
))
.
setTimeout
(
2
))
Shell
.
EXECUTOR
=
IODispatcherExecutor
()
Shell
.
EXECUTOR
=
IODispatcherExecutor
()
...
...
app/src/main/java/com/topjohnwu/magisk/core/Info.kt
View file @
bec5edca
package
com.topjohnwu.magisk.core
package
com.topjohnwu.magisk.core
import
android.os.Build
import
androidx.databinding.ObservableBoolean
import
androidx.databinding.ObservableBoolean
import
com.topjohnwu.magisk.DynAPK
import
com.topjohnwu.magisk.DynAPK
import
com.topjohnwu.magisk.core.model.UpdateInfo
import
com.topjohnwu.magisk.core.model.UpdateInfo
...
@@ -34,9 +35,10 @@ object Info {
...
@@ -34,9 +35,10 @@ object Info {
@JvmStatic
val
isFDE
get
()
=
crypto
==
"block"
@JvmStatic
val
isFDE
get
()
=
crypto
==
"block"
@JvmField
var
ramdisk
=
false
@JvmField
var
ramdisk
=
false
@JvmField
var
hasGMS
=
true
@JvmField
var
hasGMS
=
true
@JvmField
va
r
isPixel
=
false
@JvmField
va
l
isPixel
=
Build
.
BRAND
==
"google"
@JvmField
val
isEmulator
=
getProperty
(
"ro.kernel.qemu"
,
"0"
)
==
"1"
@JvmField
val
isEmulator
=
getProperty
(
"ro.kernel.qemu"
,
"0"
)
==
"1"
var
crypto
=
""
var
crypto
=
""
var
noDataExec
=
false
val
isConnected
by
lazy
{
val
isConnected
by
lazy
{
ObservableBoolean
(
false
).
also
{
field
->
ObservableBoolean
(
false
).
also
{
field
->
...
...
app/src/main/java/com/topjohnwu/magisk/core/tasks/MagiskInstaller.kt
View file @
bec5edca
...
@@ -8,9 +8,9 @@ import androidx.core.os.postDelayed
...
@@ -8,9 +8,9 @@ import androidx.core.os.postDelayed
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.DynAPK
import
com.topjohnwu.magisk.DynAPK
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.core.
Config
import
com.topjohnwu.magisk.core.
*
import
com.topjohnwu.magisk.core.
Cons
t
import
com.topjohnwu.magisk.core.
utils.BusyBoxIni
t
import
com.topjohnwu.magisk.core.
isRunningAsStub
import
com.topjohnwu.magisk.core.
utils.LightShellInit
import
com.topjohnwu.magisk.core.utils.MediaStoreUtils
import
com.topjohnwu.magisk.core.utils.MediaStoreUtils
import
com.topjohnwu.magisk.core.utils.MediaStoreUtils.inputStream
import
com.topjohnwu.magisk.core.utils.MediaStoreUtils.inputStream
import
com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
import
com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
...
@@ -27,8 +27,6 @@ import com.topjohnwu.superuser.ShellUtils
...
@@ -27,8 +27,6 @@ import com.topjohnwu.superuser.ShellUtils
import
com.topjohnwu.superuser.internal.NOPList
import
com.topjohnwu.superuser.internal.NOPList
import
com.topjohnwu.superuser.internal.UiThreadHandler
import
com.topjohnwu.superuser.internal.UiThreadHandler
import
com.topjohnwu.superuser.io.SuFile
import
com.topjohnwu.superuser.io.SuFile
import
com.topjohnwu.superuser.io.SuFileInputStream
import
com.topjohnwu.superuser.io.SuFileOutputStream
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.withContext
import
kotlinx.coroutines.withContext
import
net.jpountz.lz4.LZ4FrameInputStream
import
net.jpountz.lz4.LZ4FrameInputStream
...
@@ -53,7 +51,9 @@ abstract class MagiskInstallImpl protected constructor(
...
@@ -53,7 +51,9 @@ abstract class MagiskInstallImpl protected constructor(
protected
lateinit
var
installDir
:
File
protected
lateinit
var
installDir
:
File
private
lateinit
var
srcBoot
:
File
private
lateinit
var
srcBoot
:
File
private
var
tarOut
:
TarOutputStream
?
=
null
private
lateinit
var
shell
:
Shell
private
var
closeShell
=
false
private
val
service
:
NetworkService
by
inject
()
private
val
service
:
NetworkService
by
inject
()
protected
val
context
:
Context
by
inject
(
Protected
)
protected
val
context
:
Context
by
inject
(
Protected
)
...
@@ -68,7 +68,7 @@ abstract class MagiskInstallImpl protected constructor(
...
@@ -68,7 +68,7 @@ abstract class MagiskInstallImpl protected constructor(
return
true
return
true
}
}
private
fun
findSecondary
Image
():
Boolean
{
private
fun
findSecondary
():
Boolean
{
val
slot
=
"echo \$SLOT"
.
fsh
()
val
slot
=
"echo \$SLOT"
.
fsh
()
val
target
=
if
(
slot
==
"_a"
)
"_b"
else
"_a"
val
target
=
if
(
slot
==
"_a"
)
"_b"
else
"_a"
console
.
add
(
"- Target slot: $target"
)
console
.
add
(
"- Target slot: $target"
)
...
@@ -86,26 +86,13 @@ abstract class MagiskInstallImpl protected constructor(
...
@@ -86,26 +86,13 @@ abstract class MagiskInstallImpl protected constructor(
return
true
return
true
}
}
private
fun
installDirFile
(
name
:
String
):
File
{
return
if
(
installDir
is
SuFile
)
SuFile
(
installDir
,
name
)
else
File
(
installDir
,
name
)
}
private
fun
extractFiles
():
Boolean
{
private
fun
extractFiles
():
Boolean
{
console
.
add
(
"- Device platform: ${Const.CPU_ABI}"
)
console
.
add
(
"- Device platform: ${Const.CPU_ABI}"
)
console
.
add
(
"- Installing: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})"
)
console
.
add
(
"- Installing: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})"
)
val
binDir
=
File
(
context
.
filesDir
.
parent
,
"install"
)
installDir
=
File
(
context
.
filesDir
.
parent
,
"install"
)
binDir
.
deleteRecursively
()
installDir
.
deleteRecursively
()
binDir
.
mkdirs
()
installDir
.
mkdirs
()
installDir
=
if
(
Shell
.
rootAccess
())
{
SuFile
(
"${Const.TMPDIR}/install"
)
}
else
{
binDir
}
try
{
try
{
// Extract binaries
// Extract binaries
...
@@ -116,7 +103,7 @@ abstract class MagiskInstallImpl protected constructor(
...
@@ -116,7 +103,7 @@ abstract class MagiskInstallImpl protected constructor(
}.
forEach
{
}.
forEach
{
val
n
=
it
.
name
.
substring
(
it
.
name
.
lastIndexOf
(
'/'
)
+
1
)
val
n
=
it
.
name
.
substring
(
it
.
name
.
lastIndexOf
(
'/'
)
+
1
)
val
name
=
n
.
substring
(
3
,
n
.
length
-
3
)
val
name
=
n
.
substring
(
3
,
n
.
length
-
3
)
val
dest
=
File
(
bin
Dir
,
name
)
val
dest
=
File
(
install
Dir
,
name
)
zf
.
getInputStream
(
it
).
writeTo
(
dest
)
zf
.
getInputStream
(
it
).
writeTo
(
dest
)
}
}
}
else
{
}
else
{
...
@@ -125,21 +112,21 @@ abstract class MagiskInstallImpl protected constructor(
...
@@ -125,21 +112,21 @@ abstract class MagiskInstallImpl protected constructor(
}
?:
emptyArray
()
}
?:
emptyArray
()
for
(
lib
in
libs
)
{
for
(
lib
in
libs
)
{
val
name
=
lib
.
name
.
substring
(
3
,
lib
.
name
.
length
-
3
)
val
name
=
lib
.
name
.
substring
(
3
,
lib
.
name
.
length
-
3
)
val
bin
=
File
(
bin
Dir
,
name
)
val
bin
=
File
(
install
Dir
,
name
)
symlink
(
lib
.
path
,
bin
.
path
)
symlink
(
lib
.
path
,
bin
.
path
)
}
}
}
}
// Extract scripts
// Extract scripts
for
(
script
in
listOf
(
"util_functions.sh"
,
"boot_patch.sh"
,
"addon.d.sh"
))
{
for
(
script
in
listOf
(
"util_functions.sh"
,
"boot_patch.sh"
,
"addon.d.sh"
))
{
val
dest
=
File
(
bin
Dir
,
script
)
val
dest
=
File
(
install
Dir
,
script
)
context
.
assets
.
open
(
script
).
writeTo
(
dest
)
context
.
assets
.
open
(
script
).
writeTo
(
dest
)
}
}
// Extract chromeos tools
// Extract chromeos tools
File
(
bin
Dir
,
"chromeos"
).
mkdir
()
File
(
install
Dir
,
"chromeos"
).
mkdir
()
for
(
file
in
listOf
(
"futility"
,
"kernel_data_key.vbprivk"
,
"kernel.keyblock"
))
{
for
(
file
in
listOf
(
"futility"
,
"kernel_data_key.vbprivk"
,
"kernel.keyblock"
))
{
val
name
=
"chromeos/$file"
val
name
=
"chromeos/$file"
val
dest
=
File
(
bin
Dir
,
name
)
val
dest
=
File
(
install
Dir
,
name
)
context
.
assets
.
open
(
name
).
writeTo
(
dest
)
context
.
assets
.
open
(
name
).
writeTo
(
dest
)
}
}
}
catch
(
e
:
Exception
)
{
}
catch
(
e
:
Exception
)
{
...
@@ -148,19 +135,10 @@ abstract class MagiskInstallImpl protected constructor(
...
@@ -148,19 +135,10 @@ abstract class MagiskInstallImpl protected constructor(
return
false
return
false
}
}
if
(
installDir
!==
binDir
)
{
arrayOf
(
"rm -rf $installDir"
,
"mkdir -p $installDir"
,
"cp_readlink $binDir $installDir"
,
"rm -rf $binDir"
).
sh
()
}
return
true
return
true
}
}
private
fun
newEntry
(
name
:
String
,
size
:
Long
):
TarEntry
{
private
fun
new
Tar
Entry
(
name
:
String
,
size
:
Long
):
TarEntry
{
console
.
add
(
"-- Writing: $name"
)
console
.
add
(
"-- Writing: $name"
)
return
TarEntry
(
TarHeader
.
createHeader
(
name
,
size
,
0
,
false
,
420
/* 0644 */
))
return
TarEntry
(
TarHeader
.
createHeader
(
name
,
size
,
0
,
false
,
420
/* 0644 */
))
}
}
...
@@ -172,8 +150,13 @@ abstract class MagiskInstallImpl protected constructor(
...
@@ -172,8 +150,13 @@ abstract class MagiskInstallImpl protected constructor(
TarInputStream
(
input
).
use
{
tarIn
->
TarInputStream
(
input
).
use
{
tarIn
->
lateinit
var
entry
:
TarEntry
lateinit
var
entry
:
TarEntry
fun
decompressedStream
()
=
fun
decompressedStream
():
InputStream
{
if
(
entry
.
name
.
endsWith
(
".lz4"
))
LZ4FrameInputStream
(
tarIn
)
else
tarIn
val
src
=
if
(
entry
.
name
.
endsWith
(
".lz4"
))
LZ4FrameInputStream
(
tarIn
)
else
tarIn
return
object
:
FilterInputStream
(
src
)
{
override
fun
available
()
=
0
/* Workaround bug in LZ4FrameInputStream */
override
fun
close
()
{
/* Never close src stream */
}
}
}
while
(
tarIn
.
nextEntry
?.
let
{
entry
=
it
}
!=
null
)
{
while
(
tarIn
.
nextEntry
?.
let
{
entry
=
it
}
!=
null
)
{
if
(
entry
.
name
.
contains
(
"boot.img"
)
||
if
(
entry
.
name
.
contains
(
"boot.img"
)
||
...
@@ -181,15 +164,10 @@ abstract class MagiskInstallImpl protected constructor(
...
@@ -181,15 +164,10 @@ abstract class MagiskInstallImpl protected constructor(
val
name
=
entry
.
name
.
replace
(
".lz4"
,
""
)
val
name
=
entry
.
name
.
replace
(
".lz4"
,
""
)
console
.
add
(
"-- Extracting: $name"
)
console
.
add
(
"-- Extracting: $name"
)
val
extract
=
installDirFile
(
name
)
val
extract
=
File
(
installDir
,
name
)
SuFileOutputStream
(
extract
).
use
{
decompressedStream
().
copyTo
(
it
)
}
decompressedStream
().
writeTo
(
extract
)
}
else
if
(
entry
.
name
.
contains
(
"vbmeta.img"
))
{
}
else
if
(
entry
.
name
.
contains
(
"vbmeta.img"
))
{
// DO NOT USE readBytes() DUE TO BUG IN LZ4FrameInputStream
val
rawData
=
decompressedStream
().
readBytes
()
val
rawData
=
decompressedStream
().
run
{
val
buffer
=
ByteArrayOutputStream
()
copyTo
(
buffer
)
buffer
.
toByteArray
()
}
// Valid vbmeta.img should be at least 256 bytes
// Valid vbmeta.img should be at least 256 bytes
if
(
rawData
.
size
<
256
)
if
(
rawData
.
size
<
256
)
continue
continue
...
@@ -198,7 +176,7 @@ abstract class MagiskInstallImpl protected constructor(
...
@@ -198,7 +176,7 @@ abstract class MagiskInstallImpl protected constructor(
// AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED
// AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED
console
.
add
(
"-- Patching: vbmeta.img"
)
console
.
add
(
"-- Patching: vbmeta.img"
)
ByteBuffer
.
wrap
(
rawData
).
putInt
(
120
,
3
)
ByteBuffer
.
wrap
(
rawData
).
putInt
(
120
,
3
)
tarOut
.
putNextEntry
(
newEntry
(
"vbmeta.img"
,
rawData
.
size
.
toLong
()))
tarOut
.
putNextEntry
(
new
Tar
Entry
(
"vbmeta.img"
,
rawData
.
size
.
toLong
()))
tarOut
.
write
(
rawData
)
tarOut
.
write
(
rawData
)
}
else
{
}
else
{
console
.
add
(
"-- Copying: ${entry.name}"
)
console
.
add
(
"-- Copying: ${entry.name}"
)
...
@@ -207,19 +185,21 @@ abstract class MagiskInstallImpl protected constructor(
...
@@ -207,19 +185,21 @@ abstract class MagiskInstallImpl protected constructor(
}
}
}
}
}
}
val
boot
=
installDirFile
(
"boot.img"
)
val
boot
=
File
(
installDir
,
"boot.img"
)
val
recovery
=
installDirFile
(
"recovery.img"
)
val
recovery
=
File
(
installDir
,
"recovery.img"
)
if
(
Config
.
recovery
&&
recovery
.
exists
()
&&
boot
.
exists
())
{
if
(
Config
.
recovery
&&
recovery
.
exists
()
&&
boot
.
exists
())
{
// Install
Magisk
to recovery
// Install to recovery
srcBoot
=
recovery
srcBoot
=
recovery
// Repack boot image to prevent restore
// Repack boot image to prevent
auto
restore
arrayOf
(
arrayOf
(
"cd $installDir"
,
"./magiskboot unpack boot.img"
,
"./magiskboot unpack boot.img"
,
"./magiskboot repack boot.img"
,
"./magiskboot repack boot.img"
,
"./magiskboot cleanup"
,
"./magiskboot cleanup"
,
"mv new-boot.img boot.img"
).
sh
()
"mv new-boot.img boot.img"
,
SuFileInputStream
(
boot
).
use
{
"cd /"
).
sh
()
tarOut
.
putNextEntry
(
newEntry
(
"boot.img"
,
boot
.
length
()))
boot
.
inputStream
().
use
{
tarOut
.
putNextEntry
(
newTarEntry
(
"boot.img"
,
boot
.
length
()))
it
.
copyTo
(
tarOut
)
it
.
copyTo
(
tarOut
)
}
}
boot
.
delete
()
boot
.
delete
()
...
@@ -263,9 +243,9 @@ abstract class MagiskInstallImpl protected constructor(
...
@@ -263,9 +243,9 @@ abstract class MagiskInstallImpl protected constructor(
handleTar
(
src
,
outFile
!!
.
uri
.
outputStream
())
handleTar
(
src
,
outFile
!!
.
uri
.
outputStream
())
}
else
{
}
else
{
// Raw image
// Raw image
srcBoot
=
installDirFile
(
"boot.img"
)
srcBoot
=
File
(
installDir
,
"boot.img"
)
console
.
add
(
"- Copying image to cache"
)
console
.
add
(
"- Copying image to cache"
)
SuFileOutputStream
(
srcBoot
).
use
{
src
.
copyTo
(
it
)
}
src
.
writeTo
(
srcBoot
)
outFile
=
MediaStoreUtils
.
getFile
(
"$filename.img"
,
true
)
outFile
=
MediaStoreUtils
.
getFile
(
"$filename.img"
,
true
)
outFile
!!
.
uri
.
outputStream
()
outFile
!!
.
uri
.
outputStream
()
}
}
...
@@ -285,12 +265,12 @@ abstract class MagiskInstallImpl protected constructor(
...
@@ -285,12 +265,12 @@ abstract class MagiskInstallImpl protected constructor(
// Output file
// Output file
try
{
try
{
val
patched
=
installDirFile
(
"new-boot.img"
)
val
patched
=
File
(
installDir
,
"new-boot.img"
)
if
(
outStream
is
TarOutputStream
)
{
if
(
outStream
is
TarOutputStream
)
{
val
name
=
if
(
srcBoot
.
path
.
contains
(
"recovery"
))
"recovery.img"
else
"boot.img"
val
name
=
if
(
srcBoot
.
path
.
contains
(
"recovery"
))
"recovery.img"
else
"boot.img"
outStream
.
putNextEntry
(
newEntry
(
name
,
patched
.
length
()))
outStream
.
putNextEntry
(
new
Tar
Entry
(
name
,
patched
.
length
()))
}
}
withStreams
(
SuFileInputStream
(
patched
),
outStream
)
{
src
,
out
->
src
.
copyTo
(
out
)
}
withStreams
(
patched
.
inputStream
(
),
outStream
)
{
src
,
out
->
src
.
copyTo
(
out
)
}
patched
.
delete
()
patched
.
delete
()
console
.
add
(
""
)
console
.
add
(
""
)
...
@@ -306,22 +286,56 @@ abstract class MagiskInstallImpl protected constructor(
...
@@ -306,22 +286,56 @@ abstract class MagiskInstallImpl protected constructor(
}
}
// Fix up binaries
// Fix up binaries
if
(
installDir
is
SuFile
)
{
srcBoot
.
delete
()
"fix_env $installDir"
.
sh
()
"cp_readlink $installDir"
.
sh
()
}
else
{
"cp_readlink $installDir"
.
sh
()
}
return
true
return
true
}
}
private
fun
rootInputStream
(
file
:
File
):
InputStream
{
return
if
(
file
is
SuFile
)
object
:
BufferedInputStream
(
null
)
{
private
val
tmp
=
File
.
createTempFile
(
file
.
name
,
null
,
context
.
cacheDir
).
also
{
// Copy to tmp file and read from there
"cat $file > $it"
.
sh
()
`in`
=
it
.
inputStream
()
}
override
fun
close
()
{
super
.
close
()
tmp
.
delete
()
}
}
else
file
.
inputStream
().
buffered
()
}
private
fun
patchBoot
():
Boolean
{
private
fun
patchBoot
():
Boolean
{
"cd $installDir"
.
sh
()
val
inRootDir
=
shell
.
isRoot
&&
Info
.
noDataExec
val
newBootImg
:
File
if
(
inRootDir
)
{
// Migrate everything to tmpfs to workaround Samsung bullshit
SuFile
(
"${Const.TMPDIR}/install"
).
also
{
arrayOf
(
"rm -rf $it"
,
"mkdir -p $it"
,
"cp_readlink $installDir $it"
,
"rm -rf $installDir"
).
sh
()
installDir
=
it
}
newBootImg
=
SuFile
(
installDir
,
"new-boot.img"
)
}
else
{
newBootImg
=
File
(
installDir
,
"new-boot.img"
)
// Create the output file before hand
newBootImg
.
createNewFile
()
}
var
isSigned
=
false
var
isSigned
=
false
if
(
srcBoot
.
let
{
it
!
is
SuFile
||
!
it
.
isCharacter
})
{
if
(
srcBoot
.
let
{
it
!
is
SuFile
||
!
it
.
isCharacter
})
{
try
{
try
{
SuFile
InputStream
(
srcBoot
).
use
{
root
InputStream
(
srcBoot
).
use
{
if
(
SignBoot
.
verifySignature
(
it
,
null
))
{
if
(
SignBoot
.
verifySignature
(
it
,
null
))
{
isSigned
=
true
isSigned
=
true
console
.
add
(
"- Boot image is signed with AVB 1.0"
)
console
.
add
(
"- Boot image is signed with AVB 1.0"
)
...
@@ -333,90 +347,99 @@ abstract class MagiskInstallImpl protected constructor(
...
@@ -333,90 +347,99 @@ abstract class MagiskInstallImpl protected constructor(
}
}
}
}
val
FLAGS
=
val
flags
=
"KEEPFORCEENCRYPT=${Config.keepEnc} "
+
"KEEPFORCEENCRYPT=${Config.keepEnc} "
+
"KEEPVERITY=${Config.keepVerity} "
+
"KEEPVERITY=${Config.keepVerity} "
+
"RECOVERYMODE=${Config.recovery}"
"RECOVERYMODE=${Config.recovery}"
if
(!
"
$FLAGS
sh boot_patch.sh $srcBoot"
.
sh
().
isSuccess
)
if
(!
"
cd $installDir; $flags
sh boot_patch.sh $srcBoot"
.
sh
().
isSuccess
)
return
false
return
false
val
job
=
Shell
.
sh
(
"./magiskboot cleanup"
,
"cd /"
)
val
job
=
shell
.
newJob
().
add
(
"./magiskboot cleanup"
,
"cd /"
)
val
patched
=
installDirFile
(
"new-boot.img"
)
if
(
isSigned
)
{
if
(
isSigned
)
{
console
.
add
(
"- Signing boot image with verity keys"
)
console
.
add
(
"- Signing boot image with verity keys"
)
val
signed
=
installDirFile
(
"signed.img"
)
val
signed
=
File
.
createTempFile
(
"signed"
,
".img"
,
context
.
cacheDir
)
try
{
try
{
withStreams
(
SuFileInputStream
(
patched
),
SuFileOutputStream
(
signed
))
{
withStreams
(
rootInputStream
(
newBootImg
),
signed
.
outputStream
().
buffered
(
))
{
input
,
out
->
SignBoot
.
doSignature
(
null
,
null
,
input
,
out
,
"/boot"
)
src
,
out
->
SignBoot
.
doSignature
(
null
,
null
,
src
,
out
,
"/boot"
)
}
}
}
catch
(
e
:
IOException
)
{
}
catch
(
e
:
IOException
)
{
console
.
add
(
"! Unable to sign image"
)
console
.
add
(
"! Unable to sign image"
)
Timber
.
e
(
e
)
Timber
.
e
(
e
)
return
false
return
false
}
}
if
(
inRootDir
)
{
job
.
add
(
"mv -f $signed $patched"
)
job
.
add
(
"cp -f $signed $newBootImg"
,
"rm -f $signed"
)
}
else
{
signed
.
copyTo
(
newBootImg
,
overwrite
=
true
)
signed
.
delete
()
}
}
}
job
.
exec
()
job
.
exec
()
return
true
return
true
}
}
private
fun
flashBoot
():
Boolean
{
private
fun
flashBoot
()
=
"direct_install $installDir $srcBoot"
.
sh
().
isSuccess
if
(!
"direct_install $installDir $srcBoot"
.
sh
().
isSuccess
)
return
false
arrayOf
(
"run_migrations"
,
"copy_sepolicy_rules"
).
sh
()
return
true
}
private
suspend
fun
postOTA
():
Boolean
{
private
suspend
fun
postOTA
():
Boolean
{
val
bootctl
=
SuFile
(
"/data/adb/bootctl"
)
try
{
try
{
withStreams
(
service
.
fetchBootctl
().
byteStream
(),
SuFileOutputStream
(
bootctl
))
{
val
bootctl
=
File
.
createTempFile
(
"bootctl"
,
null
,
context
.
cacheDir
)
it
,
out
->
it
.
copyTo
(
out
)
service
.
fetchBootctl
().
byteStream
().
writeTo
(
bootctl
)
}
"post_ota $bootctl"
.
sh
()
}
catch
(
e
:
IOException
)
{
}
catch
(
e
:
IOException
)
{
console
.
add
(
"! Unable to download bootctl"
)
console
.
add
(
"! Unable to download bootctl"
)
Timber
.
e
(
e
)
Timber
.
e
(
e
)
return
false
return
false
}
}
"post_ota ${bootctl.parent}"
.
sh
()
console
.
add
(
"***************************************"
)
console
.
add
(
"***************************************"
)
console
.
add
(
" Next reboot will boot to second slot!"
)
console
.
add
(
" Next reboot will boot to second slot!"
)
console
.
add
(
"***************************************"
)
console
.
add
(
"***************************************"
)
return
true
return
true
}
}
protected
fun
uninstall
():
Boolean
{
private
fun
setupShell
(
forceNonRoot
:
Boolean
=
false
):
Boolean
{
val
apk
=
if
(
isRunningAsStub
)
{
shell
=
Shell
.
getShell
()
DynAPK
.
current
(
context
).
path
if
(
forceNonRoot
&&
shell
.
isRoot
)
{
}
else
{
shell
=
Shell
.
Builder
.
create
()
context
.
packageCodePath
.
setFlags
(
Shell
.
FLAG_NON_ROOT_SHELL
)
.
setInitializers
(
BusyBoxInit
::
class
.
java
,
LightShellInit
::
class
.
java
)
.
build
()
closeShell
=
true
}
}
return
"run_uninstaller $apk"
.
sh
().
isSuccess
return
true
}
}
private
fun
String
.
sh
()
=
Shell
.
sh
(
this
).
to
(
console
,
logs
).
exec
()
private
fun
String
.
sh
()
=
shell
.
newJob
().
add
(
this
).
to
(
console
,
logs
).
exec
()
private
fun
Array
<
String
>.
sh
()
=
Shell
.
sh
(*
this
).
to
(
console
,
logs
).
exec
()
private
fun
Array
<
String
>.
sh
()
=
shell
.
newJob
().
add
(*
this
).
to
(
console
,
logs
).
exec
()
private
fun
String
.
fsh
()
=
ShellUtils
.
fastCmd
(
this
)
private
fun
String
.
fsh
()
=
ShellUtils
.
fastCmd
(
shell
,
this
)
private
fun
Array
<
String
>.
fsh
()
=
ShellUtils
.
fastCmd
(*
this
)
private
fun
Array
<
String
>.
fsh
()
=
ShellUtils
.
fastCmd
(
shell
,
*
this
)
protected
fun
doPatchFile
(
patchFile
:
Uri
)
=
extractFiles
()
&&
handleFile
(
patchFile
)
protected
fun
doPatchFile
(
patchFile
:
Uri
)
=
setupShell
(
true
)
&&
extractFiles
()
&&
handleFile
(
patchFile
)
protected
fun
direct
()
=
findImage
()
&&
extractFiles
()
&&
patchBoot
()
&&
flashBoot
()
protected
fun
direct
()
=
setupShell
()
&&
findImage
()
&&
extractFiles
()
&&
patchBoot
()
&&
flashBoot
()
protected
suspend
fun
secondSlot
()
=
protected
suspend
fun
secondSlot
()
=
findSecondaryImage
()
&&
extractFiles
()
&&
patchBoot
()
&&
flashBoot
()
&&
postOTA
()
setupShell
()
&&
findSecondary
()
&&
extractFiles
()
&&
patchBoot
()
&&
flashBoot
()
&&
postOTA
()
protected
fun
fixEnv
()
=
extractFiles
()
&&
"fix_env $installDir"
.
sh
().
isSuccess
protected
fun
fixEnv
()
=
setupShell
()
&&
extractFiles
()
&&
"fix_env $installDir"
.
sh
().
isSuccess
protected
fun
uninstall
()
=
setupShell
()
&&
"run_uninstaller ${AssetHack.apk}"
.
sh
().
isSuccess
@WorkerThread
@WorkerThread
protected
abstract
suspend
fun
operations
():
Boolean
protected
abstract
suspend
fun
operations
():
Boolean
open
suspend
fun
exec
()
=
withContext
(
Dispatchers
.
IO
)
{
operations
()
}
open
suspend
fun
exec
()
=
withContext
(
Dispatchers
.
IO
)
{
val
result
=
operations
()
if
(
closeShell
)
shell
.
close
()
result
}
}
}
abstract
class
MagiskInstaller
(
abstract
class
MagiskInstaller
(
...
...
app/src/main/java/com/topjohnwu/magisk/core/utils/
Root
Init.kt
→
app/src/main/java/com/topjohnwu/magisk/core/utils/
Shell
Init.kt
View file @
bec5edca
...
@@ -14,20 +14,19 @@ import com.topjohnwu.superuser.ShellUtils
...
@@ -14,20 +14,19 @@ import com.topjohnwu.superuser.ShellUtils
import
java.io.File
import
java.io.File
import
java.util.jar.JarFile
import
java.util.jar.JarFile
class
RootInit
:
Shell
.
Initializer
()
{
abstract
class
BaseShellInit
:
Shell
.
Initializer
()
{
final
override
fun
onInit
(
context
:
Context
,
shell
:
Shell
):
Boolean
{
override
fun
onInit
(
context
:
Context
,
shell
:
Shell
):
Boolean
{
return
init
(
context
.
wrap
(),
shell
)
return
init
(
context
.
wrap
(),
shell
)
}
}
private
fun
init
(
context
:
Context
,
shell
:
Shell
):
Boolean
{
abstract
fun
init
(
context
:
Context
,
shell
:
Shell
):
Boolean
}
fun
fastCmd
(
cmd
:
String
)
=
ShellUtils
.
fastCmd
(
shell
,
cmd
)
fun
getVar
(
name
:
String
)
=
fastCmd
(
"echo \$$name"
)
fun
getBool
(
name
:
String
)
=
getVar
(
name
).
toBoolean
()
class
BusyBoxInit
:
BaseShellInit
()
{
override
fun
init
(
context
:
Context
,
shell
:
Shell
):
Boolean
{
shell
.
newJob
().
apply
{
shell
.
newJob
().
apply
{
add
(
"export SDK_INT=${Build.VERSION.SDK_INT}"
)
add
(
"export ASH_STANDALONE=1"
)
add
(
"export ASH_STANDALONE=1"
)
val
localBB
:
File
val
localBB
:
File
...
@@ -41,27 +40,58 @@ class RootInit : Shell.Initializer() {
...
@@ -41,27 +40,58 @@ class RootInit : Shell.Initializer() {
localBB
=
File
(
Const
.
NATIVE_LIB_DIR
,
"libbusybox.so"
)
localBB
=
File
(
Const
.
NATIVE_LIB_DIR
,
"libbusybox.so"
)
}
}
if
(!
shell
.
isRoot
)
{
if
(
shell
.
isRoot
)
{
// Directly execute the file
add
(
"export MAGISKTMP=\$(magisk --path)/.magisk"
)
add
(
"exec $localBB sh"
)
// Test if we can properly execute stuff in /data
}
else
{
Info
.
noDataExec
=
!
shell
.
newJob
().
add
(
"$localBB true"
).
exec
().
isSuccess
// Copy it out of /data to workaround Samsung BS
}
if
(
Info
.
noDataExec
)
{
// Copy it out of /data to workaround Samsung bullshit
add
(
add
(
"export MAGISKTMP=\$(magisk --path)/.magisk"
,
"if [ -x \$MAGISKTMP/busybox/busybox ]; then"
,
"if [ -x \$MAGISKTMP/busybox/busybox ]; then"
,
" cp -af $localBB \$MAGISKTMP/busybox/busybox"
,
" cp -af $localBB \$MAGISKTMP/busybox/busybox"
,
" exec \$MAGISKTMP/busybox/busybox sh"
,
" exec \$MAGISKTMP/busybox/busybox sh"
,
"else"
,
"else"
,
" exec $localBB sh"
,
" cp -af $localBB /dev/.busybox"
,
" exec /dev/.busybox sh"
,
"fi"
"fi"
)
)
}
else
{
// Directly execute the file
add
(
"exec $localBB sh"
)
}
}
}.
exec
()
return
true
}
}
class
LightShellInit
:
BaseShellInit
()
{
override
fun
init
(
context
:
Context
,
shell
:
Shell
):
Boolean
{
shell
.
newJob
().
apply
{
add
(
"export SDK_INT=${Build.VERSION.SDK_INT}"
)
add
(
context
.
rawResource
(
R
.
raw
.
manager
))
}.
exec
()
return
true
}
}
class
AppShellInit
:
BaseShellInit
()
{
override
fun
init
(
context
:
Context
,
shell
:
Shell
):
Boolean
{
fun
fastCmd
(
cmd
:
String
)
=
ShellUtils
.
fastCmd
(
shell
,
cmd
)
fun
getVar
(
name
:
String
)
=
fastCmd
(
"echo \$$name"
)
fun
getBool
(
name
:
String
)
=
getVar
(
name
).
toBoolean
()
shell
.
newJob
().
apply
{
add
(
"export SDK_INT=${Build.VERSION.SDK_INT}"
)
add
(
context
.
rawResource
(
R
.
raw
.
manager
))
add
(
context
.
rawResource
(
R
.
raw
.
manager
))
if
(
shell
.
isRoot
)
{
if
(
shell
.
isRoot
)
{
add
(
context
.
assets
.
open
(
"util_functions.sh"
))
add
(
context
.
assets
.
open
(
"util_functions.sh"
))
}
}
add
(
"
mm
_init"
)
add
(
"
app
_init"
)
}.
exec
()
}.
exec
()
Const
.
MAGISKTMP
=
getVar
(
"MAGISKTMP"
)
Const
.
MAGISKTMP
=
getVar
(
"MAGISKTMP"
)
...
@@ -69,7 +99,6 @@ class RootInit : Shell.Initializer() {
...
@@ -69,7 +99,6 @@ class RootInit : Shell.Initializer() {
Info
.
ramdisk
=
getBool
(
"RAMDISKEXIST"
)
Info
.
ramdisk
=
getBool
(
"RAMDISKEXIST"
)
Info
.
isAB
=
getBool
(
"ISAB"
)
Info
.
isAB
=
getBool
(
"ISAB"
)
Info
.
crypto
=
getVar
(
"CRYPTOTYPE"
)
Info
.
crypto
=
getVar
(
"CRYPTOTYPE"
)
Info
.
isPixel
=
fastCmd
(
"getprop ro.product.brand"
)
==
"google"
// Default presets
// Default presets
Config
.
recovery
=
getBool
(
"RECOVERYMODE"
)
Config
.
recovery
=
getBool
(
"RECOVERYMODE"
)
...
...
app/src/main/res/raw/manager.sh
View file @
bec5edca
...
@@ -36,7 +36,7 @@ fix_env() {
...
@@ -36,7 +36,7 @@ fix_env() {
rm
-rf
$MAGISKBIN
/
*
rm
-rf
$MAGISKBIN
/
*
mkdir
-p
$MAGISKBIN
2>/dev/null
mkdir
-p
$MAGISKBIN
2>/dev/null
chmod
700
$NVBASE
chmod
700
$NVBASE
cp
-af
$1
/.
$MAGISKBIN
cp
_readlink
$1
$MAGISKBIN
rm
-rf
$1
rm
-rf
$1
chown
-R
0:0
$MAGISKBIN
chown
-R
0:0
$MAGISKBIN
}
}
...
@@ -57,6 +57,8 @@ direct_install() {
...
@@ -57,6 +57,8 @@ direct_install() {
rm
-f
$1
/new-boot.img
rm
-f
$1
/new-boot.img
fix_env
$1
fix_env
$1
run_migrations
copy_sepolicy_rules
return
0
return
0
}
}
...
@@ -87,15 +89,17 @@ restore_imgs() {
...
@@ -87,15 +89,17 @@ restore_imgs() {
}
}
post_ota
()
{
post_ota
()
{
cd
$1
cd
/data/adb
cp
-f
$1
bootctl
rm
-f
$1
chmod
755 bootctl
chmod
755 bootctl
./bootctl hal-info
||
return
./bootctl hal-info
||
return
[
$(
./bootctl get-current-slot
)
-eq
0
]
&&
SLOT_NUM
=
1
||
SLOT_NUM
=
0
[
$(
./bootctl get-current-slot
)
-eq
0
]
&&
SLOT_NUM
=
1
||
SLOT_NUM
=
0
./bootctl set-active-boot-slot
$SLOT_NUM
./bootctl set-active-boot-slot
$SLOT_NUM
cat
<<
EOF
> post-fs-data.d/post_ota.sh
cat
<<
EOF
> post-fs-data.d/post_ota.sh
${
1
}
/bootctl mark-boot-successful
/data/adb
/bootctl mark-boot-successful
rm -f
${
1
}
/bootctl
rm -f
/data/adb
/bootctl
rm -f
${
1
}
/post-fs-data.d/post_ota.sh
rm -f
/data/adb
/post-fs-data.d/post_ota.sh
EOF
EOF
chmod
755 post-fs-data.d/post_ota.sh
chmod
755 post-fs-data.d/post_ota.sh
cd
/
cd
/
...
@@ -196,8 +200,7 @@ grep_prop() { return; }
...
@@ -196,8 +200,7 @@ grep_prop() { return; }
# Initialize
# Initialize
#############
#############
mm_init
()
{
app_init
()
{
export
BOOTMODE
=
true
mount_partitions
mount_partitions
get_flags
get_flags
run_migrations
run_migrations
...
@@ -207,3 +210,5 @@ mm_init() {
...
@@ -207,3 +210,5 @@ mm_init() {
# Make sure RECOVERYMODE has value
# Make sure RECOVERYMODE has value
[
-z
$RECOVERYMODE
]
&&
RECOVERYMODE
=
false
[
-z
$RECOVERYMODE
]
&&
RECOVERYMODE
=
false
}
}
export
BOOTMODE
=
true
gradle.properties
View file @
bec5edca
...
@@ -28,6 +28,6 @@ kapt.incremental.apt=true
...
@@ -28,6 +28,6 @@ kapt.incremental.apt=true
# Magisk
# Magisk
magisk.stubVersion
=
17
magisk.stubVersion
=
17
magisk.versionCode
=
2140
5
magisk.versionCode
=
2140
6
magisk.ndkVersion
=
21d
magisk.ndkVersion
=
21d
magisk.fullNdkVersion
=
21.3.6528147
magisk.fullNdkVersion
=
21.3.6528147
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment