MSD is an Android app for emulating mass storage devices over USB. It supports emulating both CD-ROM and disk devices.
MSD is installed as a Magisk/KernelSU module so that it can run with system app privileges.
- Supports Android 13 and newer
- Supports emulating multiple mass storage devices at the same time
- Including mixing and matching CD-ROM and disk devices
- Does not interfere with ADB, MTP, or any other normal USB functionality
- The device must use configfs for configuring USB gadgets
- To check, run
ls /config/usb_gadget/g1
as root.
- To check, run
- The device's kernel must be compiled with support for the mass storage USB gadget
- To check, run
zcat /proc/config.gz | grep CONFIG_USB_CONFIGFS_MASS_STORAGE
as root.
- To check, run
- The device must use Android's USB gadget HAL
- To check, run
pgrep -f android.hardware.usb.gadget-service
as root.
- To check, run
- Only local files are supported
- Android's Storage Access Framework allows cloud providers to present a file as a local file using FUSE (specifically, via
StorageManager.openProxyFileDescriptor
). Unfortunately, even for the few cloud providers that support this, these files cannot be used because Android's implementation of this mechanism does not allow files to be reopened. Setting up a mass storage device requires reopening the file because the kernel has no way to accept an already open file descriptor.
- Android's Storage Access Framework allows cloud providers to present a file as a local file using FUSE (specifically, via
-
Download the latest version from the releases page. To verify the digital signature, see the verifying digital signatures section.
-
Install the MSD module in Magisk/KernelSU.
-
Reboot and open MSD.
-
Add one or more CD-ROM/disk images.
-
Apply the settings.
-
That's it!
MSD does not need to run in the background. Once configured, the mass storage devices remain available until they're explicitly disabled or the device is rebooted.
The Android app part of MSD does not use any permissions at all. Also, despite that it is installed as a system app, the SELinux policy is configured so that it is not granted any more privileges than a regular user app.
The daemon part of MSD runs as the system
user and with the CAP_CHOWN
capability allowed. The daemon is responsible for all USB configuration. It accepts 3 requests from the app:
- Query the currently active USB gadget functions
- Set up mass storage devices from a list of file descriptors
- Query the currently active mass storage devices
When setting up mass storage devices, the daemon never opens files on its own. The app opens files itself and then sends the open file descriptor the daemon over a Unix socket. This way, even if a malicious client happened to be able to connect to the daemon, it can't expose files over mass storage devices that it didn't already have access to.
The daemon relies on SELinux for access control. If it detects certain scenarios where SELinux is not configured correctly, it will reject connections from all clients to avoid opening a security hole.
MSD has hidden debug options that can be enabled or disabled by long pressing the version number.
To access the MSD's logs, enable debug mode and press Open log directory
to open the log directory in the system file manager (DocumentsUI). Or alternatively, browse to /sdcard/Android/com.chiller3.msd/files
manually.
crash.log
: Logs for the last crash./data/local/tmp/msd.post-fs-data.log
: Logs forpost-fs-data.sh
boot script./data/local/tmp/msd.service.log
: Logs forservice.sh
boot script.
To monitor the daemon's logs, run adb logcat -v color -s msd-tool
.
When reporting bugs, please include all of the logs as they are extremely helpful for identifying what might be going wrong.
Both the zip file and the APK contained within are digitally signed.
To verify the digital signatures of the downloads, follow the steps here.
First, extract the apk from the zip and then run:
apksigner verify --print-certs system/priv-app/com.chiller3.msd/app-release.apk
Then, check that the SHA-256 digest of the APK signing certificate is:
de6ea74388dcff7a6120c0f192e77a92c486d40bb166c392fdf4101abc125954
Make sure the Rust toolchain is installed. Rust must be installed via rustup because it provides the required Android toolchains:
rustup target add aarch64-linux-android
rustup target add x86_64-linux-android
cargo-android must also be installed.
Then, MSD can be built like most other Android apps using Android Studio or the gradle command line.
To build the APK:
./gradlew assembleDebug
To build the Magisk/KernelSU module zip (which automatically runs the assembleDebug
task if needed):
./gradlew zipDebug
The output file is written to app/build/distributions/debug/
. The APK will be signed with the default autogenerated debug key.
To create a release build with a specific signing key, set up the following environment variables:
export RELEASE_KEYSTORE=/path/to/keystore.jks
export RELEASE_KEY_ALIAS=alias_name
read -r -s RELEASE_KEYSTORE_PASSPHRASE
read -r -s RELEASE_KEY_PASSPHRASE
export RELEASE_KEYSTORE_PASSPHRASE
export RELEASE_KEY_PASSPHRASE
and then build the release zip:
./gradlew zipRelease
Bug fix and translation pull requests are welcome and much appreciated!
If you are interested in implementing a new feature and would like to see it included in MSD, please open an issue to discuss it first. I intend for MSD to be as simple and low-maintenance as possible, so I am not too inclined to add new features, but I could be convinced otherwise.
MSD is licensed under GPLv3. Please see LICENSE
for the full license text.