Git Product home page Git Product logo

Comments (2)

mpartel avatar mpartel commented on July 16, 2024

Sorry for the late response. Crazy month.
bindfs doesn't currently know anything about selinux. Also, I don't currently know much about selinux, and I'm unfortunately way too busy in the foreseeable future to learn :(

The FUSE changelog says "SELinux support" was added in FUSE 2.9.7, and this commit seems to add some relevant options. Hope this helps.

from bindfs.

agnostic-apollo avatar agnostic-apollo commented on July 16, 2024

I was adding code in termux-app to detect if legacy app data directory path /data/data/com.termux is actually accessible for multi user support and was wondering whether someone would be using bindfs instead of bind mounts, and viola, someone already is! ;)

On Android version <= 10, the /data/user/0 is a symlink to /data/data directory and on Android version >= 11, the /data/data directory is bind mounted at /data/user/0. But bind mount does not exist on secondary users by default, like user 10. So if someone tried to bindfs mount /data/user/10/com.termux on /data/data/com.termux in secondary user, it would fail the check for whether both paths are for the same file, i.e device (st_dev) and inode (st_ino) are same for both paths. Currently, by default, such a case would assume non-accessible, since it would be complex to find if two directories are for the same directory with a fuse mount, since would requiring mount points parsing or creation of random file and checking existence, which may have synchronization delay issues. If using bind mount or symlink, the st_dev and st_ino are same. Also would be same if mounting an image on both paths, mounts are automatically translated with bind and bindfs mount done on single path below. I have only tested on Android 13 avd and not with symlink era.

To answer the OP's query, you can pass -o context=<context> option to bindfs to pass contexts, but its currently broken and for termux usage I would recommend using bind mounts. Persistence of context to actual files would be an issue too with such options and so bind mount should be used instead.

# Install packages
apt update
apt install root-repo
apt install bindfs mount-utils

# Start root shell in global mount namespace
# https://github.com/agnostic-apollo/sudo
sudo --su-run-options=-mm su

# Create 300mb loop image
dd if=/dev/zero of=/data/termux.img bs=1M count=0 seek=300

# Format to ext4
mkfs.ext4 /data/termux.img



# Create mount directory
# Do not try to mount on subdirectory of /data like /data/termux, since
# will result in avc denials to search `/`
# Need to assign `system_data_file` type on parent directory
mkdir -p /data/mount/termux


# Set security context same as /data/data for parent directory of mount directory
# chcon for some reason is only working from root adb shell and not in
# termux even with `setenforce 0`
chcon u:object_r:system_data_file:s0:c512,c768 /data/mount

# Set ownership
chown system:system /data/mount



# Mount termux.img as a loop device
# If using `/system/bin/mount` or its `mount` wrapper provided by termux
# by default with `termux-tools` package, it commadn may fail with
# `losetup: invalid option -- s` (not in root adb shell).
# Install `mount-utils` package to replace wrapper with `coreutils` `mount` binary.
mount -o loop /data/termux.img /data/mount/termux


# Set security context same as /data/data for parent directory of mountpoint/app data directory
# The -h option must be passed, otherwise will result in symlink files to be set to
# `u:object_r:unlabeled:s0` and result in avc denials for lnk_file
# The `c159` is for the user assigned to termux app and must be replaced
# Check `$SE_` env variables or use `/system/bin/ls -ldZ`
# on existing files to get context. The termux provided `ls` will print `?` for security context.
chcon -Rh u:object_r:app_data_file:s0:c159,c256,c512,c768 /data/mount/termux

# Set ownership
# The `10159` is for the user assigned to termux app and must be replaced
# Use `id -u` in termux shell or `$TERMUX_APP__UID` env variable
chown -R 10159:10159 /data/mount/termux

# Set `rwx------` permissions to remove group and others permission
# If different permissions already exist on subdirectories, use
# `find -exec` with `-type` option to fix them. Not required for
# functioning, but better for security while selinux is disabled
chmod 700 /data/mount/termux
  • Preferably bind mount termux image
# Bind mount loop device mountpoint to app data directory
mount -o bind /data/mount/termux /data/data/com.termux


# Check context
ls -ldZ /data/data/com.termux/files
#drwx------ 5 u0_a159 u0_a159 u:object_r:app_data_file:s0:c159,c256,c512,c768  1024 /data/data/com.termux/files

ls -ldZ /data/data/com.termux/files/usr/bin/sh
#lrwxrwxrwx 1 u0_a159 u0_a159 u:object_r:app_data_file:s0:c159,c256,c512,c768  4 /data/data/com.termux/files/usr/bin/sh -> dash

ls -ldZ /data/data/com.termux/files/usr/bin/dash
#-rwx------ 1 u0_a159 u0_a159 u:object_r:app_data_file:s0:c159,c256,c512,c768  106112 /data/data/com.termux/files/usr/bin/dash


