text:
How to exclude a specific destination IP from VPN?
I want to route a specific IP address from hotspot (wlan0) to Mobile Data (rmnet_data1) interface on Android 11, bypassing VPN.
I use my phone as a hotspot and also with the help of an app called "VPN Hotspot" I share the VPN with my PC. I want to exclude a specific IP address from VPN. I have tried the route option in "OpenVPN for Android" client and it doesn't seem to work properly. I think it might because of "Always On" enabled.
Can I achieve this with ip route command?

Not clear what you are asking. Is your device a WiFi AP? In that case every packet that appears on WiFi interface (wlan0) is already routed to Mobile Data interface (rmnet_data). Here's how you can do it manually: https://android.stackexchange.com/a/217896/218526. Or if it's the opposite case i.e. route everything coming on Mobile Data to WiFi interface, here's the detailed explanation: https://android.stackexchange.com/a/218562/218526

@IrfanLatif I use my phone as a hotspot and also with the help of an app called VPN Hotspot I share the VPN with my PC but I want to exclude a specific IP address from VPN but routing from the OpenVPN client didn't work so I was thinking how I can just route it with ip route add command

Got it. Note that whenever you enable or disable a VPN on Android device, routing table is recreated. There can be a score of rules added to the routing table when VPN is enabled, since it does filtering based on UIDs and Socket Marks. So you need to share the whole routing table (rules and routes) here in order to get a practical suggestion.

@IrfanLatif Just edited the question and added the table but is that the right one?

ip -4 ru | grep -vE 'unreachable[ ]*$|local[ ]*$'; ip -4 r s t all | grep -vE '^unreachable |^local |^broadcast '

@IrfanLatif here is the output of that command https://gist.github.com/poqdavid/a1325693f46e2c4fa399dcb2c2cba972

ip ru add iif wlan0 lookup 9999 pri 9999; ip r add 1.2.3.4 dev rmnet_data1 table 9999. Replace 1.2.3.4 with your required destination IP. Not tested. You might need to change RPDB priority (so that your rule is the first) and table number. Check /data/misc/net/rt_tables for reserved table numbers which you should not use.

Note that this routes only outgoing packets. You need to add another rule in the same way for returned traffic. And also make sure that MASQUERADE (NAT) rules are properly added (using iptables).

@IrfanLatif Ok that command works actually without killing my entire connection I tested this with TeamSpeak and it's actually reporting my IP I personally never used ip or iptables command can you like add this whole thing as an answer with the rule for incoming packets and the iptables MASQUERADE (NAT) I would really appreciate it

Please share your iptables rules: cat /proc/net/ip_tables_names | xargs -I {} iptables -t '{}' -S

@IrfanLatif when i run that it gives me an error saying xargs: unknown option 'i' https://gist.github.com/poqdavid/a1325693f46e2c4fa399dcb2c2cba972#file-xargs-error

Poor toybox. cat /proc/net/ip_tables_names | while read t; do echo $t; iptables -t $t -S; done

@IrfanLatif XD ok here got it https://gist.github.com/poqdavid/a1325693f46e2c4fa399dcb2c2cba972#file-iptables

Note: The commands given below require a rooted device.

Whenever you enable or disable VPN on Android device, routing table is recreated by the Android framework. There can be a score of rules added to the routing table when VPN is enabled, since it does filtering based on UIDs and Socket Marks. So you need to manipulate the routing table depending on the existing rules.
ROUTING POLICY AND TABLES
From the info you provided, I'm quoting the relevant parts:
~# ip -4 rule
...
11000:  from all iif tun0 lookup local_network
...
17900:  from all iif wlan0 lookup tun0
18000:  from all iif wlan0 lookup rmnet_data1
...

~# ip -4 route show table all
...
192.168.18.0/24 dev wlan0 table local_network...
...
default via 21.62.249.109 dev rmnet_data1 table rmnet_data1...
21.62.249.104/29 dev rmnet_data1 table rmnet_data1...
...

~# iptables -t nat -S
...
-A POSTROUTING -j tetherctrl_nat_POSTROUTING
-A tetherctrl_nat_POSTROUTING -o tun0 -j MASQUERADE
-A tetherctrl_nat_POSTROUTING -o rmnet_data1 -j MASQUERADE
...

In simple words what the above rules state:

Everything coming at VPN interface (tun0) is routed to hotspot interface (wlan0) if the destination IP is within hotspot subnet (192.168.18.0/24) i.e. the packets don't belong to the apps running on device (open sockets).
Everything coming at hotspot interface is routed to VPN interface.
The packets which don't qualify to be routed through VPN (mainly the VPNed traffic itself, any excluded apps, or the local packets) are routed to Mobile Data interface (rmnet_data1).
21.62.249.109 is your IP assigned by the carrier and 21.62.249.104/29 is their gateway.
All packets going out through VPN and/or Mobile Data interfaces are MASQUERADEd i.e. their source IP address is changed from local IP to a routable IP address (21.62.249.109 in your case).

So this is the simplified flow we are interested in:
Hotspot -> Routing -> FORWARD -> SNAT -> Internet
Internet -> Conntrack -> Routing -> FORWARD -> Hotspot

SOLUTION
After understanding how it works, lets route it the way we want. Say a host on hotspot network is connecting to 1.2.3.4 through internet. But you don't want to send this specific traffic through VPN on Android device.

Define a rule in RPDB and a routing table to route the traffic coming at hotspot interface to Mobile Data interface, if it's destined for 1.2.3.4:
~# ip rule add iif wlan0 lookup 9000 pri 9999
~# ip route add 1.2.3.4 dev rmnet_data1 table 9000

I used RPDB priority 9999 and table 9000. You might need to change the priority (so that your rule is always on top) and table number. Check /data/misc/net/rt_tables for reserved table numbers which you should not use.

Define another rule to route the packets coming from 1.2.3.4 at Mobile Data interface to hotspot interface (if the destination IP is within hotspot subnet):
~# ip rule add from 1.2.3.4 iif rmnet_data1 lookup local_network pri 9999

Note that I used here an already existing routing table local_network. You can define your own too.

All outgoing packets through Mobile Data interface are already MASQUERADEd as explained above, so we don't need to add another iptables rule. If needed, you can also use SNAT target in place of MASQUERADE.

Make sure that IP forwarding is enabled and allowed in firewall. Usually it's not needed because Wi-Fi hotspot already sets this up for you:
~# echo 1 > /proc/sys/net/ipv4/ip_forward
~# iptables -I FORWARD -o rmnet_data1 -d 1.2.3.4 -j ACCEPT
~# iptables -I FORWARD -i rmnet_data1 -s 1.2.3.4 -j ACCEPT

To delete these rules use ip rule del, ip route del and iptables -D.

NOT WORKING?
If the above rules don't work, or you need to adapt the rules for a different situation, iptables -j LOG is a good friend for troubleshooting.
For reference read any Linux documentation or guides about IP routing and Netfilter. It's not specifically about Android.

RELATED:

When hotspot is enabled, every packet that appears on hotspot (Wi-Fi) interface is being routed to Mobile Data interface. Here's how to do it manually: How to create a wifi hotspot from the terminal?
In the opposite case i.e. when you want to route everything coming on Mobile Data interface to WiFi interface: How to assign Mobile Data's public IP to host connected on hotspot?

Awesome one small thing let's say if I want to add another IP I can just add it to the same table correct? and also I think the VPN Hotspot app does the MASQUERADING if I am not wrong

Yes. // Never used that app but masquerading and forwarding is required for the native hotspot feature of Android to work. Otherwise hosts connected to hotspot won't be able to connect to internet.


text:
How to block access to a website?
Is there any way to block access to a particular website through the stock Android browser?

To filter adult content in web browser apps you can use "Mobile Security" which has parental controls plus backup and antivirus features for mobile.

The simplest way to block access to a website is by adding that domain name to hosts file as mostly DNS resolvers honor that file. But it's not possible to edit /etc/hosts without rooting Android device. Here are a few options you can go with on unrooted device:

Use a VPN app which intercepts DNS traffic and looks up a custom hosts file before making queries to configured upstream DNS server.
Run a DNS server; they can be configured to return a predefined IP address for a specific name. For instance if using dnsmasq, add address=/xyz.com/0.0.0.0 to “dnsmasq.conf”. Or on dnscrypt-proxy add xyz.com 0.0.0.0 to “cloaking-rules.txt”.
Configure phone to use a proxy or VPN and then add the entry 0.0.0.0 xyz.com to hosts file on proxy server or run a local DNS server on VPN server.
If bootloader is unlockable, edit hosts file from custom recovery.

For more details see: How to always resolve a domain name to a fixed IP without rooting?

If you have root, you can mount the systems partition as editable and edit the hosts file and set the site in question to redirect to 127.0.0.1.  This is somewhat complicated voodoo, however, and I wouldn't recommend it if you don't know what I'm talking about already.
However if you don't want to do this manually and have rooted your phone, the app Hosts Editor is a nice little single purpose utility just for this.
If you're up for the voodoo, and have ADB installed:

From the terminal invoke the adb command with remount option otherwise you will get "failed to copy 'hosts' to '/system/etc/hosts': Read-only file system".
adb remount
In the terminal pull the default hosts file from /system/etc/hosts or /etc/hosts which is the symlink of the file not only for backup purpose but also to get the file to modify.
adb pull /system/etc/hosts <path to pull hosts file to>
Modify the file according to your needs.
(eg) 127.0.0.1 www.somewebsite.com
Push the file back to the phone:
adb push <path you pulled hosts file to>/hosts /system/etc/
That's it.  You can check it out from the shell:
adb -e shell
cat /system/etc/hosts

source

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

sort: votes


