Skip to content

Commit d2a8e32

Browse files
committed
feat(props): adopt resetprop-rs library and defer to ZeroMount
Replaces subprocess-based resetprop/getprop with PropSystem library API. Adds zeromount detection — when meta-zeromount module is active and not disabled, overlapping boot/vbmeta props are skipped to avoid double-spoofing. Fixes 4 pre-existing prop coverage gaps (missing ro.bootimage.build.tags, ro.boot.verifiedbooterror, ro.boot.veritymode.managed, ro.is_ever_orange) and aligns avb_version to 1.3. Expands RECOVERY_PROPS from 3 to 6 entries.
1 parent ddf98fa commit d2a8e32

9 files changed

Lines changed: 191 additions & 156 deletions

File tree

prop.sh

Lines changed: 87 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ MODDIR="$MODPATH"
99
_PROP_SPOOF_COUNT=0
1010
_PROP_FAIL_COUNT=0
1111

12+
_ZEROMOUNT_ACTIVE=false
13+
_zm_dir="/data/adb/modules/meta-zeromount"
14+
if [ -d "$_zm_dir" ] && [ ! -f "$_zm_dir/disable" ] && [ ! -f "$_zm_dir/remove" ]; then
15+
_ZEROMOUNT_ACTIVE=true
16+
_log "INFO" "ZeroMount active — deferring overlapping props"
17+
fi
18+
1219
ensure_prop() {
1320
NAME=$1
1421
NEWVAL=$2
@@ -28,34 +35,34 @@ if ! resetprop -w sys.boot_completed 0 2>/dev/null; then
2835
_log "WARN" "resetprop -w sys.boot_completed timeout or failure"
2936
fi
3037

31-
# Core boot verification props
32-
check_reset_prop "ro.boot.vbmeta.device_state" "locked"
33-
check_reset_prop "ro.boot.verifiedbootstate" "green"
34-
check_reset_prop "ro.boot.flash.locked" "1"
35-
check_reset_prop "ro.boot.veritymode" "enforcing"
36-
check_reset_prop "ro.boot.warranty_bit" "0"
37-
check_reset_prop "ro.warranty_bit" "0"
38-
check_reset_prop "ro.debuggable" "0"
39-
check_reset_prop "ro.force.debuggable" "0"
40-
check_reset_prop "ro.secure" "1"
41-
check_reset_prop "ro.adb.secure" "1"
42-
check_reset_prop "ro.build.type" "user"
43-
check_reset_prop "ro.build.tags" "release-keys"
44-
check_reset_prop "ro.vendor.boot.warranty_bit" "0"
45-
check_reset_prop "ro.vendor.warranty_bit" "0"
46-
check_reset_prop "vendor.boot.vbmeta.device_state" "locked"
47-
check_reset_prop "vendor.boot.verifiedbootstate" "green"
48-
check_reset_prop "sys.oem_unlock_allowed" "0"
49-
50-
# MIUI specific
51-
check_reset_prop "ro.secureboot.lockstate" "locked"
52-
53-
# Realme specific
54-
check_reset_prop "ro.boot.realmebootstate" "green"
55-
check_reset_prop "ro.boot.realme.lockstate" "1"
56-
57-
check_reset_prop "ro.crypto.state" "encrypted"
58-
check_reset_prop "ro.is_ever_orange" "0"
38+
if [ "$_ZEROMOUNT_ACTIVE" != "true" ]; then
39+
check_reset_prop "ro.boot.vbmeta.device_state" "locked"
40+
check_reset_prop "ro.boot.verifiedbootstate" "green"
41+
check_reset_prop "ro.boot.flash.locked" "1"
42+
check_reset_prop "ro.boot.veritymode" "enforcing"
43+
check_reset_prop "ro.boot.warranty_bit" "0"
44+
check_reset_prop "ro.warranty_bit" "0"
45+
check_reset_prop "ro.debuggable" "0"
46+
check_reset_prop "ro.force.debuggable" "0"
47+
check_reset_prop "ro.secure" "1"
48+
check_reset_prop "ro.adb.secure" "1"
49+
check_reset_prop "ro.build.type" "user"
50+
check_reset_prop "ro.build.tags" "release-keys"
51+
check_reset_prop "ro.vendor.boot.warranty_bit" "0"
52+
check_reset_prop "ro.vendor.warranty_bit" "0"
53+
check_reset_prop "vendor.boot.vbmeta.device_state" "locked"
54+
check_reset_prop "vendor.boot.verifiedbootstate" "green"
55+
check_reset_prop "sys.oem_unlock_allowed" "0"
56+
57+
check_reset_prop "ro.secureboot.lockstate" "locked"
58+
59+
check_reset_prop "ro.boot.realmebootstate" "green"
60+
check_reset_prop "ro.boot.realme.lockstate" "1"
61+
62+
check_reset_prop "ro.crypto.state" "encrypted"
63+
check_reset_prop "ro.is_ever_orange" "0"
64+
fi
65+
5966
check_reset_prop "ro.oem_unlock_supported" "0"
6067
check_reset_prop "ro.secureboot.devicelock" "1"
6168

@@ -72,14 +79,16 @@ if [ "$_region_enabled" = "true" ]; then
7279
[ -n "$_cfg_hw_sku" ] && check_reset_prop "ro.boot.product.hardware.sku" "$_cfg_hw_sku"
7380
fi
7481

75-
# Delete qemu property entirely -- some detectors check existence, not value
76-
if [ -n "$(resetprop ro.kernel.qemu)" ]; then
77-
if resetprop --delete ro.kernel.qemu 2>/dev/null; then
78-
_PROP_SPOOF_COUNT=$((_PROP_SPOOF_COUNT + 1))
79-
else
80-
resetprop -n ro.kernel.qemu "" 2>/dev/null
81-
_PROP_FAIL_COUNT=$((_PROP_FAIL_COUNT + 1))
82-
_log "WARN" "Could not delete ro.kernel.qemu, blanked instead"
82+
if [ "$_ZEROMOUNT_ACTIVE" != "true" ]; then
83+
# Delete qemu property entirely -- some detectors check existence, not value
84+
if [ -n "$(resetprop ro.kernel.qemu)" ]; then
85+
if resetprop --delete ro.kernel.qemu 2>/dev/null; then
86+
_PROP_SPOOF_COUNT=$((_PROP_SPOOF_COUNT + 1))
87+
else
88+
resetprop -n ro.kernel.qemu "" 2>/dev/null
89+
_PROP_FAIL_COUNT=$((_PROP_FAIL_COUNT + 1))
90+
_log "WARN" "Could not delete ro.kernel.qemu, blanked instead"
91+
fi
8392
fi
8493
fi
8594

@@ -91,49 +100,49 @@ contains_reset_prop "vendor.bootmode" "recovery" "unknown"
91100
contains_reset_prop "vendor.boot.bootmode" "recovery" "unknown"
92101
contains_reset_prop "vendor.boot.mode" "recovery" "unknown"
93102

94-
# VBMeta digest — prefer TEESimulator's persisted value, fall back to ours
95-
_hash_src=""
96-
hash_value=""
97-
if [ -f "$TS_DIR/boot_hash.bin" ]; then
98-
hash_value=$(od -A n -t x1 "$TS_DIR/boot_hash.bin" 2>/dev/null | tr -d ' \n')
99-
[ -n "$hash_value" ] && _hash_src="teesim"
100-
fi
101-
if [ -z "$hash_value" ] && [ -f "/data/adb/boot_hash" ]; then
102-
hash_value=$(grep -v '^#' "/data/adb/boot_hash" 2>/dev/null | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')
103-
[ -n "$hash_value" ] && _hash_src="boot_hash"
104-
fi
105-
if echo "$hash_value" | grep -qE '^[a-f0-9]{64}$'; then
106-
if resetprop -n ro.boot.vbmeta.digest "$hash_value" 2>/dev/null; then
107-
_PROP_SPOOF_COUNT=$((_PROP_SPOOF_COUNT + 1))
108-
_log "INFO" "VBMeta digest set from $_hash_src: $(printf '%.16s' "$hash_value")..."
109-
else
110-
_PROP_FAIL_COUNT=$((_PROP_FAIL_COUNT + 1))
111-
_log "ERROR" "Failed to set vbmeta.digest from $_hash_src"
103+
if [ "$_ZEROMOUNT_ACTIVE" != "true" ]; then
104+
# VBMeta digest — prefer TEESimulator's persisted value, fall back to ours
105+
_hash_src=""
106+
hash_value=""
107+
if [ -f "$TS_DIR/boot_hash.bin" ]; then
108+
hash_value=$(od -A n -t x1 "$TS_DIR/boot_hash.bin" 2>/dev/null | tr -d ' \n')
109+
[ -n "$hash_value" ] && _hash_src="teesim"
112110
fi
113-
elif [ -n "$hash_value" ]; then
114-
_log "WARN" "boot_hash invalid from $_hash_src (not 64-char hex)"
115-
fi
116-
117-
# VBMeta metadata props -- ensure they exist even if kernel didn't set them
118-
ensure_prop "ro.boot.vbmeta.device_state" "locked"
119-
ensure_prop "ro.boot.vbmeta.invalidate_on_error" "yes"
120-
ensure_prop "ro.boot.vbmeta.avb_version" "1.2"
121-
ensure_prop "ro.boot.vbmeta.hash_alg" "sha256"
122-
123-
# Dynamic vbmeta_size -- use partition byte size with A/B slot suffix + multi-path fallback
124-
slot_suffix=$(getprop ro.boot.slot_suffix 2>/dev/null)
125-
VBMETA_SIZE=""
126-
for candidate in \
127-
"/dev/block/by-name/vbmeta${slot_suffix}" \
128-
"/dev/block/by-name/vbmeta" \
129-
"/dev/block/by-name/vbmeta_a" \
130-
"/dev/block/by-name/vbmeta_b"; do
131-
if [ -b "$candidate" ]; then
132-
VBMETA_SIZE=$(blockdev --getsize64 "$candidate" 2>/dev/null)
133-
[ -n "$VBMETA_SIZE" ] && [ "$VBMETA_SIZE" -gt 0 ] 2>/dev/null && break
134-
VBMETA_SIZE=""
111+
if [ -z "$hash_value" ] && [ -f "/data/adb/boot_hash" ]; then
112+
hash_value=$(grep -v '^#' "/data/adb/boot_hash" 2>/dev/null | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')
113+
[ -n "$hash_value" ] && _hash_src="boot_hash"
114+
fi
115+
if echo "$hash_value" | grep -qE '^[a-f0-9]{64}$'; then
116+
if resetprop -n ro.boot.vbmeta.digest "$hash_value" 2>/dev/null; then
117+
_PROP_SPOOF_COUNT=$((_PROP_SPOOF_COUNT + 1))
118+
_log "INFO" "VBMeta digest set from $_hash_src: $(printf '%.16s' "$hash_value")..."
119+
else
120+
_PROP_FAIL_COUNT=$((_PROP_FAIL_COUNT + 1))
121+
_log "ERROR" "Failed to set vbmeta.digest from $_hash_src"
122+
fi
123+
elif [ -n "$hash_value" ]; then
124+
_log "WARN" "boot_hash invalid from $_hash_src (not 64-char hex)"
135125
fi
136-
done
137-
ensure_prop "ro.boot.vbmeta.size" "${VBMETA_SIZE:-4096}"
126+
127+
ensure_prop "ro.boot.vbmeta.device_state" "locked"
128+
ensure_prop "ro.boot.vbmeta.invalidate_on_error" "yes"
129+
ensure_prop "ro.boot.vbmeta.avb_version" "1.3"
130+
ensure_prop "ro.boot.vbmeta.hash_alg" "sha256"
131+
132+
slot_suffix=$(getprop ro.boot.slot_suffix 2>/dev/null)
133+
VBMETA_SIZE=""
134+
for candidate in \
135+
"/dev/block/by-name/vbmeta${slot_suffix}" \
136+
"/dev/block/by-name/vbmeta" \
137+
"/dev/block/by-name/vbmeta_a" \
138+
"/dev/block/by-name/vbmeta_b"; do
139+
if [ -b "$candidate" ]; then
140+
VBMETA_SIZE=$(blockdev --getsize64 "$candidate" 2>/dev/null)
141+
[ -n "$VBMETA_SIZE" ] && [ "$VBMETA_SIZE" -gt 0 ] 2>/dev/null && break
142+
VBMETA_SIZE=""
143+
fi
144+
done
145+
ensure_prop "ro.boot.vbmeta.size" "${VBMETA_SIZE:-4096}"
146+
fi
138147

139148
_log "INFO" "Property spoofing complete: $_PROP_SPOOF_COUNT spoofed, $_PROP_FAIL_COUNT failed"

rust/Cargo.lock

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ ring = "0.17"
2020
rcgen = { version = "0.12", default-features = false, features = ["pem", "ring"] }
2121
rsa = { version = "0.9", default-features = false, features = ["std", "pem"] }
2222
rand = "0.8"
23+
resetprop = { path = "/home/president/Git-repo-success/resetprop-rs/crates/resetprop" }
2324

2425
[profile.release]
2526
lto = true

rust/src/cli/handlers.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ pub fn dispatch(command: Commands, cfg: &Config) -> anyhow::Result<()> {
2424
println!("{}", read_version_from_prop());
2525
Ok(())
2626
}
27-
Commands::Props => crate::props::handle_props(cfg),
27+
Commands::Props => {
28+
let sys = resetprop::PropSystem::open()
29+
.map_err(|e| anyhow::anyhow!("property areas: {e}"))?;
30+
crate::props::handle_props(cfg, &sys)
31+
}
2832
Commands::Daemon { manager } => crate::daemon::handle_daemon(cfg, manager.as_deref()),
2933
Commands::DaemonStop => crate::daemon::handle_daemon_stop(),
3034
Commands::Config { action } => crate::config::handle_config(action, cfg),

rust/src/platform/props.rs

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,30 @@
11
use std::process::Command;
2+
use resetprop::PropSystem;
23

3-
pub fn getprop(name: &str) -> Option<String> {
4-
Command::new("getprop")
5-
.arg(name)
6-
.output()
7-
.ok()
8-
.and_then(|o| {
9-
let s = String::from_utf8_lossy(&o.stdout).trim().to_string();
10-
if s.is_empty() { None } else { Some(s) }
11-
})
4+
pub fn getprop(sys: &PropSystem, name: &str) -> Option<String> {
5+
sys.get(name)
126
}
137

14-
pub fn resetprop(name: &str, value: &str) -> anyhow::Result<()> {
15-
let status = Command::new("resetprop")
16-
.args(["-n", name, value])
17-
.status()?;
18-
if status.success() {
19-
Ok(())
20-
} else {
21-
anyhow::bail!("resetprop -n {name} {value} failed")
22-
}
8+
pub fn set(sys: &PropSystem, name: &str, value: &str) -> anyhow::Result<()> {
9+
sys.set(name, value).map_err(|e| anyhow::anyhow!("{e}"))
2310
}
2411

25-
pub fn resetprop_delete(name: &str) -> anyhow::Result<()> {
26-
let status = Command::new("resetprop")
27-
.args(["--delete", name])
28-
.status()?;
29-
if status.success() {
30-
Ok(())
31-
} else {
32-
anyhow::bail!("resetprop --delete {name} failed")
33-
}
12+
pub fn delete(sys: &PropSystem, name: &str) -> anyhow::Result<()> {
13+
sys.delete(name)?;
14+
Ok(())
15+
}
16+
17+
// One-off ops without an existing PropSystem — for callers outside the prop pipeline
18+
pub fn getprop_once(name: &str) -> Option<String> {
19+
PropSystem::open().ok()?.get(name)
20+
}
21+
22+
pub fn set_once(name: &str, value: &str) -> anyhow::Result<()> {
23+
let sys = PropSystem::open().map_err(|e| anyhow::anyhow!("{e}"))?;
24+
sys.set(name, value).map_err(|e| anyhow::anyhow!("{e}"))
3425
}
3526

27+
// No library equivalent — blocks until property reaches value
3628
pub fn resetprop_wait(name: &str, value: &str) -> anyhow::Result<()> {
3729
let status = Command::new("resetprop")
3830
.args(["-w", name, value])

0 commit comments

Comments
 (0)