2023-01-16 17:33:12 +08:00
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdbool.h>
#include <unistd.h>
#include <spawn.h>
#include <ctype.h>
#include <errno.h>
2023-01-22 19:18:35 +08:00
#include <limits.h>
2023-01-16 17:33:12 +08:00
2023-02-20 20:00:24 +08:00
#include <assert.h>
2023-01-24 14:36:49 +08:00
#include <sys/types.h>
#include <sys/wait.h>
2023-01-16 17:33:12 +08:00
#include <sys/stat.h>
2023-10-30 17:31:54 +08:00
#include <inttypes.h>
2023-02-20 20:00:24 +08:00
#include <sys/utsname.h>
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
2023-01-16 17:33:12 +08:00
extern char ** environ ;
2023-12-26 16:41:01 +08:00
extern char * gOverrideLibcheckra1nHelper ;
2023-01-16 17:33:12 +08:00
2023-02-06 01:03:29 +08:00
#include <palerain.h>
2024-03-27 22:50:45 -07:00
#ifdef TUI
#include <tui.h>
#endif
2023-01-28 20:54:06 +08:00
#include <xxd-embedded.h>
2023-01-22 19:18:35 +08:00
char * pongo_path = NULL ;
2023-03-28 12:43:46 +08:00
bool external_pongo = false ;
2023-02-03 13:22:07 +08:00
char * ext_checkra1n = NULL ;
2023-01-16 17:33:12 +08:00
2023-02-04 21:47:53 +08:00
#define tmpdir getenv("TMPDIR") == NULL ? "/tmp" : getenv("TMPDIR")
2023-02-25 00:06:08 +09:00
int exec_checkra1n ( void ) {
2023-01-16 17:33:12 +08:00
LOG ( LOG_INFO , "About to execute checkra1n" );
2023-03-28 12:43:46 +08:00
int fd_checkra1n , fd_pongo , ret ;
2023-02-03 13:22:07 +08:00
char * checkra1n_path = NULL ;
2023-03-28 12:43:46 +08:00
#ifndef NO_CUSTOM_PONGO
if ( pongo_path == NULL ) {
pongo_path = malloc ( strlen ( tmpdir ) + 20 );
2023-10-30 17:31:54 +08:00
if ( pongo_path == NULL ) {
LOG ( LOG_FATAL , "memory allocation failed \n " );
return - 1 ;
}
2023-03-28 12:43:46 +08:00
snprintf ( pongo_path , strlen ( tmpdir ) + 20 , "%s/Pongo.bin.XXXXXX" , tmpdir );
fd_pongo = mkstemp ( pongo_path );
if ( fd_pongo == - 1 ) {
LOG ( LOG_FATAL , "Cannot open temporary file %s: %d (%s)" , pongo_path , errno , strerror ( errno ));
free ( pongo_path );
return - 1 ;
}
ssize_t didWrite_Pongo_bin = write ( fd_pongo , Pongo_bin , Pongo_bin_len );
if ( didWrite_Pongo_bin != ( ssize_t ) Pongo_bin_len ) {
2023-10-30 17:31:54 +08:00
LOG ( LOG_FATAL , "Size written to %s does not match expected: %zd != %" PRIu32 ": %d (%s)" , pongo_path , didWrite_Pongo_bin , Pongo_bin_len , errno , strerror ( errno ));
2023-03-28 12:43:46 +08:00
close ( fd_pongo );
unlink ( pongo_path );
free ( pongo_path );
pongo_path = NULL ;
return - 1 ;
}
} else external_pongo = true ;
#endif
2024-05-15 02:00:24 +08:00
if ( ext_checkra1n != NULL ) {
checkra1n_path = ext_checkra1n ;
} else {
checkra1n_path = malloc ( strlen ( tmpdir ) + 20 );
if ( checkra1n_path == NULL ) {
LOG ( LOG_FATAL , "memory allocation failed \n " );
return - 1 ;
}
snprintf ( checkra1n_path , strlen ( tmpdir ) + 20 , "%s/checkra1n.XXXXXX" , tmpdir );
fd_checkra1n = mkstemp ( checkra1n_path );
if ( fd_checkra1n == - 1 ) {
LOG ( LOG_FATAL , "Cannot open temporary file %s: %d (%s)" , checkra1n_path , errno , strerror ( errno ));
free ( checkra1n_path );
checkra1n_path = NULL ;
return - 1 ;
}
ssize_t didWrite_checkra1n = write ( fd_checkra1n , checkra1n , checkra1n_len );
if ( didWrite_checkra1n != ( ssize_t ) checkra1n_len ) {
LOG ( LOG_FATAL , "Size written to %s does not match expected: %zd != %" PRIu32 ": %d (%s)" , checkra1n_path , didWrite_checkra1n , checkra1n_len , errno , strerror ( errno ));
close ( fd_checkra1n );
unlink ( checkra1n_path );
free ( checkra1n_path );
checkra1n_path = NULL ;
return - 1 ;
}
2023-03-28 12:43:46 +08:00
close ( fd_checkra1n );
2024-05-15 02:00:24 +08:00
ret = chmod ( checkra1n_path , 0700 );
if ( ret ) {
LOG ( LOG_FATAL , "Cannot chmod %s: %d (%s)" , checkra1n_path , errno , strerror ( errno ));
unlink ( checkra1n_path );
free ( checkra1n_path );
checkra1n_path = NULL ;
return - 1 ;
}
2023-01-16 17:33:12 +08:00
}
2023-02-20 20:40:04 +08:00
#if defined(__APPLE__) && defined(__arm64__) && (TARGET_OS_IPHONE || defined(FORCE_HELPER))
2023-02-20 20:00:24 +08:00
char * libcheckra1nhelper_dylib_path = NULL ;
{
struct utsname name ;
uname ( & name );
unsigned long darwinMajor = strtoul ( name . release , NULL , 10 );
assert ( darwinMajor != 0 );
2023-02-20 20:41:43 +08:00
#if !defined(FORCE_HELPER)
2023-02-20 20:00:24 +08:00
if ( darwinMajor < 20 ) {
#endif
2023-12-26 16:41:01 +08:00
if ( gOverrideLibcheckra1nHelper ) {
libcheckra1nhelper_dylib_path = gOverrideLibcheckra1nHelper ;
goto setenv_ra1n ;
}
2023-02-20 20:00:24 +08:00
libcheckra1nhelper_dylib_path = malloc ( strlen ( tmpdir ) + 40 );
2023-10-30 17:31:54 +08:00
if ( libcheckra1nhelper_dylib_path == NULL ) {
LOG ( LOG_FATAL , "memory allocation failed \n " );
return - 1 ;
}
2023-02-20 20:00:24 +08:00
snprintf ( libcheckra1nhelper_dylib_path , strlen ( tmpdir ) + 40 , "%s/libcheckra1nhelper.dylib.XXXXXX" , tmpdir );
int helper_fd = mkstemp ( libcheckra1nhelper_dylib_path );
if ( helper_fd == - 1 ) {
LOG ( LOG_FATAL , "Cannot open temporary file: %d (%s)" , errno , strerror ( errno ));
return - 1 ;
}
2023-03-28 12:43:46 +08:00
ssize_t didWrite_libcheckra1nhelper = write ( helper_fd , libcheckra1nhelper_dylib , libcheckra1nhelper_dylib_len );
if (( unsigned int ) didWrite_libcheckra1nhelper != libcheckra1nhelper_dylib_len ) {
2023-10-30 17:31:54 +08:00
LOG ( LOG_FATAL , "Size written does not match expected: %zd != %" PRIu32 ": %d (%s)" , didWrite_libcheckra1nhelper , libcheckra1nhelper_dylib_len , errno , strerror ( errno ));
2023-02-20 20:00:24 +08:00
close ( helper_fd );
unlink ( libcheckra1nhelper_dylib_path );
return - 1 ;
}
close ( helper_fd );
ret = chmod ( libcheckra1nhelper_dylib_path , 0700 );
if ( ret ) {
LOG ( LOG_FATAL , "Cannot chmod %s: %d (%s)" , libcheckra1nhelper_dylib_path , errno , strerror ( errno ));
unlink ( libcheckra1nhelper_dylib_path );
return - 1 ;
}
2023-12-26 16:41:01 +08:00
setenv_ra1n :
2023-02-20 20:00:24 +08:00
setenv ( "DYLD_INSERT_LIBRARIES" , libcheckra1nhelper_dylib_path , 1 );
2023-02-20 20:41:43 +08:00
#if !defined(FORCE_HELPER)
2023-02-20 20:00:24 +08:00
}
#endif
}
#endif
2023-03-08 16:49:02 +08:00
char args [ 0x10 ] = "-E" ;
2023-05-29 01:56:12 +08:00
if (( palerain_flags & palerain_option_demote )) strncat ( args , "d" , 0xf );
if ( ! ( palerain_flags & palerain_option_checkrain_is_clone )) {
2023-03-08 16:49:02 +08:00
strncat ( args , "p" , 0xf );
if ( verbose >= 2 ) strncat ( args , "v" , 0xf );
2023-05-29 01:56:12 +08:00
if (( palerain_flags & palerain_option_no_colors )) strncat ( args , "n" , 0xf );
2023-03-08 16:49:02 +08:00
} else {
strncat ( args , "R" , 0xf );
}
2023-03-28 12:43:46 +08:00
LOG ( LOG_VERBOSE5 , args );
if ( pongo_path != NULL ) LOG ( LOG_VERBOSE5 , pongo_path );
2023-01-17 20:48:54 +08:00
pid_t pid ;
2024-03-27 22:50:45 -07:00
posix_spawn_file_actions_t action ;
posix_spawn_file_actions_init ( & action );
#ifdef TUI
if ( tui_is_jailbreaking ) {
// silence checkra1n
posix_spawn_file_actions_addopen ( & action , 1 , "/dev/null" , O_WRONLY , 0 );
posix_spawn_file_actions_addopen ( & action , 2 , "/dev/null" , O_WRONLY , 0 );
}
#endif
2024-05-15 02:00:24 +08:00
ret = posix_spawn ( & pid , checkra1n_path , & action , NULL , ( char * []){
checkra1n_path ,
args ,
"-k" ,
pongo_path ,
NULL
}, environ );
2024-03-27 22:50:45 -07:00
posix_spawn_file_actions_destroy ( & action );
2023-01-16 17:33:12 +08:00
if ( ret ) {
LOG ( LOG_FATAL , "Cannot posix spawn %s: %d (%s)" , checkra1n_path , errno , strerror ( errno ));
2023-02-03 13:22:07 +08:00
if ( ext_checkra1n != NULL ) unlink ( checkra1n_path );
return - 1 ;
2023-01-16 17:33:12 +08:00
}
2023-01-22 19:18:35 +08:00
LOG ( LOG_VERBOSE2 , "%s spawned successfully" , checkra1n_path );
2023-04-27 17:34:19 -04:00
sleep ( 2 );
2023-02-04 21:47:53 +08:00
if ( ext_checkra1n == NULL ) {
2023-02-06 11:27:26 +08:00
unlink ( checkra1n_path );
2023-02-03 14:42:41 +08:00
free ( checkra1n_path );
checkra1n_path = NULL ;
}
2023-03-28 23:38:54 +08:00
waitpid ( pid , NULL , 0 );
if ( ! external_pongo && pongo_path != NULL ) {
unlink ( pongo_path );
}
if ( pongo_path != NULL ) free ( pongo_path );
pongo_path = NULL ;
2023-02-20 20:40:04 +08:00
#if defined(__APPLE__) && defined(__arm64__) && (TARGET_OS_IPHONE || defined(FORCE_HELPER))
2023-02-20 20:00:24 +08:00
if ( libcheckra1nhelper_dylib_path != NULL ) {
2023-12-26 16:41:01 +08:00
if ( ! gOverrideLibcheckra1nHelper ) unlink ( libcheckra1nhelper_dylib_path );
2023-02-20 20:00:24 +08:00
unsetenv ( "DYLD_INSERT_LIBRARIES" );
unsetenv ( "DYLD_FORCE_FLAT_NAMESPACE" );
2023-12-26 16:41:01 +08:00
if ( ! gOverrideLibcheckra1nHelper ) free ( libcheckra1nhelper_dylib_path );
2023-02-20 20:00:24 +08:00
libcheckra1nhelper_dylib_path = NULL ;
}
#endif
2023-02-03 13:22:07 +08:00
return 0 ;
2023-01-16 17:33:12 +08:00
}