Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
M
Magisk
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Magisk
Commits
8e61080a
Commit
8e61080a
authored
Dec 30, 2020
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Preparation for hiding isolated processes
parent
3f9a6441
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
270 additions
and
215 deletions
+270
-215
XAndroid.kt
app/src/main/java/com/topjohnwu/magisk/ktx/XAndroid.kt
+7
-27
HideApp.kt
app/src/main/java/com/topjohnwu/magisk/ui/hide/HideApp.kt
+0
-47
HideInfo.kt
app/src/main/java/com/topjohnwu/magisk/ui/hide/HideInfo.kt
+102
-0
HideRvItems.kt
...src/main/java/com/topjohnwu/magisk/ui/hide/HideRvItems.kt
+16
-16
HideViewModel.kt
...c/main/java/com/topjohnwu/magisk/ui/hide/HideViewModel.kt
+8
-21
item_hide_md2.xml
app/src/main/res/layout/item_hide_md2.xml
+1
-1
item_hide_process_md2.xml
app/src/main/res/layout/item_hide_process_md2.xml
+1
-1
rootdir.cpp
native/jni/init/rootdir.cpp
+1
-1
hide_utils.cpp
native/jni/magiskhide/hide_utils.cpp
+47
-30
magiskhide.hpp
native/jni/magiskhide/magiskhide.hpp
+1
-0
proc_monitor.cpp
native/jni/magiskhide/proc_monitor.cpp
+76
-54
misc.cpp
native/jni/utils/misc.cpp
+0
-12
misc.hpp
native/jni/utils/misc.hpp
+10
-5
No files found.
app/src/main/java/com/topjohnwu/magisk/ktx/XAndroid.kt
View file @
8e61080a
...
@@ -7,9 +7,11 @@ import android.content.Context
...
@@ -7,9 +7,11 @@ import android.content.Context
import
android.content.ContextWrapper
import
android.content.ContextWrapper
import
android.content.Intent
import
android.content.Intent
import
android.content.pm.ApplicationInfo
import
android.content.pm.ApplicationInfo
import
android.content.pm.ComponentInfo
import
android.content.pm.PackageManager
import
android.content.pm.PackageManager
import
android.content.pm.PackageManager.*
import
android.content.pm.PackageManager.*
import
android.content.pm.ServiceInfo
import
android.content.pm.ServiceInfo.FLAG_ISOLATED_PROCESS
import
android.content.pm.ServiceInfo.FLAG_USE_APP_ZYGOTE
import
android.content.res.Configuration
import
android.content.res.Configuration
import
android.content.res.Resources
import
android.content.res.Resources
import
android.database.Cursor
import
android.database.Cursor
...
@@ -57,32 +59,10 @@ import java.lang.reflect.Array as JArray
...
@@ -57,32 +59,10 @@ import java.lang.reflect.Array as JArray
val
packageName
:
String
get
()
=
get
<
Context
>().
packageName
val
packageName
:
String
get
()
=
get
<
Context
>().
packageName
val
ApplicationInfo
.
processes
:
List
<
String
>
@SuppressLint
(
"InlinedApi"
)
get
()
{
val
ServiceInfo
.
isIsolated
get
()
=
(
flags
and
FLAG_ISOLATED_PROCESS
)
!=
0
val
pm
=
get
<
PackageManager
>()
val
appProcessName
=
processName
?:
packageName
@get
:
SuppressLint
(
"InlinedApi"
)
val
baseFlag
=
MATCH_DISABLED_COMPONENTS
or
MATCH_UNINSTALLED_PACKAGES
val
ServiceInfo
.
useAppZygote
get
()
=
(
flags
and
FLAG_USE_APP_ZYGOTE
)
!=
0
val
packageInfo
=
try
{
val
request
=
GET_ACTIVITIES
or
GET_SERVICES
or
GET_RECEIVERS
or
GET_PROVIDERS
pm
.
getPackageInfo
(
packageName
,
baseFlag
or
request
)
}
catch
(
e
:
NameNotFoundException
)
{
// EdXposed hooked, issue#3276
return
listOf
(
appProcessName
)
}
catch
(
e
:
Exception
)
{
// Exceed binder data transfer limit, fetch each component type separately
pm
.
getPackageInfo
(
packageName
,
baseFlag
).
apply
{
runCatching
{
activities
=
pm
.
getPackageInfo
(
packageName
,
GET_ACTIVITIES
).
activities
}
runCatching
{
services
=
pm
.
getPackageInfo
(
packageName
,
GET_SERVICES
).
services
}
runCatching
{
receivers
=
pm
.
getPackageInfo
(
packageName
,
GET_RECEIVERS
).
receivers
}
runCatching
{
providers
=
pm
.
getPackageInfo
(
packageName
,
GET_PROVIDERS
).
providers
}
}
}
fun
Array
<
out
ComponentInfo
>.
processNames
()
=
map
{
it
.
processName
?:
appProcessName
}
return
with
(
packageInfo
)
{
activities
?.
processNames
().
orEmpty
()
+
services
?.
processNames
().
orEmpty
()
+
receivers
?.
processNames
().
orEmpty
()
+
providers
?.
processNames
().
orEmpty
()
}
}
fun
Context
.
rawResource
(
id
:
Int
)
=
resources
.
openRawResource
(
id
)
fun
Context
.
rawResource
(
id
:
Int
)
=
resources
.
openRawResource
(
id
)
...
...
app/src/main/java/com/topjohnwu/magisk/ui/hide/HideApp.kt
deleted
100644 → 0
View file @
3f9a6441
package
com.topjohnwu.magisk.ui.hide
import
android.content.pm.ApplicationInfo
import
android.content.pm.PackageManager
import
android.graphics.drawable.Drawable
import
com.topjohnwu.magisk.core.utils.currentLocale
import
com.topjohnwu.magisk.ktx.getLabel
class
HideTarget
(
line
:
String
)
{
val
packageName
:
String
val
process
:
String
init
{
val
split
=
line
.
split
(
Regex
(
"\\|"
),
2
)
packageName
=
split
[
0
]
process
=
split
.
getOrElse
(
1
)
{
packageName
}
}
}
class
HideAppInfo
(
info
:
ApplicationInfo
,
pm
:
PackageManager
)
:
ApplicationInfo
(
info
),
Comparable
<
HideAppInfo
>
{
val
label
=
info
.
getLabel
(
pm
)
val
iconImage
:
Drawable
=
info
.
loadIcon
(
pm
)
override
fun
compareTo
(
other
:
HideAppInfo
)
=
comparator
.
compare
(
this
,
other
)
companion
object
{
private
val
comparator
=
compareBy
<
HideAppInfo
>(
{
it
.
label
.
toLowerCase
(
currentLocale
)
},
{
it
.
packageName
}
)
}
}
data class
HideProcessInfo
(
val
name
:
String
,
val
packageName
:
String
,
val
isHidden
:
Boolean
)
class
HideAppTarget
(
val
info
:
HideAppInfo
,
val
processes
:
List
<
HideProcessInfo
>
)
:
Comparable
<
HideAppTarget
>
{
override
fun
compareTo
(
other
:
HideAppTarget
)
=
compareValuesBy
(
this
,
other
)
{
it
.
info
}
}
app/src/main/java/com/topjohnwu/magisk/ui/hide/HideInfo.kt
0 → 100644
View file @
8e61080a
package
com.topjohnwu.magisk.ui.hide
import
android.annotation.SuppressLint
import
android.content.pm.ApplicationInfo
import
android.content.pm.ComponentInfo
import
android.content.pm.PackageManager
import
android.content.pm.PackageManager.*
import
android.content.pm.ServiceInfo
import
android.graphics.drawable.Drawable
import
com.topjohnwu.magisk.core.utils.currentLocale
import
com.topjohnwu.magisk.ktx.getLabel
import
com.topjohnwu.magisk.ktx.isIsolated
import
com.topjohnwu.magisk.ktx.useAppZygote
class
CmdlineHiddenItem
(
line
:
String
)
{
val
packageName
:
String
val
process
:
String
init
{
val
split
=
line
.
split
(
Regex
(
"\\|"
),
2
)
packageName
=
split
[
0
]
process
=
split
.
getOrElse
(
1
)
{
packageName
}
}
}
const
val
ISOLATED_MAGIC
=
"isolated"
@SuppressLint
(
"InlinedApi"
)
class
HideAppInfo
(
info
:
ApplicationInfo
,
pm
:
PackageManager
,
hideList
:
List
<
CmdlineHiddenItem
>)
:
ApplicationInfo
(
info
),
Comparable
<
HideAppInfo
>
{
val
label
=
info
.
getLabel
(
pm
)
val
iconImage
:
Drawable
=
info
.
loadIcon
(
pm
)
val
processes
=
fetchProcesses
(
pm
,
hideList
)
override
fun
compareTo
(
other
:
HideAppInfo
)
=
comparator
.
compare
(
this
,
other
)
private
fun
fetchProcesses
(
pm
:
PackageManager
,
hideList
:
List
<
CmdlineHiddenItem
>
):
List
<
HideProcessInfo
>
{
// Fetch full PackageInfo
val
baseFlag
=
MATCH_DISABLED_COMPONENTS
or
MATCH_UNINSTALLED_PACKAGES
val
packageInfo
=
try
{
val
request
=
GET_ACTIVITIES
or
GET_SERVICES
or
GET_RECEIVERS
or
GET_PROVIDERS
pm
.
getPackageInfo
(
packageName
,
baseFlag
or
request
)
}
catch
(
e
:
NameNotFoundException
)
{
// EdXposed hooked, issue#3276
return
emptyList
()
}
catch
(
e
:
Exception
)
{
// Exceed binder data transfer limit, fetch each component type separately
pm
.
getPackageInfo
(
packageName
,
baseFlag
).
apply
{
runCatching
{
activities
=
pm
.
getPackageInfo
(
packageName
,
baseFlag
or
GET_ACTIVITIES
).
activities
}
runCatching
{
services
=
pm
.
getPackageInfo
(
packageName
,
baseFlag
or
GET_SERVICES
).
services
}
runCatching
{
receivers
=
pm
.
getPackageInfo
(
packageName
,
baseFlag
or
GET_RECEIVERS
).
receivers
}
runCatching
{
providers
=
pm
.
getPackageInfo
(
packageName
,
baseFlag
or
GET_PROVIDERS
).
providers
}
}
}
val
hidden
=
hideList
.
filter
{
it
.
packageName
==
packageName
||
it
.
packageName
==
ISOLATED_MAGIC
}
fun
createProcess
(
name
:
String
,
pkg
:
String
=
packageName
):
HideProcessInfo
{
return
HideProcessInfo
(
name
,
pkg
,
hidden
.
any
{
it
.
process
==
name
})
}
var
haveAppZygote
=
false
fun
Array
<
out
ComponentInfo
>.
processes
()
=
map
{
createProcess
(
it
.
processName
)
}
fun
Array
<
ServiceInfo
>.
processes
()
=
map
{
if
(
it
.
isIsolated
)
{
if
(
it
.
useAppZygote
)
{
haveAppZygote
=
true
// Using app zygote, don't need to track the process
null
}
else
{
createProcess
(
"${it.processName}:${it.name}"
,
ISOLATED_MAGIC
)
}
}
else
{
createProcess
(
it
.
processName
)
}
}
return
with
(
packageInfo
)
{
activities
?.
processes
().
orEmpty
()
+
services
?.
processes
().
orEmpty
()
+
receivers
?.
processes
().
orEmpty
()
+
providers
?.
processes
().
orEmpty
()
+
listOf
(
if
(
haveAppZygote
)
createProcess
(
"${processName}_zygote"
)
else
null
)
}.
filterNotNull
().
distinctBy
{
it
.
name
}.
sortedBy
{
it
.
name
}
}
companion
object
{
private
val
comparator
=
compareBy
<
HideAppInfo
>(
{
it
.
label
.
toLowerCase
(
currentLocale
)
},
{
it
.
packageName
}
)
}
}
data class
HideProcessInfo
(
val
name
:
String
,
val
packageName
:
String
,
var
isHidden
:
Boolean
)
app/src/main/java/com/topjohnwu/magisk/ui/hide/HideRvItems.kt
View file @
8e61080a
...
@@ -12,14 +12,13 @@ import com.topjohnwu.magisk.utils.set
...
@@ -12,14 +12,13 @@ import com.topjohnwu.magisk.utils.set
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.Shell
import
kotlin.math.roundToInt
import
kotlin.math.roundToInt
class
HideItem
(
class
Hide
Rv
Item
(
app
:
HideAppTarget
val
info
:
HideAppInfo
)
:
ObservableItem
<
Hide
Item
>(),
Comparable
<
Hide
Item
>
{
)
:
ObservableItem
<
Hide
RvItem
>(),
Comparable
<
HideRv
Item
>
{
override
val
layoutRes
=
R
.
layout
.
item_hide_md2
override
val
layoutRes
get
()
=
R
.
layout
.
item_hide_md2
val
info
=
app
.
info
val
processes
=
info
.
processes
.
map
{
HideProcessRvItem
(
it
)
}
val
processes
=
app
.
processes
.
map
{
HideProcessItem
(
it
)
}
@get
:
Bindable
@get
:
Bindable
var
isExpanded
=
false
var
isExpanded
=
false
...
@@ -73,10 +72,10 @@ class HideItem(
...
@@ -73,10 +72,10 @@ class HideItem(
}
}
}
}
override
fun
compareTo
(
other
:
HideItem
)
=
comparator
.
compare
(
this
,
other
)
override
fun
compareTo
(
other
:
Hide
Rv
Item
)
=
comparator
.
compare
(
this
,
other
)
companion
object
{
companion
object
{
private
val
comparator
=
compareBy
<
HideItem
>(
private
val
comparator
=
compareBy
<
Hide
Rv
Item
>(
{
it
.
itemsChecked
==
0
},
{
it
.
itemsChecked
==
0
},
{
it
.
info
}
{
it
.
info
}
)
)
...
@@ -84,16 +83,17 @@ class HideItem(
...
@@ -84,16 +83,17 @@ class HideItem(
}
}
class
HideProcessItem
(
class
HideProcess
Rv
Item
(
val
process
:
HideProcessInfo
val
process
:
HideProcessInfo
)
:
ObservableItem
<
HideProcessItem
>()
{
)
:
ObservableItem
<
HideProcess
Rv
Item
>()
{
override
val
layoutRes
=
R
.
layout
.
item_hide_process_md2
override
val
layoutRes
get
()
=
R
.
layout
.
item_hide_process_md2
@get
:
Bindable
@get
:
Bindable
var
isHidden
=
process
.
isHidden
var
isHidden
set
(
value
)
=
set
(
value
,
field
,
{
field
=
it
},
BR
.
hidden
)
{
get
()
=
process
.
isHidden
val
arg
=
if
(
isHidden
)
"add"
else
"rm"
set
(
value
)
=
set
(
value
,
process
.
isHidden
,
{
process
.
isHidden
=
it
},
BR
.
hidden
)
{
val
arg
=
if
(
it
)
"add"
else
"rm"
val
(
name
,
pkg
)
=
process
val
(
name
,
pkg
)
=
process
Shell
.
su
(
"magiskhide --$arg $pkg $name"
).
submit
()
Shell
.
su
(
"magiskhide --$arg $pkg $name"
).
submit
()
}
}
...
@@ -102,7 +102,7 @@ class HideProcessItem(
...
@@ -102,7 +102,7 @@ class HideProcessItem(
isHidden
=
!
isHidden
isHidden
=
!
isHidden
}
}
override
fun
contentSameAs
(
other
:
HideProcessItem
)
=
process
==
other
.
process
override
fun
contentSameAs
(
other
:
HideProcess
Rv
Item
)
=
process
==
other
.
process
override
fun
itemSameAs
(
other
:
HideProcessItem
)
=
process
.
name
==
other
.
process
.
name
override
fun
itemSameAs
(
other
:
HideProcess
Rv
Item
)
=
process
.
name
==
other
.
process
.
name
}
}
app/src/main/java/com/topjohnwu/magisk/ui/hide/HideViewModel.kt
View file @
8e61080a
...
@@ -3,6 +3,7 @@ package com.topjohnwu.magisk.ui.hide
...
@@ -3,6 +3,7 @@ package com.topjohnwu.magisk.ui.hide
import
android.annotation.SuppressLint
import
android.annotation.SuppressLint
import
android.content.pm.ApplicationInfo
import
android.content.pm.ApplicationInfo
import
android.content.pm.PackageManager
import
android.content.pm.PackageManager
import
android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES
import
android.os.Process
import
android.os.Process
import
androidx.databinding.Bindable
import
androidx.databinding.Bindable
import
androidx.lifecycle.viewModelScope
import
androidx.lifecycle.viewModelScope
...
@@ -14,7 +15,6 @@ import com.topjohnwu.magisk.arch.itemBindingOf
...
@@ -14,7 +15,6 @@ import com.topjohnwu.magisk.arch.itemBindingOf
import
com.topjohnwu.magisk.core.Config
import
com.topjohnwu.magisk.core.Config
import
com.topjohnwu.magisk.ktx.get
import
com.topjohnwu.magisk.ktx.get
import
com.topjohnwu.magisk.ktx.packageName
import
com.topjohnwu.magisk.ktx.packageName
import
com.topjohnwu.magisk.ktx.processes
import
com.topjohnwu.magisk.utils.Utils
import
com.topjohnwu.magisk.utils.Utils
import
com.topjohnwu.magisk.utils.set
import
com.topjohnwu.magisk.utils.set
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.Shell
...
@@ -45,11 +45,11 @@ class HideViewModel : BaseViewModel(), Queryable {
...
@@ -45,11 +45,11 @@ class HideViewModel : BaseViewModel(), Queryable {
submitQuery
()
submitQuery
()
}
}
val
items
=
filterableListOf
<
HideItem
>()
val
items
=
filterableListOf
<
Hide
Rv
Item
>()
val
itemBinding
=
itemBindingOf
<
HideItem
>
{
val
itemBinding
=
itemBindingOf
<
Hide
Rv
Item
>
{
it
.
bindExtra
(
BR
.
viewModel
,
this
)
it
.
bindExtra
(
BR
.
viewModel
,
this
)
}
}
val
itemInternalBinding
=
itemBindingOf
<
HideProcessItem
>
{
val
itemInternalBinding
=
itemBindingOf
<
HideProcess
Rv
Item
>
{
it
.
bindExtra
(
BR
.
viewModel
,
this
)
it
.
bindExtra
(
BR
.
viewModel
,
this
)
}
}
...
@@ -62,14 +62,13 @@ class HideViewModel : BaseViewModel(), Queryable {
...
@@ -62,14 +62,13 @@ class HideViewModel : BaseViewModel(), Queryable {
state
=
State
.
LOADING
state
=
State
.
LOADING
val
(
apps
,
diff
)
=
withContext
(
Dispatchers
.
Default
)
{
val
(
apps
,
diff
)
=
withContext
(
Dispatchers
.
Default
)
{
val
pm
=
get
<
PackageManager
>()
val
pm
=
get
<
PackageManager
>()
val
hide
s
=
Shell
.
su
(
"magiskhide --ls"
).
exec
().
out
.
map
{
HideTarget
(
it
)
}
val
hide
List
=
Shell
.
su
(
"magiskhide --ls"
).
exec
().
out
.
map
{
CmdlineHiddenItem
(
it
)
}
val
apps
=
pm
.
getInstalledApplications
(
PackageManager
.
MATCH_UNINSTALLED_PACKAGES
)
val
apps
=
pm
.
getInstalledApplications
(
MATCH_UNINSTALLED_PACKAGES
)
.
asSequence
()
.
asSequence
()
.
filter
{
it
.
enabled
&&
!
blacklist
.
contains
(
it
.
packageName
)
}
.
filter
{
it
.
enabled
&&
!
blacklist
.
contains
(
it
.
packageName
)
}
.
map
{
HideAppInfo
(
it
,
pm
)
}
.
map
{
HideAppInfo
(
it
,
pm
,
hideList
)
}
.
map
{
createTarget
(
it
,
hides
)
}
.
filter
{
it
.
processes
.
isNotEmpty
()
}
.
filter
{
it
.
processes
.
isNotEmpty
()
}
.
map
{
HideItem
(
it
)
}
.
map
{
Hide
Rv
Item
(
it
)
}
.
toList
()
.
toList
()
.
sorted
()
.
sorted
()
apps
to
items
.
calculateDiff
(
apps
)
apps
to
items
.
calculateDiff
(
apps
)
...
@@ -80,18 +79,6 @@ class HideViewModel : BaseViewModel(), Queryable {
...
@@ -80,18 +79,6 @@ class HideViewModel : BaseViewModel(), Queryable {
// ---
// ---
private
fun
createTarget
(
info
:
HideAppInfo
,
hideList
:
List
<
HideTarget
>):
HideAppTarget
{
val
pkg
=
info
.
packageName
val
hidden
=
hideList
.
filter
{
it
.
packageName
==
pkg
}
val
processNames
=
info
.
processes
.
distinct
()
val
processes
=
processNames
.
map
{
name
->
HideProcessInfo
(
name
,
pkg
,
hidden
.
any
{
name
==
it
.
process
})
}
return
HideAppTarget
(
info
,
processes
)
}
// ---
override
fun
query
()
{
override
fun
query
()
{
items
.
filter
{
items
.
filter
{
fun
showHidden
()
=
it
.
itemsChecked
!=
0
fun
showHidden
()
=
it
.
itemsChecked
!=
0
...
...
app/src/main/res/layout/item_hide_md2.xml
View file @
8e61080a
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
<variable
<variable
name=
"item"
name=
"item"
type=
"com.topjohnwu.magisk.ui.hide.HideItem"
/>
type=
"com.topjohnwu.magisk.ui.hide.Hide
Rv
Item"
/>
<variable
<variable
name=
"viewModel"
name=
"viewModel"
...
...
app/src/main/res/layout/item_hide_process_md2.xml
View file @
8e61080a
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
<variable
<variable
name=
"item"
name=
"item"
type=
"com.topjohnwu.magisk.ui.hide.HideProcessItem"
/>
type=
"com.topjohnwu.magisk.ui.hide.HideProcess
Rv
Item"
/>
<variable
<variable
name=
"viewModel"
name=
"viewModel"
...
...
native/jni/init/rootdir.cpp
View file @
8e61080a
...
@@ -68,7 +68,7 @@ static void load_overlay_rc(const char *overlay) {
...
@@ -68,7 +68,7 @@ static void load_overlay_rc(const char *overlay) {
// Do not allow overwrite init.rc
// Do not allow overwrite init.rc
unlinkat
(
dfd
,
"init.rc"
,
0
);
unlinkat
(
dfd
,
"init.rc"
,
0
);
for
(
dirent
*
entry
;
(
entry
=
xreaddir
(
dir
.
get
()));)
{
for
(
dirent
*
entry
;
(
entry
=
xreaddir
(
dir
.
get
()));)
{
if
(
str
end
(
entry
->
d_name
,
".rc"
)
==
0
)
{
if
(
str
_ends
(
entry
->
d_name
,
".rc"
)
)
{
LOGD
(
"Found rc script [%s]
\n
"
,
entry
->
d_name
);
LOGD
(
"Found rc script [%s]
\n
"
,
entry
->
d_name
);
int
rc
=
xopenat
(
dfd
,
entry
->
d_name
,
O_RDONLY
|
O_CLOEXEC
);
int
rc
=
xopenat
(
dfd
,
entry
->
d_name
,
O_RDONLY
|
O_CLOEXEC
);
rc_list
.
push_back
(
fd_full_read
(
rc
));
rc_list
.
push_back
(
fd_full_read
(
rc
));
...
...
native/jni/magiskhide/hide_utils.cpp
View file @
8e61080a
...
@@ -48,23 +48,27 @@ void set_hide_state(bool state) {
...
@@ -48,23 +48,27 @@ void set_hide_state(bool state) {
hide_state
=
state
;
hide_state
=
state
;
}
}
template
<
bool
str_op
(
string_view
,
string_view
)
>
static
bool
proc_name_match
(
int
pid
,
const
char
*
name
)
{
static
bool
proc_name_match
(
int
pid
,
const
char
*
name
)
{
char
buf
[
4019
];
char
buf
[
4019
];
sprintf
(
buf
,
"/proc/%d/cmdline"
,
pid
);
sprintf
(
buf
,
"/proc/%d/cmdline"
,
pid
);
if
(
FILE
*
f
=
fopen
(
buf
,
"re"
))
{
if
(
auto
fp
=
open_file
(
buf
,
"re"
))
{
fgets
(
buf
,
sizeof
(
buf
),
f
);
fgets
(
buf
,
sizeof
(
buf
),
f
p
.
get
()
);
fclose
(
f
);
if
(
str_op
(
buf
,
name
))
{
if
(
strcmp
(
buf
,
name
)
==
0
)
LOGD
(
"hide_utils: kill PID=[%d] (%s)
\n
"
,
pid
,
buf
);
return
true
;
return
true
;
}
}
}
return
false
;
return
false
;
}
}
static
void
kill_process
(
const
char
*
name
,
bool
multi
=
false
)
{
static
inline
bool
str_eql
(
string_view
s
,
string_view
ss
)
{
return
s
==
ss
;
}
static
void
kill_process
(
const
char
*
name
,
bool
multi
=
false
,
bool
(
*
filter
)(
int
,
const
char
*
)
=
proc_name_match
<&
str_eql
>
)
{
crawl_procfs
([
=
](
int
pid
)
->
bool
{
crawl_procfs
([
=
](
int
pid
)
->
bool
{
if
(
proc_name_match
(
pid
,
name
))
{
if
(
filter
(
pid
,
name
))
{
if
(
kill
(
pid
,
SIGTERM
)
==
0
)
kill
(
pid
,
SIGTERM
);
LOGD
(
"hide_utils: killed PID=[%d] (%s)
\n
"
,
pid
,
name
);
return
multi
;
return
multi
;
}
}
return
true
;
return
true
;
...
@@ -72,6 +76,8 @@ static void kill_process(const char *name, bool multi = false) {
...
@@ -72,6 +76,8 @@ static void kill_process(const char *name, bool multi = false) {
}
}
static
bool
validate
(
const
char
*
s
)
{
static
bool
validate
(
const
char
*
s
)
{
if
(
strcmp
(
s
,
ISOLATED_MAGIC
)
==
0
)
return
true
;
bool
dot
=
false
;
bool
dot
=
false
;
for
(
char
c
;
(
c
=
*
s
);
++
s
)
{
for
(
char
c
;
(
c
=
*
s
);
++
s
)
{
if
((
c
>=
'A'
&&
c
<=
'Z'
)
||
(
c
>=
'a'
&&
c
<=
'z'
)
||
if
((
c
>=
'A'
&&
c
<=
'Z'
)
||
(
c
>=
'a'
&&
c
<=
'z'
)
||
...
@@ -87,7 +93,18 @@ static bool validate(const char *s) {
...
@@ -87,7 +93,18 @@ static bool validate(const char *s) {
return
dot
;
return
dot
;
}
}
static
int
add_list
(
const
char
*
pkg
,
const
char
*
proc
=
""
)
{
static
void
add_hide_set
(
const
char
*
pkg
,
const
char
*
proc
)
{
LOGI
(
"hide_list add: [%s/%s]
\n
"
,
pkg
,
proc
);
hide_set
.
emplace
(
pkg
,
proc
);
if
(
strcmp
(
pkg
,
ISOLATED_MAGIC
)
==
0
)
{
// Kill all matching isolated processes
kill_process
(
proc
,
true
,
proc_name_match
<&
str_starts
>
);
}
else
{
kill_process
(
proc
);
}
}
static
int
add_list
(
const
char
*
pkg
,
const
char
*
proc
)
{
if
(
proc
[
0
]
==
'\0'
)
if
(
proc
[
0
]
==
'\0'
)
proc
=
pkg
;
proc
=
pkg
;
...
@@ -105,15 +122,12 @@ static int add_list(const char *pkg, const char *proc = "") {
...
@@ -105,15 +122,12 @@ static int add_list(const char *pkg, const char *proc = "") {
char
*
err
=
db_exec
(
sql
);
char
*
err
=
db_exec
(
sql
);
db_err_cmd
(
err
,
return
DAEMON_ERROR
);
db_err_cmd
(
err
,
return
DAEMON_ERROR
);
LOGI
(
"hide_list add: [%s/%s]
\n
"
,
pkg
,
proc
);
// Critical region
{
{
// Critical region
mutex_guard
lock
(
monitor_lock
);
mutex_guard
lock
(
monitor_lock
);
hide_set
.
emplace
(
pkg
,
proc
);
add_hide_set
(
pkg
,
proc
);
}
}
kill_process
(
proc
);
return
DAEMON_SUCCESS
;
return
DAEMON_SUCCESS
;
}
}
...
@@ -123,27 +137,28 @@ int add_list(int client) {
...
@@ -123,27 +137,28 @@ int add_list(int client) {
int
ret
=
add_list
(
pkg
,
proc
);
int
ret
=
add_list
(
pkg
,
proc
);
free
(
pkg
);
free
(
pkg
);
free
(
proc
);
free
(
proc
);
update_uid_map
();
if
(
ret
==
DAEMON_SUCCESS
)
update_uid_map
();
return
ret
;
return
ret
;
}
}
static
int
rm_list
(
const
char
*
pkg
,
const
char
*
proc
=
""
)
{
static
int
rm_list
(
const
char
*
pkg
,
const
char
*
proc
)
{
bool
remove
=
false
;
{
{
// Critical region
// Critical region
mutex_guard
lock
(
monitor_lock
);
mutex_guard
lock
(
monitor_lock
);
bool
remove
=
false
;
for
(
auto
it
=
hide_set
.
begin
();
it
!=
hide_set
.
end
();)
{
for
(
auto
it
=
hide_set
.
begin
();
it
!=
hide_set
.
end
();)
{
if
(
it
->
first
==
pkg
&&
(
proc
[
0
]
==
'\0'
||
it
->
second
==
proc
))
{
if
(
it
->
first
==
pkg
&&
(
proc
[
0
]
==
'\0'
||
it
->
second
==
proc
))
{
remove
=
true
;
remove
=
true
;
LOGI
(
"hide_list rm: [%s
]
\n
"
,
it
->
second
.
data
());
LOGI
(
"hide_list rm: [%s
/%s]
\n
"
,
it
->
first
.
data
()
,
it
->
second
.
data
());
it
=
hide_set
.
erase
(
it
);
it
=
hide_set
.
erase
(
it
);
}
else
{
}
else
{
++
it
;
++
it
;
}
}
}
}
if
(
!
remove
)
return
HIDE_ITEM_NOT_EXIST
;
}
}
if
(
!
remove
)
return
HIDE_ITEM_NOT_EXIST
;
char
sql
[
4096
];
char
sql
[
4096
];
if
(
proc
[
0
]
==
'\0'
)
if
(
proc
[
0
]
==
'\0'
)
...
@@ -167,10 +182,11 @@ int rm_list(int client) {
...
@@ -167,10 +182,11 @@ int rm_list(int client) {
return
ret
;
return
ret
;
}
}
static
void
init_list
(
const
char
*
pkg
,
const
char
*
proc
)
{
static
bool
str_ends_safe
(
string_view
s
,
string_view
ss
)
{
LOGI
(
"hide_list init: [%s/%s]
\n
"
,
pkg
,
proc
);
// Never kill webview zygote
hide_set
.
emplace
(
pkg
,
proc
);
if
(
s
==
"webview_zygote"
)
kill_process
(
proc
);
return
false
;
return
str_ends
(
s
,
ss
);
}
}
#define SNET_PROC "com.google.android.gms.unstable"
#define SNET_PROC "com.google.android.gms.unstable"
...
@@ -181,25 +197,26 @@ static bool init_list() {
...
@@ -181,25 +197,26 @@ static bool init_list() {
LOGD
(
"hide_list: initialize
\n
"
);
LOGD
(
"hide_list: initialize
\n
"
);
char
*
err
=
db_exec
(
"SELECT * FROM hidelist"
,
[](
db_row
&
row
)
->
bool
{
char
*
err
=
db_exec
(
"SELECT * FROM hidelist"
,
[](
db_row
&
row
)
->
bool
{
init_lis
t
(
row
[
"package_name"
].
data
(),
row
[
"process"
].
data
());
add_hide_se
t
(
row
[
"package_name"
].
data
(),
row
[
"process"
].
data
());
return
true
;
return
true
;
});
});
db_err_cmd
(
err
,
return
false
);
db_err_cmd
(
err
,
return
false
);
// If Android Q+, also kill blastula pool
// If Android Q+, also kill blastula pool
and all app zygotes
if
(
SDK_INT
>=
29
)
{
if
(
SDK_INT
>=
29
)
{
kill_process
(
"usap32"
,
true
);
kill_process
(
"usap32"
,
true
);
kill_process
(
"usap64"
,
true
);
kill_process
(
"usap64"
,
true
);
kill_process
(
"_zygote"
,
true
,
proc_name_match
<&
str_ends_safe
>
);
}
}
// Add SafetyNet by default
// Add SafetyNet by default
init_lis
t
(
GMS_PKG
,
SNET_PROC
);
add_hide_se
t
(
GMS_PKG
,
SNET_PROC
);
init_lis
t
(
MICROG_PKG
,
SNET_PROC
);
add_hide_se
t
(
MICROG_PKG
,
SNET_PROC
);
// We also need to hide the default GMS process if MAGISKTMP != /sbin
// We also need to hide the default GMS process if MAGISKTMP != /sbin
// The snet process communicates with the main process and get additional info
// The snet process communicates with the main process and get additional info
if
(
MAGISKTMP
!=
"/sbin"
)
if
(
MAGISKTMP
!=
"/sbin"
)
init_lis
t
(
GMS_PKG
,
GMS_PKG
);
add_hide_se
t
(
GMS_PKG
,
GMS_PKG
);
update_uid_map
();
update_uid_map
();
return
true
;
return
true
;
...
@@ -251,7 +268,7 @@ int launch_magiskhide() {
...
@@ -251,7 +268,7 @@ int launch_magiskhide() {
hide_late_sensitive_props
();
hide_late_sensitive_props
();
// Start monitoring
// Start monitoring
void
*
(
*
start
)(
void
*
)
=
[](
void
*
)
->
void
*
{
proc_monitor
();
return
nullptr
;
};
void
*
(
*
start
)(
void
*
)
=
[](
void
*
)
->
void
*
{
proc_monitor
();
};
if
(
xpthread_create
(
&
proc_monitor_thread
,
nullptr
,
start
,
nullptr
))
if
(
xpthread_create
(
&
proc_monitor_thread
,
nullptr
,
start
,
nullptr
))
return
DAEMON_ERROR
;
return
DAEMON_ERROR
;
...
...
native/jni/magiskhide/magiskhide.hpp
View file @
8e61080a
...
@@ -13,6 +13,7 @@
...
@@ -13,6 +13,7 @@
#include <daemon.hpp>
#include <daemon.hpp>
#define SIGTERMTHRD SIGUSR1
#define SIGTERMTHRD SIGUSR1
#define ISOLATED_MAGIC "isolated"
// CLI entries
// CLI entries
int
launch_magiskhide
();
int
launch_magiskhide
();
...
...
native/jni/magiskhide/proc_monitor.cpp
View file @
8e61080a
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <unistd.h>
#include <fcntl.h>
#include <fcntl.h>
#include <signal.h>
#include <signal.h>
...
@@ -61,13 +58,13 @@ static int parse_ppid(int pid) {
...
@@ -61,13 +58,13 @@ static int parse_ppid(int pid) {
int
ppid
;
int
ppid
;
sprintf
(
path
,
"/proc/%d/stat"
,
pid
);
sprintf
(
path
,
"/proc/%d/stat"
,
pid
);
FILE
*
stat
=
fopen
(
path
,
"re"
);
if
(
stat
==
nullptr
)
auto
stat
=
open_file
(
path
,
"re"
);
if
(
!
stat
)
return
-
1
;
return
-
1
;
// PID COMM STATE PPID .....
// PID COMM STATE PPID .....
fscanf
(
stat
,
"%*d %*s %*c %d"
,
&
ppid
);
fscanf
(
stat
.
get
(),
"%*d %*s %*c %d"
,
&
ppid
);
fclose
(
stat
);
return
ppid
;
return
ppid
;
}
}
...
@@ -89,20 +86,27 @@ void update_uid_map() {
...
@@ -89,20 +86,27 @@ void update_uid_map() {
string
data_path
(
APP_DATA_DIR
);
string
data_path
(
APP_DATA_DIR
);
size_t
len
=
data_path
.
length
();
size_t
len
=
data_path
.
length
();
auto
dir
=
open_dir
(
APP_DATA_DIR
);
auto
dir
=
open_dir
(
APP_DATA_DIR
);
bool
firstIteration
=
true
;
for
(
dirent
*
entry
;
(
entry
=
xreaddir
(
dir
.
get
()));)
{
for
(
dirent
*
entry
;
(
entry
=
xreaddir
(
dir
.
get
()));)
{
data_path
.
resize
(
len
);
data_path
.
resize
(
len
);
data_path
+=
'/'
;
data_path
+=
'/'
;
data_path
+=
entry
->
d_name
;
data_path
+=
entry
->
d_name
;
// multiuser user id
data_path
+=
'/'
;
data_path
+=
'/'
;
size_t
user_len
=
data_path
.
length
();
size_t
user_len
=
data_path
.
length
();
struct
stat
st
;
struct
stat
st
;
for
(
auto
&
hide
:
hide_set
)
{
for
(
auto
&
hide
:
hide_set
)
{
if
(
hide
.
first
==
ISOLATED_MAGIC
)
{
if
(
!
firstIteration
)
continue
;
// Setup isolated processes
uid_proc_map
[
-
1
].
emplace_back
(
hide
.
second
);
}
data_path
.
resize
(
user_len
);
data_path
.
resize
(
user_len
);
data_path
+=
hide
.
first
;
data_path
+=
hide
.
first
;
if
(
stat
(
data_path
.
data
(),
&
st
))
if
(
stat
(
data_path
.
data
(),
&
st
))
continue
;
continue
;
uid_proc_map
[
st
.
st_uid
].
emplace_back
(
hide
.
second
);
uid_proc_map
[
st
.
st_uid
].
emplace_back
(
hide
.
second
);
}
}
firstIteration
=
false
;
}
}
}
}
...
@@ -224,7 +228,7 @@ static bool check_pid(int pid) {
...
@@ -224,7 +228,7 @@ static bool check_pid(int pid) {
sprintf
(
path
,
"/proc/%d"
,
pid
);
sprintf
(
path
,
"/proc/%d"
,
pid
);
if
(
stat
(
path
,
&
st
))
{
if
(
stat
(
path
,
&
st
))
{
// Process
kill
ed unexpectedly, ignore
// Process
di
ed unexpectedly, ignore
detach_pid
(
pid
);
detach_pid
(
pid
);
return
true
;
return
true
;
}
}
...
@@ -237,7 +241,7 @@ static bool check_pid(int pid) {
...
@@ -237,7 +241,7 @@ static bool check_pid(int pid) {
if
(
auto
f
=
open_file
(
path
,
"re"
))
{
if
(
auto
f
=
open_file
(
path
,
"re"
))
{
fgets
(
cmdline
,
sizeof
(
cmdline
),
f
.
get
());
fgets
(
cmdline
,
sizeof
(
cmdline
),
f
.
get
());
}
else
{
}
else
{
// Process
kill
ed unexpectedly, ignore
// Process
di
ed unexpectedly, ignore
detach_pid
(
pid
);
detach_pid
(
pid
);
return
true
;
return
true
;
}
}
...
@@ -247,36 +251,59 @@ static bool check_pid(int pid) {
...
@@ -247,36 +251,59 @@ static bool check_pid(int pid) {
return
false
;
return
false
;
int
uid
=
st
.
st_uid
;
int
uid
=
st
.
st_uid
;
auto
it
=
uid_proc_map
.
find
(
uid
);
auto
it
=
uid_proc_map
.
end
();
if
(
it
!=
uid_proc_map
.
end
())
{
if
(
uid
%
100000
>
90000
)
{
// Isolated process
it
=
uid_proc_map
.
find
(
-
1
);
if
(
it
==
uid_proc_map
.
end
())
goto
not_target
;
for
(
auto
&
s
:
it
->
second
)
{
for
(
auto
&
s
:
it
->
second
)
{
if
(
s
==
cmdline
)
{
if
(
str_starts
(
cmdline
,
s
))
{
// Double check whether ns is separated
LOGI
(
"proc_monitor: (isolated) [%s] PID=[%d] UID=[%d]
\n
"
,
cmdline
,
pid
,
uid
);
read_ns
(
pid
,
&
st
);
goto
inject_and_hide
;
bool
mnt_ns
=
true
;
}
for
(
auto
&
zit
:
zygote_map
)
{
}
if
(
zit
.
second
.
st_ino
==
st
.
st_ino
&&
}
zit
.
second
.
st_dev
==
st
.
st_dev
)
{
mnt_ns
=
false
;
it
=
uid_proc_map
.
find
(
uid
);
break
;
if
(
it
==
uid_proc_map
.
end
())
}
goto
not_target
;
}
for
(
auto
&
s
:
it
->
second
)
{
if
(
s
!=
cmdline
)
continue
;
if
(
str_ends
(
s
,
"_zygote"
))
{
LOGI
(
"proc_monitor: (app zygote) [%s] PID=[%d] UID=[%d]
\n
"
,
cmdline
,
pid
,
uid
);
goto
inject_and_hide
;
}
// Double check whether ns is separated
read_ns
(
pid
,
&
st
);
for
(
auto
&
zit
:
zygote_map
)
{
if
(
zit
.
second
.
st_ino
==
st
.
st_ino
&&
zit
.
second
.
st_dev
==
st
.
st_dev
)
{
// For some reason ns is not separated, abort
// For some reason ns is not separated, abort
if
(
!
mnt_ns
)
goto
not_target
;
break
;
// Finally this is our target!
// Detach from ptrace but should still remain stopped.
// The hide daemon will resume the process.
PTRACE_LOG
(
"target found
\n
"
);
LOGI
(
"proc_monitor: [%s] PID=[%d] UID=[%d]
\n
"
,
cmdline
,
pid
,
uid
);
detach_pid
(
pid
,
SIGSTOP
);
hide_daemon
(
pid
);
return
true
;
}
}
}
}
// Finally this is our target!
// Detach from ptrace but should still remain stopped.
// The hide daemon will resume the process.
LOGI
(
"proc_monitor: [%s] PID=[%d] UID=[%d]
\n
"
,
cmdline
,
pid
,
uid
);
detach_pid
(
pid
,
SIGSTOP
);
hide_daemon
(
pid
);
return
true
;
}
}
PTRACE_LOG
(
"[%s] not our target
\n
"
,
cmdline
);
not_target:
PTRACE_LOG
(
"[%s] is not our target
\n
"
,
cmdline
);
detach_pid
(
pid
);
return
true
;
inject_and_hide:
// TODO: handle isolated processes and app zygotes
detach_pid
(
pid
);
detach_pid
(
pid
);
return
true
;
return
true
;
}
}
...
@@ -324,7 +351,7 @@ static void new_zygote(int pid) {
...
@@ -324,7 +351,7 @@ static void new_zygote(int pid) {
}
}
#define WEVENT(s) (((s) & 0xffff0000) >> 16)
#define WEVENT(s) (((s) & 0xffff0000) >> 16)
#define DETACH_AND_CONT { detach
= true
; continue; }
#define DETACH_AND_CONT { detach
_pid(pid)
; continue; }
void
proc_monitor
()
{
void
proc_monitor
()
{
// Unblock some signals
// Unblock some signals
...
@@ -354,9 +381,7 @@ void proc_monitor() {
...
@@ -354,9 +381,7 @@ void proc_monitor() {
setitimer
(
ITIMER_REAL
,
&
interval
,
nullptr
);
setitimer
(
ITIMER_REAL
,
&
interval
,
nullptr
);
}
}
int
status
;
for
(
int
status
;;)
{
for
(;;)
{
const
int
pid
=
waitpid
(
-
1
,
&
status
,
__WALL
|
__WNOTHREAD
);
const
int
pid
=
waitpid
(
-
1
,
&
status
,
__WALL
|
__WNOTHREAD
);
if
(
pid
<
0
)
{
if
(
pid
<
0
)
{
if
(
errno
==
ECHILD
)
{
if
(
errno
==
ECHILD
)
{
...
@@ -370,38 +395,35 @@ void proc_monitor() {
...
@@ -370,38 +395,35 @@ void proc_monitor() {
}
}
continue
;
continue
;
}
}
bool
detach
=
false
;
run_finally
f
([
&
]
{
if
(
detach
)
// Non of our business now
detach_pid
(
pid
);
});
if
(
!
WIFSTOPPED
(
status
)
/* Ignore if not ptrace-stop */
)
if
(
!
WIFSTOPPED
(
status
)
/* Ignore if not ptrace-stop */
)
DETACH_AND_CONT
;
DETACH_AND_CONT
;
if
(
WSTOPSIG
(
status
)
==
SIGTRAP
&&
WEVENT
(
status
))
{
int
event
=
WEVENT
(
status
);
int
signal
=
WSTOPSIG
(
status
);
if
(
signal
==
SIGTRAP
&&
event
)
{
unsigned
long
msg
;
unsigned
long
msg
;
xptrace
(
PTRACE_GETEVENTMSG
,
pid
,
nullptr
,
&
msg
);
xptrace
(
PTRACE_GETEVENTMSG
,
pid
,
nullptr
,
&
msg
);
if
(
zygote_map
.
count
(
pid
))
{
if
(
zygote_map
.
count
(
pid
))
{
// Zygote event
// Zygote event
switch
(
WEVENT
(
status
)
)
{
switch
(
event
)
{
case
PTRACE_EVENT_FORK
:
case
PTRACE_EVENT_FORK
:
case
PTRACE_EVENT_VFORK
:
case
PTRACE_EVENT_VFORK
:
PTRACE_LOG
(
"zygote forked: [%
d
]
\n
"
,
msg
);
PTRACE_LOG
(
"zygote forked: [%
lu
]
\n
"
,
msg
);
attaches
[
msg
]
=
true
;
attaches
[
msg
]
=
true
;
break
;
break
;
case
PTRACE_EVENT_EXIT
:
case
PTRACE_EVENT_EXIT
:
PTRACE_LOG
(
"zygote exited with status: [%
d
]
\n
"
,
msg
);
PTRACE_LOG
(
"zygote exited with status: [%
lu
]
\n
"
,
msg
);
[[
fallthrough
]];
[[
fallthrough
]];
default:
default:
zygote_map
.
erase
(
pid
);
zygote_map
.
erase
(
pid
);
DETACH_AND_CONT
;
DETACH_AND_CONT
;
}
}
}
else
{
}
else
{
switch
(
WEVENT
(
status
)
)
{
switch
(
event
)
{
case
PTRACE_EVENT_CLONE
:
case
PTRACE_EVENT_CLONE
:
PTRACE_LOG
(
"create new threads: [%
d
]
\n
"
,
msg
);
PTRACE_LOG
(
"create new threads: [%
lu
]
\n
"
,
msg
);
if
(
attaches
[
pid
]
&&
check_pid
(
pid
))
if
(
attaches
[
pid
]
&&
check_pid
(
pid
))
continue
;
continue
;
break
;
break
;
...
@@ -414,7 +436,7 @@ void proc_monitor() {
...
@@ -414,7 +436,7 @@ void proc_monitor() {
}
}
}
}
xptrace
(
PTRACE_CONT
,
pid
);
xptrace
(
PTRACE_CONT
,
pid
);
}
else
if
(
WSTOPSIG
(
status
)
==
SIGSTOP
)
{
}
else
if
(
signal
==
SIGSTOP
)
{
if
(
!
attaches
[
pid
])
{
if
(
!
attaches
[
pid
])
{
// Double check if this is actually a process
// Double check if this is actually a process
attaches
[
pid
]
=
is_process
(
pid
);
attaches
[
pid
]
=
is_process
(
pid
);
...
@@ -432,8 +454,8 @@ void proc_monitor() {
...
@@ -432,8 +454,8 @@ void proc_monitor() {
}
}
}
else
{
}
else
{
// Not caused by us, resend signal
// Not caused by us, resend signal
xptrace
(
PTRACE_CONT
,
pid
,
nullptr
,
WSTOPSIG
(
status
)
);
xptrace
(
PTRACE_CONT
,
pid
,
nullptr
,
signal
);
PTRACE_LOG
(
"signal [%d]
\n
"
,
WSTOPSIG
(
status
)
);
PTRACE_LOG
(
"signal [%d]
\n
"
,
signal
);
}
}
}
}
}
}
native/jni/utils/misc.cpp
View file @
8e61080a
...
@@ -58,12 +58,6 @@ int gen_rand_str(char *buf, int len, bool varlen) {
...
@@ -58,12 +58,6 @@ int gen_rand_str(char *buf, int len, bool varlen) {
return
len
-
1
;
return
len
-
1
;
}
}
int
strend
(
const
char
*
s1
,
const
char
*
s2
)
{
size_t
l1
=
strlen
(
s1
);
size_t
l2
=
strlen
(
s2
);
return
strcmp
(
s1
+
l1
-
l2
,
s2
);
}
int
exec_command
(
exec_t
&
exec
)
{
int
exec_command
(
exec_t
&
exec
)
{
int
pipefd
[]
=
{
-
1
,
-
1
};
int
pipefd
[]
=
{
-
1
,
-
1
};
int
outfd
=
-
1
;
int
outfd
=
-
1
;
...
@@ -151,12 +145,6 @@ void set_nice_name(const char *name) {
...
@@ -151,12 +145,6 @@ void set_nice_name(const char *name) {
prctl
(
PR_SET_NAME
,
name
);
prctl
(
PR_SET_NAME
,
name
);
}
}
bool
ends_with
(
const
std
::
string_view
&
s1
,
const
std
::
string_view
&
s2
)
{
unsigned
l1
=
s1
.
length
();
unsigned
l2
=
s2
.
length
();
return
l1
<
l2
?
false
:
s1
.
compare
(
l1
-
l2
,
l2
,
s2
)
==
0
;
}
/*
/*
* Bionic's atoi runs through strtol().
* Bionic's atoi runs through strtol().
* Use our own implementation for faster conversion.
* Use our own implementation for faster conversion.
...
...
native/jni/utils/misc.hpp
View file @
8e61080a
...
@@ -8,9 +8,6 @@
...
@@ -8,9 +8,6 @@
#define UID_ROOT 0
#define UID_ROOT 0
#define UID_SHELL 2000
#define UID_SHELL 2000
#define str_contains(s, ss) ((ss) != nullptr && (s).find(ss) != std::string::npos)
#define str_starts(s, ss) ((ss) != nullptr && (s).compare(0, strlen(ss), ss) == 0)
class
mutex_guard
{
class
mutex_guard
{
public
:
public
:
explicit
mutex_guard
(
pthread_mutex_t
&
m
)
:
mutex
(
&
m
)
{
explicit
mutex_guard
(
pthread_mutex_t
&
m
)
:
mutex
(
&
m
)
{
...
@@ -65,10 +62,18 @@ using thread_entry = void *(*)(void *);
...
@@ -65,10 +62,18 @@ using thread_entry = void *(*)(void *);
int
new_daemon_thread
(
thread_entry
entry
,
void
*
arg
=
nullptr
,
const
pthread_attr_t
*
attr
=
nullptr
);
int
new_daemon_thread
(
thread_entry
entry
,
void
*
arg
=
nullptr
,
const
pthread_attr_t
*
attr
=
nullptr
);
int
new_daemon_thread
(
std
::
function
<
void
()
>
&&
entry
);
int
new_daemon_thread
(
std
::
function
<
void
()
>
&&
entry
);
bool
ends_with
(
const
std
::
string_view
&
s1
,
const
std
::
string_view
&
s2
);
static
inline
bool
str_contains
(
std
::
string_view
s
,
std
::
string_view
ss
)
{
return
s
.
find
(
ss
)
!=
std
::
string
::
npos
;
}
static
inline
bool
str_starts
(
std
::
string_view
s
,
std
::
string_view
ss
)
{
return
s
.
rfind
(
ss
,
0
)
==
0
;
}
static
inline
bool
str_ends
(
std
::
string_view
s
,
std
::
string_view
ss
)
{
return
s
.
size
()
>=
ss
.
size
()
&&
s
.
compare
(
s
.
size
()
-
ss
.
size
(),
std
::
string
::
npos
,
ss
)
==
0
;
}
int
fork_dont_care
();
int
fork_dont_care
();
int
fork_no_orphan
();
int
fork_no_orphan
();
int
strend
(
const
char
*
s1
,
const
char
*
s2
);
void
init_argv0
(
int
argc
,
char
**
argv
);
void
init_argv0
(
int
argc
,
char
**
argv
);
void
set_nice_name
(
const
char
*
name
);
void
set_nice_name
(
const
char
*
name
);
uint32_t
binary_gcd
(
uint32_t
u
,
uint32_t
v
);
uint32_t
binary_gcd
(
uint32_t
u
,
uint32_t
v
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment