Termux /proc on Android: What Works Without Root

Termux /proc on Android: What Works Without Root

TL;DR: Termux runs on a real Linux kernel, but Android's SELinux policy hides half of /proc from non-root apps: /proc/sys is locked, /proc/net has been blocked since Android 10, and /proc/stat, /proc/loadavg, /proc/uptime and /proc/vmstat are denied as side-channel leaks. What still works — /proc/meminfo, /proc/cpuinfo, /proc/pressure/*, /proc/self/* — is enough to build a solid pocket recon kit. This war story shows you exactly where the walls are and what to read instead.


Why does /proc on Termux show 128 GB RAM when your phone has 8 GB — and which other lies does the kernel tell you? The question stopped me cold at 21:40 on a Tuesday, staring at a loaner Redmi that had just reported double its physical RAM to a dumb little free -h.

It wasn't the phone's fault, and it wasn't Termux's. The kernel was telling the truth, in its own way — the way it always does when you read the wrong field. That night turned into a three-hour tour of every wall Android puts between a non-root shell and /proc. This is the map I wish I'd had: what lies, what's locked, and what the kernel still hands you for free.

The First Lie: MemTotal

Start with the number that started it all. On a 6 GB phone, free -h said 12 GB. The mechanism is documented and it's not a bug: Xiaomi, Realme and OPPO ship a "RAM expansion" feature that carves flash into swap and adds it to the kernel's reported MemTotal. The kernel doesn't know it's lying — it reports what it was told to report. A 6 GB phone reports 8 or 10 GB to the operating system, and the wilder forum screenshots are the same mechanism with a bigger shovel.

Read the file yourself and the lie becomes obvious:

termux
grep -E "MemTotal|MemAvailable|SwapTotal|SwapFree" /proc/meminfo

MemTotal is the marketing number. SwapTotal is the OEM's flash pretending to be RAM. Subtract the second from the first and you're back to physics. And MemAvailable is the only number that tells you whether the phone is actually hurting — Android reserves a serious chunk of RAM for the GPU, the modem and the DSP, so MemTotal was never yours to begin with.

termux
free -h

free reads /proc/meminfo directly, so it repeats the lie faithfully. First lesson of the night: tools don't lie, they just don't know better. Read the fields yourself.

Wrong Turn One: I Tried to Tune It

On a desktop, the fix for a memory problem is a knob. I reached for /proc/sys the way I'd done a thousand times on Ubuntu:

termux
cat /proc/sys/vm/swappiness

Permission denied. Not "file not found" — the file exists, the kernel is right there, and SELinux says no. /proc/sys is read-only for anything that isn't root or a system domain. sysctl -w fails the same way, and most Termux setups don't even ship sysctl. There is no tuning without root, full stop. I checked the SELinux angle, found the AOSP policy that labels these files and denies untrusted_app, and moved on. The wall is intentional and it's not coming down.

Wrong Turn Two: I Blamed proot

Next suspect: proot. I'd been running an Ubuntu container through proot-distro, and I was sure the weird /proc behavior was proot's fault. Wrong again. proot doesn't virtualize /proc at all — it passes the host's /proc straight through, then fakes the files Android blocks:

termux
proot-distro login ubuntu

Now, inside the distro:

ubuntu
cat /proc/loadavg

It works. Because it's fake. proot-distro binds generated files over the real ones — /proc/stat, /proc/loadavg, /proc/uptime, /proc/vmstat, even /proc/sys/fs/inotify/max_user_watches — so that ps, top and uptime don't crash. The numbers are real enough to keep tools alive, but they're not the phone's actual load. The giveaway: the value never changes. I watched it sit at the same number for an hour while the phone warmed up. That's when I stopped blaming tools and started reading the policy.

Wrong Turn Three: I Went Looking for Other Processes

Recon on a desktop starts with ps aux and a walk through /proc/PID. On Android, the /proc/PID directories of other apps are invisible — hidepid-style, enforced by SELinux rather than mount options. You can read your own process tree and nothing else. And the files that would describe the system as a whole are blocked as side-channel leaks. Google's own issue tracker calls the /proc/stat removal "intended behavior": one app shouldn't be able to infer what another app is doing from CPU counters.

Here's the full wall, as it stands on stock Android in 2026. Restrictions vary by version and ROM — Android 7 was wide open, 8 closed /proc/stat, 10 closed /proc/net:

