[Solved] Finding offset to write to read() buffer

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
codyd51
Member
Member
Posts: 77
Joined: Fri May 20, 2016 2:29 pm
Location: London, UK
GitHub: https://github.com/codyd51
Contact:

[Solved] Finding offset to write to read() buffer

Post by codyd51 »

Hi!

I've ported newlib to my OS, but am having some issues with read() and getchar(). If I call read() with a buffer on the stack, everything works as expected and I can write to the buffer from the kernel without needing to modify the address at all.

However, if I attempt to call getchar() through newlib, then I see a read() syscall being made with something like the following parameters: read(0, 0x10, 1024). So, read is asking to write to a buffer really low in memory. Am I supposed to be doing something to this address before writing to it? Is this address supposed to be an offset into .bss, or some other segment? If it is an offset into a segment, how am I to differentiate between when the kernel is being given a buffer on the stack (which requires no translation) vs. an offset into a segment (which does require translation)?

Just to demonstrate, here's a screenshot of output when using newlib's getchar() in a loaded ELF. You'll also notice some garbage characters being printed, which is strange considering the ELF loader zeroes-out the .bss segment, and sbrk does the same to any memory it gives it. That's another thing I'm still trying to figure out. http://imgur.com/gallery/wmUKS

Any tips or ideas are appreciated, thanks!
Last edited by codyd51 on Fri Mar 10, 2017 11:04 pm, edited 1 time in total.
User avatar
Velko
Member
Member
Posts: 153
Joined: Fri Oct 03, 2008 4:13 am
Location: Ogre, Latvia, EU

Re: Finding offset to write to read() buffer

Post by Velko »

Am I supposed to be doing something to this address before writing to it?
No. You just fill memory at this address, no translation of any kind. You should, however, validate
if it points to sane location (and refuse to proceed in this particular case).

Newlib allocates buffer(s) in heap for stdio routines. Check if your sbrk() and malloc() works as expected.
If something looks overcomplicated, most likely it is.
codyd51
Member
Member
Posts: 77
Joined: Fri May 20, 2016 2:29 pm
Location: London, UK
GitHub: https://github.com/codyd51
Contact:

Re: Finding offset to write to read() buffer

Post by codyd51 »

Velko wrote:
Am I supposed to be doing something to this address before writing to it?
No. You just fill memory at this address, no translation of any kind. You should, however, validate
if it points to sane location (and refuse to proceed in this particular case).

Newlib allocates buffer(s) in heap for stdio routines. Check if your sbrk() and malloc() works as expected.
Gotcha, thanks for clearing that up! I tried a malloc() with newlib, and, as expected, got a very low address in memory (0x10). Trying getchar() again gives read() a buffer around 0x410. What I don't understand is why these addresses are so low, when sbrk() gives addresses above 0x8050000. Also, when I attempt to write to this buffer without translation, I still get garbled memory on the ELF-side.
codyd51
Member
Member
Posts: 77
Joined: Fri May 20, 2016 2:29 pm
Location: London, UK
GitHub: https://github.com/codyd51
Contact:

Re: Finding offset to write to read() buffer

Post by codyd51 »

Ah, I just logged sbrk on the elf-side and realized that it's not returning the correct values to the program. I think my syscall handler might be trashing eax after running the syscall function. I'll fix my syscalls to make sure they're returning values as expected and try again. Thanks for your help!
codyd51
Member
Member
Posts: 77
Joined: Fri May 20, 2016 2:29 pm
Location: London, UK
GitHub: https://github.com/codyd51
Contact:

Re: Finding offset to write to read() buffer

Post by codyd51 »

Okay, syscalls are now returning values properly. If I read() into a buffer myself and print it out, everything works as expected, However, if I attempt to use getchar(), EOF is returned. Why would this be?
User avatar
lkurusa
Member
Member
Posts: 42
Joined: Wed Aug 08, 2012 6:39 am
Libera.chat IRC: Levex
Location: New York, NY
Contact:

Re: Finding offset to write to read() buffer

Post by lkurusa »

Hi,

Is your read system call working properly as expected? In newlib, can you trace what your kernel passes? Maybe it gets zero'd somewhere?

Lastly, do you get EOF as well when you are issuing a read system call?
Cheers,

Lev
codyd51
Member
Member
Posts: 77
Joined: Fri May 20, 2016 2:29 pm
Location: London, UK
GitHub: https://github.com/codyd51
Contact:

Re: Finding offset to write to read() buffer

Post by codyd51 »

lev wrote:Hi,

Is your read system call working properly as expected? In newlib, can you trace what your kernel passes? Maybe it gets zero'd somewhere?

Lastly, do you get EOF as well when you are issuing a read system call?

As a matter of fact, yes. If I call read() manually from an ELF, everything works fine. It's only when I try to use newlib's getchar. It seems newlib's sprintf is also borked, which may or may not be a related issue.

No. My current read implementation, for testing purposes, never gives EOF.
User avatar
Velko
Member
Member
Posts: 153
Joined: Fri Oct 03, 2008 4:13 am
Location: Ogre, Latvia, EU

Re: Finding offset to write to read() buffer

Post by Velko »

Return value of read() syscall?
If something looks overcomplicated, most likely it is.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Finding offset to write to read() buffer

Post by Solar »

Do your OS and newlib agree on what stdin is? This looks like newlib taking its buffer address from some uninitialized structure...?!?

(No idea about newlib's internals, I am just guessing here.)
Every good solution is obvious once you've found it.
codyd51
Member
Member
Posts: 77
Joined: Fri May 20, 2016 2:29 pm
Location: London, UK
GitHub: https://github.com/codyd51
Contact:

Re: Finding offset to write to read() buffer

Post by codyd51 »

Velko wrote:Return value of read() syscall?
Thank you!! This was the issue. I appreciate you pointing me in the right direction!

The exact problem was this syscall stub in newlib:

Code: Select all

int read(int fd, char* buf, int count) {
    sys_read(fd, buf, count);
    return 0;
}
For some stupid reason I wasn't returning sys_read's return value. So, the buffer was filled correctly, which is why when calling read() myself the buffer was filled as expected, but the caller is told that no characters were read, which is why getchar() returned EOF.

Thanks for the help, everyone!
Post Reply