Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Design decision for multiple ABI support #5

Open
maxbla opened this issue Jul 6, 2020 · 3 comments
Open

Design decision for multiple ABI support #5

maxbla opened this issue Jul 6, 2020 · 3 comments

Comments

@maxbla
Copy link
Contributor

maxbla commented Jul 6, 2020

Here's a function I was messing around with that would make supporting multiple ABIs easier.

int read_syacall_arg(pid_t pid, void * dst, size_t len, struct user_regs_struct * uregs, int arg_idx) {
	// basically the core definition of Linux's ABI
	// https://blog.packagecloud.io/eng/2016/04/05/the-definitive-guide-to-linux-system-calls/
#ifdef __x86_64__
	switch (arg_idx) {
		case 0: read_block(pid, dst, uregs->rdi, len); break;
		case 1: read_block(pid, dst, uregs->rsi, len); break;
		case 2: read_block(pid, dst, uregs->rdx, len); break;
		case 3: read_block(pid, dst, uregs->rcx, len); break;
		case 4: read_block(pid, dst, uregs->r8, len); break;
		case 5: read_block(pid, dst, uregs->r9, len); break;
		default: return 1; // 6 arguments maximum per syscall
	}
	return 0;
#else
#ifdef __i386__
	switch (arg_idx) {
		case 0: read_block(pid, dst, uregs->ebx, len); break;
		case 1: read_block(pid, dst, uregs->ecx, len); break;
		case 2: read_block(pid, dst, uregs->edx, len); break;
		case 3: read_block(pid, dst, uregs->esi, len); break;
		case 4: read_block(pid, dst, uregs->edi, len); break;
		case 5: read_block(pid, dst, uregs->ebp, len); break;
		default: return 1; // 6 arguments maximum per syscall
	}
	return 0;
//add more architectures here
#endif
#endif
	return 2; //Unsupported architecture

}

Then, I would replace all other instances of read_block in tardis.c with this new read_syscall_arg (and similar for write_block). For example, before_nanosleep would be rewritten as

void before_nanosleep(pid_t pid, struct user_regs_struct * uregs) {
	struct timespec ts;
	read_syscall_arg(pid, &ts, sizeof(struct timespec), uregs, 0);
	scale_timespec(&ts, 1.0/delayfactor, 0);
	write_syscall_arg(pid, &ts, sizeof(struct timespec), uregs, 0);
}

P.S. I think I would need to use runtime ABI detection, not macros, because x86_64 CPUs can run 32-bit x86 binaries.

@DavidBuchanan314
Copy link
Owner

I'd definitely be open to adding multi-arch support, although I'll need to have a sit down and think about the design first (It's been a while since I've looked at this project)

I think you're right about the runtime arch detection, and if I remember correctly there's already some code present that checks if the target process is 64-bit.

@maxbla
Copy link
Contributor Author

maxbla commented Jul 8, 2020

if I remember correctly there's already some code present that checks if the target process is 64-bit.

Yeah, I'm not sure that is64bit works as intended. When I tested it, it report 64-bit for 32-bit processes on my 64-bit machine. Here's another way to test, which works as expected for me. I wrote a modified is64bit function using my new method which you might see in an upcoming PR.

After experimenting with my prototype a bit longer, it has become clear to me that TARDIS needs to be recompiled as 32 bit to work with 32 bit binaries (there are ways around doing so, but they aren't worth it). Syscalls have different numbers on the different platforms (including x86 vs x86_64)

@maxbla
Copy link
Contributor Author

maxbla commented Sep 8, 2020

I'm not sure that is64bit works as intended.

Just to get the record straight, the original version of is64bit worked as intended. The reason I thought otherwise is when running tardis compiled as 64-bit on a 32-bit program, I called is64bit when the first execve was interrupted by ptrace. The execve hadn't completed, so is64bit was always returning true (more accurately matching how tardis was compiled).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants