[Solved] Finding offset to write to read() buffer
-
- 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
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!
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.
Re: Finding offset to write to read() buffer
No. You just fill memory at this address, no translation of any kind. You should, however, validateAm I supposed to be doing something to this address before writing to it?
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.
-
- 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
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.Velko wrote:No. You just fill memory at this address, no translation of any kind. You should, however, validateAm I supposed to be doing something to this address before writing to it?
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.
-
- 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
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!
-
- 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
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?
- lkurusa
- 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
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?
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
Lev
-
- 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
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.
Re: Finding offset to write to read() buffer
Return value of read() syscall?
If something looks overcomplicated, most likely it is.
Re: Finding offset to write to read() buffer
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.)
(No idea about newlib's internals, I am just guessing here.)
Every good solution is obvious once you've found it.
-
- 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
Thank you!! This was the issue. I appreciate you pointing me in the right direction!Velko wrote:Return value of read() syscall?
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;
}
Thanks for the help, everyone!