Thread: pread & related hang when I try to read /proc/pid/mem of rpcs3

  1. #1
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733

    pread & related hang when I try to read /proc/pid/mem of rpcs3

    I've tried countless times to get it to stop hanging by myself and now I'm done banging my head against the wall, on manjaro cinnamon x64 minimal, using kernel 5.4 LTS. The code I'm using is as follows:
    Code:
    proc_handle_t* proc_handle_open( int *err, int pid )
    {
    	proc_handle_t *handle;
    #ifdef gasp_pread
    	char path[32] = {0};
    #endif
    	
    	if ( pid <= 0 ) {
    		errno = EINVAL;
    		if ( err ) *err = errno;
    		ERRMSG( errno, "Invalid Pid");
    		return NULL;
    	}
    
    	if ( !(handle = calloc(sizeof(proc_handle_t),1)) ) {
    		if ( err ) *err = errno;
    		ERRMSG( errno, "Couldn't allocate memory for handle");
    		return NULL;
    	}
    	handle->perm = 0;
    	handle->memfd = -1;
    	
    	if ( !proc_notice_info( err, pid, &(handle->notice) ) ) {
    		proc_handle_shut( handle );
    		return NULL;
    	}
    	
    	if ( handle->notice.self )
    		sprintf( handle->procdir, "/proc/self" );
    	else {
    		sprintf( handle->procdir, "/proc/%d", pid );
    #ifdef PTRACE_SIEZE
    		ptrace( PTRACE_SEIZE, pid, NULL, NULL );
    #endif
    #ifdef gasp_pread
    		sprintf( path, "/proc/%d/mem", pid );
    		handle->memfd = open( path, O_RDWR );
    		if ( handle->memfd >= 0 )
    			handle->perm = O_RDWR;
    		else {
    			handle->memfd = open( path, O_RDONLY );
    			if ( handle->memfd >= 0 )
    				handle->perm = 0;
    		}
    #endif
    	}
    	
    	handle->running = 1;
    	
    	return handle;
    }
    ...
    intptr_t proc__glance_file(
    	int *err, proc_handle_t *handle,
    	intptr_t addr, void *mem, size_t size
    )
    {
    #ifdef gasp_pread
    	intptr_t done = 0;
    	int ret;
    	
    	if ( (ret = proc__rwvmem_test(handle, mem,size)) != EXIT_SUCCESS )
    	{
    		if ( err ) *err = ret;
    		return 0;
    	}
    	
    	if ( (handle->perm != O_RDWR && handle->perm != O_RDONLY)
    		|| handle->memfd < 0 )
    		return 0;
    	
    	done = gasp_pread( handle->memfd, mem, size, addr );
    	if ( done < 0 ) {
    		if ( err ) *err = errno;
    		ERRMSG( errno, "Couldn't read process memory" );
    	}
    	return done;
    #else
    	if ( err ) err = ENOSYS;
    	return 0;
    #endif
    }
    ...
    intptr_t proc_glance_data(
    	int *err, proc_handle_t *handle,
    	intptr_t addr, void *mem, size_t size
    )
    {
    	intptr_t done;
    	mode_t perm;
    	int ret = proc__rwvmem_test( handle, mem, size );
    	
    	if ( ret != EXIT_SUCCESS ) {
    		if ( err ) *err = ret;
    		return 0;
    	}
    	errno = EXIT_SUCCESS;
    
    #ifndef PTRACE_SEIZE
    	ptrace( PTRACE_ATTACH, handle->notice.entryId, NULL, NULL );
    #else
    	ptrace( PTRACE_INTERRUPT, handle->notice.entryId, NULL, NULL );
    #endif
    	
    	if ( (perm = proc_mapped_addr( &ret, handle, addr, 0777, NULL )) == 0
    		&& ret != EXIT_SUCCESS ) {
    		if ( err ) *err = ret;
    
    		ptrace( PTRACE_CONT, handle->notice.entryId, NULL, NULL );
    		return 0;
    	}
    	
    	/* Aviod fiddling with own memory file */
    	if ( (done = proc__glance_self( err, handle, addr, mem, size ))
    		> 0 ) goto success;
    	/* gasp_pread() */
    	if ( (done = proc__glance_file( err, handle, addr, mem, size ))
    		> 0 ) goto success;
    	/* gasp_lseek() & gasp_read() */
    	if ( (done = proc__glance_seek( err, handle, addr, mem, size ))
    		> 0 ) goto success;
    	/* Last ditch effort to avoid ptrace */
    	if ( (done = proc__glance_vmem( err, handle, addr, mem, size ))
    		> 0 ) goto success;
    	/* ptrace */
    	if ( (done = proc__glance_peek( err, handle, addr, mem, size ))
    		> 0 ) goto success;
    	
    #ifndef PTRACE_SEIZE
    	ptrace( PTRACE_DETACH, handle->notice.entryId, NULL, NULL );
    #else
    	ptrace( PTRACE_CONT, handle->notice.entryId, NULL, NULL );
    #endif
    
    	if ( proc_mapped_addr( &ret, handle, addr, perm, NULL ) == 0
    		&& ret != EXIT_SUCCESS && err )
    		*err = ret;
    	return 0;
    	success:
    
    #ifndef PTRACE_SEIZE
    	ptrace( PTRACE_DETACH, handle->notice.entryId, NULL, NULL );
    #else
    	ptrace( PTRACE_CONT, handle->notice.entryId, NULL, NULL );
    #endif
    
    	if ( proc_mapped_addr( &ret, handle, addr, perm, NULL ) == 0
    		&& ret != EXIT_SUCCESS && err )
    		*err = ret;
    	return done;
    }
    The gasp_* is just a define that changes based on whether large file support is detect at compile time or not, in this case it is and maps to pread64 etc
    Full project code here:
    GitHub - awsdert/gasp at 6e028dcbc6853b469dfd63ead6fae82e42079649

  2. #2
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Just occured to me you may want the cheat list I'm working with:
    Code:
    --Dragon Quest Builders
    t = {
    	endian = "Big",
    	list = {
    { desc = "Days", addr = 18036876676, signed = 2 },
    { desc = "HP Upto", addr = 18036876678, signed = 2 },
    { desc = "HP Left", addr = 18036876680, signed = 2 },
    { desc = "Hunger Upto", addr = 18036876682, signed = 2 },
    { desc = "Hunger Left", addr = 18036876684, signed = 2 },
    { desc = "Attack", addr = 18036876686, signed = 2 },
    { desc = "Defence", addr = 18036876688, signed = 2 },
    { desc = "???", addr = 18036876692, signed = 2 },
    -- Once implemented will render the below list wasteful
    { desc = "Items", addr = 18036976864,
    	count = 15, size = 4, split = {
    		{desc="ID",bytes = 2}, {desc="Qty",signed = 2}
    	}
    },
    -- Imported from GameConqueror cheat file
    { desc = "Slot 1 ID", addr = 18036976864, bytes = 2 },
    { desc = "Slot 1", addr = 18036976867, signed = 1 },
    { desc = "Slot 2 ID", addr = 18036976868, bytes = 2 },
    { desc = "Slot 2", addr = 18036976871, signed = 1 },
    { desc = "Slot 3 ID", addr = 18036976872, bytes = 2 },
    { desc = "Slot 3", addr = 18036976875, signed = 1 },
    { desc = "Slot 4 ID", addr = 18036976876, bytes = 2 },
    { desc = "Slot 4", addr = 18036976879, signed = 1 },
    { desc = "Slot 5", addr = 18036976883, signed = 1 },
    { desc = "Slot 6", addr = 18036976887, signed = 1 },
    { desc = "Slot 7", addr = 18036976891, signed = 1 },
    { desc = "Slot 8", addr = 18036976895, signed = 1 },
    { desc = "Slot 9", addr = 18036976899, signed = 1 },
    { desc = "Slot 10", addr = 18036976903, signed = 1 },
    { desc = "Slot 11", addr = 18036976907, signed = 1 },
    { desc = "Slot 12", addr = 18036976911, signed = 1 },
    { desc = "Slot 13", addr = 18036976915, signed = 1 },
    { desc = "Slot 14", addr = 18036976919, signed = 1 },
    { desc = "Slot 15", addr = 18036976923, signed = 1 },
    -- Once implemented will render the below list wasteful
    { desc = "Gear", addr = 18036976924,
    	count = 16, size = 4, split = {
    		{desc="ID",bytes = 2}, {desc="HP",signed = 2}
    	}
    },
    { desc = "Gear 4 ID", addr = 18036976936, signed = 2 },
    { desc = "Gear 4", addr = 18036976938, signed = 2 },
    { desc = "Gear 5", addr = 18036976942, signed = 2 },
    { desc = "Gear 6", addr = 18036976946, signed = 2 }
    	}
    }
    return t

  3. #3
    Registered User
    Join Date
    Mar 2008
    Location
    India
    Posts
    147
    May be this one more suits to the linux related forum than a c programming message boards.

  4. #4
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by vlrk View Post
    May be this one more suits to the linux related forum than a c programming message boards.
    Well now it is posted here also:
    pread & related hang when I try to read /proc/pid/mem of rpcs3 - Programming - Manjaro Linux Forum

  5. #5
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Turns out PTRACE_SEIZE is useless when cheating/hacking, also can't immediately hook the process so must wait until about to read or write to the process vm before hooking it but after stopping the app in the 1st place (that's how I solved the hang).

    Since it is kinda related to the original topic I'll ask my next question here, would the following be the correct way of detecting endianess?
    Code:
    int lua_get_endian( lua_State *L ) {
    	long val = 0x12345678
    	uchar *bytes = (uchar*)&val;
    	switch ( *bytes ) {
    	case 0x78: lua_pushstring(L, "Little"); return 1;
    	case 0x12: lua_pushstring(L, "Big"); return 1;
    	case 0x56: lua_pushstring(L, "BPDP"); return 1;
    	case 0x34: lua_pushstring(L, "LPDP"); return 1;
    	}
    	switch ( bytes[4] ) {
    	case 0x78: lua_pushstring(L, "Little"); return 1;
    	case 0x12: lua_pushstring(L, "Big"); return 1;
    	case 0x56: lua_pushstring(L, "BPDP"); return 1;
    	case 0x34: lua_pushstring(L, "LPDP"); return 1;
    	}
    	return 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. pwrite and pread
    By Fábio Lanza in forum C Programming
    Replies: 1
    Last Post: 04-21-2012, 03:54 PM
  2. Unkown Hang
    By Bladactania in forum C Programming
    Replies: 31
    Last Post: 04-22-2009, 09:33 AM
  3. HANG MAN i need deperate help
    By cprogrammer22 in forum C Programming
    Replies: 4
    Last Post: 11-26-2008, 11:20 PM
  4. Why does it hang?
    By Jackie Chan in forum C Programming
    Replies: 1
    Last Post: 05-24-2008, 01:27 AM
  5. getting the hang of classes.
    By The Gweech in forum C++ Programming
    Replies: 1
    Last Post: 03-20-2002, 06:35 PM

Tags for this Thread