├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── build.bat
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── local.properties
├── module.gradle
├── module
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── cpp
│ ├── CMakeLists.txt
│ ├── external
│ ├── magiskhide
│ │ └── include
│ │ │ ├── hide_mount.hpp
│ │ │ ├── hide_prop.hpp
│ │ │ └── magisk.hpp
│ ├── systemproperties
│ │ ├── context_node.cpp
│ │ ├── contexts_serialized.cpp
│ │ ├── contexts_split.cpp
│ │ ├── include
│ │ │ ├── _system_properties.h
│ │ │ ├── async_safe
│ │ │ │ └── log.h
│ │ │ ├── private
│ │ │ │ ├── ErrnoRestorer.h
│ │ │ │ ├── bionic_defs.h
│ │ │ │ ├── bionic_futex.h
│ │ │ │ ├── bionic_lock.h
│ │ │ │ ├── bionic_macros.h
│ │ │ │ └── hacks.h
│ │ │ ├── property_info_parser
│ │ │ │ └── property_info_parser.h
│ │ │ ├── system_properties.h
│ │ │ └── system_properties
│ │ │ │ ├── context_node.h
│ │ │ │ ├── contexts.h
│ │ │ │ ├── contexts_pre_split.h
│ │ │ │ ├── contexts_serialized.h
│ │ │ │ ├── contexts_split.h
│ │ │ │ ├── prop_area.h
│ │ │ │ ├── prop_info.h
│ │ │ │ └── system_properties.h
│ │ ├── prop_area.cpp
│ │ ├── prop_info.cpp
│ │ ├── property_info_parser.cpp
│ │ ├── system_properties.cpp
│ │ ├── system_property_api.cpp
│ │ └── system_property_set.cpp
│ └── util.hpp
│ ├── log.hpp
│ ├── main.cpp
│ └── zygisk.hpp
├── out
├── magisk_module_release
│ ├── .gitattributes
│ ├── META-INF
│ │ └── com
│ │ │ └── google
│ │ │ └── android
│ │ │ ├── update-binary
│ │ │ ├── update-binary.sha256sum
│ │ │ ├── updater-script
│ │ │ └── updater-script.sha256sum
│ ├── README.md
│ ├── README.md.sha256sum
│ ├── customize.sh
│ ├── customize.sh.sha256sum
│ ├── lib
│ │ ├── arm64-v8a
│ │ │ ├── libhide.so
│ │ │ └── libhide.so.sha256sum
│ │ ├── armeabi-v7a
│ │ │ ├── libhide.so
│ │ │ └── libhide.so.sha256sum
│ │ ├── x86
│ │ │ ├── libhide.so
│ │ │ └── libhide.so.sha256sum
│ │ └── x86_64
│ │ │ ├── libhide.so
│ │ │ └── libhide.so.sha256sum
│ ├── module.prop
│ ├── module.prop.sha256sum
│ ├── service.sh
│ ├── service.sh.sha256sum
│ ├── uninstall.sh
│ ├── uninstall.sh.sha256sum
│ ├── verify.sh
│ └── verify.sh.sha256sum
└── zygisk-magiskhide-v1.0.1-release.zip
├── settings.gradle
└── template
└── magisk_module
├── .gitattributes
├── META-INF
└── com
│ └── google
│ └── android
│ ├── update-binary
│ └── updater-script
├── README.md
├── customize.sh
├── module.prop
├── service.sh
├── uninstall.sh
└── verify.sh
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 |
3 | *.bat text eol=crlf
4 | *.jar binary
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | .idea
4 | /.idea/caches/build_file_checksums.ser
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | .DS_Store
9 | /build
10 | /captures
11 | .externalNativeBuild
12 | .cxx
13 | build
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Shocker
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | MagiskHide in zygsik
2 |
3 | **https://pshocker.github.io/2022/07/30/Zygisk-MagiskHide/**
--------------------------------------------------------------------------------
/build.bat:
--------------------------------------------------------------------------------
1 | gradlew :module:assembleRelease
2 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'idea'
3 | }
4 |
5 | idea.module {
6 | excludeDirs += file('out')
7 | resourceDirs += file('template')
8 | resourceDirs += file('scripts')
9 | }
10 |
11 | ext {
12 | min_sdk = 23
13 | target_sdk = 31
14 |
15 | outDir = file("$rootDir/out")
16 | }
17 |
18 | task clean(type: Delete) {
19 | delete rootProject.buildDir, outDir
20 | }
21 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | # org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PShocker/Zygisk-MagiskHide/310b2236de31b7042d565ca73dcd6060247f20d0/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Jul 12 21:05:17 CST 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/local.properties:
--------------------------------------------------------------------------------
1 | ## This file must *NOT* be checked into Version Control Systems,
2 | # as it contains information specific to your local configuration.
3 | #
4 | # Location of the SDK. This is only used by Gradle.
5 | # For customization when using a Version Control System, please read the
6 | # header note.
7 | #Fri Mar 11 12:09:22 CST 2022
8 | sdk.dir=C\:\\Users\\Shocker\\AppData\\Local\\Android\\Sdk
9 |
--------------------------------------------------------------------------------
/module.gradle:
--------------------------------------------------------------------------------
1 | ext {
2 | /*
3 | This name will be used in the name of the so file ("lib${moduleLibraryName}.so").
4 | */
5 | moduleLibraryName = "hide"
6 | /*
7 | Magisk module ID
8 | Since Magisk use it to distinguish different modules, you should never change it.
9 |
10 | Note, the older version of the template uses '-' instead of '_', if your are upgrading from
11 | the older version, please pay attention.
12 | */
13 | magiskModuleId = "zygisk_magiskhide"
14 |
15 | moduleName = "Zygisk - Hide"
16 | moduleAuthor = "Shocker"
17 | moduleDescription = "MagiskHide in Zygisk"
18 | moduleVersion = "v1.0.1"
19 | moduleVersionCode = 26
20 | }
21 |
--------------------------------------------------------------------------------
/module/build.gradle:
--------------------------------------------------------------------------------
1 | import org.apache.tools.ant.filters.FixCrLfFilter
2 | import org.apache.tools.ant.filters.ReplaceTokens
3 |
4 | import java.security.MessageDigest
5 |
6 | plugins {
7 | id 'com.android.library'
8 | }
9 |
10 | apply from: file(rootProject.file('module.gradle'))
11 |
12 | android {
13 | compileSdk target_sdk
14 | defaultConfig {
15 | minSdk min_sdk
16 | targetSdk target_sdk
17 | externalNativeBuild {
18 | cmake {
19 | arguments "-DMODULE_NAME:STRING=$moduleLibraryName";
20 | }
21 | }
22 | }
23 | buildFeatures {
24 | prefab false
25 | }
26 | externalNativeBuild {
27 | cmake {
28 | path "src/main/cpp/CMakeLists.txt"
29 | version "3.20.3"
30 | }
31 | }
32 | ndkVersion '23.1.7779620'
33 | }
34 |
35 | afterEvaluate {
36 | android.libraryVariants.forEach { variant ->
37 | def variantCapped = variant.name.capitalize()
38 | def variantLowered = variant.name.toLowerCase()
39 |
40 | def zipName = "${magiskModuleId.replace('_', '-')}-${moduleVersion}-${variantLowered}.zip"
41 | def magiskDir = file("$outDir/magisk_module_$variantLowered")
42 |
43 | task("prepareMagiskFiles${variantCapped}", type: Sync) {
44 | dependsOn("assemble$variantCapped")
45 |
46 | def templatePath = "$rootDir/template/magisk_module"
47 |
48 | into magiskDir
49 | from(templatePath) {
50 | exclude 'module.prop'
51 | }
52 | from(templatePath) {
53 | include 'module.prop'
54 | expand([
55 | id : magiskModuleId,
56 | name : moduleName,
57 | version : moduleVersion,
58 | versionCode: moduleVersionCode.toString(),
59 | author : moduleAuthor,
60 | description: moduleDescription,
61 | ])
62 | filter(FixCrLfFilter.class,
63 | eol: FixCrLfFilter.CrLf.newInstance("lf"))
64 | }
65 | from("$buildDir/intermediates/stripped_native_libs/$variantLowered/out/lib") {
66 | into 'lib'
67 | }
68 | doLast {
69 | fileTree("$magiskDir").visit { f ->
70 | if (f.directory) return
71 | if (f.file.name == '.gitattributes') return
72 |
73 | def md = MessageDigest.getInstance("SHA-256")
74 | f.file.eachByte 4096, { bytes, size ->
75 | md.update(bytes, 0, size)
76 | }
77 | file(f.file.path + ".sha256sum").text = md.digest().encodeHex()
78 | }
79 | }
80 | }
81 |
82 | task("zip${variantCapped}", type: Zip) {
83 | dependsOn("prepareMagiskFiles${variantCapped}")
84 | from magiskDir
85 | archiveName zipName
86 | destinationDir outDir
87 | }
88 |
89 | task("push${variantCapped}", type: Exec) {
90 | dependsOn("zip${variantCapped}")
91 | workingDir outDir
92 | commandLine android.adbExecutable, "push", zipName, "/data/local/tmp/"
93 | }
94 |
95 | task("flash${variantCapped}", type: Exec) {
96 | dependsOn("push${variantCapped}")
97 | commandLine android.adbExecutable, "shell", "su", "-c",
98 | "magisk --install-module /data/local/tmp/${zipName}"
99 | }
100 |
101 | task("flashAndReboot${variantCapped}", type: Exec) {
102 | dependsOn("flash${variantCapped}")
103 | commandLine android.adbExecutable, "shell", "reboot"
104 | }
105 |
106 | variant.assembleProvider.get().finalizedBy("zip${variantCapped}")
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/module/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/module/src/main/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.4.1)
2 |
3 | if (NOT DEFINED MODULE_NAME)
4 | message(FATAL_ERROR "MODULE_NAME is not set")
5 | else ()
6 | project(${MODULE_NAME})
7 | endif ()
8 |
9 |
10 | message("Build type: ${CMAKE_BUILD_TYPE}")
11 |
12 | set(CMAKE_CXX_STANDARD 17)
13 |
14 | set(LINKER_FLAGS "-ffixed-x18 -Wl,--hash-style=both")
15 | set(C_FLAGS "-Werror=format -fdata-sections -ffunction-sections")
16 | set(CXX_FLAGS "${CXX_FLAGS} -fno-exceptions -fno-rtti")
17 |
18 | if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
19 | set(C_FLAGS "${C_FLAGS} -O2 -fvisibility=hidden -fvisibility-inlines-hidden")
20 | set(LINKER_FLAGS "${LINKER_FLAGS} -Wl,-exclude-libs,ALL -Wl,--gc-sections -Wl,--strip-all")
21 | else ()
22 | set(C_FLAGS "${C_FLAGS} -O0")
23 | endif ()
24 |
25 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS}")
26 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${C_FLAGS} ${CXX_FLAGS}")
27 |
28 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
29 | set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
30 |
31 | # find_package(REQUIRED CONFIG)
32 |
33 | include_directories(./)
34 | include_directories(./external/systemproperties/include)
35 | include_directories(./external/magiskhide/include)
36 | include_directories(./external/resetprop/include)
37 | include_directories(./external)
38 |
39 | ##################### ⬇CMake源文件设置⬇ #####################
40 | FILE(GLOB_RECURSE FILE_INCLUDES # 遍历子目录下所有符合情况的头文件
41 | ${CMAKE_CURRENT_SOURCE_DIR}/*.h*
42 | )
43 |
44 | FILE(GLOB_RECURSE FILE_SOURCES # 遍历子目录下所有符合情况的源文件
45 | ${CMAKE_CURRENT_SOURCE_DIR}/*.c*
46 | )
47 | ##################### ⬆CMake源文件设置⬆ #####################
48 |
49 | add_library(${MODULE_NAME} SHARED
50 | ${FILE_INCLUDES}
51 | ${FILE_SOURCES})
52 | target_link_libraries(${MODULE_NAME} log)
53 |
54 | if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
55 | add_custom_command(TARGET ${MODULE_NAME} POST_BUILD
56 | COMMAND ${CMAKE_STRIP} --strip-all --remove-section=.comment "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${MODULE_NAME}.so")
57 | endif ()
58 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/magiskhide/include/hide_mount.hpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "util.hpp"
9 | #include "log.hpp"
10 | #include "magisk.hpp"
11 |
12 | #define TMPFS_MNT(dir) (mentry->mnt_type == "tmpfs"sv && \
13 | strncmp(mentry->mnt_dir, "/" #dir, sizeof("/" #dir) - 1) == 0)
14 |
15 | using namespace std;
16 |
17 | int switch_mnt_ns(int pid) {
18 | char mnt[32];
19 | snprintf(mnt, sizeof(mnt), "/proc/%d/ns/mnt", pid);
20 | if (access(mnt, R_OK) == -1) return 1; // Maybe process died..
21 |
22 | int fd, ret;
23 | fd = open(mnt, O_RDONLY);
24 | if (fd < 0) return 1;
25 | // Switch to its namespace
26 | ret = setns(fd, 0);
27 | close(fd);
28 | return ret;
29 | }
30 |
31 | static void lazy_unmount(const char *mountpoint)
32 | {
33 | if (umount2(mountpoint, MNT_DETACH) != -1)
34 | LOGD("hide: Unmounted (%s)\n", mountpoint);
35 | }
36 |
37 | void do_hide(int pid)
38 | {
39 | if (pid > 0 && switch_mnt_ns(pid))
40 | return;
41 |
42 | char buf[64];
43 | readlink("/proc/self/exe", buf, sizeof(buf));
44 | string MAGISKTMP = dirname(buf);
45 |
46 | lazy_unmount(MAGISKTMP.data());
47 |
48 | parse_mnt("/proc/self/mounts", [&](mntent *mentry) {
49 | if (TMPFS_MNT(system) || TMPFS_MNT(vendor) || TMPFS_MNT(product) || TMPFS_MNT(system_ext))
50 | {
51 | lazy_unmount(mentry->mnt_dir);
52 | }
53 | return true;
54 | });
55 |
56 | // Unmount all Magisk created mounts
57 | parse_mnt("/proc/self/mounts", [&](mntent *mentry) {
58 | if (strstr(mentry->mnt_fsname, BLOCKDIR))
59 | {
60 | lazy_unmount(mentry->mnt_dir);
61 | }
62 | return true;
63 | });
64 | return;
65 | }
--------------------------------------------------------------------------------
/module/src/main/cpp/external/magiskhide/include/hide_prop.hpp:
--------------------------------------------------------------------------------
1 | #include "_system_properties.h"
2 | #include "log.hpp"
3 |
4 | static const char *prop_key[] =
5 | {"ro.boot.vbmeta.device_state", "ro.boot.verifiedbootstate", "ro.boot.flash.locked",
6 | "ro.boot.veritymode", "ro.boot.warranty_bit", "ro.warranty_bit",
7 | "ro.debuggable", "ro.secure", "ro.build.type", "ro.build.tags",
8 | "ro.vendor.boot.warranty_bit", "ro.vendor.warranty_bit",
9 | "vendor.boot.vbmeta.device_state", "ro.secureboot.lockstate", nullptr};
10 |
11 | static const char *prop_val[] =
12 | {"locked", "green", "1",
13 | "enforcing", "0", "0",
14 | "0", "1", "user", "release-keys",
15 | "0", "0",
16 | "locked", "locked", nullptr};
17 |
18 | int getprop(const char *name, char *buf)
19 | {
20 | return __system_property_get(name, buf);
21 | }
22 |
23 | int setprop(const char *name, const char *value)
24 | {
25 | __system_property_delete(name);
26 | __system_property_add(name, strlen(name), value, strlen(value));
27 | return 0;
28 | }
29 |
30 | void hide_sensitive_props()
31 | {
32 | LOGD("hide: Hiding sensitive props\n");
33 |
34 | for (int i = 0; prop_key[i]; ++i)
35 | {
36 | char buf[256];
37 | getprop(prop_key[i], buf);
38 | string value = buf;
39 | if (!value.empty())
40 | {
41 | LOGD("set %s:%s", prop_key[i], prop_val[i]);
42 | setprop(prop_key[i], prop_val[i]);
43 | }
44 | }
45 | }
46 |
47 | void do_hide_prop()
48 | {
49 | //初始化
50 | __system_properties_init();
51 | //隐藏敏感信息
52 | hide_sensitive_props();
53 | }
--------------------------------------------------------------------------------
/module/src/main/cpp/external/magiskhide/include/magisk.hpp:
--------------------------------------------------------------------------------
1 | #define INTLROOT ".magisk"
2 | #define MIRRDIR INTLROOT "/mirror"
3 | #define RULESDIR MIRRDIR "/sepolicy.rules"
4 | #define BLOCKDIR INTLROOT "/block"
5 | #define MODULEMNT INTLROOT "/modules"
6 | #define BBPATH INTLROOT "/busybox"
7 | #define ROOTOVL INTLROOT "/rootdir"
8 | #define ROOTMNT ROOTOVL "/.mount_list"
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/context_node.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #include "system_properties/context_node.h"
30 |
31 | #include
32 | #include
33 |
34 | #include
35 |
36 | #include "system_properties/system_properties.h"
37 |
38 | // pthread_mutex_lock() calls into system_properties in the case of contention.
39 | // This creates a risk of dead lock if any system_properties functions
40 | // use pthread locks after system_property initialization.
41 | //
42 | // For this reason, the below three functions use a bionic Lock and static
43 | // allocation of memory for each filename.
44 |
45 | bool ContextNode::Open(bool access_rw, bool* fsetxattr_failed) {
46 | lock_.lock();
47 | if (pa_) {
48 | lock_.unlock();
49 | return true;
50 | }
51 |
52 | char filename[PROP_FILENAME_MAX];
53 | int len = async_safe_format_buffer(filename, sizeof(filename), "%s/%s", filename_, context_);
54 | if (len < 0 || len >= PROP_FILENAME_MAX) {
55 | lock_.unlock();
56 | return false;
57 | }
58 |
59 | if (access_rw) {
60 | pa_ = prop_area::map_prop_area_rw(filename, context_, fsetxattr_failed);
61 | } else {
62 | pa_ = prop_area::map_prop_area(filename);
63 | }
64 | lock_.unlock();
65 | return pa_;
66 | }
67 |
68 | bool ContextNode::CheckAccessAndOpen() {
69 | if (!pa_ && !no_access_) {
70 | if (!CheckAccess() || !Open(false, nullptr)) {
71 | no_access_ = true;
72 | }
73 | }
74 | return pa_;
75 | }
76 |
77 | void ContextNode::ResetAccess() {
78 | if (!CheckAccess()) {
79 | Unmap();
80 | no_access_ = true;
81 | } else {
82 | no_access_ = false;
83 | }
84 | }
85 |
86 | bool ContextNode::CheckAccess() {
87 | char filename[PROP_FILENAME_MAX];
88 | int len = async_safe_format_buffer(filename, sizeof(filename), "%s/%s", filename_, context_);
89 | if (len < 0 || len >= PROP_FILENAME_MAX) {
90 | return false;
91 | }
92 |
93 | return access(filename, R_OK) == 0;
94 | }
95 |
96 | void ContextNode::Unmap() {
97 | prop_area::unmap_prop_area(&pa_);
98 | }
99 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/contexts_serialized.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #include "system_properties/contexts_serialized.h"
30 |
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 |
38 | #include
39 |
40 | #include
41 |
42 | #include "system_properties/system_properties.h"
43 |
44 | bool ContextsSerialized::InitializeContextNodes() {
45 | auto num_context_nodes = property_info_area_file_->num_contexts();
46 | auto context_nodes_mmap_size = sizeof(ContextNode) * num_context_nodes;
47 | // We want to avoid malloc in system properties, so we take an anonymous map instead (b/31659220).
48 | void* const map_result = mmap(nullptr, context_nodes_mmap_size, PROT_READ | PROT_WRITE,
49 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
50 | if (map_result == MAP_FAILED) {
51 | return false;
52 | }
53 |
54 | prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_result, context_nodes_mmap_size,
55 | "System property context nodes");
56 |
57 | context_nodes_ = reinterpret_cast(map_result);
58 | num_context_nodes_ = num_context_nodes;
59 | context_nodes_mmap_size_ = context_nodes_mmap_size;
60 |
61 | for (size_t i = 0; i < num_context_nodes; ++i) {
62 | new (&context_nodes_[i]) ContextNode(property_info_area_file_->context(i), filename_);
63 | }
64 |
65 | return true;
66 | }
67 |
68 | bool ContextsSerialized::MapSerialPropertyArea(bool access_rw, bool* fsetxattr_failed) {
69 | char filename[PROP_FILENAME_MAX];// /dev/__properties__/properties_serial
70 | int len = async_safe_format_buffer(filename, sizeof(filename), "%s/properties_serial", filename_);
71 | if (len < 0 || len >= PROP_FILENAME_MAX) {
72 | serial_prop_area_ = nullptr;
73 | return false;
74 | }
75 |
76 | if (access_rw) {
77 | serial_prop_area_ =
78 | prop_area::map_prop_area_rw(filename, "u:object_r:properties_serial:s0", fsetxattr_failed);
79 | } else {
80 | serial_prop_area_ = prop_area::map_prop_area(filename);
81 | }
82 | return serial_prop_area_;
83 | }
84 |
85 | bool ContextsSerialized::InitializeProperties() {
86 | if (!property_info_area_file_.LoadDefaultPath()) {
87 | return false;
88 | }
89 |
90 | if (!InitializeContextNodes()) {
91 | FreeAndUnmap();
92 | return false;
93 | }
94 |
95 | return true;
96 | }
97 |
98 | bool ContextsSerialized::Initialize(bool writable, const char* filename, bool* fsetxattr_failed) {
99 | filename_ = filename;
100 | if (!InitializeProperties()) {
101 | return false;
102 | }
103 |
104 | if (writable) {
105 | mkdir(filename_, S_IRWXU | S_IXGRP | S_IXOTH);
106 | bool open_failed = false;
107 | if (fsetxattr_failed) {
108 | *fsetxattr_failed = false;
109 | }
110 |
111 | for (size_t i = 0; i < num_context_nodes_; ++i) {
112 | if (!context_nodes_[i].Open(true, fsetxattr_failed)) {
113 | open_failed = true;
114 | }
115 | }
116 | if (open_failed || !MapSerialPropertyArea(true, fsetxattr_failed)) {
117 | FreeAndUnmap();
118 | return false;
119 | }
120 | } else {
121 | if (!MapSerialPropertyArea(false, nullptr)) {
122 | FreeAndUnmap();
123 | return false;
124 | }
125 | }
126 | return true;
127 | }
128 |
129 | prop_area* ContextsSerialized::GetPropAreaForName(const char* name) {
130 | uint32_t index;
131 | property_info_area_file_->GetPropertyInfoIndexes(name, &index, nullptr);
132 | if (index == ~0u || index >= num_context_nodes_) {
133 | async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Could not find context for property \"%s\"",
134 | name);
135 | return nullptr;
136 | }
137 | auto* context_node = &context_nodes_[index];
138 | if (!context_node->pa()) {
139 | // We explicitly do not check no_access_ in this case because unlike the
140 | // case of foreach(), we want to generate an selinux audit for each
141 | // non-permitted property access in this function.
142 | context_node->Open(false, nullptr);
143 | }
144 | return context_node->pa();
145 | }
146 |
147 | void ContextsSerialized::ForEach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
148 | for (size_t i = 0; i < num_context_nodes_; ++i) {
149 | if (context_nodes_[i].CheckAccessAndOpen()) {
150 | context_nodes_[i].pa()->foreach (propfn, cookie);
151 | }
152 | }
153 | }
154 |
155 | void ContextsSerialized::ResetAccess() {
156 | for (size_t i = 0; i < num_context_nodes_; ++i) {
157 | context_nodes_[i].ResetAccess();
158 | }
159 | }
160 |
161 | void ContextsSerialized::FreeAndUnmap() {
162 | property_info_area_file_.Reset();
163 | if (context_nodes_ != nullptr) {
164 | for (size_t i = 0; i < num_context_nodes_; ++i) {
165 | context_nodes_[i].Unmap();
166 | }
167 | munmap(context_nodes_, context_nodes_mmap_size_);
168 | context_nodes_ = nullptr;
169 | }
170 | prop_area::unmap_prop_area(&serial_prop_area_);
171 | serial_prop_area_ = nullptr;
172 | }
173 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/contexts_split.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #include "system_properties/contexts_split.h"
30 |
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 |
37 | #include
38 |
39 | #include "system_properties/context_node.h"
40 | #include "system_properties/system_properties.h"
41 |
42 | class ContextListNode : public ContextNode {
43 | public:
44 | ContextListNode(ContextListNode* next, const char* context, const char* filename)
45 | : ContextNode(strdup(context), filename), next(next) {
46 | }
47 |
48 | ~ContextListNode() {
49 | free(const_cast(context()));
50 | }
51 |
52 | ContextListNode* next;
53 | };
54 |
55 | struct PrefixNode {
56 | PrefixNode(struct PrefixNode* next, const char* prefix, ContextListNode* context)
57 | : prefix(strdup(prefix)), prefix_len(strlen(prefix)), context(context), next(next) {
58 | }
59 | ~PrefixNode() {
60 | free(prefix);
61 | }
62 | char* prefix;
63 | const size_t prefix_len;
64 | ContextListNode* context;
65 | PrefixNode* next;
66 | };
67 |
68 | template
69 | static inline void ListAdd(List** list, Args... args) {
70 | *list = new List(*list, args...);
71 | }
72 |
73 | static void ListAddAfterLen(PrefixNode** list, const char* prefix, ContextListNode* context) {
74 | size_t prefix_len = strlen(prefix);
75 |
76 | auto next_list = list;
77 |
78 | while (*next_list) {
79 | if ((*next_list)->prefix_len < prefix_len || (*next_list)->prefix[0] == '*') {
80 | ListAdd(next_list, prefix, context);
81 | return;
82 | }
83 | next_list = &(*next_list)->next;
84 | }
85 | ListAdd(next_list, prefix, context);
86 | }
87 |
88 | template
89 | static void ListForEach(List* list, Func func) {
90 | while (list) {
91 | func(list);
92 | list = list->next;
93 | }
94 | }
95 |
96 | template
97 | static List* ListFind(List* list, Func func) {
98 | while (list) {
99 | if (func(list)) {
100 | return list;
101 | }
102 | list = list->next;
103 | }
104 | return nullptr;
105 | }
106 |
107 | template
108 | static void ListFree(List** list) {
109 | while (*list) {
110 | auto old_list = *list;
111 | *list = old_list->next;
112 | delete old_list;
113 | }
114 | }
115 |
116 | // The below two functions are duplicated from label_support.c in libselinux.
117 | // TODO: Find a location suitable for these functions such that both libc and
118 | // libselinux can share a common source file.
119 |
120 | // The read_spec_entries and read_spec_entry functions may be used to
121 | // replace sscanf to read entries from spec files. The file and
122 | // property services now use these.
123 |
124 | // Read an entry from a spec file (e.g. file_contexts)
125 | static inline int read_spec_entry(char** entry, char** ptr, int* len) {
126 | *entry = nullptr;
127 | char* tmp_buf = nullptr;
128 |
129 | while (isspace(**ptr) && **ptr != '\0') (*ptr)++;
130 |
131 | tmp_buf = *ptr;
132 | *len = 0;
133 |
134 | while (!isspace(**ptr) && **ptr != '\0') {
135 | (*ptr)++;
136 | (*len)++;
137 | }
138 |
139 | if (*len) {
140 | *entry = strndup(tmp_buf, *len);
141 | if (!*entry) return -1;
142 | }
143 |
144 | return 0;
145 | }
146 |
147 | // line_buf - Buffer containing the spec entries .
148 | // num_args - The number of spec parameter entries to process.
149 | // ... - A 'char **spec_entry' for each parameter.
150 | // returns - The number of items processed.
151 | //
152 | // This function calls read_spec_entry() to do the actual string processing.
153 | static int read_spec_entries(char* line_buf, int num_args, ...) {
154 | char **spec_entry, *buf_p;
155 | int len, rc, items, entry_len = 0;
156 | va_list ap;
157 |
158 | len = strlen(line_buf);
159 | if (line_buf[len - 1] == '\n')
160 | line_buf[len - 1] = '\0';
161 | else
162 | // Handle case if line not \n terminated by bumping
163 | // the len for the check below (as the line is NUL
164 | // terminated by getline(3))
165 | len++;
166 |
167 | buf_p = line_buf;
168 | while (isspace(*buf_p)) buf_p++;
169 |
170 | // Skip comment lines and empty lines.
171 | if (*buf_p == '#' || *buf_p == '\0') return 0;
172 |
173 | // Process the spec file entries
174 | va_start(ap, num_args);
175 |
176 | items = 0;
177 | while (items < num_args) {
178 | spec_entry = va_arg(ap, char**);
179 |
180 | if (len - 1 == buf_p - line_buf) {
181 | va_end(ap);
182 | return items;
183 | }
184 |
185 | rc = read_spec_entry(spec_entry, &buf_p, &entry_len);
186 | if (rc < 0) {
187 | va_end(ap);
188 | return rc;
189 | }
190 | if (entry_len) items++;
191 | }
192 | va_end(ap);
193 | return items;
194 | }
195 |
196 | bool ContextsSplit::MapSerialPropertyArea(bool access_rw, bool* fsetxattr_failed) {
197 | char filename[PROP_FILENAME_MAX];
198 | int len = async_safe_format_buffer(filename, sizeof(filename), "%s/properties_serial", filename_);
199 | if (len < 0 || len >= PROP_FILENAME_MAX) {
200 | serial_prop_area_ = nullptr;
201 | return false;
202 | }
203 |
204 | if (access_rw) {
205 | serial_prop_area_ =
206 | prop_area::map_prop_area_rw(filename, "u:object_r:properties_serial:s0", fsetxattr_failed);
207 | } else {
208 | serial_prop_area_ = prop_area::map_prop_area(filename);
209 | }
210 | return serial_prop_area_;
211 | }
212 |
213 | bool ContextsSplit::InitializePropertiesFromFile(const char* filename) {
214 | FILE* file = fopen(filename, "re");
215 | if (!file) {
216 | return false;
217 | }
218 |
219 | char* buffer = nullptr;
220 | size_t line_len;
221 | char* prop_prefix = nullptr;
222 | char* context = nullptr;
223 |
224 | while (getline(&buffer, &line_len, file) > 0) {
225 | int items = read_spec_entries(buffer, 2, &prop_prefix, &context);
226 | if (items <= 0) {
227 | continue;
228 | }
229 | if (items == 1) {
230 | free(prop_prefix);
231 | continue;
232 | }
233 |
234 | // init uses ctl.* properties as an IPC mechanism and does not write them
235 | // to a property file, therefore we do not need to create property files
236 | // to store them.
237 | if (!strncmp(prop_prefix, "ctl.", 4)) {
238 | free(prop_prefix);
239 | free(context);
240 | continue;
241 | }
242 |
243 | auto old_context = ListFind(
244 | contexts_, [context](ContextListNode* l) { return !strcmp(l->context(), context); });
245 | if (old_context) {
246 | ListAddAfterLen(&prefixes_, prop_prefix, old_context);
247 | } else {
248 | ListAdd(&contexts_, context, filename_);
249 | ListAddAfterLen(&prefixes_, prop_prefix, contexts_);
250 | }
251 | free(prop_prefix);
252 | free(context);
253 | }
254 |
255 | free(buffer);
256 | fclose(file);
257 |
258 | return true;
259 | }
260 |
261 | bool ContextsSplit::InitializeProperties() {
262 | // If we do find /property_contexts, then this is being
263 | // run as part of the OTA updater on older release that had
264 | // /property_contexts - b/34370523
265 | if (InitializePropertiesFromFile("/property_contexts")) {
266 | return true;
267 | }
268 |
269 | // Use property_contexts from /system & /vendor, fall back to those from /
270 | if (access("/system/etc/selinux/plat_property_contexts", R_OK) != -1) {
271 | if (!InitializePropertiesFromFile("/system/etc/selinux/plat_property_contexts")) {
272 | return false;
273 | }
274 | // Don't check for failure here, so we always have a sane list of properties.
275 | // E.g. In case of recovery, the vendor partition will not have mounted and we
276 | // still need the system / platform properties to function.
277 | if (access("/vendor/etc/selinux/vendor_property_contexts", R_OK) != -1) {
278 | InitializePropertiesFromFile("/vendor/etc/selinux/vendor_property_contexts");
279 | } else {
280 | // Fallback to nonplat_* if vendor_* doesn't exist.
281 | InitializePropertiesFromFile("/vendor/etc/selinux/nonplat_property_contexts");
282 | }
283 | } else {
284 | if (!InitializePropertiesFromFile("/plat_property_contexts")) {
285 | return false;
286 | }
287 | if (access("/vendor_property_contexts", R_OK) != -1) {
288 | InitializePropertiesFromFile("/vendor_property_contexts");
289 | } else {
290 | // Fallback to nonplat_* if vendor_* doesn't exist.
291 | InitializePropertiesFromFile("/nonplat_property_contexts");
292 | }
293 | }
294 |
295 | return true;
296 | }
297 |
298 | bool ContextsSplit::Initialize(bool writable, const char* filename, bool* fsetxattr_failed) {
299 | filename_ = filename;
300 | if (!InitializeProperties()) {
301 | return false;
302 | }
303 |
304 | if (writable) {
305 | mkdir(filename_, S_IRWXU | S_IXGRP | S_IXOTH);
306 | bool open_failed = false;
307 | if (fsetxattr_failed) {
308 | *fsetxattr_failed = false;
309 | }
310 |
311 | ListForEach(contexts_, [&fsetxattr_failed, &open_failed](ContextListNode* l) {
312 | if (!l->Open(true, fsetxattr_failed)) {
313 | open_failed = true;
314 | }
315 | });
316 | if (open_failed || !MapSerialPropertyArea(true, fsetxattr_failed)) {
317 | FreeAndUnmap();
318 | return false;
319 | }
320 | } else {
321 | if (!MapSerialPropertyArea(false, nullptr)) {
322 | FreeAndUnmap();
323 | return false;
324 | }
325 | }
326 | return true;
327 | }
328 |
329 | prop_area* ContextsSplit::GetPropAreaForName(const char* name) {
330 | auto entry = ListFind(prefixes_, [name](PrefixNode* l) {
331 | return l->prefix[0] == '*' || !strncmp(l->prefix, name, l->prefix_len);
332 | });
333 | if (!entry) {
334 | return nullptr;
335 | }
336 |
337 | auto cnode = entry->context;
338 | if (!cnode->pa()) {
339 | // We explicitly do not check no_access_ in this case because unlike the
340 | // case of foreach(), we want to generate an selinux audit for each
341 | // non-permitted property access in this function.
342 | cnode->Open(false, nullptr);
343 | }
344 | return cnode->pa();
345 | }
346 |
347 | void ContextsSplit::ForEach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
348 | ListForEach(contexts_, [propfn, cookie](ContextListNode* l) {
349 | if (l->CheckAccessAndOpen()) {
350 | l->pa()->foreach (propfn, cookie);
351 | }
352 | });
353 | }
354 |
355 | void ContextsSplit::ResetAccess() {
356 | ListForEach(contexts_, [](ContextListNode* l) { l->ResetAccess(); });
357 | }
358 |
359 | void ContextsSplit::FreeAndUnmap() {
360 | ListFree(&prefixes_);
361 | ListFree(&contexts_);
362 | prop_area::unmap_prop_area(&serial_prop_area_);
363 | }
364 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/_system_properties.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #ifndef _INCLUDE_SYS__SYSTEM_PROPERTIES_H
30 | #define _INCLUDE_SYS__SYSTEM_PROPERTIES_H
31 |
32 | #include
33 | #include
34 |
35 |
36 | //#include
37 | #include "system_properties.h"
38 |
39 | __BEGIN_DECLS
40 |
41 | #define PROP_SERVICE_NAME "property_service"
42 | #define PROP_FILENAME "/dev/__properties__"
43 |
44 | #define PROP_MSG_SETPROP 1
45 | #define PROP_MSG_SETPROP2 0x00020001
46 |
47 | #define PROP_SUCCESS 0
48 | #define PROP_ERROR_READ_CMD 0x0004
49 | #define PROP_ERROR_READ_DATA 0x0008
50 | #define PROP_ERROR_READ_ONLY_PROPERTY 0x000B
51 | #define PROP_ERROR_INVALID_NAME 0x0010
52 | #define PROP_ERROR_INVALID_VALUE 0x0014
53 | #define PROP_ERROR_PERMISSION_DENIED 0x0018
54 | #define PROP_ERROR_INVALID_CMD 0x001B
55 | #define PROP_ERROR_HANDLE_CONTROL_MESSAGE 0x0020
56 | #define PROP_ERROR_SET_FAILED 0x0024
57 |
58 | /*
59 | ** This was previously for testing, but now that SystemProperties is its own testable class,
60 | ** there is never a reason to call this function and its implementation simply returns -1.
61 | */
62 | int __system_property_set_filename(const char* __filename);
63 |
64 | /*
65 | ** Initialize the area to be used to store properties. Can
66 | ** only be done by a single process that has write access to
67 | ** the property area.
68 | */
69 | int __system_property_area_init(void);
70 |
71 | /* Read the global serial number of the system properties
72 | **
73 | ** Called to predict if a series of cached __system_property_find
74 | ** objects will have seen __system_property_serial values change.
75 | ** But also aids the converse, as changes in the global serial can
76 | ** also be used to predict if a failed __system_property_find
77 | ** could in-turn now find a new object; thus preventing the
78 | ** cycles of effort to poll __system_property_find.
79 | **
80 | ** Typically called at beginning of a cache cycle to signal if _any_ possible
81 | ** changes have occurred since last. If there is, one may check each individual
82 | ** __system_property_serial to confirm dirty, or __system_property_find
83 | ** to check if the property now exists. If a call to __system_property_add
84 | ** or __system_property_update has completed between two calls to
85 | ** __system_property_area_serial then the second call will return a larger
86 | ** value than the first call. Beware of race conditions as changes to the
87 | ** properties are not atomic, the main value of this call is to determine
88 | ** whether the expensive __system_property_find is worth retrying to see if
89 | ** a property now exists.
90 | **
91 | ** Returns the serial number on success, -1 on error.
92 | */
93 | uint32_t __system_property_area_serial(void);
94 |
95 | /* Add a new system property. Can only be done by a single
96 | ** process that has write access to the property area, and
97 | ** that process must handle sequencing to ensure the property
98 | ** does not already exist and that only one property is added
99 | ** or updated at a time.
100 | **
101 | ** Returns 0 on success, -1 if the property area is full.
102 | */
103 | int __system_property_add(const char* __name, unsigned int __name_length, const char* __value, unsigned int __value_length);
104 |
105 | /* Delete a system property. Added in resetprop
106 | **
107 | ** Returns 0 on success, -1 if the property area is full.
108 | */
109 | int __system_property_delete(const char *__name);
110 |
111 | /* Update the value of a system property returned by
112 | ** __system_property_find. Can only be done by a single process
113 | ** that has write access to the property area, and that process
114 | ** must handle sequencing to ensure that only one property is
115 | ** updated at a time.
116 | **
117 | ** Returns 0 on success, -1 if the parameters are incorrect.
118 | */
119 | int __system_property_update(prop_info* __pi, const char* __value, unsigned int __value_length);
120 |
121 | /* Read the serial number of a system property returned by
122 | ** __system_property_find.
123 | **
124 | ** Returns the serial number on success, -1 on error.
125 | */
126 | uint32_t __system_property_serial(const prop_info* __pi);
127 |
128 | /* Initialize the system properties area in read only mode.
129 | * Should be done by all processes that need to read system
130 | * properties.
131 | *
132 | * Returns 0 on success, -1 otherwise.
133 | */
134 | int __system_properties_init(void);
135 |
136 | /* Deprecated: use __system_property_wait instead. */
137 | uint32_t __system_property_wait_any(uint32_t __old_serial);
138 |
139 | __END_DECLS
140 |
141 | #endif
142 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/async_safe/log.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define async_safe_format_buffer snprintf
4 | #define async_safe_format_log(...) /* NOP */
5 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/private/ErrnoRestorer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include
20 |
21 | #include "bionic_macros.h"
22 |
23 | class ErrnoRestorer {
24 | public:
25 | explicit ErrnoRestorer() : saved_errno_(errno) {
26 | }
27 |
28 | ~ErrnoRestorer() {
29 | errno = saved_errno_;
30 | }
31 |
32 | void override(int new_errno) {
33 | saved_errno_ = new_errno;
34 | }
35 |
36 | private:
37 | int saved_errno_;
38 |
39 | BIONIC_DISALLOW_COPY_AND_ASSIGN(ErrnoRestorer);
40 | };
41 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/private/bionic_defs.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #ifndef __BIONIC_PRIVATE_BIONIC_DEFS_H_
30 | #define __BIONIC_PRIVATE_BIONIC_DEFS_H_
31 |
32 | /*
33 | * This label is used to mark libc/libdl symbols that may need to be replaced
34 | * by native bridge implementation.
35 | */
36 | #define __BIONIC_WEAK_FOR_NATIVE_BRIDGE __attribute__((__weak__, __noinline__))
37 | #define __BIONIC_WEAK_VARIABLE_FOR_NATIVE_BRIDGE __attribute__((__weak__))
38 |
39 | #endif /* __BIONIC_PRIVATE_BIONIC_DEFS_H_ */
40 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/private/bionic_futex.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 | #ifndef _BIONIC_FUTEX_H
29 | #define _BIONIC_FUTEX_H
30 |
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include
38 |
39 | struct timespec;
40 |
41 | static inline __always_inline int __futex(volatile void* ftx, int op, int value,
42 | const timespec* timeout, int bitset) {
43 | // Our generated syscall assembler sets errno, but our callers (pthread functions) don't want to.
44 | int saved_errno = errno;
45 | int result = syscall(__NR_futex, ftx, op, value, timeout, NULL, bitset);
46 | if (__predict_false(result == -1)) {
47 | result = -errno;
48 | errno = saved_errno;
49 | }
50 | return result;
51 | }
52 |
53 | static inline int __futex_wake(volatile void* ftx, int count) {
54 | return __futex(ftx, FUTEX_WAKE, count, nullptr, 0);
55 | }
56 |
57 | static inline int __futex_wake_ex(volatile void* ftx, bool shared, int count) {
58 | return __futex(ftx, shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, count, nullptr, 0);
59 | }
60 |
61 | static inline int __futex_wait(volatile void* ftx, int value, const timespec* timeout) {
62 | return __futex(ftx, FUTEX_WAIT, value, timeout, 0);
63 | }
64 |
65 | static inline int __futex_wait_ex(volatile void* ftx, bool shared, int value) {
66 | return __futex(ftx, (shared ? FUTEX_WAIT_BITSET : FUTEX_WAIT_BITSET_PRIVATE), value, nullptr,
67 | FUTEX_BITSET_MATCH_ANY);
68 | }
69 |
70 | __LIBC_HIDDEN__ int __futex_wait_ex(volatile void* ftx, bool shared, int value,
71 | bool use_realtime_clock, const timespec* abs_timeout);
72 |
73 | static inline int __futex_pi_unlock(volatile void* ftx, bool shared) {
74 | return __futex(ftx, shared ? FUTEX_UNLOCK_PI : FUTEX_UNLOCK_PI_PRIVATE, 0, nullptr, 0);
75 | }
76 |
77 | __LIBC_HIDDEN__ int __futex_pi_lock_ex(volatile void* ftx, bool shared, bool use_realtime_clock,
78 | const timespec* abs_timeout);
79 |
80 | #endif /* _BIONIC_FUTEX_H */
81 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/private/bionic_lock.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #pragma once
30 |
31 | #include
32 | #include "private/bionic_futex.h"
33 | #include "private/bionic_macros.h"
34 |
35 | // Lock is used in places like pthread_rwlock_t, which can be initialized without calling
36 | // an initialization function. So make sure Lock can be initialized by setting its memory to 0.
37 | class Lock {
38 | private:
39 | enum LockState {
40 | Unlocked = 0,
41 | LockedWithoutWaiter,
42 | LockedWithWaiter,
43 | };
44 | _Atomic(LockState) state;
45 | bool process_shared;
46 |
47 | public:
48 | void init(bool process_shared) {
49 | atomic_init(&state, Unlocked);
50 | this->process_shared = process_shared;
51 | }
52 |
53 | bool trylock() {
54 | LockState old_state = Unlocked;
55 | return __predict_true(atomic_compare_exchange_strong_explicit(&state, &old_state,
56 | LockedWithoutWaiter, memory_order_acquire, memory_order_relaxed));
57 | }
58 |
59 | void lock() {
60 | LockState old_state = Unlocked;
61 | if (__predict_true(atomic_compare_exchange_strong_explicit(&state, &old_state,
62 | LockedWithoutWaiter, memory_order_acquire, memory_order_relaxed))) {
63 | return;
64 | }
65 | while (atomic_exchange_explicit(&state, LockedWithWaiter, memory_order_acquire) != Unlocked) {
66 | // TODO: As the critical section is brief, it is a better choice to spin a few times befor sleeping.
67 | __futex_wait_ex(&state, process_shared, LockedWithWaiter);
68 | }
69 | return;
70 | }
71 |
72 | void unlock() {
73 | bool shared = process_shared; /* cache to local variable */
74 | if (atomic_exchange_explicit(&state, Unlocked, memory_order_release) == LockedWithWaiter) {
75 | __futex_wake_ex(&state, shared, 1);
76 | }
77 | }
78 | };
79 |
80 | class LockGuard {
81 | public:
82 | explicit LockGuard(Lock& lock) : lock_(lock) {
83 | lock_.lock();
84 | }
85 | ~LockGuard() {
86 | lock_.unlock();
87 | }
88 |
89 | BIONIC_DISALLOW_COPY_AND_ASSIGN(LockGuard);
90 |
91 | private:
92 | Lock& lock_;
93 | };
94 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/private/bionic_macros.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include
20 |
21 | #define BIONIC_DISALLOW_COPY_AND_ASSIGN(TypeName) \
22 | TypeName(const TypeName&) = delete; \
23 | void operator=(const TypeName&) = delete
24 |
25 | #define BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
26 | TypeName() = delete; \
27 | BIONIC_DISALLOW_COPY_AND_ASSIGN(TypeName)
28 |
29 | #define BIONIC_ROUND_UP_POWER_OF_2(value) \
30 | ((sizeof(value) == 8) \
31 | ? (1UL << (64 - __builtin_clzl(static_cast(value)))) \
32 | : (1UL << (32 - __builtin_clz(static_cast(value)))))
33 |
34 | static constexpr uintptr_t align_down(uintptr_t p, size_t align) {
35 | return p & ~(align - 1);
36 | }
37 |
38 | static constexpr uintptr_t align_up(uintptr_t p, size_t align) {
39 | return (p + align - 1) & ~(align - 1);
40 | }
41 |
42 | template
43 | static inline T* align_down(T* p, size_t align) {
44 | return reinterpret_cast(align_down(reinterpret_cast(p), align));
45 | }
46 |
47 | template
48 | static inline T* align_up(T* p, size_t align) {
49 | return reinterpret_cast(align_up(reinterpret_cast(p), align));
50 | }
51 |
52 | #if defined(__arm__)
53 | // Do not emit anything for arm, clang does not allow emiting an arm unwind
54 | // directive.
55 | // #define BIONIC_STOP_UNWIND asm volatile(".cantunwind")
56 | #define BIONIC_STOP_UNWIND
57 | #elif defined(__aarch64__)
58 | #define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined x30")
59 | #elif defined(__i386__)
60 | #define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined \%eip")
61 | #elif defined(__x86_64__)
62 | #define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined \%rip")
63 | #elif defined (__mips__)
64 | #define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined $ra")
65 | #endif
66 |
67 | // The arraysize(arr) macro returns the # of elements in an array arr.
68 | // The expression is a compile-time constant, and therefore can be
69 | // used in defining new arrays, for example. If you use arraysize on
70 | // a pointer by mistake, you will get a compile-time error.
71 | //
72 | // One caveat is that arraysize() doesn't accept any array of an
73 | // anonymous type or a type defined inside a function.
74 | //
75 | // This template function declaration is used in defining arraysize.
76 | // Note that the function doesn't need an implementation, as we only
77 | // use its type.
78 | template
79 | char (&ArraySizeHelper(T (&array)[N]))[N]; // NOLINT(readability/casting)
80 |
81 | #define arraysize(array) (sizeof(ArraySizeHelper(array)))
82 |
83 | // Used to inform clang's -Wimplicit-fallthrough that a fallthrough is intended. There's no way to
84 | // silence (or enable, apparently) -Wimplicit-fallthrough in C yet.
85 | #ifdef __cplusplus
86 | #define __BIONIC_FALLTHROUGH [[clang::fallthrough]]
87 | #else
88 | #define __BIONIC_FALLTHROUGH
89 | #endif
90 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/private/hacks.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | // Missing defines
7 | #ifndef PR_SET_VMA
8 | #define PR_SET_VMA 0x53564d41
9 | #endif
10 | #ifndef PR_SET_VMA_ANON_NAME
11 | #define PR_SET_VMA_ANON_NAME 0
12 | #endif
13 |
14 | // Missing functions
15 | #define getline compat_getline
16 | ssize_t compat_getline(char **, size_t *, FILE *);
17 |
18 | // Rename symbols
19 | #pragma redefine_extname __system_property_set _system_property_set2
20 | #pragma redefine_extname __system_property_find _system_property_find2
21 | #pragma redefine_extname __system_property_read_callback _system_property_read_callback2
22 | #pragma redefine_extname __system_property_foreach __system_property_foreach2
23 | #pragma redefine_extname __system_property_wait __system_property_wait2
24 | #pragma redefine_extname __system_property_read __system_property_read2
25 | #pragma redefine_extname __system_property_get __system_property_get2
26 | #pragma redefine_extname __system_property_find_nth __system_property_find_nth2
27 | #pragma redefine_extname __system_property_set_filename __system_property_set_filename2
28 | #pragma redefine_extname __system_property_area_init __system_property_area_init2
29 | #pragma redefine_extname __system_property_area_serial __system_property_area_serial2
30 | #pragma redefine_extname __system_property_add __system_property_add2
31 | #pragma redefine_extname __system_property_update __system_property_update2
32 | #pragma redefine_extname __system_property_serial __system_property_serial2
33 | #pragma redefine_extname __system_properties_init __system_properties_init2
34 | #pragma redefine_extname __system_property_wait_any __system_property_wait_any2
35 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/property_info_parser/property_info_parser.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 The Android Open Source Project
3 | //
4 | // Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | // You may obtain a copy of the License at
7 | //
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | //
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 | //
16 |
17 | #ifndef PROPERTY_INFO_PARSER_H
18 | #define PROPERTY_INFO_PARSER_H
19 |
20 | #include
21 | #include
22 |
23 | namespace android {
24 | namespace properties {
25 |
26 | // The below structs intentionally do not end with char name[0] or other tricks to allocate
27 | // with a dynamic size, such that they can be added onto in the future without breaking
28 | // backwards compatibility.
29 | struct PropertyEntry {
30 | uint32_t name_offset;
31 | uint32_t namelen;
32 |
33 | // This is the context match for this node_; ~0u if it doesn't correspond to any.
34 | uint32_t context_index;
35 | // This is the type for this node_; ~0u if it doesn't correspond to any.
36 | uint32_t type_index;
37 | };
38 |
39 | struct TrieNodeInternal {
40 | // This points to a property entry struct, which includes the name for this node
41 | uint32_t property_entry;
42 |
43 | // Children are a sorted list of child nodes_; binary search them.
44 | uint32_t num_child_nodes;
45 | uint32_t child_nodes;
46 |
47 | // Prefixes are terminating prefix matches at this node, sorted longest to smallest
48 | // Take the first match sequentially found with StartsWith().
49 | uint32_t num_prefixes;
50 | uint32_t prefix_entries;
51 |
52 | // Exact matches are a sorted list of exact matches at this node_; binary search them.
53 | uint32_t num_exact_matches;
54 | uint32_t exact_match_entries;
55 | };
56 |
57 | struct PropertyInfoAreaHeader {
58 | // The current version of this data as created by property service.
59 | uint32_t current_version;
60 | // The lowest version of libc that can properly parse this data.
61 | uint32_t minimum_supported_version;
62 | uint32_t size;
63 | uint32_t contexts_offset;
64 | uint32_t types_offset;
65 | uint32_t root_offset;
66 | };
67 |
68 | class SerializedData {
69 | public:
70 | uint32_t size() const {
71 | return reinterpret_cast(data_base_)->size;
72 | }
73 |
74 | const char* c_string(uint32_t offset) const {
75 | if (offset != 0 && offset > size()) return nullptr;
76 | return static_cast(data_base_ + offset);
77 | }
78 |
79 | const uint32_t* uint32_array(uint32_t offset) const {
80 | if (offset != 0 && offset > size()) return nullptr;
81 | return reinterpret_cast(data_base_ + offset);
82 | }
83 |
84 | uint32_t uint32(uint32_t offset) const {
85 | if (offset != 0 && offset > size()) return ~0u;
86 | return *reinterpret_cast(data_base_ + offset);
87 | }
88 |
89 | const char* data_base() const { return data_base_; }
90 |
91 | private:
92 | const char data_base_[0];
93 | };
94 |
95 | class TrieNode {
96 | public:
97 | TrieNode() : serialized_data_(nullptr), trie_node_base_(nullptr) {}
98 | TrieNode(const SerializedData* data_base, const TrieNodeInternal* trie_node_base)
99 | : serialized_data_(data_base), trie_node_base_(trie_node_base) {}
100 |
101 | const char* name() const {
102 | return serialized_data_->c_string(node_property_entry()->name_offset);
103 | }
104 |
105 | uint32_t context_index() const { return node_property_entry()->context_index; }
106 | uint32_t type_index() const { return node_property_entry()->type_index; }
107 |
108 | uint32_t num_child_nodes() const { return trie_node_base_->num_child_nodes; }
109 | TrieNode child_node(int n) const {
110 | uint32_t child_node_offset = serialized_data_->uint32_array(trie_node_base_->child_nodes)[n];
111 | const TrieNodeInternal* trie_node_base =
112 | reinterpret_cast(serialized_data_->data_base() + child_node_offset);
113 | return TrieNode(serialized_data_, trie_node_base);
114 | }
115 |
116 | bool FindChildForString(const char* input, uint32_t namelen, TrieNode* child) const;
117 |
118 | uint32_t num_prefixes() const { return trie_node_base_->num_prefixes; }
119 | const PropertyEntry* prefix(int n) const {
120 | uint32_t prefix_entry_offset =
121 | serialized_data_->uint32_array(trie_node_base_->prefix_entries)[n];
122 | return reinterpret_cast(serialized_data_->data_base() +
123 | prefix_entry_offset);
124 | }
125 |
126 | uint32_t num_exact_matches() const { return trie_node_base_->num_exact_matches; }
127 | const PropertyEntry* exact_match(int n) const {
128 | uint32_t exact_match_entry_offset =
129 | serialized_data_->uint32_array(trie_node_base_->exact_match_entries)[n];
130 | return reinterpret_cast(serialized_data_->data_base() +
131 | exact_match_entry_offset);
132 | }
133 |
134 | private:
135 | const PropertyEntry* node_property_entry() const {
136 | return reinterpret_cast(serialized_data_->data_base() +
137 | trie_node_base_->property_entry);
138 | }
139 |
140 | const SerializedData* serialized_data_;
141 | const TrieNodeInternal* trie_node_base_;
142 | };
143 |
144 | class PropertyInfoArea : private SerializedData {
145 | public:
146 | void GetPropertyInfoIndexes(const char* name, uint32_t* context_index, uint32_t* type_index) const;
147 | void GetPropertyInfo(const char* property, const char** context, const char** type) const;
148 |
149 | int FindContextIndex(const char* context) const;
150 | int FindTypeIndex(const char* type) const;
151 |
152 | const char* context(uint32_t index) const {
153 | uint32_t context_array_size_offset = contexts_offset();
154 | const uint32_t* context_array = uint32_array(context_array_size_offset + sizeof(uint32_t));
155 | return data_base() + context_array[index];
156 | }
157 |
158 | const char* type(uint32_t index) const {
159 | uint32_t type_array_size_offset = types_offset();
160 | const uint32_t* type_array = uint32_array(type_array_size_offset + sizeof(uint32_t));
161 | return data_base() + type_array[index];
162 | }
163 |
164 | uint32_t current_version() const { return header()->current_version; }
165 | uint32_t minimum_supported_version() const { return header()->minimum_supported_version; }
166 |
167 | uint32_t size() const { return SerializedData::size(); }
168 |
169 | uint32_t num_contexts() const { return uint32_array(contexts_offset())[0]; }
170 | uint32_t num_types() const { return uint32_array(types_offset())[0]; }
171 |
172 | TrieNode root_node() const { return trie(header()->root_offset); }
173 |
174 | private:
175 | void CheckPrefixMatch(const char* remaining_name, const TrieNode& trie_node,
176 | uint32_t* context_index, uint32_t* type_index) const;
177 |
178 | const PropertyInfoAreaHeader* header() const {
179 | return reinterpret_cast(data_base());
180 | }
181 | uint32_t contexts_offset() const { return header()->contexts_offset; }
182 | uint32_t contexts_array_offset() const { return contexts_offset() + sizeof(uint32_t); }
183 | uint32_t types_offset() const { return header()->types_offset; }
184 | uint32_t types_array_offset() const { return types_offset() + sizeof(uint32_t); }
185 |
186 | TrieNode trie(uint32_t offset) const {
187 | if (offset != 0 && offset > size()) return TrieNode();
188 | const TrieNodeInternal* trie_node_base =
189 | reinterpret_cast(data_base() + offset);
190 | return TrieNode(this, trie_node_base);
191 | }
192 | };
193 |
194 | // This is essentially a smart pointer for read only mmap region for property contexts.
195 | class PropertyInfoAreaFile {
196 | public:
197 | PropertyInfoAreaFile() : mmap_base_(nullptr), mmap_size_(0) {}
198 | ~PropertyInfoAreaFile() { Reset(); }
199 |
200 | PropertyInfoAreaFile(const PropertyInfoAreaFile&) = delete;
201 | void operator=(const PropertyInfoAreaFile&) = delete;
202 | PropertyInfoAreaFile(PropertyInfoAreaFile&&) = default;
203 | PropertyInfoAreaFile& operator=(PropertyInfoAreaFile&&) = default;
204 |
205 | bool LoadDefaultPath();
206 | bool LoadPath(const char* filename);
207 |
208 | const PropertyInfoArea* operator->() const {
209 | return reinterpret_cast(mmap_base_);
210 | }
211 |
212 | explicit operator bool() const { return mmap_base_ != nullptr; }
213 |
214 | void Reset();
215 |
216 | private:
217 | void* mmap_base_;
218 | size_t mmap_size_;
219 | };
220 |
221 | } // namespace properties
222 | } // namespace android
223 |
224 | #endif
225 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/system_properties.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #ifndef _INCLUDE_SYS_SYSTEM_PROPERTIES_H
30 | #define _INCLUDE_SYS_SYSTEM_PROPERTIES_H
31 |
32 | #include
33 | #include
34 | #include
35 | #include
36 |
37 | #include "private/hacks.h"
38 |
39 | __BEGIN_DECLS
40 |
41 | typedef struct prop_info prop_info;
42 |
43 | #define PROP_VALUE_MAX 92
44 |
45 | /*
46 | * Sets system property `name` to `value`, creating the system property if it doesn't already exist.
47 | */
48 | int __system_property_set(const char* __name, const char* __value) __INTRODUCED_IN(12);
49 |
50 | /*
51 | * Returns a `prop_info` corresponding system property `name`, or nullptr if it doesn't exist.
52 | * Use __system_property_read_callback to query the current value.
53 | *
54 | * Property lookup is expensive, so it can be useful to cache the result of this function.
55 | */
56 | const prop_info* __system_property_find(const char* __name);
57 |
58 | /*
59 | * Calls `callback` with a consistent trio of name, value, and serial number for property `pi`.
60 | */
61 | void __system_property_read_callback(const prop_info* __pi,
62 | void (*__callback)(void* __cookie, const char* __name, const char* __value, uint32_t __serial),
63 | void* __cookie) __INTRODUCED_IN(26);
64 |
65 | /*
66 | * Passes a `prop_info` for each system property to the provided
67 | * callback. Use __system_property_read_callback() to read the value.
68 | *
69 | * This method is for inspecting and debugging the property system, and not generally useful.
70 | */
71 | int __system_property_foreach(void (*__callback)(const prop_info* __pi, void* __cookie), void* __cookie)
72 | __INTRODUCED_IN(19);
73 |
74 | /*
75 | * Waits for the specific system property identified by `pi` to be updated
76 | * past `old_serial`. Waits no longer than `relative_timeout`, or forever
77 | * if `relaive_timeout` is null.
78 | *
79 | * If `pi` is null, waits for the global serial number instead.
80 | *
81 | * If you don't know the current serial, use 0.
82 | *
83 | * Returns true and updates `*new_serial_ptr` on success, or false if the call
84 | * timed out.
85 | */
86 | struct timespec;
87 | bool __system_property_wait(const prop_info* __pi, uint32_t __old_serial, uint32_t* __new_serial_ptr, const struct timespec* __relative_timeout)
88 | __INTRODUCED_IN(26);
89 |
90 | /* Deprecated. In Android O and above, there's no limit on property name length. */
91 | #define PROP_NAME_MAX 32
92 | /* Deprecated. Use __system_property_read_callback instead. */
93 | int __system_property_read(const prop_info* __pi, char* __name, char* __value);
94 | /* Deprecated. Use __system_property_read_callback instead. */
95 | int __system_property_get(const char* __name, char* __value);
96 | /* Deprecated. Use __system_property_foreach instead. */
97 | const prop_info* __system_property_find_nth(unsigned __n);
98 |
99 | __END_DECLS
100 |
101 | #endif
102 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/system_properties/context_node.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #pragma once
30 |
31 | #include "private/bionic_lock.h"
32 |
33 | #include "prop_area.h"
34 |
35 | class ContextNode {
36 | public:
37 | ContextNode(const char* context, const char* filename)
38 | : context_(context), pa_(nullptr), no_access_(false), filename_(filename) {
39 | lock_.init(false);
40 | }
41 | ~ContextNode() {
42 | Unmap();
43 | }
44 |
45 | BIONIC_DISALLOW_COPY_AND_ASSIGN(ContextNode);
46 |
47 | bool Open(bool access_rw, bool* fsetxattr_failed);
48 | bool CheckAccessAndOpen();
49 | void ResetAccess();
50 | void Unmap();
51 |
52 | const char* context() const {
53 | return context_;
54 | }
55 | prop_area* pa() {
56 | return pa_;
57 | }
58 |
59 | private:
60 | bool CheckAccess();
61 |
62 | Lock lock_;
63 | const char* context_;
64 | prop_area* pa_;
65 | bool no_access_;
66 | const char* filename_;
67 | };
68 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/system_properties/contexts.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #pragma once
30 |
31 | #include "prop_area.h"
32 | #include "prop_info.h"
33 |
34 | class Contexts {
35 | public:
36 | virtual ~Contexts() {
37 | }
38 |
39 | virtual bool Initialize(bool writable, const char* filename, bool* fsetxattr_failed) = 0;
40 | virtual prop_area* GetPropAreaForName(const char* name) = 0;
41 | virtual prop_area* GetSerialPropArea() = 0;
42 | virtual void ForEach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) = 0;
43 | virtual void ResetAccess() = 0;
44 | virtual void FreeAndUnmap() = 0;
45 | };
46 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/system_properties/contexts_pre_split.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #pragma once
30 |
31 | #include "contexts.h"
32 | #include "prop_area.h"
33 | #include "prop_info.h"
34 |
35 | class ContextsPreSplit : public Contexts {
36 | public:
37 | virtual ~ContextsPreSplit() override {
38 | }
39 |
40 | // We'll never initialize this legacy option as writable, so don't even check the arg.
41 | virtual bool Initialize(bool, const char* filename, bool*) override {
42 | pre_split_prop_area_ = prop_area::map_prop_area(filename);
43 | return pre_split_prop_area_ != nullptr;
44 | }
45 |
46 | virtual prop_area* GetPropAreaForName(const char*) override {
47 | return pre_split_prop_area_;
48 | }
49 |
50 | virtual prop_area* GetSerialPropArea() override {
51 | return pre_split_prop_area_;
52 | }
53 |
54 | virtual void ForEach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) override {
55 | pre_split_prop_area_->foreach (propfn, cookie);
56 | }
57 |
58 | // This is a no-op for pre-split properties as there is only one property file and it is
59 | // accessible by all domains
60 | virtual void ResetAccess() override {
61 | }
62 |
63 | virtual void FreeAndUnmap() override {
64 | prop_area::unmap_prop_area(&pre_split_prop_area_);
65 | }
66 |
67 | private:
68 | prop_area* pre_split_prop_area_ = nullptr;
69 | };
70 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/system_properties/contexts_serialized.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #pragma once
30 |
31 | #include
32 |
33 | #include "context_node.h"
34 | #include "contexts.h"
35 |
36 | class ContextsSerialized : public Contexts {
37 | public:
38 | virtual ~ContextsSerialized() override {
39 | }
40 |
41 | virtual bool Initialize(bool writable, const char* filename, bool* fsetxattr_failed) override;
42 | virtual prop_area* GetPropAreaForName(const char* name) override;
43 | virtual prop_area* GetSerialPropArea() override {
44 | return serial_prop_area_;
45 | }
46 | virtual void ForEach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) override;
47 | virtual void ResetAccess() override;
48 | virtual void FreeAndUnmap() override;
49 |
50 | private:
51 | bool InitializeContextNodes();
52 | bool InitializeProperties();
53 | bool MapSerialPropertyArea(bool access_rw, bool* fsetxattr_failed);
54 |
55 | const char* filename_;
56 | android::properties::PropertyInfoAreaFile property_info_area_file_;
57 | ContextNode* context_nodes_ = nullptr;
58 | size_t num_context_nodes_ = 0;
59 | size_t context_nodes_mmap_size_ = 0;
60 | prop_area* serial_prop_area_ = nullptr;
61 | };
62 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/system_properties/contexts_split.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #pragma once
30 |
31 | #include "contexts.h"
32 |
33 | struct PrefixNode;
34 | class ContextListNode;
35 |
36 | class ContextsSplit : public Contexts {
37 | public:
38 | virtual ~ContextsSplit() override {
39 | }
40 |
41 | virtual bool Initialize(bool writable, const char* filename, bool* fsetxattr_failed) override;
42 | virtual prop_area* GetPropAreaForName(const char* name) override;
43 | virtual prop_area* GetSerialPropArea() override {
44 | return serial_prop_area_;
45 | }
46 | virtual void ForEach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) override;
47 | virtual void ResetAccess() override;
48 | virtual void FreeAndUnmap() override;
49 |
50 | private:
51 | bool MapSerialPropertyArea(bool access_rw, bool* fsetxattr_failed);
52 | bool InitializePropertiesFromFile(const char* filename);
53 | bool InitializeProperties();
54 |
55 | PrefixNode* prefixes_ = nullptr;
56 | ContextListNode* contexts_ = nullptr;
57 | prop_area* serial_prop_area_ = nullptr;
58 | const char* filename_ = nullptr;
59 | };
60 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/system_properties/prop_area.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #pragma once
30 |
31 | #include
32 | #include
33 | #include
34 | #include
35 |
36 | #include "private/bionic_macros.h"
37 |
38 | #include "prop_info.h"
39 |
40 | // Properties are stored in a hybrid trie/binary tree structure.
41 | // Each property's name is delimited at '.' characters, and the tokens are put
42 | // into a trie structure. Siblings at each level of the trie are stored in a
43 | // binary tree. For instance, "ro.secure"="1" could be stored as follows:
44 | //
45 | // +-----+ children +----+ children +--------+
46 | // | |-------------->| ro |-------------->| secure |
47 | // +-----+ +----+ +--------+
48 | // / \ / |
49 | // left / \ right left / | prop +===========+
50 | // v v v +-------->| ro.secure |
51 | // +-----+ +-----+ +-----+ +-----------+
52 | // | net | | sys | | com | | 1 |
53 | // +-----+ +-----+ +-----+ +===========+
54 |
55 | // Represents a node in the trie.
56 | struct prop_bt {
57 | uint32_t namelen;
58 |
59 | // The property trie is updated only by the init process (single threaded) which provides
60 | // property service. And it can be read by multiple threads at the same time.
61 | // As the property trie is not protected by locks, we use atomic_uint_least32_t types for the
62 | // left, right, children "pointers" in the trie node. To make sure readers who see the
63 | // change of "pointers" can also notice the change of prop_bt structure contents pointed by
64 | // the "pointers", we always use release-consume ordering pair when accessing these "pointers".
65 |
66 | // prop "points" to prop_info structure if there is a propery associated with the trie node.
67 | // Its situation is similar to the left, right, children "pointers". So we use
68 | // atomic_uint_least32_t and release-consume ordering to protect it as well.
69 |
70 | // We should also avoid rereading these fields redundantly, since not
71 | // all processor implementations ensure that multiple loads from the
72 | // same field are carried out in the right order.
73 | atomic_uint_least32_t prop;
74 |
75 | atomic_uint_least32_t left;
76 | atomic_uint_least32_t right;
77 |
78 | atomic_uint_least32_t children;
79 |
80 | char name[0];
81 |
82 | prop_bt(const char* name, const uint32_t name_length) {
83 | this->namelen = name_length;
84 | memcpy(this->name, name, name_length);
85 | this->name[name_length] = '\0';
86 | }
87 |
88 | private:
89 | BIONIC_DISALLOW_COPY_AND_ASSIGN(prop_bt);
90 | };
91 |
92 | class prop_area {
93 | public:
94 | static prop_area* map_prop_area_rw(const char* filename, const char* context,
95 | bool* fsetxattr_failed);
96 | static prop_area* map_prop_area(const char* filename);
97 | static void unmap_prop_area(prop_area** pa) {
98 | if (*pa) {
99 | munmap(*pa, pa_size_);
100 | *pa = nullptr;
101 | }
102 | }
103 |
104 | prop_area(const uint32_t magic, const uint32_t version) : magic_(magic), version_(version) {
105 | atomic_init(&serial_, 0u);
106 | memset(reserved_, 0, sizeof(reserved_));
107 | // Allocate enough space for the root node.
108 | bytes_used_ = sizeof(prop_bt);
109 | }
110 |
111 | const prop_info* find(const char* name);
112 | bool add(const char* name, unsigned int namelen, const char* value, unsigned int valuelen);
113 | bool rm(const char *name);
114 |
115 | bool foreach (void (*propfn)(const prop_info* pi, void* cookie), void* cookie);
116 |
117 | atomic_uint_least32_t* serial() {
118 | return &serial_;
119 | }
120 | uint32_t magic() const {
121 | return magic_;
122 | }
123 | uint32_t version() const {
124 | return version_;
125 | }
126 |
127 | private:
128 | static prop_area* map_fd_ro(const int fd);
129 |
130 | void* allocate_obj(const size_t size, uint_least32_t* const off);
131 | prop_bt* new_prop_bt(const char* name, uint32_t namelen, uint_least32_t* const off);
132 | prop_info* new_prop_info(const char* name, uint32_t namelen, const char* value, uint32_t valuelen,
133 | uint_least32_t* const off);
134 | void* to_prop_obj(uint_least32_t off);
135 | prop_bt* to_prop_bt(atomic_uint_least32_t* off_p);
136 | prop_info* to_prop_info(atomic_uint_least32_t* off_p);
137 |
138 | prop_bt* root_node();
139 |
140 | /* resetprop new: traverse through the trie and find the node */
141 | prop_bt *find_prop_bt(prop_bt *const bt, const char* name, bool alloc_if_needed);
142 |
143 | prop_bt* find_prop_bt(prop_bt* const bt, const char* name, uint32_t namelen, bool alloc_if_needed);
144 |
145 | const prop_info* find_property(prop_bt* const trie, const char* name, uint32_t namelen,
146 | const char* value, uint32_t valuelen, bool alloc_if_needed);
147 |
148 | bool foreach_property(prop_bt* const trie, void (*propfn)(const prop_info* pi, void* cookie),
149 | void* cookie);
150 |
151 | // The original design doesn't include pa_size or pa_data_size in the prop_area struct itself.
152 | // Since we'll need to be backwards compatible with that design, we don't gain much by adding it
153 | // now, especially since we don't have any plans to make different property areas different sizes,
154 | // and thus we share these two variables among all instances.
155 | static size_t pa_size_;
156 | static size_t pa_data_size_;
157 |
158 | uint32_t bytes_used_;
159 | atomic_uint_least32_t serial_;
160 | uint32_t magic_;
161 | uint32_t version_;
162 | uint32_t reserved_[28];
163 | char data_[0];
164 |
165 | BIONIC_DISALLOW_COPY_AND_ASSIGN(prop_area);
166 | };
167 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/system_properties/prop_info.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #pragma once
30 |
31 | #include
32 | #include
33 | //#include
34 | #include "../system_properties.h"
35 |
36 | #include "private/bionic_macros.h"
37 |
38 | // The C11 standard doesn't allow atomic loads from const fields,
39 | // though C++11 does. Fudge it until standards get straightened out.
40 | static inline uint_least32_t load_const_atomic(const atomic_uint_least32_t* s, memory_order mo) {
41 | atomic_uint_least32_t* non_const_s = const_cast(s);
42 | return atomic_load_explicit(non_const_s, mo);
43 | }
44 |
45 | struct prop_info {
46 | // Read only properties will not set anything but the bottom most bit of serial and the top byte.
47 | // We borrow the 2nd from the top byte for extra flags, and use the bottom most bit of that for
48 | // our first user, kLongFlag.
49 | constexpr static uint32_t kLongFlag = 1 << 16;
50 |
51 | // The error message fits in part of a union with the previous 92 char property value so there
52 | // must be room left over after the error message for the offset to the new longer property value
53 | // and future expansion fields if needed. Note that this value cannot ever increase. The offset
54 | // to the new longer property value appears immediately after it, so an increase of this size will
55 | // break compatibility.
56 | constexpr static size_t kLongLegacyErrorBufferSize = 56;
57 |
58 | public:
59 | atomic_uint_least32_t serial;
60 | // we need to keep this buffer around because the property
61 | // value can be modified whereas name is constant.
62 | union {
63 | char value[PROP_VALUE_MAX];
64 | struct {
65 | char error_message[kLongLegacyErrorBufferSize];
66 | uint32_t offset;
67 | } long_property;
68 | };
69 | char name[0];
70 |
71 | bool is_long() const {
72 | return (load_const_atomic(&serial, memory_order_relaxed) & kLongFlag) != 0;
73 | }
74 |
75 | const char* long_value() const {
76 | // We can't store pointers here since this is shared memory that will have different absolute
77 | // pointers in different processes. We don't have data_ from prop_area, but since we know
78 | // `this` is data_ + some offset and long_value is data_ + some other offset, we calculate the
79 | // offset from `this` to long_value and store it as long_property.offset.
80 | return reinterpret_cast(this) + long_property.offset;
81 | }
82 |
83 | prop_info(const char* name, uint32_t namelen, const char* value, uint32_t valuelen);
84 | prop_info(const char* name, uint32_t namelen, uint32_t long_offset);
85 |
86 | private:
87 | BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(prop_info);
88 | };
89 |
90 | static_assert(sizeof(prop_info) == 96, "sizeof struct prop_info must be 96 bytes");
91 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/include/system_properties/system_properties.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #pragma once
30 |
31 | #include
32 | #include
33 | //#include
34 | #include "../system_properties.h"
35 |
36 | #include "contexts.h"
37 | #include "contexts_pre_split.h"
38 | #include "contexts_serialized.h"
39 | #include "contexts_split.h"
40 |
41 | constexpr int PROP_FILENAME_MAX = 1024;
42 |
43 | class SystemProperties {
44 | public:
45 | friend struct LocalPropertyTestState;
46 | friend class SystemPropertiesTest;
47 | // Note that system properties are initialized before libc calls static initializers, so
48 | // doing any initialization in this constructor is an error. Even a Constructor that zero
49 | // initializes this class will clobber the previous property initialization.
50 | // We rely on the static SystemProperties in libc to be placed in .bss and zero initialized.
51 | SystemProperties() = default;
52 | // Special constructor for testing that also zero initializes the important members.
53 | explicit SystemProperties(bool initialized) : initialized_(initialized) {
54 | }
55 |
56 | BIONIC_DISALLOW_COPY_AND_ASSIGN(SystemProperties);
57 |
58 | bool Init(const char* filename);
59 | bool AreaInit(const char* filename, bool* fsetxattr_failed);
60 | uint32_t AreaSerial();
61 | const prop_info* Find(const char* name);
62 | int Read(const prop_info* pi, char* name, char* value);
63 | void ReadCallback(const prop_info* pi,
64 | void (*callback)(void* cookie, const char* name, const char* value,
65 | uint32_t serial),
66 | void* cookie);
67 | int Get(const char* name, char* value);
68 | int Update(prop_info* pi, const char* value, unsigned int len);
69 | int Add(const char* name, unsigned int namelen, const char* value, unsigned int valuelen);
70 | int Delete(const char *name);
71 | uint32_t Serial(const prop_info* pi);
72 | uint32_t WaitAny(uint32_t old_serial);
73 | bool Wait(const prop_info* pi, uint32_t old_serial, uint32_t* new_serial_ptr,
74 | const timespec* relative_timeout);
75 | const prop_info* FindNth(unsigned n);
76 | int Foreach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie);
77 |
78 | private:
79 | // We don't want to use new or malloc in properties (b/31659220), and we don't want to waste a
80 | // full page by using mmap(), so we set aside enough space to create any context of the three
81 | // contexts.
82 | static constexpr size_t kMaxContextsAlign =
83 | MAX(alignof(ContextsSerialized), MAX(alignof(ContextsSplit), alignof(ContextsPreSplit)));
84 | static constexpr size_t kMaxContextsSize =
85 | MAX(sizeof(ContextsSerialized), MAX(sizeof(ContextsSplit), sizeof(ContextsPreSplit)));
86 | alignas(kMaxContextsAlign) char contexts_data_[kMaxContextsSize];
87 | Contexts* contexts_;
88 |
89 | bool initialized_;
90 | char property_filename_[PROP_FILENAME_MAX];
91 | };
92 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/prop_area.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #include "system_properties/prop_area.h"
30 |
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 |
40 | #include
41 |
42 | #include
43 |
44 | constexpr size_t PA_SIZE = 128 * 1024;
45 | constexpr uint32_t PROP_AREA_MAGIC = 0x504f5250;
46 | constexpr uint32_t PROP_AREA_VERSION = 0xfc6ed0ab;
47 |
48 | size_t prop_area::pa_size_ = 0;
49 | size_t prop_area::pa_data_size_ = 0;
50 |
51 | prop_area* prop_area::map_prop_area_rw(const char* filename, const char* context,
52 | bool* fsetxattr_failed) {
53 | /* dev is a tmpfs that we can use to carve a shared workspace
54 | * out of, so let's do that...
55 | */
56 | const int fd = open(filename, O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC | O_EXCL, 0444);
57 |
58 | if (fd < 0) {
59 | if (errno == EACCES) {
60 | /* for consistency with the case where the process has already
61 | * mapped the page in and segfaults when trying to write to it
62 | */
63 | abort();
64 | }
65 | return nullptr;
66 | }
67 |
68 | if (context) {
69 | if (fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0) != 0) {
70 | async_safe_format_log(ANDROID_LOG_ERROR, "libc",
71 | "fsetxattr failed to set context (%s) for \"%s\"", context, filename);
72 | /*
73 | * fsetxattr() will fail during system properties tests due to selinux policy.
74 | * We do not want to create a custom policy for the tester, so we will continue in
75 | * this function but set a flag that an error has occurred.
76 | * Init, which is the only daemon that should ever call this function will abort
77 | * when this error occurs.
78 | * Otherwise, the tester will ignore it and continue, albeit without any selinux
79 | * property separation.
80 | */
81 | if (fsetxattr_failed) {
82 | *fsetxattr_failed = true;
83 | }
84 | }
85 | }
86 |
87 | if (ftruncate(fd, PA_SIZE) < 0) {
88 | close(fd);
89 | return nullptr;
90 | }
91 |
92 | pa_size_ = PA_SIZE;
93 | pa_data_size_ = pa_size_ - sizeof(prop_area);
94 |
95 | void* const memory_area = mmap(nullptr, pa_size_, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
96 | if (memory_area == MAP_FAILED) {
97 | close(fd);
98 | return nullptr;
99 | }
100 |
101 | prop_area* pa = new (memory_area) prop_area(PROP_AREA_MAGIC, PROP_AREA_VERSION);
102 |
103 | close(fd);
104 | return pa;
105 | }
106 |
107 | prop_area* prop_area::map_fd_ro(const int fd) {
108 | struct stat fd_stat;
109 | if (fstat(fd, &fd_stat) < 0) {
110 | return nullptr;
111 | }
112 |
113 | if ((fd_stat.st_uid != 0) || (fd_stat.st_gid != 0) ||
114 | ((fd_stat.st_mode & (S_IWGRP | S_IWOTH)) != 0) ||
115 | (fd_stat.st_size < static_cast(sizeof(prop_area)))) {
116 | return nullptr;
117 | }
118 |
119 | pa_size_ = fd_stat.st_size;
120 | pa_data_size_ = pa_size_ - sizeof(prop_area);
121 |
122 | /* resetprop: add PROT_WRITE */
123 | void* const map_result = mmap(nullptr, pa_size_, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
124 | if (map_result == MAP_FAILED) {
125 | return nullptr;
126 | }
127 |
128 | prop_area* pa = reinterpret_cast(map_result);
129 | if ((pa->magic() != PROP_AREA_MAGIC) || (pa->version() != PROP_AREA_VERSION)) {
130 | munmap(pa, pa_size_);
131 | return nullptr;
132 | }
133 |
134 | return pa;
135 | }
136 |
137 | prop_area* prop_area::map_prop_area(const char* filename) {
138 | /* resetprop: O_RDONLY -> O_RDWR */
139 | int fd = open(filename, O_CLOEXEC | O_NOFOLLOW | O_RDWR);
140 | if (fd == -1) return nullptr;
141 |
142 | prop_area* map_result = map_fd_ro(fd);
143 | close(fd);
144 |
145 | return map_result;
146 | }
147 |
148 | void* prop_area::allocate_obj(const size_t size, uint_least32_t* const off) {
149 | const size_t aligned = __BIONIC_ALIGN(size, sizeof(uint_least32_t));
150 | if (bytes_used_ + aligned > pa_data_size_) {
151 | return nullptr;
152 | }
153 |
154 | *off = bytes_used_;
155 | bytes_used_ += aligned;
156 | return data_ + *off;
157 | }
158 |
159 | prop_bt* prop_area::new_prop_bt(const char* name, uint32_t namelen, uint_least32_t* const off) {
160 | uint_least32_t new_offset;
161 | void* const p = allocate_obj(sizeof(prop_bt) + namelen + 1, &new_offset);
162 | if (p != nullptr) {
163 | prop_bt* bt = new (p) prop_bt(name, namelen);
164 | *off = new_offset;
165 | return bt;
166 | }
167 |
168 | return nullptr;
169 | }
170 |
171 | prop_info* prop_area::new_prop_info(const char* name, uint32_t namelen, const char* value,
172 | uint32_t valuelen, uint_least32_t* const off) {
173 | uint_least32_t new_offset;
174 | void* const p = allocate_obj(sizeof(prop_info) + namelen + 1, &new_offset);
175 | if (p == nullptr) return nullptr;
176 |
177 | prop_info* info;
178 | if (valuelen >= PROP_VALUE_MAX) {
179 | uint32_t long_value_offset = 0;
180 | char* long_location = reinterpret_cast(allocate_obj(valuelen + 1, &long_value_offset));
181 | if (!long_location) return nullptr;
182 |
183 | memcpy(long_location, value, valuelen);
184 | long_location[valuelen] = '\0';
185 |
186 | // Both new_offset and long_value_offset are offsets based off of data_, however prop_info
187 | // does not know what data_ is, so we change this offset to be an offset from the prop_info
188 | // pointer that contains it.
189 | long_value_offset -= new_offset;
190 |
191 | info = new (p) prop_info(name, namelen, long_value_offset);
192 | } else {
193 | info = new (p) prop_info(name, namelen, value, valuelen);
194 | }
195 | *off = new_offset;
196 | return info;
197 | }
198 |
199 | void* prop_area::to_prop_obj(uint_least32_t off) {
200 | if (off > pa_data_size_) return nullptr;
201 |
202 | return (data_ + off);
203 | }
204 |
205 | inline prop_bt* prop_area::to_prop_bt(atomic_uint_least32_t* off_p) {
206 | uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume);
207 | return reinterpret_cast(to_prop_obj(off));
208 | }
209 |
210 | inline prop_info* prop_area::to_prop_info(atomic_uint_least32_t* off_p) {
211 | uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume);
212 | return reinterpret_cast(to_prop_obj(off));
213 | }
214 |
215 | inline prop_bt* prop_area::root_node() {
216 | return reinterpret_cast(to_prop_obj(0));
217 | }
218 |
219 | static int cmp_prop_name(const char* one, uint32_t one_len, const char* two, uint32_t two_len) {
220 | if (one_len < two_len)
221 | return -1;
222 | else if (one_len > two_len)
223 | return 1;
224 | else
225 | return strncmp(one, two, one_len);
226 | }
227 |
228 | prop_bt* prop_area::find_prop_bt(prop_bt* const bt, const char* name, uint32_t namelen,
229 | bool alloc_if_needed) {
230 | prop_bt* current = bt;
231 | while (true) {
232 | if (!current) {
233 | return nullptr;
234 | }
235 |
236 | const int ret = cmp_prop_name(name, namelen, current->name, current->namelen);
237 | if (ret == 0) {
238 | return current;
239 | }
240 |
241 | if (ret < 0) {
242 | uint_least32_t left_offset = atomic_load_explicit(¤t->left, memory_order_relaxed);
243 | if (left_offset != 0) {
244 | current = to_prop_bt(¤t->left);
245 | } else {
246 | if (!alloc_if_needed) {
247 | return nullptr;
248 | }
249 |
250 | uint_least32_t new_offset;
251 | prop_bt* new_bt = new_prop_bt(name, namelen, &new_offset);
252 | if (new_bt) {
253 | atomic_store_explicit(¤t->left, new_offset, memory_order_release);
254 | }
255 | return new_bt;
256 | }
257 | } else {
258 | uint_least32_t right_offset = atomic_load_explicit(¤t->right, memory_order_relaxed);
259 | if (right_offset != 0) {
260 | current = to_prop_bt(¤t->right);
261 | } else {
262 | if (!alloc_if_needed) {
263 | return nullptr;
264 | }
265 |
266 | uint_least32_t new_offset;
267 | prop_bt* new_bt = new_prop_bt(name, namelen, &new_offset);
268 | if (new_bt) {
269 | atomic_store_explicit(¤t->right, new_offset, memory_order_release);
270 | }
271 | return new_bt;
272 | }
273 | }
274 | }
275 | }
276 |
277 | /* resetprop new: traverse through the trie and find the node.
278 | * This was originally part of prop_area::find_property. */
279 | prop_bt *prop_area::find_prop_bt(prop_bt *const trie, const char *name, bool alloc_if_needed) {
280 | if (!trie) return nullptr;
281 |
282 | const char* remaining_name = name;
283 | prop_bt* current = trie;
284 | while (true) {
285 | const char* sep = strchr(remaining_name, '.');
286 | const bool want_subtree = (sep != nullptr);
287 | const uint32_t substr_size = (want_subtree) ? sep - remaining_name : strlen(remaining_name);
288 |
289 | if (!substr_size) {
290 | return nullptr;
291 | }
292 |
293 | prop_bt* root = nullptr;
294 | uint_least32_t children_offset = atomic_load_explicit(¤t->children, memory_order_relaxed);
295 | if (children_offset != 0) {
296 | root = to_prop_bt(¤t->children);
297 | } else if (alloc_if_needed) {
298 | uint_least32_t new_offset;
299 | root = new_prop_bt(remaining_name, substr_size, &new_offset);
300 | if (root) {
301 | atomic_store_explicit(¤t->children, new_offset, memory_order_release);
302 | }
303 | }
304 |
305 | if (!root) {
306 | return nullptr;
307 | }
308 |
309 | current = find_prop_bt(root, remaining_name, substr_size, alloc_if_needed);
310 | if (!current) {
311 | return nullptr;
312 | }
313 |
314 | if (!want_subtree) break;
315 |
316 | remaining_name = sep + 1;
317 | }
318 | return current;
319 | }
320 |
321 | /* resetprop: move trie traversal logic out of the function */
322 | const prop_info* prop_area::find_property(prop_bt* const trie, const char* name, uint32_t namelen,
323 | const char* value, uint32_t valuelen,
324 | bool alloc_if_needed) {
325 | prop_bt* current = find_prop_bt(trie, name, alloc_if_needed);
326 | if (!current)
327 | return nullptr;
328 |
329 | uint_least32_t prop_offset = atomic_load_explicit(¤t->prop, memory_order_relaxed);
330 | if (prop_offset != 0) {
331 | return to_prop_info(¤t->prop);
332 | } else if (alloc_if_needed) {
333 | uint_least32_t new_offset;
334 | prop_info* new_info = new_prop_info(name, namelen, value, valuelen, &new_offset);
335 | if (new_info) {
336 | atomic_store_explicit(¤t->prop, new_offset, memory_order_release);
337 | }
338 |
339 | return new_info;
340 | } else {
341 | return nullptr;
342 | }
343 | }
344 |
345 | bool prop_area::foreach_property(prop_bt* const trie,
346 | void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
347 | if (!trie) return false;
348 |
349 | uint_least32_t left_offset = atomic_load_explicit(&trie->left, memory_order_relaxed);
350 | if (left_offset != 0) {
351 | const int err = foreach_property(to_prop_bt(&trie->left), propfn, cookie);
352 | if (err < 0) return false;
353 | }
354 | uint_least32_t prop_offset = atomic_load_explicit(&trie->prop, memory_order_relaxed);
355 | if (prop_offset != 0) {
356 | prop_info* info = to_prop_info(&trie->prop);
357 | if (!info) return false;
358 | propfn(info, cookie);
359 | }
360 | uint_least32_t children_offset = atomic_load_explicit(&trie->children, memory_order_relaxed);
361 | if (children_offset != 0) {
362 | const int err = foreach_property(to_prop_bt(&trie->children), propfn, cookie);
363 | if (err < 0) return false;
364 | }
365 | uint_least32_t right_offset = atomic_load_explicit(&trie->right, memory_order_relaxed);
366 | if (right_offset != 0) {
367 | const int err = foreach_property(to_prop_bt(&trie->right), propfn, cookie);
368 | if (err < 0) return false;
369 | }
370 |
371 | return true;
372 | }
373 |
374 | const prop_info* prop_area::find(const char* name) {
375 | return find_property(root_node(), name, strlen(name), nullptr, 0, false);
376 | }
377 |
378 | bool prop_area::add(const char* name, unsigned int namelen, const char* value,
379 | unsigned int valuelen) {
380 | return find_property(root_node(), name, namelen, value, valuelen, true);
381 | }
382 |
383 | bool prop_area::rm(const char *name) {
384 | prop_bt* node = find_prop_bt(root_node(), name, false);
385 | if (!node)
386 | return false;
387 | uint_least32_t new_offset = 0;
388 | atomic_store_explicit(&node->prop, new_offset, memory_order_release);
389 | return true;
390 | }
391 |
392 | bool prop_area::foreach (void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
393 | return foreach_property(root_node(), propfn, cookie);
394 | }
395 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/prop_info.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #include "system_properties/prop_info.h"
30 |
31 | #include
32 |
33 | constexpr static const char kLongLegacyError[] =
34 | "Must use __system_property_read_callback() to read";
35 | static_assert(sizeof(kLongLegacyError) < prop_info::kLongLegacyErrorBufferSize,
36 | "Error message for long properties read by legacy libc must fit within 56 chars");
37 |
38 | prop_info::prop_info(const char* name, uint32_t namelen, const char* value, uint32_t valuelen) {
39 | memcpy(this->name, name, namelen);
40 | this->name[namelen] = '\0';
41 | atomic_init(&this->serial, valuelen << 24);
42 | memcpy(this->value, value, valuelen);
43 | this->value[valuelen] = '\0';
44 | }
45 |
46 | prop_info::prop_info(const char* name, uint32_t namelen, uint32_t long_offset) {
47 | memcpy(this->name, name, namelen);
48 | this->name[namelen] = '\0';
49 |
50 | atomic_uint_least32_t error_value_len = sizeof(kLongLegacyError) - 1;
51 | atomic_init(&this->serial, error_value_len << 24 | kLongFlag);
52 | memcpy(this->long_property.error_message, kLongLegacyError, sizeof(kLongLegacyError));
53 |
54 | this->long_property.offset = long_offset;
55 | }
56 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/property_info_parser.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) 2017 The Android Open Source Project
3 | //
4 | // Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | // You may obtain a copy of the License at
7 | //
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | //
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 | //
16 |
17 | #include "property_info_parser/property_info_parser.h"
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | namespace android {
27 | namespace properties {
28 |
29 | namespace {
30 |
31 | // Binary search to find index of element in an array compared via f(search).
32 | template
33 | int Find(uint32_t array_length, F&& f) {
34 | int bottom = 0;
35 | int top = array_length - 1;
36 | while (top >= bottom) {
37 | int search = (top + bottom) / 2;
38 |
39 | auto cmp = f(search);
40 |
41 | if (cmp == 0) return search;
42 | if (cmp < 0) bottom = search + 1;
43 | if (cmp > 0) top = search - 1;
44 | }
45 | return -1;
46 | }
47 |
48 | } // namespace
49 |
50 | // Binary search the list of contexts to find the index of a given context string.
51 | // Only should be used for TrieSerializer to construct the Trie.
52 | int PropertyInfoArea::FindContextIndex(const char* context) const {
53 | return Find(num_contexts(), [this, context](auto array_offset) {
54 | auto string_offset = uint32_array(contexts_array_offset())[array_offset];
55 | return strcmp(c_string(string_offset), context);
56 | });
57 | }
58 |
59 | // Binary search the list of types to find the index of a given type string.
60 | // Only should be used for TrieSerializer to construct the Trie.
61 | int PropertyInfoArea::FindTypeIndex(const char* type) const {
62 | return Find(num_types(), [this, type](auto array_offset) {
63 | auto string_offset = uint32_array(types_array_offset())[array_offset];
64 | return strcmp(c_string(string_offset), type);
65 | });
66 | }
67 |
68 | // Binary search the list of children nodes to find a TrieNode for a given property piece.
69 | // Used to traverse the Trie in GetPropertyInfoIndexes().
70 | bool TrieNode::FindChildForString(const char* name, uint32_t namelen, TrieNode* child) const {
71 | auto node_index = Find(trie_node_base_->num_child_nodes, [this, name, namelen](auto array_offset) {
72 | const char* child_name = child_node(array_offset).name();
73 | int cmp = strncmp(child_name, name, namelen);
74 | if (cmp == 0 && child_name[namelen] != '\0') {
75 | // We use strncmp() since name isn't null terminated, but we don't want to match only a
76 | // prefix of a child node's name, so we check here if we did only match a prefix and
77 | // return 1, to indicate to the binary search to search earlier in the array for the real
78 | // match.
79 | return 1;
80 | }
81 | return cmp;
82 | });
83 |
84 | if (node_index == -1) {
85 | return false;
86 | }
87 | *child = child_node(node_index);
88 | return true;
89 | }
90 |
91 | void PropertyInfoArea::CheckPrefixMatch(const char* remaining_name, const TrieNode& trie_node,
92 | uint32_t* context_index, uint32_t* type_index) const {
93 | const uint32_t remaining_name_size = strlen(remaining_name);
94 | for (uint32_t i = 0; i < trie_node.num_prefixes(); ++i) {
95 | auto prefix_len = trie_node.prefix(i)->namelen;
96 | if (prefix_len > remaining_name_size) continue;
97 |
98 | if (!strncmp(c_string(trie_node.prefix(i)->name_offset), remaining_name, prefix_len)) {
99 | if (trie_node.prefix(i)->context_index != ~0u) {
100 | *context_index = trie_node.prefix(i)->context_index;
101 | }
102 | if (trie_node.prefix(i)->type_index != ~0u) {
103 | *type_index = trie_node.prefix(i)->type_index;
104 | }
105 | return;
106 | }
107 | }
108 | }
109 |
110 | void PropertyInfoArea::GetPropertyInfoIndexes(const char* name, uint32_t* context_index,
111 | uint32_t* type_index) const {
112 | uint32_t return_context_index = ~0u;
113 | uint32_t return_type_index = ~0u;
114 | const char* remaining_name = name;
115 | auto trie_node = root_node();
116 | while (true) {
117 | const char* sep = strchr(remaining_name, '.');
118 |
119 | // Apply prefix match for prefix deliminated with '.'
120 | if (trie_node.context_index() != ~0u) {
121 | return_context_index = trie_node.context_index();
122 | }
123 | if (trie_node.type_index() != ~0u) {
124 | return_type_index = trie_node.type_index();
125 | }
126 |
127 | // Check prefixes at this node. This comes after the node check since these prefixes are by
128 | // definition longer than the node itself.
129 | CheckPrefixMatch(remaining_name, trie_node, &return_context_index, &return_type_index);
130 |
131 | if (sep == nullptr) {
132 | break;
133 | }
134 |
135 | const uint32_t substr_size = sep - remaining_name;
136 | TrieNode child_node;
137 | if (!trie_node.FindChildForString(remaining_name, substr_size, &child_node)) {
138 | break;
139 | }
140 |
141 | trie_node = child_node;
142 | remaining_name = sep + 1;
143 | }
144 |
145 | // We've made it to a leaf node, so check contents and return appropriately.
146 | // Check exact matches
147 | for (uint32_t i = 0; i < trie_node.num_exact_matches(); ++i) {
148 | if (!strcmp(c_string(trie_node.exact_match(i)->name_offset), remaining_name)) {
149 | if (context_index != nullptr) {
150 | if (trie_node.exact_match(i)->context_index != ~0u) {
151 | *context_index = trie_node.exact_match(i)->context_index;
152 | } else {
153 | *context_index = return_context_index;
154 | }
155 | }
156 | if (type_index != nullptr) {
157 | if (trie_node.exact_match(i)->type_index != ~0u) {
158 | *type_index = trie_node.exact_match(i)->type_index;
159 | } else {
160 | *type_index = return_type_index;
161 | }
162 | }
163 | return;
164 | }
165 | }
166 | // Check prefix matches for prefixes not deliminated with '.'
167 | CheckPrefixMatch(remaining_name, trie_node, &return_context_index, &return_type_index);
168 | // Return previously found prefix match.
169 | if (context_index != nullptr) *context_index = return_context_index;
170 | if (type_index != nullptr) *type_index = return_type_index;
171 | return;
172 | }
173 |
174 | void PropertyInfoArea::GetPropertyInfo(const char* property, const char** context,
175 | const char** type) const {
176 | uint32_t context_index;
177 | uint32_t type_index;
178 | GetPropertyInfoIndexes(property, &context_index, &type_index);
179 | if (context != nullptr) {
180 | if (context_index == ~0u) {
181 | *context = nullptr;
182 | } else {
183 | *context = this->context(context_index);
184 | }
185 | }
186 | if (type != nullptr) {
187 | if (type_index == ~0u) {
188 | *type = nullptr;
189 | } else {
190 | *type = this->type(type_index);
191 | }
192 | }
193 | }
194 |
195 | bool PropertyInfoAreaFile::LoadDefaultPath() {
196 | return LoadPath("/dev/__properties__/property_info");
197 | }
198 |
199 | bool PropertyInfoAreaFile::LoadPath(const char* filename) {
200 | int fd = open(filename, O_CLOEXEC | O_NOFOLLOW | O_RDONLY);
201 |
202 | struct stat fd_stat;
203 | if (fstat(fd, &fd_stat) < 0) {
204 | close(fd);
205 | return false;
206 | }
207 |
208 | if ((fd_stat.st_uid != 0) || (fd_stat.st_gid != 0) ||
209 | ((fd_stat.st_mode & (S_IWGRP | S_IWOTH)) != 0) ||
210 | (fd_stat.st_size < static_cast(sizeof(PropertyInfoArea)))) {
211 | close(fd);
212 | return false;
213 | }
214 |
215 | auto mmap_size = fd_stat.st_size;
216 |
217 | void* map_result = mmap(nullptr, mmap_size, PROT_READ, MAP_SHARED, fd, 0);
218 | if (map_result == MAP_FAILED) {
219 | close(fd);
220 | return false;
221 | }
222 |
223 | auto property_info_area = reinterpret_cast(map_result);
224 | if (property_info_area->minimum_supported_version() > 1 ||
225 | property_info_area->size() != mmap_size) {
226 | munmap(map_result, mmap_size);
227 | close(fd);
228 | return false;
229 | }
230 |
231 | close(fd);
232 | mmap_base_ = map_result;
233 | mmap_size_ = mmap_size;
234 | return true;
235 | }
236 |
237 | void PropertyInfoAreaFile::Reset() {
238 | if (mmap_size_ > 0) {
239 | munmap(mmap_base_, mmap_size_);
240 | }
241 | mmap_base_ = nullptr;
242 | mmap_size_ = 0;
243 | }
244 |
245 | } // namespace properties
246 | } // namespace android
247 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/system_properties.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2008 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #include "system_properties/system_properties.h"
30 |
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include
38 |
39 | #include
40 |
41 | #include
42 |
43 | #include "private/ErrnoRestorer.h"
44 | #include "private/bionic_futex.h"
45 |
46 | #include "system_properties/context_node.h"
47 | #include "system_properties/prop_area.h"
48 | #include "system_properties/prop_info.h"
49 |
50 | #define SERIAL_DIRTY(serial) ((serial)&1)
51 | #define SERIAL_VALUE_LEN(serial) ((serial) >> 24)
52 |
53 | static bool is_dir(const char* pathname) {
54 | struct stat info;
55 | if (stat(pathname, &info) == -1) {
56 | return false;
57 | }
58 | return S_ISDIR(info.st_mode);
59 | }
60 | /*
61 | #define PROP_SERVICE_NAME "property_service"
62 | #define PROP_FILENAME "/dev/__properties__"
63 | */
64 | bool SystemProperties::Init(const char* filename) { // "/dev/__properties__"
65 | // This is called from __libc_init_common, and should leave errno at 0 (http://b/37248982).
66 | ErrnoRestorer errno_restorer;
67 |
68 | if (initialized_) {
69 | /* resetprop remove */
70 | // contexts_->ResetAccess();
71 | return true;
72 | }
73 |
74 | if (strlen(filename) >= PROP_FILENAME_MAX) {
75 | return false;
76 | }
77 | strcpy(property_filename_, filename);
78 |
79 | if (is_dir(property_filename_)) {
80 | if (access("/dev/__properties__/property_info", R_OK) == 0) {
81 | contexts_ = new (contexts_data_) ContextsSerialized();
82 | if (!contexts_->Initialize(false, property_filename_, nullptr)) {
83 | return false;
84 | }
85 | } else {
86 | contexts_ = new (contexts_data_) ContextsSplit();
87 | if (!contexts_->Initialize(false, property_filename_, nullptr)) {
88 | return false;
89 | }
90 | }
91 | } else {
92 | contexts_ = new (contexts_data_) ContextsPreSplit();
93 | if (!contexts_->Initialize(false, property_filename_, nullptr)) {
94 | return false;
95 | }
96 | }
97 | initialized_ = true;
98 | return true;
99 | }
100 |
101 | bool SystemProperties::AreaInit(const char* filename, bool* fsetxattr_failed) {
102 | if (strlen(filename) >= PROP_FILENAME_MAX) {
103 | return false;
104 | }
105 | strcpy(property_filename_, filename);
106 |
107 | contexts_ = new (contexts_data_) ContextsSerialized();
108 | if (!contexts_->Initialize(true, property_filename_, fsetxattr_failed)) {
109 | return false;
110 | }
111 | initialized_ = true;
112 | return true;
113 | }
114 |
115 | uint32_t SystemProperties::AreaSerial() {
116 | if (!initialized_) {
117 | return -1;
118 | }
119 |
120 | prop_area* pa = contexts_->GetSerialPropArea();
121 | if (!pa) {
122 | return -1;
123 | }
124 |
125 | // Make sure this read fulfilled before __system_property_serial
126 | return atomic_load_explicit(pa->serial(), memory_order_acquire);
127 | }
128 |
129 | const prop_info* SystemProperties::Find(const char* name) {
130 | if (!initialized_) {
131 | return nullptr;
132 | }
133 |
134 | prop_area* pa = contexts_->GetPropAreaForName(name);
135 | if (!pa) {
136 | async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied finding property \"%s\"", name);
137 | return nullptr;
138 | }
139 |
140 | return pa->find(name);
141 | }
142 |
143 | static bool is_read_only(const char* name) {
144 | return strncmp(name, "ro.", 3) == 0;
145 | }
146 |
147 | int SystemProperties::Read(const prop_info* pi, char* name, char* value) {
148 | while (true) {
149 | uint32_t serial = Serial(pi); // acquire semantics
150 | size_t len = SERIAL_VALUE_LEN(serial);
151 | memcpy(value, pi->value, len + 1);
152 | // TODO: Fix the synchronization scheme here.
153 | // There is no fully supported way to implement this kind
154 | // of synchronization in C++11, since the memcpy races with
155 | // updates to pi, and the data being accessed is not atomic.
156 | // The following fence is unintuitive, but would be the
157 | // correct one if memcpy used memory_order_relaxed atomic accesses.
158 | // In practice it seems unlikely that the generated code would
159 | // would be any different, so this should be OK.
160 | atomic_thread_fence(memory_order_acquire);
161 | if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) {
162 | if (name != nullptr) {
163 | size_t namelen = strlcpy(name, pi->name, PROP_NAME_MAX);
164 | if (namelen >= PROP_NAME_MAX) {
165 | async_safe_format_log(ANDROID_LOG_ERROR, "libc",
166 | "The property name length for \"%s\" is >= %d;"
167 | " please use __system_property_read_callback"
168 | " to read this property. (the name is truncated to \"%s\")",
169 | pi->name, PROP_NAME_MAX - 1, name);
170 | }
171 | }
172 | if (is_read_only(pi->name) && pi->is_long()) {
173 | async_safe_format_log(
174 | ANDROID_LOG_ERROR, "libc",
175 | "The property \"%s\" has a value with length %zu that is too large for"
176 | " __system_property_get()/__system_property_read(); use"
177 | " __system_property_read_callback() instead.",
178 | pi->name, strlen(pi->long_value()));
179 | }
180 | return len;
181 | }
182 | }
183 | }
184 |
185 | void SystemProperties::ReadCallback(const prop_info* pi,
186 | void (*callback)(void* cookie, const char* name,
187 | const char* value, uint32_t serial),
188 | void* cookie) {
189 | // Read only properties don't need to copy the value to a temporary buffer, since it can never
190 | // change.
191 | if (is_read_only(pi->name)) {
192 | uint32_t serial = Serial(pi);
193 | if (pi->is_long()) {
194 | callback(cookie, pi->name, pi->long_value(), serial);
195 | } else {
196 | callback(cookie, pi->name, pi->value, serial);
197 | }
198 | return;
199 | }
200 |
201 | while (true) {
202 | uint32_t serial = Serial(pi); // acquire semantics
203 | size_t len = SERIAL_VALUE_LEN(serial);
204 | char value_buf[len + 1];
205 |
206 | memcpy(value_buf, pi->value, len);
207 | value_buf[len] = '\0';
208 |
209 | // TODO: see todo in Read function
210 | atomic_thread_fence(memory_order_acquire);
211 | if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) {
212 | callback(cookie, pi->name, value_buf, serial);
213 | return;
214 | }
215 | }
216 | }
217 |
218 | int SystemProperties::Get(const char* name, char* value) {
219 | const prop_info* pi = Find(name);
220 |
221 | if (pi != nullptr) {
222 | return Read(pi, nullptr, value);
223 | } else {
224 | value[0] = 0;
225 | return 0;
226 | }
227 | }
228 |
229 | int SystemProperties::Update(prop_info* pi, const char* value, unsigned int len) {
230 | if (len >= PROP_VALUE_MAX) {
231 | return -1;
232 | }
233 |
234 | if (!initialized_) {
235 | return -1;
236 | }
237 |
238 | prop_area* pa = contexts_->GetSerialPropArea();
239 | if (!pa) {
240 | return -1;
241 | }
242 |
243 | uint32_t serial = atomic_load_explicit(&pi->serial, memory_order_relaxed);
244 | serial |= 1;
245 | atomic_store_explicit(&pi->serial, serial, memory_order_relaxed);
246 | // The memcpy call here also races. Again pretend it
247 | // used memory_order_relaxed atomics, and use the analogous
248 | // counterintuitive fence.
249 | atomic_thread_fence(memory_order_release);
250 | strlcpy(pi->value, value, len + 1);
251 |
252 | atomic_store_explicit(&pi->serial, (len << 24) | ((serial + 1) & 0xffffff), memory_order_release);
253 | __futex_wake(&pi->serial, INT32_MAX);
254 |
255 | atomic_store_explicit(pa->serial(), atomic_load_explicit(pa->serial(), memory_order_relaxed) + 1,
256 | memory_order_release);
257 | __futex_wake(pa->serial(), INT32_MAX);
258 |
259 | return 0;
260 | }
261 |
262 | int SystemProperties::Add(const char* name, unsigned int namelen, const char* value,
263 | unsigned int valuelen) {
264 | if (valuelen >= PROP_VALUE_MAX && !is_read_only(name)) {
265 | return -1;
266 | }
267 |
268 | if (namelen < 1) {
269 | return -1;
270 | }
271 |
272 | if (!initialized_) {
273 | return -1;
274 | }
275 |
276 | prop_area* serial_pa = contexts_->GetSerialPropArea();
277 | if (serial_pa == nullptr) {
278 | return -1;
279 | }
280 |
281 | prop_area* pa = contexts_->GetPropAreaForName(name);
282 | if (!pa) {
283 | async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied adding property \"%s\"", name);
284 | return -1;
285 | }
286 |
287 | bool ret = pa->add(name, namelen, value, valuelen);
288 | if (!ret) {
289 | return -1;
290 | }
291 |
292 | // There is only a single mutator, but we want to make sure that
293 | // updates are visible to a reader waiting for the update.
294 | atomic_store_explicit(serial_pa->serial(),
295 | atomic_load_explicit(serial_pa->serial(), memory_order_relaxed) + 1,
296 | memory_order_release);
297 | __futex_wake(serial_pa->serial(), INT32_MAX);
298 | return 0;
299 | }
300 |
301 | int SystemProperties::Delete(const char *name) {
302 | if (!initialized_) {
303 | return -1;
304 | }
305 |
306 | prop_area* serial_pa = contexts_->GetSerialPropArea();
307 | if (serial_pa == nullptr) {
308 | return -1;
309 | }
310 |
311 | prop_area* pa = contexts_->GetPropAreaForName(name);
312 | if (!pa) {
313 | async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied adding property \"%s\"", name);
314 | return -1;
315 | }
316 |
317 | bool ret = pa->rm(name);
318 | if (!ret) {
319 | return -1;
320 | }
321 |
322 | // There is only a single mutator, but we want to make sure that
323 | // updates are visible to a reader waiting for the update.
324 | atomic_store_explicit(serial_pa->serial(),
325 | atomic_load_explicit(serial_pa->serial(), memory_order_relaxed) + 1,
326 | memory_order_release);
327 | __futex_wake(serial_pa->serial(), INT32_MAX);
328 | return 0;
329 | }
330 |
331 | // Wait for non-locked serial, and retrieve it with acquire semantics.
332 | uint32_t SystemProperties::Serial(const prop_info* pi) {
333 | uint32_t serial = load_const_atomic(&pi->serial, memory_order_acquire);
334 | while (SERIAL_DIRTY(serial)) {
335 | __futex_wait(const_cast<_Atomic(uint_least32_t)*>(&pi->serial), serial, nullptr);
336 | serial = load_const_atomic(&pi->serial, memory_order_acquire);
337 | }
338 | return serial;
339 | }
340 |
341 | uint32_t SystemProperties::WaitAny(uint32_t old_serial) {
342 | uint32_t new_serial;
343 | Wait(nullptr, old_serial, &new_serial, nullptr);
344 | return new_serial;
345 | }
346 |
347 | bool SystemProperties::Wait(const prop_info* pi, uint32_t old_serial, uint32_t* new_serial_ptr,
348 | const timespec* relative_timeout) {
349 | // Are we waiting on the global serial or a specific serial?
350 | atomic_uint_least32_t* serial_ptr;
351 | if (pi == nullptr) {
352 | if (!initialized_) {
353 | return -1;
354 | }
355 |
356 | prop_area* serial_pa = contexts_->GetSerialPropArea();
357 | if (serial_pa == nullptr) {
358 | return -1;
359 | }
360 |
361 | serial_ptr = serial_pa->serial();
362 | } else {
363 | serial_ptr = const_cast(&pi->serial);
364 | }
365 |
366 | uint32_t new_serial;
367 | do {
368 | int rc;
369 | if ((rc = __futex_wait(serial_ptr, old_serial, relative_timeout)) != 0 && rc == -ETIMEDOUT) {
370 | return false;
371 | }
372 | new_serial = load_const_atomic(serial_ptr, memory_order_acquire);
373 | } while (new_serial == old_serial);
374 |
375 | *new_serial_ptr = new_serial;
376 | return true;
377 | }
378 |
379 | const prop_info* SystemProperties::FindNth(unsigned n) {
380 | struct find_nth {
381 | const uint32_t sought;
382 | uint32_t current;
383 | const prop_info* result;
384 |
385 | explicit find_nth(uint32_t n) : sought(n), current(0), result(nullptr) {
386 | }
387 | static void fn(const prop_info* pi, void* ptr) {
388 | find_nth* self = reinterpret_cast(ptr);
389 | if (self->current++ == self->sought) self->result = pi;
390 | }
391 | } state(n);
392 | Foreach(find_nth::fn, &state);
393 | return state.result;
394 | }
395 |
396 | int SystemProperties::Foreach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
397 | if (!initialized_) {
398 | return -1;
399 | }
400 |
401 | contexts_->ForEach(propfn, cookie);
402 |
403 | return 0;
404 | }
405 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/system_property_api.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
30 | //#include
31 | #include <_system_properties.h>
32 |
33 | #include
34 | #include
35 |
36 | #include "private/bionic_defs.h"
37 |
38 | static SystemProperties system_properties;
39 | static_assert(__is_trivially_constructible(SystemProperties),
40 | "System Properties must be trivially constructable");
41 |
42 | // This is public because it was exposed in the NDK. As of 2017-01, ~60 apps reference this symbol.
43 | // It is set to nullptr and never modified.
44 | __BIONIC_WEAK_VARIABLE_FOR_NATIVE_BRIDGE
45 | prop_area* __system_property_area__ = nullptr;
46 |
47 | __BIONIC_WEAK_FOR_NATIVE_BRIDGE
48 | int __system_properties_init() {
49 | return system_properties.Init(PROP_FILENAME) ? 0 : -1;
50 | }
51 |
52 | __BIONIC_WEAK_FOR_NATIVE_BRIDGE
53 | int __system_property_set_filename(const char*) {
54 | return -1;
55 | }
56 |
57 | __BIONIC_WEAK_FOR_NATIVE_BRIDGE
58 | int __system_property_area_init() {
59 | bool fsetxattr_failed = false;
60 | return system_properties.AreaInit(PROP_FILENAME, &fsetxattr_failed) && !fsetxattr_failed ? 0 : -1;
61 | }
62 |
63 | __BIONIC_WEAK_FOR_NATIVE_BRIDGE
64 | uint32_t __system_property_area_serial() {
65 | return system_properties.AreaSerial();
66 | }
67 |
68 | __BIONIC_WEAK_FOR_NATIVE_BRIDGE
69 | const prop_info* __system_property_find(const char* name) {
70 | return system_properties.Find(name);
71 | }
72 |
73 | __BIONIC_WEAK_FOR_NATIVE_BRIDGE
74 | int __system_property_read(const prop_info* pi, char* name, char* value) {
75 | return system_properties.Read(pi, name, value);
76 | }
77 |
78 | __BIONIC_WEAK_FOR_NATIVE_BRIDGE
79 | void __system_property_read_callback(const prop_info* pi,
80 | void (*callback)(void* cookie, const char* name,
81 | const char* value, uint32_t serial),
82 | void* cookie) {
83 | return system_properties.ReadCallback(pi, callback, cookie);
84 | }
85 |
86 | __BIONIC_WEAK_FOR_NATIVE_BRIDGE
87 | int __system_property_get(const char* name, char* value) {
88 | return system_properties.Get(name, value);
89 | }
90 |
91 | __BIONIC_WEAK_FOR_NATIVE_BRIDGE
92 | int __system_property_update(prop_info* pi, const char* value, unsigned int len) {
93 | return system_properties.Update(pi, value, len);
94 | }
95 |
96 | __BIONIC_WEAK_FOR_NATIVE_BRIDGE
97 | int __system_property_add(const char* name, unsigned int namelen, const char* value,
98 | unsigned int valuelen) {
99 | return system_properties.Add(name, namelen, value, valuelen);
100 | }
101 |
102 | __BIONIC_WEAK_FOR_NATIVE_BRIDGE
103 | int __system_property_delete(const char* name) {
104 | return system_properties.Delete(name);
105 | }
106 |
107 | __BIONIC_WEAK_FOR_NATIVE_BRIDGE
108 | uint32_t __system_property_serial(const prop_info* pi) {
109 | return system_properties.Serial(pi);
110 | }
111 |
112 | __BIONIC_WEAK_FOR_NATIVE_BRIDGE
113 | uint32_t __system_property_wait_any(uint32_t old_serial) {
114 | return system_properties.WaitAny(old_serial);
115 | }
116 |
117 | __BIONIC_WEAK_FOR_NATIVE_BRIDGE
118 | bool __system_property_wait(const prop_info* pi, uint32_t old_serial, uint32_t* new_serial_ptr,
119 | const timespec* relative_timeout) {
120 | return system_properties.Wait(pi, old_serial, new_serial_ptr, relative_timeout);
121 | }
122 |
123 | __BIONIC_WEAK_FOR_NATIVE_BRIDGE
124 | const prop_info* __system_property_find_nth(unsigned n) {
125 | return system_properties.FindNth(n);
126 | }
127 |
128 | __BIONIC_WEAK_FOR_NATIVE_BRIDGE
129 | int __system_property_foreach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
130 | return system_properties.Foreach(propfn, cookie);
131 | }
132 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/systemproperties/system_property_set.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 The Android Open Source Project
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | * * Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in
12 | * the documentation and/or other materials provided with the
13 | * distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 | * SUCH DAMAGE.
27 | */
28 |
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 | #include
40 | #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
41 | //#include
42 | #include <_system_properties.h>
43 | #include
44 |
45 | #include
46 |
47 | #include "private/bionic_defs.h"
48 | #include "private/bionic_macros.h"
49 |
50 | static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
51 | static const char* kServiceVersionPropertyName = "ro.property_service.version";
52 |
53 | #define CHECK(x) /* NOP */
54 |
55 | class PropertyServiceConnection {
56 | public:
57 | PropertyServiceConnection() : last_error_(0) {
58 | socket_ = ::socket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
59 | if (socket_ == -1) {
60 | last_error_ = errno;
61 | return;
62 | }
63 |
64 | const size_t namelen = strlen(property_service_socket);
65 | sockaddr_un addr;
66 | memset(&addr, 0, sizeof(addr));
67 | strlcpy(addr.sun_path, property_service_socket, sizeof(addr.sun_path));
68 | addr.sun_family = AF_LOCAL;
69 | socklen_t alen = namelen + offsetof(sockaddr_un, sun_path) + 1;
70 |
71 | if (TEMP_FAILURE_RETRY(connect(socket_, reinterpret_cast(&addr), alen)) == -1) {
72 | last_error_ = errno;
73 | close(socket_);
74 | socket_ = -1;
75 | }
76 | }
77 |
78 | bool IsValid() {
79 | return socket_ != -1;
80 | }
81 |
82 | int GetLastError() {
83 | return last_error_;
84 | }
85 |
86 | bool RecvInt32(int32_t* value) {
87 | int result = TEMP_FAILURE_RETRY(recv(socket_, value, sizeof(*value), MSG_WAITALL));
88 | return CheckSendRecvResult(result, sizeof(*value));
89 | }
90 |
91 | int socket() {
92 | return socket_;
93 | }
94 |
95 | ~PropertyServiceConnection() {
96 | if (socket_ != -1) {
97 | close(socket_);
98 | }
99 | }
100 |
101 | private:
102 | bool CheckSendRecvResult(int result, int expected_len) {
103 | if (result == -1) {
104 | last_error_ = errno;
105 | } else if (result != expected_len) {
106 | last_error_ = -1;
107 | } else {
108 | last_error_ = 0;
109 | }
110 |
111 | return last_error_ == 0;
112 | }
113 |
114 | int socket_;
115 | int last_error_;
116 |
117 | friend class SocketWriter;
118 | };
119 |
120 | class SocketWriter {
121 | public:
122 | explicit SocketWriter(PropertyServiceConnection* connection)
123 | : connection_(connection), iov_index_(0), uint_buf_index_(0) {
124 | }
125 |
126 | SocketWriter& WriteUint32(uint32_t value) {
127 | CHECK(uint_buf_index_ < kUintBufSize);
128 | CHECK(iov_index_ < kIovSize);
129 | uint32_t* ptr = uint_buf_ + uint_buf_index_;
130 | uint_buf_[uint_buf_index_++] = value;
131 | iov_[iov_index_].iov_base = ptr;
132 | iov_[iov_index_].iov_len = sizeof(*ptr);
133 | ++iov_index_;
134 | return *this;
135 | }
136 |
137 | SocketWriter& WriteString(const char* value) {
138 | uint32_t valuelen = strlen(value);
139 | WriteUint32(valuelen);
140 | if (valuelen == 0) {
141 | return *this;
142 | }
143 |
144 | CHECK(iov_index_ < kIovSize);
145 | iov_[iov_index_].iov_base = const_cast(value);
146 | iov_[iov_index_].iov_len = valuelen;
147 | ++iov_index_;
148 |
149 | return *this;
150 | }
151 |
152 | bool Send() {
153 | if (!connection_->IsValid()) {
154 | return false;
155 | }
156 |
157 | if (writev(connection_->socket(), iov_, iov_index_) == -1) {
158 | connection_->last_error_ = errno;
159 | return false;
160 | }
161 |
162 | iov_index_ = uint_buf_index_ = 0;
163 | return true;
164 | }
165 |
166 | private:
167 | static constexpr size_t kUintBufSize = 8;
168 | static constexpr size_t kIovSize = 8;
169 |
170 | PropertyServiceConnection* connection_;
171 | iovec iov_[kIovSize];
172 | size_t iov_index_;
173 | uint32_t uint_buf_[kUintBufSize];
174 | size_t uint_buf_index_;
175 |
176 | BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(SocketWriter);
177 | };
178 |
179 | struct prop_msg {
180 | unsigned cmd;
181 | char name[PROP_NAME_MAX];
182 | char value[PROP_VALUE_MAX];
183 | };
184 |
185 | static int send_prop_msg(const prop_msg* msg) {
186 | PropertyServiceConnection connection;
187 | if (!connection.IsValid()) {
188 | return connection.GetLastError();
189 | }
190 |
191 | int result = -1;
192 | int s = connection.socket();
193 |
194 | const int num_bytes = TEMP_FAILURE_RETRY(send(s, msg, sizeof(prop_msg), 0));
195 | if (num_bytes == sizeof(prop_msg)) {
196 | // We successfully wrote to the property server but now we
197 | // wait for the property server to finish its work. It
198 | // acknowledges its completion by closing the socket so we
199 | // poll here (on nothing), waiting for the socket to close.
200 | // If you 'adb shell setprop foo bar' you'll see the POLLHUP
201 | // once the socket closes. Out of paranoia we cap our poll
202 | // at 250 ms.
203 | pollfd pollfds[1];
204 | pollfds[0].fd = s;
205 | pollfds[0].events = 0;
206 | const int poll_result = TEMP_FAILURE_RETRY(poll(pollfds, 1, 250 /* ms */));
207 | if (poll_result == 1 && (pollfds[0].revents & POLLHUP) != 0) {
208 | result = 0;
209 | } else {
210 | // Ignore the timeout and treat it like a success anyway.
211 | // The init process is single-threaded and its property
212 | // service is sometimes slow to respond (perhaps it's off
213 | // starting a child process or something) and thus this
214 | // times out and the caller thinks it failed, even though
215 | // it's still getting around to it. So we fake it here,
216 | // mostly for ctl.* properties, but we do try and wait 250
217 | // ms so callers who do read-after-write can reliably see
218 | // what they've written. Most of the time.
219 | // TODO: fix the system properties design.
220 | async_safe_format_log(ANDROID_LOG_WARN, "libc",
221 | "Property service has timed out while trying to set \"%s\" to \"%s\"",
222 | msg->name, msg->value);
223 | result = 0;
224 | }
225 | }
226 |
227 | return result;
228 | }
229 |
230 | static constexpr uint32_t kProtocolVersion1 = 1;
231 | static constexpr uint32_t kProtocolVersion2 = 2; // current
232 |
233 | static atomic_uint_least32_t g_propservice_protocol_version(0);
234 |
235 | static void detect_protocol_version() {
236 | char value[PROP_VALUE_MAX];
237 | if (__system_property_get(kServiceVersionPropertyName, value) == 0) {
238 | g_propservice_protocol_version = kProtocolVersion1;
239 | async_safe_format_log(ANDROID_LOG_WARN, "libc",
240 | "Using old property service protocol (\"%s\" is not set)",
241 | kServiceVersionPropertyName);
242 | } else {
243 | uint32_t version = static_cast(atoll(value));
244 | if (version >= kProtocolVersion2) {
245 | g_propservice_protocol_version = kProtocolVersion2;
246 | } else {
247 | async_safe_format_log(ANDROID_LOG_WARN, "libc",
248 | "Using old property service protocol (\"%s\"=\"%s\")",
249 | kServiceVersionPropertyName, value);
250 | g_propservice_protocol_version = kProtocolVersion1;
251 | }
252 | }
253 | }
254 |
255 | __BIONIC_WEAK_FOR_NATIVE_BRIDGE
256 | int __system_property_set(const char* key, const char* value) {
257 | if (key == nullptr) return -1;
258 | if (value == nullptr) value = "";
259 |
260 | if (g_propservice_protocol_version == 0) {
261 | detect_protocol_version();
262 | }
263 |
264 | if (g_propservice_protocol_version == kProtocolVersion1) {
265 | // Old protocol does not support long names or values
266 | if (strlen(key) >= PROP_NAME_MAX) return -1;
267 | if (strlen(value) >= PROP_VALUE_MAX) return -1;
268 |
269 | prop_msg msg;
270 | memset(&msg, 0, sizeof msg);
271 | msg.cmd = PROP_MSG_SETPROP;
272 | strlcpy(msg.name, key, sizeof msg.name);
273 | strlcpy(msg.value, value, sizeof msg.value);
274 |
275 | return send_prop_msg(&msg);
276 | } else {
277 | // New protocol only allows long values for ro. properties only.
278 | if (strlen(value) >= PROP_VALUE_MAX && strncmp(key, "ro.", 3) != 0) return -1;
279 | // Use proper protocol
280 | PropertyServiceConnection connection;
281 | if (!connection.IsValid()) {
282 | errno = connection.GetLastError();
283 | async_safe_format_log(
284 | ANDROID_LOG_WARN, "libc",
285 | "Unable to set property \"%s\" to \"%s\": connection failed; errno=%d (%s)", key, value,
286 | errno, strerror(errno));
287 | return -1;
288 | }
289 |
290 | SocketWriter writer(&connection);
291 | if (!writer.WriteUint32(PROP_MSG_SETPROP2).WriteString(key).WriteString(value).Send()) {
292 | errno = connection.GetLastError();
293 | async_safe_format_log(ANDROID_LOG_WARN, "libc",
294 | "Unable to set property \"%s\" to \"%s\": write failed; errno=%d (%s)",
295 | key, value, errno, strerror(errno));
296 | return -1;
297 | }
298 |
299 | int result = -1;
300 | if (!connection.RecvInt32(&result)) {
301 | errno = connection.GetLastError();
302 | async_safe_format_log(ANDROID_LOG_WARN, "libc",
303 | "Unable to set property \"%s\" to \"%s\": recv failed; errno=%d (%s)",
304 | key, value, errno, strerror(errno));
305 | return -1;
306 | }
307 |
308 | if (result != PROP_SUCCESS) {
309 | async_safe_format_log(ANDROID_LOG_WARN, "libc",
310 | "Unable to set property \"%s\" to \"%s\": error code: 0x%x", key, value,
311 | result);
312 | return -1;
313 | }
314 |
315 | return 0;
316 | }
317 | }
318 |
--------------------------------------------------------------------------------
/module/src/main/cpp/external/util.hpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | using namespace std;
14 |
15 | ssize_t compat_getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) {
16 | char *ptr, *eptr;
17 |
18 | if (*buf == nullptr || *bufsiz == 0) {
19 | *bufsiz = BUFSIZ;
20 | if ((*buf = (char *) malloc(*bufsiz)) == nullptr)
21 | return -1;
22 | }
23 |
24 | for (ptr = *buf, eptr = *buf + *bufsiz;;) {
25 | int c = fgetc(fp);
26 | if (c == -1) {
27 | if (feof(fp))
28 | return ptr == *buf ? -1 : ptr - *buf;
29 | else
30 | return -1;
31 | }
32 | *ptr++ = c;
33 | if (c == delimiter) {
34 | *ptr = '\0';
35 | return ptr - *buf;
36 | }
37 | if (ptr + 2 >= eptr) {
38 | char *nbuf;
39 | size_t nbufsiz = *bufsiz * 2;
40 | ssize_t d = ptr - *buf;
41 | if ((nbuf = (char *) realloc(*buf, nbufsiz)) == nullptr)
42 | return -1;
43 | *buf = nbuf;
44 | *bufsiz = nbufsiz;
45 | eptr = nbuf + nbufsiz;
46 | ptr = nbuf + d;
47 | }
48 | }
49 | }
50 |
51 | ssize_t compat_getline(char **buf, size_t *bufsiz, FILE *fp) {
52 | return compat_getdelim(buf, bufsiz, '\n', fp);
53 | }
54 |
55 | struct mntent *getmntent(FILE *fp, struct mntent *e, char *buf, int buf_len)
56 | {
57 | memset(e, 0, sizeof(*e));
58 | while (fgets(buf, buf_len, fp) != nullptr)
59 | {
60 | // Entries look like "proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0".
61 | // That is: mnt_fsname mnt_dir mnt_type mnt_opts 0 0.
62 | int fsname0, fsname1, dir0, dir1, type0, type1, opts0, opts1;
63 | if (sscanf(buf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d",
64 | &fsname0, &fsname1, &dir0, &dir1, &type0, &type1, &opts0, &opts1,
65 | &e->mnt_freq, &e->mnt_passno) == 2)
66 | {
67 | e->mnt_fsname = &buf[fsname0];
68 | buf[fsname1] = '\0';
69 | e->mnt_dir = &buf[dir0];
70 | buf[dir1] = '\0';
71 | e->mnt_type = &buf[type0];
72 | buf[type1] = '\0';
73 | e->mnt_opts = &buf[opts0];
74 | buf[opts1] = '\0';
75 | return e;
76 | }
77 | }
78 | return nullptr;
79 | }
80 |
81 | void parse_mnt(const char *file, const function &fn)
82 | {
83 | char path[PATH_MAX];
84 | FILE *fp;
85 |
86 | sprintf(path, "/proc/self/mounts");
87 | fp = fopen(path, "r");
88 | if (fp)
89 | {
90 | mntent mentry{};
91 | char buf[4096];
92 | while (getmntent(fp, &mentry, buf, sizeof(buf)))
93 | {
94 | if (!fn(&mentry))
95 | break;
96 | }
97 | }
98 | }
99 |
100 | void file_readline(bool trim, const char *file, const function &fn) {
101 | FILE *fp = fopen(file, "re");
102 | if (fp == nullptr)
103 | return;
104 | size_t len = 1024;
105 | char *buf = (char *) malloc(len);
106 | char *start;
107 | ssize_t read;
108 | while ((read = getline(&buf, &len, fp)) >= 0) {
109 | start = buf;
110 | if (trim) {
111 | while (read && "\n\r "sv.find(buf[read - 1]) != string::npos)
112 | --read;
113 | buf[read] = '\0';
114 | while (*start == ' ')
115 | ++start;
116 | }
117 | if (!fn(start))
118 | break;
119 | }
120 | fclose(fp);
121 | free(buf);
122 | }
123 |
124 | void parse_prop_file(const char *file, const function &fn) {
125 | file_readline(true, file, [&](string_view line_view) -> bool {
126 | char *line = (char *) line_view.data();
127 | if (line[0] == '#')
128 | return true;
129 | char *eql = strchr(line, '=');
130 | if (eql == nullptr || eql == line)
131 | return true;
132 | *eql = '\0';
133 | return fn(line, eql + 1);
134 | });
135 | }
--------------------------------------------------------------------------------
/module/src/main/cpp/log.hpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "Shocker", __VA_ARGS__)
4 |
--------------------------------------------------------------------------------
/module/src/main/cpp/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #include "hide_mount.hpp"
8 | #include "hide_prop.hpp"
9 | #include "log.hpp"
10 | #include "zygisk.hpp"
11 |
12 |
13 | using zygisk::Api;
14 | using zygisk::AppSpecializeArgs;
15 | using zygisk::ServerSpecializeArgs;
16 |
17 | //要隐藏的app包名
18 | const char *hook_pkg_name = "com.shocker.zygiskdetect";
19 |
20 | class MyModule : public zygisk::ModuleBase
21 | {
22 | public:
23 | void onLoad(Api *api, JNIEnv *env) override
24 | {
25 | this->api = api;
26 | this->env = env;
27 | }
28 |
29 | void preAppSpecialize(AppSpecializeArgs *args) override
30 | {
31 | const char *process = env->GetStringUTFChars(args->nice_name, nullptr);
32 | if (strcmp(hook_pkg_name, process) == 0)
33 | {
34 | int pid=getpid();
35 | int fd = api->connectCompanion();
36 | write(fd, &pid, sizeof(pid));
37 | close(fd);
38 | }
39 | env->ReleaseStringUTFChars(args->nice_name, process);
40 | return;
41 | }
42 |
43 | private:
44 | Api *api;
45 | JNIEnv *env;
46 | };
47 |
48 | static void companion_handler(int i)
49 | {
50 | int pid;
51 | read(i, &pid, sizeof(pid));
52 |
53 | unshare(CLONE_NEWNS);
54 | mount(nullptr, "/", nullptr, MS_PRIVATE | MS_REC, nullptr);
55 | LOGD("daemon pid:%d,do_hide start pid:%d\n",getpid(),pid);
56 | do_hide(pid);
57 | do_hide_prop();
58 | return;
59 | }
60 |
61 | REGISTER_ZYGISK_MODULE(MyModule)
62 | REGISTER_ZYGISK_COMPANION(companion_handler)
63 |
--------------------------------------------------------------------------------
/module/src/main/cpp/zygisk.hpp:
--------------------------------------------------------------------------------
1 | // This is the public API for Zygisk modules.
2 | // DO NOT MODIFY ANY CODE IN THIS HEADER.
3 |
4 | #pragma once
5 |
6 | #include
7 |
8 | #define ZYGISK_API_VERSION 2
9 |
10 | /*
11 |
12 | Define a class and inherit zygisk::ModuleBase to implement the functionality of your module.
13 | Use the macro REGISTER_ZYGISK_MODULE(className) to register that class to Zygisk.
14 |
15 | Please note that modules will only be loaded after zygote has forked the child process.
16 | THIS MEANS ALL OF YOUR CODE RUNS IN THE APP/SYSTEM SERVER PROCESS, NOT THE ZYGOTE DAEMON!
17 |
18 | Example code:
19 |
20 | static jint (*orig_logger_entry_max)(JNIEnv *env);
21 | static jint my_logger_entry_max(JNIEnv *env) { return orig_logger_entry_max(env); }
22 |
23 | static void example_handler(int socket) { ... }
24 |
25 | class ExampleModule : public zygisk::ModuleBase {
26 | public:
27 | void onLoad(zygisk::Api *api, JNIEnv *env) override {
28 | this->api = api;
29 | this->env = env;
30 | }
31 | void preAppSpecialize(zygisk::AppSpecializeArgs *args) override {
32 | JNINativeMethod methods[] = {
33 | { "logger_entry_max_payload_native", "()I", (void*) my_logger_entry_max },
34 | };
35 | api->hookJniNativeMethods(env, "android/util/Log", methods, 1);
36 | *(void **) &orig_logger_entry_max = methods[0].fnPtr;
37 | }
38 | private:
39 | zygisk::Api *api;
40 | JNIEnv *env;
41 | };
42 |
43 | REGISTER_ZYGISK_MODULE(ExampleModule)
44 |
45 | REGISTER_ZYGISK_COMPANION(example_handler)
46 |
47 | */
48 |
49 | namespace zygisk {
50 |
51 | struct Api;
52 | struct AppSpecializeArgs;
53 | struct ServerSpecializeArgs;
54 |
55 | class ModuleBase {
56 | public:
57 |
58 | // This function is called when the module is loaded into the target process.
59 | // A Zygisk API handle will be sent as an argument; call utility functions or interface
60 | // with Zygisk through this handle.
61 | virtual void onLoad([[maybe_unused]] Api *api, [[maybe_unused]] JNIEnv *env) {}
62 |
63 | // This function is called before the app process is specialized.
64 | // At this point, the process just got forked from zygote, but no app specific specialization
65 | // is applied. This means that the process does not have any sandbox restrictions and
66 | // still runs with the same privilege of zygote.
67 | //
68 | // All the arguments that will be sent and used for app specialization is passed as a single
69 | // AppSpecializeArgs object. You can read and overwrite these arguments to change how the app
70 | // process will be specialized.
71 | //
72 | // If you need to run some operations as superuser, you can call Api::connectCompanion() to
73 | // get a socket to do IPC calls with a root companion process.
74 | // See Api::connectCompanion() for more info.
75 | virtual void preAppSpecialize([[maybe_unused]] AppSpecializeArgs *args) {}
76 |
77 | // This function is called after the app process is specialized.
78 | // At this point, the process has all sandbox restrictions enabled for this application.
79 | // This means that this function runs as the same privilege of the app's own code.
80 | virtual void postAppSpecialize([[maybe_unused]] const AppSpecializeArgs *args) {}
81 |
82 | // This function is called before the system server process is specialized.
83 | // See preAppSpecialize(args) for more info.
84 | virtual void preServerSpecialize([[maybe_unused]] ServerSpecializeArgs *args) {}
85 |
86 | // This function is called after the system server process is specialized.
87 | // At this point, the process runs with the privilege of system_server.
88 | virtual void postServerSpecialize([[maybe_unused]] const ServerSpecializeArgs *args) {}
89 | };
90 |
91 | struct AppSpecializeArgs {
92 | // Required arguments. These arguments are guaranteed to exist on all Android versions.
93 | jint &uid;
94 | jint &gid;
95 | jintArray &gids;
96 | jint &runtime_flags;
97 | jint &mount_external;
98 | jstring &se_info;
99 | jstring &nice_name;
100 | jstring &instruction_set;
101 | jstring &app_data_dir;
102 |
103 | // Optional arguments. Please check whether the pointer is null before de-referencing
104 | jboolean *const is_child_zygote;
105 | jboolean *const is_top_app;
106 | jobjectArray *const pkg_data_info_list;
107 | jobjectArray *const whitelisted_data_info_list;
108 | jboolean *const mount_data_dirs;
109 | jboolean *const mount_storage_dirs;
110 |
111 | AppSpecializeArgs() = delete;
112 | };
113 |
114 | struct ServerSpecializeArgs {
115 | jint &uid;
116 | jint &gid;
117 | jintArray &gids;
118 | jint &runtime_flags;
119 | jlong &permitted_capabilities;
120 | jlong &effective_capabilities;
121 |
122 | ServerSpecializeArgs() = delete;
123 | };
124 |
125 | namespace internal {
126 | struct api_table;
127 | template void entry_impl(api_table *, JNIEnv *);
128 | }
129 |
130 | // These values are used in Api::setOption(Option)
131 | enum Option : int {
132 | // Force Magisk's denylist unmount routines to run on this process.
133 | //
134 | // Setting this option only makes sense in preAppSpecialize.
135 | // The actual unmounting happens during app process specialization.
136 | //
137 | // Set this option to force all Magisk and modules' files to be unmounted from the
138 | // mount namespace of the process, regardless of the denylist enforcement status.
139 | FORCE_DENYLIST_UNMOUNT = 0,
140 |
141 | // When this option is set, your module's library will be dlclose-ed after post[XXX]Specialize.
142 | // Be aware that after dlclose-ing your module, all of your code will be unmapped from memory.
143 | // YOU MUST NOT ENABLE THIS OPTION AFTER HOOKING ANY FUNCTIONS IN THE PROCESS.
144 | DLCLOSE_MODULE_LIBRARY = 1,
145 | };
146 |
147 | // Bit masks of the return value of Api::getFlags()
148 | enum StateFlag : uint32_t {
149 | // The user has granted root access to the current process
150 | PROCESS_GRANTED_ROOT = (1u << 0),
151 |
152 | // The current process was added on the denylist
153 | PROCESS_ON_DENYLIST = (1u << 1),
154 | };
155 |
156 | // All API functions will stop working after post[XXX]Specialize as Zygisk will be unloaded
157 | // from the specialized process afterwards.
158 | struct Api {
159 |
160 | // Connect to a root companion process and get a Unix domain socket for IPC.
161 | //
162 | // This API only works in the pre[XXX]Specialize functions due to SELinux restrictions.
163 | //
164 | // The pre[XXX]Specialize functions run with the same privilege of zygote.
165 | // If you would like to do some operations with superuser permissions, register a handler
166 | // function that would be called in the root process with REGISTER_ZYGISK_COMPANION(func).
167 | // Another good use case for a companion process is that if you want to share some resources
168 | // across multiple processes, hold the resources in the companion process and pass it over.
169 | //
170 | // The root companion process is ABI aware; that is, when calling this function from a 32-bit
171 | // process, you will be connected to a 32-bit companion process, and vice versa for 64-bit.
172 | //
173 | // Returns a file descriptor to a socket that is connected to the socket passed to your
174 | // module's companion request handler. Returns -1 if the connection attempt failed.
175 | int connectCompanion();
176 |
177 | // Get the file descriptor of the root folder of the current module.
178 | //
179 | // This API only works in the pre[XXX]Specialize functions.
180 | // Accessing the directory returned is only possible in the pre[XXX]Specialize functions
181 | // or in the root companion process (assuming that you sent the fd over the socket).
182 | // Both restrictions are due to SELinux and UID.
183 | //
184 | // Returns -1 if errors occurred.
185 | int getModuleDir();
186 |
187 | // Set various options for your module.
188 | // Please note that this function accepts one single option at a time.
189 | // Check zygisk::Option for the full list of options available.
190 | void setOption(Option opt);
191 |
192 | // Get information about the current process.
193 | // Returns bitwise-or'd zygisk::StateFlag values.
194 | uint32_t getFlags();
195 |
196 | // Hook JNI native methods for a class
197 | //
198 | // Lookup all registered JNI native methods and replace it with your own functions.
199 | // The original function pointer will be saved in each JNINativeMethod's fnPtr.
200 | // If no matching class, method name, or signature is found, that specific JNINativeMethod.fnPtr
201 | // will be set to nullptr.
202 | void hookJniNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods, int numMethods);
203 |
204 | // For ELFs loaded in memory matching `regex`, replace function `symbol` with `newFunc`.
205 | // If `oldFunc` is not nullptr, the original function pointer will be saved to `oldFunc`.
206 | void pltHookRegister(const char *regex, const char *symbol, void *newFunc, void **oldFunc);
207 |
208 | // For ELFs loaded in memory matching `regex`, exclude hooks registered for `symbol`.
209 | // If `symbol` is nullptr, then all symbols will be excluded.
210 | void pltHookExclude(const char *regex, const char *symbol);
211 |
212 | // Commit all the hooks that was previously registered.
213 | // Returns false if an error occurred.
214 | bool pltHookCommit();
215 |
216 | private:
217 | internal::api_table *impl;
218 | template friend void internal::entry_impl(internal::api_table *, JNIEnv *);
219 | };
220 |
221 | // Register a class as a Zygisk module
222 |
223 | #define REGISTER_ZYGISK_MODULE(clazz) \
224 | void zygisk_module_entry(zygisk::internal::api_table *table, JNIEnv *env) { \
225 | zygisk::internal::entry_impl(table, env); \
226 | }
227 |
228 | // Register a root companion request handler function for your module
229 | //
230 | // The function runs in a superuser daemon process and handles a root companion request from
231 | // your module running in a target process. The function has to accept an integer value,
232 | // which is a socket that is connected to the target process.
233 | // See Api::connectCompanion() for more info.
234 | //
235 | // NOTE: the function can run concurrently on multiple threads.
236 | // Be aware of race conditions if you have a globally shared resource.
237 |
238 | #define REGISTER_ZYGISK_COMPANION(func) \
239 | void zygisk_companion_entry(int client) { func(client); }
240 |
241 | /************************************************************************************
242 | * All the code after this point is internal code used to interface with Zygisk
243 | * and guarantee ABI stability. You do not have to understand what it is doing.
244 | ************************************************************************************/
245 |
246 | namespace internal {
247 |
248 | struct module_abi {
249 | long api_version;
250 | ModuleBase *_this;
251 |
252 | void (*preAppSpecialize)(ModuleBase *, AppSpecializeArgs *);
253 | void (*postAppSpecialize)(ModuleBase *, const AppSpecializeArgs *);
254 | void (*preServerSpecialize)(ModuleBase *, ServerSpecializeArgs *);
255 | void (*postServerSpecialize)(ModuleBase *, const ServerSpecializeArgs *);
256 |
257 | module_abi(ModuleBase *module) : api_version(ZYGISK_API_VERSION), _this(module) {
258 | preAppSpecialize = [](auto self, auto args) { self->preAppSpecialize(args); };
259 | postAppSpecialize = [](auto self, auto args) { self->postAppSpecialize(args); };
260 | preServerSpecialize = [](auto self, auto args) { self->preServerSpecialize(args); };
261 | postServerSpecialize = [](auto self, auto args) { self->postServerSpecialize(args); };
262 | }
263 | };
264 |
265 | struct api_table {
266 | // These first 2 entries are permanent, shall never change
267 | void *_this;
268 | bool (*registerModule)(api_table *, module_abi *);
269 |
270 | // Utility functions
271 | void (*hookJniNativeMethods)(JNIEnv *, const char *, JNINativeMethod *, int);
272 | void (*pltHookRegister)(const char *, const char *, void *, void **);
273 | void (*pltHookExclude)(const char *, const char *);
274 | bool (*pltHookCommit)();
275 |
276 | // Zygisk functions
277 | int (*connectCompanion)(void * /* _this */);
278 | void (*setOption)(void * /* _this */, Option);
279 | int (*getModuleDir)(void * /* _this */);
280 | uint32_t (*getFlags)(void * /* _this */);
281 | };
282 |
283 | template
284 | void entry_impl(api_table *table, JNIEnv *env) {
285 | ModuleBase *module = new T();
286 | if (!table->registerModule(table, new module_abi(module)))
287 | return;
288 | auto api = new Api();
289 | api->impl = table;
290 | module->onLoad(api, env);
291 | }
292 |
293 | } // namespace internal
294 |
295 | inline int Api::connectCompanion() {
296 | return impl->connectCompanion ? impl->connectCompanion(impl->_this) : -1;
297 | }
298 | inline int Api::getModuleDir() {
299 | return impl->getModuleDir ? impl->getModuleDir(impl->_this) : -1;
300 | }
301 | inline void Api::setOption(Option opt) {
302 | if (impl->setOption) impl->setOption(impl->_this, opt);
303 | }
304 | inline uint32_t Api::getFlags() {
305 | return impl->getFlags ? impl->getFlags(impl->_this) : 0;
306 | }
307 | inline void Api::hookJniNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods, int numMethods) {
308 | if (impl->hookJniNativeMethods) impl->hookJniNativeMethods(env, className, methods, numMethods);
309 | }
310 | inline void Api::pltHookRegister(const char *regex, const char *symbol, void *newFunc, void **oldFunc) {
311 | if (impl->pltHookRegister) impl->pltHookRegister(regex, symbol, newFunc, oldFunc);
312 | }
313 | inline void Api::pltHookExclude(const char *regex, const char *symbol) {
314 | if (impl->pltHookExclude) impl->pltHookExclude(regex, symbol);
315 | }
316 | inline bool Api::pltHookCommit() {
317 | return impl->pltHookCommit != nullptr && impl->pltHookCommit();
318 | }
319 |
320 | } // namespace zygisk
321 |
322 | [[gnu::visibility("default")]] [[gnu::used]]
323 | extern "C" void zygisk_module_entry(zygisk::internal::api_table *, JNIEnv *);
324 |
325 | [[gnu::visibility("default")]] [[gnu::used]]
326 | extern "C" void zygisk_companion_entry(int);
327 |
--------------------------------------------------------------------------------
/out/magisk_module_release/.gitattributes:
--------------------------------------------------------------------------------
1 | # Declare files that will always have LF line endings on checkout.
2 | META-INF/** text eol=lf
3 | *.prop text eol=lf
4 | *.sh text eol=lf
5 | *.md text eol=lf
6 | sepolicy.rule text eol=lf
7 |
8 | # Denote all files that are truly binary and should not be modified.
9 | system/** binary
10 | system_x86/** binary
--------------------------------------------------------------------------------
/out/magisk_module_release/META-INF/com/google/android/update-binary:
--------------------------------------------------------------------------------
1 | #!/sbin/sh
2 |
3 | #################
4 | # Initialization
5 | #################
6 |
7 | umask 022
8 |
9 | # echo before loading util_functions
10 | ui_print() { echo "$1"; }
11 |
12 | require_new_magisk() {
13 | ui_print "*******************************"
14 | ui_print " Please install Magisk v20.4+! "
15 | ui_print "*******************************"
16 | exit 1
17 | }
18 |
19 | #########################
20 | # Load util_functions.sh
21 | #########################
22 |
23 | OUTFD=$2
24 | ZIPFILE=$3
25 |
26 | mount /data 2>/dev/null
27 |
28 | [ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk
29 | . /data/adb/magisk/util_functions.sh
30 | [ $MAGISK_VER_CODE -lt 20400 ] && require_new_magisk
31 |
32 | install_module
33 | exit 0
34 |
--------------------------------------------------------------------------------
/out/magisk_module_release/META-INF/com/google/android/update-binary.sha256sum:
--------------------------------------------------------------------------------
1 | bcf4b1d9913f3af17755569c853e0b5a75b8005f6a18eb3f86dadcc0e968c29d
--------------------------------------------------------------------------------
/out/magisk_module_release/META-INF/com/google/android/updater-script:
--------------------------------------------------------------------------------
1 | #MAGISK
2 |
--------------------------------------------------------------------------------
/out/magisk_module_release/META-INF/com/google/android/updater-script.sha256sum:
--------------------------------------------------------------------------------
1 | d2b8203193a083e43ad076fde01b9c7821e0aa521e1f8077b8628fb1cdb70c60
--------------------------------------------------------------------------------
/out/magisk_module_release/README.md:
--------------------------------------------------------------------------------
1 | # Riru - Template
--------------------------------------------------------------------------------
/out/magisk_module_release/README.md.sha256sum:
--------------------------------------------------------------------------------
1 | cc316a39370ad108ff5708381a05897210dd0465a3377ca7cef5f4408e4da39f
--------------------------------------------------------------------------------
/out/magisk_module_release/customize.sh:
--------------------------------------------------------------------------------
1 | # shellcheck disable=SC2034
2 | SKIPUNZIP=1
3 |
4 | FLAVOR=zygisk
5 |
6 | enforce_install_from_magisk_app() {
7 | if $BOOTMODE; then
8 | ui_print "- Installing from Magisk app"
9 | else
10 | ui_print "*********************************************************"
11 | ui_print "! Install from recovery is NOT supported"
12 | ui_print "! Recovery sucks"
13 | ui_print "! Please install from Magisk app"
14 | abort "*********************************************************"
15 | fi
16 | }
17 |
18 | check_magisk_version() {
19 | ui_print "- Magisk version: $MAGISK_VER_CODE"
20 | if [ "$MAGISK_VER_CODE" -lt 24200 ]; then
21 | ui_print "*********************************************************"
22 | ui_print "! Please install Magisk v24.2+ (24200+)"
23 | abort "*********************************************************"
24 | fi
25 | }
26 |
27 | VERSION=$(grep_prop version "${TMPDIR}/module.prop")
28 | ui_print "- zygisk_magiskhide version ${VERSION}"
29 |
30 | # Extract verify.sh
31 | ui_print "- Extracting verify.sh"
32 | unzip -o "$ZIPFILE" 'verify.sh' -d "$TMPDIR" >&2
33 | if [ ! -f "$TMPDIR/verify.sh" ]; then
34 | ui_print "*********************************************************"
35 | ui_print "! Unable to extract verify.sh!"
36 | ui_print "! This zip may be corrupted, please try downloading again"
37 | abort "*********************************************************"
38 | fi
39 | . "$TMPDIR/verify.sh"
40 |
41 | extract "$ZIPFILE" 'customize.sh' "$TMPDIR"
42 | extract "$ZIPFILE" 'verify.sh' "$TMPDIR"
43 |
44 | check_magisk_version
45 | enforce_install_from_magisk_app
46 |
47 | # Check architecture
48 | if [ "$ARCH" != "arm" ] && [ "$ARCH" != "arm64" ] && [ "$ARCH" != "x86" ] && [ "$ARCH" != "x64" ]; then
49 | abort "! Unsupported platform: $ARCH"
50 | else
51 | ui_print "- Device platform: $ARCH"
52 | fi
53 |
54 | if [ "$API" -lt 27 ]; then
55 | abort "! Only support SDK 27+ devices"
56 | fi
57 |
58 | extract "$ZIPFILE" 'module.prop' "$MODPATH"
59 | extract "$ZIPFILE" 'service.sh' "$MODPATH"
60 | extract "$ZIPFILE" 'uninstall.sh' "$MODPATH"
61 |
62 | ui_print "- Extracting zygisk libraries"
63 |
64 | if [ "$FLAVOR" == "zygisk" ]; then
65 | mkdir -p "$MODPATH/zygisk"
66 | if [ "$ARCH" = "arm" ] || [ "$ARCH" = "arm64" ]; then
67 | extract "$ZIPFILE" "lib/armeabi-v7a/libhide.so" "$MODPATH/zygisk" true
68 | mv "$MODPATH/zygisk/libhide.so" "$MODPATH/zygisk/armeabi-v7a.so"
69 |
70 | if [ "$IS64BIT" = true ]; then
71 | extract "$ZIPFILE" "lib/arm64-v8a/libhide.so" "$MODPATH/zygisk" true
72 | mv "$MODPATH/zygisk/libhide.so" "$MODPATH/zygisk/arm64-v8a.so"
73 | fi
74 | fi
75 |
76 | if [ "$ARCH" = "x86" ] || [ "$ARCH" = "x64" ]; then
77 | extract "$ZIPFILE" "lib/x86_64/libhide.so" "$MODPATH/zygisk" true
78 | mv "$MODPATH/zygisk/libhide.so" "$MODPATH/zygisk/x86_64.so"
79 |
80 | if [ "$IS64BIT" = true ]; then
81 | extract "$ZIPFILE" "lib/x86/libhide.so" "$MODPATH/zygisk" true
82 | mv "$MODPATH/zygisk/libhide.so" "$MODPATH/zygisk/x86.so"
83 | fi
84 | fi
85 | fi
86 |
87 |
88 | set_perm_recursive "$MODPATH" 0 0 0755 0644
89 |
90 | ui_print "- 少年よ大志を抱け"
91 |
--------------------------------------------------------------------------------
/out/magisk_module_release/customize.sh.sha256sum:
--------------------------------------------------------------------------------
1 | e967d629bd25cd95789dbbd0e5003d1f438ec2b6661f3690631477166b648dce
--------------------------------------------------------------------------------
/out/magisk_module_release/lib/arm64-v8a/libhide.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PShocker/Zygisk-MagiskHide/310b2236de31b7042d565ca73dcd6060247f20d0/out/magisk_module_release/lib/arm64-v8a/libhide.so
--------------------------------------------------------------------------------
/out/magisk_module_release/lib/arm64-v8a/libhide.so.sha256sum:
--------------------------------------------------------------------------------
1 | 253764354de8292647344d949d1fcad74599dea70ff009b993889e537cc2ebc6
--------------------------------------------------------------------------------
/out/magisk_module_release/lib/armeabi-v7a/libhide.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PShocker/Zygisk-MagiskHide/310b2236de31b7042d565ca73dcd6060247f20d0/out/magisk_module_release/lib/armeabi-v7a/libhide.so
--------------------------------------------------------------------------------
/out/magisk_module_release/lib/armeabi-v7a/libhide.so.sha256sum:
--------------------------------------------------------------------------------
1 | eb27457b52f7cda9f0d2db356337ce90f3113728fb9e3357371316553c0de191
--------------------------------------------------------------------------------
/out/magisk_module_release/lib/x86/libhide.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PShocker/Zygisk-MagiskHide/310b2236de31b7042d565ca73dcd6060247f20d0/out/magisk_module_release/lib/x86/libhide.so
--------------------------------------------------------------------------------
/out/magisk_module_release/lib/x86/libhide.so.sha256sum:
--------------------------------------------------------------------------------
1 | 2b23f139a407888e37c202076e24c8b6b0b20b1616906caf1dbf2979dbcd4c3a
--------------------------------------------------------------------------------
/out/magisk_module_release/lib/x86_64/libhide.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PShocker/Zygisk-MagiskHide/310b2236de31b7042d565ca73dcd6060247f20d0/out/magisk_module_release/lib/x86_64/libhide.so
--------------------------------------------------------------------------------
/out/magisk_module_release/lib/x86_64/libhide.so.sha256sum:
--------------------------------------------------------------------------------
1 | e0dd46f3593683054bbe08d43bfb286a5ea7a5501865b2689fe2b0affc79ac6e
--------------------------------------------------------------------------------
/out/magisk_module_release/module.prop:
--------------------------------------------------------------------------------
1 | id=zygisk_magiskhide
2 | name=Zygisk - Hide
3 | version=v1.0.1
4 | versionCode=26
5 | author=Shocker
6 | description=MagiskHide in Zygisk
7 |
--------------------------------------------------------------------------------
/out/magisk_module_release/module.prop.sha256sum:
--------------------------------------------------------------------------------
1 | 6d6c4b54a0fbb2806653f9fae33bcceded644d4b51ce0175394da946d7cc3f71
--------------------------------------------------------------------------------
/out/magisk_module_release/service.sh:
--------------------------------------------------------------------------------
1 | MODDIR=${0%/*}
--------------------------------------------------------------------------------
/out/magisk_module_release/service.sh.sha256sum:
--------------------------------------------------------------------------------
1 | 68da6150109c2cc9cccf108bdf57193e6619a5ae348642d467430a613b76244f
--------------------------------------------------------------------------------
/out/magisk_module_release/uninstall.sh:
--------------------------------------------------------------------------------
1 | #!/sbin/sh
2 | # MODDIR=${0%/*}
3 | rm -rf /data/adb/modules/zygisk_magiskhide
4 |
--------------------------------------------------------------------------------
/out/magisk_module_release/uninstall.sh.sha256sum:
--------------------------------------------------------------------------------
1 | fd23cfa7f45c22b0094de202649444632a57596c9c20254d2cb5aca044840bc5
--------------------------------------------------------------------------------
/out/magisk_module_release/verify.sh:
--------------------------------------------------------------------------------
1 | TMPDIR_FOR_VERIFY="$TMPDIR/.vunzip"
2 | mkdir "$TMPDIR_FOR_VERIFY"
3 |
4 | abort_verify() {
5 | ui_print "*********************************************************"
6 | ui_print "! $1"
7 | ui_print "! This zip may be corrupted, please try downloading again"
8 | abort "*********************************************************"
9 | }
10 |
11 | # extract
12 | extract() {
13 | zip=$1
14 | file=$2
15 | dir=$3
16 | junk_paths=$4
17 | [ -z "$junk_paths" ] && junk_paths=false
18 | opts="-o"
19 | [ $junk_paths = true ] && opts="-oj"
20 |
21 | file_path=""
22 | hash_path=""
23 | if [ $junk_paths = true ]; then
24 | file_path="$dir/$(basename "$file")"
25 | hash_path="$TMPDIR_FOR_VERIFY/$(basename "$file").sha256sum"
26 | else
27 | file_path="$dir/$file"
28 | hash_path="$TMPDIR_FOR_VERIFY/$file.sha256sum"
29 | fi
30 |
31 | unzip $opts "$zip" "$file" -d "$dir" >&2
32 | [ -f "$file_path" ] || abort_verify "$file not exists"
33 |
34 | unzip $opts "$zip" "$file.sha256sum" -d "$TMPDIR_FOR_VERIFY" >&2
35 | [ -f "$hash_path" ] || abort_verify "$file.sha256sum not exists"
36 |
37 | (echo "$(cat "$hash_path") $file_path" | sha256sum -c -s -) || abort_verify "Failed to verify $file"
38 | ui_print "- Verified $file" >&1
39 | }
40 |
--------------------------------------------------------------------------------
/out/magisk_module_release/verify.sh.sha256sum:
--------------------------------------------------------------------------------
1 | ff6cfc26dbfba2c0feeac333300c27a1e3a668b50ae0fb6ce07b245f30f9c5e8
--------------------------------------------------------------------------------
/out/zygisk-magiskhide-v1.0.1-release.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PShocker/Zygisk-MagiskHide/310b2236de31b7042d565ca73dcd6060247f20d0/out/zygisk-magiskhide-v1.0.1-release.zip
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | import org.apache.tools.ant.DirectoryScanner
2 |
3 | pluginManagement {
4 | repositories {
5 | gradlePluginPortal()
6 | google()
7 | mavenCentral()
8 | }
9 | plugins {
10 | id 'com.android.application' version '7.0.2'
11 | id 'com.android.library' version '7.0.2'
12 | }
13 | }
14 | dependencyResolutionManagement {
15 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
16 | repositories {
17 | mavenLocal()
18 | google()
19 | mavenCentral()
20 | }
21 | }
22 |
23 | DirectoryScanner.removeDefaultExclude('**/.gitattributes')
24 |
25 | include ':module'
26 |
--------------------------------------------------------------------------------
/template/magisk_module/.gitattributes:
--------------------------------------------------------------------------------
1 | # Declare files that will always have LF line endings on checkout.
2 | META-INF/** text eol=lf
3 | *.prop text eol=lf
4 | *.sh text eol=lf
5 | *.md text eol=lf
6 | sepolicy.rule text eol=lf
7 |
8 | # Denote all files that are truly binary and should not be modified.
9 | system/** binary
10 | system_x86/** binary
--------------------------------------------------------------------------------
/template/magisk_module/META-INF/com/google/android/update-binary:
--------------------------------------------------------------------------------
1 | #!/sbin/sh
2 |
3 | #################
4 | # Initialization
5 | #################
6 |
7 | umask 022
8 |
9 | # echo before loading util_functions
10 | ui_print() { echo "$1"; }
11 |
12 | require_new_magisk() {
13 | ui_print "*******************************"
14 | ui_print " Please install Magisk v20.4+! "
15 | ui_print "*******************************"
16 | exit 1
17 | }
18 |
19 | #########################
20 | # Load util_functions.sh
21 | #########################
22 |
23 | OUTFD=$2
24 | ZIPFILE=$3
25 |
26 | mount /data 2>/dev/null
27 |
28 | [ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk
29 | . /data/adb/magisk/util_functions.sh
30 | [ $MAGISK_VER_CODE -lt 20400 ] && require_new_magisk
31 |
32 | install_module
33 | exit 0
34 |
--------------------------------------------------------------------------------
/template/magisk_module/META-INF/com/google/android/updater-script:
--------------------------------------------------------------------------------
1 | #MAGISK
2 |
--------------------------------------------------------------------------------
/template/magisk_module/README.md:
--------------------------------------------------------------------------------
1 | # Riru - Template
--------------------------------------------------------------------------------
/template/magisk_module/customize.sh:
--------------------------------------------------------------------------------
1 | # shellcheck disable=SC2034
2 | SKIPUNZIP=1
3 |
4 | FLAVOR=zygisk
5 |
6 | enforce_install_from_magisk_app() {
7 | if $BOOTMODE; then
8 | ui_print "- Installing from Magisk app"
9 | else
10 | ui_print "*********************************************************"
11 | ui_print "! Install from recovery is NOT supported"
12 | ui_print "! Recovery sucks"
13 | ui_print "! Please install from Magisk app"
14 | abort "*********************************************************"
15 | fi
16 | }
17 |
18 | check_magisk_version() {
19 | ui_print "- Magisk version: $MAGISK_VER_CODE"
20 | if [ "$MAGISK_VER_CODE" -lt 24200 ]; then
21 | ui_print "*********************************************************"
22 | ui_print "! Please install Magisk v24.2+ (24200+)"
23 | abort "*********************************************************"
24 | fi
25 | }
26 |
27 | VERSION=$(grep_prop version "${TMPDIR}/module.prop")
28 | ui_print "- zygisk_magiskhide version ${VERSION}"
29 |
30 | # Extract verify.sh
31 | ui_print "- Extracting verify.sh"
32 | unzip -o "$ZIPFILE" 'verify.sh' -d "$TMPDIR" >&2
33 | if [ ! -f "$TMPDIR/verify.sh" ]; then
34 | ui_print "*********************************************************"
35 | ui_print "! Unable to extract verify.sh!"
36 | ui_print "! This zip may be corrupted, please try downloading again"
37 | abort "*********************************************************"
38 | fi
39 | . "$TMPDIR/verify.sh"
40 |
41 | extract "$ZIPFILE" 'customize.sh' "$TMPDIR"
42 | extract "$ZIPFILE" 'verify.sh' "$TMPDIR"
43 |
44 | check_magisk_version
45 | enforce_install_from_magisk_app
46 |
47 | # Check architecture
48 | if [ "$ARCH" != "arm" ] && [ "$ARCH" != "arm64" ] && [ "$ARCH" != "x86" ] && [ "$ARCH" != "x64" ]; then
49 | abort "! Unsupported platform: $ARCH"
50 | else
51 | ui_print "- Device platform: $ARCH"
52 | fi
53 |
54 | if [ "$API" -lt 27 ]; then
55 | abort "! Only support SDK 27+ devices"
56 | fi
57 |
58 | extract "$ZIPFILE" 'module.prop' "$MODPATH"
59 | extract "$ZIPFILE" 'service.sh' "$MODPATH"
60 | extract "$ZIPFILE" 'uninstall.sh' "$MODPATH"
61 |
62 | ui_print "- Extracting zygisk libraries"
63 |
64 | if [ "$FLAVOR" == "zygisk" ]; then
65 | mkdir -p "$MODPATH/zygisk"
66 | if [ "$ARCH" = "arm" ] || [ "$ARCH" = "arm64" ]; then
67 | extract "$ZIPFILE" "lib/armeabi-v7a/libhide.so" "$MODPATH/zygisk" true
68 | mv "$MODPATH/zygisk/libhide.so" "$MODPATH/zygisk/armeabi-v7a.so"
69 |
70 | if [ "$IS64BIT" = true ]; then
71 | extract "$ZIPFILE" "lib/arm64-v8a/libhide.so" "$MODPATH/zygisk" true
72 | mv "$MODPATH/zygisk/libhide.so" "$MODPATH/zygisk/arm64-v8a.so"
73 | fi
74 | fi
75 |
76 | if [ "$ARCH" = "x86" ] || [ "$ARCH" = "x64" ]; then
77 | extract "$ZIPFILE" "lib/x86_64/libhide.so" "$MODPATH/zygisk" true
78 | mv "$MODPATH/zygisk/libhide.so" "$MODPATH/zygisk/x86_64.so"
79 |
80 | if [ "$IS64BIT" = true ]; then
81 | extract "$ZIPFILE" "lib/x86/libhide.so" "$MODPATH/zygisk" true
82 | mv "$MODPATH/zygisk/libhide.so" "$MODPATH/zygisk/x86.so"
83 | fi
84 | fi
85 | fi
86 |
87 |
88 | set_perm_recursive "$MODPATH" 0 0 0755 0644
89 |
90 | ui_print "- 少年よ大志を抱け"
91 |
--------------------------------------------------------------------------------
/template/magisk_module/module.prop:
--------------------------------------------------------------------------------
1 | id=${id}
2 | name=${name}
3 | version=${version}
4 | versionCode=${versionCode}
5 | author=${author}
6 | description=${description}
7 |
--------------------------------------------------------------------------------
/template/magisk_module/service.sh:
--------------------------------------------------------------------------------
1 | MODDIR=${0%/*}
--------------------------------------------------------------------------------
/template/magisk_module/uninstall.sh:
--------------------------------------------------------------------------------
1 | #!/sbin/sh
2 | # MODDIR=${0%/*}
3 | rm -rf /data/adb/modules/zygisk_magiskhide
4 |
--------------------------------------------------------------------------------
/template/magisk_module/verify.sh:
--------------------------------------------------------------------------------
1 | TMPDIR_FOR_VERIFY="$TMPDIR/.vunzip"
2 | mkdir "$TMPDIR_FOR_VERIFY"
3 |
4 | abort_verify() {
5 | ui_print "*********************************************************"
6 | ui_print "! $1"
7 | ui_print "! This zip may be corrupted, please try downloading again"
8 | abort "*********************************************************"
9 | }
10 |
11 | # extract
12 | extract() {
13 | zip=$1
14 | file=$2
15 | dir=$3
16 | junk_paths=$4
17 | [ -z "$junk_paths" ] && junk_paths=false
18 | opts="-o"
19 | [ $junk_paths = true ] && opts="-oj"
20 |
21 | file_path=""
22 | hash_path=""
23 | if [ $junk_paths = true ]; then
24 | file_path="$dir/$(basename "$file")"
25 | hash_path="$TMPDIR_FOR_VERIFY/$(basename "$file").sha256sum"
26 | else
27 | file_path="$dir/$file"
28 | hash_path="$TMPDIR_FOR_VERIFY/$file.sha256sum"
29 | fi
30 |
31 | unzip $opts "$zip" "$file" -d "$dir" >&2
32 | [ -f "$file_path" ] || abort_verify "$file not exists"
33 |
34 | unzip $opts "$zip" "$file.sha256sum" -d "$TMPDIR_FOR_VERIFY" >&2
35 | [ -f "$hash_path" ] || abort_verify "$file.sha256sum not exists"
36 |
37 | (echo "$(cat "$hash_path") $file_path" | sha256sum -c -s -) || abort_verify "Failed to verify $file"
38 | ui_print "- Verified $file" >&1
39 | }
40 |
--------------------------------------------------------------------------------