cpio: fix special perms bug

also add dispol to decompile sepolicy binary file
pull/66/head
cfig 4 years ago
parent 71fcc9b26e
commit e6ed2d7b96
No known key found for this signature in database
GPG Key ID: B104C307F0FDABB7

@ -55,12 +55,13 @@ Well done you did it! The last step is to star this repo :smile
## Supported ROM image types
| Image Type | file names | |
| Image Type | file names | platforms |
| --------------- | ----------------------------------- | ---- |
| boot images | boot.img, vendor_boot.img | |
| recovery images | recovery.img, recovery-two-step.img | |
| vbmeta images | vbmeta.img, vbmeta_system.img etc. | |
| dtbo images | dtbo.img | |
| boot images | boot.img, vendor_boot.img | all |
| recovery images | recovery.img, recovery-two-step.img | all |
| vbmeta images | vbmeta.img, vbmeta_system.img etc. | all |
| dtbo images | dtbo.img | linux & mac |
| sparse images | system.img, vendor.img, product.img etc. | linux & mac |
Please note that the boot.img MUST follows AOSP verified boot flow, either [Boot image signature](https://source.android.com/security/verifiedboot/verified-boot#signature_format) in VBoot 1.0 or [AVB HASH footer](https://android.googlesource.com/platform/external/avb/+/master/README.md#The-VBMeta-struct) (a.k.a. AVB) in VBoot 2.0.

@ -0,0 +1,24 @@
.PHONY: all checkpolicy libsepol prepare
nothing:
@echo "Nothing to do"
checkpolicy: export CFLAGS := -g -Wall -Werror -Wshadow -pipe -fno-strict-aliasing -I$(CURDIR)/libsepol-3.2/include
checkpolicy: export LIBSEPOLA := $(CURDIR)/libsepol-3.2/src/libsepol.a
checkpolicy: export LDLIBS_LIBSEPOLA := -l:libsepol.a -L$(CURDIR)/libsepol-3.2/src
checkpolicy: libsepol
make -C checkpolicy-3.2 -j
cp checkpolicy-3.2/test/dispol .
libsepol:
make -C libsepol-3.2 -j
prepare:
rm -fr libsepol-3.2 checkpolicy-3.2
wget https://github.com/SELinuxProject/selinux/releases/download/3.2/libsepol-3.2.tar.gz
wget https://github.com/SELinuxProject/selinux/releases/download/3.2/checkpolicy-3.2.tar.gz
tar xaf checkpolicy-3.2.tar.gz
tar xaf libsepol-3.2.tar.gz
all: checkpolicy libsepol prepare
# vim:ft=make
#

@ -0,0 +1,7 @@
# dispol
decompile binary selinux policy file
Android sepolicy file is `/sys/fs/selinux/policy`
```
make all
./dispol <policy_file>
```

@ -484,7 +484,7 @@ class Avb {
}
}
if (-1 == seq) {
log.warn("main vbmeta doesn't have $partitionName hashDescriptor, skip")
log.warn("main vbmeta doesn't have $partitionName hashDescriptor, won't update vbmeta.img")
} else {
val hd = newHashDesc.auxBlob!!.hashDescriptors.get(0).apply { this.sequence = seq }
this.auxBlob!!.hashDescriptors.add(hd)

@ -180,6 +180,7 @@ class AndroidCpio {
companion object {
private val log = LoggerFactory.getLogger(AndroidCpio::class.java)
private val PERM_MASK = java.lang.Long.valueOf("777", 8)
fun decompressCPIO(cpioFile: String, outDir: String, fileList: String? = null) {
run { //clean up
if (File(outDir).exists()) {
@ -222,7 +223,7 @@ class AndroidCpio {
} else {
Files.setPosixFilePermissions(
Paths.get(outEntryName),
Helper.modeToPermissions((entry.mode and 0xfff).toInt())
Helper.modeToPermissions((entry.mode and PERM_MASK).toInt())
)
}
}
@ -232,7 +233,7 @@ class AndroidCpio {
if (!EnvironmentVerifier().isWindows) {
Files.setPosixFilePermissions(
Paths.get(outEntryName),
Helper.modeToPermissions((entry.mode and 0xfff).toInt())
Helper.modeToPermissions((entry.mode and PERM_MASK).toInt())
)
} else {
//Windows

@ -29,7 +29,7 @@ class KernelExtractor {
it.addArgument("--output-version")
it.addArgument(kernelVersionFile)
}
DefaultExecutor().let {
DefaultExecutor().let { it ->
it.workingDirectory = workDir ?: File("../")
try {
it.execute(cmd)
@ -41,6 +41,11 @@ class KernelExtractor {
ret.add(kernelVersionFile)
ret.add(kernelConfigFile)
} catch (e: org.apache.commons.exec.ExecuteException) {
listOf(kernelConfigFile, kernelVersionFile).forEach { fn ->
File(fn).let { f ->
if (f.exists()) f.delete()
}
}
log.warn("can not parse kernel info")
}
}

@ -0,0 +1,97 @@
import org.junit.Test
import java.math.BigInteger
import java.util.concurrent.Callable
import java.util.regex.Matcher
import java.util.regex.Pattern
class CVEtest {
private val printkFormat = """
0xffffff8008cce7ee : "Rescheduling interrupts"
0xffffff8008cce806 : "Function call interrupts"
0xffffff8008cce81f : "CPU stop interrupts"
0xffffff8008cce833 : "CPU stop (for crash dump) interrupts"
0xffffff8008cce858 : "Timer broadcast interrupts"
0xffffff8008cce873 : "IRQ work interrupts"
0xffffff8008cce887 : "CPU wake-up interrupts"
0xffffff8009070140 : "rcu_sched"
0xffffff8009070500 : "rcu_bh"
0xffffff8009070920 : "rcu_preempt"
"""
private val printkFormatPatch = """
0x0 : "Rescheduling interrupts"
0x0 : "Function call interrupts"
0x0 : "CPU stop interrupts"
0x0 : "Timer broadcast interrupts"
0x0 : "IRQ work interrupts"
0x0 : "CPU wake-up interrupts"
0x0 : "CPU backtrace"
0x0 : "rcu_bh"
0x0 : "rcu_preempt"
0x0 : "rcu_sched"
""".trimIndent()
@Test
fun testPocCVE_2017_0630() {
val printkFormats: String = printkFormatPatch
val pointerStrings = printkFormats.split("\n").toTypedArray()
assertNotKernelPointer(object : Callable<String?> {
var index = 0
override fun call(): String? {
while (index < pointerStrings.size) {
val line = pointerStrings[index]
val pattern = "0x"
val startIndex = line.indexOf(pattern)
if (startIndex == -1) {
index++
continue
}
return line.substring(startIndex + pattern.length)
}
return null
}
}, null)
}
fun assertNotKernelPointer(getPtrFunction: Callable<String?>, deviceToReboot: String?) {
var ptr: String? = null
for (i in 0..3) { // ~0.4% chance of false positive
ptr = getPtrFunction.call()
if (ptr == null) {
return
}
if (!isKptr(ptr)) {
// quit early because the ptr is likely hashed or zeroed.
return
}
}
throw IllegalArgumentException("\"$ptr\" is an exposed kernel pointer.")
}
private fun isKptr(ptr: String): Boolean {
val RADIX_HEX = 16
val m: Matcher = Pattern.compile("[0-9a-fA-F]*").matcher(ptr)
if (!m.find() || m.start() != 0) {
// ptr string is malformed
return false
}
val length: Int = m.end()
if (length == 8) {
// 32-bit pointer
val address = BigInteger(ptr.substring(0, length), RADIX_HEX)
// 32-bit kernel memory range: 0xC0000000 -> 0xffffffff
// 0x3fffffff bytes = 1GB / 0xffffffff = 4 GB
// 1 in 4 collision for hashed pointers
return address >= BigInteger("C0000000", RADIX_HEX)
} else if (length == 16) {
// 64-bit pointer
val address = BigInteger(ptr.substring(0, length), RADIX_HEX)
// 64-bit kernel memory range: 0x8000000000000000 -> 0xffffffffffffffff
// 48-bit implementation: 0xffff800000000000; 1 in 131,072 collision
// 56-bit implementation: 0xff80000000000000; 1 in 512 collision
// 64-bit implementation: 0x8000000000000000; 1 in 2 collision
return address >= BigInteger("ff80000000000000", RADIX_HEX)
}
return false
}
}

@ -65,6 +65,9 @@ place 'ramdisk.img.gz' in directory, delete "root/", program will use it as preb
## cpio
decompress cpio with commandline `cpio -idmv -F <file>`
Some file system(also java) doesn't support special file permissions, https://docs.oracle.com/cd/E19455-01/805-7229/secfiles-69/index.html
So we have to save the file perms in `build/unzip_boot/ramdisk_filelist.txt`, and use it when doing 'pack'.
### cpio on windows
* got `java.nio.file.FileSystemException` and says "A required privilege is not held by the client"
```
@ -87,4 +90,3 @@ out/host/linux-x86/bin/avbtool add_hash_footer --image out/target/product/vsoc_a
```
As it's only used for GKI verification, I don't want to spend too much time on any special steps in 'gradle pack' flow, as long as DUT can boot up properly.

@ -93,7 +93,7 @@ class Helper {
}
fun extractFile(s: Slice) {
return extractFile(s.srcFile, s.dumpFile, s.offset.toLong(), s.length)
return extractFile(s.srcFile, s.dumpFile, s.offset.toLong(), s.length)
}
fun extractFile(fileName: String, outImgName: String, offset: Long, length: Int) {
@ -320,12 +320,10 @@ class Helper {
fun modeToPermissions(inMode: Int): Set<PosixFilePermission> {
var mode = inMode
val PERMISSIONS_MASK = 4095
// setgid/setuid/sticky are not supported.
val MAX_SUPPORTED_MODE = 511
mode = mode and PERMISSIONS_MASK
if (mode and MAX_SUPPORTED_MODE != mode) {
throw IOException("Invalid mode: $mode")
mode = mode and Integer.valueOf("7777", 8) //trim to xxxx
val maxSupportedMode = Integer.valueOf("777", 8) //setgid/setuid/sticky are not supported
if (mode and maxSupportedMode != mode) {
throw IOException("Invalid mode(oct): ${Integer.toOctalString(mode)}")
}
val allPermissions = PosixFilePermission.values()
val result: MutableSet<PosixFilePermission> = EnumSet.noneOf(PosixFilePermission::class.java)

Loading…
Cancel
Save