# Check mounts
cat /proc/self/mountinfo | grep termux
#4919 92 7:256 / /data/mount/termux rw,relatime shared:43 - ext4 /dev/block/loop32 rw,seclabel
#4918 92 7:256 / /data/data/com.termux rw,relatime shared:43 - ext4 /dev/block/loop32 rw,seclabel
#4923 99 7:256 / /data_mirror/data_ce/null/0/com.termux rw,relatime shared:43 - ext4 /dev/block/loop32 rw,seclabel
#4920 94 7:256 / /data/user/0/com.termux rw,relatime shared:43 - ext4 /dev/block/loop32 rw,seclabel
  • bindfs mount termux image, will have performance degradation due to fuse
# Patch sepolicy temporarily to prevent policy violation and use `deny` again afterwards
# `avc: denied { associate } for scontext=u:object_r:app_data_file:s0:c159 tcontext=u:object_r:app_data_file:s0:c159 tclass=filesystem permissive=0`
# Or use `setenforce 0` temporarily
supolicy --live "allow app_data_file app_data_file filesystem associate"


# Bindfs mount loop device mountpoint to app data directory
# This fails with `fuse: unknown option `c256'` since `bindfs` `1.17.1` uses comma to separate different fuse `-o` options.
bindfs -o nonempty -o 'context=u:object_r:app_data_file:s0:c159,c256,c512,c768' /data/mount/termux /data/data/com.termux


# Mount with the categories removed from `context` since termux app
# process with security context `u:r:untrusted_app_27:s0:c159,c256,c512,c768`
# should still be able to access files without any categories.
# However, even though mount works, the shell doesn't
# avc: denied { read } for name="sh" dev="fuse" ino=16350 scontext=u:r:untrusted_app_27:s0:c159,c256,c512,c768 tcontext=u:object_r:app_data_file:s0 tclass=lnk_file permissive=0 app=com.termux
bindfs -o nonempty -o 'context=u:object_r:app_data_file:s0' /data/mount/termux /data/data/com.termux


# Check context
ls -ldZ /data/data/com.termux/files
#drwxrwx--x 5 u0_a159 u0_a159 u:object_r:app_data_file:s0  1024 /data/data/com.termux/files

ls -ldZ /data/data/com.termux/files/usr/bin/sh
#lrwxrwxrwx 1 u0_a159 u0_a159 u:object_r:app_data_file:s0  4 /data/data/com.termux/files/usr/bin/sh -> dash

ls -ldZ /data/data/com.termux/files/usr/bin/dash
#-rwx------ 1 u0_a159 u0_a159 u:object_r:app_data_file:s0  106112 /data/data/com.termux/files/usr/bin/dash


# Check mounts
cat /proc/self/mountinfo | grep termux
#4919 92 7:256 / /data/mount/termux rw,relatime shared:43 - ext4 /dev/block/loop32 rw,seclabel
#87 92 0:114 / /data/data/com.termux rw,nosuid,nodev,relatime shared:44 - fuse /data/mount/termux rw,context=u:object_r:app_data_file:s0,user_id=0,group_id=0,default_permissions,allow_other
#4920 99 0:114 / /data_mirror/data_ce/null/0/com.termux rw,nosuid,nodev,relatime shared:44 - fuse /data/mount/termux rw,context=u:object_r:app_data_file:s0,user_id=0,group_id=0,default_permissions,allow_other
#4918 94 0:114 / /data/user/0/com.termux rw,nosuid,nodev,relatime shared:44 - fuse /data/mount/termux rw,context=u:object_r:app_data_file:s0,user_id=0,group_id=0,default_permissions,allow_other

I tried patching the sepolicy with supolicy --live "allow untrusted_app_27 app_data_file lnk_file read" and also for open, getattr, setattr, link, unlink and rename, but didn't work. Disabling selinux policy with setenforce 0 does work. I am not sure why this is happening. Maybe selinux is getting confused for a lnk_file without the categories or maybe fuse filesystem itself is broken. Mounting with fscontext or rootcontext option does not work either. Mounting with defcontext fails with fuse: mount failed: Invalid argument.

The c159,c256,c512,c768 categories are part of Multi-Category Security (MCS) and required to Isolate the app data from access by another app and Isolate the app data from one physical user to another. The c512 is for user 0 (primary user), it gets changed to c522 for user 10 (secondary user).

https://source.android.com/docs/security/features/selinux/concepts#security_contexts

https://cs.android.com/android/platform/superproject/+/android-13.0.0_r18:cts/tests/tests/selinux/selinuxTargetSdk28/src/android/security/SELinuxTargetSdkTest.java;l=34;bpv=0

https://github.com/SELinuxProject/selinux-notebook/blob/main/src/mls_mcs.md#multi-level-and-multi-category-security

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/using_selinux/using-multi-level-security-mls_using-selinux

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/using_selinux/assembly_using-multi-category-security-mcs-for-data-confidentiality_using-selinux

https://selinuxproject.org/page/NB_SEforAndroid_2#Computing_a_Context

https://github.com/termux/termux-app/blob/v0.118.0/termux-shared/src/main/java/com/termux/shared/file/TermuxFileUtils.java#L200

@mpartel The bindfs -o option will need to be fixed to allow passing commas in context/fscontext/defcontext/rootcontext args, but likely not easily possible so dedicated options would need to be provided instead. Don't think you will need to do anything else, like learning selinux ;) The lnk_file issue is likely not related to bindfs.

from bindfs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.