Skip to content

Commit b6639f8

Browse files
committed
Security: Add SELinux detection
Signed-off-by: Akane Beneckendorff <[email protected]>
1 parent f53f22a commit b6639f8

File tree

4 files changed

+128
-32
lines changed

4 files changed

+128
-32
lines changed

app/src/main/java/org/akanework/checker/MainActivity.kt

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import com.google.android.material.card.MaterialCardView
2424
import com.google.android.material.color.MaterialColors
2525
import kotlinx.coroutines.CoroutineScope
2626
import kotlinx.coroutines.Dispatchers
27+
import kotlinx.coroutines.async
28+
import kotlinx.coroutines.awaitAll
2729
import kotlinx.coroutines.launch
2830
import kotlinx.coroutines.withContext
2931
import org.akanework.checker.utils.CheckerUtils
@@ -43,6 +45,7 @@ class MainActivity : Activity() {
4345
private lateinit var headerCardFrame: MaterialCardView
4446

4547
private val abnormalitiesList = mutableListOf<String>()
48+
private val abnormalitiesAdapter = EntryAdapter(abnormalitiesList)
4649

4750
private fun changeTitleStatus(status: Int) {
4851
var titleString = getString(R.string.normal_title)
@@ -136,13 +139,17 @@ class MainActivity : Activity() {
136139
val widevineAlgoTextView = findViewById<TextView>(R.id.widevine_algo)
137140

138141
val connectivityRadioTextView = findViewById<TextView>(R.id.connectivity_radio)
139-
val connectivityGnssHalStatus = findViewById<TextView>(R.id.connectivity_gps)
142+
val connectivityGNSSHalStatus = findViewById<TextView>(R.id.connectivity_gps)
140143

141144
val mediaHdrTypeTextView = findViewById<TextView>(R.id.media_hdr_types)
142145
val mediaWideColorGamutTextView = findViewById<TextView>(R.id.media_wide_color_gamut)
143146

147+
val securitySELinuxStateTextView = findViewById<TextView>(R.id.security_selinux_state)
148+
144149
val abnormalitiesFrame = findViewById<MaterialCardView>(R.id.abnormal_frame)
145150
val abnormalitiesRecyclerView = findViewById<RecyclerView>(R.id.abnormal_recyclerview)
151+
abnormalitiesRecyclerView.layoutManager = LinearLayoutManager(this@MainActivity)
152+
abnormalitiesRecyclerView.adapter = abnormalitiesAdapter
146153

147154
// Set up basic info
148155
val basicAndroidVersion = Build.VERSION.RELEASE
@@ -189,14 +196,16 @@ class MainActivity : Activity() {
189196

190197
// Set up radio info
191198
val connectivityRadioVersion = Build.getRadioVersion().substringAfterLast(',')
192-
CoroutineScope(Dispatchers.Default).launch {
193-
val connectivityGnssVersionRawList = CheckerUtils.checkGnssHal()
194-
val connectivityGnssVersionList = connectivityGnssVersionRawList
199+
val connectivityGNSSQueryJob = CoroutineScope(Dispatchers.Default).async {
200+
val connectivityGNSSVersionRawList = CheckerUtils.checkGnssHal()
201+
val connectivityGNSSVersionList = connectivityGNSSVersionRawList
195202
.filter { it.contains("android.hardware.gnss") }
196-
.joinToString(separator = "\n") {
197-
it.substringBefore(":").substringAfterLast("? ").trim()
203+
.map {
204+
it.substringBefore(":").substringAfterLast("? ").substringAfterLast("Y ").trim()
198205
}
199-
if (connectivityGnssVersionRawList.isNotEmpty()) {
206+
.distinct()
207+
.joinToString(separator = "\n")
208+
if (connectivityGNSSVersionRawList.isNotEmpty()) {
200209
withContext(Dispatchers.Main) {
201210
val anim = AlphaAnimation(1.0f, 0.0f)
202211
anim.duration = 200
@@ -207,27 +216,18 @@ class MainActivity : Activity() {
207216
override fun onAnimationEnd(animation: Animation?) {}
208217
override fun onAnimationStart(animation: Animation?) {}
209218
override fun onAnimationRepeat(animation: Animation?) {
210-
connectivityGnssHalStatus.text =
211-
"${getString(R.string.connectivity_gnss)}\n$connectivityGnssVersionList"
219+
connectivityGNSSHalStatus.text =
220+
"${getString(R.string.connectivity_gnss)}\n$connectivityGNSSVersionList"
212221
}
213222
})
214223

215-
connectivityGnssHalStatus.startAnimation(anim)
224+
connectivityGNSSHalStatus.startAnimation(anim)
216225
}
217226
} else {
218227
withContext(Dispatchers.Main) {
219228
abnormalitiesList.add(getString(R.string.abnormalities_gnss_hal_broken))
220-
val abnormalitiesAdapter = EntryAdapter(abnormalitiesList)
221-
abnormalitiesRecyclerView.layoutManager = LinearLayoutManager(this@MainActivity)
222-
abnormalitiesRecyclerView.adapter = abnormalitiesAdapter
223-
abnormalitiesFrame.visibility = View.VISIBLE
224229
}
225230
}
226-
if (abnormalitiesList.isEmpty()) {
227-
changeTitleStatus(1)
228-
} else {
229-
changeTitleStatus(2)
230-
}
231231
}
232232
connectivityRadioTextView.text =
233233
"${getString(R.string.connectivity_radio)} - $connectivityRadioVersion"
@@ -261,6 +261,25 @@ class MainActivity : Activity() {
261261
mediaWideColorGamutTextView.text =
262262
"${getString(R.string.media_wide_color_gamut)} - $mediaIsDeviceColorGamut"
263263

264+
// Set up security info
265+
val securitySELinuxQueryJob = CoroutineScope(Dispatchers.Default).async {
266+
val securityIsSELinuxEnforcing = CheckerUtils.isSELinuxEnforcing()
267+
withContext(Dispatchers.Main) {
268+
securitySELinuxStateTextView.text = getString(R.string.security_selinux_state) + " - " +
269+
when (securityIsSELinuxEnforcing) {
270+
0 -> "Enforcing"
271+
1 -> {
272+
abnormalitiesList.add(getString(R.string.abnormalities_selinux_not_enforcing))
273+
"Permissive"
274+
}
275+
2 -> {
276+
"Invalid"
277+
}
278+
else -> throw IllegalArgumentException()
279+
}
280+
}
281+
}
282+
264283
// Get abnormalities
265284
val verifiedBootStat = SystemProperties.read("ro.boot.verifiedbootstate", "unknown")
266285
val isDrmPassing =
@@ -276,11 +295,19 @@ class MainActivity : Activity() {
276295
abnormalitiesList.add(getString(R.string.abnormalities_baseband_broken))
277296
}
278297

279-
if (abnormalitiesList.size != 0) {
280-
val abnormalitiesAdapter = EntryAdapter(abnormalitiesList)
281-
abnormalitiesRecyclerView.layoutManager = LinearLayoutManager(this)
282-
abnormalitiesRecyclerView.adapter = abnormalitiesAdapter
283-
abnormalitiesFrame.visibility = View.VISIBLE
298+
CoroutineScope(Dispatchers.Default).launch {
299+
awaitAll(connectivityGNSSQueryJob, securitySELinuxQueryJob)
300+
withContext(Dispatchers.Main) {
301+
if (abnormalitiesList.isEmpty()) {
302+
changeTitleStatus(1)
303+
} else {
304+
changeTitleStatus(2)
305+
}
306+
if (abnormalitiesList.size != 0) {
307+
abnormalitiesAdapter.notifyItemRangeInserted(0, abnormalitiesList.size)
308+
abnormalitiesFrame.visibility = View.VISIBLE
309+
}
310+
}
284311
}
285312
}
286313

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,56 @@
11
package org.akanework.checker.utils
22

3+
import android.util.Log
34
import java.io.BufferedReader
45
import java.io.InputStreamReader
56

67
object CheckerUtils {
78

8-
fun checkGnssHal(): MutableList<String> {
9+
private val commandCache = mutableMapOf<String, List<String>>()
10+
11+
private fun executeShellCommand(command: String): List<String> {
12+
// Check if the result is already cached
13+
if (commandCache.containsKey(command)) {
14+
return commandCache[command]!!
15+
}
16+
17+
val outputLines = mutableListOf<String>()
18+
919
try {
10-
val command = "lshal | grep gnss"
11-
val process = Runtime.getRuntime().exec(arrayOf("sh", "-c", command))
20+
val processBuilder = ProcessBuilder("sh", "-c", command)
21+
val process = processBuilder.start()
1222
val reader = BufferedReader(InputStreamReader(process.inputStream))
23+
val errorReader = BufferedReader(InputStreamReader(process.errorStream))
1324
var line: String?
1425

15-
val gnssList = mutableListOf<String>()
1626
while (reader.readLine().also { line = it } != null) {
17-
line?.let { gnssList.add(it) }
27+
line?.let { outputLines.add(it) }
1828
}
1929

20-
process.waitFor()
21-
return gnssList
30+
while (errorReader.readLine().also { line = it } != null) {
31+
// Handle errors if needed
32+
}
2233

34+
process.waitFor()
2335
} catch (e: Exception) {
2436
e.printStackTrace()
25-
return mutableListOf()
2637
}
38+
39+
// Cache the result for future use
40+
commandCache[command] = outputLines
41+
42+
return outputLines
2743
}
2844

45+
fun checkGnssHal(): List<String> {
46+
val command = "lshal | grep gnss"
47+
return executeShellCommand(command)
48+
}
49+
50+
fun isSELinuxEnforcing(): Int {
51+
val command = "lshal"
52+
val output = executeShellCommand(command)
53+
Log.d("TAG", output.toString())
54+
return if (output.joinToString().contains(" Y ")) 1 else 0
55+
}
2956
}

app/src/main/res/layout/main_content.xml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,45 @@
275275

276276
</com.google.android.material.card.MaterialCardView>
277277

278+
<com.google.android.material.card.MaterialCardView
279+
android:layout_width="match_parent"
280+
android:layout_height="wrap_content"
281+
android:layout_marginStart="12dp"
282+
android:layout_marginEnd="12dp"
283+
android:layout_marginBottom="22dp"
284+
app:cardCornerRadius="8dp">
285+
286+
<LinearLayout
287+
android:layout_width="match_parent"
288+
android:layout_height="wrap_content"
289+
android:orientation="vertical"
290+
android:paddingStart="18dp"
291+
android:paddingTop="18dp"
292+
android:paddingEnd="18dp"
293+
android:paddingBottom="24dp">
294+
295+
<TextView
296+
android:layout_width="wrap_content"
297+
android:layout_height="wrap_content"
298+
android:layout_marginBottom="12dp"
299+
android:text="@string/security"
300+
android:textColor="?attr/colorOnSurface"
301+
android:textFontWeight="600"
302+
android:textSize="20sp" />
303+
304+
<TextView
305+
android:id="@+id/security_selinux_state"
306+
android:layout_width="wrap_content"
307+
android:layout_height="wrap_content"
308+
android:textColor="?attr/colorOnSurface"
309+
android:textSize="16sp"
310+
android:textFontWeight="500"
311+
tools:text="@string/connectivity_radio" />
312+
313+
</LinearLayout>
314+
315+
</com.google.android.material.card.MaterialCardView>
316+
278317
<com.google.android.material.card.MaterialCardView
279318
android:layout_width="match_parent"
280319
android:layout_height="wrap_content"

app/src/main/res/values/strings.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,12 @@
2828
<string name="abnormalities_verified_boot_stat">Abnormalities found in Verified boot state.</string>
2929
<string name="abnormalities_baseband_broken">Baseband is broken.</string>
3030
<string name="abnormalities_gnss_hal_broken">GNSS Hal is broken.</string>
31+
<string name="abnormalities_selinux_not_enforcing">SELinux is not enforcing.</string>
3132
<string name="github">Open-sourced under GPL-3.0.\nCopyright © AkaneTan 2023</string>
3233
<string name="normal_title">No abnomilities found.</string>
3334
<string name="normal_summary">You\'re running a sane build.</string>
3435
<string name="notice_title">Abnormalities found.</string>
3536
<string name="notice_summary">Consider reconfiguring your device tree or ROM.</string>
37+
<string name="security">Security</string>
38+
<string name="security_selinux_state">SELinux state</string>
3639
</resources>

0 commit comments

Comments
 (0)