Skip to content

Commit

Permalink
Merge pull request #48 from bobrofon/magisk-27-support
Browse files Browse the repository at this point in the history
Magisk 27 support
  • Loading branch information
bobrofon authored Feb 20, 2024
2 parents 1bcb854 + b90e3a9 commit d9c03b1
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.drawerlayout.widget.DrawerLayout
import androidx.lifecycle.ViewModelProvider
import com.topjohnwu.superuser.BusyBoxInstaller
import com.topjohnwu.superuser.Shell
import ru.nsu.bobrofon.easysshfs.log.LogFragment
import ru.nsu.bobrofon.easysshfs.mountpointlist.MountPointsList
Expand Down Expand Up @@ -188,16 +187,11 @@ class EasySSHFSActivity : AppCompatActivity(), NavigationDrawerFragment.Navigati
}

fun initNewShell(): Shell {
return Shell.getShell()
return ShellBuilder.sharedShell()
}

init {
Shell.enableVerboseLogging = BuildConfig.DEBUG
Shell.setDefaultBuilder(
Shell.Builder.create()
.setFlags(Shell.FLAG_MOUNT_MASTER)
.setInitializers(BusyBoxInstaller::class::java.get())
)
}
}

Expand Down
87 changes: 87 additions & 0 deletions app/src/main/java/ru/nsu/bobrofon/easysshfs/ShellBuilder.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package ru.nsu.bobrofon.easysshfs

import android.util.Log
import com.topjohnwu.superuser.BusyBoxInstaller
import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.Shell.Builder
import ru.nsu.bobrofon.easysshfs.log.AppLog
import java.lang.ref.WeakReference

object ShellBuilder {
private const val TAG = "ShellBuilder"

private var sharedShell = WeakReference<Shell?>(null)

@Synchronized
fun sharedShell(): Shell {
val oldShell = sharedShell.get()
if (oldShell == null) {
Log.i(TAG, "create new shared shell")
val newShell = build()
sharedShell = WeakReference(newShell)
return newShell
}
return oldShell
}

private fun build(): Shell {
val builder = Builder.create()
.setInitializers(BusyBoxInstaller::class::java.get())

return if (isMagiskV27x()) {
// TODO: remove logging after the following release (or maybe a few releases)
AppLog.instance().addMessage("Magisk SU v27+ detected")
// '--master-mount' actually spawns shell in an isolated mount namespace
// try to run shell in an init process namespace instead
// TODO: use Zygote namespace instead
builder.build("su", "-t", "1")
} else {
// assume that 'su' implementation supports '--master-mount' option
// (SuperSu or Magisk until v27.0)
builder.setFlags(Shell.FLAG_MOUNT_MASTER)
builder.build()
}
}

private fun isMagiskV27x(): Boolean {
val sh = Builder.create()
.setInitializers(BusyBoxInstaller::class::java.get())
.setFlags(Shell.FLAG_NON_ROOT_SHELL)
.build()

// The result should be something like this:
// $ su -v 2>/dev/null
// 27.0:MAGISKSU
// $ echo $?
// 0
val displayVersionCmd = "su -v"
val verResult = sh.newJob().add(displayVersionCmd).to(arrayListOf()).exec()
if (!verResult.isSuccess) {
Log.d(TAG, "failed to exec '$displayVersionCmd' (exit with ${verResult.code})")
return false
}
if (verResult.out.isEmpty()) {
Log.d(TAG, "'$displayVersionCmd' output is empty")
return false
}

// 27.0:MAGISKSU
val match = Regex("(\\d+)\\.?.*:MAGISKSU").matchEntire(verResult.out[0])
if (match == null) {
Log.d(TAG, "Magisk SU version signature is not found in ${verResult.out}")
return false
}
Log.d(TAG, "detected Magisk SU version signature in ${verResult.out}")
val majorVerString = match.groupValues[1] // 0 is the whole match
val majorVer = try {
majorVerString.toInt()
} catch (e: NumberFormatException) {
AppLog.instance().addMessage("failed to parse Magisk SU version '$majorVerString'")
Log.w(TAG, "failed to parse '$majorVerString'", e)
return false
}

Log.d(TAG, "detected Magisk SU version $majorVer")
return majorVer >= 27
}
}

0 comments on commit d9c03b1

Please sign in to comment.