Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ cmake_minimum_required(VERSION 3.10.2)
# The project generates following files:
# * lib/${ANDROID_ABI}/libssh.so
# * lib/${ANDROID_ABI}/libsshfs.so
# * lib/${ANDROID_ABI}/libnsenter.so
# * lib/${ANDROID_ABI}/libstub.so
project(assets LANGUAGES NONE)

Expand All @@ -19,7 +20,7 @@ add_subdirectory(../sshfs-static "${SSHFS_BINARY_DIR}")
# TODO(bobrofon): report issue
add_subdirectory(src/main/cpp)

set(ASSETS_EXECUTABLES ssh sshfs)
set(ASSETS_EXECUTABLES ssh sshfs nsenter)

foreach (exe IN LISTS ASSETS_EXECUTABLES)
set(src_path "${SSHFS_BINARY_DIR}/${exe}-static-${ANDROID_ABI}")
Expand Down
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ android {

externalNativeBuild {
cmake {
targets "ssh", "sshfs"
targets "ssh", "sshfs", "nsenter"
}
}
}
Expand Down
75 changes: 24 additions & 51 deletions app/src/main/java/ru/nsu/bobrofon/easysshfs/ShellBuilder.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// SPDX-License-Identifier: MIT
package ru.nsu.bobrofon.easysshfs

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

