├── .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 | --------------------------------------------------------------------------------