Compare commits

...

13 Commits

Author SHA1 Message Date
topjohnwu
0495468d02 Release new canary build 2024-07-24 23:13:21 -07:00
topjohnwu
300a2a242c Add release script 2024-07-24 23:10:57 -07:00
topjohnwu
33aebb5976 Stop embedding executables 2024-07-24 22:49:48 -07:00
pndwal
b3d6809c0b Update README.MD
Remove redundant Canary changelog link
2024-07-24 19:04:50 -07:00
LoveSy
461f7e9f89 Use metadata even if it is f2fs 2024-07-24 19:02:35 -07:00
LoveSy
9cc50b20d8 Correctly handle comments in sepolicy.rule 2024-07-24 19:02:25 -07:00
LoveSy
f488e9df8f Fix sepolicy rule path 2024-07-24 19:02:12 -07:00
LoveSy
0dc596e206 Update Chinese translation 2024-07-24 19:01:59 -07:00
topjohnwu
c3bf03190b Use K2 in kapt 2024-07-24 17:06:41 -07:00
topjohnwu
021ae891a9 Update dependencies 2024-07-24 16:53:15 -07:00
topjohnwu
9c03514eb1 Create :app:clean task 2024-07-24 16:46:47 -07:00
topjohnwu
eb74b266e1 Do not modify args
Close #8242
2024-07-24 16:37:22 -07:00
topjohnwu
80eb6ff25a Update README 2024-07-23 21:37:04 -07:00
22 changed files with 409 additions and 199 deletions

View File