FileIn Termux (non-root)Why
/proc/meminfoReadableApps need it for memory reporting
/proc/cpuinfoReadable on most devicesHardware info, low leak value
/proc/pressure/*Readable on most devicesPSI, used by Android's own lmkd
/proc/self/*ReadableYour own sandbox, fully mirrored
/proc/PID/* (other apps)Deniedhidepid-style SELinux
/proc/statDeniedSide-channel leak (Google: intended)
/proc/loadavg, /proc/uptime, /proc/version, /proc/vmstatDeniedSame side-channel reasoning
/proc/net/*Denied since Android 10Network metadata leak
/proc/sys/*Denied, read and writeKernel control
/proc/zoneinfoVaries by device and ROMproc_zoneinfo label, often denied

Root bypasses all of it, and so does a custom ROM with SELinux permissive. On stock, non-root, the table above is your world. Learn it, because it changes between Android versions and the tutorials that don't mention it will waste your evening.

The Catch: What the Kernel Still Gives You

The aha moment came when I stopped treating Android as broken Linux. It's a sandbox with a different threat model: the kernel tells you everything about your own cage and almost nothing about your neighbors. And your own cage is where you live.

The files that matter for mobile recon are all still there. /proc/pressure/memory is the big one — Pressure Stall Information, the same PSI that Android's own low-memory killer (lmkd) uses to decide when to start killing background apps:

termux
cat /proc/pressure/memory

The output has two averages per window: some (some tasks stalled) and full (everything stalled). If full climbs past 10 in the 10-second window, the phone is drowning and lmkd is about to start swinging. That's your early warning system, and it's world-readable on most devices because Android's init chmods it precisely so the system's own watchers can read it.

Uptime works too, just not from /proc/uptime. Termux's busybox reads the sysinfo() syscall instead, which SELinux can't block:

termux
busybox uptime

And the whole /proc/self tree is yours: /proc/self/status (your UID, your VmRSS), /proc/self/fd (your open file descriptors), /proc/self/cmdline. The kernel gives you a complete mirror of your own sandbox. For a pentester doing authorized recon on their own device, that's the whole ballgame. One more quirk worth knowing: Android runs cgroups v2, so the same pressure data also exists per-cgroup under /sys/fs/cgroup — but /sys is its own locked door for apps. /proc/pressure is the one that's open.

The Fix: A Pocket Recon Script

Here's what that night produced — a script that reads every file the kernel still hands a non-root Termux shell, with fallbacks for the ROMs that lock more than stock:

termux
cat > ~/proc-recon.sh <<'EOF'
#!/data/data/com.termux/files/usr/bin/bash
# proc-recon.sh — what the kernel tells a non-root Termux shell
echo "== uptime (sysinfo syscall, not /proc/uptime) =="
busybox uptime
echo "== memory: the honest numbers =="
grep -E "MemTotal|MemAvailable|SwapTotal|SwapFree" /proc/meminfo
echo "== memory pressure (PSI) =="
cat /proc/pressure/memory 2>/dev/null || echo "PSI blocked on this ROM"
echo "== cpu cores =="
grep -c ^processor /proc/cpuinfo 2>/dev/null || echo "cpuinfo blocked"
echo "== my sandbox =="
grep -E "Name|Pid|Uid|VmRSS" /proc/self/status
echo "== kernel build =="
cat /proc/version 2>/dev/null || echo "/proc/version blocked (SELinux)"
EOF
chmod +x ~/proc-recon.sh

Run it:

termux
bash ~/proc-recon.sh

⚠ Run this on your own phone, your own lab device, or hardware you're authorized to test. It's a recon script — the same pattern that maps a target's memory pressure and sandbox is exactly what you'd use in an assessment, so keep the authorization paperwork next to the phone.

The script answers the three questions that matter on a mobile target: is the device under memory pressure, how much RAM is real, and what does my sandbox look like. On the loaner Redmi, it took eleven seconds to expose the lie — 12 GB reported, 6 GB real, and a full PSI number that explained why the phone felt sluggish all week.

What I'd Do Differently

Three things. First: read MemAvailable before MemTotal, always — the marketing number ate my first hour. Second: check /proc/pressure/memory before blaming any app for a laggy phone; if full is high, the kernel is already fighting itself and no app is at fault. Third: keep the script on every phone I set up, because the walls move between Android versions and the script adapts faster than my memory does.

And for the gaps /proc can't fill: sensors, battery and wifi details live behind Android APIs, not procfs. That's what termux-api is for:

termux
termux-sensor -s accelerometer -n 1

termux-battery-status, termux-wifi-connectioninfo, termux-sensor — the API app reads what the kernel won't show and hands it to your shell. /proc plus termux-api covers the mobile recon surface without root.

Postscript — Oh, and One Thing We Almost Forgot

/proc/self is a symlink, and it's the cheapest trick on the box. Instead of hunting your PID with pgrep, just ask:

termux
readlink /proc/self

Your PID, instantly, in any shell, no parsing. Combine it with the fd directory and you can see what your own process has open:

termux
ls -l /proc/self/fd

On a phone where half of /proc sits behind a wall, the one directory that's always open is the one that describes you. Learn it first.

Go deeper: Termux on Android (Non-Root): Complete Setup Guide for the foundation this builds on · PCAP on Android Without Root: PCAPdroid vs. tcpdump in Termux for the network side of mobile recon · netcat (nc) in Termux: Usage & Examples for raw port checks from the same shell.