mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-12-11 07:22:35 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff4ca74cfe | ||
|
|
200665c48a | ||
|
|
dd42aa99ea | ||
|
|
0936cdb192 | ||
|
|
871643dce2 | ||
|
|
a510554b21 | ||
|
|
9cc830c565 | ||
|
|
ddbac50645 | ||
|
|
b5138a4af0 | ||
|
|
64752f38e8 | ||
|
|
9ac4b5ce7d | ||
|
|
505053f9b4 | ||
|
|
ccb264f33a | ||
|
|
84f7d75d30 | ||
|
|
9a776c22d9 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -82,7 +82,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
version: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, "CANARY"]
|
version: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36.1, "CANARY"]
|
||||||
type: [""]
|
type: [""]
|
||||||
include:
|
include:
|
||||||
- version: "CANARY"
|
- version: "CANARY"
|
||||||
|
|||||||
@@ -15,18 +15,18 @@
|
|||||||
<string name="app_changelog">앱 변경 사항</string>
|
<string name="app_changelog">앱 변경 사항</string>
|
||||||
<string name="loading">로딩중…</string>
|
<string name="loading">로딩중…</string>
|
||||||
<string name="update">업데이트</string>
|
<string name="update">업데이트</string>
|
||||||
<string name="not_available">N/A</string>
|
<string name="not_available">알 수 없음</string>
|
||||||
<string name="hide">숨기기</string>
|
<string name="hide">숨기기</string>
|
||||||
<string name="home_package">패키지</string>
|
<string name="home_package">패키지</string>
|
||||||
<string name="home_app_title">앱</string>
|
<string name="home_app_title">앱</string>
|
||||||
|
|
||||||
<string name="home_notice_content">공식 Github 페이지에서 Magisk를 다운로드하십시오. 알 수 없는 소스의 파일이 악의적일 수 있습니다!</string>
|
<string name="home_notice_content">공식 Github 페이지에서 Magisk를 다운로드하십시오. 알 수 없는 출처에서 받은 파일이 위험할 수 있습니다!</string>
|
||||||
<string name="home_support_title">후원하기</string>
|
<string name="home_support_title">후원하기</string>
|
||||||
<string name="home_item_source">소스</string>
|
<string name="home_item_source">소스</string>
|
||||||
<string name="home_support_content">Magisk는 항상 무료일 것이며, 오픈소스일 것입니다. 그러나 소액의 후원을 통해 관심을 표할 수 있습니다.</string>
|
<string name="home_support_content">Magisk는 항상 무료일 것이며, 오픈소스일 것입니다. 그러나 소액의 후원을 통해 관심을 표할 수 있습니다.</string>
|
||||||
<string name="home_installed_version">설치됨</string>
|
<string name="home_installed_version">설치됨</string>
|
||||||
<string name="home_latest_version">최신</string>
|
<string name="home_latest_version">최신</string>
|
||||||
<string name="invalid_update_channel">올바르지 않은 업데이트 채널</string>
|
<string name="invalid_update_channel">잘못된 업데이트 채널</string>
|
||||||
<string name="uninstall_magisk_title">Magisk 제거</string>
|
<string name="uninstall_magisk_title">Magisk 제거</string>
|
||||||
<string name="uninstall_magisk_msg">모든 모듈이 비활성화/제거됩니다. 루트도 제거될 것이며, 데이터도 암호화 되어있지 않으면 암호화될 수도 있습니다.</string>
|
<string name="uninstall_magisk_msg">모든 모듈이 비활성화/제거됩니다. 루트도 제거될 것이며, 데이터도 암호화 되어있지 않으면 암호화될 수도 있습니다.</string>
|
||||||
|
|
||||||
@@ -51,11 +51,11 @@
|
|||||||
<!--Superuser-->
|
<!--Superuser-->
|
||||||
<string name="su_request_title">슈퍼유저 요청</string>
|
<string name="su_request_title">슈퍼유저 요청</string>
|
||||||
<string name="touch_filtered_warning">앱이 슈퍼유저 요청을 가려, Magisk에서 응답을 확인할 수 없습니다.</string>
|
<string name="touch_filtered_warning">앱이 슈퍼유저 요청을 가려, Magisk에서 응답을 확인할 수 없습니다.</string>
|
||||||
<string name="deny">일괄 거부</string>
|
<string name="deny">모두 거부</string>
|
||||||
<string name="prompt">수동 허가</string>
|
<string name="prompt">물어보기</string>
|
||||||
<string name="grant">일괄 허용</string>
|
<string name="grant">모두 허용</string>
|
||||||
<string name="su_warning">기기에 대한 전체 액세스 권한을 부여합니다.\n확실하지 않은 경우 거부하세요!</string>
|
<string name="su_warning">기기에 대한 슈퍼유저 권한을 부여합니다.\n확실하지 않은 경우 거부하세요!</string>
|
||||||
<string name="forever">영구적으로</string>
|
<string name="forever">영구</string>
|
||||||
<string name="once">한 번만</string>
|
<string name="once">한 번만</string>
|
||||||
<string name="tenmin">10분</string>
|
<string name="tenmin">10분</string>
|
||||||
<string name="twentymin">20분</string>
|
<string name="twentymin">20분</string>
|
||||||
@@ -69,20 +69,20 @@
|
|||||||
<string name="su_snack_notif_off">%1$s의 알림이 비활성화됨</string>
|
<string name="su_snack_notif_off">%1$s의 알림이 비활성화됨</string>
|
||||||
<string name="su_snack_log_on">%1$s의 로깅이 활성화됨</string>
|
<string name="su_snack_log_on">%1$s의 로깅이 활성화됨</string>
|
||||||
<string name="su_snack_log_off">%1$s의 로깅이 비활성화됨</string>
|
<string name="su_snack_log_off">%1$s의 로깅이 비활성화됨</string>
|
||||||
<string name="su_revoke_title">취소하시겠습니까?</string>
|
<string name="su_revoke_title">제거하시겠습니까?</string>
|
||||||
<string name="su_revoke_msg">정말 %1$s의 권한을 취소하시겠습니까?</string>
|
<string name="su_revoke_msg">정말 %1$s의 권한을 제거하시겠습니까?</string>
|
||||||
<string name="toast">토스트</string>
|
<string name="toast">토스트</string>
|
||||||
<string name="none">없음</string>
|
<string name="none">없음</string>
|
||||||
|
|
||||||
<string name="superuser_toggle_notification">알림</string>
|
<string name="superuser_toggle_notification">알림</string>
|
||||||
<string name="superuser_toggle_revoke">권한삭제</string>
|
<string name="superuser_toggle_revoke">권한 제거</string>
|
||||||
<string name="superuser_policy_none">슈퍼유저 권한을 요청한 앱이 없습니다.</string>
|
<string name="superuser_policy_none">슈퍼유저 권한을 요청한 앱이 없습니다.</string>
|
||||||
|
|
||||||
<!--Logs-->
|
<!--Logs-->
|
||||||
<string name="log_data_none">로그가 없습니다. 슈퍼유저 권한을 필요로 하는 앱을 사용하십시오.</string>
|
<string name="log_data_none">로그가 없습니다. 슈퍼유저 권한을 필요로 하는 앱을 사용하십시오.</string>
|
||||||
<string name="log_data_magisk_none">Magisk 로그가 없습니다.</string>
|
<string name="log_data_magisk_none">Magisk 로그가 없습니다.</string>
|
||||||
<string name="menuSaveLog">로그 저장</string>
|
<string name="menuSaveLog">로그 저장</string>
|
||||||
<string name="menuClearLog">지금 로그 삭제</string>
|
<string name="menuClearLog">로그 삭제</string>
|
||||||
<string name="logs_cleared">로그 삭제 완료.</string>
|
<string name="logs_cleared">로그 삭제 완료.</string>
|
||||||
<string name="pid">PID: %1$d</string>
|
<string name="pid">PID: %1$d</string>
|
||||||
<string name="target_uid">Target UID: %1$d</string>
|
<string name="target_uid">Target UID: %1$d</string>
|
||||||
@@ -96,9 +96,9 @@
|
|||||||
<string name="hide_search">검색</string>
|
<string name="hide_search">검색</string>
|
||||||
|
|
||||||
<!--Module-->
|
<!--Module-->
|
||||||
<string name="no_info_provided">(제공된 정보 없음)</string>
|
<string name="no_info_provided">(정보 없음)</string>
|
||||||
<string name="reboot_userspace">조용히 다시 시작</string>
|
<string name="reboot_userspace">조용히 다시 시작</string>
|
||||||
<string name="reboot_recovery">리커버리로 다시 시작</string>
|
<string name="reboot_recovery">복구 모드로 다시 시작</string>
|
||||||
<string name="reboot_bootloader">부트로더로 다시 시작</string>
|
<string name="reboot_bootloader">부트로더로 다시 시작</string>
|
||||||
<string name="reboot_download">다운로드 모드로 다시 시작</string>
|
<string name="reboot_download">다운로드 모드로 다시 시작</string>
|
||||||
<string name="reboot_edl">EDL로 다시 시작</string>
|
<string name="reboot_edl">EDL로 다시 시작</string>
|
||||||
@@ -107,20 +107,20 @@
|
|||||||
<string name="module_state_restore">복구</string>
|
<string name="module_state_restore">복구</string>
|
||||||
<string name="module_action_install_external">저장소에서 설치</string>
|
<string name="module_action_install_external">저장소에서 설치</string>
|
||||||
<string name="update_available">업데이트 가능</string>
|
<string name="update_available">업데이트 가능</string>
|
||||||
<string name="suspend_text_riru">%1$s 가 활성화 되어있어 모듈 로드가 일시정지 되었습니다.</string>
|
<string name="suspend_text_riru">%1$s 가 활성화 되어있어 모듈이 로드되지 않았습니다.</string>
|
||||||
<string name="suspend_text_zygisk">%1$s 가 비활성화 되어있어 모듈이 로드되지 않았습니다.</string>
|
<string name="suspend_text_zygisk">%1$s 가 활성화되어 있지 않아 모듈이 로드되지 않았습니다.</string>
|
||||||
<string name="zygisk_module_unloaded">호환성 문제로 인해 Zygisk 모듈이 로드되지 않았습니다.</string>
|
<string name="zygisk_module_unloaded">호환성 문제로 인해 Zygisk 모듈이 로드되지 않았습니다.</string>
|
||||||
|
|
||||||
<!--Settings-->
|
<!--Settings-->
|
||||||
<string name="settings_dark_mode_title">테마 선택</string>
|
<string name="settings_dark_mode_title">테마 선택</string>
|
||||||
<string name="settings_dark_mode_message">원하는 테마 모드를 선택하세요!</string>
|
<string name="settings_dark_mode_message">원하는 테마 모드를 선택하세요!</string>
|
||||||
<string name="settings_dark_mode_light">기본</string>
|
<string name="settings_dark_mode_light">기본</string>
|
||||||
<string name="settings_dark_mode_system">시스템 설정값</string>
|
<string name="settings_dark_mode_system">자동</string>
|
||||||
<string name="settings_dark_mode_dark">다크 모드</string>
|
<string name="settings_dark_mode_dark">다크 모드</string>
|
||||||
<string name="settings_download_path_title">다운로드 경로</string>
|
<string name="settings_download_path_title">다운로드 위치</string>
|
||||||
<string name="settings_download_path_message">파일이 %1$s에 저장됩니다</string>
|
<string name="settings_download_path_message">파일이 %1$s에 저장됩니다</string>
|
||||||
<string name="settings_hide_app_title">Magisk 앱 숨기기</string>
|
<string name="settings_hide_app_title">Magisk 앱 숨기기</string>
|
||||||
<string name="settings_hide_app_summary">랜덤 패키지 ID와 커스텀 앱 이름으로 Magisk 프록시 앱을 설치합니다.</string>
|
<string name="settings_hide_app_summary">무작위 패키지명과 사용자 지정 앱 이름으로 Magisk 프록시 앱을 설치합니다.</string>
|
||||||
<string name="settings_restore_app_title">Magisk 앱 복원</string>
|
<string name="settings_restore_app_title">Magisk 앱 복원</string>
|
||||||
<string name="settings_restore_app_summary">앱 숨기기를 해제하고 원래 APK로 복원합니다.</string>
|
<string name="settings_restore_app_summary">앱 숨기기를 해제하고 원래 APK로 복원합니다.</string>
|
||||||
<string name="language">언어</string>
|
<string name="language">언어</string>
|
||||||
@@ -167,12 +167,12 @@
|
|||||||
<string name="settings_doh_description">일부 국가에 존재하는 DNS 포이즈닝을 해결합니다.</string>
|
<string name="settings_doh_description">일부 국가에 존재하는 DNS 포이즈닝을 해결합니다.</string>
|
||||||
|
|
||||||
<string name="multiuser_mode">다중 사용자 모드</string>
|
<string name="multiuser_mode">다중 사용자 모드</string>
|
||||||
<string name="settings_owner_only">기기 소유자만</string>
|
<string name="settings_owner_only">주인 사용자만</string>
|
||||||
<string name="settings_owner_manage">기기 소유자에 의해 관리됨</string>
|
<string name="settings_owner_manage">주인 사용자에 의해 관리됨</string>
|
||||||
<string name="settings_user_independent">사용자별</string>
|
<string name="settings_user_independent">사용자별 분리</string>
|
||||||
<string name="owner_only_summary">소유자만 루트 액세스를 갖습니다.</string>
|
<string name="owner_only_summary">주인 사용자만 루트 액세스를 갖습니다.</string>
|
||||||
<string name="owner_manage_summary">소유자만 루트 액세스를 관리하고 요청을 받을 수 있습니다.</string>
|
<string name="owner_manage_summary">주인 사용자가 다른 사용자들의 루트 액세스를 관리하고 요청을 받을 수 있습니다.</string>
|
||||||
<string name="user_independent_summary">각각의 사용자가 개별적인 권한을 갖습니다.</string>
|
<string name="user_independent_summary">각각의 사용자가 권한을 관리합니다.</string>
|
||||||
|
|
||||||
<string name="mount_namespace_mode">네임스페이스 마운트 모드</string>
|
<string name="mount_namespace_mode">네임스페이스 마운트 모드</string>
|
||||||
<string name="settings_ns_global">전역 네임스페이스</string>
|
<string name="settings_ns_global">전역 네임스페이스</string>
|
||||||
@@ -187,7 +187,7 @@
|
|||||||
<string name="progress_channel">진행 상황</string>
|
<string name="progress_channel">진행 상황</string>
|
||||||
<string name="updated_channel">업데이트 완료</string>
|
<string name="updated_channel">업데이트 완료</string>
|
||||||
<string name="download_complete">다운로드 완료</string>
|
<string name="download_complete">다운로드 완료</string>
|
||||||
<string name="download_file_error">파일 다운로드 오류</string>
|
<string name="download_file_error">파일 다운로드 실패</string>
|
||||||
<string name="magisk_update_title">새 버전의 Magisk를 사용할 수 있습니다!</string>
|
<string name="magisk_update_title">새 버전의 Magisk를 사용할 수 있습니다!</string>
|
||||||
<string name="updated_title">Magisk가 업데이트 되었습니다!</string>
|
<string name="updated_title">Magisk가 업데이트 되었습니다!</string>
|
||||||
<string name="updated_text">터치하여 앱 열기</string>
|
<string name="updated_text">터치하여 앱 열기</string>
|
||||||
@@ -208,7 +208,7 @@
|
|||||||
<string name="restore_img">이미지 복구</string>
|
<string name="restore_img">이미지 복구</string>
|
||||||
<string name="restore_img_msg">복구하는 중…</string>
|
<string name="restore_img_msg">복구하는 중…</string>
|
||||||
<string name="restore_done">복구 완료!</string>
|
<string name="restore_done">복구 완료!</string>
|
||||||
<string name="restore_fail">원 백업이 존재하지 않습니다!</string>
|
<string name="restore_fail">백업이 존재하지 않습니다!</string>
|
||||||
<string name="setup_fail">설치 실패</string>
|
<string name="setup_fail">설치 실패</string>
|
||||||
<string name="env_fix_title">추가 설정 필요</string>
|
<string name="env_fix_title">추가 설정 필요</string>
|
||||||
<string name="env_fix_msg">Magisk가 제대로 작동하려면 추가 설정이 필요합니다. 다시 시작 하시겠습니까?</string>
|
<string name="env_fix_msg">Magisk가 제대로 작동하려면 추가 설정이 필요합니다. 다시 시작 하시겠습니까?</string>
|
||||||
@@ -219,10 +219,10 @@
|
|||||||
<string name="unsupport_system_app_msg">해당 앱을 시스템 앱으로 실행하는 것은 지원되지 않습니다. 앱을 일반 사용자 앱으로 실행해 주세요.</string>
|
<string name="unsupport_system_app_msg">해당 앱을 시스템 앱으로 실행하는 것은 지원되지 않습니다. 앱을 일반 사용자 앱으로 실행해 주세요.</string>
|
||||||
<string name="unsupport_other_su_msg">Magisk으로 부터 설치되지 않은 \"su\" 바이너리가 감지되었습니다. 다른 루팅 방법을 제거하거나, Magisk 를 다시 설치해주세요.</string>
|
<string name="unsupport_other_su_msg">Magisk으로 부터 설치되지 않은 \"su\" 바이너리가 감지되었습니다. 다른 루팅 방법을 제거하거나, Magisk 를 다시 설치해주세요.</string>
|
||||||
<string name="unsupport_external_storage_msg">Magisk 가 외부 저장소에 설치되어 있습니다. Magisk 를 내부 저장소에 설치 해주세요.</string>
|
<string name="unsupport_external_storage_msg">Magisk 가 외부 저장소에 설치되어 있습니다. Magisk 를 내부 저장소에 설치 해주세요.</string>
|
||||||
<string name="unsupport_nonroot_stub_msg">숨겨진 Magisk 앱은 루팅이 풀려 더이상 작동하지 못합니다. 본래 APK 를 복원하거나 재설치 해주세요.</string>
|
<string name="unsupport_nonroot_stub_msg">이 숨겨진 Magisk 앱은 루트 권한이 손실되어 사용할 수 없습니다. 원래 APK 를 복원하거나 재설치 해주세요.</string>
|
||||||
<string name="unsupport_nonroot_stub_title">@string/settings_restore_app_title</string>
|
<string name="unsupport_nonroot_stub_title">@string/settings_restore_app_title</string>
|
||||||
<string name="external_rw_permission_denied">해당 기능을 사용하려면 저장소 권한을 허용해 주십시오.</string>
|
<string name="external_rw_permission_denied">해당 기능을 사용하려면 저장소 권한을 허용해 주십시오.</string>
|
||||||
<string name="install_unknown_denied">이 기능을 활성화 하려면 "알 수 없는 앱 설치"를 허용해주세요.</string>
|
<string name="install_unknown_denied">이 기능을 활성화 하려면 "출처를 알 수 없는 앱 설치"를 허용해주세요.</string>
|
||||||
<string name="add_shortcut_title">홈 화면에 바로가기 추가</string>
|
<string name="add_shortcut_title">홈 화면에 바로가기 추가</string>
|
||||||
<string name="add_shortcut_msg">앱을 숨긴 후 아이콘과 이름을 알아보기 힘들 경우를 위해 알아보기 쉬운 바로가기를 홈 화면에 추가합니다.</string>
|
<string name="add_shortcut_msg">앱을 숨긴 후 아이콘과 이름을 알아보기 힘들 경우를 위해 알아보기 쉬운 바로가기를 홈 화면에 추가합니다.</string>
|
||||||
<string name="app_not_found">해당 작업을 처리할 어플리케이션이 없습니다.</string>
|
<string name="app_not_found">해당 작업을 처리할 어플리케이션이 없습니다.</string>
|
||||||
|
|||||||
@@ -2,242 +2,255 @@
|
|||||||
|
|
||||||
<!--Sections-->
|
<!--Sections-->
|
||||||
<string name="modules">Modulet</string>
|
<string name="modules">Modulet</string>
|
||||||
<string name="superuser">Super-përdoruesi</string>
|
<string name="superuser">Superuser</string>
|
||||||
<string name="logs">Regjistrat</string>
|
<string name="logs">Regjistrimet</string>
|
||||||
<string name="settings">Cilësimet</string>
|
<string name="settings">Parametrat</string>
|
||||||
<string name="install">Instalo</string>
|
<string name="install">Instalo</string>
|
||||||
<string name="section_home">Shtëpi</string>
|
<string name="section_home">Shtëpia</string>
|
||||||
<string name="section_theme">Tema</string>
|
<string name="section_theme">Temat</string>
|
||||||
<string name="denylist">Lista e mohimit</string>
|
<string name="denylist">Lista e ndaluar</string>
|
||||||
|
|
||||||
<!--Home-->
|
<!--Home-->
|
||||||
<string name="no_connection">Nuk ka lidhje interneti</string>
|
<string name="no_connection">Nuk ka lidhje të disponueshme</string>
|
||||||
<string name="app_changelog">Ndryshimet</string>
|
<string name="app_changelog">Shënimet e ndryshimeve</string>
|
||||||
<string name="loading">Po ngarkohet…</string>
|
<string name="loading">Duke u ngarkuar…</string>
|
||||||
<string name="update">Përditëso</string>
|
<string name="update">Përditëso</string>
|
||||||
<string name="not_available">N/A</string>
|
<string name="not_available">N/A</string>
|
||||||
<string name="hide">Fshih</string>
|
<string name="hide">Fshih</string>
|
||||||
<string name="home_package">Paketa</string>
|
<string name="home_package">Paketa</string>
|
||||||
<string name="home_app_title">App</string>
|
<string name="home_app_title">Aplikacioni</string>
|
||||||
|
<string name="home_notice_content">Shkarkoni Magisk VETËM nga faqja zyrtare në GitHub. Skedarët nga burime të panjohura mund të jenë të dëmshëm!</string>
|
||||||
<string name="home_notice_content">Shkarkoni Magisk VETEM nga faqja zyrtare e GitHub. Skedarët nga burime të panjohura mund të jenë me qëllim të keq! </string>
|
|
||||||
<string name="home_support_title">Na mbështetni</string>
|
<string name="home_support_title">Na mbështetni</string>
|
||||||
<string name="home_follow_title">Na ndiqni</string>
|
<string name="home_follow_title">Na ndiqni</string>
|
||||||
<string name="home_item_source">Burimi</string>
|
<string name="home_item_source">Burimi</string>
|
||||||
<string name="home_support_content">Magisk është, dhe gjithmonë do të jetë, falas dhe me burim të hapur. Sidoqoftë, mund të na tregoni se kujdeseni duke dërguar një donacion të vogël.</string>
|
<string name="home_support_content">Magisk është dhe do të mbetet gjithmonë falas dhe me burim të hapur. Megjithatë, mund të na mbështesni duke bërë një donacion.</string>
|
||||||
<string name="home_installed_version">Instaluar</string>
|
<string name="home_installed_version">Instaluar</string>
|
||||||
<string name="home_latest_version">E fundit</string>
|
<string name="home_latest_version">Më i fundit</string>
|
||||||
<string name="invalid_update_channel">Kanali i përditësimit i pavlefshëm</string>
|
<string name="invalid_update_channel">Kanal i pavlefshëm për përditësime</string>
|
||||||
<string name="uninstall_magisk_title">Çinstalo Magisk</string>
|
<string name="uninstall_magisk_title">Çinstalo Magisk</string>
|
||||||
<string name="uninstall_magisk_msg">Të gjitha modulet do të çaktivizohen/hiqen!\nRrënja do të hiqet!\nTë dhënat tuaja potencialisht të koduara nëse jo tashmë!</string>
|
<string name="uninstall_magisk_msg">Të gjitha modulet do të çaktivizohen/hiqen!
|
||||||
|
Root-i do të hiqet!
|
||||||
|
Çdo memorie e brendshme që është çenkriptuar përmes Magisk do të rikriptohet!</string>
|
||||||
|
|
||||||
<!--Install-->
|
<!--Install-->
|
||||||
<string name="keep_force_encryption">Ruaj kriptimin me forcë</string>
|
<string name="keep_force_encryption">Ruaj enkriptimin e detyruar</string>
|
||||||
<string name="keep_dm_verity">Ruaj AVB 2.0/dm-verity</string>
|
<string name="keep_dm_verity">Ruaj AVB 2.0/dm-verity</string>
|
||||||
<string name="recovery_mode">Recovery Mode</string>
|
<string name="recovery_mode">Mënyra Recovery</string>
|
||||||
<string name="install_options_title">Opsionet</string>
|
<string name="install_options_title">Opsionet</string>
|
||||||
<string name="install_method_title">Metoda</string>
|
<string name="install_method_title">Metoda</string>
|
||||||
<string name="install_next">Tjetër</string>
|
<string name="install_next">Vazhdoni</string>
|
||||||
<string name="install_start">Shkojme</string>
|
<string name="install_start">Le të fillojmë</string>
|
||||||
<string name="manager_download_install">Shtypni për ta shkarkuar dhe instaluarl</string>
|
<string name="manager_download_install">Shtypni për të shkarkuar dhe instaluar</string>
|
||||||
<string name="direct_install">Instalimi i direkt (Rekomandohet)</string>
|
<string name="direct_install">Instalim i drejtpërdrejtë (Rekomandohet)</string>
|
||||||
<string name="install_inactive_slot">Instaloni në slotin joaktiv(Pas OTA)</string>
|
<string name="install_inactive_slot">Instalo në slot-in joaktiv (Pas OTA)</string>
|
||||||
<string name="install_inactive_slot_msg">Pajisja juaj do të detyrohet të fillojë në folenë aktuale joaktive pas një rindezje!\nPërdoreni këtë opsion vetëm pasi të keni përfunduar OTA.\nVazhdo?</string>
|
<string name="install_inactive_slot_msg">Pajisja juaj do të detyrohet të niset në slot-in joaktiv pas rinisjes!
|
||||||
<string name="setup_title">Konfigurimet shtesë</string>
|
Përdorni këtë opsion vetëm pasi OTA të ketë përfunduar.
|
||||||
<string name="select_patch_file">Zgjidhni dhe Patch një skader</string>
|
Të vazhdoj?</string>
|
||||||
<string name="patch_file_msg">Zgjidhni një imazh të papërpunuar (*.img) ose një skedar ODIN (*.tar) ose një payload.bin (*.bin)</string>
|
<string name="setup_title">Konfigurim shtesë</string>
|
||||||
<string name="reboot_delay_toast">Rinisje pas 5 sekondash…</string>
|
<string name="select_patch_file">Zgjidh dhe përpuno një skedar</string>
|
||||||
|
<string name="patch_file_msg">Zgjidh një imazh të papërpunuar (*.img) ose një skedar ODIN (*.tar) ose një payload.bin (*.bin)</string>
|
||||||
|
<string name="reboot_delay_toast">Rinisja pas 5 sekondash…</string>
|
||||||
<string name="flash_screen_title">Instalimi</string>
|
<string name="flash_screen_title">Instalimi</string>
|
||||||
|
|
||||||
<!--Superuser-->
|
<!--Superuser-->
|
||||||
<string name="su_request_title">Kërkesë nga superpërdoruesi</string>
|
<string name="su_request_title">Kërkesë Superuser</string>
|
||||||
<string name="touch_filtered_warning">Për shkak se një aplikacion po errëson një kërkesë të superpërdoruesit, Magisk nuk mund të verifikojë përgjigjen tuaj</string>
|
<string name="touch_filtered_warning">Për shkak se një aplikacion po mbivendos kërkesën Superuser, Magisk nuk mund të verifikojë përgjigjen tuaj.</string>
|
||||||
<string name="deny">Refuzo</string>
|
<string name="deny">Refuzo</string>
|
||||||
<string name="prompt">Pyet</string>
|
<string name="prompt">Pyete</string>
|
||||||
|
<string name="restrict">Kufizo</string>
|
||||||
<string name="grant">Lejo</string>
|
<string name="grant">Lejo</string>
|
||||||
<string name="su_warning">Jep akses të plotë në pajisjen tuaj.\nRefuzo nëse nuk jeni të sigurt!</string>
|
<string name="su_warning">Jep akses të plotë në pajisjen tuaj.
|
||||||
<string name="forever">Gjithmonë</string>
|
Refuzoni nëse nuk jeni të sigurt!</string>
|
||||||
|
<string name="forever">Përgjithmonë</string>
|
||||||
<string name="once">Një herë</string>
|
<string name="once">Një herë</string>
|
||||||
<string name="tenmin">10 minuta</string>
|
<string name="tenmin">10 minuta</string>
|
||||||
<string name="twentymin">20 minuta</string>
|
<string name="twentymin">20 minuta</string>
|
||||||
<string name="thirtymin">30 minuta</string>
|
<string name="thirtymin">30 minuta</string>
|
||||||
<string name="sixtymin">60 minuta</string>
|
<string name="sixtymin">60 minuta</string>
|
||||||
<string name="su_allow_toast">%1$s iu dha aksesi te Super-përdoruesi</string>
|
<string name="su_allow_toast">%1$s mori të drejtat Superuser</string>
|
||||||
<string name="su_deny_toast">%1$s iu refuzua aksesi te Super -përdoruesi</string>
|
<string name="su_deny_toast">%1$s u refuzua të drejtat Superuser</string>
|
||||||
<string name="su_snack_grant">Aksesi i super-përdoruesit te %1$s është lenuar</string>
|
<string name="su_snack_grant">%1$s mori të drejtat Superuser</string>
|
||||||
<string name="su_snack_deny">Aksesi i super-përdoruesit te %1$s është refuzuar</string>
|
<string name="su_snack_deny">%1$s u refuzua të drejtat Superuser</string>
|
||||||
<string name="su_snack_notif_on">Njoftimet e %1$s janë aktivizuar</string>
|
<string name="su_snack_notif_on">Njoftimet për %1$s u aktivizuan</string>
|
||||||
<string name="su_snack_notif_off">Njoftimet e %1$s janë çaktivizuar</string>
|
<string name="su_snack_notif_off">Njoftimet për %1$s u çaktivizuan</string>
|
||||||
<string name="su_snack_log_on">Regjistrat e %1$s janë aktivizuar</string>
|
<string name="su_snack_log_on">Regjistrimi për %1$s u aktivizua</string>
|
||||||
<string name="su_snack_log_off">Regjistrat e %1$s janë çaktivizuar</string>
|
<string name="su_snack_log_off">Regjistrimi për %1$s u çaktivizua</string>
|
||||||
<string name="su_revoke_title">Të drejtat?</string>
|
<string name="su_revoke_title">Të hiqen?</string>
|
||||||
<string name="su_revoke_msg">Konfirmo për të hequr të drejtat e %1$s?</string>
|
<string name="su_revoke_msg">Konfirmoni heqjen e të drejtave Superuser për %1$s</string>
|
||||||
<string name="toast">Dolli</string>
|
<string name="toast">Njoftim</string>
|
||||||
<string name="none">Asnjë</string>
|
<string name="none">Asnjë</string>
|
||||||
<string name="superuser_toggle_notification">Njoftimet</string>
|
<string name="superuser_toggle_notification">Njoftimet</string>
|
||||||
<string name="superuser_toggle_revoke">Të drejtat</string>
|
<string name="superuser_toggle_revoke">Hiq</string>
|
||||||
<string name="superuser_policy_none">Asnjë aplikacion nuk ka kërkuar akoma akses për super-përdoruesin.</string>
|
<string name="superuser_policy_none">Asnjë aplikacion nuk ka kërkuar ende leje Superuser.</string>
|
||||||
|
|
||||||
<!--Logs-->
|
<!--Logs-->
|
||||||
<string name="log_data_none">Nuk ka regjistra, provoni të përdorni më shumë aplikacionet tuaja me SU</string>
|
<string name="log_data_none">Nuk keni regjistrime. Provojeni të përdorni më shumë aplikacionet me root.</string>
|
||||||
<string name="log_data_magisk_none">Regjistrat Magisk janë bosh, kjo është e çuditshme</string>
|
<string name="log_data_magisk_none">Regjistrimet e Magisk janë bosh — çuditërisht.</string>
|
||||||
<string name="menuSaveLog">Ruaj regjistrar</string>
|
<string name="menuSaveLog">Ruaj regjistrimin</string>
|
||||||
<string name="menuClearLog">Pastro regjistrat tani</string>
|
<string name="menuClearLog">Pastro regjistrimin tani</string>
|
||||||
<string name="logs_cleared">Regjistrat u pastuan me sukses</string>
|
<string name="logs_cleared">Regjistrimet u pastruan me sukses</string>
|
||||||
<string name="pid">PID: %1$d</string>
|
<string name="pid">PID: %1$d</string>
|
||||||
<string name="target_uid">Target UID: %1$d</string>
|
<string name="target_uid">UID i synuar: %1$d</string>
|
||||||
<string name="target_pid">Montoni PID të synuar ns: %s</string>
|
<string name="target_pid">PID i synuar: %s</string>
|
||||||
<string name="selinux_context">Konteksti SELinux: %s</string>
|
<string name="selinux_context">Konteksti SELinux: %s</string>
|
||||||
<string name="supp_group">Grupi suplementar: %s</string>
|
<string name="supp_group">Grupi shtesë: %s</string>
|
||||||
|
|
||||||
<!--MagiskHide-->
|
<!--MagiskHide-->
|
||||||
<string name="show_system_app">Shfaq aplikacionet e sistemit</string>
|
<string name="show_system_app">Shfaq aplikacionet e sistemit</string>
|
||||||
<string name="show_os_app">Shfaq aplikacionet e sistemit operativ</string>
|
<string name="show_os_app">Shfaq aplikacionet e OS</string>
|
||||||
<string name="hide_filter_hint">Kërko sipas emrit</string>
|
<string name="hide_filter_hint">Filtro sipas emrit</string>
|
||||||
<string name="hide_search">Kërko</string>
|
<string name="hide_search">Kërko</string>
|
||||||
|
|
||||||
<!--Module-->
|
<!--Module-->
|
||||||
<string name="no_info_provided">(Nuk ka asnjë informacion)</string>
|
<string name="no_info_provided">(Nuk u dha informacion)</string>
|
||||||
<string name="reboot_userspace">Rinisje e shpejtë</string>
|
<string name="reboot_userspace">Rinisje Normale</string>
|
||||||
<string name="reboot_recovery">Rinis te Recovery</string>
|
<string name="reboot_recovery">Rinis në Recovery</string>
|
||||||
<string name="reboot_bootloader">Rinis te Bootloader</string>
|
<string name="reboot_bootloader">Rinis në Bootloader</string>
|
||||||
<string name="reboot_download">Rinis te Download</string>
|
<string name="reboot_download">Rinis në Download</string>
|
||||||
<string name="reboot_edl">Rinis te EDL</string>
|
<string name="reboot_edl">Rinis në EDL</string>
|
||||||
<string name="reboot_safe_mode">Rinis në safe mode</string>
|
<string name="reboot_safe_mode">Mënyra e sigurt</string>
|
||||||
<string name="module_version_author">%1$s nga %2$s</string>
|
<string name="module_version_author">%1$s nga %2$s</string>
|
||||||
<string name="module_state_remove">Hiqe</string>
|
<string name="module_state_remove">Hiqe</string>
|
||||||
<string name="module_action">Veprim</string>
|
<string name="module_action">Veprimi</string>
|
||||||
<string name="module_state_restore">Rikëthe</string>
|
<string name="module_state_restore">Rikthe</string>
|
||||||
<string name="module_action_install_external">Instaloni nga sdcard</string>
|
<string name="module_action_install_external">Instalo nga memoria</string>
|
||||||
<string name="update_available">Përditësimi në dispozicion</string>
|
<string name="update_available">Përditësim i disponueshëm</string>
|
||||||
<string name="suspend_text_riru">Moduli u pezullua sepse %1$s është aktivizuar</string>
|
<string name="suspend_text_riru">Moduli u pezullua sepse %1$s është aktiv</string>
|
||||||
<string name="suspend_text_zygisk">Moduli është pezulluar sepse %1$s nuk është i aktivizuar</string>
|
<string name="suspend_text_zygisk">Moduli u pezullua sepse %1$s nuk është aktiv</string>
|
||||||
<string name="zygisk_module_unloaded">Moduli Zygisk nuk është ngarkuar për shkak të papajtueshmërisë</string>
|
<string name="zygisk_module_unloaded">Moduli Zygisk nuk u ngarkua për shkak të mospërputhjes</string>
|
||||||
<string name="module_empty">Ska module të instaluar</string>
|
<string name="module_empty">Nuk ka module të instaluara</string>
|
||||||
<string name="confirm_install">Të instalohet moduli %1$s?</string>
|
<string name="confirm_install">Të instalohet moduli %1$s?</string>
|
||||||
<string name="confirm_install_title">Konfirmo instalimin</string>
|
<string name="confirm_install_title">Konfirmim instalimi</string>
|
||||||
|
|
||||||
<!--Settings-->
|
<!--Settings-->
|
||||||
<string name="settings_dark_mode_title">Mënyra e temës</string>
|
<string name="settings_dark_mode_title">Mënyra e temës</string>
|
||||||
<string name="settings_dark_mode_message">Zgjidhni mënyrën që i përshtatet më shumë stilit tuaj!</string>
|
<string name="settings_dark_mode_message">Zgjidh mënyrën që i përshtatet më shumë stilit tënd!</string>
|
||||||
<string name="settings_dark_mode_light">Gjithmonë e bardhë</string>
|
<string name="settings_dark_mode_light">Gjithmonë e ndritshme</string>
|
||||||
<string name="settings_dark_mode_system">Sipas sistemit</string>
|
<string name="settings_dark_mode_system">Ndiq sistemin</string>
|
||||||
<string name="settings_dark_mode_dark">Gjithmonë e zezë</string>
|
<string name="settings_dark_mode_dark">Gjithmonë e errët</string>
|
||||||
<string name="settings_download_path_title">Vendodhje e shkarkimit</string>
|
<string name="settings_download_path_title">Rruga e shkarkimit</string>
|
||||||
<string name="settings_download_path_message">Shkarkimet do të ruhen në %1$s</string>
|
<string name="settings_download_path_message">Skedarët do të ruhen në %1$s</string>
|
||||||
<string name="settings_hide_app_title">Fsheh aplikacionin Magisk</string>
|
<string name="settings_hide_app_title">Fshi aplikacionin Magisk</string>
|
||||||
<string name="settings_hide_app_summary">Instaloni një aplikacion përfaqësues me ID të paketës të rastësishme dhe etiketë të personalizuar të aplikacionitl</string>
|
<string name="settings_hide_app_summary">Instalo një aplikacion proxy me një ID pakete të rastësishme dhe emër të personalizuar</string>
|
||||||
<string name="settings_restore_app_title">Rivendosni aplikacionin Magisk</string>
|
<string name="settings_restore_app_title">Rikthe aplikacionin Magisk</string>
|
||||||
<string name="settings_restore_app_summary">un-fsheh aplikacionin dhe riktheni atë në APK origjinale</string>
|
<string name="settings_restore_app_summary">Zbulo aplikacionin dhe rikthe APK-në origjinale</string>
|
||||||
<string name="language">Gjuha</string>
|
<string name="language">Gjuha</string>
|
||||||
<string name="system_default">(Parazgjedhja e sistemit)</string>
|
<string name="system_default">(Parazgjedhja e sistemit)</string>
|
||||||
<string name="settings_check_update_title">Kontrollo për përditësime</string>
|
<string name="settings_check_update_title">Kontrollo për përditësime</string>
|
||||||
<string name="settings_check_update_summary">Kontrolloni automatikisht për përditësime në sfond</string>
|
<string name="settings_check_update_summary">Kontrollo periodikisht për përditësimet në sfond</string>
|
||||||
<string name="settings_update_channel_title">Perditeso kanalin</string>
|
<string name="settings_update_channel_title">Kanal për përditësime</string>
|
||||||
<string name="settings_update_stable">E qëndrueshme</string>
|
<string name="settings_update_stable">Stable</string>
|
||||||
<string name="settings_update_beta">Beta</string>
|
<string name="settings_update_beta">Beta</string>
|
||||||
<string name="settings_update_custom">Kanal me porosi</string>
|
<string name="settings_update_debug">Debug</string>
|
||||||
<string name="settings_update_custom_msg">Fut një URL të personalizuar</string>
|
<string name="settings_update_custom">Custom</string>
|
||||||
<string name="settings_zygisk_summary">Drejtoni pjesë të Magisk në demonin zygote</string>
|
<string name="settings_update_custom_msg">Fut një URL të personalizuar të kanalit</string>
|
||||||
<string name="settings_denylist_title">Zbato Listën e Mohimit</string>
|
<string name="settings_zygisk_summary">Ekzekuto pjesë të Magisk në demonin Zygote</string>
|
||||||
<string name="settings_denylist_summary">Proceset në listën e mohimit do të kenë të gjitha modifikimet e Magisk</string>
|
<string name="settings_denylist_title">Zbato listën e ndaluar</string>
|
||||||
<string name="settings_denylist_config_title">Konfiguro Listën e Mohimit</string>
|
<string name="settings_denylist_summary">Proceset në listën e ndaluar do të rikthehen pa modifikimet e Magisk</string>
|
||||||
<string name="settings_denylist_config_summary">Zgjidhni proceset që do të përfshihen në listën e mohimit</string>
|
<string name="settings_denylist_config_title">Konfiguro listën e ndaluar</string>
|
||||||
<string name="settings_hosts_title">Pritësit pa sistem</string>
|
<string name="settings_denylist_config_summary">Zgjidh proceset që do të përfshihen në listën e ndaluar</string>
|
||||||
<string name="settings_hosts_summary">Pritësit pa sistem mbështesin aplikacionet Adblock</string>
|
<string name="settings_hosts_title">Systemless hosts</string>
|
||||||
<string name="settings_hosts_toast">Moduli i hosteve pa sistem u shtua</string>
|
<string name="settings_hosts_summary">Mbështetje për systemless hosts për aplikacionet që bllokojnë reklamat</string>
|
||||||
<string name="settings_app_name_hint">Emri i ri</string>
|
<string name="settings_hosts_toast">U shtua moduli systemless hosts</string>
|
||||||
<string name="settings_app_name_helper">Aplikacioni do të ripaketohet me këtë emër</string>
|
<string name="settings_app_name_hint">Emër i ri</string>
|
||||||
|
<string name="settings_app_name_helper">Aplikacioni do të ripaketizohet me këtë emër</string>
|
||||||
<string name="settings_app_name_error">Format i pavlefshëm</string>
|
<string name="settings_app_name_error">Format i pavlefshëm</string>
|
||||||
<string name="settings_su_app_adb">Aplikacionet dhe ADB</string>
|
<string name="settings_su_app_adb">Aplikacionet dhe ADB</string>
|
||||||
<string name="settings_su_app">Vetëm aplikacionet</string>
|
<string name="settings_su_app">Vetëm aplikacionet</string>
|
||||||
<string name="settings_su_adb">Vetëm ADB</string>
|
<string name="settings_su_adb">Vetëm ADB</string>
|
||||||
<string name="settings_su_disable">Çaktivizuar</string>
|
<string name="settings_su_disable">Çaktivizuar</string>
|
||||||
<string name="settings_su_request_10">10 Sekonda</string>
|
<string name="settings_su_request_10">10 sekonda</string>
|
||||||
<string name="settings_su_request_15">15 Sekonda</string>
|
<string name="settings_su_request_15">15 sekonda</string>
|
||||||
<string name="settings_su_request_20">20 Sekonda</string>
|
<string name="settings_su_request_20">20 sekonda</string>
|
||||||
<string name="settings_su_request_30">30 Sekonda</string>
|
<string name="settings_su_request_30">30 sekonda</string>
|
||||||
<string name="settings_su_request_45">45 Sekonda</string>
|
<string name="settings_su_request_45">45 sekonda</string>
|
||||||
<string name="settings_su_request_60">60 Sekonda</string>
|
<string name="settings_su_request_60">60 sekonda</string>
|
||||||
<string name="superuser_access">Aksesi i Super-përdorues</string>
|
<string name="superuser_access">Akses Superuser</string>
|
||||||
<string name="auto_response">Përgjigje automatike</string>
|
<string name="auto_response">Përgjigje automatike</string>
|
||||||
<string name="request_timeout">Koha për mbarimit të Kërkesës</string>
|
<string name="request_timeout">Koha e skadimit të kërkesës</string>
|
||||||
<string name="superuser_notification">Njoftimi i Super-përdoruesit</string>
|
<string name="superuser_notification">Njoftimi Superuser</string>
|
||||||
<string name="settings_su_reauth_title">Ri-vërtetimi pas azhurnimit</string>
|
<string name="settings_su_reauth_title">Riautentifikimi pas përditësimit</string>
|
||||||
<string name="settings_su_reauth_summary">Ri-vërtetoni lejet e super-përdoruesit pas azhurnimit të aplikacionit</string>
|
<string name="settings_su_reauth_summary">Kërko sërish lejet Superuser pas përditësimit të aplikacioneve</string>
|
||||||
<string name="settings_su_tapjack_title">Aktivizo mbrojtjen tapjacking</string>
|
<string name="settings_su_tapjack_title">Mbrojtje nga mbivendosja e klikimeve</string>
|
||||||
<string name="settings_su_tapjack_summary">Dialogu i menjëhershëm i super-përdoruesit nuk do ti përgjigjet hyrjes ndërsa është i errësuar nga ndonjë dritare ose mbivendosje tjetër</string>
|
<string name="settings_su_tapjack_summary">Dritarja e kërkesës Superuser nuk do të pranojë input kur është e mbuluar nga ndonjë dritare tjetër</string>
|
||||||
|
<string name="settings_su_auth_title">Autentifikimi i përdoruesit</string>
|
||||||
|
<string name="settings_su_auth_summary">Kërko autentifikim të përdoruesit gjatë kërkesave Superuser</string>
|
||||||
|
<string name="settings_su_auth_insecure">Nuk ka asnjë metodë autentifikimi të konfiguruar në pajisje</string>
|
||||||
|
<string name="settings_su_restrict_title">Kufizo aftësitë e root</string>
|
||||||
|
<string name="settings_su_restrict_summary">Do të kufizojë aplikacionet e reja Superuser si parazgjedhje. Kujdes: kjo mund të prishë shumicën e aplikacioneve. Mos e aktivizoni nëse nuk dini çfarë bëni.</string>
|
||||||
<string name="settings_customization">Personalizimi</string>
|
<string name="settings_customization">Personalizimi</string>
|
||||||
<string name="setting_add_shortcut_summary">Shtoni një shkurtore mjaft të mirë në ekranin fillestar në rast se emri dhe ikona janë të vështira për tu njohur pasi keni fshehur aplikacionin</string>
|
<string name="setting_add_shortcut_summary">Shto një shkurtore në ekranin bazë nëse emri/ikona bëhen të vështira për t’u dalluar pas fshehjes së aplikacionit</string>
|
||||||
<string name="settings_doh_title">DNS mbi HTTPS</string>
|
<string name="settings_doh_title">DNS mbi HTTPS</string>
|
||||||
<string name="settings_doh_description">Helmimi i paqartë nga DNS në disa kombe</string>
|
<string name="settings_doh_description">Zgjidhje për helmimin e DNS në disa shtete</string>
|
||||||
<string name="multiuser_mode">Mënyra Multi-përdoruesit</string>
|
<string name="settings_random_name_title">Emër i rastësishëm</string>
|
||||||
<string name="settings_owner_only">Vetëm pronari i paisjes</string>
|
<string name="settings_random_name_description">Rastësizo emrin e skedarit të daljes për imazhet e patch-uara dhe skedarët tar për të shmangur detektimin</string>
|
||||||
<string name="settings_owner_manage">Pronari i paisjes që e manaxhon</string>
|
<string name="multiuser_mode">Mënyra multi-përdorues</string>
|
||||||
<string name="settings_user_independent">I pavarur nga përdoruesi</string>
|
<string name="settings_owner_only">Vetëm pronari i pajisjes</string>
|
||||||
<string name="owner_only_summary">Vetëm pronari ka akses në rrënjë</string>
|
<string name="settings_owner_manage">Menaxhuar nga pronari</string>
|
||||||
<string name="owner_manage_summary">Vetëm pronari mund të menaxhojë aksesin në rrënjë dhe të marrë kërkesat</string>
|
<string name="settings_user_independent">I pavarur për përdoruesit</string>
|
||||||
<string name="user_independent_summary">Çdo përdorues ka rregullat e veta të veçanta rrënjësore</string>
|
<string name="owner_only_summary">Vetëm pronari ka akses root</string>
|
||||||
<string name="mount_namespace_mode">Mënyra e Montimit të Hapësirës Emërore</string>
|
<string name="owner_manage_summary">Vetëm pronari mund të menaxhojë aksesin root dhe të marrë kërkesat</string>
|
||||||
<string name="settings_ns_global">Hapësira globale e emrave</string>
|
<string name="user_independent_summary">Çdo përdorues ka rregullat e veta të root</string>
|
||||||
<string name="settings_ns_requester">Trashëgoni hapësirën e emrave</string>
|
<string name="mount_namespace_mode">Mënyra e mount namespace</string>
|
||||||
<string name="settings_ns_isolate">Hapësira e izoluar e emrave</string>
|
<string name="settings_ns_global">Namespace global</string>
|
||||||
<string name="global_summary">Të gjitha sesionet rrënjë përdorin hapësirën globale të emrave të montimit</string>
|
<string name="settings_ns_requester">Trashëgo namespace</string>
|
||||||
<string name="requester_summary">Seancat rrënjësore do të trashëgojnë hapësirën e emrave të kërkuesit të tyre</string>
|
<string name="settings_ns_isolate">Namespace i izoluar</string>
|
||||||
<string name="isolate_summary">Çdo sesion rrënjë do të ketë hapësirën e vet të izoluar të emrave</string>
|
<string name="global_summary">Të gjitha sesionet root përdorin namespace global</string>
|
||||||
<string name="settings_su_auth_title">Vërtetimi i përdoruesit</string>
|
<string name="requester_summary">Sesioni root trashëgon namespace-in e kërkuesit</string>
|
||||||
<string name="settings_su_auth_summary">Kërkoni vërtetimin e përdoruesit gjatë kërkesave të Superpërdoruesit</string>
|
<string name="isolate_summary">Çdo sesion root do të ketë namespace të izoluar</string>
|
||||||
<string name="settings_su_auth_insecure">Asnjë metodë vërtetimi nuk është konfiguruar në pajisje</string>
|
|
||||||
|
|
||||||
<!--Notifications-->
|
<!--Notifications-->
|
||||||
<string name="update_channel">Përditësimet e magisk</string>
|
<string name="update_channel">Përditësimet e Magisk</string>
|
||||||
<string name="updated_channel">Përditësimi përfundoi</string>
|
|
||||||
<string name="progress_channel">Njoftimet e progresit</string>
|
<string name="progress_channel">Njoftimet e progresit</string>
|
||||||
|
<string name="updated_channel">Përditësimi përfundoi</string>
|
||||||
<string name="download_complete">Shkarkimi përfundoi</string>
|
<string name="download_complete">Shkarkimi përfundoi</string>
|
||||||
<string name="download_file_error">Gabim në shkarkimin e skedarit</string>
|
<string name="download_file_error">Gabim gjatë shkarkimit të skedarit</string>
|
||||||
<string name="magisk_update_title">Përditësimi Magisk i disponueshëm!</string>
|
<string name="magisk_update_title">Përditësim i ri i Magisk!</string>
|
||||||
<string name="updated_title">Magisk u përditësua</string>
|
<string name="updated_title">Magisk u përditësua</string>
|
||||||
<string name="updated_text">Prekni për të hapur aplikacionin</string>
|
<string name="updated_text">Shtypni për të hapur aplikacionin</string>
|
||||||
|
|
||||||
<!--Toasts, Dialogs-->
|
<!--Toasts, Dialogs-->
|
||||||
<string name="yes">Po</string>
|
<string name="yes">Po</string>
|
||||||
<string name="no">Jo</string>
|
<string name="no">Jo</string>
|
||||||
<string name="repo_install_title">Instalo %1$s %2$s(%3$d)</string>
|
<string name="repo_install_title">Instalo %1$s %2$s(%3$d)</string>
|
||||||
<string name="download">Shkarko</string>
|
<string name="download">Shkarko</string>
|
||||||
<string name="reboot">Rinis</string>
|
<string name="reboot">Rinise</string>
|
||||||
<string name="close">Mbylle</string>
|
<string name="close">Mbyll</string>
|
||||||
<string name="release_notes">Shënimet e lëshimit</string>
|
<string name="release_notes">Shënimet e versionit</string>
|
||||||
<string name="flashing">Duke flashuar…</string>
|
<string name="flashing">Duke flashuar..</string>
|
||||||
<string name="running">Duke vepruar...</string>
|
<string name="running">Duke u ekzekutuar..</string>
|
||||||
<string name="done">U krye!</string>
|
<string name="done">U krye!</string>
|
||||||
<string name="done_action">Veprimi i ekzekutimit të %1$s u krye</string>
|
<string name="done_action">Veprimi i %1$s u krye</string>
|
||||||
<string name="failure">Dështoi!</string>
|
<string name="failure">Dështoi!</string>
|
||||||
<string name="hide_app_title">Fshehja e aplikacionit Magisk…</string>
|
<string name="hide_app_title">Duke fshehur aplikacionin Magisk..</string>
|
||||||
<string name="open_link_failed_toast">Nuk u gjet asnjë aplikacion për të hapur lidhjen</string>
|
<string name="open_link_failed_toast">Nuk u gjet asnjë aplikacion për të hapur lidhjen</string>
|
||||||
<string name="complete_uninstall">Çinstalimi i plotë</string>
|
<string name="complete_uninstall">Çinstalim i plotë</string>
|
||||||
<string name="restore_img">Rivendosni imazhet</string>
|
<string name="restore_img">Rikthe imazhet</string>
|
||||||
<string name="restore_img_msg">Duke rivendosur…</string>
|
<string name="restore_img_msg">Duke rikthyer..</string>
|
||||||
<string name="restore_done">Rivendosja u krye!</string>
|
<string name="restore_done">Rikthimi u krye!</string>
|
||||||
<string name="restore_fail">Rezervimi i aksioneve nuk ekziston!</string>
|
<string name="restore_fail">Backup-i origjinal nuk ekziston!</string>
|
||||||
<string name="setup_fail">Konfigurimi dështoi</string>
|
<string name="setup_fail">Konfigurimi dështoi</string>
|
||||||
<string name="env_fix_title">Kërkon Konfigurim shtesë</string>
|
<string name="env_fix_title">Kërkohet konfigurim shtesë</string>
|
||||||
<string name="env_fix_msg">Pajisja juaj ka nevojë për konfigurim shtesë që Magisk të funksionojë siç duhet. Dëshironi të vazhdoni dhe rindizni?</string>
|
<string name="env_fix_msg">Pajisja ka nevojë për konfigurim shtesë që Magisk të funksionojë si duhet. Dëshironi të vazhdoni dhe të rinisni pajisjen?</string>
|
||||||
<string name="env_full_fix_msg">Pajisja juaj ka nevojë për re-flashuar Magisk që të funksionojë siç duhet. Ju lutemi ri-instaloni Magisk brenda aplikacionit, modaliteti i rikuperimit nuk mund të marrë informacionin e saktë të pajisjes.</string>
|
<string name="env_full_fix_msg">Pajisja ka nevojë për ri-flash të Magisk për të funksionuar saktë. Ju lutemi riinstaloni Magisk brenda aplikacionit; Recovery nuk mund të marrë informacionet e sakta të pajisjes.</string>
|
||||||
<string name="setup_msg">Konfigurimi i mjedisit të funksionimit…</string>
|
<string name="setup_msg">Duke ekzekutuar konfigurimin e mjedisit..</string>
|
||||||
<string name="unsupport_magisk_title">Version Magjik i Pambështetur</string>
|
<string name="unsupport_magisk_title">Version i Magisk i pambështetur</string>
|
||||||
<string name="unsupport_magisk_msg">Ky version i aplikacionit nuk e mbështet versionin Magisk më të ulët se %1$s.\n\nAplikacioni do të sillet sikur të mos jetë i instaluar Magisk, ju lutemi azhurnoni Magisk sa më shpejt të jetë e mundur.</string>
|
<string name="unsupport_magisk_msg">Ky version i aplikacionit nuk mbështet versione të Magisk më të ulëta se %1$s.
|
||||||
|
|
||||||
|
Aplikacioni do të sillet sikur Magisk nuk është i instaluar. Ju lutemi përditësoni Magisk sa më shpejt të jetë e mundur.</string>
|
||||||
<string name="unsupport_general_title">Gjendje jonormale</string>
|
<string name="unsupport_general_title">Gjendje jonormale</string>
|
||||||
<string name="unsupport_system_app_msg">Drejtimi i këtij aplikacioni si një aplikacion sistemi nuk mbështetet. Ju lutemi kthejeni aplikacionin në një aplikacion përdoruesi.</string>
|
<string name="unsupport_system_app_msg">Ekzekutimi i këtij aplikacioni si aplikacion sistemi nuk mbështetet. Ju lutemi kthejeni në aplikacion përdoruesi.</string>
|
||||||
<string name="unsupport_other_su_msg">Një komandë \"su"\ që nuk i përket Magisk është zbuluar. Ju lutemi hiqni SU-në tjetër të pambështetur.</string>
|
<string name="unsupport_other_su_msg">Është zbuluar një binar "su" që nuk është nga Magisk. Ju lutemi hiqni çdo zgjidhje tjetër root dhe/ose riinstaloni Magisk.</string>
|
||||||
<string name="unsupport_external_storage_msg">Magisk është instaluar në ruajtjen e jashtme. Ju lutemi zhvendosni aplikacionin në ruajtjen e brendshme.</string>
|
<string name="unsupport_external_storage_msg">Magisk është instaluar në memorien e jashtme. Lëvizni aplikacionin në memorien e brendshme.</string>
|
||||||
<string name="unsupport_nonroot_stub_msg">Aplikacioni nuk mund të vazhdojë të punojë në gjendjen e fshehur pasi rrënja ishte e humbur. Ju lutemi rivendoseni përsëri në APK-në origjinale.</string>
|
<string name="unsupport_nonroot_stub_msg">Aplikacioni i fshehur i Magisk nuk mund të vazhdojë të funksionojë sepse root u humb. Ju lutemi riktheni APK-në origjinale.</string>
|
||||||
<string name="unsupport_nonroot_stub_title">@string/settings_restore_app_title</string>
|
<string name="unsupport_nonroot_stub_title">@string/settings_restore_app_title</string>
|
||||||
<string name="external_rw_permission_denied">Jepni lejen e ruajtjes për të aktivizuar këtë funksion</string>
|
<string name="external_rw_permission_denied">Jepni lejen e magazinimit për të aktivizuar këtë funksion</string>
|
||||||
<string name="post_notifications_denied">Jepni lejen e njoftimeve për të aktivizuar këtë funksion</string>
|
<string name="post_notifications_denied">Jepni lejen e njoftimeve për të aktivizuar këtë funksion</string>
|
||||||
<string name="install_unknown_denied">Lejo "instaloni aplikacione të panjohura" për të aktivizuar këtë funksion</string>
|
<string name="install_unknown_denied">Lejoni "Instalo aplikacione të panjohura" për të aktivizuar këtë funksion</string>
|
||||||
<string name="add_shortcut_title">Shto shkurtore në ekranin bazë</string>
|
<string name="add_shortcut_title">Shto shkurtore në ekranin bazë</string>
|
||||||
<string name="add_shortcut_msg">Pas fshehjes së këtij aplikacioni, emri dhe ikona e tij mund të bëhen të vështira për tu njohur. Dëshironi të shtoni një shkurtore mjaft të bukur në ekranin bazë?</string>
|
<string name="add_shortcut_msg">Pas fshehjes së aplikacionit, emri dhe ikona mund të jenë të vështira për t’u njohur. Dëshironi të shtoni një shkurtore të bukur në ekranin bazë?</string>
|
||||||
<string name="app_not_found">Asnjë aplikacion nuk u gjet për të trajtuar këtë veprim</string>
|
<string name="app_not_found">Nuk u gjet aplikacion për të kryer këtë veprim</string>
|
||||||
<string name="reboot_apply_change">Rinisni për të aplikuar ndryshimet</string>
|
<string name="reboot_apply_change">Rinisni për të aplikuar ndryshimet</string>
|
||||||
<string name="restore_app_confirmation">Kjo do të rivendosë aplikacionin e fshehur në aplikacionin origjinal. A dëshironi vërtet ta bëni këtë?</string>
|
<string name="restore_app_confirmation">Kjo do të rikthejë aplikacionin e fshehur në gjendjen origjinale. Jeni të sigurt që dëshironi ta bëni këtë?</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -30,4 +30,4 @@ android.nonFinalResIds=false
|
|||||||
|
|
||||||
# Magisk
|
# Magisk
|
||||||
magisk.stubVersion=40
|
magisk.stubVersion=40
|
||||||
magisk.versionCode=30500
|
magisk.versionCode=30600
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
# Magisk Changelog
|
# Magisk Changelog
|
||||||
|
|
||||||
|
### v30.6 (2025.12.1)
|
||||||
|
|
||||||
|
- [MagiskInit] Revert a change that could result in bootloops
|
||||||
|
|
||||||
### v30.5 (2025.12.1)
|
### v30.5 (2025.12.1)
|
||||||
|
|
||||||
- [General] Improve commandline argument parsing logic
|
- [General] Improve commandline argument parsing logic
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ pb-rs = { git = "https://github.com/topjohnwu/quick-protobuf.git" }
|
|||||||
quick-protobuf = { git = "https://github.com/topjohnwu/quick-protobuf.git" }
|
quick-protobuf = { git = "https://github.com/topjohnwu/quick-protobuf.git" }
|
||||||
lz4-sys = { path = "external/lz4-sys" }
|
lz4-sys = { path = "external/lz4-sys" }
|
||||||
|
|
||||||
|
[workspace.lints.clippy]
|
||||||
|
unwrap_used = "deny"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
opt-level = "z"
|
opt-level = "z"
|
||||||
lto = "thin"
|
lto = "thin"
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ path = "lib.rs"
|
|||||||
[features]
|
[features]
|
||||||
selinux = []
|
selinux = []
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cxx-gen = { workspace = true }
|
cxx-gen = { workspace = true }
|
||||||
|
|
||||||
|
|||||||
@@ -132,13 +132,9 @@ impl PositionalArgParser<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_end(&mut self) -> Result<(), EarlyExit> {
|
fn ensure_end(&mut self) -> Result<(), EarlyExit> {
|
||||||
if self.0.len() == 0 {
|
match self.0.next() {
|
||||||
Ok(())
|
None => Ok(()),
|
||||||
} else {
|
Some(s) => Err(EarlyExit::from(format!("Unrecognized argument: {s}\n"))),
|
||||||
Err(EarlyExit::from(format!(
|
|
||||||
"Unrecognized argument: {}\n",
|
|
||||||
self.0.next().unwrap()
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ edition.workspace = true
|
|||||||
crate-type = ["staticlib"]
|
crate-type = ["staticlib"]
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cxx-gen = { workspace = true }
|
cxx-gen = { workspace = true }
|
||||||
pb-rs = { workspace = true }
|
pb-rs = { workspace = true }
|
||||||
|
|||||||
@@ -53,6 +53,19 @@ static bool check_env(const char *name) {
|
|||||||
return val != nullptr && val == "true"sv;
|
return val != nullptr && val == "true"sv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool guess_lzma(const uint8_t *buf, size_t len) {
|
||||||
|
// 0 : (pb * 5 + lp) * 9 + lc
|
||||||
|
// 1 - 4 : dict size, must be 2^n
|
||||||
|
// 5 - 12: all 0xFF
|
||||||
|
if (len <= 13) return false;
|
||||||
|
if (memcmp(buf, "\x5d", 1) != 0) return false;
|
||||||
|
uint32_t dict_sz = 0;
|
||||||
|
memcpy(&dict_sz, buf + 1, sizeof(dict_sz));
|
||||||
|
if (dict_sz == 0 || (dict_sz & (dict_sz - 1)) != 0) return false;
|
||||||
|
if (memcmp(buf + 5, "\xff\xff\xff\xff\xff\xff\xff\xff", 8) != 0) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
FileFormat check_fmt(const void *buf, size_t len) {
|
FileFormat check_fmt(const void *buf, size_t len) {
|
||||||
if (CHECKED_MATCH(CHROMEOS_MAGIC)) {
|
if (CHECKED_MATCH(CHROMEOS_MAGIC)) {
|
||||||
return FileFormat::CHROMEOS;
|
return FileFormat::CHROMEOS;
|
||||||
@@ -66,8 +79,7 @@ FileFormat check_fmt(const void *buf, size_t len) {
|
|||||||
return FileFormat::LZOP;
|
return FileFormat::LZOP;
|
||||||
} else if (CHECKED_MATCH(XZ_MAGIC)) {
|
} else if (CHECKED_MATCH(XZ_MAGIC)) {
|
||||||
return FileFormat::XZ;
|
return FileFormat::XZ;
|
||||||
} else if (len >= 13 && memcmp(buf, "\x5d\x00\x00", 3) == 0
|
} else if (guess_lzma(static_cast<const uint8_t *>(buf), len)) {
|
||||||
&& (((char *)buf)[12] == '\xff' || ((char *)buf)[12] == '\x00')) {
|
|
||||||
return FileFormat::LZMA;
|
return FileFormat::LZMA;
|
||||||
} else if (CHECKED_MATCH(BZIP_MAGIC)) {
|
} else if (CHECKED_MATCH(BZIP_MAGIC)) {
|
||||||
return FileFormat::BZIP2;
|
return FileFormat::BZIP2;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use crate::codegen::gen_cxx_binding;
|
|||||||
#[path = "../include/codegen.rs"]
|
#[path = "../include/codegen.rs"]
|
||||||
mod codegen;
|
mod codegen;
|
||||||
|
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("cargo:rerun-if-changed=proto/update_metadata.proto");
|
println!("cargo:rerun-if-changed=proto/update_metadata.proto");
|
||||||
|
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ Supported actions:
|
|||||||
dumped to the file 'header', which can be used to modify header
|
dumped to the file 'header', which can be used to modify header
|
||||||
configurations during repacking.
|
configurations during repacking.
|
||||||
Return values:
|
Return values:
|
||||||
0:valid 1:error 2:chromeos
|
0:valid 1:error 2:chromeos 3:vendor_boot
|
||||||
|
|
||||||
repack [-n] <origbootimg> [outbootimg]
|
repack [-n] <origbootimg> [outbootimg]
|
||||||
Repack boot image components using files from the current directory
|
Repack boot image components using files from the current directory
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
use crate::ffi::{FileFormat, check_fmt};
|
use crate::ffi::{FileFormat, check_fmt};
|
||||||
use base::nix::fcntl::OFlag;
|
use base::nix::fcntl::OFlag;
|
||||||
use base::{
|
use base::{Chunker, FileOrStd, LoggedResult, ReadExt, Utf8CStr, Utf8CString, WriteExt, log_err};
|
||||||
Chunker, FileOrStd, LoggedResult, ReadExt, ResultExt, Utf8CStr, Utf8CString, WriteExt, log_err,
|
|
||||||
};
|
|
||||||
use bzip2::Compression as BzCompression;
|
use bzip2::Compression as BzCompression;
|
||||||
use bzip2::read::BzDecoder;
|
use bzip2::read::BzDecoder;
|
||||||
use bzip2::write::BzEncoder;
|
use bzip2::write::BzEncoder;
|
||||||
@@ -218,16 +216,21 @@ impl<R: Read> Read for LZ4BlockDecoder<R> {
|
|||||||
|
|
||||||
// Top-level APIs
|
// Top-level APIs
|
||||||
|
|
||||||
pub fn get_encoder<'a, W: Write + 'a>(format: FileFormat, w: W) -> Box<dyn WriteFinish<W> + 'a> {
|
pub fn get_encoder<'a, W: Write + 'a>(
|
||||||
match format {
|
format: FileFormat,
|
||||||
|
w: W,
|
||||||
|
) -> std::io::Result<Box<dyn WriteFinish<W> + 'a>> {
|
||||||
|
Ok(match format {
|
||||||
FileFormat::XZ => {
|
FileFormat::XZ => {
|
||||||
let mut opt = XzOptions::with_preset(9);
|
let mut opt = XzOptions::with_preset(9);
|
||||||
opt.set_check_sum_type(CheckType::Crc32);
|
opt.set_check_sum_type(CheckType::Crc32);
|
||||||
Box::new(XzWriter::new(w, opt).unwrap())
|
Box::new(XzWriter::new(w, opt)?)
|
||||||
}
|
|
||||||
FileFormat::LZMA => {
|
|
||||||
Box::new(LzmaWriter::new_use_header(w, &LzmaOptions::with_preset(9), None).unwrap())
|
|
||||||
}
|
}
|
||||||
|
FileFormat::LZMA => Box::new(LzmaWriter::new_use_header(
|
||||||
|
w,
|
||||||
|
&LzmaOptions::with_preset(9),
|
||||||
|
None,
|
||||||
|
)?),
|
||||||
FileFormat::BZIP2 => Box::new(BzEncoder::new(w, BzCompression::best())),
|
FileFormat::BZIP2 => Box::new(BzEncoder::new(w, BzCompression::best())),
|
||||||
FileFormat::LZ4 => {
|
FileFormat::LZ4 => {
|
||||||
let encoder = LZ4FrameEncoderBuilder::new()
|
let encoder = LZ4FrameEncoderBuilder::new()
|
||||||
@@ -237,8 +240,7 @@ pub fn get_encoder<'a, W: Write + 'a>(format: FileFormat, w: W) -> Box<dyn Write
|
|||||||
.block_checksum(BlockChecksum::BlockChecksumEnabled)
|
.block_checksum(BlockChecksum::BlockChecksumEnabled)
|
||||||
.level(9)
|
.level(9)
|
||||||
.auto_flush(true)
|
.auto_flush(true)
|
||||||
.build(w)
|
.build(w)?;
|
||||||
.unwrap();
|
|
||||||
Box::new(encoder)
|
Box::new(encoder)
|
||||||
}
|
}
|
||||||
FileFormat::LZ4_LEGACY => Box::new(LZ4BlockEncoder::new(w, false)),
|
FileFormat::LZ4_LEGACY => Box::new(LZ4BlockEncoder::new(w, false)),
|
||||||
@@ -246,27 +248,30 @@ pub fn get_encoder<'a, W: Write + 'a>(format: FileFormat, w: W) -> Box<dyn Write
|
|||||||
FileFormat::ZOPFLI => {
|
FileFormat::ZOPFLI => {
|
||||||
// These options are already better than gzip -9
|
// These options are already better than gzip -9
|
||||||
let opt = ZopfliOptions {
|
let opt = ZopfliOptions {
|
||||||
iteration_count: NonZeroU64::new(1).unwrap(),
|
iteration_count: unsafe { NonZeroU64::new_unchecked(1) },
|
||||||
maximum_block_splits: 1,
|
maximum_block_splits: 1,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
Box::new(ZopFliEncoder::new_buffered(opt, BlockType::Dynamic, w).unwrap())
|
Box::new(ZopFliEncoder::new_buffered(opt, BlockType::Dynamic, w)?)
|
||||||
}
|
}
|
||||||
FileFormat::GZIP => Box::new(GzEncoder::new(w, GzCompression::best())),
|
FileFormat::GZIP => Box::new(GzEncoder::new(w, GzCompression::best())),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_decoder<'a, R: Read + 'a>(format: FileFormat, r: R) -> Box<dyn Read + 'a> {
|
pub fn get_decoder<'a, R: Read + 'a>(
|
||||||
match format {
|
format: FileFormat,
|
||||||
|
r: R,
|
||||||
|
) -> std::io::Result<Box<dyn Read + 'a>> {
|
||||||
|
Ok(match format {
|
||||||
FileFormat::XZ => Box::new(XzReader::new(r, true)),
|
FileFormat::XZ => Box::new(XzReader::new(r, true)),
|
||||||
FileFormat::LZMA => Box::new(LzmaReader::new_mem_limit(r, u32::MAX, None).unwrap()),
|
FileFormat::LZMA => Box::new(LzmaReader::new_mem_limit(r, u32::MAX, None)?),
|
||||||
FileFormat::BZIP2 => Box::new(BzDecoder::new(r)),
|
FileFormat::BZIP2 => Box::new(BzDecoder::new(r)),
|
||||||
FileFormat::LZ4 => Box::new(LZ4FrameDecoder::new(r).unwrap()),
|
FileFormat::LZ4 => Box::new(LZ4FrameDecoder::new(r)?),
|
||||||
FileFormat::LZ4_LG | FileFormat::LZ4_LEGACY => Box::new(LZ4BlockDecoder::new(r)),
|
FileFormat::LZ4_LG | FileFormat::LZ4_LEGACY => Box::new(LZ4BlockDecoder::new(r)),
|
||||||
FileFormat::ZOPFLI | FileFormat::GZIP => Box::new(MultiGzDecoder::new(r)),
|
FileFormat::ZOPFLI | FileFormat::GZIP => Box::new(MultiGzDecoder::new(r)),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// C++ FFI
|
// C++ FFI
|
||||||
@@ -274,9 +279,9 @@ pub fn get_decoder<'a, R: Read + 'a>(format: FileFormat, r: R) -> Box<dyn Read +
|
|||||||
pub fn compress_bytes(format: FileFormat, in_bytes: &[u8], out_fd: RawFd) {
|
pub fn compress_bytes(format: FileFormat, in_bytes: &[u8], out_fd: RawFd) {
|
||||||
let mut out_file = unsafe { ManuallyDrop::new(File::from_raw_fd(out_fd)) };
|
let mut out_file = unsafe { ManuallyDrop::new(File::from_raw_fd(out_fd)) };
|
||||||
|
|
||||||
let mut encoder = get_encoder(format, out_file.deref_mut());
|
|
||||||
let _: LoggedResult<()> = try {
|
let _: LoggedResult<()> = try {
|
||||||
encoder.write_all(in_bytes)?;
|
let mut encoder = get_encoder(format, out_file.deref_mut())?;
|
||||||
|
std::io::copy(&mut Cursor::new(in_bytes), encoder.deref_mut())?;
|
||||||
encoder.finish()?;
|
encoder.finish()?;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -284,8 +289,10 @@ pub fn compress_bytes(format: FileFormat, in_bytes: &[u8], out_fd: RawFd) {
|
|||||||
pub fn decompress_bytes(format: FileFormat, in_bytes: &[u8], out_fd: RawFd) {
|
pub fn decompress_bytes(format: FileFormat, in_bytes: &[u8], out_fd: RawFd) {
|
||||||
let mut out_file = unsafe { ManuallyDrop::new(File::from_raw_fd(out_fd)) };
|
let mut out_file = unsafe { ManuallyDrop::new(File::from_raw_fd(out_fd)) };
|
||||||
|
|
||||||
let mut decoder = get_decoder(format, in_bytes);
|
let _: LoggedResult<()> = try {
|
||||||
std::io::copy(decoder.as_mut(), out_file.deref_mut()).log_ok();
|
let mut decoder = get_decoder(format, in_bytes)?;
|
||||||
|
std::io::copy(decoder.as_mut(), out_file.deref_mut())?;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command-line entry points
|
// Command-line entry points
|
||||||
@@ -341,7 +348,7 @@ pub(crate) fn decompress_cmd(infile: &Utf8CStr, outfile: Option<&Utf8CStr>) -> L
|
|||||||
FileOrStd::File(outfile.create(OFlag::O_WRONLY | OFlag::O_TRUNC, 0o644)?)
|
FileOrStd::File(outfile.create(OFlag::O_WRONLY | OFlag::O_TRUNC, 0o644)?)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut decoder = get_decoder(format, Cursor::new(buf).chain(input.as_file()));
|
let mut decoder = get_decoder(format, Cursor::new(buf).chain(input.as_file()))?;
|
||||||
std::io::copy(decoder.as_mut(), &mut output.as_file())?;
|
std::io::copy(decoder.as_mut(), &mut output.as_file())?;
|
||||||
|
|
||||||
if rm_in {
|
if rm_in {
|
||||||
@@ -384,7 +391,7 @@ pub(crate) fn compress_cmd(
|
|||||||
FileOrStd::File(outfile)
|
FileOrStd::File(outfile)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut encoder = get_encoder(method, output.as_file());
|
let mut encoder = get_encoder(method, output.as_file())?;
|
||||||
std::io::copy(&mut input.as_file(), encoder.as_mut())?;
|
std::io::copy(&mut input.as_file(), encoder.as_mut())?;
|
||||||
encoder.finish()?;
|
encoder.finish()?;
|
||||||
|
|
||||||
|
|||||||
@@ -484,10 +484,9 @@ impl Cpio {
|
|||||||
};
|
};
|
||||||
for (name, entry) in &self.entries {
|
for (name, entry) in &self.entries {
|
||||||
let p = "/".to_string() + name.as_str();
|
let p = "/".to_string() + name.as_str();
|
||||||
if !p.starts_with(&path) {
|
let Some(p) = p.strip_prefix(&path) else {
|
||||||
continue;
|
continue;
|
||||||
}
|
};
|
||||||
let p = p.strip_prefix(&path).unwrap();
|
|
||||||
if !p.is_empty() && !p.starts_with('/') {
|
if !p.is_empty() && !p.starts_with('/') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -614,8 +613,11 @@ impl Cpio {
|
|||||||
o.rm(".backup", true);
|
o.rm(".backup", true);
|
||||||
self.rm(".backup", true);
|
self.rm(".backup", true);
|
||||||
|
|
||||||
let mut lhs = o.entries.into_iter().peekable();
|
let mut left_iter = o.entries.into_iter();
|
||||||
let mut rhs = self.entries.iter().peekable();
|
let mut right_iter = self.entries.iter();
|
||||||
|
|
||||||
|
let mut lhs = left_iter.next();
|
||||||
|
let mut rhs = right_iter.next();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
enum Action<'a> {
|
enum Action<'a> {
|
||||||
@@ -623,32 +625,38 @@ impl Cpio {
|
|||||||
Record(&'a String),
|
Record(&'a String),
|
||||||
Noop,
|
Noop,
|
||||||
}
|
}
|
||||||
let action = match (lhs.peek(), rhs.peek()) {
|
|
||||||
(Some((l, _)), Some((r, re))) => match l.as_str().cmp(r.as_str()) {
|
// Move the iterator forward if needed
|
||||||
|
if lhs.is_none() {
|
||||||
|
lhs = left_iter.next();
|
||||||
|
}
|
||||||
|
if rhs.is_none() {
|
||||||
|
rhs = right_iter.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
let action = match (lhs.take(), rhs.take()) {
|
||||||
|
(Some((ln, le)), Some((rn, re))) => match ln.as_str().cmp(rn.as_str()) {
|
||||||
Ordering::Less => {
|
Ordering::Less => {
|
||||||
let (l, le) = lhs.next().unwrap();
|
// Put rhs back
|
||||||
Action::Backup(l, le)
|
rhs = Some((rn, re));
|
||||||
|
Action::Backup(ln, le)
|
||||||
|
}
|
||||||
|
Ordering::Greater => {
|
||||||
|
// Put lhs back
|
||||||
|
lhs = Some((ln, le));
|
||||||
|
Action::Record(rn)
|
||||||
}
|
}
|
||||||
Ordering::Greater => Action::Record(rhs.next().unwrap().0),
|
|
||||||
Ordering::Equal => {
|
Ordering::Equal => {
|
||||||
let (l, le) = lhs.next().unwrap();
|
if re.data != le.data {
|
||||||
let action = if re.data != le.data {
|
Action::Backup(ln, le)
|
||||||
Action::Backup(l, le)
|
|
||||||
} else {
|
} else {
|
||||||
Action::Noop
|
Action::Noop
|
||||||
};
|
}
|
||||||
rhs.next();
|
|
||||||
action
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(Some(_), None) => {
|
(Some((ln, le)), None) => Action::Backup(ln, le),
|
||||||
let (l, le) = lhs.next().unwrap();
|
(None, Some((rn, _))) => Action::Record(rn),
|
||||||
Action::Backup(l, le)
|
(None, None) => break,
|
||||||
}
|
|
||||||
(None, Some(_)) => Action::Record(rhs.next().unwrap().0),
|
|
||||||
(None, None) => {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
match action {
|
match action {
|
||||||
Action::Backup(name, mut entry) => {
|
Action::Backup(name, mut entry) => {
|
||||||
@@ -691,8 +699,8 @@ impl CpioEntry {
|
|||||||
if self.mode & S_IFMT != S_IFREG {
|
if self.mode & S_IFMT != S_IFREG {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let mut encoder = get_encoder(FileFormat::XZ, Vec::new());
|
|
||||||
let Ok(data): std::io::Result<Vec<u8>> = (try {
|
let Ok(data): std::io::Result<Vec<u8>> = (try {
|
||||||
|
let mut encoder = get_encoder(FileFormat::XZ, Vec::new())?;
|
||||||
encoder.write_all(&self.data)?;
|
encoder.write_all(&self.data)?;
|
||||||
encoder.finish()?
|
encoder.finish()?
|
||||||
}) else {
|
}) else {
|
||||||
@@ -710,7 +718,7 @@ impl CpioEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let Ok(data): std::io::Result<Vec<u8>> = (try {
|
let Ok(data): std::io::Result<Vec<u8>> = (try {
|
||||||
let mut decoder = get_decoder(FileFormat::XZ, Cursor::new(&self.data));
|
let mut decoder = get_decoder(FileFormat::XZ, Cursor::new(&self.data))?;
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
std::io::copy(decoder.as_mut(), &mut data)?;
|
std::io::copy(decoder.as_mut(), &mut data)?;
|
||||||
data
|
data
|
||||||
|
|||||||
@@ -164,8 +164,8 @@ pub fn extract_boot_from_payload(
|
|||||||
out_file.seek(SeekFrom::Start(out_offset))?;
|
out_file.seek(SeekFrom::Start(out_offset))?;
|
||||||
let fmt = check_fmt(data);
|
let fmt = check_fmt(data);
|
||||||
|
|
||||||
let mut decoder = get_decoder(fmt, Cursor::new(data));
|
|
||||||
let Ok(_): std::io::Result<()> = (try {
|
let Ok(_): std::io::Result<()> = (try {
|
||||||
|
let mut decoder = get_decoder(fmt, Cursor::new(data))?;
|
||||||
std::io::copy(decoder.as_mut(), &mut out_file)?;
|
std::io::copy(decoder.as_mut(), &mut out_file)?;
|
||||||
}) else {
|
}) else {
|
||||||
return Err(bad_payload!("decompression failed"));
|
return Err(bad_payload!("decompression failed"));
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ check-signature = []
|
|||||||
check-client = []
|
check-client = []
|
||||||
su-check-db = []
|
su-check-db = []
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cxx-gen = { workspace = true }
|
cxx-gen = { workspace = true }
|
||||||
pb-rs = { workspace = true }
|
pb-rs = { workspace = true }
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ impl MagiskD {
|
|||||||
Command::new(&tmp_bb)
|
Command::new(&tmp_bb)
|
||||||
.arg("--install")
|
.arg("--install")
|
||||||
.arg("-s")
|
.arg("-s")
|
||||||
.arg(tmp_bb.parent_dir().unwrap())
|
.arg(tmp_bb.parent_dir().unwrap_or_default())
|
||||||
.stdout(Stdio::null())
|
.stdout(Stdio::null())
|
||||||
.stderr(Stdio::null())
|
.stderr(Stdio::null())
|
||||||
.status()
|
.status()
|
||||||
@@ -186,13 +186,13 @@ impl MagiskD {
|
|||||||
setup_preinit_dir();
|
setup_preinit_dir();
|
||||||
self.ensure_manager();
|
self.ensure_manager();
|
||||||
if self.zygisk_enabled.load(Ordering::Relaxed) {
|
if self.zygisk_enabled.load(Ordering::Relaxed) {
|
||||||
self.zygisk.lock().unwrap().reset(true);
|
self.zygisk.lock().reset(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn boot_stage_handler(&self, client: UnixStream, code: RequestCode) {
|
pub fn boot_stage_handler(&self, client: UnixStream, code: RequestCode) {
|
||||||
// Make sure boot stage execution is always serialized
|
// Make sure boot stage execution is always serialized
|
||||||
let mut state = self.boot_stage_lock.lock().unwrap();
|
let mut state = self.boot_stage_lock.lock();
|
||||||
|
|
||||||
match code {
|
match code {
|
||||||
RequestCode::POST_FS_DATA => {
|
RequestCode::POST_FS_DATA => {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use crate::codegen::gen_cxx_binding;
|
|||||||
#[path = "../include/codegen.rs"]
|
#[path = "../include/codegen.rs"]
|
||||||
mod codegen;
|
mod codegen;
|
||||||
|
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("cargo:rerun-if-changed=resetprop/proto/persistent_properties.proto");
|
println!("cargo:rerun-if-changed=resetprop/proto/persistent_properties.proto");
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,9 @@ use std::io::{BufReader, Write};
|
|||||||
use std::os::fd::{AsFd, AsRawFd, IntoRawFd, RawFd};
|
use std::os::fd::{AsFd, AsRawFd, IntoRawFd, RawFd};
|
||||||
use std::os::unix::net::{UCred, UnixListener, UnixStream};
|
use std::os::unix::net::{UCred, UnixListener, UnixStream};
|
||||||
use std::process::{Command, exit};
|
use std::process::{Command, exit};
|
||||||
|
use std::sync::OnceLock;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::{Mutex, OnceLock};
|
use std::sync::nonpoison::Mutex;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
// Global magiskd singleton
|
// Global magiskd singleton
|
||||||
@@ -105,7 +106,7 @@ impl MagiskD {
|
|||||||
denylist_handler(-1);
|
denylist_handler(-1);
|
||||||
|
|
||||||
// Restore native bridge property
|
// Restore native bridge property
|
||||||
self.zygisk.lock().unwrap().restore_prop();
|
self.zygisk.lock().restore_prop();
|
||||||
|
|
||||||
client.write_pod(&0).log_ok();
|
client.write_pod(&0).log_ok();
|
||||||
|
|
||||||
@@ -129,7 +130,7 @@ impl MagiskD {
|
|||||||
self.prune_su_access();
|
self.prune_su_access();
|
||||||
scan_deny_apps();
|
scan_deny_apps();
|
||||||
if self.zygisk_enabled.load(Ordering::Relaxed) {
|
if self.zygisk_enabled.load(Ordering::Relaxed) {
|
||||||
self.zygisk.lock().unwrap().reset(false);
|
self.zygisk.lock().reset(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RequestCode::SQLITE_CMD => {
|
RequestCode::SQLITE_CMD => {
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ unsafe extern "C" fn read_db_row<T: SqlTable>(
|
|||||||
|
|
||||||
impl MagiskD {
|
impl MagiskD {
|
||||||
fn with_db<F: FnOnce(*mut sqlite3) -> i32>(&self, f: F) -> i32 {
|
fn with_db<F: FnOnce(*mut sqlite3) -> i32>(&self, f: F) -> i32 {
|
||||||
let mut db = self.sql_connection.lock().unwrap();
|
let mut db = self.sql_connection.lock();
|
||||||
if db.is_none() {
|
if db.is_none() {
|
||||||
let raw_db = open_and_init_db();
|
let raw_db = open_and_init_db();
|
||||||
*db = NonNull::new(raw_db).map(Sqlite3);
|
*db = NonNull::new(raw_db).map(Sqlite3);
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
#![feature(unix_socket_peek)]
|
#![feature(unix_socket_peek)]
|
||||||
#![feature(default_field_values)]
|
#![feature(default_field_values)]
|
||||||
#![feature(peer_credentials_unix_socket)]
|
#![feature(peer_credentials_unix_socket)]
|
||||||
|
#![feature(sync_nonpoison)]
|
||||||
|
#![feature(nonpoison_mutex)]
|
||||||
|
#![feature(nonpoison_condvar)]
|
||||||
#![allow(clippy::missing_safety_doc)]
|
#![allow(clippy::missing_safety_doc)]
|
||||||
|
|
||||||
use crate::ffi::SuRequest;
|
use crate::ffi::SuRequest;
|
||||||
|
|||||||
@@ -20,9 +20,10 @@ use std::io::{IoSlice, Read, Write};
|
|||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
use std::os::fd::{FromRawFd, IntoRawFd, RawFd};
|
use std::os::fd::{FromRawFd, IntoRawFd, RawFd};
|
||||||
use std::ptr::null_mut;
|
use std::ptr::null_mut;
|
||||||
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicI32, Ordering};
|
use std::sync::atomic::{AtomicI32, Ordering};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::nonpoison::Mutex;
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||||
use std::{fs, io};
|
use std::{fs, io};
|
||||||
|
|
||||||
#[allow(dead_code, non_camel_case_types)]
|
#[allow(dead_code, non_camel_case_types)]
|
||||||
@@ -117,12 +118,12 @@ fn write_log_to_pipe(mut logd: &File, prio: i32, msg: &Utf8CStr) -> io::Result<u
|
|||||||
static MAGISK_LOGD_FD: Mutex<Option<Arc<File>>> = Mutex::new(None);
|
static MAGISK_LOGD_FD: Mutex<Option<Arc<File>>> = Mutex::new(None);
|
||||||
|
|
||||||
fn with_logd_fd<R, F: FnOnce(&File) -> io::Result<R>>(f: F) {
|
fn with_logd_fd<R, F: FnOnce(&File) -> io::Result<R>>(f: F) {
|
||||||
let fd = MAGISK_LOGD_FD.lock().unwrap().clone();
|
let fd = MAGISK_LOGD_FD.lock().clone();
|
||||||
if let Some(logd) = fd
|
if let Some(logd) = fd
|
||||||
&& f(&logd).is_err()
|
&& f(&logd).is_err()
|
||||||
{
|
{
|
||||||
// If any error occurs, shut down the logd pipe
|
// If any error occurs, shut down the logd pipe
|
||||||
*MAGISK_LOGD_FD.lock().unwrap() = None;
|
*MAGISK_LOGD_FD.lock() = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +266,9 @@ fn logfile_write_loop(mut pipe: File) -> io::Result<()> {
|
|||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
|
let now = SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap_or(Duration::ZERO);
|
||||||
|
|
||||||
// Note: the obvious better implementation is to use the rust chrono crate, however
|
// Note: the obvious better implementation is to use the rust chrono crate, however
|
||||||
// the crate cannot fetch the proper local timezone without pulling in a bunch of
|
// the crate cannot fetch the proper local timezone without pulling in a bunch of
|
||||||
@@ -322,7 +325,7 @@ pub fn start_log_daemon() {
|
|||||||
let file = unsafe { File::from_raw_fd(arg as RawFd) };
|
let file = unsafe { File::from_raw_fd(arg as RawFd) };
|
||||||
logfile_write_loop(file).ok();
|
logfile_write_loop(file).ok();
|
||||||
// If any error occurs, shut down the logd pipe
|
// If any error occurs, shut down the logd pipe
|
||||||
*MAGISK_LOGD_FD.lock().unwrap() = None;
|
*MAGISK_LOGD_FD.lock() = None;
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,7 +334,7 @@ pub fn start_log_daemon() {
|
|||||||
chown(path.as_utf8_cstr(), Some(Uid::from(0)), Some(Gid::from(0)))?;
|
chown(path.as_utf8_cstr(), Some(Uid::from(0)), Some(Gid::from(0)))?;
|
||||||
let read = path.open(OFlag::O_RDWR | OFlag::O_CLOEXEC)?;
|
let read = path.open(OFlag::O_RDWR | OFlag::O_CLOEXEC)?;
|
||||||
let write = path.open(OFlag::O_WRONLY | OFlag::O_CLOEXEC)?;
|
let write = path.open(OFlag::O_WRONLY | OFlag::O_CLOEXEC)?;
|
||||||
*MAGISK_LOGD_FD.lock().unwrap() = Some(Arc::new(write));
|
*MAGISK_LOGD_FD.lock() = Some(Arc::new(write));
|
||||||
unsafe {
|
unsafe {
|
||||||
new_daemon_thread(logfile_writer_thread, read.into_raw_fd() as usize);
|
new_daemon_thread(logfile_writer_thread, read.into_raw_fd() as usize);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -889,7 +889,7 @@ impl MagiskD {
|
|||||||
|
|
||||||
// Handle zygisk
|
// Handle zygisk
|
||||||
if self.zygisk_enabled.load(Ordering::Acquire) {
|
if self.zygisk_enabled.load(Ordering::Acquire) {
|
||||||
let mut zygisk = self.zygisk.lock().unwrap();
|
let mut zygisk = self.zygisk.lock();
|
||||||
zygisk.set_prop();
|
zygisk.set_prop();
|
||||||
inject_zygisk_bins(&zygisk.lib_name, &mut system);
|
inject_zygisk_bins(&zygisk.lib_name, &mut system);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use nix::mount::MsFlags;
|
|||||||
use nix::sys::stat::{Mode, SFlag, mknod};
|
use nix::sys::stat::{Mode, SFlag, mknod};
|
||||||
use num_traits::AsPrimitive;
|
use num_traits::AsPrimitive;
|
||||||
use std::cmp::Ordering::{Greater, Less};
|
use std::cmp::Ordering::{Greater, Less};
|
||||||
|
use std::ffi::OsStr;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
pub fn setup_preinit_dir() {
|
pub fn setup_preinit_dir() {
|
||||||
@@ -203,9 +204,8 @@ pub fn find_preinit_device() -> String {
|
|||||||
}
|
}
|
||||||
Path::new(&info.source)
|
Path::new(&info.source)
|
||||||
.file_name()
|
.file_name()
|
||||||
.unwrap()
|
.and_then(OsStr::to_str)
|
||||||
.to_str()
|
.unwrap_or_default()
|
||||||
.unwrap()
|
|
||||||
.to_string()
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,10 +221,7 @@ pub fn revert_unmount(pid: i32) {
|
|||||||
|
|
||||||
// Unmount Magisk tmpfs and mounts from module files
|
// Unmount Magisk tmpfs and mounts from module files
|
||||||
for info in parse_mount_info("self") {
|
for info in parse_mount_info("self") {
|
||||||
if info.source == "magisk"
|
if info.source == "magisk" || info.root.starts_with("/adb/modules") {
|
||||||
|| info.root.starts_with("/adb/modules")
|
|
||||||
|| (info.fs_type == "rootfs" && info.root.starts_with("/magisk"))
|
|
||||||
{
|
|
||||||
targets.push(info.target);
|
targets.push(info.target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -441,7 +441,7 @@ impl MagiskD {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn preserve_stub_apk(&self) {
|
pub fn preserve_stub_apk(&self) {
|
||||||
let mut info = self.manager_info.lock().unwrap();
|
let mut info = self.manager_info.lock();
|
||||||
|
|
||||||
let apk = cstr::buf::default()
|
let apk = cstr::buf::default()
|
||||||
.join_path(get_magisk_tmp())
|
.join_path(get_magisk_tmp())
|
||||||
@@ -458,19 +458,19 @@ impl MagiskD {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_manager_uid(&self, user: i32) -> i32 {
|
pub fn get_manager_uid(&self, user: i32) -> i32 {
|
||||||
let mut info = self.manager_info.lock().unwrap();
|
let mut info = self.manager_info.lock();
|
||||||
let (uid, _) = info.get_manager(self, user, false);
|
let (uid, _) = info.get_manager(self, user, false);
|
||||||
uid
|
uid
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_manager(&self, user: i32, install: bool) -> (i32, String) {
|
pub fn get_manager(&self, user: i32, install: bool) -> (i32, String) {
|
||||||
let mut info = self.manager_info.lock().unwrap();
|
let mut info = self.manager_info.lock();
|
||||||
let (uid, pkg) = info.get_manager(self, user, install);
|
let (uid, pkg) = info.get_manager(self, user, install);
|
||||||
(uid, pkg.to_string())
|
(uid, pkg.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ensure_manager(&self) {
|
pub fn ensure_manager(&self) {
|
||||||
let mut info = self.manager_info.lock().unwrap();
|
let mut info = self.manager_info.lock();
|
||||||
let _ = info.get_manager(self, 0, true);
|
let _ = info.get_manager(self, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,9 @@ impl Extra<'_> {
|
|||||||
IntList(list) => {
|
IntList(list) => {
|
||||||
cmd.args(["--es", self.key]);
|
cmd.args(["--es", self.key]);
|
||||||
let mut tmp = String::new();
|
let mut tmp = String::new();
|
||||||
list.iter().for_each(|i| write!(&mut tmp, "{i},").unwrap());
|
list.iter().for_each(|i| {
|
||||||
|
write!(&mut tmp, "{i},").ok();
|
||||||
|
});
|
||||||
tmp.pop();
|
tmp.pop();
|
||||||
cmd.arg(&tmp);
|
cmd.arg(&tmp);
|
||||||
}
|
}
|
||||||
@@ -67,7 +69,9 @@ impl Extra<'_> {
|
|||||||
IntList(list) => {
|
IntList(list) => {
|
||||||
tmp = format!("{}:s:", self.key);
|
tmp = format!("{}:s:", self.key);
|
||||||
if !list.is_empty() {
|
if !list.is_empty() {
|
||||||
list.iter().for_each(|i| write!(&mut tmp, "{i},").unwrap());
|
list.iter().for_each(|i| {
|
||||||
|
write!(&mut tmp, "{i},").ok();
|
||||||
|
});
|
||||||
tmp.pop();
|
tmp.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,8 +206,11 @@ impl SuAppContext<'_> {
|
|||||||
let mut pfd = [PollFd::new(fd.as_fd(), PollFlags::POLLIN)];
|
let mut pfd = [PollFd::new(fd.as_fd(), PollFlags::POLLIN)];
|
||||||
|
|
||||||
// Wait for data input for at most 70 seconds
|
// Wait for data input for at most 70 seconds
|
||||||
nix::poll::poll(&mut pfd, PollTimeout::try_from(70 * 1000).unwrap())
|
nix::poll::poll(
|
||||||
.check_os_err("poll", None, None)?;
|
&mut pfd,
|
||||||
|
PollTimeout::try_from(70 * 1000).unwrap_or(PollTimeout::NONE),
|
||||||
|
)
|
||||||
|
.check_os_err("poll", None, None)?;
|
||||||
fd
|
fd
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,12 @@ use crate::socket::IpcRead;
|
|||||||
use base::{LoggedResult, ResultExt, WriteExt, debug, error, exit_on_error, libc, warn};
|
use base::{LoggedResult, ResultExt, WriteExt, debug, error, exit_on_error, libc, warn};
|
||||||
use std::os::fd::IntoRawFd;
|
use std::os::fd::IntoRawFd;
|
||||||
use std::os::unix::net::{UCred, UnixStream};
|
use std::os::unix::net::{UCred, UnixStream};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use std::os::fd::AsRawFd;
|
use std::os::fd::AsRawFd;
|
||||||
|
use std::sync::nonpoison::Mutex;
|
||||||
|
|
||||||
const DEFAULT_SHELL: &str = "/system/bin/sh";
|
const DEFAULT_SHELL: &str = "/system/bin/sh";
|
||||||
|
|
||||||
@@ -132,7 +133,7 @@ impl MagiskD {
|
|||||||
|
|
||||||
let info = self.get_su_info(cred.uid as i32);
|
let info = self.get_su_info(cred.uid as i32);
|
||||||
{
|
{
|
||||||
let mut access = info.access.lock().unwrap();
|
let mut access = info.access.lock();
|
||||||
|
|
||||||
// Talk to su manager
|
// Talk to su manager
|
||||||
let mut app = SuAppContext {
|
let mut app = SuAppContext {
|
||||||
@@ -203,7 +204,7 @@ impl MagiskD {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let cached = self.cached_su_info.load();
|
let cached = self.cached_su_info.load();
|
||||||
if cached.uid == uid && cached.access.lock().unwrap().is_fresh() {
|
if cached.uid == uid && cached.access.lock().is_fresh() {
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,6 @@ fn pump_tty_impl(ptmx: File, pump_stdin: bool) -> LoggedResult<()> {
|
|||||||
let mut signal_fd: Option<SignalFd> = None;
|
let mut signal_fd: Option<SignalFd> = None;
|
||||||
|
|
||||||
let raw_ptmx = ptmx.as_raw_fd();
|
let raw_ptmx = ptmx.as_raw_fd();
|
||||||
let mut raw_sig = -1;
|
|
||||||
|
|
||||||
let mut poll_fds = Vec::with_capacity(3);
|
let mut poll_fds = Vec::with_capacity(3);
|
||||||
poll_fds.push(PollFd::new(ptmx.as_fd(), PollFlags::POLLIN));
|
poll_fds.push(PollFd::new(ptmx.as_fd(), PollFlags::POLLIN));
|
||||||
@@ -111,12 +110,14 @@ fn pump_tty_impl(ptmx: File, pump_stdin: bool) -> LoggedResult<()> {
|
|||||||
.check_os_err("pthread_sigmask", None, None)?;
|
.check_os_err("pthread_sigmask", None, None)?;
|
||||||
let sig = SignalFd::with_flags(&set, SfdFlags::SFD_CLOEXEC)
|
let sig = SignalFd::with_flags(&set, SfdFlags::SFD_CLOEXEC)
|
||||||
.into_os_result("signalfd", None, None)?;
|
.into_os_result("signalfd", None, None)?;
|
||||||
raw_sig = sig.as_raw_fd();
|
|
||||||
signal_fd = Some(sig);
|
signal_fd = Some(sig);
|
||||||
poll_fds.push(PollFd::new(
|
unsafe {
|
||||||
signal_fd.as_ref().unwrap().as_fd(),
|
// SAFETY: signal_fd is always Some
|
||||||
PollFlags::POLLIN,
|
poll_fds.push(PollFd::new(
|
||||||
));
|
signal_fd.as_ref().unwrap_unchecked().as_fd(),
|
||||||
|
PollFlags::POLLIN,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// We also need to pump stdin to ptmx
|
// We also need to pump stdin to ptmx
|
||||||
poll_fds.push(PollFd::new(
|
poll_fds.push(PollFd::new(
|
||||||
@@ -142,9 +143,11 @@ fn pump_tty_impl(ptmx: File, pump_stdin: bool) -> LoggedResult<()> {
|
|||||||
pump_via_splice(FileOrStd::StdIn.as_file(), &ptmx, &pipe_fd)?;
|
pump_via_splice(FileOrStd::StdIn.as_file(), &ptmx, &pipe_fd)?;
|
||||||
} else if raw_fd == raw_ptmx {
|
} else if raw_fd == raw_ptmx {
|
||||||
pump_via_splice(&ptmx, FileOrStd::StdOut.as_file(), &pipe_fd)?;
|
pump_via_splice(&ptmx, FileOrStd::StdOut.as_file(), &pipe_fd)?;
|
||||||
} else if raw_fd == raw_sig {
|
} else if let Some(sig) = &signal_fd
|
||||||
|
&& raw_fd == sig.as_raw_fd()
|
||||||
|
{
|
||||||
sync_winsize(raw_ptmx);
|
sync_winsize(raw_ptmx);
|
||||||
signal_fd.as_ref().unwrap().read_signal()?;
|
sig.read_signal()?;
|
||||||
}
|
}
|
||||||
} else if pfd
|
} else if pfd
|
||||||
.revents()
|
.revents()
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
use base::{ResultExt, new_daemon_thread};
|
use base::{ResultExt, new_daemon_thread};
|
||||||
use nix::sys::signal::SigSet;
|
use nix::sys::signal::SigSet;
|
||||||
use nix::unistd::{getpid, gettid};
|
use nix::unistd::{getpid, gettid};
|
||||||
use std::sync::{Condvar, LazyLock, Mutex, WaitTimeoutResult};
|
use std::sync::nonpoison::{Condvar, Mutex};
|
||||||
|
use std::sync::{LazyLock, WaitTimeoutResult};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
static THREAD_POOL: LazyLock<ThreadPool> = LazyLock::new(ThreadPool::default);
|
static THREAD_POOL: LazyLock<ThreadPool> = LazyLock::new(ThreadPool::default);
|
||||||
@@ -33,16 +34,16 @@ impl ThreadPool {
|
|||||||
|
|
||||||
let task: Option<Box<dyn FnOnce() + Send>>;
|
let task: Option<Box<dyn FnOnce() + Send>>;
|
||||||
{
|
{
|
||||||
let mut info = self.info.lock().unwrap();
|
let mut info = self.info.lock();
|
||||||
info.idle_threads += 1;
|
info.idle_threads += 1;
|
||||||
if info.task.is_none() {
|
if info.task.is_none() {
|
||||||
if is_core_pool {
|
if is_core_pool {
|
||||||
// Core pool never closes, wait forever.
|
// Core pool never closes, wait forever.
|
||||||
info = self.task_is_some.wait(info).unwrap();
|
info = self.task_is_some.wait(info);
|
||||||
} else {
|
} else {
|
||||||
let dur = Duration::from_secs(THREAD_IDLE_MAX_SEC);
|
let dur = Duration::from_secs(THREAD_IDLE_MAX_SEC);
|
||||||
let result: WaitTimeoutResult;
|
let result: WaitTimeoutResult;
|
||||||
(info, result) = self.task_is_some.wait_timeout(info, dur).unwrap();
|
(info, result) = self.task_is_some.wait_timeout(info, dur);
|
||||||
if result.timed_out() {
|
if result.timed_out() {
|
||||||
// Terminate thread after timeout
|
// Terminate thread after timeout
|
||||||
info.idle_threads -= 1;
|
info.idle_threads -= 1;
|
||||||
@@ -72,10 +73,10 @@ impl ThreadPool {
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut info = self.info.lock().unwrap();
|
let mut info = self.info.lock();
|
||||||
while info.task.is_some() {
|
while info.task.is_some() {
|
||||||
// Wait until task is none
|
// Wait until task is none
|
||||||
info = self.task_is_none.wait(info).unwrap();
|
info = self.task_is_none.wait(info);
|
||||||
}
|
}
|
||||||
info.task = Some(Box::new(f));
|
info.task = Some(Box::new(f));
|
||||||
if info.idle_threads == 0 {
|
if info.idle_threads == 0 {
|
||||||
|
|||||||
@@ -87,25 +87,23 @@ impl ZygiskState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let socket = if let Some(fd) = socket {
|
if let Some(fd) = socket {
|
||||||
fd
|
fd.send_fds(&[client.as_raw_fd()])?;
|
||||||
} else {
|
} else {
|
||||||
// Create a new socket pair and fork zygiskd process
|
// Create a new socket pair and fork zygiskd process
|
||||||
let (local, remote) = UnixStream::pair()?;
|
let (mut local, remote) = UnixStream::pair()?;
|
||||||
if fork_dont_care() == 0 {
|
if fork_dont_care() == 0 {
|
||||||
exec_zygiskd(is_64_bit, remote);
|
exec_zygiskd(is_64_bit, remote);
|
||||||
}
|
}
|
||||||
*socket = Some(local);
|
|
||||||
let local = socket.as_mut().unwrap();
|
|
||||||
if let Some(module_fds) = daemon.get_module_fds(is_64_bit) {
|
if let Some(module_fds) = daemon.get_module_fds(is_64_bit) {
|
||||||
local.send_fds(&module_fds)?;
|
local.send_fds(&module_fds)?;
|
||||||
}
|
}
|
||||||
if local.read_decodable::<i32>()? != 0 {
|
if local.read_decodable::<i32>()? != 0 {
|
||||||
return log_err!();
|
return log_err!();
|
||||||
}
|
}
|
||||||
local
|
local.send_fds(&[client.as_raw_fd()])?;
|
||||||
};
|
*socket = Some(local);
|
||||||
socket.send_fds(&[client.as_raw_fd()])?;
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +166,6 @@ impl MagiskD {
|
|||||||
ZygiskRequest::ConnectCompanion => self
|
ZygiskRequest::ConnectCompanion => self
|
||||||
.zygisk
|
.zygisk
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
|
||||||
.connect_zygiskd(client, self)
|
.connect_zygiskd(client, self)
|
||||||
.log_with_msg(|w| w.write_str("zygiskd startup error"))?,
|
.log_with_msg(|w| w.write_str("zygiskd startup error"))?,
|
||||||
ZygiskRequest::GetModDir => self.get_mod_dir(client)?,
|
ZygiskRequest::GetModDir => self.get_mod_dir(client)?,
|
||||||
@@ -222,9 +219,12 @@ impl MagiskD {
|
|||||||
let failed_ids: Vec<i32> = client.read_decodable()?;
|
let failed_ids: Vec<i32> = client.read_decodable()?;
|
||||||
if let Some(module_list) = self.module_list.get() {
|
if let Some(module_list) = self.module_list.get() {
|
||||||
for id in failed_ids {
|
for id in failed_ids {
|
||||||
|
let Some(module) = module_list.get(id as usize) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
let path = cstr::buf::default()
|
let path = cstr::buf::default()
|
||||||
.join_path(MODULEROOT)
|
.join_path(MODULEROOT)
|
||||||
.join_path(&module_list[id as usize].name)
|
.join_path(&module.name)
|
||||||
.join_path("zygisk");
|
.join_path("zygisk");
|
||||||
// Create the unloaded marker file
|
// Create the unloaded marker file
|
||||||
if let Ok(dir) = Directory::open(&path) {
|
if let Ok(dir) = Directory::open(&path) {
|
||||||
@@ -240,7 +240,13 @@ impl MagiskD {
|
|||||||
|
|
||||||
fn get_mod_dir(&self, mut client: UnixStream) -> LoggedResult<()> {
|
fn get_mod_dir(&self, mut client: UnixStream) -> LoggedResult<()> {
|
||||||
let id: i32 = client.read_decodable()?;
|
let id: i32 = client.read_decodable()?;
|
||||||
let module = &self.module_list.get().unwrap()[id as usize];
|
let Some(module) = self
|
||||||
|
.module_list
|
||||||
|
.get()
|
||||||
|
.and_then(|list| list.get(id as usize))
|
||||||
|
else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
let dir = cstr::buf::default()
|
let dir = cstr::buf::default()
|
||||||
.join_path(MODULEROOT)
|
.join_path(MODULEROOT)
|
||||||
.join_path(&module.name);
|
.join_path(&module.name);
|
||||||
|
|||||||
@@ -1,238 +1,591 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
primitives = ['jint', 'jboolean', 'jlong']
|
primitives = ["jint", "jboolean", "jlong"]
|
||||||
|
|
||||||
|
|
||||||
class JType:
|
class JType:
|
||||||
def __init__(self, cpp, jni):
|
def __init__(self, cpp: str, jni: str):
|
||||||
self.cpp = cpp
|
self.cpp = cpp
|
||||||
self.jni = jni
|
self.jni = jni
|
||||||
|
|
||||||
|
|
||||||
class JArray(JType):
|
class JArray(JType):
|
||||||
def __init__(self, type):
|
def __init__(self, type: JType):
|
||||||
if type.cpp in primitives:
|
if type.cpp in primitives:
|
||||||
name = type.cpp + 'Array'
|
name = type.cpp + "Array"
|
||||||
else:
|
else:
|
||||||
name = 'jobjectArray'
|
name = "jobjectArray"
|
||||||
super().__init__(name, '[' + type.jni)
|
super().__init__(name, "[" + type.jni)
|
||||||
|
|
||||||
|
|
||||||
class Argument:
|
class Argument:
|
||||||
def __init__(self, name, type, set_arg = False):
|
def __init__(self, name: str, type: JType, set_arg=False):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.type = type
|
self.type = type
|
||||||
self.set_arg = set_arg
|
self.set_arg = set_arg
|
||||||
|
|
||||||
def cpp(self):
|
def cpp(self) -> str:
|
||||||
return f'{self.type.cpp} {self.name}'
|
return f"{self.type.cpp} {self.name}"
|
||||||
|
|
||||||
|
|
||||||
# Args we don't care, give it an auto generated name
|
# Args we don't care, give it an auto generated name
|
||||||
class Anon(Argument):
|
class Anon(Argument):
|
||||||
cnt = 0
|
cnt = 0
|
||||||
def __init__(self, type):
|
|
||||||
super().__init__(f'_{Anon.cnt}', type)
|
def __init__(self, type: JType):
|
||||||
|
super().__init__(f"_{Anon.cnt}", type)
|
||||||
Anon.cnt += 1
|
Anon.cnt += 1
|
||||||
|
|
||||||
|
|
||||||
class Return:
|
class Return:
|
||||||
def __init__(self, value, type):
|
def __init__(self, value: str, type: JType):
|
||||||
self.value = value
|
self.value = value
|
||||||
self.type = type
|
self.type = type
|
||||||
|
|
||||||
class Method:
|
|
||||||
def __init__(self, name, ret, args):
|
class JNIMethod:
|
||||||
|
def __init__(self, name: str, ret: Return, args: list[Argument]):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.ret = ret
|
self.ret = ret
|
||||||
self.args = args
|
self.args = args
|
||||||
|
|
||||||
def cpp(self):
|
def arg_list_name(self) -> str:
|
||||||
return ', '.join(map(lambda x: x.cpp(), self.args))
|
return "env, clazz, " + ", ".join(map(lambda x: x.name, self.args))
|
||||||
|
|
||||||
def name_list(self):
|
def arg_list_cpp(self) -> str:
|
||||||
return ', '.join(map(lambda x: x.name, self.args))
|
return "JNIEnv *env, jclass clazz, " + ", ".join(
|
||||||
|
map(lambda x: x.cpp(), self.args)
|
||||||
|
)
|
||||||
|
|
||||||
def jni(self):
|
def cpp_fn_type(self) -> str:
|
||||||
args = ''.join(map(lambda x: x.type.jni, self.args))
|
return f"{self.ret.type.cpp}(*)({self.arg_list_cpp()}"
|
||||||
return f'({args}){self.ret.type.jni}'
|
|
||||||
|
|
||||||
def body(self, name, i):
|
def cpp_lambda_sig(self) -> str:
|
||||||
return ''
|
return f"[] [[clang::no_stack_protector]] ({self.arg_list_cpp()}) static -> {self.ret.type.cpp}"
|
||||||
|
|
||||||
class JNIHook(Method):
|
def jni_sig(self):
|
||||||
def __init__(self, ver, ret, args):
|
args = "".join(map(lambda x: x.type.jni, self.args))
|
||||||
name = f'{self.base_name()}_{ver}'
|
return f"({args}){self.ret.type.jni}"
|
||||||
|
|
||||||
|
|
||||||
|
class JNIHook(JNIMethod):
|
||||||
|
def __init__(self, ver: str, ret: Return, args: list[Argument]):
|
||||||
|
name = f"{self.hook_target()}_{ver}"
|
||||||
super().__init__(name, ret, args)
|
super().__init__(name, ret, args)
|
||||||
|
|
||||||
def base_name(self):
|
def hook_target(self):
|
||||||
return ''
|
return ""
|
||||||
|
|
||||||
|
def body(self, orig_fn_ptr: str):
|
||||||
|
return ""
|
||||||
|
|
||||||
def orig_method(self, name, i):
|
|
||||||
return f'reinterpret_cast<{self.ret.type.cpp}(*)(JNIEnv *env, jclass clazz, {self.cpp()})>(g_hook->{name}_methods[{i}].fnPtr)'
|
|
||||||
|
|
||||||
def ind(i):
|
def ind(i):
|
||||||
return '\n' + ' ' * i
|
return "\n" + " " * i
|
||||||
|
|
||||||
|
|
||||||
# Common types
|
# Common types
|
||||||
jint = JType('jint', 'I')
|
jint = JType("jint", "I")
|
||||||
jintArray = JArray(jint)
|
jintArray = JArray(jint)
|
||||||
jstring = JType('jstring', 'Ljava/lang/String;')
|
jstring = JType("jstring", "Ljava/lang/String;")
|
||||||
jboolean = JType('jboolean', 'Z')
|
jboolean = JType("jboolean", "Z")
|
||||||
jlong = JType('jlong', 'J')
|
jlong = JType("jlong", "J")
|
||||||
void = JType('void', 'V')
|
void = JType("void", "V")
|
||||||
|
|
||||||
class ForkAndSpec(JNIHook):
|
|
||||||
|
class ForkApp(JNIHook):
|
||||||
def __init__(self, ver, args):
|
def __init__(self, ver, args):
|
||||||
super().__init__(ver, Return('ctx.pid', jint), args)
|
super().__init__(ver, Return("ctx.pid", jint), args)
|
||||||
|
|
||||||
def base_name(self):
|
def hook_target(self):
|
||||||
return 'nativeForkAndSpecialize'
|
return "nativeForkAndSpecialize"
|
||||||
|
|
||||||
def init_args(self):
|
def init_args(self):
|
||||||
return 'AppSpecializeArgs_v5 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);'
|
return "AppSpecializeArgs_v5 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);"
|
||||||
|
|
||||||
def body(self, name, i):
|
def body(self, orig_fn_ptr: str):
|
||||||
decl = ''
|
decl = ""
|
||||||
decl += ind(3) + self.init_args()
|
decl += ind(3) + self.init_args()
|
||||||
for a in self.args:
|
for a in self.args:
|
||||||
if a.set_arg:
|
if a.set_arg:
|
||||||
decl += ind(3) + f'args.{a.name} = &{a.name};'
|
decl += ind(3) + f"args.{a.name} = &{a.name};"
|
||||||
decl += ind(3) + 'ZygiskContext ctx(env, &args);'
|
decl += ind(3) + "ZygiskContext ctx(env, &args);"
|
||||||
decl += ind(3) + f'ctx.{self.base_name()}_pre();'
|
decl += ind(3) + f"ctx.{self.hook_target()}_pre();"
|
||||||
decl += ind(3) + self.orig_method(name, i) + '('
|
decl += ind(3) + f"reinterpret_cast<{self.cpp_fn_type()})>({orig_fn_ptr})("
|
||||||
decl += ind(4) + f'env, clazz, {self.name_list()}'
|
decl += ind(4) + self.arg_list_name()
|
||||||
decl += ind(3) + ');'
|
decl += ind(3) + ");"
|
||||||
decl += ind(3) + f'ctx.{self.base_name()}_post();'
|
decl += ind(3) + f"ctx.{self.hook_target()}_post();"
|
||||||
|
if self.ret.value:
|
||||||
|
decl += ind(3) + f"return {self.ret.value};"
|
||||||
return decl
|
return decl
|
||||||
|
|
||||||
class SpecApp(ForkAndSpec):
|
|
||||||
def __init__(self, ver, args):
|
class SpecializeApp(ForkApp):
|
||||||
|
def __init__(self, ver: str, args: list[Argument]):
|
||||||
super().__init__(ver, args)
|
super().__init__(ver, args)
|
||||||
self.ret = Return('', void)
|
self.ret = Return("", void)
|
||||||
|
|
||||||
def base_name(self):
|
def hook_target(self):
|
||||||
return 'nativeSpecializeAppProcess'
|
return "nativeSpecializeAppProcess"
|
||||||
|
|
||||||
class ForkServer(ForkAndSpec):
|
|
||||||
def base_name(self):
|
class ForkServer(ForkApp):
|
||||||
return 'nativeForkSystemServer'
|
def hook_target(self):
|
||||||
|
return "nativeForkSystemServer"
|
||||||
|
|
||||||
def init_args(self):
|
def init_args(self):
|
||||||
return 'ServerSpecializeArgs_v1 args(uid, gid, gids, runtime_flags, permitted_capabilities, effective_capabilities);'
|
return "ServerSpecializeArgs_v1 args(uid, gid, gids, runtime_flags, permitted_capabilities, effective_capabilities);"
|
||||||
|
|
||||||
|
|
||||||
# Common args
|
# Common args
|
||||||
uid = Argument('uid', jint)
|
uid = Argument("uid", jint)
|
||||||
gid = Argument('gid', jint)
|
gid = Argument("gid", jint)
|
||||||
gids = Argument('gids', jintArray)
|
gids = Argument("gids", jintArray)
|
||||||
runtime_flags = Argument('runtime_flags', jint)
|
runtime_flags = Argument("runtime_flags", jint)
|
||||||
rlimits = Argument('rlimits', JArray(jintArray))
|
rlimits = Argument("rlimits", JArray(jintArray))
|
||||||
mount_external = Argument('mount_external', jint)
|
mount_external = Argument("mount_external", jint)
|
||||||
se_info = Argument('se_info', jstring)
|
se_info = Argument("se_info", jstring)
|
||||||
nice_name = Argument('nice_name', jstring)
|
nice_name = Argument("nice_name", jstring)
|
||||||
fds_to_close = Argument('fds_to_close', jintArray)
|
fds_to_close = Argument("fds_to_close", jintArray)
|
||||||
instruction_set = Argument('instruction_set', jstring)
|
instruction_set = Argument("instruction_set", jstring)
|
||||||
app_data_dir = Argument('app_data_dir', jstring)
|
app_data_dir = Argument("app_data_dir", jstring)
|
||||||
|
|
||||||
# o
|
# o
|
||||||
fds_to_ignore = Argument('fds_to_ignore', jintArray, True)
|
fds_to_ignore = Argument("fds_to_ignore", jintArray, True)
|
||||||
|
|
||||||
# p
|
# p
|
||||||
is_child_zygote = Argument('is_child_zygote', jboolean, True)
|
is_child_zygote = Argument("is_child_zygote", jboolean, True)
|
||||||
|
|
||||||
# q_alt
|
# q_alt
|
||||||
is_top_app = Argument('is_top_app', jboolean, True)
|
is_top_app = Argument("is_top_app", jboolean, True)
|
||||||
|
|
||||||
# r
|
# r
|
||||||
pkg_data_info_list = Argument('pkg_data_info_list', JArray(jstring), True)
|
pkg_data_info_list = Argument("pkg_data_info_list", JArray(jstring), True)
|
||||||
whitelisted_data_info_list = Argument('whitelisted_data_info_list', JArray(jstring), True)
|
whitelisted_data_info_list = Argument(
|
||||||
mount_data_dirs = Argument('mount_data_dirs', jboolean, True)
|
"whitelisted_data_info_list", JArray(jstring), True
|
||||||
mount_storage_dirs = Argument('mount_storage_dirs', jboolean, True)
|
)
|
||||||
|
mount_data_dirs = Argument("mount_data_dirs", jboolean, True)
|
||||||
|
mount_storage_dirs = Argument("mount_storage_dirs", jboolean, True)
|
||||||
|
|
||||||
# u
|
# u
|
||||||
mount_sysprop_overrides = Argument('mount_sysprop_overrides', jboolean, True)
|
mount_sysprop_overrides = Argument("mount_sysprop_overrides", jboolean, True)
|
||||||
|
|
||||||
|
# b
|
||||||
|
use_fifo_ui = Argument("use_fifo_ui", jboolean, False)
|
||||||
|
|
||||||
# server
|
# server
|
||||||
permitted_capabilities = Argument('permitted_capabilities', jlong)
|
permitted_capabilities = Argument("permitted_capabilities", jlong)
|
||||||
effective_capabilities = Argument('effective_capabilities', jlong)
|
effective_capabilities = Argument("effective_capabilities", jlong)
|
||||||
|
|
||||||
# Method definitions
|
# Method definitions
|
||||||
fas_l = ForkAndSpec('l', [uid, gid, gids, runtime_flags, rlimits, mount_external,
|
fas_l = ForkApp(
|
||||||
se_info, nice_name, fds_to_close, instruction_set, app_data_dir])
|
"l",
|
||||||
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
rlimits,
|
||||||
|
mount_external,
|
||||||
|
se_info,
|
||||||
|
nice_name,
|
||||||
|
fds_to_close,
|
||||||
|
instruction_set,
|
||||||
|
app_data_dir,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
fas_o = ForkAndSpec('o', [uid, gid, gids, runtime_flags, rlimits, mount_external,
|
fas_o = ForkApp(
|
||||||
se_info, nice_name, fds_to_close, fds_to_ignore, instruction_set, app_data_dir])
|
"o",
|
||||||
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
rlimits,
|
||||||
|
mount_external,
|
||||||
|
se_info,
|
||||||
|
nice_name,
|
||||||
|
fds_to_close,
|
||||||
|
fds_to_ignore,
|
||||||
|
instruction_set,
|
||||||
|
app_data_dir,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
fas_p = ForkAndSpec('p', [uid, gid, gids, runtime_flags, rlimits, mount_external, se_info,
|
fas_p = ForkApp(
|
||||||
nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir])
|
"p",
|
||||||
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
rlimits,
|
||||||
|
mount_external,
|
||||||
|
se_info,
|
||||||
|
nice_name,
|
||||||
|
fds_to_close,
|
||||||
|
fds_to_ignore,
|
||||||
|
is_child_zygote,
|
||||||
|
instruction_set,
|
||||||
|
app_data_dir,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
fas_q_alt = ForkAndSpec('q_alt', [uid, gid, gids, runtime_flags, rlimits, mount_external, se_info,
|
fas_q_alt = ForkApp(
|
||||||
nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir, is_top_app])
|
"q_alt",
|
||||||
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
rlimits,
|
||||||
|
mount_external,
|
||||||
|
se_info,
|
||||||
|
nice_name,
|
||||||
|
fds_to_close,
|
||||||
|
fds_to_ignore,
|
||||||
|
is_child_zygote,
|
||||||
|
instruction_set,
|
||||||
|
app_data_dir,
|
||||||
|
is_top_app,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
fas_r = ForkAndSpec('r', [uid, gid, gids, runtime_flags, rlimits, mount_external, se_info,
|
fas_r = ForkApp(
|
||||||
nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir, is_top_app,
|
"r",
|
||||||
pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs])
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
rlimits,
|
||||||
|
mount_external,
|
||||||
|
se_info,
|
||||||
|
nice_name,
|
||||||
|
fds_to_close,
|
||||||
|
fds_to_ignore,
|
||||||
|
is_child_zygote,
|
||||||
|
instruction_set,
|
||||||
|
app_data_dir,
|
||||||
|
is_top_app,
|
||||||
|
pkg_data_info_list,
|
||||||
|
whitelisted_data_info_list,
|
||||||
|
mount_data_dirs,
|
||||||
|
mount_storage_dirs,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
fas_u = ForkAndSpec('u', [uid, gid, gids, runtime_flags, rlimits, mount_external, se_info,
|
fas_u = ForkApp(
|
||||||
nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir, is_top_app,
|
"u",
|
||||||
pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs, mount_sysprop_overrides])
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
rlimits,
|
||||||
|
mount_external,
|
||||||
|
se_info,
|
||||||
|
nice_name,
|
||||||
|
fds_to_close,
|
||||||
|
fds_to_ignore,
|
||||||
|
is_child_zygote,
|
||||||
|
instruction_set,
|
||||||
|
app_data_dir,
|
||||||
|
is_top_app,
|
||||||
|
pkg_data_info_list,
|
||||||
|
whitelisted_data_info_list,
|
||||||
|
mount_data_dirs,
|
||||||
|
mount_storage_dirs,
|
||||||
|
mount_sysprop_overrides,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
fas_samsung_m = ForkAndSpec('samsung_m', [uid, gid, gids, runtime_flags, rlimits, mount_external,
|
fas_b = ForkApp(
|
||||||
se_info, Anon(jint), Anon(jint), nice_name, fds_to_close, instruction_set, app_data_dir])
|
"b",
|
||||||
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
rlimits,
|
||||||
|
mount_external,
|
||||||
|
se_info,
|
||||||
|
nice_name,
|
||||||
|
fds_to_close,
|
||||||
|
fds_to_ignore,
|
||||||
|
is_child_zygote,
|
||||||
|
instruction_set,
|
||||||
|
app_data_dir,
|
||||||
|
is_top_app,
|
||||||
|
use_fifo_ui,
|
||||||
|
pkg_data_info_list,
|
||||||
|
whitelisted_data_info_list,
|
||||||
|
mount_data_dirs,
|
||||||
|
mount_storage_dirs,
|
||||||
|
mount_sysprop_overrides,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
fas_samsung_n = ForkAndSpec('samsung_n', [uid, gid, gids, runtime_flags, rlimits, mount_external,
|
fas_samsung_m = ForkApp(
|
||||||
se_info, Anon(jint), Anon(jint), nice_name, fds_to_close, instruction_set, app_data_dir, Anon(jint)])
|
"samsung_m",
|
||||||
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
rlimits,
|
||||||
|
mount_external,
|
||||||
|
se_info,
|
||||||
|
Anon(jint),
|
||||||
|
Anon(jint),
|
||||||
|
nice_name,
|
||||||
|
fds_to_close,
|
||||||
|
instruction_set,
|
||||||
|
app_data_dir,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
fas_samsung_o = ForkAndSpec('samsung_o', [uid, gid, gids, runtime_flags, rlimits, mount_external,
|
fas_samsung_n = ForkApp(
|
||||||
se_info, Anon(jint), Anon(jint), nice_name, fds_to_close, fds_to_ignore, instruction_set, app_data_dir])
|
"samsung_n",
|
||||||
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
rlimits,
|
||||||
|
mount_external,
|
||||||
|
se_info,
|
||||||
|
Anon(jint),
|
||||||
|
Anon(jint),
|
||||||
|
nice_name,
|
||||||
|
fds_to_close,
|
||||||
|
instruction_set,
|
||||||
|
app_data_dir,
|
||||||
|
Anon(jint),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
fas_samsung_p = ForkAndSpec('samsung_p', [uid, gid, gids, runtime_flags, rlimits, mount_external,
|
fas_samsung_o = ForkApp(
|
||||||
se_info, Anon(jint), Anon(jint), nice_name, fds_to_close, fds_to_ignore, is_child_zygote,
|
"samsung_o",
|
||||||
instruction_set, app_data_dir])
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
rlimits,
|
||||||
|
mount_external,
|
||||||
|
se_info,
|
||||||
|
Anon(jint),
|
||||||
|
Anon(jint),
|
||||||
|
nice_name,
|
||||||
|
fds_to_close,
|
||||||
|
fds_to_ignore,
|
||||||
|
instruction_set,
|
||||||
|
app_data_dir,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
spec_q = SpecApp('q', [uid, gid, gids, runtime_flags, rlimits, mount_external, se_info,
|
fas_samsung_p = ForkApp(
|
||||||
nice_name, is_child_zygote, instruction_set, app_data_dir])
|
"samsung_p",
|
||||||
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
rlimits,
|
||||||
|
mount_external,
|
||||||
|
se_info,
|
||||||
|
Anon(jint),
|
||||||
|
Anon(jint),
|
||||||
|
nice_name,
|
||||||
|
fds_to_close,
|
||||||
|
fds_to_ignore,
|
||||||
|
is_child_zygote,
|
||||||
|
instruction_set,
|
||||||
|
app_data_dir,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
spec_q_alt = SpecApp('q_alt', [uid, gid, gids, runtime_flags, rlimits, mount_external, se_info,
|
spec_q = SpecializeApp(
|
||||||
nice_name, is_child_zygote, instruction_set, app_data_dir, is_top_app])
|
"q",
|
||||||
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
rlimits,
|
||||||
|
mount_external,
|
||||||
|
se_info,
|
||||||
|
nice_name,
|
||||||
|
is_child_zygote,
|
||||||
|
instruction_set,
|
||||||
|
app_data_dir,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
spec_r = SpecApp('r', [uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name,
|
spec_q_alt = SpecializeApp(
|
||||||
is_child_zygote, instruction_set, app_data_dir, is_top_app, pkg_data_info_list,
|
"q_alt",
|
||||||
whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs])
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
rlimits,
|
||||||
|
mount_external,
|
||||||
|
se_info,
|
||||||
|
nice_name,
|
||||||
|
is_child_zygote,
|
||||||
|
instruction_set,
|
||||||
|
app_data_dir,
|
||||||
|
is_top_app,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
spec_u = SpecApp('u', [uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name,
|
spec_r = SpecializeApp(
|
||||||
is_child_zygote, instruction_set, app_data_dir, is_top_app, pkg_data_info_list,
|
"r",
|
||||||
whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs, mount_sysprop_overrides])
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
rlimits,
|
||||||
|
mount_external,
|
||||||
|
se_info,
|
||||||
|
nice_name,
|
||||||
|
is_child_zygote,
|
||||||
|
instruction_set,
|
||||||
|
app_data_dir,
|
||||||
|
is_top_app,
|
||||||
|
pkg_data_info_list,
|
||||||
|
whitelisted_data_info_list,
|
||||||
|
mount_data_dirs,
|
||||||
|
mount_storage_dirs,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
spec_samsung_q = SpecApp('samsung_q', [uid, gid, gids, runtime_flags, rlimits, mount_external,
|
spec_u = SpecializeApp(
|
||||||
se_info, Anon(jint), Anon(jint), nice_name, is_child_zygote, instruction_set, app_data_dir])
|
"u",
|
||||||
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
rlimits,
|
||||||
|
mount_external,
|
||||||
|
se_info,
|
||||||
|
nice_name,
|
||||||
|
is_child_zygote,
|
||||||
|
instruction_set,
|
||||||
|
app_data_dir,
|
||||||
|
is_top_app,
|
||||||
|
pkg_data_info_list,
|
||||||
|
whitelisted_data_info_list,
|
||||||
|
mount_data_dirs,
|
||||||
|
mount_storage_dirs,
|
||||||
|
mount_sysprop_overrides,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
server_l = ForkServer('l', [uid, gid, gids, runtime_flags, rlimits,
|
spec_samsung_q = SpecializeApp(
|
||||||
permitted_capabilities, effective_capabilities])
|
"samsung_q",
|
||||||
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
rlimits,
|
||||||
|
mount_external,
|
||||||
|
se_info,
|
||||||
|
Anon(jint),
|
||||||
|
Anon(jint),
|
||||||
|
nice_name,
|
||||||
|
is_child_zygote,
|
||||||
|
instruction_set,
|
||||||
|
app_data_dir,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
server_samsung_q = ForkServer('samsung_q', [uid, gid, gids, runtime_flags, Anon(jint), Anon(jint), rlimits,
|
server_l = ForkServer(
|
||||||
permitted_capabilities, effective_capabilities])
|
"l",
|
||||||
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
rlimits,
|
||||||
|
permitted_capabilities,
|
||||||
|
effective_capabilities,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
def gen_jni_def(name, methods):
|
server_samsung_q = ForkServer(
|
||||||
decl = ''
|
"samsung_q",
|
||||||
decl += ind(0) + f'std::array<JNINativeMethod, {len(methods)}> {name}_methods = {{{{'
|
[
|
||||||
|
uid,
|
||||||
|
gid,
|
||||||
|
gids,
|
||||||
|
runtime_flags,
|
||||||
|
Anon(jint),
|
||||||
|
Anon(jint),
|
||||||
|
rlimits,
|
||||||
|
permitted_capabilities,
|
||||||
|
effective_capabilities,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def gen_jni_def(field: str, methods: list[JNIHook]):
|
||||||
|
decl = ""
|
||||||
|
decl += ind(0) + f"std::array<JNINativeMethod, {len(methods)}> {field} = {{{{"
|
||||||
for i, m in enumerate(methods):
|
for i, m in enumerate(methods):
|
||||||
decl += ind(1) + '{'
|
decl += ind(1) + f"// {m.name}"
|
||||||
decl += ind(2) + f'"{m.base_name()}",'
|
decl += ind(1) + "{"
|
||||||
decl += ind(2) + f'"{m.jni()}",'
|
decl += ind(2) + f'"{m.hook_target()}",'
|
||||||
decl += ind(2) + f'(void *) +[] [[clang::no_stack_protector]] (JNIEnv *env, jclass clazz, {m.cpp()}) static -> {m.ret.type.cpp} {{'
|
decl += ind(2) + f'"{m.jni_sig()}",'
|
||||||
decl += m.body(name, i)
|
decl += ind(2) + f"(void *) +{m.cpp_lambda_sig()} {{"
|
||||||
if m.ret.value:
|
orig_fn_ptr = f"get_defs()->{field}[{i}].fnPtr"
|
||||||
decl += ind(3) + f'return {m.ret.value};'
|
decl += m.body(orig_fn_ptr)
|
||||||
decl += ind(2) + '}'
|
decl += ind(2) + "}"
|
||||||
decl += ind(1) + '},'
|
decl += ind(1) + "},"
|
||||||
decl += ind(0) + '}};'
|
decl += ind(0) + "}};"
|
||||||
decl += ind(0)
|
decl += ind(0)
|
||||||
|
|
||||||
return decl
|
return decl
|
||||||
|
|
||||||
with open('jni_hooks.hpp', 'w') as f:
|
|
||||||
f.write('// Generated by gen_jni_hooks.py\n')
|
|
||||||
|
|
||||||
f.write(gen_jni_def('zygote', [
|
with open("jni_hooks.hpp", "w") as f:
|
||||||
fas_l, fas_o, fas_p, fas_q_alt, fas_r, fas_u, fas_samsung_m, fas_samsung_n, fas_samsung_o,
|
f.write("// Generated by gen_jni_hooks.py\n")
|
||||||
fas_samsung_p, spec_q, spec_q_alt, spec_r, spec_u, spec_samsung_q, server_l, server_samsung_q]))
|
f.write("#pragma once\n\n")
|
||||||
|
f.write("struct JniHookDefinitions;\n")
|
||||||
|
f.write("static JniHookDefinitions *get_defs();\n\n")
|
||||||
|
f.write("struct JniHookDefinitions {\n")
|
||||||
|
f.write(
|
||||||
|
gen_jni_def(
|
||||||
|
"fork_app_methods",
|
||||||
|
[
|
||||||
|
fas_l,
|
||||||
|
fas_o,
|
||||||
|
fas_p,
|
||||||
|
fas_q_alt,
|
||||||
|
fas_r,
|
||||||
|
fas_u,
|
||||||
|
fas_b,
|
||||||
|
fas_samsung_m,
|
||||||
|
fas_samsung_n,
|
||||||
|
fas_samsung_o,
|
||||||
|
fas_samsung_p,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
f.write('\n')
|
f.write(
|
||||||
|
gen_jni_def(
|
||||||
|
"specialize_app_methods",
|
||||||
|
[spec_q, spec_q_alt, spec_r, spec_u, spec_samsung_q],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
f.write(gen_jni_def("fork_server_methods", [server_l, server_samsung_q]))
|
||||||
|
|
||||||
|
f.write("\n};\n")
|
||||||
|
|||||||
@@ -8,10 +8,10 @@
|
|||||||
#include <lsplt.hpp>
|
#include <lsplt.hpp>
|
||||||
|
|
||||||
#include <base.hpp>
|
#include <base.hpp>
|
||||||
#include <consts.hpp>
|
|
||||||
|
|
||||||
#include "zygisk.hpp"
|
#include "zygisk.hpp"
|
||||||
#include "module.hpp"
|
#include "module.hpp"
|
||||||
|
#include "jni_hooks.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@@ -90,25 +90,15 @@ using namespace std;
|
|||||||
|
|
||||||
constexpr const char *kZygoteInit = "com.android.internal.os.ZygoteInit";
|
constexpr const char *kZygoteInit = "com.android.internal.os.ZygoteInit";
|
||||||
constexpr const char *kZygote = "com/android/internal/os/Zygote";
|
constexpr const char *kZygote = "com/android/internal/os/Zygote";
|
||||||
|
constexpr const char *kForkApp = "nativeForkAndSpecialize";
|
||||||
// Global contexts:
|
constexpr const char *kSpecializeApp = "nativeSpecializeAppProcess";
|
||||||
//
|
constexpr const char *kForkServer = "nativeForkSystemServer";
|
||||||
// HookContext lives as long as Zygisk is loaded in memory. It tracks the process's function
|
|
||||||
// hooking state and bootstraps code injection until we replace the process specialization methods.
|
|
||||||
//
|
|
||||||
// ZygiskContext lives during the process specialization process. It implements Zygisk
|
|
||||||
// features, such as loading modules and customizing process fork/specialization.
|
|
||||||
|
|
||||||
ZygiskContext *g_ctx;
|
|
||||||
struct HookContext;
|
|
||||||
static HookContext *g_hook;
|
|
||||||
|
|
||||||
using JNIMethods = std::span<JNINativeMethod>;
|
using JNIMethods = std::span<JNINativeMethod>;
|
||||||
|
using JNIMethodsDyn = std::pair<unique_ptr<JNINativeMethod[]>, size_t>;
|
||||||
|
|
||||||
struct HookContext {
|
struct HookContext : JniHookDefinitions {
|
||||||
#include "jni_hooks.hpp"
|
|
||||||
|
|
||||||
// std::array<JNINativeMethod> zygote_methods
|
|
||||||
vector<tuple<dev_t, ino_t, const char *, void **>> plt_backup;
|
vector<tuple<dev_t, ino_t, const char *, void **>> plt_backup;
|
||||||
const NativeBridgeRuntimeCallbacks *runtime_callbacks = nullptr;
|
const NativeBridgeRuntimeCallbacks *runtime_callbacks = nullptr;
|
||||||
void *self_handle = nullptr;
|
void *self_handle = nullptr;
|
||||||
@@ -119,15 +109,34 @@ struct HookContext {
|
|||||||
void restore_plt_hook();
|
void restore_plt_hook();
|
||||||
void hook_zygote_jni();
|
void hook_zygote_jni();
|
||||||
void restore_zygote_hook(JNIEnv *env);
|
void restore_zygote_hook(JNIEnv *env);
|
||||||
void hook_jni_methods(JNIEnv *env, const char *clz, JNIMethods methods);
|
void hook_jni_methods(JNIEnv *env, const char *clz, JNIMethods methods) const;
|
||||||
void post_native_bridge_load(void *handle);
|
void post_native_bridge_load(void *handle);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void register_hook(dev_t dev, ino_t inode, const char *symbol, void *new_func, void **old_func);
|
void register_hook(dev_t dev, ino_t inode, const char *symbol, void *new_func, void **old_func);
|
||||||
|
int hook_jni_methods(JNIEnv *env, jclass clazz, JNIMethods methods) const;
|
||||||
|
JNIMethodsDyn get_jni_methods(JNIEnv *env, jclass clazz) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
// Global contexts:
|
||||||
|
//
|
||||||
|
// HookContext lives as long as Zygisk is loaded in memory. It tracks the process's function
|
||||||
|
// hooking state and bootstraps code injection until we replace the process specialization methods.
|
||||||
|
//
|
||||||
|
// ZygiskContext lives during the process specialization process. It implements Zygisk
|
||||||
|
// features, such as loading modules and customizing process fork/specialization.
|
||||||
|
|
||||||
|
ZygiskContext *g_ctx;
|
||||||
|
static HookContext *g_hook;
|
||||||
|
|
||||||
|
static JniHookDefinitions *get_defs() {
|
||||||
|
return g_hook;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
#define DCL_HOOK_FUNC(ret, func, ...) \
|
#define DCL_HOOK_FUNC(ret, func, ...) \
|
||||||
ret (*old_##func)(__VA_ARGS__); \
|
ret (*old_##func)(__VA_ARGS__); \
|
||||||
ret new_##func(__VA_ARGS__)
|
ret new_##func(__VA_ARGS__)
|
||||||
@@ -452,56 +461,74 @@ void HookContext::restore_plt_hook() {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
void HookContext::hook_jni_methods(JNIEnv *env, const char *clz, JNIMethods methods) {
|
JNIMethodsDyn HookContext::get_jni_methods(JNIEnv *env, jclass clazz) const {
|
||||||
jclass clazz;
|
size_t total = runtime_callbacks->getNativeMethodCount(env, clazz);
|
||||||
if (!runtime_callbacks || !env || !clz || !(clazz = env->FindClass(clz))) {
|
auto methods = std::make_unique_for_overwrite<JNINativeMethod[]>(total);
|
||||||
for (auto &method : methods) {
|
runtime_callbacks->getNativeMethods(env, clazz, methods.get(), total);
|
||||||
method.fnPtr = nullptr;
|
return std::make_pair(std::move(methods), total);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Backup existing methods
|
static void register_jni_methods(JNIEnv *env, jclass clazz, JNIMethods methods) {
|
||||||
auto total = runtime_callbacks->getNativeMethodCount(env, clazz);
|
|
||||||
auto old_methods = std::make_unique_for_overwrite<JNINativeMethod[]>(total);
|
|
||||||
runtime_callbacks->getNativeMethods(env, clazz, old_methods.get(), total);
|
|
||||||
|
|
||||||
// WARNING: the signature field returned from getNativeMethods is in a non-standard format.
|
|
||||||
// DO NOT TRY TO USE IT. This is the reason why we try to call RegisterNatives on every single
|
|
||||||
// provided JNI methods directly to be 100% sure about whether a signature matches or not.
|
|
||||||
|
|
||||||
// Replace methods
|
|
||||||
for (auto &method : methods) {
|
for (auto &method : methods) {
|
||||||
// It's useful to allow nullptr function pointer for restoring hook
|
// It's useful to allow nullptr function pointer for restoring hook
|
||||||
if (!method.fnPtr) continue;
|
if (!method.fnPtr) continue;
|
||||||
|
|
||||||
// It's normal that the method is not found
|
// It's normal that the method is not found
|
||||||
if (env->RegisterNatives(clazz, &method, 1) == JNI_ERR || env->ExceptionCheck() == JNI_TRUE) {
|
if (env->RegisterNatives(clazz, &method, 1) == JNI_ERR || env->ExceptionCheck() == JNI_TRUE) {
|
||||||
if (auto exception = env->ExceptionOccurred()) {
|
|
||||||
env->DeleteLocalRef(exception);
|
|
||||||
}
|
|
||||||
env->ExceptionClear();
|
env->ExceptionClear();
|
||||||
method.fnPtr = nullptr;
|
method.fnPtr = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int HookContext::hook_jni_methods(JNIEnv *env, jclass clazz, JNIMethods methods) const {
|
||||||
|
// Backup existing methods
|
||||||
|
auto o = get_jni_methods(env, clazz);
|
||||||
|
const auto old_methods = span(o.first.get(), o.second);
|
||||||
|
|
||||||
|
// WARNING: the signature field returned from getNativeMethods is in a non-standard format.
|
||||||
|
// DO NOT TRY TO USE IT. This is the reason why we try to call RegisterNatives on every single
|
||||||
|
// provided JNI methods directly to be 100% sure about whether a signature matches or not.
|
||||||
|
|
||||||
|
// Replace methods
|
||||||
|
register_jni_methods(env, clazz, methods);
|
||||||
|
|
||||||
// Fetch the new set of native methods
|
// Fetch the new set of native methods
|
||||||
auto new_methods = std::make_unique_for_overwrite<JNINativeMethod[]>(total);
|
auto n = get_jni_methods(env, clazz);
|
||||||
runtime_callbacks->getNativeMethods(env, clazz, new_methods.get(), total);
|
const auto new_methods = span(n.first.get(), n.second);
|
||||||
|
|
||||||
// Find the old function pointer and return to caller
|
// Find the old function pointer and return to caller
|
||||||
|
int hook_count = 0;
|
||||||
for (auto &method : methods) {
|
for (auto &method : methods) {
|
||||||
if (!method.fnPtr) continue;
|
if (!method.fnPtr) continue;
|
||||||
for (auto i = 0; i < total; ++i) {
|
for (const auto &new_method : new_methods) {
|
||||||
auto &new_method = new_methods[i];
|
|
||||||
if (new_method.fnPtr == method.fnPtr) {
|
if (new_method.fnPtr == method.fnPtr) {
|
||||||
auto &old_method = old_methods[i];
|
for (const auto &old_method : old_methods) {
|
||||||
ZLOGV("replace %s#%s%s %p -> %p\n", clz, method.name, method.signature, old_method.fnPtr, method.fnPtr);
|
if (strcmp(old_method.name, new_method.name) == 0 &&
|
||||||
method.fnPtr = old_method.fnPtr;
|
strcmp(old_method.signature, new_method.signature) == 0) {
|
||||||
break;
|
ZLOGV("replace %s %s %p -> %p\n",
|
||||||
|
method.name, method.signature, old_method.fnPtr, method.fnPtr);
|
||||||
|
method.fnPtr = old_method.fnPtr;
|
||||||
|
++hook_count;
|
||||||
|
// Break 2 levels of for loop
|
||||||
|
goto next_method;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
next_method:
|
||||||
}
|
}
|
||||||
|
return hook_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void HookContext::hook_jni_methods(JNIEnv *env, const char *clz, JNIMethods methods) const {
|
||||||
|
jclass clazz;
|
||||||
|
if (!runtime_callbacks || !env || !clz || !((clazz = env->FindClass(clz)))) {
|
||||||
|
ranges::for_each(methods, [](auto &m) { m.fnPtr = nullptr; });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hook_jni_methods(env, clazz, methods);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HookContext::hook_zygote_jni() {
|
void HookContext::hook_zygote_jni() {
|
||||||
@@ -538,11 +565,54 @@ void HookContext::hook_zygote_jni() {
|
|||||||
if (res != JNI_OK || env == nullptr) {
|
if (res != JNI_OK || env == nullptr) {
|
||||||
ZLOGW("JNIEnv not found\n");
|
ZLOGW("JNIEnv not found\n");
|
||||||
}
|
}
|
||||||
hook_jni_methods(env, kZygote, zygote_methods);
|
|
||||||
|
JNINativeMethod missing_method{};
|
||||||
|
bool replaced_fork_app = false;
|
||||||
|
bool replaced_specialize_app = false;
|
||||||
|
bool replaced_fork_server = false;
|
||||||
|
|
||||||
|
jclass clazz = env->FindClass(kZygote);
|
||||||
|
auto [ptr, count] = get_jni_methods(env, clazz);
|
||||||
|
for (const auto methods = span(ptr.get(), count); const auto &method : methods) {
|
||||||
|
if (strcmp(method.name, kForkApp) == 0) {
|
||||||
|
if (hook_jni_methods(env, clazz, fork_app_methods) == 0) {
|
||||||
|
missing_method = method;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
replaced_fork_app = true;
|
||||||
|
} else if (strcmp(method.name, kSpecializeApp) == 0) {
|
||||||
|
if (hook_jni_methods(env, clazz, specialize_app_methods) == 0) {
|
||||||
|
missing_method = method;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
replaced_specialize_app = true;
|
||||||
|
} else if (strcmp(method.name, kForkServer) == 0) {
|
||||||
|
if (hook_jni_methods(env, clazz, fork_server_methods) == 0) {
|
||||||
|
missing_method = method;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
replaced_fork_server = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missing_method.name != nullptr) {
|
||||||
|
ZLOGE("Cannot hook method: %s %s\n", missing_method.name, missing_method.signature);
|
||||||
|
// Restore methods that were already replaced
|
||||||
|
if (replaced_fork_app) register_jni_methods(env, clazz, fork_app_methods);
|
||||||
|
if (replaced_specialize_app) register_jni_methods(env, clazz, specialize_app_methods);
|
||||||
|
if (replaced_fork_server) register_jni_methods(env, clazz, fork_server_methods);
|
||||||
|
// Clear the method lists just in case
|
||||||
|
ranges::for_each(fork_app_methods, [](auto &m) { m.fnPtr = nullptr; });
|
||||||
|
ranges::for_each(specialize_app_methods, [](auto &m) { m.fnPtr = nullptr; });
|
||||||
|
ranges::for_each(fork_server_methods, [](auto &m) { m.fnPtr = nullptr; });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HookContext::restore_zygote_hook(JNIEnv *env) {
|
void HookContext::restore_zygote_hook(JNIEnv *env) {
|
||||||
hook_jni_methods(env, kZygote, zygote_methods);
|
jclass clazz = env->FindClass(kZygote);
|
||||||
|
register_jni_methods(env, clazz, fork_app_methods);
|
||||||
|
register_jni_methods(env, clazz, specialize_app_methods);
|
||||||
|
register_jni_methods(env, clazz, fork_server_methods);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
@@ -553,5 +623,5 @@ void hook_entry() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void hookJniNativeMethods(JNIEnv *env, const char *clz, JNINativeMethod *methods, int numMethods) {
|
void hookJniNativeMethods(JNIEnv *env, const char *clz, JNINativeMethod *methods, int numMethods) {
|
||||||
g_hook->hook_jni_methods(env, clz, { methods, (size_t) numMethods });
|
g_hook->hook_jni_methods(env, clz, { methods, static_cast<size_t>(numMethods) });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
// Generated by gen_jni_hooks.py
|
// Generated by gen_jni_hooks.py
|
||||||
|
#pragma once
|
||||||
|
|
||||||
std::array<JNINativeMethod, 17> zygote_methods = {{
|
struct JniHookDefinitions;
|
||||||
|
static JniHookDefinitions *get_defs();
|
||||||
|
|
||||||
|
struct JniHookDefinitions {
|
||||||
|
|
||||||
|
std::array<JNINativeMethod, 11> fork_app_methods = {{
|
||||||
|
// nativeForkAndSpecialize_l
|
||||||
{
|
{
|
||||||
"nativeForkAndSpecialize",
|
"nativeForkAndSpecialize",
|
||||||
"(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;Ljava/lang/String;)I",
|
"(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;Ljava/lang/String;)I",
|
||||||
@@ -8,13 +15,14 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
AppSpecializeArgs_v5 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
AppSpecializeArgs_v5 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
||||||
ZygiskContext ctx(env, &args);
|
ZygiskContext ctx(env, &args);
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jstring instruction_set, jstring app_data_dir)>(g_hook->zygote_methods[0].fnPtr)(
|
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jstring instruction_set, jstring app_data_dir)>(get_defs()->fork_app_methods[0].fnPtr)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, instruction_set, app_data_dir
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, instruction_set, app_data_dir
|
||||||
);
|
);
|
||||||
ctx.nativeForkAndSpecialize_post();
|
ctx.nativeForkAndSpecialize_post();
|
||||||
return ctx.pid;
|
return ctx.pid;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// nativeForkAndSpecialize_o
|
||||||
{
|
{
|
||||||
"nativeForkAndSpecialize",
|
"nativeForkAndSpecialize",
|
||||||
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[ILjava/lang/String;Ljava/lang/String;)I",
|
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[ILjava/lang/String;Ljava/lang/String;)I",
|
||||||
@@ -23,13 +31,14 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
args.fds_to_ignore = &fds_to_ignore;
|
args.fds_to_ignore = &fds_to_ignore;
|
||||||
ZygiskContext ctx(env, &args);
|
ZygiskContext ctx(env, &args);
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jstring instruction_set, jstring app_data_dir)>(g_hook->zygote_methods[1].fnPtr)(
|
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jstring instruction_set, jstring app_data_dir)>(get_defs()->fork_app_methods[1].fnPtr)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, instruction_set, app_data_dir
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, instruction_set, app_data_dir
|
||||||
);
|
);
|
||||||
ctx.nativeForkAndSpecialize_post();
|
ctx.nativeForkAndSpecialize_post();
|
||||||
return ctx.pid;
|
return ctx.pid;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// nativeForkAndSpecialize_p
|
||||||
{
|
{
|
||||||
"nativeForkAndSpecialize",
|
"nativeForkAndSpecialize",
|
||||||
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)I",
|
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)I",
|
||||||
@@ -39,13 +48,14 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
args.is_child_zygote = &is_child_zygote;
|
args.is_child_zygote = &is_child_zygote;
|
||||||
ZygiskContext ctx(env, &args);
|
ZygiskContext ctx(env, &args);
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir)>(g_hook->zygote_methods[2].fnPtr)(
|
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir)>(get_defs()->fork_app_methods[2].fnPtr)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir
|
||||||
);
|
);
|
||||||
ctx.nativeForkAndSpecialize_post();
|
ctx.nativeForkAndSpecialize_post();
|
||||||
return ctx.pid;
|
return ctx.pid;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// nativeForkAndSpecialize_q_alt
|
||||||
{
|
{
|
||||||
"nativeForkAndSpecialize",
|
"nativeForkAndSpecialize",
|
||||||
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Z)I",
|
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Z)I",
|
||||||
@@ -56,13 +66,14 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
args.is_top_app = &is_top_app;
|
args.is_top_app = &is_top_app;
|
||||||
ZygiskContext ctx(env, &args);
|
ZygiskContext ctx(env, &args);
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app)>(g_hook->zygote_methods[3].fnPtr)(
|
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app)>(get_defs()->fork_app_methods[3].fnPtr)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir, is_top_app
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir, is_top_app
|
||||||
);
|
);
|
||||||
ctx.nativeForkAndSpecialize_post();
|
ctx.nativeForkAndSpecialize_post();
|
||||||
return ctx.pid;
|
return ctx.pid;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// nativeForkAndSpecialize_r
|
||||||
{
|
{
|
||||||
"nativeForkAndSpecialize",
|
"nativeForkAndSpecialize",
|
||||||
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)I",
|
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)I",
|
||||||
@@ -77,13 +88,14 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
args.mount_storage_dirs = &mount_storage_dirs;
|
args.mount_storage_dirs = &mount_storage_dirs;
|
||||||
ZygiskContext ctx(env, &args);
|
ZygiskContext ctx(env, &args);
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app, jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list, jboolean mount_data_dirs, jboolean mount_storage_dirs)>(g_hook->zygote_methods[4].fnPtr)(
|
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app, jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list, jboolean mount_data_dirs, jboolean mount_storage_dirs)>(get_defs()->fork_app_methods[4].fnPtr)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir, is_top_app, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir, is_top_app, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs
|
||||||
);
|
);
|
||||||
ctx.nativeForkAndSpecialize_post();
|
ctx.nativeForkAndSpecialize_post();
|
||||||
return ctx.pid;
|
return ctx.pid;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// nativeForkAndSpecialize_u
|
||||||
{
|
{
|
||||||
"nativeForkAndSpecialize",
|
"nativeForkAndSpecialize",
|
||||||
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Z[Ljava/lang/String;[Ljava/lang/String;ZZZ)I",
|
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Z[Ljava/lang/String;[Ljava/lang/String;ZZZ)I",
|
||||||
@@ -99,13 +111,37 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
args.mount_sysprop_overrides = &mount_sysprop_overrides;
|
args.mount_sysprop_overrides = &mount_sysprop_overrides;
|
||||||
ZygiskContext ctx(env, &args);
|
ZygiskContext ctx(env, &args);
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app, jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list, jboolean mount_data_dirs, jboolean mount_storage_dirs, jboolean mount_sysprop_overrides)>(g_hook->zygote_methods[5].fnPtr)(
|
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app, jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list, jboolean mount_data_dirs, jboolean mount_storage_dirs, jboolean mount_sysprop_overrides)>(get_defs()->fork_app_methods[5].fnPtr)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir, is_top_app, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs, mount_sysprop_overrides
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir, is_top_app, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs, mount_sysprop_overrides
|
||||||
);
|
);
|
||||||
ctx.nativeForkAndSpecialize_post();
|
ctx.nativeForkAndSpecialize_post();
|
||||||
return ctx.pid;
|
return ctx.pid;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// nativeForkAndSpecialize_b
|
||||||
|
{
|
||||||
|
"nativeForkAndSpecialize",
|
||||||
|
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;ZZ[Ljava/lang/String;[Ljava/lang/String;ZZZ)I",
|
||||||
|
(void *) +[] [[clang::no_stack_protector]] (JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app, jboolean use_fifo_ui, jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list, jboolean mount_data_dirs, jboolean mount_storage_dirs, jboolean mount_sysprop_overrides) static -> jint {
|
||||||
|
AppSpecializeArgs_v5 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
||||||
|
args.fds_to_ignore = &fds_to_ignore;
|
||||||
|
args.is_child_zygote = &is_child_zygote;
|
||||||
|
args.is_top_app = &is_top_app;
|
||||||
|
args.pkg_data_info_list = &pkg_data_info_list;
|
||||||
|
args.whitelisted_data_info_list = &whitelisted_data_info_list;
|
||||||
|
args.mount_data_dirs = &mount_data_dirs;
|
||||||
|
args.mount_storage_dirs = &mount_storage_dirs;
|
||||||
|
args.mount_sysprop_overrides = &mount_sysprop_overrides;
|
||||||
|
ZygiskContext ctx(env, &args);
|
||||||
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
|
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app, jboolean use_fifo_ui, jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list, jboolean mount_data_dirs, jboolean mount_storage_dirs, jboolean mount_sysprop_overrides)>(get_defs()->fork_app_methods[6].fnPtr)(
|
||||||
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir, is_top_app, use_fifo_ui, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs, mount_sysprop_overrides
|
||||||
|
);
|
||||||
|
ctx.nativeForkAndSpecialize_post();
|
||||||
|
return ctx.pid;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// nativeForkAndSpecialize_samsung_m
|
||||||
{
|
{
|
||||||
"nativeForkAndSpecialize",
|
"nativeForkAndSpecialize",
|
||||||
"(II[II[[IILjava/lang/String;IILjava/lang/String;[ILjava/lang/String;Ljava/lang/String;)I",
|
"(II[II[[IILjava/lang/String;IILjava/lang/String;[ILjava/lang/String;Ljava/lang/String;)I",
|
||||||
@@ -113,13 +149,14 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
AppSpecializeArgs_v5 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
AppSpecializeArgs_v5 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
||||||
ZygiskContext ctx(env, &args);
|
ZygiskContext ctx(env, &args);
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _0, jint _1, jstring nice_name, jintArray fds_to_close, jstring instruction_set, jstring app_data_dir)>(g_hook->zygote_methods[6].fnPtr)(
|
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _0, jint _1, jstring nice_name, jintArray fds_to_close, jstring instruction_set, jstring app_data_dir)>(get_defs()->fork_app_methods[7].fnPtr)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _0, _1, nice_name, fds_to_close, instruction_set, app_data_dir
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _0, _1, nice_name, fds_to_close, instruction_set, app_data_dir
|
||||||
);
|
);
|
||||||
ctx.nativeForkAndSpecialize_post();
|
ctx.nativeForkAndSpecialize_post();
|
||||||
return ctx.pid;
|
return ctx.pid;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// nativeForkAndSpecialize_samsung_n
|
||||||
{
|
{
|
||||||
"nativeForkAndSpecialize",
|
"nativeForkAndSpecialize",
|
||||||
"(II[II[[IILjava/lang/String;IILjava/lang/String;[ILjava/lang/String;Ljava/lang/String;I)I",
|
"(II[II[[IILjava/lang/String;IILjava/lang/String;[ILjava/lang/String;Ljava/lang/String;I)I",
|
||||||
@@ -127,13 +164,14 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
AppSpecializeArgs_v5 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
AppSpecializeArgs_v5 args(uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, instruction_set, app_data_dir);
|
||||||
ZygiskContext ctx(env, &args);
|
ZygiskContext ctx(env, &args);
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _2, jint _3, jstring nice_name, jintArray fds_to_close, jstring instruction_set, jstring app_data_dir, jint _4)>(g_hook->zygote_methods[7].fnPtr)(
|
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _2, jint _3, jstring nice_name, jintArray fds_to_close, jstring instruction_set, jstring app_data_dir, jint _4)>(get_defs()->fork_app_methods[8].fnPtr)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _2, _3, nice_name, fds_to_close, instruction_set, app_data_dir, _4
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _2, _3, nice_name, fds_to_close, instruction_set, app_data_dir, _4
|
||||||
);
|
);
|
||||||
ctx.nativeForkAndSpecialize_post();
|
ctx.nativeForkAndSpecialize_post();
|
||||||
return ctx.pid;
|
return ctx.pid;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// nativeForkAndSpecialize_samsung_o
|
||||||
{
|
{
|
||||||
"nativeForkAndSpecialize",
|
"nativeForkAndSpecialize",
|
||||||
"(II[II[[IILjava/lang/String;IILjava/lang/String;[I[ILjava/lang/String;Ljava/lang/String;)I",
|
"(II[II[[IILjava/lang/String;IILjava/lang/String;[I[ILjava/lang/String;Ljava/lang/String;)I",
|
||||||
@@ -142,13 +180,14 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
args.fds_to_ignore = &fds_to_ignore;
|
args.fds_to_ignore = &fds_to_ignore;
|
||||||
ZygiskContext ctx(env, &args);
|
ZygiskContext ctx(env, &args);
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _5, jint _6, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jstring instruction_set, jstring app_data_dir)>(g_hook->zygote_methods[8].fnPtr)(
|
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _5, jint _6, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jstring instruction_set, jstring app_data_dir)>(get_defs()->fork_app_methods[9].fnPtr)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _5, _6, nice_name, fds_to_close, fds_to_ignore, instruction_set, app_data_dir
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _5, _6, nice_name, fds_to_close, fds_to_ignore, instruction_set, app_data_dir
|
||||||
);
|
);
|
||||||
ctx.nativeForkAndSpecialize_post();
|
ctx.nativeForkAndSpecialize_post();
|
||||||
return ctx.pid;
|
return ctx.pid;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// nativeForkAndSpecialize_samsung_p
|
||||||
{
|
{
|
||||||
"nativeForkAndSpecialize",
|
"nativeForkAndSpecialize",
|
||||||
"(II[II[[IILjava/lang/String;IILjava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)I",
|
"(II[II[[IILjava/lang/String;IILjava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)I",
|
||||||
@@ -158,13 +197,17 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
args.is_child_zygote = &is_child_zygote;
|
args.is_child_zygote = &is_child_zygote;
|
||||||
ZygiskContext ctx(env, &args);
|
ZygiskContext ctx(env, &args);
|
||||||
ctx.nativeForkAndSpecialize_pre();
|
ctx.nativeForkAndSpecialize_pre();
|
||||||
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _7, jint _8, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir)>(g_hook->zygote_methods[9].fnPtr)(
|
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _7, jint _8, jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir)>(get_defs()->fork_app_methods[10].fnPtr)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _7, _8, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _7, _8, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir
|
||||||
);
|
);
|
||||||
ctx.nativeForkAndSpecialize_post();
|
ctx.nativeForkAndSpecialize_post();
|
||||||
return ctx.pid;
|
return ctx.pid;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
}};
|
||||||
|
|
||||||
|
std::array<JNINativeMethod, 5> specialize_app_methods = {{
|
||||||
|
// nativeSpecializeAppProcess_q
|
||||||
{
|
{
|
||||||
"nativeSpecializeAppProcess",
|
"nativeSpecializeAppProcess",
|
||||||
"(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;)V",
|
"(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;)V",
|
||||||
@@ -173,12 +216,13 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
args.is_child_zygote = &is_child_zygote;
|
args.is_child_zygote = &is_child_zygote;
|
||||||
ZygiskContext ctx(env, &args);
|
ZygiskContext ctx(env, &args);
|
||||||
ctx.nativeSpecializeAppProcess_pre();
|
ctx.nativeSpecializeAppProcess_pre();
|
||||||
reinterpret_cast<void(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir)>(g_hook->zygote_methods[10].fnPtr)(
|
reinterpret_cast<void(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir)>(get_defs()->specialize_app_methods[0].fnPtr)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir
|
||||||
);
|
);
|
||||||
ctx.nativeSpecializeAppProcess_post();
|
ctx.nativeSpecializeAppProcess_post();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// nativeSpecializeAppProcess_q_alt
|
||||||
{
|
{
|
||||||
"nativeSpecializeAppProcess",
|
"nativeSpecializeAppProcess",
|
||||||
"(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Z)V",
|
"(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Z)V",
|
||||||
@@ -188,12 +232,13 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
args.is_top_app = &is_top_app;
|
args.is_top_app = &is_top_app;
|
||||||
ZygiskContext ctx(env, &args);
|
ZygiskContext ctx(env, &args);
|
||||||
ctx.nativeSpecializeAppProcess_pre();
|
ctx.nativeSpecializeAppProcess_pre();
|
||||||
reinterpret_cast<void(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app)>(g_hook->zygote_methods[11].fnPtr)(
|
reinterpret_cast<void(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app)>(get_defs()->specialize_app_methods[1].fnPtr)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir, is_top_app
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir, is_top_app
|
||||||
);
|
);
|
||||||
ctx.nativeSpecializeAppProcess_post();
|
ctx.nativeSpecializeAppProcess_post();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// nativeSpecializeAppProcess_r
|
||||||
{
|
{
|
||||||
"nativeSpecializeAppProcess",
|
"nativeSpecializeAppProcess",
|
||||||
"(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)V",
|
"(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)V",
|
||||||
@@ -207,12 +252,13 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
args.mount_storage_dirs = &mount_storage_dirs;
|
args.mount_storage_dirs = &mount_storage_dirs;
|
||||||
ZygiskContext ctx(env, &args);
|
ZygiskContext ctx(env, &args);
|
||||||
ctx.nativeSpecializeAppProcess_pre();
|
ctx.nativeSpecializeAppProcess_pre();
|
||||||
reinterpret_cast<void(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app, jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list, jboolean mount_data_dirs, jboolean mount_storage_dirs)>(g_hook->zygote_methods[12].fnPtr)(
|
reinterpret_cast<void(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app, jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list, jboolean mount_data_dirs, jboolean mount_storage_dirs)>(get_defs()->specialize_app_methods[2].fnPtr)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir, is_top_app, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir, is_top_app, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs
|
||||||
);
|
);
|
||||||
ctx.nativeSpecializeAppProcess_post();
|
ctx.nativeSpecializeAppProcess_post();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// nativeSpecializeAppProcess_u
|
||||||
{
|
{
|
||||||
"nativeSpecializeAppProcess",
|
"nativeSpecializeAppProcess",
|
||||||
"(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Z[Ljava/lang/String;[Ljava/lang/String;ZZZ)V",
|
"(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Z[Ljava/lang/String;[Ljava/lang/String;ZZZ)V",
|
||||||
@@ -227,12 +273,13 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
args.mount_sysprop_overrides = &mount_sysprop_overrides;
|
args.mount_sysprop_overrides = &mount_sysprop_overrides;
|
||||||
ZygiskContext ctx(env, &args);
|
ZygiskContext ctx(env, &args);
|
||||||
ctx.nativeSpecializeAppProcess_pre();
|
ctx.nativeSpecializeAppProcess_pre();
|
||||||
reinterpret_cast<void(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app, jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list, jboolean mount_data_dirs, jboolean mount_storage_dirs, jboolean mount_sysprop_overrides)>(g_hook->zygote_methods[13].fnPtr)(
|
reinterpret_cast<void(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app, jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list, jboolean mount_data_dirs, jboolean mount_storage_dirs, jboolean mount_sysprop_overrides)>(get_defs()->specialize_app_methods[3].fnPtr)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir, is_top_app, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs, mount_sysprop_overrides
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, nice_name, is_child_zygote, instruction_set, app_data_dir, is_top_app, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs, mount_storage_dirs, mount_sysprop_overrides
|
||||||
);
|
);
|
||||||
ctx.nativeSpecializeAppProcess_post();
|
ctx.nativeSpecializeAppProcess_post();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// nativeSpecializeAppProcess_samsung_q
|
||||||
{
|
{
|
||||||
"nativeSpecializeAppProcess",
|
"nativeSpecializeAppProcess",
|
||||||
"(II[II[[IILjava/lang/String;IILjava/lang/String;ZLjava/lang/String;Ljava/lang/String;)V",
|
"(II[II[[IILjava/lang/String;IILjava/lang/String;ZLjava/lang/String;Ljava/lang/String;)V",
|
||||||
@@ -241,12 +288,16 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
args.is_child_zygote = &is_child_zygote;
|
args.is_child_zygote = &is_child_zygote;
|
||||||
ZygiskContext ctx(env, &args);
|
ZygiskContext ctx(env, &args);
|
||||||
ctx.nativeSpecializeAppProcess_pre();
|
ctx.nativeSpecializeAppProcess_pre();
|
||||||
reinterpret_cast<void(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _9, jint _10, jstring nice_name, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir)>(g_hook->zygote_methods[14].fnPtr)(
|
reinterpret_cast<void(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jint _9, jint _10, jstring nice_name, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir)>(get_defs()->specialize_app_methods[4].fnPtr)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _9, _10, nice_name, is_child_zygote, instruction_set, app_data_dir
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, mount_external, se_info, _9, _10, nice_name, is_child_zygote, instruction_set, app_data_dir
|
||||||
);
|
);
|
||||||
ctx.nativeSpecializeAppProcess_post();
|
ctx.nativeSpecializeAppProcess_post();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
}};
|
||||||
|
|
||||||
|
std::array<JNINativeMethod, 2> fork_server_methods = {{
|
||||||
|
// nativeForkSystemServer_l
|
||||||
{
|
{
|
||||||
"nativeForkSystemServer",
|
"nativeForkSystemServer",
|
||||||
"(II[II[[IJJ)I",
|
"(II[II[[IJJ)I",
|
||||||
@@ -254,13 +305,14 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
ServerSpecializeArgs_v1 args(uid, gid, gids, runtime_flags, permitted_capabilities, effective_capabilities);
|
ServerSpecializeArgs_v1 args(uid, gid, gids, runtime_flags, permitted_capabilities, effective_capabilities);
|
||||||
ZygiskContext ctx(env, &args);
|
ZygiskContext ctx(env, &args);
|
||||||
ctx.nativeForkSystemServer_pre();
|
ctx.nativeForkSystemServer_pre();
|
||||||
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities, jlong effective_capabilities)>(g_hook->zygote_methods[15].fnPtr)(
|
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities, jlong effective_capabilities)>(get_defs()->fork_server_methods[0].fnPtr)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities, effective_capabilities
|
env, clazz, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities, effective_capabilities
|
||||||
);
|
);
|
||||||
ctx.nativeForkSystemServer_post();
|
ctx.nativeForkSystemServer_post();
|
||||||
return ctx.pid;
|
return ctx.pid;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// nativeForkSystemServer_samsung_q
|
||||||
{
|
{
|
||||||
"nativeForkSystemServer",
|
"nativeForkSystemServer",
|
||||||
"(II[IIII[[IJJ)I",
|
"(II[IIII[[IJJ)I",
|
||||||
@@ -268,7 +320,7 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
ServerSpecializeArgs_v1 args(uid, gid, gids, runtime_flags, permitted_capabilities, effective_capabilities);
|
ServerSpecializeArgs_v1 args(uid, gid, gids, runtime_flags, permitted_capabilities, effective_capabilities);
|
||||||
ZygiskContext ctx(env, &args);
|
ZygiskContext ctx(env, &args);
|
||||||
ctx.nativeForkSystemServer_pre();
|
ctx.nativeForkSystemServer_pre();
|
||||||
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jint _11, jint _12, jobjectArray rlimits, jlong permitted_capabilities, jlong effective_capabilities)>(g_hook->zygote_methods[16].fnPtr)(
|
reinterpret_cast<jint(*)(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jint _11, jint _12, jobjectArray rlimits, jlong permitted_capabilities, jlong effective_capabilities)>(get_defs()->fork_server_methods[1].fnPtr)(
|
||||||
env, clazz, uid, gid, gids, runtime_flags, _11, _12, rlimits, permitted_capabilities, effective_capabilities
|
env, clazz, uid, gid, gids, runtime_flags, _11, _12, rlimits, permitted_capabilities, effective_capabilities
|
||||||
);
|
);
|
||||||
ctx.nativeForkSystemServer_post();
|
ctx.nativeForkSystemServer_post();
|
||||||
@@ -277,3 +329,4 @@ std::array<JNINativeMethod, 17> zygote_methods = {{
|
|||||||
},
|
},
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
};
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Extreme verbose logging
|
// Extreme verbose logging
|
||||||
//#define ZLOGV(...) ZLOGD(__VA_ARGS__)
|
// #define ZLOGV(...) ZLOGD(__VA_ARGS__)
|
||||||
#define ZLOGV(...) (void*)0
|
#define ZLOGV(...) (void*)0
|
||||||
|
|
||||||
void hook_entry();
|
void hook_entry();
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ edition.workspace = true
|
|||||||
crate-type = ["staticlib"]
|
crate-type = ["staticlib"]
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cxx-gen = { workspace = true }
|
cxx-gen = { workspace = true }
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
use crate::ffi::{BootConfig, MagiskInit, backup_init, magisk_proxy_main};
|
use crate::ffi::{BootConfig, MagiskInit, backup_init, magisk_proxy_main};
|
||||||
use crate::logging::setup_klog;
|
use crate::logging::setup_klog;
|
||||||
use crate::mount::{is_rootfs, occupy, unoccupy};
|
use crate::mount::is_rootfs;
|
||||||
use crate::twostage::hexpatch_init_for_second_stage;
|
use crate::twostage::hexpatch_init_for_second_stage;
|
||||||
use base::libc::{basename, getpid, mount, umask};
|
use base::libc::{basename, getpid, mount, umask};
|
||||||
use base::nix::mount::MsFlags;
|
use base::{LibcReturn, LoggedResult, ResultExt, cstr, info, raw_cstr};
|
||||||
use base::{LibcReturn, LoggedResult, ResultExt, Utf8CStr, cstr, info, nix, raw_cstr};
|
|
||||||
use std::ffi::{CStr, c_char};
|
use std::ffi::{CStr, c_char};
|
||||||
use std::ptr::null;
|
use std::ptr::null;
|
||||||
|
|
||||||
@@ -32,7 +31,7 @@ impl MagiskInit {
|
|||||||
|
|
||||||
fn first_stage(&self) {
|
fn first_stage(&self) {
|
||||||
info!("First Stage Init");
|
info!("First Stage Init");
|
||||||
let rootfs_magisktmp = self.prepare_data(true);
|
self.prepare_data();
|
||||||
|
|
||||||
if !cstr!("/sdcard").exists() && !cstr!("/first_stage_ramdisk/sdcard").exists() {
|
if !cstr!("/sdcard").exists() && !cstr!("/first_stage_ramdisk/sdcard").exists() {
|
||||||
self.hijack_init_with_switch_root();
|
self.hijack_init_with_switch_root();
|
||||||
@@ -42,28 +41,11 @@ impl MagiskInit {
|
|||||||
// Fallback to hexpatch if /sdcard exists
|
// Fallback to hexpatch if /sdcard exists
|
||||||
hexpatch_init_for_second_stage(true);
|
hexpatch_init_for_second_stage(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if rootfs_magisktmp {
|
|
||||||
info!("Occupy /data");
|
|
||||||
occupy(cstr!("/data"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn second_stage(&mut self) {
|
fn second_stage(&mut self) {
|
||||||
info!("Second Stage Init");
|
info!("Second Stage Init");
|
||||||
|
|
||||||
if unoccupy(cstr!("/data")) {
|
|
||||||
nix::mount::mount(
|
|
||||||
None::<&Utf8CStr>,
|
|
||||||
cstr!("/data"),
|
|
||||||
None::<&Utf8CStr>,
|
|
||||||
MsFlags::MS_REMOUNT,
|
|
||||||
Some(cstr!("size=100%")),
|
|
||||||
)
|
|
||||||
.check_os_err("mount", Some("/data"), Some("tmpfs"))
|
|
||||||
.log_ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
cstr!("/init").unmount().ok();
|
cstr!("/init").unmount().ok();
|
||||||
cstr!("/system/bin/init").unmount().ok(); // just in case
|
cstr!("/system/bin/init").unmount().ok(); // just in case
|
||||||
cstr!("/data/init").remove().ok();
|
cstr!("/data/init").remove().ok();
|
||||||
@@ -89,7 +71,7 @@ impl MagiskInit {
|
|||||||
|
|
||||||
fn legacy_system_as_root(&mut self) {
|
fn legacy_system_as_root(&mut self) {
|
||||||
info!("Legacy SAR Init");
|
info!("Legacy SAR Init");
|
||||||
self.prepare_data(false);
|
self.prepare_data();
|
||||||
let is_two_stage = self.mount_system_root();
|
let is_two_stage = self.mount_system_root();
|
||||||
if is_two_stage {
|
if is_two_stage {
|
||||||
hexpatch_init_for_second_stage(false);
|
hexpatch_init_for_second_stage(false);
|
||||||
@@ -100,7 +82,7 @@ impl MagiskInit {
|
|||||||
|
|
||||||
fn rootfs(&mut self) {
|
fn rootfs(&mut self) {
|
||||||
info!("RootFS Init");
|
info!("RootFS Init");
|
||||||
self.prepare_data(false);
|
self.prepare_data();
|
||||||
self.restore_ramdisk_init();
|
self.restore_ramdisk_init();
|
||||||
self.patch_rw_root();
|
self.patch_rw_root();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
use crate::ffi::MagiskInit;
|
use crate::ffi::MagiskInit;
|
||||||
use base::WalkResult::{Continue, Skip};
|
|
||||||
use base::nix::mount::{MntFlags, mount, umount2};
|
|
||||||
use base::{
|
use base::{
|
||||||
Directory, FsPathBuilder, LibcReturn, LoggedResult, ResultExt, Utf8CStr, cstr, debug, libc,
|
Directory, FsPathBuilder, LibcReturn, LoggedResult, ResultExt, Utf8CStr, cstr, debug, libc,
|
||||||
nix, parse_mount_info, raw_cstr,
|
nix, parse_mount_info, raw_cstr,
|
||||||
@@ -64,54 +62,6 @@ pub(crate) fn is_device_mounted(dev: u64, target: Pin<&mut CxxString>) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn occupy(path: &Utf8CStr) {
|
|
||||||
Directory::open(path)
|
|
||||||
.map(|mut dir| {
|
|
||||||
dir.pre_order_walk(|entry| {
|
|
||||||
let mut path = cstr::buf::default();
|
|
||||||
entry.resolve_path(&mut path)?;
|
|
||||||
let path = path.as_utf8_cstr();
|
|
||||||
mount(
|
|
||||||
Some(path),
|
|
||||||
path,
|
|
||||||
None::<&Utf8CStr>,
|
|
||||||
MsFlags::MS_BIND | MsFlags::MS_RDONLY,
|
|
||||||
None::<&Utf8CStr>,
|
|
||||||
)
|
|
||||||
.check_os_err("occupy", Some(path), None)?;
|
|
||||||
Ok(Continue)
|
|
||||||
})
|
|
||||||
.log_ok();
|
|
||||||
})
|
|
||||||
.log_ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn unoccupy(path: &Utf8CStr) -> bool {
|
|
||||||
let mut ok = false;
|
|
||||||
Directory::open(path)
|
|
||||||
.map(|mut dir| {
|
|
||||||
ok = dir
|
|
||||||
.pre_order_walk(|entry| {
|
|
||||||
let mut path = cstr::buf::default();
|
|
||||||
entry.resolve_path(&mut path)?;
|
|
||||||
let path = path.as_utf8_cstr();
|
|
||||||
umount2(path, MntFlags::MNT_DETACH).check_os_err(
|
|
||||||
"unoccupy",
|
|
||||||
Some(path),
|
|
||||||
None,
|
|
||||||
)?;
|
|
||||||
if entry.is_dir() {
|
|
||||||
Ok(Skip)
|
|
||||||
} else {
|
|
||||||
Ok(Continue)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.is_ok();
|
|
||||||
})
|
|
||||||
.log_ok();
|
|
||||||
ok
|
|
||||||
}
|
|
||||||
|
|
||||||
const RAMFS_MAGIC: u32 = 0x858458f6;
|
const RAMFS_MAGIC: u32 = 0x858458f6;
|
||||||
|
|
||||||
pub(crate) fn is_rootfs() -> bool {
|
pub(crate) fn is_rootfs() -> bool {
|
||||||
@@ -123,44 +73,22 @@ pub(crate) fn is_rootfs() -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MagiskInit {
|
impl MagiskInit {
|
||||||
pub(crate) fn prepare_data(&self, use_rootfs: bool) -> bool {
|
pub(crate) fn prepare_data(&self) {
|
||||||
debug!("Setup data tmp");
|
debug!("Setup data tmp");
|
||||||
cstr!("/data").mkdir(0o755).log_ok();
|
cstr!("/data").mkdir(0o755).log_ok();
|
||||||
|
nix::mount::mount(
|
||||||
|
Some(cstr!("magisk")),
|
||||||
|
cstr!("/data"),
|
||||||
|
Some(cstr!("tmpfs")),
|
||||||
|
MsFlags::empty(),
|
||||||
|
Some(cstr!("mode=755")),
|
||||||
|
)
|
||||||
|
.check_os_err("mount", Some("/data"), Some("tmpfs"))
|
||||||
|
.log_ok();
|
||||||
|
|
||||||
let mut rootfs_magisktmp = false;
|
cstr!("/init").copy_to(cstr!("/data/magiskinit")).ok();
|
||||||
|
cstr!("/.backup").copy_to(cstr!("/data/.backup")).ok();
|
||||||
if use_rootfs {
|
cstr!("/overlay.d").copy_to(cstr!("/data/overlay.d")).ok();
|
||||||
cstr!("/magisk").mkdir(0o755).log_ok();
|
|
||||||
rootfs_magisktmp = cstr!("/magisk")
|
|
||||||
.bind_mount_to(cstr!("/data"), false)
|
|
||||||
.is_ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
if rootfs_magisktmp {
|
|
||||||
cstr!("/init")
|
|
||||||
.rename_to(cstr!("/magisk/magiskinit"))
|
|
||||||
.log_ok();
|
|
||||||
cstr!("/.backup").copy_to(cstr!("/magisk/.backup")).ok();
|
|
||||||
cstr!("/overlay.d")
|
|
||||||
.rename_to(cstr!("/magisk/overlay.d"))
|
|
||||||
.ok();
|
|
||||||
} else {
|
|
||||||
nix::mount::mount(
|
|
||||||
Some(cstr!("magisk")),
|
|
||||||
cstr!("/data"),
|
|
||||||
Some(cstr!("tmpfs")),
|
|
||||||
MsFlags::empty(),
|
|
||||||
Some(cstr!("mode=755")),
|
|
||||||
)
|
|
||||||
.check_os_err("mount", Some("/data"), Some("tmpfs"))
|
|
||||||
.log_ok();
|
|
||||||
|
|
||||||
cstr!("/init").copy_to(cstr!("/data/magiskinit")).ok();
|
|
||||||
cstr!("/.backup").copy_to(cstr!("/data/.backup")).ok();
|
|
||||||
cstr!("/overlay.d").copy_to(cstr!("/data/overlay.d")).ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
rootfs_magisktmp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn exec_init(&mut self) {
|
pub(crate) fn exec_init(&mut self) {
|
||||||
|
|||||||
@@ -84,14 +84,20 @@ impl MagiskInit {
|
|||||||
.log_ok();
|
.log_ok();
|
||||||
debug!("Symlink /storage/self/primary -> /system/system/bin/init");
|
debug!("Symlink /storage/self/primary -> /system/system/bin/init");
|
||||||
}
|
}
|
||||||
|
cstr!("/init").rename_to(cstr!("/sdcard")).log_ok();
|
||||||
|
|
||||||
// Binding mounting from rootfs is not supported before Linux 3.12
|
// First try to mount magiskinit from rootfs to workaround Samsung RKP
|
||||||
cstr!("/sdcard")
|
if cstr!("/sdcard")
|
||||||
.create(OFlag::O_RDONLY | OFlag::O_CLOEXEC, 0)
|
|
||||||
.log_ok();
|
|
||||||
cstr!("/data/magiskinit")
|
|
||||||
.bind_mount_to(cstr!("/sdcard"), false)
|
.bind_mount_to(cstr!("/sdcard"), false)
|
||||||
.log_ok();
|
.is_ok()
|
||||||
debug!("Bind mount /data/magiskinit -> /sdcard");
|
{
|
||||||
|
debug!("Bind mount /sdcard -> /sdcard");
|
||||||
|
} else {
|
||||||
|
// Binding mounting from rootfs is not supported before Linux 3.12
|
||||||
|
cstr!("/data/magiskinit")
|
||||||
|
.bind_mount_to(cstr!("/sdcard"), false)
|
||||||
|
.log_ok();
|
||||||
|
debug!("Bind mount /data/magiskinit -> /sdcard");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,15 @@ edition.workspace = true
|
|||||||
crate-type = ["staticlib", "rlib"]
|
crate-type = ["staticlib", "rlib"]
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
cxx-gen = { workspace = true }
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
no-main = []
|
no-main = []
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
cxx-gen = { workspace = true }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base = { workspace = true }
|
base = { workspace = true }
|
||||||
cxx = { workspace = true }
|
cxx = { workspace = true }
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ impl SePolicy {
|
|||||||
allow(["kernel"], ["rootfs", "tmpfs"], ["chr_file"], ["write"]);
|
allow(["kernel"], ["rootfs", "tmpfs"], ["chr_file"], ["write"]);
|
||||||
|
|
||||||
// Allow magiskinit daemon to handle mock selinuxfs
|
// Allow magiskinit daemon to handle mock selinuxfs
|
||||||
allow(["kernel"], ["rootfs", "tmpfs"], ["fifo_file"], ["open", "read", "write"]);
|
allow(["kernel"], ["tmpfs"], ["fifo_file"], ["open", "read", "write"]);
|
||||||
|
|
||||||
// For relabelling files
|
// For relabelling files
|
||||||
allow(["rootfs"], ["labeledfs", "tmpfs"], ["filesystem"], ["associate"]);
|
allow(["rootfs"], ["labeledfs", "tmpfs"], ["filesystem"], ["associate"]);
|
||||||
|
|||||||
@@ -32,17 +32,17 @@ case $(uname -m) in
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
pkill -INT -P $$
|
|
||||||
wait
|
|
||||||
trap - EXIT
|
|
||||||
rm -f magisk_*.img
|
rm -f magisk_*.img
|
||||||
"$avd" delete avd -n test
|
"$avd" delete avd -n test
|
||||||
exit 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test_error() {
|
test_error() {
|
||||||
|
trap - EXIT
|
||||||
print_error "! An error occurred"
|
print_error "! An error occurred"
|
||||||
|
pkill -INT -P $$
|
||||||
|
wait
|
||||||
cleanup
|
cleanup
|
||||||
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
wait_for_boot() {
|
wait_for_boot() {
|
||||||
@@ -72,13 +72,14 @@ wait_emu() {
|
|||||||
|
|
||||||
dump_vars() {
|
dump_vars() {
|
||||||
local val
|
local val
|
||||||
for name in $@; do
|
for name in $@ emu_args; do
|
||||||
eval val=\$$name
|
eval val=\$$name
|
||||||
echo $name=\"$val\"\;
|
echo $name=\"$val\"\;
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve_vars() {
|
resolve_vars() {
|
||||||
|
set +x
|
||||||
local arg_list="$1"
|
local arg_list="$1"
|
||||||
local ver=$2
|
local ver=$2
|
||||||
local type=$3
|
local type=$3
|
||||||
@@ -138,8 +139,14 @@ dl_emu() {
|
|||||||
|
|
||||||
setup_emu() {
|
setup_emu() {
|
||||||
local avd_pkg=$1
|
local avd_pkg=$1
|
||||||
|
local ver=$2
|
||||||
dl_emu $avd_pkg
|
dl_emu $avd_pkg
|
||||||
echo no | "$avd" create avd -f -n test -k $avd_pkg
|
echo no | "$avd" create avd -f -n test -k $avd_pkg
|
||||||
|
|
||||||
|
# avdmanager is outdated, it might not set the proper target
|
||||||
|
local ini=$ANDROID_AVD_HOME/test.ini
|
||||||
|
sed "s:^target\s*=.*:target=android-$ver:g" $ini > $ini.new
|
||||||
|
mv $ini.new $ini
|
||||||
}
|
}
|
||||||
|
|
||||||
test_emu() {
|
test_emu() {
|
||||||
@@ -169,16 +176,15 @@ test_emu() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test_main() {
|
test_main() {
|
||||||
local avd_pkg ramdisk vars
|
local ver avd_pkg ramdisk
|
||||||
vars=$(resolve_vars "emu_args avd_pkg ramdisk" $1 $2)
|
eval $(resolve_vars "ver avd_pkg ramdisk" $1 $2)
|
||||||
eval $vars
|
|
||||||
|
|
||||||
# Specify an explicit port so that tests can run with other emulators running at the same time
|
# Specify an explicit port so that tests can run with other emulators running at the same time
|
||||||
local emu_port=5682
|
local emu_port=5682
|
||||||
emu_args="$emu_args -port $emu_port"
|
emu_args="$emu_args -port $emu_port"
|
||||||
export ANDROID_SERIAL="emulator-$emu_port"
|
export ANDROID_SERIAL="emulator-$emu_port"
|
||||||
|
|
||||||
setup_emu "$avd_pkg"
|
setup_emu "$avd_pkg" $ver
|
||||||
|
|
||||||
# Restart ADB daemon just in case
|
# Restart ADB daemon just in case
|
||||||
adb kill-server
|
adb kill-server
|
||||||
@@ -211,24 +217,21 @@ test_main() {
|
|||||||
test_emu release
|
test_emu release
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Cleanup
|
cleanup
|
||||||
rm -f magisk_*.img
|
|
||||||
"$avd" delete avd -n test
|
|
||||||
}
|
}
|
||||||
|
|
||||||
run_main() {
|
run_main() {
|
||||||
local avd_pkg vars
|
local ver avd_pkg
|
||||||
vars=$(resolve_vars "emu_args avd_pkg" $1 $2)
|
eval $(resolve_vars "ver avd_pkg" $1 $2)
|
||||||
eval $vars
|
setup_emu "$avd_pkg" $ver
|
||||||
setup_emu "$avd_pkg"
|
|
||||||
print_title "* Launching $avd_pkg"
|
print_title "* Launching $avd_pkg"
|
||||||
"$emu" @test $emu_args 2>/dev/null
|
"$emu" @test $emu_args 2>/dev/null
|
||||||
|
cleanup
|
||||||
}
|
}
|
||||||
|
|
||||||
dl_main() {
|
dl_main() {
|
||||||
local avd_pkg vars
|
local avd_pkg
|
||||||
vars=$(resolve_vars "avd_pkg" $1 $2)
|
eval $(resolve_vars "avd_pkg" $1 $2)
|
||||||
eval $vars
|
|
||||||
print_title "* Downloading $avd_pkg"
|
print_title "* Downloading $avd_pkg"
|
||||||
dl_emu "$avd_pkg"
|
dl_emu "$avd_pkg"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,25 +36,6 @@ disable_version_config() {
|
|||||||
sed -i "s:^version=:# version=:g" $CONFIG
|
sed -i "s:^version=:# version=:g" $CONFIG
|
||||||
}
|
}
|
||||||
|
|
||||||
bump_canary_version() {
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# Commit version code changes
|
|
||||||
git add -u .
|
|
||||||
git status
|
|
||||||
git commit -m "Release new canary build" -m "[skip ci]"
|
|
||||||
git tag $tag
|
|
||||||
|
|
||||||
# Update version name
|
|
||||||
local ver=$(git rev-parse --short=8 HEAD)
|
|
||||||
sed -i "s:version=.*:version=${ver}:g" $CONFIG
|
|
||||||
sed -i "1s:.*:## Magisk (${ver}) (${code}):" $NOTES
|
|
||||||
}
|
|
||||||
|
|
||||||
# $1 = ver
|
# $1 = ver
|
||||||
set_version() {
|
set_version() {
|
||||||
local ver=$1
|
local ver=$1
|
||||||
@@ -69,89 +50,45 @@ set_version() {
|
|||||||
git add -u .
|
git add -u .
|
||||||
git status
|
git status
|
||||||
git commit -m "Release Magisk v$ver" -m "[skip ci]"
|
git commit -m "Release Magisk v$ver" -m "[skip ci]"
|
||||||
git tag $tag
|
|
||||||
}
|
}
|
||||||
|
|
||||||
build_apk() {
|
# $1 = ver
|
||||||
|
build() {
|
||||||
|
[ -z $1 ] && exit 1
|
||||||
|
local ver=$1
|
||||||
|
git pull
|
||||||
|
set_version $ver
|
||||||
$BUILDCMD clean
|
$BUILDCMD clean
|
||||||
$BUILDCMD all
|
$BUILDCMD all
|
||||||
$BUILDCMD -r all
|
$BUILDCMD -r all
|
||||||
}
|
}
|
||||||
|
|
||||||
build_canary() {
|
|
||||||
bump_canary_version
|
|
||||||
build_apk
|
|
||||||
}
|
|
||||||
|
|
||||||
# $1 = ver
|
|
||||||
build_public() {
|
|
||||||
[ -z $1 ] && exit 1
|
|
||||||
local ver=$1
|
|
||||||
set_version $ver
|
|
||||||
build_apk
|
|
||||||
}
|
|
||||||
|
|
||||||
upload() {
|
upload() {
|
||||||
# Verify pattern
|
|
||||||
[[ "$1" =~ canary|beta|stable ]]
|
|
||||||
local type=$1
|
|
||||||
|
|
||||||
gh auth status
|
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 code=$(grep_prop magisk.versionCode $GCONFIG)
|
||||||
local out=$(grep_prop outdir $CONFIG)
|
local ver=$(echo - | awk "{ print $code / 1000 }")
|
||||||
local tag title
|
local tag="v$ver"
|
||||||
|
local title="Magisk v$ver"
|
||||||
|
|
||||||
|
local out=$(grep_prop outdir $CONFIG)
|
||||||
if [ -z $out ]; then
|
if [ -z $out ]; then
|
||||||
out=out
|
out=out
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
git tag $tag
|
||||||
git push origin master
|
git push origin master
|
||||||
git push --tags
|
git push --tags
|
||||||
|
|
||||||
# Prepare release notes
|
# Prepare release notes
|
||||||
tail -n +3 $NOTES > release.md
|
tail -n +3 $NOTES > release.md
|
||||||
|
|
||||||
case $type in
|
# Publish release
|
||||||
canary )
|
local release_apk="Magisk-v${ver}.apk"
|
||||||
tag="canary-$code"
|
cp $out/app-release.apk $release_apk
|
||||||
title="Magisk ($ver) ($code)"
|
gh release create --verify-tag $tag -p -t "$title" -F release.md $release_apk $out/app-debug.apk $NOTES
|
||||||
|
|
||||||
# Assert tag format
|
rm -f $release_apk release.md
|
||||||
[ $latest_tag = $tag ]
|
|
||||||
|
|
||||||
# Publish release
|
|
||||||
gh release create --verify-tag $tag -p -t "$title" -F release.md $out/app-release.apk $out/app-debug.apk $NOTES
|
|
||||||
;;
|
|
||||||
beta|stable )
|
|
||||||
tag="v$ver"
|
|
||||||
title="Magisk v$ver"
|
|
||||||
|
|
||||||
# Assert tag format
|
|
||||||
[ $latest_tag = $tag ]
|
|
||||||
|
|
||||||
# Publish release
|
|
||||||
local release_apk="Magisk-v${ver}.apk"
|
|
||||||
cp $out/app-release.apk $release_apk
|
|
||||||
gh release create --verify-tag $tag -p -t "$title" -F release.md $release_apk $out/app-debug.apk $NOTES
|
|
||||||
rm -f $release_apk
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# If publishing stable, make it not prerelease and explicitly latest
|
|
||||||
if [ $type = "stable" ]; then
|
|
||||||
gh release edit $tag --prerelease=false --latest
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f release.md
|
|
||||||
}
|
|
||||||
|
|
||||||
revert() {
|
|
||||||
local latest_tag=$(git describe --abbrev=0 --tags)
|
|
||||||
git tag -d $latest_tag
|
|
||||||
git reset --hard HEAD~
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Use GNU sed on macOS
|
# Use GNU sed on macOS
|
||||||
@@ -160,14 +97,10 @@ if command -v gsed >/dev/null; then
|
|||||||
export -f sed
|
export -f sed
|
||||||
fi
|
fi
|
||||||
|
|
||||||
git pull
|
|
||||||
|
|
||||||
trap disable_version_config EXIT
|
trap disable_version_config EXIT
|
||||||
ensure_config
|
ensure_config
|
||||||
case $1 in
|
case $1 in
|
||||||
canary ) build_canary ;;
|
build ) build $2 ;;
|
||||||
public ) build_public $2 ;;
|
upload ) upload ;;
|
||||||
upload ) upload $2 ;;
|
|
||||||
revert ) revert ;;
|
|
||||||
* ) exit 1 ;;
|
* ) exit 1 ;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
Reference in New Issue
Block a user