text:
Why can't I delete a folder in /config/sdcardfs as root (Termux)?
I'm looking to delete a folder that is in /config/sdcardfs. My device is rooted and I'm trying as superuser. I still get the results operation not permitted.
What do I need to do to get the permission to do this.
I have tried to do sudo rm -rf name-of-folder with no success.
I have also tried to do it after running tsu (Termux's version of su). No success.
P.S.
I haven't had any issues deleting in other places even in places I need root permission (for example in the /data folder.

configfs is kernel's virtual filesystem like sysfs. What's inside them aren't actual files but kernel intrrfaces to userspace, to provide some info or make configurations. You can't simply delete them. Instead build the kernel with the said filesystem disabled. // What are you trying to achieve by deleting sdcardfs? It's one of Android's core components. External storage (/sdcard as well as physically external SD cards, USB drives etc.) functionality entirely depends on it. And most probably device will bootloop when vold is unable to emulate filesystems.

I'm trying to delete a folder residing in the /config/sdcardfs folder. There seems to be a folder left there from an app that isn't installed on my device anymore that I want to get rid of.

SHORT ANSWER
You don't need to delete anything in /config. What appear inside the directory aren't actual files. They are cleared and repopulated on device restart.
You can't delete /config/sdcardfs directory. SDCard FileSystem (sdcardfs) is a core OS component. Your device (or at least storage) won't be usable without sdcardfs properly configured.
DETAILS
Android is based on Linux kernel. Kernel is the backbone of OS which handles hardware components and many other core functionalities. The other part of OS: userspace talks to kernel space through different mechanisms like syscalls, sockets and virtual filesystems. procfs, sysfs and configfs are common virtual/pseudo filesystems i.e. they live in RAM. Kernel exports information about processes, hardware devices, and drivers etc. to user space through virtual files in these filesystems.
/proc and /sys are mostly read-only, except a few interfaces to which userspace can write some values in order to make configurations. configfs (which is mounted at /config on Android devices) is relatively a new addition to Linux kernel. It allows userspace to make relatively bigger kernel configurations by creating large number of virtual files in sub-directories under /config.
Android uses configfs at least for two purposes:

External storage permissions management
Setting USB gadget modes

In order to make file sharing among apps possible, Android sets fixed permissions on files in external storage (be it physically internal or external). To achieve this, at start, Android used FUSE for filesystem emulation, then sdcardfs replaced it. For more details see my answer to What is /storage/emulated/0/? and Android's Storage Journey, in particular the concept of synthesized permissions.
So it's the Android OS which creates and deletes virtual files in /config/sdcardfs/ in order to let kernel know which permissions to enforce on which files/directories in external storage (/sdcard as well as physically external SD cards, USB drives etc).
Additionally Android uses sdcardfs to assign three GIDs: AID_MEDIA_AUDIO (1055), AID_MEDIA_VIDEO (1056) and AID_MEDIA_IMAGE (1057) to media files by providing their relevant list of file extensions in /config/sdcardfs/extensions/. It's to quickly categorize files without scanning all of them. See some details in this answer.
So deleting something in /config/sdcardfs (and in kernel's other virtual filesystems as well) doesn't make sense if you don't know what you are doing. That would do no good except breaking storage functionality on your device.

Thanks for the detailed answer, this helped me understand more of what is going on.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
How to grant certain apps root permission through ADB?
I have an Android TV box (4.4.2, armv7), and I can login the device as root by ADB (local network). What I want to do is to give certain apps root permission. How can I do it?

You don't give certain apps root permission, but certain apps ask for root permission by executing su binary. It's the developer of the app who decides if the app would perform some tasks with root privileges or not. In order to let apps request root privileges, you need to root your device using e.g. Magisk, SuperSU etc. (whatever works on your device).
When you get root privileges on adb (e.g. by executing adb root or adb shell su) it runs adbd process on device as root (UID 0) user. So all commands which you run through adb have root privileges. To grant root access to apps you need a special su binary which is not shipped with Android.
The usual su binary (like on any UNIX-like OS) makes a transition to UID 0 by making setuid syscall to kernel. This is not possible on Android due to certain restrictions. The special su binary (the one provided by rooting solutions like Magisk) connects to a background daemon to get a root shell for the requesting app, where the app can execute commands with root privileges. However the app itself is still running with its own UID (assigned at the time of installation).
For more details see:

What special privileges “/system/xbin/su” does have w.r.t. root access?
How Magisk works?
How to manually root a phone?

Thanks for ans, and I found there is a file named su which's location is /system/xbin and I run chmod 777 to this file. Then I install supersu on the box but it remind "su binary occupied". So do I have a solution to solve it?

@punnpkin you need to root your device, using e.g. Magisk or SuperSU. The su binary already provided in Android cannot be used with SuperSU. They provide their own su binaries. That's what I tried to explain in the answer. For more details see linked answers.

OK, I learned it, Actually, I'm just looking for a way to root my device without changing the rom. (Because it has some customized content.)

I don't understand this answer. If you can adb root and you run have root privs, why can't you run the app? That doesn't make sense, you grant root access to anything root runs. Why can't someone with root access run an android app?

@EvanCarroll because Android apps cannot make use of SUID bit. Please read “How Android restricts root access?” in the linked answers.


text:
How can I get as much data as possible off a phone with broken USB?
I have a BV7000pro running Marshmallow (according to the specs - it's off now for a good reason that will become clear soon).  It stopped charging after a period of very poor battery life, so I bought a replacement battery.  It still doesn't charge, doesn't show a charging LED and, despite having previously enabled developer mode, and checked just now, it doesn't show up when I run adb devices from the terminal.  It does turn on, but I only have about 70% of one charge, which is why I'm keeping the battery disconnected for the time being.
Although it's only my spare handset, I have data I'd like to get off before it's completely dead.  I can put in an SD card, and it's on WiFi.  I think it's mainly app data, though there are some photos (most were on an SD card but the stock  camera app sometimes switched to internal storage).
Google's backup appears to only be any use to restore to the same phone, so that's not much use, though it's present in my GDrive. (If I can download this an extract stuff from it I'd be interested to hear, but that's not the focus of the question).  Edit: I was apparently wrong and it could restore to a newer phone - but I don't have one I can overwrite; my newer phone is my main phone
BTW I'm also considering buying a replacement USB board on AliExpress, but I'm not sure if it's just a case of throwing good money after bad given that it's a battered old backup phone. It's no longer waterproof after falling off my bike too many times, which also led to me replacing the screen myself. At least it's easy to work on.
So, with no USB connection and one charge in the battery, how can I extract as much data as possible from my handset?  It's not rooted,and I already have one or two file manager apps on there (at least the free version of file commander).

Google Drive backup should be restorable as long as the device to restore to has the same or a higher Android version. As far as I remember GDrive backup on Android 6 was limited to apps and their app-data that explicitly requested it and it is limited to 5, 15 or 25 MB per app (not sure which value is effective in your case). In any way I would try to start copying all files you can reach via USB to a PC.

@Robert on the more technical comments: I'd expect restoring a backup to a newer phone to overwrite what's on that phone - not an option as the only other phone I have is my main device.  And you suggest copying what I can via USB, but the whole point of the question is that USB is broken.

Sorry, I missed that part because you only mention it in the title. Please do misuse the title for providing important info A title is there for summarizing the questions, it is not the first line of the questions. With a  broken USB you can still use one of the file-explorer or FTP/HTTP server apps that can provide the /sdcard section via FTP or HTTP. So effectively you can get all the files you would have access to via USB. See for example this FTP server app: https://f-droid.org/en/packages/be.ppareit.swiftp_free/

@Robert it wasn't only in the title - the last paragraph starts, and started, "So, with no USB connection and one charge in the battery..."

...but that looks like it might be a good answer - thoguh I don't know if it offers as much as adb backup

For adb backup you require a wireless adb connection which usually requires an USB connection to activate the adb Wfif connection. If you manage to get adb to work over Wifi without USB connection you should backup all apps via adb just to be sure.

@Robert yes, I'm used to running adb over loopback (faked as WiFi) to allow Tasker to control aeroplane mode on my new phone; I'd assumed that adb backup was impossible without USB, but also think that it can grab more than copying files


text:
Opening local HTML project shortcut from tablet desktop with Chrome
Trying to create shortcut to my html project on my tablet desktop. I've use File Manager/File Shortcut etc from Play Store to create the shortcut. My problem is my best option with "complete action using" when tyring to open it is HTML Viewer which doesn't really cut it.
Anyway way to do what I'm doing but open it with Chrome?
running android 4.1.1

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
WhatsApp does not download images during call
During a WhatsApp call, if I receive a media element from a WhatsApp contact (does not necessarily has to be the person whom I am talking with), the loading icon rotates, but the download of the element never starts.
First I thought it is due to my internet connection, but regardless of my speed, it is the same for LTE+ or WLAN connections.
Is that intentional? How can I solve this problem?
EDIT: This happens only on Android phones. On iPhones, this does not seem to be an issue.

I have the same issue, in my case on Galaxy S7 running Android version 8.0. Has anyone found a solution?

Hi. Apparently this is a bug that they do not intend to solve. However, I found a workaround. Tap on X to stop downloading, and tap on the picture again to download it.

@www you should make your comment as an answer and OP to accept it

Apparently this is a bug that still exists. However, I found a workaround. Tap on X to stop downloading the media, and tap again to download it.


text:
Chrome disappears/hangs after reboot?
I'm using Android 4.1.2 that's rooted.
Because Google Chrome has a big size, especially the cache (which is troublesome to delete it every visiting a new site), i moved my Chrome to SD Card by using Titanium Backup.(In my phone chrome is a system app so i deleted it and reinstall the Playstore version)
But now, when i reboot my phone, my Chrome will either crashes or disappears entirely at startup. Is there any way to solve this?
If that's impossible, is there any way to move cache to SD Card? Because that what makes my internal memory loses much space.
My phone is Oppo Find Way (U7015) - it's only released in china and southeast asia :)

Welcome to Android Enthusiasts Stack Exchange! The question-and-answer format of this site works best if you put each question in a separate question post. Please edit your post down to one question, and create new posts to ask any further questions. You'll get better answers that way.

Or just remove the second part: A reboot is needed when a reboot is needed, not when the day changes. I reboot my devices only when something "got stuck", which doesn't happen more than once or twice a month usually. On some devices, even much less frequent.

@Izzy I was going to leave this for a separate question, but there is a reason why a manufacturer might recommend this: they (think they) have introduced a memory leak in a core system component such as a driver. In that case, a reboot every so often may be the only way to stop the device running out of memory.

Thanks for your suggestion, i already deleted the second part :) Thanks for letting me know :D

@DanHulme Agreed, and that's probably overlapping with my "getting stuck". "every so often" = "when it's needed" ≠ "every 24h". I doubt there's a definite time table ;) // user46097: You might wish to take a look at our app2sd tag-wiki, which also lists available alternatives concerning your app-move.

So if the manufacturer/device aren't stating that the device needed to be rebooted at a definite time table, it's okay to let my device run for days or months without rebooting right?
@Izzy: Okay then, i'm going to ask if it is possible to move cache to SD Card, but i guess i'll leave it as a different question lol

Let's say if everything runs fine, you definitly do not need to reboot. When in doubt, it doesn't hurt. And yes, make that a separate question – after having read the app2sd tag-wiki. If you still need to ask then, that is :)


text:
How to detect filesystem type of un-mounted partition?
These commands won't work:
fdisk -l      #outputs nothing...
su; fdisk -l  #nothing..
sudo fdisk -l #sudo not found...
parted -l     #parted not found...

Is there any app that shows that easly?
EDIT:
For now I had to attach the sdcard to PC and let Linux mount it, I found the partition was ext3 and not ext2 that I thought! All I read says partition must be mounted to know its type. I think we must create a path and mount it with automatic detection and see mount output to know the partition type.

Related: How do I find what type of file system is of an attached USB or SD card?

Have you got the file command available? This question on SuperUser says that's the way to go.

very interesting, on my PC, this command: sudo file -Ls /dev/sda4; shows, without mounting, that the filesystem is ext4! but file command isnt available on my android :(, I have busybox, but no file command was found :(

mmm, seems we can have the file command: http://forum.xda-developers.com/showthread.php?p=25264786, I just dont know if it will work on my android kernel


text:
Is there a RAM test for Android devices?
I need to fix a friend's phone this evening that has suddenly produced loads of android.process.media and com.google.process.gapps errors.  I am going to reinstall the OS as it's an older ROM but it got me wondering: there is memtest for x86 based devices that will test the RAM of a PC, is there a similar app that can be loaded in place of an OS on Android that will do the same thing?

Not that I know of, for starters MemTest x86 is specifically orientated obviously to x86 architecture. None such thing exists for ARMv6 or ARMv7 architecture! The reason you're getting force closes there - has nothing to do with RAM chips, rather, a app that was installed somewhat crashed the dalvikvm's cache which produces the neglible effect, or possibly modified a framework portion to add extra icons and whatnots and re-flashed it back in or pushed it into the handset...

I loaded a fresh ROM to the device and have not had a recurrence of the issue.  I still feel this question has merit in that it might someday be answered -- I know of no hardware diagnostics, be it for ARMv6, ARMv7, or any other potential architecture.  It would be useful.

In all fairness, the controls and regulations involved in producing RAM chips is quite high and there would be no room for errors that would be tolerated either (think of equivalent Intel's pre-fabrication factory...) Devices like smartphones with their RAM chips tightly integrated, are not going to fail. SO I think your question is not a real question and not constructive either. As you have found out, a simple wipe/flash of the ROM cured the hiccup and has zero to do with RAM chips!!!

Sorry tm, but obviously you know only little about integrated circuits. Of course the memory of a handheld device can fail. It is in this respect no different than any other memory. The reason why there are no testing utilities are not clear to me either. I guess that most people would not bother to check but just claim their guarantee. Also, these tools run typically at boot time, so the phone must be put in recovery mode - also not very attractive when you can just exchange the device.

Unfortunately there isn't any tool like memtest86 for ARM architecture. Related: How to disable bad RAM addresses and fix bad storage blocks?.

This tests RAM, storage and well many other device features: Phone Check (and Test)

Apps can't test hardware resources without root access. All they can do is either rely on system provided APIs to get AMAP information about hardware, or perform a stress test within the limitations enforced by OS. So they can't estimate performance correctly.

Like to point out that Apps most definitely can test hardware without root access. Bad memory can be traced via stress tests even within OS limitations, although not pinpointed but to know if its bad or not its quite useful.


text:
How much privileged GMS Core is in the Android Stack?
The GMS Core has a ton of capabilities and doesn't seem to perform like a typical application (as in an Application living in the 'Applications' layer shown below). I would assume it would have more privileges and potentially live in the Android Framework layer or the same place as the 'Core Libraries' mention. However, I noticed a u0_a12 UID (not root or system) was attached to the com.google.android.gms process indicating that it's a user owned application. Can someone elaborate on this a little?

Android reserves UID range 10000 to 19999 for apps - user, system or framework. u0_a12 doesn't indicate a user owned application, it simply means UID 10012 which can be assigned to any app. On Android every app is assigned a unique non-zero UID. No app can run with root privileges, including system apps.
UID 0 (root) is the privileged user in Discretionary Access Control (DAC) but be noted that even a process running with UID 0 can be non-privileged or one with non-zero UID can be privileged. Refer to Linux capabilities, particularly Ambient Capabilities.
However Android's Java framework doesn't rely directly on DAC very much, it has its own privilege control mechanism through permissions e.g. Storage, Camera, Internet etc. Manifest permissions have different Protection Levels. Some are granted without asking user, some others require user's approval to be granted or denied and some are reserved only for system use. For more details please see this answer.
Google Mobile Services (GMS) make use of both; application layer and some features only available to framework/system/privileged apps. For instance Play Services has android.permission.INTERNET which is granted to every app that requests for it. But it also has android.permission.READ_LOGS (1) which has protection level signature|privileged and can't be granted to user installed apps. Similarly GMS Core has unrestricted internet access even in Data Saver and Battery Saver modes (2) which is also possible only for framework apps.

RELATED:

What is the “u#_everybody” UID?
How Android's permissions mapping with UIDs/GIDs works?


text:
How MIUI releases based on different Android versions have same features?
I would like to know how MIUI can provide features on all devices that have the same version of MIUI on it, without the same Android version?

Android version is mainly developed by Google. OEMs like Xiaomi modify AOSP to inject their own features. Other OEMs like Samsung, Huawei also do the same but they don't make visual changes as much as Xiaomi does. Even community based ROMs like Lineage, Omni and their offshoots like AOSP Extended, Resurrection Remix also have an almost standard set of modifications which they do to every AOSP release.
You can also customize AOSP to build a ROM of your own choice with required features.

But if LineageOS releases version 17 it is Android 10(as base) but by MIUI it is not compellingly the latest Android base, like MIUI 11 is not in every case Android 10 but all phones who has MIUI 11 have the same functions

@lucki1000 they have teams of thousands of developers - in-office and online - who work on every new upcoming MIUI release for months to add new features. They work on every Android base separately for every targeted device. Beta versions are released before stable one for testing. MIUI 11 development was started back at start of 2019 and it's released now in October.


text:
How to send all internet traffic to a SOCKS5 proxy server in local network?
I got the inspiration here. It looks like AFWall+ is able to create a NAT forwarding policy to keep all traffic going through a SOCKS5 proxy and fool Google apps into thinking they are not connected via a VPN (Google apps implement additional security measures when connecting via VPNService and if you are in China you will not pass the security check - the security check requests don't go through VPN, so they will EOF because GFW will kill these requests, read more here).
So my question is, if let's say I have a socks5 server running at 192.168.1.1:1088 which tunnels all connections via vmess protocol (aka V2Ray) to remote servers in the US, how do I create my custom script? I have tried:
IP6TABLES=/system/bin/ip6tables
IPTABLES=/system/bin/iptables
ULIMIT=/system/bin/ulimit
PORT=1088
SERVER=192.168.1.1
$ULIMIT -n 4096
$IP6TABLES -F
$IP6TABLES -A INPUT -j DROP
$IP6TABLES -A OUTPUT -j DROP
$IPTABLES -t nat -F OUTPUT
$IPTABLES -t nat -A OUTPUT -o lo -j RETURN
$IPTABLES -t nat -A OUTPUT -d 127.0.0.1 -j RETURN
$IPTABLES -t nat -A OUTPUT -p tcp --dport 53 -j DNAT --to-destination $SERVER:$PORT
$IPTABLES -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination $SERVER:$PORT
$IPTABLES -t nat -A OUTPUT -p tcp -j DNAT --to-destination $SERVER:$PORT
$IPTABLES -t nat -A OUTPUT -p udp -j DNAT --to-destination $SERVER:$PORT

This does not work. So:

Did I create a wrong script? How do I create a script that does what I want to do?
Are there other settings that I should enable first? I didn't tick any app so I assume that means all app go through custom script, right?

The link you have provided is not setting up SOCKS but a transparent proxy i.e. it takes TCP/UDP traffic and SOCKSify it before sending through shadowsocks tunnel. But you need to make your traffic SOCKS-aware before directing towards SOCKS proxy. Either configure individual apps (which have built-in support for SOCKS) or enforce proxy system-wide transparently (what you are trying to do).
LIMITATIONS OF SOCKS PROXY:

It looks like AFWall+ is able to create a NAT forwarding policy

AFWall+ uses iptables at back end and it can execute your script on network changes. Enforcing global proxy is (at least partially) possible with proxifier apps like ProxyDroid (which is iptables-based) and SocksDroid (which is VPN/routing based). I have no affiliation with either.
If manually workig from CLI, you can use a transparent TCP/UDP-to-proxy redirector like redsocks in combination with iptables. shadowsocks provides its own similar tool (ss-redir), so does Tor.

I didn't tick any app so I assume that means all app go through custom script, right?

No. The problem with the iptables approach is that SOCKS5 is a layer 5 protocol in OSI model. So it cannot carry whole traffic from all apps. Most of the traffic generated by apps is TCP which works fine with SOCKS and is easy to setup. But some games, VoIP apps and above all the traditional DNS generate UDP traffic which is not supported by many SOCKS5 proxies. E.g. openssh and tor both don't, shadowsocks however does have UDP associate features. But it doesn't work with simple DNAT or REDIRECT (probably because SO_ORIGINAL_DST is not available for UDP sockets, I don't know the details). You can possibly redirect traffic only towards a fixed socket (IP:PORT) e.g. a DNS server or game server.
TPROXY is the alternative here, but the trouble is that it works only with PREROUTING chain i.e. the traffic coming from outside, not that generated on device. So you have to do extra setup to route your on-device traffic without NATing towards a local proxy server (usually default gateway) where you'll set up TPROXY.
Complicated? That's why VPN is preferred. Even if you need to use a proxy to circumvent firewalls, VPN tunneling through proxy spares you from the traffic redirection complexities. VPN operates at lower level in network stack (L2/L3 in OSI), so it flawlessly carries all IP traffic including ICMP echos (ping) etc. which can no way be sent through SOCKS. Another plus point is that VPN can be tunneled through transparent proxies - like shapeshifter-dispatcher and stunnel - or SOCKS proxies which are meant to forward only single port - like obfs4proxy.
If not forwarding single port (tunneling), SOCKS5 must be an application level proxy i.e. it should be able to forward arbitrary ports from different apps like SSH dynamic port forwarding does.
tun2socks is another SOCKSification method which collects TCP/UDP traffic on a tun interface (same like a VPN, no NAT involved) and forwards it through a SOCKS proxy. It recently added UDP associate support. Previously used UDP Gateway method also worked quite fine but it requires running a separate daemon (udpgw) along with proxy server. tun2socks is a non-root solution because apps - like SocksDroid and many other firewalls, sniffers etc. - using this method rely on Android's VPN facilities.

... and fool Google apps into thinking they are not connected via a VPN (Google apps implement additional security measures when connecting via VPNService ...

With both above methods (VPN through tunnel and Tun-to-SOCKS) it's not necessary to use Android's VPNService API (if that's causing problems for you). On a rooted device you can get a static openvpn or tun2socks binary and run that through CLI. That's far less hassle than setting up proxy through iptables. In former case, though, you need a VPN server obviously.
SOCKSIFY WHOLE DEVICE:
As you don't want to go with VPN/routing based solution, here is the simple iptables-based method.
First get redsocks binary for your device architecture (or try this one for aarch64 or this one for armeabi-v7a).
Create configuration file:
// redsocks.conf

// general configuration
base {
    redirector = iptables;
}

// for TCP
redsocks {
    local_ip = "127.0.0.1"; local_port = "12345";
    ip = "192.168.1.1"; port = "1088"; type = socks5;
}

// for UDP, assuming your SOCKS5 proxy supports UDP associate
redudp {
    local_ip = "127.0.0.1"; local_port = "12345";
    ip = "192.168.1.1"; port = "1088";
    dest_ip = "1.1.1.1"; dest_port = "53";  /* set whatever DNS server */
}

 * See redsocks.conf.example for details and more options.
Run:
#!/system/bin/sh

IPTABLES="/system/bin/iptables -w5 -t nat"

# create new chain
$IPTABLES -N PROXY
$IPTABLES -I OUTPUT -j PROXY

# exclude local traffic, see: http://manpages.org/ss-redir
$IPTABLES -A PROXY -d 127.0.0.0/8 -j RETURN
$IPTABLES -A PROXY -d 192.168.0.0/16 -j RETURN

# socksify whole TCP traffic
$IPTABLES -A PROXY -p tcp -j DNAT --to 127.0.0.1:12345

# socksify only DNS UDP traffic
$IPTABLES -A PROXY -p udp --dport 53 -j DNAT --to 127.0.0.1:12345

echo "Ctrl^C to exit."
trap "$IPTABLES -D OUTPUT -j PROXY; $IPTABLES -F PROXY; $IPTABLES -X PROXY" EXIT

# run socksifier
redsocks -c /path/to/redsocks.conf

You can add custom iptables script to AFWall+. redsocks can be run as init service with non-root UID, dropped capabilities and restricted SELinux context. See How to run an executable on boot?

RELATED:

Why is not all traffic captured from my device when routing through proxy?
How to set up a socks5 with Android CLI?

Your redsocks + iptables solution worked but I had to correct several things to use Dante SOCKS proxy on Anbox. For the first iptables command, I got error unknown option "-w5". Adding a space before the number did not solve the problem. Anbox used Android 7 (x86) with iptables v1.4.20 and the -w parameter did not accept any value. Is this parameter necessary? I did not need to use it. Then I had to comment the iptables command for UDP, otherwise DNS would not work. In redsocks.conf, I also had to comment the redudp block because of the error file parsing error at line 13: unknown section.

@baptx for -w see iptables manpage. // UDP is officially supported by redsocks: https://github.com/darkk/redsocks/blob/master/redsocks.conf.example#L117. It doesn't work for you because your proxy doesn't have UDP associate feature. So you can't send DNS or any other UDP traffic through proxy. That's what I've explained under LIMITATIONS OF SOCKS PROXY. Please go through the answer completely for better understanding. // May be you need an empty line at .conf end: https://github.com/darkk/redsocks/issues/134

I still got the file parsing error on the redudp line, even with an empty line at the end of the config file. It looks like this configuration is not supported by the version of redsocks I am using. I downloaded the x86 build of redsocks from ProxyDroid. With redsocks -v, I can see that they are using an older version, 0.4 instead of latest 0.5.

@baptx UDP is supported since version 0.1: https://github.com/darkk/redsocks/commit/c0d4cede5a43e552017f2696d5b80dc2741e3190#diff-d64baa8264254662e7f0007c0f4fa939. But you may consider building from latest source.

@IrfanLatif how to use TPROXY instead of DNAT? here not all UDP traffic is redirected.

@hldev read the link given in the answer. Or any other TPROXY setup guide on internet.

@IrfanLatif yes, I found TPROXY can be used only from PREROUTING, so I cant route the output like you did, redsocks must run on another machine.

You can tunnel all your traffic or only selected apps from your android device to a SOCKS5 proxy using Tun2Socks app which is available in Playstore

Hi. Looks like the app was released very recently on May 2024 and only has 50+ downloads as of now. Are you affiliated with the app? If yes, then please disclose the affiliation.


text:
How to make Ethernet work on Android over OTG?
I am trying to use an LTE modem connected to an Android 7 device over an OTG cable. The kernel recognizes the device and registers it with cdc_ether, but I am unable to use the connection from the device. Is this because it is subsequently mounted as USB storage?
The device does not show up as a device in the Android UI / status bar.
If I disable MTP support, then the device wont register cdc_ether at all.
dmesg:
[10946.408785] usb 1-1.3: new high-speed USB device number 21 using msm_hsusb_host
[10946.525287] usb 1-1.3: New USB device found, idVendor=19d2, idProduct=1225
[10946.525306] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[10946.525316] usb 1-1.3: Product: ZTE Mobile Broadband
[10946.525325] usb 1-1.3: Manufacturer: ZTE,Incorporated
[10946.525335] usb 1-1.3: SerialNumber: MF8610ZTED000000
[10946.529662] usb-storage 1-1.3:1.0: USB Mass Storage device detected
[10946.532702] scsi host19: usb-storage 1-1.3:1.0
[10947.538579] scsi 19:0:0:0: CD-ROM            ZTE      USB SCSI CD-ROM  2.31 PQ: 0 ANSI: 2
[10952.740595] usb 1-1.3: USB disconnect, device number 21
[10953.087891] usb 1-1.3: new high-speed USB device number 22 using msm_hsusb_host
[10953.232955] usb 1-1.3: New USB device found, idVendor=19d2, idProduct=1405
[10953.232969] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[10953.232977] usb 1-1.3: Product: ZTE Mobile Broadband
[10953.232984] usb 1-1.3: Manufacturer: ZTE,Incorporated
[10953.232991] usb 1-1.3: SerialNumber: MF8610ZTED000000
[10953.260856] cdc_ether 1-1.3:1.0 usb0: register 'cdc_ether' at usb-msm_hsusb_host-1.3, CDC Ethernet Device, 36:4b:50:b7:ef:da
[10953.262322] usb-storage 1-1.3:1.2: USB Mass Storage device detected
[10953.262652] scsi host20: usb-storage 1-1.3:1.2
[10954.261139] scsi 20:0:0:0: CD-ROM            ZTE      USB SCSI CD-ROM  2.31 PQ: 0 ANSI: 2

dmesg with MTP disabled:
[10664.987934] usb 1-1.3: new high-speed USB device number 19 using msm_hsusb_host
[10665.105272] usb 1-1.3: New USB device found, idVendor=19d2, idProduct=1225
[10665.105291] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[10665.105301] usb 1-1.3: Product: ZTE Mobile Broadband
[10665.105310] usb 1-1.3: Manufacturer: ZTE,Incorporated
[10665.105320] usb 1-1.3: SerialNumber: MF8610ZTED000000
[10665.110339] usb-storage 1-1.3:1.0: USB Mass Storage device detected
[10665.111320] scsi host17: usb-storage 1-1.3:1.0
[10666.110748] scsi 17:0:0:0: CD-ROM            ZTE      USB SCSI CD-ROM  2.31 PQ: 0 ANSI: 2
[10671.223090] usb 1-1.3: USB disconnect, device number 19
[10671.407859] msm_otg 78db000.usb: OTG runtime idle
[10671.407887] msm_otg 78db000.usb: OTG runtime suspend

ifconfig:
TB-8504F:/ # ifconfig
wlan0     Link encap:Ethernet  HWaddr 40:a1:08:36:5b:0d
          inet addr:192.168.1.133  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: 2605:a601:ab2b:9900:b19e:4f2e:5d28:5fa9/64 Scope: Global
          inet6 addr: fe80::42a1:8ff:fe36:5b0d/64 Scope: Link
          inet6 addr: 2605:a601:ab2b:9900:42a1:8ff:fe36:5b0d/64 Scope: Global
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:27906 errors:0 dropped:4 overruns:0 frame:0
          TX packets:17795 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:14342222 TX bytes:8697917

dummy0    Link encap:Ethernet  HWaddr c6:b9:c8:82:8f:7e
          inet6 addr: fe80::c4b9:c8ff:fe82:8f7e/64 Scope: Link
          UP BROADCAST RUNNING NOARP  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 TX bytes:210

p2p0      Link encap:Ethernet  HWaddr 42:a1:08:36:5b:0d
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 TX bytes:0

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope: Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 TX bytes:0

ip l:
255|TB-8504F:/ # ip l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: dummy0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default
    link/ether c6:b9:c8:82:8f:7e brd ff:ff:ff:ff:ff:ff
3: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default
    link/sit 0.0.0.0 brd 0.0.0.0
20: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DORMANT group default qlen 1000
    link/ether 40:a1:08:36:5b:0d brd ff:ff:ff:ff:ff:ff
21: p2p0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN mode DORMANT group default qlen 1000
    link/ether 42:a1:08:36:5b:0d brd ff:ff:ff:ff:ff:ff
31: usb0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 36:4b:50:b7:ef:da brd ff:ff:ff:ff:ff:ff

The device does show up as usb0 with the MAC address that was listed in dmesg.

but I am unable to use the connection from the device How did you try using it? Android won't configure it (unless a custom configuration is added to some of  init's .rc files), you have to do it manually. Does it appear as a network interface (check using ip l or ifconfig)?

thank you for the response - i added the requested logs - do you have an example of how to add a custom entry to init.rc files? I can modify the boot partition on this device

I think usb0 is the interface. You can confirm though by removing the dongle. You can configure this interface using ip commands (set up, set IP, add route etc.). But Android framework won't be aware of this interface, so some APIs would report device offline. Android doesn't configure and manage hardware resources directly but through vendor provided HALs. So if you want to add a new hardware resource, you need to run its HAL as a native service. Android framework would interact with that. In simple words it requires rebuilding a custom ROM.

I have the source for this device and have been building the ROM / modifying it to support a quectel modem. Thank you so much for your information! usb0 is the interface - it disappears when I remove it

Development related questions are off-topic here. // Android provides limited support for Ethernet. See this, this, this and this. If only Mass Storage device appears and not the Ethernet, your dongle must be a flip flop device which needs USB_ModeSwitch.

where are development questions allowed? If I ask in SO, I get directed here...

Moderators have their own constraints and line of action. But you should state clearly AMAP that your question is development oriented. As in the case of this question, it looks like it's related to end users. But after conversation it turns out to be development oriented. This can mislead.

There is a long list of Ethernet related questions but none has a comprehensive answer covering all aspects. I'm generalizing your question in order to share my knowledge on this.
This is what you need to do in order to make Ethernet work on Android:

Make sure OTG support is available
Kernel must be built with Ethernet (and USB Ethernet) support
Handle USB mode switch and kernel module loading (if applicable)
Make Android framework do network configuration or do it manually

Note: Everything described below requires a rooted device, or at least the one with unlocked bootloader.
You should be familiar with commandline interface.

OTG SUPPORT
Your device must be able to operate in USB host mode.EthernetService is started only if device supports feature USB host (android.hardware.usb.host) or Ethernet (android.hardware.ethernet). You may also need to use a powered USB hub if Android's USB power supply is not enough for connected device. Related question:

Is there a definite way to know if my phone supports USB-OTG or not?

KERNEL CONFIGURATION
In order to use Ethernet over USB (adapters or modem-like devices) kernel must be built with CONFIG_USB_USBNET and other configurations like USB_NET_CDCETHER, USB_NET_HUAWEI_CDC_NCM, USB_NET_CDC_MBIM etc. depending on the type of connected device and the protocol it talks. Related questions:

Where kernel modules are installed?
Add a driver to kernel without flashing a new kernel
Load an unsigned Kernel Module to signature enforcing Kernel

USB MODE SWITCH AND LOADING KERNEL MODULE
Many USB network devices are multi-mode or flip flop devices. They appear as USB Mass Storage device (also called ZeroCD mode) when inserted and need to be switched to Ethernet/PPP mode. USB_ModeSwitch is a Linux tool commonly used for this purpose. See some details here how it works. You need to build this tool for your device, or may download this binary for aarch64. Get device database from here.
In order to automatically switch mode whenever the device is connected to Android, we need to listen to kernel USB uevents, either through hotplug helper or a userspace daemon (like udev on Linux and ueventd on Android). Additionally the kernel module can also be loaded/unloaded automatically. I'm defining an init service here to achieve this, you can do it manually too.
Note: There is an Android app PPP Widget (by the developer of USB_ModeSwitch, I have no affiliation) which handles mode switching automatically and needs "no kernel driver modules, the 'driver' implementation is based on the Android USB host API". You might be interested in that too.
# /system/etc/init/custom.rc

# kernel hotplug or uevent daemon service
service cust.udevd /system/sbin/busybox uevent /system/sbin/udev.sh
    seclabel u:r:magisk:s0
    disabled
    writepid /dev/cpuset/system-background/tasks

# set kernel hotplug helper or start uevent daemon on boot
on property:sys.boot_completed=1
    #write /proc/sys/kernel/hotplug /system/sbin/udev.sh
    start cust.udevd

* In case of hotplug you need to define custom SELinux policies to let kernel make changes (see this answer for details).
#!/system/bin/sh

# /system/sbin/udev.sh script is executed from kernel hotplug or uevent daemon

# set PATH where you placed binaries
export PATH=/system/bin

# save log
exec >>/dev/udev.log 2>&1

# don't execute multiple instances
exec 200<>/dev/udev.lock
flock 200

VID="12d1"          # USB vendor ID of a Huawei devcie
PID_UMS="1f01"      # product ID in ZeroCD mode
PID_ETH="14db"      # product ID in Ethernet mode
MODULE="cdc_ether"  # kernel module for USB Ethernet
IFACE="usb0"        # Ethernet interface name

matches() {
    [ -e "/sys/$DEVPATH/$1" ] || return 1
    [ "$(cat "/sys/$DEVPATH/$1")" = "$2" ] || return 1
    return 0
}

# check if a new USB device is added or removed
if [ "$SUBSYSTEM" = "usb" ]
then
    # check if a USB device is added, then match VID and PID for mode switching
    # also device must belong to UMS class: https://www.usb.org/defined-class-codes#anchor_BaseClass08h
    if [ "$ACTION" = "add" ] && echo "$PRODUCT" | grep -q "$VID/$PID_UMS/" &&
        matches bInterfaceClass 08 && matches bInterfaceNumber 00
    then
        echo "Switching USB mode..."

        # USB mode switching of flip flop devices (USB modems, routers etc.)
        # usb_modeswitch_dispatcher needs /system/sbin/usb_modeswitch binary and configuration files in /etc
        # so you need to modify the hard-coded paths in source code as per your requirement
        usb_modeswitch_dispatcher --switch-mode "$(basename "$DEVPATH")"
    fi

    # match VID and PID for module loading
    # modprobe should be built with the hard-coded path to where you place modules e.g. /system/lib
    if echo "$PRODUCT" | grep -q "$VID/$PID_ETH/"
    then
        if [ "$ACTION" = "add" ] && ! grep -q "^$MODULE " /proc/modules
        then
            echo "Loading $MODULE module..."
            modprobe "$MODULE"

        elif [ "$ACTION" = "remove" ] && grep -q "^$MODULE " /proc/modules
        then
            echo "Removing $MODULE module..."
            modprobe -r "$MODULE"
        fi
    fi
fi

# on network interface event
if [ "$SUBSYSTEM" = "net" ] && [ "$INTERFACE" = "$IFACE" ]
then
    if [ "$ACTION" = "add" ]
    then
        echo "Starting cust.eth_config service..."
        #start cust.eth_config    # uncomment if you want to do manual network configuration
    fi

    if [ "$ACTION" = "remove" ]
    then
        echo "Stopping cust.eth_config service..."
        #stop cust.eth_config    # uncomment if you want to do manual network configuration
    fi
fi

NETWORK CONFIGURATION
Android framework has a hard-coded name for Ethernet interface (default is eth0, eth1, ...). Whenever an Ethernet interface appears, its name is matched with the hard-coded value. Renaming interface afterwards doesn't work because only kernel provided interface name is tracked.
So you need to make this naming convention consistent between kernel and AOSP by modifying one of the both (if needed). Kernel provided name can be seen using ip tool (as in your case it's usb0). Use dumpsys or de-compile /system/framework/framework-res.apk using apktool to see the AOSP value.
~$ dumpsys ethernet
...
  Ethernet interface name filter: eth\d
...

As soon as an Ethernet interface appears, Android configures it automatically, NetworkMonitor validates the connectivity and ConnectivityService turns off WiFi and Mobile Data (if it's ON). Other services and components involved in configuration include UsbHostManager, EthernetTracker, EthernetNetworkFactory, IpClient.eth0, DhcpClient, DnsManager and Netd.
EthernetService was added in Android 5. Before that AOSP was patched to make Ethernet work (e.g. see this and this). Still stock Android provides no GUI settings for Ethernet, but some custom ROM developers and OEMs do (e.g. see this). EthernetManager class which is used to set and save manual IP configuration (to /data/misc/ethernet/ipconfig.txt) is hidden. Default is to use a hard-coded configuration (see using dumpsys ethernet under "IP Configurations:") or DHCP provided configuration.
MANUAL CONFIGURATION
You might want to do manual network configuration e.g. if:

Android framework doesn't configure the Ethernet interface (on older devices or due to interface name inconsistency).
You want to set static IP address or different DNS server.
You want to use Ethernet along with WiFi or Mobile Data, or want to share internet among any of these.

But in this case Android's Java network stack remains down, so some apps depending on Android APIs may not behave normally. For related details see Connecting to WiFi via ADB Shell.
# /system/etc/init/custom.rc

# Ethernet IP configuration service
service cust.eth_config /system/sbin/eth_config.sh
    seclabel u:r:magisk:s0
    disabled
    writepid /dev/cpuset/system-background/tasks

# clear routing and DNS
on property:init.svc.cust.eth_config=stopped
    exec u:r:magisk:s0 -- /system/sbin/eth_config.sh stop

#!/system/bin/sh

# /system/sbin/eth_config.sh script is executed from eth_config init service

# set PATH where you placed binaries
export PATH=/system/bin

IFACE=usb0                    # Ethernet interface name
DIR=/data/local/tmp/ethernet  # temporary directory
mkdir -p $DIR

# save log
exec >$DIR/eth_config.log 2>&1

if [ "$1" = stop ]
then
    echo "Clearing configuration..."
    ip ru del lookup main
    ip r f table main
    ndc resolver setnetdns 0 '' 0.0.0.0
    exit
fi

# destroy set network if any
ndc network default set 0

# turn WiFi and Mobile Data off
svc wifi disable
svc data disable

# set interfaces up
ip link set dev lo up
ip link set dev $IFACE up

# Android doesn't use main table by default
ip rule add lookup main

# set IP, route and DNS manually here
# or add any other IP/routing configuration
# or run a minimal DHCP client as follows

# create 'udhcpc' script
<<-'SCRIPT' cat >$DIR/udhcpc_default.script
#!/system/bin/sh

case $1 in
    bound|renew)
        echo "Setting IP address, gateway route and DNS for $interface..."
        ip address f dev $interface
        ip route f table main
        ip address add $ip/$mask dev $interface
        ip route add default via $router dev $interface
        ndc resolver setnetdns 0 '' $dns
    ;;
    *)
        echo "Ignoring $1"
    ;;
esac
SCRIPT

# start DHCP client to obtain IP from server
chmod 0755 $DIR/udhcpc_default.script
exec busybox udhcpc -v -f -i $IFACE -s $DIR/udhcpc_default.script

Do not forget to set proper permissions on .rc file and shell scripts. Once setup, Ethernet works as soon as you connect USB adapter.

@moderators merge it with some other similar question if needed.

https://chat.stackexchange.com/transcript/121034

This seems precisely the problem that I am facing. But I cannot understand how the usbX interface is renamed as ethX... Could you please provide more details?

@EM90 I think I've already explained it well: "So you need to make this naming convention consistent between kernel and AOSP by modifying one of the both". In simple words: rebuild your kernel or the ROM. Or "you might want to do manual network configuration if Android framework doesn't configure the Ethernet interface due to interface name inconsistency".

Ok, thanks. I read it with more care. If I understand it correctly, I can use the scripts above to manually configure the network settings. Trying those.

+1 Thank you a lot for this great answer! Really a lot of specifics that are super hard to find anywhere else... If I didn't find the  "Android doesn't use main table by default" remark, I would have likely wasted so much time on trying to make an RNDIS ethernet connection work!


text:
How to bind mount a folder inside /sdcard with correct permissions?
I am using a Sony Xperia M4 Aqua. As is well known, the internal memory is rather small. Especially the Media directory of WhatsApp uses a lot of precious space, therefore I am trying to move it to the SD card.
I am using Android 6 and I have formatted the SD card to have an adopted storage partition.
Adopted storage would be normally used to migrate all /data to it, as discussed here.
I am however interested in moving just the single directory WhatsApp/Media somewhere else (possibly in the adopted storage partition), and then bind-mount it to its original location.
For this purpose, I moved the WhatsApp/Media directory to the adopted storage. Then, following this discussion, I have modified the script /system/etc/init.qcom.post_boot.sh adding the following mountcommands (the phone has no support for init.d scripts)
mount -o bind /mnt/expand/4fdb2500-9aa7-44bc-a2c4-80aeae28e764/WhatsAppMedia /storage/emulated/0/WhatsApp/Media
mount -o bind /mnt/expand/4fdb2500-9aa7-44bc-a2c4-80aeae28e764/WhatsAppMedia /mnt/runtime/write/emulated/0/WhatsApp/Media
mount -o bind /mnt/expand/4fdb2500-9aa7-44bc-a2c4-80aeae28e764/WhatsAppMedia /mnt/runtime/read/emulated/0/WhatsApp/Media
mount -o bind /mnt/expand/4fdb2500-9aa7-44bc-a2c4-80aeae28e764/WhatsAppMedia /mnt/runtime/default/emulated/0/WhatsApp/Media
mount -o bind /mnt/expand/4fdb2500-9aa7-44bc-a2c4-80aeae28e764/WhatsAppMedia /data/media/0/WhatsApp/Media

Notice: /mnt/expand/4fdb25.... points to the adopted storage partition.
This only apparently works: if I open a shell with adb I can correctly see that the WhatsApp/Media directory contains the mounted directory. Also, I see no additional views that contains the WhatsApp directory, as can be checked by doing, in an adb shell
find / -type d -name WhatsApp

Nevertheless, WhatsApp is not able to access the Media gallery. For instance, in the chat I just see blurred pictures (like a preview), and clicking on it I do not see the full picture. Moreover, if somebody sends me a picture, all I can see is a blurred preview with the download icon. Clicking on the download icon does not produce anything.
Wrong permissions are presumably the source of problems. For example, some permissions/group ownership appear to be incorrect on some views:
root@E2303:/ # ls -n /storage/emulated/0/WhatsApp
drwxrwx--x 0        1015              2019-09-04 14:37 Backups
drwxrwx--x 0        1015              2019-10-19 02:00 Databases
drwxrwx--x 0        1015              2019-09-04 20:24 Media
root@E2303:/ # ls -n /mnt/runtime/write/emulated/0/WhatsApp
drwxrwx--- 0        9997              2019-09-04 14:37 Backups
drwxrwx--- 0        9997              2019-10-19 02:00 Databases
drwxrwx--x 0        1015              2019-09-04 20:24 Media
root@E2303:/ # ls -n /mnt/runtime/read/emulated/0/WhatsApp
drwxr-x--- 0        9997              2019-09-04 14:37 Backups
drwxr-x--- 0        9997              2019-10-19 02:00 Databases
drwxrwx--x 0        1015              2019-09-04 20:24 Media
root@E2303:/ # ls -n /mnt/runtime/default/emulated/0/WhatsApp
drwxrwx--x 0        1015              2019-09-04 14:37 Backups
drwxrwx--x 0        1015              2019-10-19 02:00 Databases
drwxrwx--x 0        1015              2019-09-04 20:24 Media
root@E2303:/ # ls -n /data/media/0/WhatsApp/
drwxrwxr-x 1023     1023              2019-09-04 14:37 Backups
drwxrwxr-x 1023     1023              2019-10-19 02:00 Databases
drwxrwx--x 0        1015              2019-09-04 20:24 Media

Permissions and group ownership of the Media directory should be the same of the other (non bind-mounted) directories Backups and Databases.
Oddly enough, an attempt to remount the directories with the correct gid
root@E2303:/ # mount -o remount, gid=9997 /mnt/runtime/write/emulated/0/WhatsApp/Media
root@E2303:/ # mount -o remount, gid=9997 /mnt/runtime/read/emulated/0/WhatsApp/Media
root@E2303:/ # mount -o remount, gid=1023 /data/media/0/WhatsApp/Media

does not produce any changes in the group ownership: ls -n as above gives identical results.
Even more strange, but maybe unrelated, omitting the space between remount and gid=... results in
mount: Invalid argument

How to bind mount WhatsApp/Media folder from external SD card with correct permissions?

I have been using two different approaches (in fact many with small differences) on my older Android versions to mount whole /sdcard/WhatsApp directory from external SD card. I have tested, it works on Android 9 too, but the storage things have changed on Android 10.
Before getting into practical details, we need to keep in mind a few points:

/sdcard isn't an actual but emulated filesystem. Android uses sdcardfs (or FUSE) to emulate actual storage on /sdcard. See What is /storage/emulated/0/?
Both of the above filesystems have a fixed SELinux context: u:object_r:sdcardfs:s0 (or u:object_r:fuse:s0).
Normally /data/media is emulated over /sdcard, but in case of Adoptable Storage when data is migrated, /mnt/expand/[UUID]/media is emulated. See How to free Internal Storage by moving data or using symlink / bind-mount with Adoptable Storage?
Files and directories on /sdcard have fixed ownership and permissions which depend on if the app has android.permission.[READ|WRITE]_EXTERNAL_STORAGE permission granted or not. Files have never executable permission. Apps' data directories in /sdcard/Android/data/ have ownership set to respective app's UID. For details see What is the “u#_everybody” UID?
We assume here that every app is allowed to write to /sdcard by setting ownership 0/9997 (user/group) and permissions 0771/0660 (directories/files).
To achieve above said behavior, since Android 6 every app is run in an isolated mount namespace and /storage/emulated is bind mounted to a different VIEW: /mnt/runtime/[default|read|write]/emulated with private/slave mount propagation. So mounting directly to /storage/emulated won't appear in apps' mount namespaces unless you enter every app's mount namespace explicitly. The same is true if you mount from some app's isolated mount namespace. See Partition gets unmounted automatically in Android Oreo.
We are going to mount from root mount namespace to /mnt/runtime/write/emulated which is propagated to all apps' mount namespaces.
read and default views have different permissions than write (1), but mounting to both is usually unnecessary. Permissions READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE belong to same permission group. So granting one to an app through GUI also grants the other, and all apps with Storage permission will only see write view. default is only to let apps (which don't have READ/WRITE Storage permission) traverse /sdcard/Android/data directories. So mounting to default will let such apps just pass through subdirectories on /sdcard/, no files will be visible.
Also at least with sdcardfs emulation, read and write are bind-mounted (2) from default and mounting to one also mounts to other two. So it's not possible to mount all of three with different permissions.
/sdcard does not support Extended Attributes (xattr) and Access Time (atime). Other mount options include nosuid, nodev and noexec. See mount manpage for details.

First of all make sure you are in root mount namespace as explained in the link given above. Or use nsenter to get a root shell in global namespace:
~# [ $(readlink /proc/1/ns/mnt) = $(readlink /proc/self/ns/mnt) ] || busybox nsenter -t 1 -m /system/bin/sh

1. MOUNT SD CARD MANUALLY:
The straightforward way is to format external SD card as portable storage with exFAT or FAT32. Since these filesystems aren't native to Linux, their in-kernel driver implementations support uid, gid, fmask and dmask mount options. You can use exfat or sdfat drivers with exFAT and vfat with FAT32. Former has also a userspace implementation mount.exfat-fuse which requires only FUSE support from kernel. Check with grep fuse /proc/filesystems.
Let's say /dev/block/sda1 is your exFAT partition:
~# mount -t exfat -o nosuid,nodev,noexec,noatime,context=u:object_r:sdcardfs:s0,uid=0,gid=9997,fmask=0117,dmask=0006 /dev/block/sda1 /mnt/runtime/write/emulated/0/WhatsApp
~# mv /data/media/0/WhatsApp/* /sdcard/WhatsApp/

* Replace u:object_r:sdcardfs:s0 with u:object_r:fuse:s0 or whatever label your /sdcard has.
You can also create multiple partitions on SD card. Or after mounting with required mount options you may also bind mount a directory instead of whole partition. Let's say you first mount SD card to /mnt/my_sdcard, then bind mount WhatsApp directory:
~# mount -o bind /mnt/my_sdcard/WhatsApp /mnt/runtime/write/emulated/0/WhatsApp

Downside with this approach is that vold mounts external SD card on boot, so you need to un-mount first.
Secondly the data on SD card isn't encrypted, though there are multiple ways to encrypt manually. See Decrypting microSD card on another Android device or desktop computer.
2. ADOPTABLE STORAGE:
An easy way to counter the above said downsides is to make use of kernel's built-in FDE by formatting the SD card as Adoptable Storage, but only if you don't want to migrate all /data/media/ to external SD card. Once formatted, external SD card will be mounted at /mnt/expand/[UUID] (filesystem UUID is a 16 bytes number). But we can't simply bind mount a directory from there to /sdcard because the filesystem on Adoptable Storage is ext4, which follows UNIX permissions model but the apps can't handle those as explained above. Even if you make it work somehow (using chown, chmod etc.), every app will create files with its own UID which won't be accessible to other apps e.g. Gallery may not be able see pictures downloaded by WhatsApp.
For this method to work your kernel must support sdcardfs (check with grep sdcardfs /proc/filesystems). Create a directory on Adopted SD card and emulate it to /sdcard/WhatsApp:
~# mkdir /mnt/expand/[UUID]/media/0/WhatsApp
~# mv /sdcard/WhatsApp/* /mnt/expand/[UUID]/media/0/WhatsApp/
~# restorecon -rv /mnt/expand/[UUID]/media/
~# mount -t sdcardfs -o nosuid,nodev,noexec,noatime,mask=7,gid=9997 /mnt/expand/[UUID]/media/0/WhatsApp /mnt/runtime/write/emulated/0/Whatsapp

Please note that we necessarily need to use path /mnt/expand/[UUID]/media/ because it's labeled as media_rw_data_file (3) (like /data/media (4)) which is allowed by SELinux policy to be accessed by apps (5). If you use a different path, you need to modify SELinux policy. Unlike other filesystems sdcardfs itself doesn't change SELinux context when accessing underlying filesystem.
3. PORTABLE / ADOPTABLE STORAGE:
This method is the most flexible, it works if you want to use:

Portable storage but don't want to mount whole partition, instead a directory.
Adoptable storage but your kernel doesn't have sdcardfs support.
Adoptable storage but don't want to use /mnt/expand/[UUID]/media/ path necessarily.

Use a third party tool named bindfs (which uses FUSE) to simulate the behavior of emulated filesystem. Actually Android's built-in tool /system/bin/sdcard does exactly this on pre-sdcardfs releases but it has some fixed paths and other unnecessary things, so its source code needs to be modified to achieve what we want. You can build bindfs yourself or try this this one.
~# DIR=/mnt/media_rw/[UUID]    # for Portable Storage
~# DIR=/mnt/expand/[UUID]      # for Adoptable Storage
~# mkdir $DIR/WhatsApp
~# mv /sdcard/WhatsApp/* $DIR/WhatsApp/
~# bindfs -o nosuid,nodev,noexec,noatime,context=u:object_r:sdcardfs:s0 -u 0 -g 9997 -p a-rwx,ug+rw,ugo+X --create-with-perms=a-rwx,ug+rw,ugo+X --xattr-none --chown-ignore --chgrp-ignore --chmod-ignore $DIR/WhatsApp /mnt/runtime/write/emulated/0/WhatsApp

Side notes:

sdcardfs also works partially with this method except it doesn't support SELinux context= option (so far). So it depends on what is the SELinux label of backing directory on SD card.
Other tools like rclone, encfs, sshfs etc. which make use of FUSE can also be mounted inside /sdcard the same way. Related: How to mount rclone on Android?
-u and -g options require /etc/passwd and /etc/group to exist on bindfs < v1.14.2.

So you may go with whatever method suits you. Usually in-kernel drivers perform better than userspace solutions, and methods native to Linux kernel are more robust and stable. FUSE (over FUSE) may exert performance penalty sometimes e.g. if SD card itself supports high speed data transfers.
You can place the required mount commands in an init.d script or define and init service. See How to run an executable on boot and keep it running?
Note:

Apps which don't scan /sdcard filesystem themselves but rely on Android's MediaProvider for any changes may need a forced media scan for new files on mounted filesystem to appear immediately.
If you use multiple users or profiles, you need to mount new filesystem for every User_ID. For device owner it's 0.

RELATED:

How to bind-mount “data” and “obb” folders from external SD card in “/sdcard/Android”?

Hi Irfan . Going through your meticulous answer... ( and thanks for the same ) ... My situation is a multi partitioned ext4   card where even the main partition is ext4. My ROM is a Stock ROM  that will unlike lineage not support ext4 mount out of box . I can mount my partitions with an approach similar to init.d and they are visible to rooted TC apps but they are not RW. I would like partition wide RW for  certain apps. Not just private dirs. I tried vold-posix it does not like my OS and arch. not executable: 64-bit ELF file I get this error for bindfs. Any other ?

getprop ro.product.cpu.abilist gives  armeabi-v7a,armeabi . Any other approach so I can get a RW partition wide mount for  specific rooted and non rooted apps ( non rooted app is stock ROM's file manager that is invoked by default by all apps to traverse directories ) . As I understand ,Android 'deprecates this but I'd  appreciate it' , if you can throw in your 2 cents !

If this partition wide approach is not feasible then at the time of mounting  want to give specific app IDs RW.  as part of mount. How can I do this ?

@user1874594 we have been through similar discussions on your previous questions and could hardly conclude anything. So I don't think I'd be able to explain anything newer than what I've already done. I don't have a 32-bit ARM bindfs binary, you have to build from source. If you can't, let me know and I'll build one for you when I get time. As far as your other queries are concerned, they cannot be explained (again) in comments. You may ask a precise and unique question with all necessary information and I can try to briefly explain steps specific to your situation.

yes this has been discussed in different context after that I could manage mounting part but making it RW is where I am stuck and I hope I am clear now sorry I do apologize if I wasn't clear enough articulating my situation and objective

@IrfanLatif Great answer. It works as expected, but it doesn't seem I'm able to unmount a mount I make this way. The original mount command creates the three mounts in /mnt/runtime along with two duplicate mounts in /storage/emulated/0. umount called on these directories returns no errors, but trying to re-mount to the same directory later doesn't propagate to non-root namespaces. SELinux is set to permissive. Only thing that fixes it is a reboot of the tablet. Using LineageOS 16.0 (Android 9) with Magisk.

This is for an in-car tablet with OTG storage via permanently-mounted USB hub. When powered-off and back on, the OTG storage needs to be unmounted and then remounted, since the device gets re-probed (i.e. /dev/block/sdb1 will disappear on loss of power, and then when power is applied, it will appear again as /dev/block/sdc1).

@IrfanLatif I made a question here... I'd greatly appreciate any input you can provide: https://android.stackexchange.com/questions/230436/how-to-properly-propagate-unmounting-of-usb-otg-storage-to-all-mount-namespaces

@IrfanLatif How do you build the bindfs?

@Jtnqr using GCC.

@IrfanLatif I compiled bindfs   and it does seem to atleast execute with whatever options you have shown. I am on Android 10. Unfortunately after trying each and every option with various user id and group ID's and mounting options..... I am still not able to get right access to the target folder which is actually the WhatsApp folder. in light of this can you please modify your  answer for Android 10 or else maybe del it ✌

@IrfanLatif :  just to update. With  bindfs  I can  as much as re-name with non root  privs. But creating  folders is a NO.  Any combination  .Here is my context for the target u:object_r:media_rw_data_file:s0  so why is that no Folders cant be created .  I see something like an untrusted process app is accessing media_rw . But that 's happening with your bindfs e.g.  as well. Any ts-shooting help wd be appreciated ✌

Android 11+
On my Android 13 phone (but released with Android 11), the above answer by @IrfanLatif no longer works. SDCardFS has been deprecated is/will be replaced by a FUSE filesystem by MediaProvider.
My phone's primary internal storage has its physical storage at /data/media/0, then there is an sdcardfs filesystem on top of that, and a FUSE filesystem (provided by MediaProvider) on top of the sdcardfs. The FUSE fs is the one that is visible to apps. See my addition to @IrfanLatif's Android storage journey for details.
My phone also has a microSD slot, and I wanted to encrypt my sd card (without using adoptable storage). I'll leave the details of the encryption to another answer, but I ended up creating a LUKS partition with an F2FS filesystem inside.
I first tried mounting the encrypted partition on a subdirectory of /data/media/0, that doesn't work because sdcardfs doesn't accept mounts of other devices on its source tree, and returns an "Invalid cross-device link" error. Then I tried mounting on top of the sdcardfs at /mnt/runtime/write/emulated/0/cryptcard, following @IrfanLatif's answer. While it is possible to mount there (and on the other paths at /mnt/runtime/*), doing so doesn't make the new filesystem show up under /sdcard (or the equivalent /storage/emulated/0), /sdcard ignores the mount as if it didn't happen.
After some digging, it turned out that MediaProvider's FUSE filesystem doesn't read from /mnt/runtime/*, instead it has its own mount of the sdcardfs under /storage/emulated/0, in a private mount namespace. So mounting in the master mount namespace didn't affect it.
Mount under MediaProvider
First you need to identify the PID of MediaProvider, so you can access its mount namespace. On my device it uses a command line of rs.media.module, so pgrep rs.media.module gives the PID. The command line name is probably not going to change across Android distributions, but if it does, you can find all processes that implement FUSE mounts using lsof /dev/fuse. That should narrow down your search, and probably there is only one process.
Once you know MediaProvider's PID, you need to be able to enter its mount namespace. For that you either need nsenter or a mount which supports the -N switch.
To put it all together:
Create a mount target folder:
mkdir /storage/emulated/0/myfilesystem

Mount your device to the mount point:
nsenter -m -t `pgrep rs.media.module` -- mount /dev/block/my_device /storage/emulated/0/myfilesystem

or
mount -N `pgrep rs.media.module` /dev/block/my_device /storage/emulated/0/myfilesystem

The necessary tools (pgrep, lsof, nsenter, mount) can all be installed through Termux if your Android doesn't include them.
Mounting an SDCardFS
To get the same permissions/features/etc I wanted to recreate the same stack as my Android uses. The physical storage I wanted to mount was an F2FS filesystem. For details of the encryption, see my answer to this question.
Because SDCardFS doesn't allow unprivileged users to read its root directory, I made a subfolder on my f2fs filesystem which is what will actually get mounted. For some details about SDCardFS, see this question.
First I made a working directory at /data/root to put some intermediate mounts. NB: on devices using FBE (file based encryption), such a directory is not encrypted!
Then I made subdirectories /data/root/cryptcard and data/root/cryptcard-sdcardfs
Mounting under /data/root should happen in the master mount namespace. If you use Magisk root, you can enter it with su -M. For other root apps, check their docs.
I mount the f2fs filesystem on /data/root/cryptcard:
mount -t f2fs /dev/block/my_device /data/root/cryptcard

If it does not exist yet, create a subdirectory on the device:
mkdir /data/root/cryptcard/mountdir

I am trying to duplicate the stack that my Android uses for its emulated primary external storage, so give the mountdir the same owner, group, permissions and security context as is used on the physical storage of your primary external storage. Owner, group and security context are not strictly necessary as sdcardfs ignores them.
Then we want to create an sdcardfs with the same options as the primary internal storage uses (which also uses the f2fs filesystem containing /data as backing storage). To see its mount options, run
findmnt -N `pgrep rs.media.module` -u /storage/emulated

Then mount an sdcardfs with the same options to /data/root/cryptcard-sdcardfs:
mount -t sdcardfs -o options_from_above_go_here /data/root/cryptcard /data/root/cryptcard-sdcardfs

The above two mounts should also be visible in MediaProvider's mount namespace. You can check that with
findmnt -N `pgrep rs.media.module` -R /data/root

If they don't show up, you could try making those mounts explicitly in MediaProvider's mount namespace.
Finally, bind-mount the subdirectory we want to use to MediaProvider's source tree:
mount -N `pgrep rs.media.module` --bind /data/root/cryptcard-sdcardfs/mountdir /storage/emulated/0/myfilesystem

The filesystem should now be visible under /sdcard/myfilesystem to your shell and your apps.

How to find out where MediaProvider reads from
I expect that MediaProvider keeps reading from /storage/emulated as its source. But if that stops working, here's how to find where MediaProvider reads from.
In one shell session, strace your MediaProvider:
strace -fp `pgrep rs.media.module`

This shows all the system calls that it makes, so make sure your Android is quiet when you try this.
Then, in another shell, do
stat /sdcard/Documents/some_file_that_exists

This should produce output from strace in the first shell, something like
[pid 30441] <... splice resumed> )      = 53
[pid 30441] read(93, "5\0\0\0\1\0\0\0qa/\0\0\0\0\0\320\213a\314s\0\0\264\314'\0\0\314'\0\0"..., 53) = 53
[pid 30441] write(2, "unique: 3105137, opcode: LOOKUP "..., 115) = 115
[pid 30441] newfstatat(AT_FDCWD, "/storage/emulated/0/Documents/some_file_that_exists", {st_mode=S_IFDIR|0770, st_size=3452, ...}, AT_SYMLINK_NOFOLLOW) = 0
[pid 30441] write(2, "   unique: 3105137, success, out"..., 42) = 42
[pid 30441] writev(90, [{iov_base="\220\0\0\0\0\0\0\0qa/\0\0\0\0\0", iov_len=16}, {iov_base="\20\0_\314s\0\0\264\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\377\377\377\377\377\377\377"..., iov_len=128}], 2) = 144
[pid 30441] splice(90, NULL, 122, NULL, 135168, 0 <unfinished ...>

This is one MediaProvider thread waking up, reading from /dev/fuse, doing the newfstatat system call, sending its response back, and going back to sleep. With some logging interspersed. The interesting part is the newfstatat(AT_FDCWD, "/storage/emulated/0/Documents/some_file_that_exists", system call, which shows us the path MediaProvider is reading from (within its own mount namespace), and where our mount should be created.
Again, the tools (findmnt, strace, stat) are available in Termux.


text:
How to mount NFS on Android with correct permissions?
I am trying to mount an NFS share on my Android phone.
I have already compiled and installed all the needed kernel modules. The NFS share mounts flawlessly but I can only mount as the system user.
This wouldn't be an issue if I could set the correct ownership for the mounted file system.
The problem is that the share is always mounted as user=system and group=system, making it inaccessible to regular apps.
I would like to be able to specify the ownership of the mounted filesystem at mount time.
This is how I mount the NFS share
su -c "busybox mount -o nosuid,nolock,nodev,rw,nofail,noatime,intr,tcp,actimeo=1800,context=u:object_r:rootfs:s0,user -t nfs $REMOTE_URI $LOCAL_DIRECTORY"

where REMOTE_URI is the remote location and LOCAL_DIRECTORY is the local directory. The above command is inside a script.
This is the relevant line of the /etc/exports file on the NFS server (a raspberry pi 3)
/media/neo/BLACKBOX XXX.XXX.XXX.XXX/0(rw,insecure,sync,no_root_squash,no_subtree_check,anonuid=1000,anongid=1000)

System Specs:

LG V20 H990DS
System - V10i-TWN (6th-Nov-17) 7.0 Stock, Rooted & Xposed
Kernel - D.O.T.S. v1.4
NFS version 4

PS: The UID and GID on the server are 1000 and 1000 respectively. In Android those are reserved for the system user and group. All my other computers have UID and GID 1000 and the same username neo. It would be much easier to just modify how Android mount the share. I would like to map uid=neo(1000)->root(0) and guid=neo(1000)->sdcard_r(1028) where neo:neo is the user on the server and root:sdcard_r is the user on the phone.

Let us continue this discussion in chat.

I would like to map uid=neo(1000)->root(0) and guid=neo(1000)->sdcard_r(1028) where neo:neo is the user on the server and root:sdcard_r is the user on the phone.

Files ownership root:sdcard_r (0:1028) on Android won't work for apps. It should be root:everybody (0:9997) with mode 0770 for directories and 0660 for files.
HOW TO MAKE NFS WORK WITH ANDROID APPS?
Traditional *NIX DAC (UIDs/GIDs) was designed to isolate human users, not programs. On Android devices - meant for one human user usually - apps need to be isolated and protected so that they can't access each other's data. So Android treats every app like a human user - with a unique UID/GID.
External storage (/sdcard) - whether physically external or internal - is meant to be shared by all apps i.e. multiple UIDs. If it's a traditional *NIX filesystem (like ext4), every app would create files with its own UID/GID which makes it nearly impossible to share files among all apps with read/write access. To come up with a solution, Android opted emulated filesystem - based on FUSE or sdcardfs - with fixed ownership and mode. See details in What is the “u#_everybody” UID?
These UIDs/GIDs and modes also control apps' access to files in /sdcard. So if we want to mount NFS to be accessible by all apps, we need to mitigate these permissions according to Android's storage design.
PLAIN UNIX SECURITY ON NFS:
sec=sys mode enforces UNIX permissions without any translation. As explained in previous section, files would be created with random ownership by different apps. So those have to be readable/writable by world (o+rw), otherwise apps won't be able to read/write. But there is no way to enforce file creation mode globally, neither it's a good idea to share files with too open permissions. A possible solution is to use ID mapping and/or anonymous mode.
NFSv4 ID MAPPING:
With NFSv4 it's possible to map different UIDs/GIDs between client and server. If a user with same name but different UIDs/GIDs exists on both sides, files on client look owned by the same user name, not same UID. Linux key-management facility * is used to store mappings of remote user IDs to local user IDs. A good explanation can be found here.
So the idea is to create user:group neo:neo on NFS server (1000:1000) and on Android (0:9997). For this, rpc.idmapd needs to be running on both server and client which queries user database (/etc/{passwd,group} in simplest case) through NSS.  On more recent kernels the NFSv4 client instead uses nfsidmap, and only falls back to rpc.idmapd if there was a problem running the nfsidmap. Kernel calls /sbin/request-key binary in userspace which executes nfsidmap to query users database. So the kernel would map server's neo (1000:1000) to client's neo (0:9997).
In simple case, if UID/GID range 10000 to 19999 is not assigned to any user/group on NFS server and Nobody-User = root/Nobody-Group = everybody is defined in /etc/idmapd.conf on client, all files (created by Android apps) owned by non-existent users on server would be returned as owned by 0:9997 on client. But it doesn't resolve the problem of random ownership of files on server.
Running rpc.idmapd or providing nfsidmap on Android is a complicated task (static linking and all that). However - making use of keyutils (request-key and keyctl) - we can trick kernel to show fixed ownership 0:9997 for all mappings regardless of what the actual ownership is:
On NFS server:

Run services:
~# mount -t nfsd nfsd /proc/fs/nfsd
~# rpc.mountd -g -N2 -N3 -N4 -N4.1 -N4.2 -p 4000
~# rpc.nfsd -N2 -N3 -N4 -N4.1 -N4.2 -U --p 2049 4
~# mkdir -p /run/rpc_pipefs
~# mount -t rpc_pipefs sunrpc /run/rpc_pipefs
~# rpc.idmapd -S -p /run/rpc_pipefs
~# echo -n N >/sys/module/nfsd/parameters/nfs4_disable_idmapping
~# exportfs -o rw,insecure,hide,no_subtree_check,sec=sys <CLIENT_IP>:/SHARED_DIR

Or configure and run required init services. Also unblock ports though firewall on client and server.

On Android:

Create /sbin/nfsidmap_pseudo and /etc/request-key.conf:
#!/system/bin/sh

uid=0
gid=9997

case $2 in
    uid:*)
        printf '%s\0' "$uid" | /sbin/keyctl pinstantiate $1 0 ;;
    gid:*)
        printf '%s\0' "$gid" | /sbin/keyctl pinstantiate $1 0 ;;
    *)
        # won't do anything to "user" or "group" types
        exit 1 ;;
esac

# /etc/request-key.conf
create  id_resolver  *  *  /sbin/nfsidmap_pseudo  %k  %d

Place files, set permissions and enable ID mapping::
~# chmod 0755 /sbin/request-key /sbin/nfsidmap_pseudo /sbin/keyctl
~# chmod 0644 /etc/request-key.conf
~# chown 0.0 /sbin/request-key /sbin/nfsidmap_pseudo /sbin/keyctl /etc/request-key.conf
~# chcon u:object_r:rootfs:s0 /sbin/request-key /sbin/nfsidmap_pseudo /sbin/keyctl
~# chcon u:object_r:system_file:s0 /etc/request-key.conf
~# echo -n N >/sys/module/nfs/parameters/nfs4_disable_idmapping

Since NFS isn't supported officially on Android, SELinux policy doesn't have required rules. You may need to set SELinux permissive or allow kernel to read/write keys, execute files in userspace and make connections:
~# supolicy --live 'allow kernel kernel key { search write view read }'
~# supolicy --live 'allow kernel kernel capability { net_raw net_bind_service sys_admin }'
~# supolicy --live 'allow kernel { rootfs shell_exec system_file } file { execute_no_trans execute open getattr }'

Mount:
~# mkdir -p /sdcard/NFS
~# busybox mount -v -t nfs4 -o vers=4.2,sec=sys,rw,tcp,port=2049,context=u:object_r:sdcardfs:s0 <SERVER_IP>:/SHARED_DIR /mnt/runtime/write/emulated/0/NFS

Unfortunately what we get from all this setup is that now apps apparently see files in /sdcard/NFS owned by 0:9997. But with sec=sys security, actual file access is not governed by NFSv4 UID Mapping **. Permissions are enforced by RPC mechanism which is not yet ready to work with ID mapping. So UID Mapping without Kerberos security works only if user/group name and number spaces are consistent between the client and server. It means that neo user on server should have UID/GID: 0/9997 (which nullifies the whole purpose of ID mapping). On the other hand Kerberos security (sec=krb5) is too hectic to be tried on Android.
Similarly file locking on NFSv2/3 requires portmapper (rpcbind) and rpc.statd running on server and client both, which is not the case with Android client. So, we need to use nolock mount option. On NFSv4, however, locking is built-in NFS protocol, NLM isn't needed. So better is to not go for UID Mapping (on NFSv4, and File Locking on NFSv2/3). If you need all NFS features (including Kerberos) working on Android device, rather try a tiny Linux distro in chroot.

* On kernel older than v4.6, /proc/keys is exposed if kernel is built with KEYS_DEBUG_PROC_KEYS.
** References: 1, 2, 3, 4, 5, 6

NFS ANONYMOUS ACCESS:
One of NFS security flavors is anonymous mode. Every request from any UID/GID on client is treated as the anonymous UID/GID on server. Initially all files in shared directory must be owned by this UID/GID and all subsequently created files from client side would also have the same ownership:
Export share with sec=none on server:
~# exportfs -o rw,insecure,no_subtree_check,anonuid=1000,anongid=1000,sec=none,root_squash,all_squash <CLIENT_IP>:/SHARED_DIR
~# chown -R 1000.1000 /SHARED_DIR; chmod 0700 /SHARED_SIR

* For NFSv2/3 also run rpcbind (on default port 111)
Mount with sec=none On Android:
~# busybox mount -v -t nfs4 -o vers=4.2,sec=none,rw,tcp,port=2049,context=u:object_r:sdcardfs:s0 <SERVER_IP>:/SHARED_DIR /mnt/runtime/write/emulated/0/NFS

* Use -t and vers= according to your kernel build configuration CONFIG_NFS_V[2|3|4|4_1|4_2].
* Use -t nfs -o nolock with vers=3 or vers=2.
* Make sure you are mounting from root mount namespace.
* Mounting with sec=none doesn't work with NFSv3.

All apps on Android can now read and write to NFS directory and all files are created with single anonymous UID/GID on server, easy to manage by a user. However apparent ownership (if ID mapping not setup) and permission mode is not according to Android's flavor, so...
TRY IT THE ANDROID WAY...
Let's make use of FUSE or sdcardfs as Android does:
~# mkdir -p /mnt/NFS /sdcard/NFS
~# busybox mount -v -t nfs4 -o vers=4.2,sec=none,rw,tcp,port=2049,context=u:object_r:sdcardfs:s0 <SERVER_IP>:/SHARED_DIR /mnt/NFS
~# mount -t sdcardfs -o nosuid,nodev,noexec,noatime,mask=7,gid=9997 /mnt/NFS /mnt/runtime/write/emulated/0/NFS

If your device doesn't support sdcardfs, use bindfs and replace SELinux context u:object_r:sdcardfs:s0 with u:object_r:fuse:s0:
~# bindfs -o nosuid,nodev,noexec,noatime,context=u:object_r:fuse:s0 -u 0 -g 9997 -p a-rwx,ug+rw,ugo+X --xattr-none --chown-ignore --chgrp-ignore --chmod-ignore /mnt/NFS /mnt/runtime/write/emulated/0/NFS

It leaves us with no remaining problems. For more details see How to bind mount a folder inside /sdcard with correct permissions?
GIVE CIFS A CHANCE...
NFS being Linux's native filesystem (like ext4) is meant to enforce *NIX permissions. Non-native filesystems like FAT and CIFS let fixed ownership and permissions be set across whole filesystem. So what you are looking for is relatively easy to achieve with CIFS:
~# mkdir -p /sdcard/CIFS
~# busybox mount -v -t cifs -o vers=3.0,nosuid,nodev,noexec,noatime,rw,hard,context=u:object_r:sdcardfs:s0,nounix,uid=0,gid=9997,file_mode=0660,dir_mode=0770,nouser_xattr,port=445,username=USERNAME,password=PASSWORD //<SERVER_IP>/SHARED_DIR /mnt/runtime/write/emulated/0/CIFS

* Kernel must be built with CONFIG_CIFS and preferably CONFIG_CIFS_SMB2, use vers= accordingly.
* For mount options detail see mount.cifs(8)

OTHER OPTIONS?
Other FUSE-based mountable filesystems are sshfs and rclone. Latter offers a large range of protocols and configurations while requiring a very simple setup.

Love the detailed explanation of the fundamentals that affect this. Thank you so much!

@polynomial I'm glad it helped.

It seems that every distribution of Busybox that is on Google Play is not compatible with NFSv4 but only NFSv3. So I gave up the idea of using idmapd on Android.

Instead, I changed the UID and GID on the NFS server to 4444 so that they don't correspond to the system user anymore.
Then I created a new user on Busybox with the same name, UID, and GID as the server (In my Busybox distribution the adduser and addgroup utilities are included).
I have purchased Tasker and downloaded this set of tasks from the XDA forum.
I have chosen the /mnt/nfs directory to mount the share.

I have no time to investigate which of the previous points is necessary and which is only irrelevant or optional. If you have any idea please write it in a comment.


text:
Extract DB from accidentally formatted /data
I had to factory reset my Samsung Galaxy Note i717 (1stGen AT&T), and I forgot to backup before formatting /data.
I need to extract the messages DB from it, because I have many important messages from my phone that I require.
So far, I have (after rebooting into CWM):
$ adb shell mount
rootfs on / type rootfs (rw)
tmpfs on /dev type tmpfs (rw,nosuid,relatime,mode=755)
devpts on /dev/pts type devpts (rw,relatime,mode=600)
proc on /proc type proc (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
/dev/block/mmcblk0p26 on /cache type ext4 (rw,nodev,noatime,nodiratime,user_xattr,acl,barrier=1,data=ordered)
/dev/block/mmcblk1p1 on /external_sd type vfat (rw,nodev,noatime,nodiratime,fmask=0000,dmask=0000,allow_utime=0022,codepage=cp437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro)
/dev/block/mmcblk0p28 on /sdcard type vfat (rw,nodev,noatime,nodiratime,fmask=0000,dmask=0000,allow_utime=0022,codepage=cp437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro)
/dev/block/mmcblk0p25 on /data type ext4 (rw,nodev,noatime,nodiratime,user_xattr,acl,barrier=1,data=ordered)

Then I unmounted data from CWM, and then:
$ adb shell dd if=/dev/block/mmcblk0p25 of=/external_sd/data.backup bs=4M
512+1 records in
512+1 records out
2149580800 bytes (2.0GB) copied, 226.108215 seconds, 9.1MB/s

$ adb shell ls -l /external_sd
drwxrwxrwx    3 root     root         16384 Mar 18  2013 2
drwxrwxrwx    3 root     root         16384 Apr 20  2013 Android
drwxrwxrwx    3 root     root         16384 Dec 14  2012 DCIM
drwxrwxrwx    2 root     root         16384 Mar 20  2013 DriveDroid
drwxrwxrwx    2 root     root         16384 Dec  5  2012 LOST.DIR
drwxrwxrwx    2 root     root        360448 May  1  2013 TitaniumBackup
drwxrwxrwx    3 root     root         16384 Dec 16  2012 clockworkmod
-rwxrwxrwx    1 root     root     173194344 Apr 25  2013 cm-10.1-20130411-EXPERIMENTAL-quincyatt-M3.zip
drwxrwxrwx    3 root     root         16384 Dec  5  2012 data
-rwxrwxrwx    1 root     root     2149580800 Nov 14 10:43 data.backup
drwxrwxrwx    3 root     root         16384 Dec 22  2012 media
-rwxrwxrwx    1 root     root        102400 Apr  8  2013 mmssms.db
-rwxrwxrwx    1 root     root       7686144 Feb 16  2013 recovery.img

Next I DL'ed the backup file to my computer:
$ adb pull /external_sd/data.backup
8224 KB/s (2149580800 bytes in 255.223s)

$ ls -l
total 2099204
-rw-r--r-- 1 haneefmubarak haneefmubarak 2149580800 Nov 14 02:56 data.backup

So now what I have is an image of my /data partition (ext4). How can I file-carve for the messages (SMS) DB file? I have a nandroid copy from a while back that has some of my old messages (I set my SMS to never delete), would that help?
Model: SGH-I717
Manu.: Samsung
Carrier: AT&T
ROM: CM 10.2
AOSP: v4.2 Jelly Bean
code: quincyatt

I recommend you taking a look into our data-recovery tag-wiki, which explicitly mentions file carving and gives a few references.

@Izzy Well, this question isn't about how to generically file-carve, but rather on how to file-carve for Android DB files, especially Android SMS DBs.