1

A lot of Android devices out there use sdcardfs to implement external storage. The actual storage (in the case where primary external storage is actually internal) is on the data partition in /data/media/0, which is then mounted as sdcardfs to (on my device) a directory under /mnt/runtime.

I've not been able to find the basic documentation on what sdcardfs does exactly. There are higher level descriptions in the Android docs, but I would like to know for example what mount options sdcardfs supports and what they do exactly. The kind of info you would find in a unix man page.

The android code is open source, so I have been able to find the source code for sdcardfs, but that too doesn't seem to include an overview of what the filesystem does. There is a list of mount options it supports, which are:

  • fsuid=%u
  • fsgid=%u
  • gid=%u
  • debug
  • mask=%u
  • userid=%d
  • multiuser
  • derive_gid
  • default_normal
  • reserved_mb=%u

But there is no explanation for them. For some of them I can guess what they probably do, but not all of them. And also, the higher level Android storage documentation says sdcardfs also does case insensitivity mapping and additional tracking, which do not appear to correspond to any mount options.

So, is there any man page-level documentation out there? Or can someone describe what exactly the mount options do and what other transformations sdcardfs applies to its underlying filesystem?

6
  • 2
    sdcardfs is a stackable filesystem (like FUSE-based filesystems), which Android has used to emulate a permission-less filesystem (like FAT). But unlike FUSE, sdcardfs has an entirely in-kernel driver i.e. no userspace daemon is required. Anyway, Android has dumped sdcardfs, coming back to FUSE again. // Please state what you want to achieve to get better help. Commented May 14 at 20:12
  • If it exists, I'd like to find the man page for sdcardfs to better understand what it does.
    – JanKanis
    Commented May 15 at 9:23
  • 2
    Details of sdcardfs deprecation. Commented May 15 at 11:22
  • 4
    @JanKanis no it doesn't exist. It was removed from Android kernel almost 4 years back. But even if it exists, it's meant to be configured by OEMs, not by end users. So if we don't find a public documentation for it, it makes sense (as a wide guess, more than 90% Android's internal APIs are undocumented for end users). But the source code is available. And anyone with a basic knowledge of filesystems and coding can understand it. So if you let us know what you want to do with it, community may help you. Commented May 15 at 12:46
  • What I want to do is encrypt my removable sdcard, but without making it adoptable storage and in such a way I can also access it from my computer or other devices. There are answers to that effect around, including from you, but they don't work on my device, so I'm trying to figure it out myself. For that I wanted to better understand sdcardfs, hence this question. I have so far figured out enough for my needs, which I've posted here. But anyone is encouraged to add to it.
    – JanKanis
    Commented yesterday

1 Answer 1

1

Some things I've found out so far:

SDCardFS is not written to be configurable like a general purpose file system, it only has options which are needed by Android.

Meaning of some of the options:

  • fsuid, fsgid: the uid/gid with which sdcardfs writes files to the underlying storage.
  • mask: this mask subtracts permission bits from files as exposed on sdcardfs, see below for details.
  • derive_gid: apparently has something to do with adjusting the uid/gid on the lower filesystem.
  • default_normal: "The default_normal option causes mounts with the gid set to AID_SDCARD_RW to have user specific gids, as in the normal case." This option appears to disable an optimization that improves speed at the cost of security, where a user-specific gid is not calculated if the requesting gid == AID_SDCARD_RW. On new enough Androids, that gid is only given to certain trusted processes, which makes the optimization valid for those cases.

SDCardFS also has some non-configurable functionality:

As mentioned in the question, SDCardFS implements case-preserving case-insensitivity. If you try to access a file that doesn't exist on the lower fs, sdcardfs will attempt to find and return a file with a name that has a different capitalization, if it exists.

Sdcardfs will not follow cross-device mount points in its lower filesystem. If it encounters a mount point to a different file system, it will return an "Invalid cross-device link" error. You can bind-mount a directory from the same filesystem to somewhere under sdcardfs' target, but only if you haven't yet accessed that path through sdcardfs. If you have, sdcardfs will have cached the folder and ignore the bind-mount.

The root directory of an sdcardfs is always non-readable and -writable for group and other, so a normal user cannot access the root directory.

Sdcardfs doesn't seem to care about access restrictions on the lower filesystem. The owner and group of files on the lower filesystem does not seem to matter, and neither does the SELinux context.

Permission bits are copied from the lower file to the sdcardfs file, with the following changes:

  • The bits specified in mask are unset.
  • other never gets w
  • group gets a copy of the owner's bits, group's bits are ignored (I don't know if e.g. derive_gid has any influence on this.)
  • The root directory itself, and files (but not directories) directly under it, always get rw?--?--?, where ? is a copy of the owners execute bit.

This means that you cannot mount an sdcardfs somewhere in the middle of a file tree you want user accessible (as the root of the sdcardfs is forbidden for regular users), and you also cannot mount another filesystem under an sdcardfs. But you can still bind-mount a subdirectory from one sdcardfs (or other fs) on top of another sdcardfs, which can be useful when you want put a custom mount within the /sdcard tree as explained here.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .