1

I want to intercept the load_elf_binary function in fs/binfmt_elf.c file, read a few custom section headers from the file passed to it via an argument and set a few registers(eax, ebx, ecx, edx) before returning from the function.

Now I read that Jprobes is a good way to access the arguments of the target function but the problem is that once the control returns from Jprobes function the register and stack values are restored as per it's specifications, so I am looking into a way around it and probably inserting a probe in the middle of the function (preferably towards the end) would be a good idea. Please correct me if I am wrong and help with this.

bawejakunal
  • 1,678
  • 2
  • 25
  • 54
  • Why are you trying to change registers here, exactly? – bdonlan Jun 19 '15 at 04:47
  • I won't say change exactly, i need to execute the following piece of code `__asm__ __volatile__ (".byte 0xf1" : : "a"(eax), "b"(ebx), "c"(ecx), "d"(edx), "D"(edi), "S"(esi));` to let the CPU know that certain ELF files have to be treated as special files for the security feature that I am working on. – bawejakunal Jun 19 '15 at 04:59
  • As far as I can tell, changing the registers on return will just change the function's return value. which will only serve to put things onto an error path (or fail to put things on an error path when it should be on an error path). It's hard to suggest things to do given that you've zeroed in on a really rather convoluted and brittle method to do whatever it is you're doing. Why don't you tell us what you're really trying to do so we can perhaps suggest an easier way? – bdonlan Jun 19 '15 at 05:04
  • Oh, and 0xf1 doesn't seem to be a defined opcode on x86 (c.f. http://ref.x86asm.net/coder32.html#xF1 ) – bdonlan Jun 19 '15 at 05:05
  • yeah that is a custom defined instruction – bawejakunal Jun 19 '15 at 05:51
  • @bdonlan this is in continuation with my previous question where I have described in more details what exactly I am trying to do. http://stackoverflow.com/questions/30797827/intercept-elf-loader-in-linux-kernel-fs-binfmt-elf-c-file-via-loadable-kernel-m/30803779#30803779 – bawejakunal Jun 19 '15 at 05:53

1 Answers1

2

So, let me see if I understand what you're doing properly.

You've modified the CPU (running in an emulator?) so that instruction 0xF1 does some sort of cryptographic thing. You want to arrange for load_elf_binary to invoke this instruction on return, with registers set properly for this instruction to do its magic. Somehow custom sections are involved.

This is going to be very difficult to do in the way you state. There are a few major problems:

  1. I'm not sure what your threat model is, but if your magic CPU instruction just decrypts the mapped data directly you'll modify the pages in the linux page cache, and the decrypted code or data will be visible to other processes that mmap these pages.
  2. Moreover, if the kernel frees the pages later, the encrypted data will be reloaded into memory, resulting in crashes at unpredictable times.
  3. If some process makes those pages dirty, the decrypted data will be flushed back to disk, leaving a mix of decrypted and encrypted data on disk.
  4. If you use a JProbe, your callback is invoked on entry to the function, which is way too early anyway.

All in all, this isn't going to work too well the way you state it.

A better approach might be to define your own binfmt (or replace the load_binary callback in elf_format). Your binfmt could then load the binary in whatever way it needs to. If you want to leverage the existing ELF loader, you could delegate to load_elf_binary, and on return do whatever you need to manipulate the loaded process, without any of this JProbe stuff.

In either case, do be sure to remap all of the pages you're encrypting/decrypting as MAP_PRIVATE and mark them dirty before changing their contents.

bdonlan
  • 224,562
  • 31
  • 268
  • 324
  • this is part of a research project to propose a new architecture as an extension to existing x86 architecure, all the page handling problems that you mentioned have already been taken care of, in fact the logic for modifying the ELF loading itself was also working when implemented within the `fs/binfmt_elf.c`, it's just that since it was only about 300 lines of code change in kernel I am looking into implementing it as a kernel module so that the user doesn't need to recompile the whole kernel for such small changes. The bottomline is to keep the kernel as much unchanged as possible. – bawejakunal Jun 19 '15 at 08:15
  • @bawejakunal honestly when you're talking about introducing new architectural primitives like this you should probably consider a kernel patch rather than monkey-patching kernel code like this :/ But in that case consider registering a new binary format as a module – bdonlan Jun 21 '15 at 04:33
  • you went too deep into this, but your efforts are really appreciable and yeah like you suggested we had initially gone for a kernel patch only (modifying the load_elf_binary minimally) but during one of the paper reviews we got a comment that recompiling the whole kernel just for a couple hundred lines of code is too much of an effort :| Anyways I kind of strayed away, I implemented the thing using entry and return handlers of kprobes yesterday. – bawejakunal Jun 21 '15 at 15:07
  • I guess the moral of the story is that the needs of academia are different from those of the production code :) – bdonlan Jun 21 '15 at 20:52