@@ -22,8 +22,7 @@ Click the icon below to download Magisk apk.
[![](https://img.shields.io/badge/Magisk-v27.0-blue)](https://github.com/topjohnwu/Magisk/releases/tag/v27.0)
[![](https://img.shields.io/badge/Magisk%20Beta-v27.0-blue)](https://github.com/topjohnwu/Magisk/releases/tag/v27.0)
[![](https://img.shields.io/badge/Magisk-Canary-red)](https://raw.githubusercontent.com/topjohnwu/magisk-files/canary/app-release.apk)
[![](https://img.shields.io/badge/Magisk-Debug-red)](https://raw.githubusercontent.com/topjohnwu/magisk-files/canary/app-debug.apk)
[![](https://img.shields.io/badge/Magisk-Canary-red)](https://github.com/topjohnwu/Magisk/releases/tag/canary-27006)
## Useful Links
@@ -31,8 +30,6 @@ Click the icon below to download Magisk apk.
- [Building and Development](https://topjohnwu.github.io/Magisk/build.html)
- [Magisk Documentation](https://topjohnwu.github.io/Magisk/)
- [Zygisk module sample](https://github.com/topjohnwu/zygisk-module-sample)
- [Canary channel changelog](https://github.com/topjohnwu/magisk-files/blob/canary/notes.md)
## Bug Reports

View File

@@ -59,8 +59,8 @@ dependencies {
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("androidx.recyclerview:recyclerview:1.3.2")
implementation("androidx.transition:transition:1.5.0")
implementation("androidx.fragment:fragment-ktx:1.8.1")
implementation("androidx.transition:transition:1.5.1")
implementation("androidx.fragment:fragment-ktx:1.8.2")
implementation("androidx.appcompat:appcompat:1.7.0")
implementation("com.google.android.material:material:1.12.0")

5
app/build.gradle.kts Normal file
View File

@@ -0,0 +1,5 @@
tasks.register("clean") {
subprojects.forEach {
dependsOn(":app:${it.name}:clean")
}
}

View File

@@ -61,8 +61,8 @@ dependencies {
implementation("androidx.core:core-splashscreen:1.0.1")
implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.activity:activity:1.9.0")
implementation("androidx.collection:collection-ktx:1.4.1")
implementation("androidx.activity:activity:1.9.1")
implementation("androidx.collection:collection-ktx:1.4.2")
implementation("androidx.profileinstaller:profileinstaller:1.3.1")
implementation("androidx.lifecycle:lifecycle-process:2.8.3")
implementation("androidx.lifecycle:lifecycle-process:2.8.4")
}

View File

@@ -176,6 +176,8 @@
<string name="setting_add_shortcut_summary">在隐藏后难以识别名称和图标的情况下,添加快捷方式到桌面</string>
<string name="settings_doh_title">安全 DNSDoH</string>
<string name="settings_doh_description">解决某些地区的 DNS 污染问题</string>
<string name="settings_random_name_title">随机文件名</string>
<string name="settings_random_name_description">随机修补镜像和 tar 文件的文件名以防止检测</string>
<string name="multiuser_mode">多用户模式</string>
<string name="settings_owner_only">仅设备所有者</string>

View File

@@ -6,7 +6,7 @@ plugins {
lsparanoid {
seed = if (RAND_SEED != 0) RAND_SEED else null
includeDependencies = true
global = true
classFilter = { true }
}
android {

215
build.py
View File

@@ -81,9 +81,9 @@ triples = [
"x86_64-linux-android",
"riscv64-linux-android",
]
default_targets = ["magisk", "magiskinit", "magiskboot", "magiskpolicy"]
support_targets = default_targets + ["resetprop"]
rust_targets = ["magisk", "magiskinit", "magiskboot", "magiskpolicy"]
default_targets = {"magisk", "magiskinit", "magiskboot", "magiskpolicy"}
support_targets = default_targets | {"resetprop"}
rust_targets = {"magisk", "magiskinit", "magiskboot", "magiskpolicy"}
ndk_root = sdk_path / "ndk"
ndk_path = ndk_root / "magisk"
@@ -243,13 +243,54 @@ def run_ndk_build(args, flags):
if proc.returncode != 0:
error("Build binary failed!")
os.chdir("..")
for arch in archs:
for tgt in support_targets + ["libinit-ld.so"]:
source = Path("native", "libs", arch, tgt)
target = Path("native", "out", arch, tgt)
arch_dir = Path("native", "libs", arch)
out_dir = Path("native", "out", arch)
for source in arch_dir.iterdir():
target = out_dir / source.name
mv(source, target)
def build_cpp_src(args, targets: set):
dump_flag_header()
flags = ""
clean = False
if "magisk" in targets:
flags += " B_MAGISK=1"
clean = True
if "magiskpolicy" in targets:
flags += " B_POLICY=1"
clean = True
if "magiskinit" in targets:
flags += " B_PRELOAD=1"
if "resetprop" in targets:
flags += " B_PROP=1"
if flags:
run_ndk_build(args, flags)
flags = ""
if "magiskinit" in targets:
flags += " B_INIT=1"
if "magiskboot" in targets:
flags += " B_BOOT=1"
if flags:
flags += " B_CRT0=1"
run_ndk_build(args, flags)
if clean:
clean_elf()
def run_cargo(cmds):
env = os.environ.copy()
env["PATH"] = f'{rust_bin}{os.pathsep}{env["PATH"]}'
@@ -258,17 +299,19 @@ def run_cargo(cmds):
return execv([cargo, *cmds], env)
def run_cargo_build(args):
def build_rust_src(args, targets: set):
targets = targets.copy()
if "resetprop" in targets:
targets.add("magisk")
targets = targets & rust_targets
if not targets:
return
os.chdir(Path("native", "src"))
native_out = Path("..", "out")
native_out.mkdir(mode=0o755, exist_ok=True)
targets = set(args.target) & set(rust_targets)
if "resetprop" in args.target:
targets.add("magisk")
if len(targets) == 0:
return
# Start building the actual build commands
cmds = ["build", "-p", ""]
rust_out = "debug"
@@ -289,8 +332,8 @@ def run_cargo_build(args):
)
cmds[-1] = rust_triple
for target in targets:
cmds[2] = target
for tgt in targets:
cmds[2] = tgt
proc = run_cargo(cmds)
if proc.returncode != 0:
error("Build binary failed!")
@@ -302,6 +345,8 @@ def run_cargo_build(args):
target = arch_out / f"lib{tgt}-rs.a"
mv(source, target)
os.chdir(Path("..", ".."))
def run_cargo_cmd(args):
global STDOUT
@@ -324,25 +369,6 @@ def write_if_diff(file_name: Path, text: str):
f.write(text)
def binary_dump(src, var_name, compressor=xz):
out_str = f"constexpr unsigned char {var_name}[] = {{"
for i, c in enumerate(compressor(src.read())):
if i % 16 == 0:
out_str += "\n"
out_str += f"0x{c:02X},"
out_str += "\n};\n"
return out_str
def dump_bin_header(args):
native_gen_path.mkdir(mode=0o755, parents=True, exist_ok=True)
for arch in archs:
preload = Path("native", "out", arch, "libinit-ld.so")
with open(preload, "rb") as src:
text = binary_dump(src, "init_ld_xz")
write_if_diff(Path(native_gen_path, f"{arch}_binaries.h"), text)
def dump_flag_header():
flag_txt = textwrap.dedent(
"""\
@@ -369,65 +395,17 @@ def build_binary(args):
except:
error('Unmatched NDK. Please install/upgrade NDK with "build.py ndk"')
if "target" not in vars(args):
vars(args)["target"] = []
if args.target:
args.target = set(args.target) & set(support_targets)
if not args.target:
return
if "targets" not in vars(args) or not args.targets:
targets = default_targets
else:
args.target = default_targets
targets = set(args.targets) & support_targets
if not targets:
return
header("* Building binaries: " + " ".join(args.target))
header("* Building binaries: " + " ".join(targets))
os.chdir(Path("native", "src"))
run_cargo_build(args)
os.chdir(Path("..", ".."))
dump_flag_header()
flag = ""
clean = False
if "magisk" in args.target:
flag += " B_MAGISK=1"
clean = True
if "magiskpolicy" in args.target:
flag += " B_POLICY=1"
clean = True
if "magiskinit" in args.target:
flag += " B_PRELOAD=1"
if "resetprop" in args.target:
flag += " B_PROP=1"
if flag:
run_ndk_build(args, flag)
flag = ""
if "magiskinit" in args.target:
# magiskinit embeds preload.so
dump_bin_header(args)
flag += " B_INIT=1"
if "magiskboot" in args.target:
flag += " B_BOOT=1"
if flag:
flag += " B_CRT0=1"
run_ndk_build(args, flag)
if clean:
clean_elf()
# BusyBox is built with different API level
if "busybox" in args.target:
run_ndk_build(args, "B_BB=1")
build_rust_src(args, targets)
build_cpp_src(args, targets)
def find_jdk():
@@ -513,21 +491,21 @@ def build_stub(args):
def cleanup(args):
support_targets = {"native", "cpp", "rust", "java"}
if args.target:
args.target = set(args.target) & support_targets
if "native" in args.target:
args.target.add("cpp")
args.target.add("rust")
if args.targets:
targets = set(args.targets) & support_targets
if "native" in targets:
targets.add("cpp")
targets.add("rust")
else:
args.target = support_targets
targets = support_targets
if "cpp" in args.target:
if "cpp" in targets:
header("* Cleaning C++")
rm_rf(Path("native", "libs"))
rm_rf(Path("native", "obj"))
rm_rf(Path("native", "out"))
if "rust" in args.target:
if "rust" in targets:
header("* Cleaning Rust")
rm_rf(Path("native", "src", "target"))
rm(Path("native", "src", "boot", "proto", "mod.rs"))
@@ -535,18 +513,9 @@ def cleanup(args):
for rs_gen in glob.glob("native/**/*-rs.*pp", recursive=True):
rm(rs_gen)
if "java" in args.target:
if "java" in targets:
header("* Cleaning java")
execv(
[
gradlew,
":app:apk:clean",
":app:core:clean",
":app:shared:clean",
":app:stub:clean",
],
env=find_jdk(),
)
execv([gradlew, ":app:clean"], env=find_jdk())
def setup_ndk(args):
@@ -611,22 +580,22 @@ def setup_avd(args):
def patch_avd_file(args):
if not args.skip:
args.release = False
build_all(args)
args.target = Path(args.target)
src_file = f"/data/local/tmp/{args.target.name}"
out_file = f"{src_file}.magisk"
input = Path(args.image)
if args.output:
args.output = Path(args.output)
output = Path(args.output)
else:
args.output = args.target.parent / f"{args.target.name}.magisk"
output = input.parent / f"{input.name}.magisk"
header(f"* Patching {args.target.name}")
src_file = f"/data/local/tmp/{input.name}"
out_file = f"{src_file}.magisk"
header(f"* Patching {input.name}")
push_files(args, Path("scripts", "avd_patch.sh"))
proc = execv([adb_path, "push", args.target, "/data/local/tmp"])
proc = execv([adb_path, "push", input, "/data/local/tmp"])
if proc.returncode != 0:
error("adb push failed!")
@@ -634,11 +603,11 @@ def patch_avd_file(args):
if proc.returncode != 0:
error("avd_patch.sh failed!")
proc = execv([adb_path, "pull", out_file, args.output])
proc = execv([adb_path, "pull", out_file, output])
if proc.returncode != 0:
error("adb pull failed!")
header(f"Output: {args.output}")
header(f"Output: {output}")
def build_all(args):
@@ -693,7 +662,7 @@ all_parser.set_defaults(func=build_all)
binary_parser = subparsers.add_parser("binary", help="build binaries")
binary_parser.add_argument(
"target",
"targets",
nargs="*",
help=f"{', '.join(support_targets)}, \
or empty for defaults ({', '.join(default_targets)})",
@@ -723,7 +692,7 @@ avd_parser.set_defaults(func=setup_avd)
avd_patch_parser = subparsers.add_parser(
"avd_patch", help="patch AVD ramdisk.img or init_boot.img"
)
avd_patch_parser.add_argument("target", help="path to ramdisk.img or init_boot.img")
avd_patch_parser.add_argument("image", help="path to ramdisk.img or init_boot.img")
avd_patch_parser.add_argument("output", help="optional output file name", nargs="?")
avd_patch_parser.add_argument(
"-s", "--skip", action="store_true", help="skip building binaries and the app"
@@ -732,7 +701,7 @@ avd_patch_parser.set_defaults(func=patch_avd_file)
clean_parser = subparsers.add_parser("clean", help="cleanup")
clean_parser.add_argument(
"target", nargs="*", help="native, cpp, rust, java, or empty to clean all"
"targets", nargs="*", help="native, cpp, rust, java, or empty to clean all"
)
clean_parser.set_defaults(func=cleanup)

View File

@@ -29,6 +29,6 @@ dependencies {
implementation("com.android.tools.build:gradle:8.5.1")
implementation("com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:2.0.0-1.0.23")
implementation("androidx.navigation:navigation-safe-args-gradle-plugin:2.7.7")
implementation("org.lsposed.lsparanoid:gradle-plugin:0.5.2")
implementation("org.lsposed.lsparanoid:gradle-plugin:0.6.0")
implementation("org.eclipse.jgit:org.eclipse.jgit:6.10.0.202406032230-r")
}

View File

@@ -126,13 +126,13 @@ fun Project.setupCoreLib() {
for (abi in arrayOf("armeabi-v7a", "x86", "arm64-v8a", "x86_64", "riscv64")) {
into(abi) {
from(rootProject.file("native/out/$abi")) {
include("magiskboot", "magiskinit", "magiskpolicy", "magisk")
rename { "lib$it.so" }
include("magiskboot", "magiskinit", "magiskpolicy", "magisk", "libinit-ld.so")
rename { if (it.endsWith(".so")) it else "lib$it.so" }
}
}
}
onlyIf {
if (inputs.sourceFiles.files.size != 20)
if (inputs.sourceFiles.files.size != 25)
throw StopExecutionException("Please build binaries first! (./build.py binary)")
true
}

View File

@@ -20,6 +20,9 @@ org.gradle.parallel=true
# Enable build cache
org.gradle.caching=true
# Use K2 in kapt
kapt.use.k2=true
# Android
android.useAndroidX=true
android.injected.testOnly=false
@@ -27,5 +30,5 @@ android.nonFinalResIds=false
# Magisk
magisk.stubVersion=40
magisk.versionCode=27005
magisk.versionCode=27006
magisk.ondkVersion=r27.2

View File

@@ -7,7 +7,7 @@ LOCAL_MODULE := libbase
LOCAL_C_INCLUDES := \
src/include \
$(LOCAL_PATH)/include \
$(LOCAL_PATH)/../external/cxx-rs/include \
src/external/cxx-rs/include \
out/generated
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
LOCAL_EXPORT_STATIC_LIBRARIES := libcxx

View File

@@ -1,13 +0,0 @@
#if defined(__arm__)
#include <armeabi-v7a_binaries.h>
#elif defined(__aarch64__)
#include <arm64-v8a_binaries.h>
#elif defined(__i386__)
#include <x86_binaries.h>
#elif defined(__x86_64__)
#include <x86_64_binaries.h>
#elif defined(__riscv)
#include <riscv64_binaries.h>
#else
#error Unsupported ABI
#endif

View File

@@ -201,12 +201,16 @@ pub fn find_preinit_device() -> String {
let (_, preinit_info, _) = matched_info.select_nth_unstable_by(
0,
|(ap, MountInfo { fs_type: at, .. }), (bp, MountInfo { fs_type: bt, .. })| match (
ap,
bp,
at.as_str() == "ext4",
bt.as_str() == "ext4",
) {
// take ext4 over others (f2fs) because f2fs has a kernel bug that causes kernel panic
(true, false) => Less,
(false, true) => Greater,
// metadata is not affected by f2fs kernel bug
(PartId::Metadata, _, _, true) | (_, PartId::Metadata, true, _) => ap.cmp(bp),
// otherwise, take ext4 f2fs because f2fs has a kernel bug that causes kernel panic
(_, _, true, false) => Less,
(_, _, false, true) => Greater,
// if both has the same fs type, compare the mount point
_ => ap.cmp(bp),
},

View File

@@ -6,7 +6,6 @@
#include <xz.h>
#include <base.hpp>
#include <embed.hpp>
#include "init.hpp"

View File

@@ -189,6 +189,7 @@ static void magic_mount(const string &sdir, const string &ddir = "") {
static void extract_files(bool sbin) {
const char *magisk_xz = sbin ? "/sbin/magisk.xz" : "magisk.xz";
const char *stub_xz = sbin ? "/sbin/stub.xz" : "stub.xz";
const char *init_ld_xz = sbin ? "/sbin/init-ld.xz" : "init-ld.xz";
if (access(magisk_xz, F_OK) == 0) {
mmap_data magisk(magisk_xz);
@@ -206,6 +207,14 @@ static void extract_files(bool sbin) {
unxz(ch, stub);
close(fd);
}
if (access(init_ld_xz, F_OK) == 0) {
mmap_data init_ld(init_ld_xz);
unlink(init_ld_xz);
int fd = xopen("init-ld", O_WRONLY | O_CREAT, 0);
fd_stream ch(fd);
unxz(ch, init_ld);
close(fd);
}
}
void MagiskInit::parse_config_file() {
@@ -279,16 +288,19 @@ void MagiskInit::patch_ro_root() {
patch_rc_scripts("/", tmp_dir.data(), false);
}
// Extract magisk
// Extract overlay archives
extract_files(false);
// Oculus Go will use a special sepolicy if unlocked
if (access("/sepolicy.unlocked", F_OK) == 0) {
patch_sepolicy("/sepolicy.unlocked", ROOTOVL "/sepolicy.unlocked");
} else if ((access(SPLIT_PLAT_CIL, F_OK) != 0 && access("/sepolicy", F_OK) == 0) ||
!hijack_sepolicy()) {
patch_sepolicy("/sepolicy", ROOTOVL "/sepolicy");
} else {
bool patch = access(SPLIT_PLAT_CIL, F_OK) != 0 && access("/sepolicy", F_OK) == 0;
if (patch || !hijack_sepolicy()) {
patch_sepolicy("/sepolicy", ROOTOVL "/sepolicy");
}
}
unlink("init-ld");
// Mount rootdir
magic_mount(ROOTOVL);
@@ -338,12 +350,14 @@ void MagiskInit::patch_rw_root() {
setup_tmp(PRE_TMPDIR);
chdir(PRE_TMPDIR);
// Extract magisk
// Extract overlay archives
extract_files(true);
if ((!treble && access("/sepolicy", F_OK) == 0) || !hijack_sepolicy()) {
bool patch = !treble && access("/sepolicy", F_OK) == 0;
if (patch || !hijack_sepolicy()) {
patch_sepolicy("/sepolicy", "/sepolicy");
}
unlink("init-ld");
chdir("/");

View File

@@ -2,7 +2,6 @@
#include <consts.hpp>
#include <sepolicy.hpp>
#include <embed.hpp>
#include "init.hpp"
@@ -31,16 +30,6 @@ void MagiskInit::patch_sepolicy(const char *in, const char *out) {
}
}
static void dump_preload() {
int fd = xopen("/dev/preload.so", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644);
if (fd < 0)
return;
fd_stream ch(fd);
if (!unxz(ch, byte_view(init_ld_xz, sizeof(init_ld_xz))))
return;
close(fd);
}
#define MOCK_COMPAT SELINUXMOCK "/compatible"
#define MOCK_LOAD SELINUXMOCK "/load"
#define MOCK_ENFORCE SELINUXMOCK "/enforce"
@@ -53,7 +42,7 @@ bool MagiskInit::hijack_sepolicy() {
// This meant that instead of going through convoluted methods trying to alter
// and block init's control flow, we can just LD_PRELOAD and replace the
// security_load_policy function with our own implementation.
dump_preload();
cp_afc("init-ld", "/dev/preload.so");
setenv("LD_PRELOAD", "/dev/preload.so", 1);
}
@@ -100,18 +89,10 @@ bool MagiskInit::hijack_sepolicy() {
// Read all custom rules into memory
string rules;
if (auto dir = xopen_dir("/data/" PREINITMIRR)) {
for (dirent *entry; (entry = xreaddir(dir.get()));) {
auto name = "/data/" PREINITMIRR "/"s + entry->d_name;
auto rule_file = name + "/sepolicy.rule";
if (xaccess(rule_file.data(), R_OK) == 0 &&
access((name + "/disable").data(), F_OK) != 0 &&
access((name + "/remove").data(), F_OK) != 0) {
LOGD("Load custom sepolicy patch: [%s]\n", rule_file.data());
full_read(rule_file.data(), rules);
rules += '\n';
}
}
auto rule = "/data/" PREINITMIRR "/sepolicy.rule";
if (xaccess(rule, R_OK) == 0) {
LOGD("Loading custom sepolicy patch: [%s]\n", rule);
rules = full_read(rule);
}
// Create a new process waiting for init operations
if (xfork()) {

View File

@@ -118,10 +118,6 @@ impl SepolicyExt for sepolicy {
fn load_rules_from_reader<T: BufRead>(mut self: Pin<&mut sepolicy>, reader: &mut T) {
reader.foreach_lines(|line| {
let line = line.trim();
if line.is_empty() {
return true;
}
parse_statement(self.as_mut(), line);
true
});

View File

@@ -3,7 +3,6 @@ use std::io::stderr;
use std::{iter::Peekable, pin::Pin, vec::IntoIter};
use base::{error, warn, FmtAdaptor};
use crate::ffi::Xperm;
use crate::sepolicy;
@@ -436,15 +435,16 @@ fn extract_token<'a>(s: &'a str, tokens: &mut Vec<Token<'a>>) {
fn tokenize_statement(statement: &str) -> Vec<Token> {
let mut tokens = Vec::new();
for s in statement.split_whitespace() {
if s.starts_with('#') {
break;
}
extract_token(s, &mut tokens);
}
tokens
}
pub fn parse_statement(sepolicy: Pin<&mut sepolicy>, statement: &str) {
let statement = statement.trim();
if statement.is_empty() || statement.starts_with('#') {
return;
}
let mut tokens = tokenize_statement(statement).into_iter().peekable();
let result = exec_statement(sepolicy, &mut tokens);
if let Err(e) = result {

View File

@@ -71,13 +71,14 @@ export KEEPFORCEENCRYPT=true
echo "KEEPVERITY=$KEEPVERITY" > config
echo "KEEPFORCEENCRYPT=$KEEPFORCEENCRYPT" >> config
echo "PREINITDEVICE=$(./magisk --preinit-device)" >> config
# For API 28, we also patch advancedFeatures.ini to disable SAR
# Manually override skip_initramfs by setting RECOVERYMODE=true
# For API 28, we also manually disable SystemAsRoot
# Explicitly override skip_initramfs by setting RECOVERYMODE=true
[ $API = "28" ] && echo 'RECOVERYMODE=true' >> config
cat config
./magiskboot compress=xz magisk magisk.xz
./magiskboot compress=xz stub.apk stub.xz
./magiskboot compress=xz init-ld init-ld.xz
./magiskboot cpio ramdisk.cpio \
"add 0750 init magiskinit" \
@@ -85,12 +86,13 @@ cat config
"mkdir 0750 overlay.d/sbin" \
"add 0644 overlay.d/sbin/magisk.xz magisk.xz" \
"add 0644 overlay.d/sbin/stub.xz stub.xz" \
"add 0644 overlay.d/sbin/init-ld.xz init-ld.xz" \
"patch" \
"backup ramdisk.cpio.orig" \
"mkdir 000 .backup" \
"add 000 .backup/.magisk config"
rm -f ramdisk.cpio.orig config magisk*.xz stub.xz
rm -f ramdisk.cpio.orig config *.xz
if $IS_RAMDISK; then
./magiskboot compress=gzip ramdisk.cpio "$OUTPUT_FILE"
else

View File

@@ -221,7 +221,7 @@ else
# Android 15 Beta
run_test 35 google_apis
# Run 16k page tests
run_test VanillaIceCream google_apis_ps16k
run_test 35 google_apis_ps16k
fi
"$avd" delete avd -n test

View File

@@ -20,6 +20,7 @@
# magiskinit binary The binary to replace /init.
# magisk binary The magisk binary.
# magiskboot binary A tool to manipulate boot images.
# init-ld binary The library that will be LD_PRELOAD of /init
# stub.apk binary The stub Magisk app to embed into ramdisk.
# chromeos folder This folder includes the utility and keys to sign
# (optional) chromeos boot images. Only used for Pixel C.
@@ -161,6 +162,7 @@ $BOOTMODE && [ -z "$PREINITDEVICE" ] && PREINITDEVICE=$(./magisk --preinit-devic
# Compress to save precious ramdisk space
./magiskboot compress=xz magisk magisk.xz
./magiskboot compress=xz stub.apk stub.xz
./magiskboot compress=xz init-ld init-ld.xz
echo "KEEPVERITY=$KEEPVERITY" > config
echo "KEEPFORCEENCRYPT=$KEEPFORCEENCRYPT" >> config
@@ -177,13 +179,14 @@ fi
"mkdir 0750 overlay.d/sbin" \
"add 0644 overlay.d/sbin/magisk.xz magisk.xz" \
"add 0644 overlay.d/sbin/stub.xz stub.xz" \
"add 0644 overlay.d/sbin/init-ld.xz init-ld.xz" \
"patch" \
"$SKIP_BACKUP backup ramdisk.cpio.orig" \
"mkdir 000 .backup" \
"add 000 .backup/.magisk config" \
|| abort "! Unable to patch ramdisk"
rm -f ramdisk.cpio.orig config magisk*.xz stub.xz
rm -f ramdisk.cpio.orig config *.xz
#################
# Binary Patches

248
scripts/release.sh Executable file
View File

@@ -0,0 +1,248 @@
#!/usr/bin/env bash
set -e
# On macOS, gsed is required (brew install gnu-sed)
# Required tools: jq, gh
# The GitHub cli (gh) has to be properly authenticated
# These variables can be modified as needed
MAGISK_FILES=../magisk-files
CONFIG=config.prop
NOTES=notes.md
# These are constants, do not modify
GCONFIG=gradle.properties
README=README.MD
BUILDCMD="./build.py -c $CONFIG"
CWD=$(pwd)
grep_prop() {
local REGEX="s/^$1=//p"
shift
local FILES=$@
sed -n "$REGEX" $FILES | head -n 1
}
enable_version_config() {
# Make sure version is not commented out and exists
sed -i "s:^# version=:version=:g" $CONFIG
if ! grep -qE '^version=' $CONFIG; then
echo 'version=' >> $CONFIG
fi
}
disable_version_config() {
# Comment out version config
sed -i "s:^version=:# version=:g" $CONFIG
}
# $1 = tag
update_readme_stable() {
sed -i "s:badge/Magisk-v.*:badge/Magisk-${1}-blue)](https\://github.com/topjohnwu/Magisk/releases/tag/$1):g" $README
}
# $1 = tag
update_readme_beta() {
sed -i "s:badge/Magisk%20Beta.*:badge/Magisk%20Beta-${1}-blue)](https\://github.com/topjohnwu/Magisk/releases/tag/$1):g" $README
}
# $1 = tag
update_readme_canary() {
sed -i "s:badge/Magisk-Canary.*:badge/Magisk-Canary-red)](https\://github.com/topjohnwu/Magisk/releases/tag/$1):g" $README
}
gen_link() {
echo "https://github.com/topjohnwu/Magisk/releases/download/$1/$2"
}
update_canary_json() {
local ver=$(grep_prop version $CONFIG)
local code=$(grep_prop magisk.versionCode $GCONFIG)
local tag="canary-$code"
local json
json=$MAGISK_FILES/canary.json
jq ".magisk.version=\"$ver\"|.magisk.versionCode=\"$code\"|
.magisk.link=\"$(gen_link $tag app-release.apk)\"|
.magisk.note=\"$(gen_link $tag notes.md)\"" $json > ${json}.tmp
mv ${json}.tmp $json
json=$MAGISK_FILES/debug.json
jq ".magisk.version=\"$ver\"|.magisk.versionCode=\"$code\"|
.magisk.link=\"$(gen_link $tag app-debug.apk)\"|
.magisk.note=\"$(gen_link $tag notes.md)\"" $json > ${json}.tmp
mv ${json}.tmp $json
}
# $1 = json path
update_release_json() {
local json=$1
local ver=$(grep_prop version $CONFIG)
local code=$(grep_prop magisk.versionCode $GCONFIG)
jq ".magisk.version=\"$ver\"|.magisk.versionCode=\"$code\"|
.magisk.link=\"$(gen_link v${ver} Magisk-v${ver}.apk)\"|
.magisk.note=\"https://topjohnwu.github.io/Magisk/releases/${code}.md\"" $json > ${json}.tmp
mv ${json}.tmp $json
}
build_canary() {
enable_version_config
# Update version code
local code=$(grep_prop magisk.versionCode $GCONFIG)
code=$((code + 1))
local tag="canary-$code"
sed -i "s:versionCode=.*:versionCode=${code}:g" $GCONFIG
update_readme_canary $tag
# Commit version code changes
git add -u .
git status
git commit -m "Release new canary build"
git tag $tag
# Update version name
local ver=$(git rev-parse --short=8 HEAD)
sed -i "s:version=.*:version=${ver}:g" $CONFIG
sed -i "s:## Magisk (.*:## Magisk (${ver}) (${code}):g" $NOTES
# Update and commit JSON
update_canary_json
cd $MAGISK_FILES
git add -u .
git status
git commit -m "Update Canary Channel: Upstream to $ver"
cd $CWD
# Build
$BUILDCMD clean
$BUILDCMD all
$BUILDCMD -r all
disable_version_config
}
# $1 = ver, $2 = stable?
build_release() {
enable_version_config
# Update version configs
local ver=$1
local stable=$2
local code=$(echo - | awk "{ print $ver * 1000 }")
local tag="v$ver"
sed -i "s:versionCode=.*:versionCode=${code}:g" $GCONFIG
sed -i "s:version=.*:version=${ver}:g" $CONFIG
# Update and commit JSON
if $stable; then
update_readme_stable $tag
update_readme_beta $tag
update_release_json $MAGISK_FILES/stable.json
cp -vf $MAGISK_FILES/stable.json $MAGISK_FILES/beta.json
else
update_readme_beta $tag
update_release_json $MAGISK_FILES/beta.json
fi
cd $MAGISK_FILES
git add -u .
git status
git commit -m "Release Magisk v$ver"
cd $CWD
# Commit version code changes
git add -u .
git status
git commit -m "Release Magisk v$ver"
git tag $tag
# Build
$BUILDCMD clean
$BUILDCMD -r all
disable_version_config
}
stable() {
[ -z $1 ] && exit 1
local ver=$1
build_release $ver true
}
beta() {
[ -z $1 ] && exit 1
local ver=$1
build_release $ver false
}
pub() {
gh auth status
local latest_tag=$(git describe --abbrev=0 --tags)
local ver=$(grep_prop version $CONFIG)
local code=$(grep_prop magisk.versionCode $GCONFIG)
local out=$(grep_prop outdir $CONFIG)
local tag title
if [ -z $out ]; then
out=out
fi
git push origin master
git push --tags
if [ $(($code % 100)) -ne 0 ]; then
tag="canary-$code"
title="Magisk ($ver) ($code)"
# Assert tag format
[ $latest_tag = $tag ]
# Publish release
tail -n +3 $NOTES > release.md
gh release create --verify-tag $tag -p -t "$title" -F release.md $out/app-release.apk $out/app-debug.apk $NOTES
else
tag="v$ver"
title="Magisk v$ver"
# Assert tag format
[ $latest_tag = $tag ]
# Publish release
tail -n +3 docs/releases/$code.md > release.md
gh release create --verify-tag $tag -t "$title" -F release.md "$out/app-release.apk#Magisk-v${ver}.apk"
fi
rm -f release.md
cd $MAGISK_FILES
git push origin master
cd $CWD
}
revert() {
local latest_tag=$(git describe --abbrev=0 --tags)
git tag -d $latest_tag
git reset --hard HEAD~
cd $MAGISK_FILES
git reset --hard HEAD~
cd $CWD
}
# Use GNU sed on macOS
if command -v gsed >/dev/null; then
function sed() { gsed "$@"; }
export -f sed
fi
git pull
case $1 in
"canary" ) build_canary ;;
"stable" ) stable $2 ;;
"beta" ) beta $2 ;;
"pub" ) pub ;;
"revert" ) revert ;;
* ) exit 1 ;;
esac