Add ci for manager and userspace (#2)

* kernel: move EXPECTED_* macro to Makefile

* manager: add sign configs

* tools: add check_v2

* CI: build manager

* CI: build userspace
This commit is contained in:
Ylarod 2022-12-15 12:22:43 +08:00 committed by GitHub
parent 6b84b7ed4d
commit 8e89b90b80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 271 additions and 4 deletions

40
.github/workflows/build-manager.yml vendored Normal file
View File

@ -0,0 +1,40 @@
name: Build Manager
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./manager
steps:
- uses: actions/checkout@v3
- name: set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
cache: gradle
- name: Extract keystore
if: ${{ ( github.event_name != 'pull_request' && github.ref == 'refs/heads/main' ) || github.ref_type == 'tag' }}
run: |
if [ ! -z "${{ secrets.KEY_STORE }}" ]; then
echo KEYSTORE_PASSWORD='${{ secrets.KEYSTORE_PASSWORD }}' >> sign.properties
echo KEY_ALIAS='${{ secrets.KEY_ALIAS }}' >> sign.properties
echo KEY_PASSWORD='${{ secrets.KEY_PASSWORD }}' >> sign.properties
echo KEYSTORE_FILE='../key.jks' >> sign.properties
echo ${{ secrets.KEYSTORE }} | base64 --decode > key.jks
fi
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
- name: Upload build artifact
uses: actions/upload-artifact@v2
with:
name: manager
path: manager/app/build/outputs/apk/release/*.apk

24
.github/workflows/build-userspace.yml vendored Normal file
View File

@ -0,0 +1,24 @@
name: Build Userspace
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: nttld/setup-ndk@v1
with:
ndk-version: r25b
local-cache: true
- name: Build with NDK
working-directory: ./userspace
run: ndk-build
- name: Upload a Build Artifact
uses: actions/upload-artifact@v3
with:
name: su
path: ./userspace/libs

View File

@ -6,4 +6,8 @@ obj-y += sucompat.o
obj-y += selinux/
EXPECTED_SIZE := 0x033b
EXPECTED_HASH := 0xb0b91415
ccflags-y += -DEXPECTED_SIZE=$(EXPECTED_SIZE)
ccflags-y += -DEXPECTED_HASH=$(EXPECTED_HASH)
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat

View File

@ -112,9 +112,6 @@ clean:
return sign;
}
#define EXPECTED_SIZE 0x033b
#define EXPECTED_HASH 0xb0b91415
int is_manager_apk(char* path) {
return check_v2_signature(path, EXPECTED_SIZE, EXPECTED_HASH);
}

2
manager/.gitignore vendored
View File

@ -13,3 +13,5 @@
.externalNativeBuild
.cxx
local.properties
sign.properties
key.jks

View File

@ -7,6 +7,10 @@ android {
namespace 'me.weishu.kernelsu'
compileSdk 33
signingConfigs {
sign
}
defaultConfig {
applicationId "me.weishu.kernelsu"
minSdk 26
@ -29,6 +33,7 @@ android {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.sign
}
}
compileOptions {
@ -83,4 +88,6 @@ dependencies {
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_ui_version"
debugImplementation "androidx.compose.ui:ui-tooling:$compose_ui_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_ui_version"
}
}
apply from: rootProject.file('sign.gradle')

View File

@ -0,0 +1,4 @@
KEYSTORE_FILE=
KEYSTORE_PASSWORD=
KEY_ALIAS=
KEY_PASSWORD=

16
manager/sign.gradle Normal file
View File

@ -0,0 +1,16 @@
def ksFile = rootProject.file('sign.properties')
def props = new Properties()
if (ksFile.canRead()) {
props.load(new FileInputStream(ksFile))
if (props != null) {
android.signingConfigs.sign.storeFile file(props['KEYSTORE_FILE'])
android.signingConfigs.sign.storePassword props['KEYSTORE_PASSWORD']
android.signingConfigs.sign.keyAlias props['KEY_ALIAS']
android.signingConfigs.sign.keyPassword props['KEY_PASSWORD']
}
} else {
android.signingConfigs.sign.storeFile = android.signingConfigs.debug.storeFile
android.signingConfigs.sign.storePassword = android.signingConfigs.debug.storePassword
android.signingConfigs.sign.keyAlias = android.signingConfigs.debug.keyAlias
android.signingConfigs.sign.keyPassword = android.signingConfigs.debug.keyPassword
}

173
tools/check_v2.c Normal file
View File

@ -0,0 +1,173 @@
//
// Created by Thom on 2019/3/8.
//
// Credits: https://github.com/brevent/genuine/blob/master/src/main/jni/apk-sign-v2.c
#include <fcntl.h>
#include <unistd.h>
#include <stdbool.h>
#define MAIN
#ifdef MAIN
#include <stdio.h>
#else
#include "common.h"
#include "openat.h"
#endif
static bool isApkSigBlock42(const char *buffer) {
// APK Sig Block 42
return *buffer == 'A'
&& *++buffer == 'P'
&& *++buffer == 'K'
&& *++buffer == ' '
&& *++buffer == 'S'
&& *++buffer == 'i'
&& *++buffer == 'g'
&& *++buffer == ' '
&& *++buffer == 'B'
&& *++buffer == 'l'
&& *++buffer == 'o'
&& *++buffer == 'c'
&& *++buffer == 'k'
&& *++buffer == ' '
&& *++buffer == '4'
&& *++buffer == '2';
}
int checkSignature(const char *path) {
unsigned char buffer[0x11] = {0};
uint32_t size4;
uint64_t size8, size_of_block;
#ifdef DEBUG
LOGI("check signature for %s", path);
#endif
int sign = -1;
int fd = (int) openat(AT_FDCWD, path, O_RDONLY);
#ifdef DEBUG_OPENAT
LOGI("openat %s returns %d", path, fd);
#endif
if (fd < 0) {
return sign;
}
sign = 1;
// https://en.wikipedia.org/wiki/Zip_(file_format)#End_of_central_directory_record_(EOCD)
for (int i = 0;; ++i) {
unsigned short n;
lseek(fd, -i - 2, SEEK_END);
read(fd, &n, 2);
if (n == i) {
lseek(fd, -22, SEEK_CUR);
read(fd, &size4, 4);
if ((size4 ^ 0xcafebabeu) == 0xccfbf1eeu) {
#ifdef MAIN
if (i > 0) {
printf("warning: comment length is %d\n", i);
}
#endif
break;
}
}
if (i == 0xffff) {
#ifdef MAIN
printf("error: cannot find eocd\n");
#endif
goto clean;
}
}
lseek(fd, 12, SEEK_CUR);
// offset
read(fd, &size4, 0x4);
lseek(fd, (off_t) (size4 - 0x18), SEEK_SET);
read(fd, &size8, 0x8);
read(fd, buffer, 0x10);
if (!isApkSigBlock42((char *) buffer)) {
goto clean;
}
lseek(fd, (off_t) (size4 - (size8 + 0x8)), SEEK_SET);
read(fd, &size_of_block, 0x8);
if (size_of_block != size8) {
goto clean;
}
for (;;) {
uint32_t id;
uint32_t offset;
read(fd, &size8, 0x8); // sequence length
if (size8 == size_of_block) {
break;
}
read(fd, &id, 0x4); // id
offset = 4;
#ifdef MAIN
// printf("id: 0x%08x\n", id);
#endif
if ((id ^ 0xdeadbeefu) == 0xafa439f5u || (id ^ 0xdeadbeefu) == 0x2efed62f) {
read(fd, &size4, 0x4); // signer-sequence length
read(fd, &size4, 0x4); // signer length
read(fd, &size4, 0x4); // signed data length
offset += 0x4 * 3;
read(fd, &size4, 0x4); // digests-sequence length
lseek(fd, (off_t) (size4), SEEK_CUR);// skip digests
offset += 0x4 + size4;
read(fd, &size4, 0x4); // certificates length
read(fd, &size4, 0x4); // certificate length
offset += 0x4 * 2;
#ifdef MAIN
int hash = 1;
signed char c;
for (unsigned i = 0; i < size4; ++i) {
read(fd, &c, 0x1);
hash = 31 * hash + c;
}
offset += size4;
// printf(" size: 0x%04x, hash: 0x%08x\n", size4, ((unsigned) hash) ^ 0x14131211u);
printf("0x%04x 0x%08x\n", size4, ((unsigned) hash) ^ 0x14131211u);
#else
#if defined(GENUINE_SIZE) && defined(GENUINE_HASH)
if (size4 == GENUINE_SIZE) {
int hash = 1;
signed char c;
for (unsigned i = 0; i < size4; ++i) {
read(fd, &c, 0x1);
hash = 31 * hash + c;
}
offset += size4;
if ((((unsigned) hash) ^ 0x14131211u) == GENUINE_HASH) {
sign = 0;
break;
}
}
#else
sign = 0;
break;
#endif
#endif
}
lseek(fd, (off_t) (size8 - offset), SEEK_CUR);
}
clean:
close(fd);
return sign;
}
#ifdef MAIN
int main(int argc, char **argv) {
if (argc > 1) {
checkSignature(argv[1]);
}
}
#endif