/proc/pid/mem and stack variables
Hello everyone,
I'm new on this list. I looked through the archives but could not find answer to my problem.
I have a library that makes use of /proc/pid/mem entries in the /proc pseudo-filesystem. It runs perfectly on IA32 under 2.2.12 (and some superficial tests suggest that it works under 2.4.0-test12 as well).
I have recompiled the library on IA64 under 2.4.0-test12 and using version 2.9-ia64-000216-final. The library works OK except when the address it tries to access via /proc/pid/mem refers to variables allocated on stack (e.g. local arrays defined in functions).
This is a snippet of code used to access memory via /proc/pid/mem:
void mem_read (int fd, void *buf, void *addr, size_t len) {
if (lseek (fd, (off_t)addr, SEEK_SET) == (off_t)-1)
perror ("lseek");
read (fd, buf, len);lseek in this code fails (EINVAL) always when addr is address of a variable allocated on stack.
I have no idea if the problem is because I'm doing something wrong, or because /proc/pid/mem is not yet fully implemented on IA64. I appreciate any hints and help with this.
Thanks in advance,
Maciej
Signature · 4 lines
Maciej Go³êbiewski [email protected] http://www.ccrl-nece.technopark.gmd.de/~maciej C&C Research Laboratories, NEC Europe Ltd., Sankt Augustin, Germany
Quoted 8 lines · [email protected] said:
I have recompiled the library on IA64 under 2.4.0-test12 and using version 2.9-ia64-000216-final. The library works OK except when the address it tries to access via
/proc/pid/memrefers to variables allocated on stack (e.g. local arrays defined in functions).This is a snippet of code used to access memory via
/proc/pid/mem:
Quoted 8 lines
void
mem_read(int fd, void *buf, void *addr,size_tlen) {if (lseek (fd, (off_t)addr, SEEK_SET) = (off_t)-1) perror ("lseek"); read (fd, buf, len);lseek in this code fails (EINVAL) always when addr is address of a variable allocated on stack.
Try removing the "offset >= 0" check in default_llseek in fs/read_write.c. Stack pages seem to have the high bit set which is flummoxing that test.
If you keep this "solution" you may want to write an llseek function for /proc/pid/mem so that the entire kernel doesn't suffer any unforseen consequences.
-- Pete
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Pete Wyckoff
Quoted 9 lines · Pete> [email protected] said:
Quoted 9 lines
I have recompiled the library on IA64 under 2.4.0-test12 and using version 2.9-ia64-000216-final. The library works OK except when the address it tries to access via
/proc/pid/memrefers to variables allocated on stack (e.g. local arrays defined in functions).This is a snippet of code used to access memory via
/proc/pid/mem:
Quoted 7 lines
Quoted 7 lines
void
mem_read(int fd, void *buf, void *addr,size_tlen) {if (lseek (fd, (off_t)addr,
SEEK_SET) = (off_t)-1) perror ("lseek"); read (fd, buf, len);lseek in this code fails (EINVAL) always when addr is address of a variable allocated on stack.
Pete> Try removing the "offset >= 0" check in default_llseek in Pete> fs/read_write.c. Stack pages seem to have the high bit set Pete> which is flummoxing that test.
Pete> If you keep this "solution" you may want to write an llseek Pete> function for /proc/pid/mem so that the entire kernel doesn't Pete> suffer any unforseen consequences.
Yes, implementing llseek for fs/proc/base.c:proc_mem_operations is the right solution. /dev/kmem already has its own llseek (which treats the offset as unsigned) but, for some reason, was left out of the /proc/pid/mem support.
Don, can you add this to the TODO list so we won't forget about it?
Thanks,
--david
Quoted 7 lines · David Mosberger
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Pete Wyckoff
Yes, implementing llseek for fs/proc/base.c:proc_mem_operations is the right solution.
/dev/kmemalready has its own llseek (which treats the offset as unsigned) but, for some reason, was left out of the/proc/pid/memsupport.Don, can you add this to the TODO list so we won't forget about it?
Thanks a lot for help. It seems that the solution is simpler than I was expecting. Anyway, I don't have a root access to the IA64 machine in question, so I can't test it myself, but one of the guys with root access told me he'll try to find some time and try it out.
Once again thank a lot.
Maciej
Signature · 4 lines
Maciej Go³êbiewski [email protected] http://www.ccrl-nece.technopark.gmd.de/~maciej C&C Research Laboratories, NEC Europe Ltd., Sankt Augustin, Germany
A small patch for the file fs/proc/base.c implementing llseek for /proc/PID/mem is appended. It's the same as for /dev/kmem therefore it does only SEEK_SET and SEEK_CUR, not SEEK_END.
It works for reading from stack pages, positioning is ok but the return value is -1 (which is wrong). Probably because the offsets seem to be negative... Can anybody please tell me why I'm getting the -1 error return though I should get back the huge negative offset?
Thanks in advance,
Erich
Quoted 7 lines · Maciej Golebiewski
Quoted 6 lines · David Mosberger
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Pete Wyckoff
Yes, implementing llseek for fs/proc/base.c:proc_mem_operations is the right solution.
/dev/kmemalready has its own llseek (which treats the offset as unsigned) but, for some reason, was left out of the/proc/pid/memsupport.
Quoted 6 lines
Quoted 1 line
Don, can you add this to the TODO list so we won't forget about it?
Thanks a lot for help. It seems that the solution is simpler than I was expecting. Anyway, I don't have a root access to the IA64 machine in question, so I can't test it myself, but one of the guys with root access told me he'll try to find some time and try it out.
*** linux-2.4.0test12/fs/proc/base.c.orig1 Mon Jan 15 13:12:36 2001
--- linux-2.4.0test12/fs/proc/base.c Mon Jan 15 13:14:49 2001
***************
*** 396,402 ****
--- 396,417 ----
}
#endif
+ static loff_t mem_lseek(struct file * file, loff_t offset, int orig)
+ {
+ switch (orig) {
+ case 0:
+ file->f_pos = offset;
+ return file->f_pos;
+ case 1:
+ file->f_pos += offset;
+ return file->f_pos;
+ default:
+ return -EINVAL;
+ }
+ }
+
static struct file_operations proc_mem_operations = {
+ llseek: mem_lseek,
read: mem_read,
write: mem_write,};
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Erich Focht
Erich> A small patch for the file fs/proc/base.c implementing llseek for Erich> /proc/PID/mem is appended. It's the same as for /dev/kmem therefore it Erich> does only SEEK_SET and SEEK_CUR, not SEEK_END.
Thanks for the patch, I applied it to my tree and will work on getting it into Linus's tree.
Erich> It works for reading from stack pages, positioning is ok but the return Erich> value is -1 (which is wrong). Probably because the offsets seem to be Erich> negative... Can anybody please tell me why I'm getting the -1 error return Erich> though I should get back the huge negative offset?
I added a force_successful_syscall_return() to ensure that a succesful lseek() returning a "negative" value isn't mistaken as an error. I did the same to memory_lseek() in drivers/char/mem.c. This should avoid the problem you were seeing.
--david