object ShellBuilder {
Expand All @@ -24,60 +25,32 @@ object ShellBuilder {
return oldShell
}

private fun build(): Shell {
val builder = Builder.create()

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
class NsenterInitiallizer : Shell.Initializer() {
override fun onInit(context: Context, shell: Shell): Boolean {
val nsenter = File(context.filesDir.path, "nsenter")
// 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()
val cmd = "${nsenter.path} -m -t 1"

val result =
shell.newJob().add(cmd).to(mutableListOf<String>(), mutableListOf<String>()).exec()
return if (result.isSuccess) {
Log.i(
TAG,
"'$cmd' succeed: code=${result.code} stdout=${result.out} stderr=${result.err}"
)
super.onInit(context, shell)
} else {
Log.w(
TAG,
"'$cmd' failed: code=${result.code} stdout=${result.out} stderr=${result.err}"
)
false
}
}
}

private fun isMagiskV27x(): Boolean {
val sh = Builder.create().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
private fun build(): Shell {
return Builder.create().setInitializers(NsenterInitiallizer::class.java).build()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class VersionUpdater(
// directly use .so files, it will be not possible.
makeLibrarySymlink("ssh", "ssh", lastVersion != currentVersion)
makeLibrarySymlink("sshfs", "sshfs", lastVersion != currentVersion)
makeLibrarySymlink("nsenter", "nsenter", lastVersion != currentVersion)

if (lastVersion < 9) {
update02to03()
Expand Down
3 changes: 2 additions & 1 deletion sshfs-static/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ cmake_minimum_required(VERSION 3.10.2)
# The project generates following files:
# * ssh-static-${arch}
# * sshfs-static-${arch}
# * nsenter-static-${arch}
project(sshfs-static LANGUAGES NONE)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Buildroot.cmake")
Expand All @@ -13,7 +14,7 @@ set(BUILDROOT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/buildroot")
include("Buildroot")

set(SSHFS_STATIC_SUPPORTED_ARCHS armeabi-v7a arm64-v8a x86 x86_64)
set(SSHFS_STATIC_EXECUTABLES ssh sshfs)
set(SSHFS_STATIC_EXECUTABLES ssh sshfs nsenter)

foreach(arch IN LISTS SSHFS_STATIC_SUPPORTED_ARCHS)
set(buildroot_sshfs buildroot-sshfs-static-${arch})
Expand Down
81 changes: 78 additions & 3 deletions sshfs-static/configs/sshfs-static-arm64-v8a.config
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
# Buildroot 2025.11.11-sshfs Configuration
# Buildroot 2022.02.1 Configuration
#
BR2_HAVE_DOT_CONFIG=y
BR2_HOST_GCC_AT_LEAST_4_9=y
Expand Down Expand Up @@ -222,7 +222,7 @@ BR2_PACKAGE_HAS_TOOLCHAIN_EXTERNAL=y
BR2_PACKAGE_PROVIDES_TOOLCHAIN_EXTERNAL="toolchain-external-custom"
BR2_TOOLCHAIN_EXTERNAL_PREFIX="$(ARCH)-buildroot-linux-musl"
BR2_TOOLCHAIN_EXTERNAL_BOOTLIN_ARCH_SUPPORTS=y
BR2_TOOLCHAIN_EXTERNAL_URL="https://github.com/bobrofon/buildroot/releases/download/2022.04.17-musl-trusty/aarch64-buildroot-linux-musl.tar.xz"
BR2_TOOLCHAIN_EXTERNAL_URL="https://github.com/bobrofon/buildroot/releases/download/2026.04.24-musl-trusty/aarch64-buildroot-linux-musl.tar.xz"
BR2_TOOLCHAIN_EXTERNAL_REL_BIN_PATH="bin"
BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="$(ARCH)-buildroot-linux-musl"
# BR2_TOOLCHAIN_EXTERNAL_GCC_11 is not set
Expand Down Expand Up @@ -4342,7 +4342,82 @@ BR2_PACKAGE_SYSTEMD_BOOTCHART_ARCH_SUPPORTS=y
#
# unscd needs a glibc toolchain
#
# BR2_PACKAGE_UTIL_LINUX is not set
BR2_PACKAGE_UTIL_LINUX=y
# BR2_PACKAGE_UTIL_LINUX_LIBBLKID is not set
# BR2_PACKAGE_UTIL_LINUX_LIBFDISK is not set
# BR2_PACKAGE_UTIL_LINUX_LIBMOUNT is not set
# BR2_PACKAGE_UTIL_LINUX_LIBSMARTCOLS is not set
# BR2_PACKAGE_UTIL_LINUX_LIBUUID is not set
# BR2_PACKAGE_UTIL_LINUX_BINARIES is not set
# BR2_PACKAGE_UTIL_LINUX_AGETTY is not set
# BR2_PACKAGE_UTIL_LINUX_BFS is not set
# BR2_PACKAGE_UTIL_LINUX_CAL is not set

#
# chfn/chsh needs a toolchain w/ wchar, locale, dynamic library
#
# BR2_PACKAGE_UTIL_LINUX_CHMEM is not set
# BR2_PACKAGE_UTIL_LINUX_CRAMFS is not set
# BR2_PACKAGE_UTIL_LINUX_EJECT is not set
# BR2_PACKAGE_UTIL_LINUX_FALLOCATE is not set
# BR2_PACKAGE_UTIL_LINUX_FDFORMAT is not set
# BR2_PACKAGE_UTIL_LINUX_FSCK is not set
# BR2_PACKAGE_UTIL_LINUX_HARDLINK is not set
# BR2_PACKAGE_UTIL_LINUX_HWCLOCK is not set
# BR2_PACKAGE_UTIL_LINUX_IPCRM is not set
# BR2_PACKAGE_UTIL_LINUX_IPCS is not set
# BR2_PACKAGE_UTIL_LINUX_KILL is not set
# BR2_PACKAGE_UTIL_LINUX_LAST is not set
# BR2_PACKAGE_UTIL_LINUX_LINE is not set
# BR2_PACKAGE_UTIL_LINUX_LOGGER is not set

#
# login needs a uClibc or glibc toolchain w/ wchar, locale, dynamic library
#
# BR2_PACKAGE_UTIL_LINUX_LOSETUP is not set
# BR2_PACKAGE_UTIL_LINUX_LSLOGINS is not set
# BR2_PACKAGE_UTIL_LINUX_LSMEM is not set
# BR2_PACKAGE_UTIL_LINUX_MESG is not set
# BR2_PACKAGE_UTIL_LINUX_MINIX is not set
# BR2_PACKAGE_UTIL_LINUX_MORE is not set
# BR2_PACKAGE_UTIL_LINUX_MOUNT is not set
# BR2_PACKAGE_UTIL_LINUX_MOUNTPOINT is not set
# BR2_PACKAGE_UTIL_LINUX_NEWGRP is not set
# BR2_PACKAGE_UTIL_LINUX_NOLOGIN is not set
BR2_PACKAGE_UTIL_LINUX_NSENTER=y
# BR2_PACKAGE_UTIL_LINUX_PG is not set
# BR2_PACKAGE_UTIL_LINUX_PARTX is not set
# BR2_PACKAGE_UTIL_LINUX_PIVOT_ROOT is not set
# BR2_PACKAGE_UTIL_LINUX_RAW is not set
# BR2_PACKAGE_UTIL_LINUX_RENAME is not set
# BR2_PACKAGE_UTIL_LINUX_RFKILL is not set

#
# runuser needs a uClibc or glibc toolchain w/ wchar, locale, dynamic library
#

#
# scheduling utilities need a toolchain w/ headers >= 3.14
#
# BR2_PACKAGE_UTIL_LINUX_SETPRIV is not set
# BR2_PACKAGE_UTIL_LINUX_SETTERM is not set

#
# su needs a uClibc or glibc toolchain w/ wchar, locale, dynamic library
#
# BR2_PACKAGE_UTIL_LINUX_SULOGIN is not set
# BR2_PACKAGE_UTIL_LINUX_SWITCH_ROOT is not set
# BR2_PACKAGE_UTIL_LINUX_TUNELP is not set
# BR2_PACKAGE_UTIL_LINUX_UL is not set
# BR2_PACKAGE_UTIL_LINUX_UNSHARE is not set
# BR2_PACKAGE_UTIL_LINUX_UTMPDUMP is not set
# BR2_PACKAGE_UTIL_LINUX_UUIDD is not set
# BR2_PACKAGE_UTIL_LINUX_VIPW is not set
# BR2_PACKAGE_UTIL_LINUX_WALL is not set
# BR2_PACKAGE_UTIL_LINUX_WIPEFS is not set
# BR2_PACKAGE_UTIL_LINUX_WDCTL is not set
# BR2_PACKAGE_UTIL_LINUX_WRITE is not set
# BR2_PACKAGE_UTIL_LINUX_ZRAMCTL is not set
# BR2_PACKAGE_WATCHDOG is not set
# BR2_PACKAGE_WATCHDOGD is not set
# BR2_PACKAGE_XDG_DBUS_PROXY is not set
Expand Down
98 changes: 84 additions & 14 deletions sshfs-static/configs/sshfs-static-armeabi-v7a.config
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
# Buildroot 2025.11.11-sshfs Configuration
# Buildroot 2022.02.1 Configuration
#
BR2_HAVE_DOT_CONFIG=y
BR2_HOST_GCC_AT_LEAST_4_9=y
Expand Down Expand Up @@ -258,7 +258,7 @@ BR2_TOOLCHAIN_EXTERNAL_MUSL=y
BR2_PACKAGE_HAS_TOOLCHAIN_EXTERNAL=y
BR2_PACKAGE_PROVIDES_TOOLCHAIN_EXTERNAL="toolchain-external-custom"
BR2_TOOLCHAIN_EXTERNAL_PREFIX="$(ARCH)-buildroot-linux-musleabi"
BR2_TOOLCHAIN_EXTERNAL_URL="https://github.com/bobrofon/buildroot/releases/download/2022.04.17-musl-trusty/arm-buildroot-linux-musleabi.tar.xz"
BR2_TOOLCHAIN_EXTERNAL_URL="https://github.com/bobrofon/buildroot/releases/download/2026.04.24-musl-trusty/arm-buildroot-linux-musleabi.tar.xz"
BR2_TOOLCHAIN_EXTERNAL_REL_BIN_PATH="bin"
BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="$(ARCH)-buildroot-linux-musleabi"
# BR2_TOOLCHAIN_EXTERNAL_GCC_11 is not set
Expand Down Expand Up @@ -333,8 +333,8 @@ BR2_TOOLCHAIN_EXTERNAL_GCC_10=y
# BR2_TOOLCHAIN_EXTERNAL_HEADERS_3_3 is not set
# BR2_TOOLCHAIN_EXTERNAL_HEADERS_3_2 is not set
# BR2_TOOLCHAIN_EXTERNAL_HEADERS_3_1 is not set
# BR2_TOOLCHAIN_EXTERNAL_HEADERS_3_0 is not set
BR2_TOOLCHAIN_EXTERNAL_HEADERS_REALLY_OLD=y
BR2_TOOLCHAIN_EXTERNAL_HEADERS_3_0=y
# BR2_TOOLCHAIN_EXTERNAL_HEADERS_REALLY_OLD is not set

#
# Kernel headers older than 3.13 is not tested by Buildroot. Use at your own risk.
Expand Down Expand Up @@ -376,7 +376,8 @@ BR2_USE_MMU=y
BR2_TARGET_OPTIMIZATION=""
BR2_TARGET_LDFLAGS="-Wl,-z,max-page-size=16384"
# BR2_ECLIPSE_REGISTER is not set
BR2_TOOLCHAIN_HEADERS_AT_LEAST="2.6"
BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_0=y
BR2_TOOLCHAIN_HEADERS_AT_LEAST="3.0"
BR2_TOOLCHAIN_GCC_AT_LEAST_4_3=y
BR2_TOOLCHAIN_GCC_AT_LEAST_4_4=y
BR2_TOOLCHAIN_GCC_AT_LEAST_4_5=y
Expand Down Expand Up @@ -735,10 +736,7 @@ BR2_PACKAGE_LTRACE_ARCH_SUPPORTS=y
#
# BR2_PACKAGE_MEMSTAT is not set
# BR2_PACKAGE_NETPERF is not set

#
# netsniff-ng needs a toolchain w/ threads, headers >= 3.0
#
# BR2_PACKAGE_NETSNIFF_NG is not set

#
# nmon needs a glibc toolchain
Expand Down Expand Up @@ -922,10 +920,7 @@ BR2_PACKAGE_PROVIDES_HOST_GETTEXT="host-gettext-tiny"
# BR2_PACKAGE_GENPART is not set
# BR2_PACKAGE_GENROMFS is not set
# BR2_PACKAGE_IMX_USB_LOADER is not set

#
# mmc-utils needs a toolchain w/ headers >= 3.0
#
# BR2_PACKAGE_MMC_UTILS is not set
# BR2_PACKAGE_MTD is not set
# BR2_PACKAGE_MTOOLS is not set
# BR2_PACKAGE_NFS_UTILS is not set
Expand Down Expand Up @@ -4430,7 +4425,82 @@ BR2_PACKAGE_SYSTEMD_BOOTCHART_ARCH_SUPPORTS=y
#
# unscd needs a glibc toolchain
#
# BR2_PACKAGE_UTIL_LINUX is not set
BR2_PACKAGE_UTIL_LINUX=y
# BR2_PACKAGE_UTIL_LINUX_LIBBLKID is not set
# BR2_PACKAGE_UTIL_LINUX_LIBFDISK is not set
# BR2_PACKAGE_UTIL_LINUX_LIBMOUNT is not set
# BR2_PACKAGE_UTIL_LINUX_LIBSMARTCOLS is not set
# BR2_PACKAGE_UTIL_LINUX_LIBUUID is not set
# BR2_PACKAGE_UTIL_LINUX_BINARIES is not set
# BR2_PACKAGE_UTIL_LINUX_AGETTY is not set
# BR2_PACKAGE_UTIL_LINUX_BFS is not set
# BR2_PACKAGE_UTIL_LINUX_CAL is not set

#
# chfn/chsh needs a toolchain w/ wchar, locale, dynamic library
#
# BR2_PACKAGE_UTIL_LINUX_CHMEM is not set
# BR2_PACKAGE_UTIL_LINUX_CRAMFS is not set
# BR2_PACKAGE_UTIL_LINUX_EJECT is not set
# BR2_PACKAGE_UTIL_LINUX_FALLOCATE is not set
# BR2_PACKAGE_UTIL_LINUX_FDFORMAT is not set
# BR2_PACKAGE_UTIL_LINUX_FSCK is not set
# BR2_PACKAGE_UTIL_LINUX_HARDLINK is not set
# BR2_PACKAGE_UTIL_LINUX_HWCLOCK is not set
# BR2_PACKAGE_UTIL_LINUX_IPCRM is not set
# BR2_PACKAGE_UTIL_LINUX_IPCS is not set
# BR2_PACKAGE_UTIL_LINUX_KILL is not set
# BR2_PACKAGE_UTIL_LINUX_LAST is not set
# BR2_PACKAGE_UTIL_LINUX_LINE is not set
# BR2_PACKAGE_UTIL_LINUX_LOGGER is not set

#
# login needs a uClibc or glibc toolchain w/ wchar, locale, dynamic library
#
# BR2_PACKAGE_UTIL_LINUX_LOSETUP is not set
# BR2_PACKAGE_UTIL_LINUX_LSLOGINS is not set
# BR2_PACKAGE_UTIL_LINUX_LSMEM is not set
# BR2_PACKAGE_UTIL_LINUX_MESG is not set
# BR2_PACKAGE_UTIL_LINUX_MINIX is not set
# BR2_PACKAGE_UTIL_LINUX_MORE is not set
# BR2_PACKAGE_UTIL_LINUX_MOUNT is not set
# BR2_PACKAGE_UTIL_LINUX_MOUNTPOINT is not set
# BR2_PACKAGE_UTIL_LINUX_NEWGRP is not set
# BR2_PACKAGE_UTIL_LINUX_NOLOGIN is not set
BR2_PACKAGE_UTIL_LINUX_NSENTER=y
# BR2_PACKAGE_UTIL_LINUX_PG is not set
# BR2_PACKAGE_UTIL_LINUX_PARTX is not set
# BR2_PACKAGE_UTIL_LINUX_PIVOT_ROOT is not set
# BR2_PACKAGE_UTIL_LINUX_RAW is not set
# BR2_PACKAGE_UTIL_LINUX_RENAME is not set
# BR2_PACKAGE_UTIL_LINUX_RFKILL is not set

#
# runuser needs a uClibc or glibc toolchain w/ wchar, locale, dynamic library
#

#
# scheduling utilities need a toolchain w/ headers >= 3.14
#
# BR2_PACKAGE_UTIL_LINUX_SETPRIV is not set
# BR2_PACKAGE_UTIL_LINUX_SETTERM is not set

#
# su needs a uClibc or glibc toolchain w/ wchar, locale, dynamic library
#
# BR2_PACKAGE_UTIL_LINUX_SULOGIN is not set
# BR2_PACKAGE_UTIL_LINUX_SWITCH_ROOT is not set
# BR2_PACKAGE_UTIL_LINUX_TUNELP is not set
# BR2_PACKAGE_UTIL_LINUX_UL is not set
# BR2_PACKAGE_UTIL_LINUX_UNSHARE is not set
# BR2_PACKAGE_UTIL_LINUX_UTMPDUMP is not set
# BR2_PACKAGE_UTIL_LINUX_UUIDD is not set
# BR2_PACKAGE_UTIL_LINUX_VIPW is not set
# BR2_PACKAGE_UTIL_LINUX_WALL is not set
# BR2_PACKAGE_UTIL_LINUX_WIPEFS is not set
# BR2_PACKAGE_UTIL_LINUX_WDCTL is not set
# BR2_PACKAGE_UTIL_LINUX_WRITE is not set
# BR2_PACKAGE_UTIL_LINUX_ZRAMCTL is not set
# BR2_PACKAGE_WATCHDOG is not set
# BR2_PACKAGE_WATCHDOGD is not set
# BR2_PACKAGE_XDG_DBUS_PROXY is not set
Expand Down
Loading
Loading