Skip to contentSkip to conversation

/proc/pid/mem and stack variables

Linux-ia64 Maciej Golebiewski 4 participants 6 messages Jan 12, 2001 – Jan 18, 2001

lore
Share & tools
lore
#0 lore raw

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
#1 lore raw
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/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:

Quoted 8 lines

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.

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
#2 lore raw
In reply to Maciej Golebiewski
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/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:

Quoted 7 lines
Quoted 7 lines

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.

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
#3 lore raw
In reply to Maciej Golebiewski
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/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 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
#4 lore raw
In reply to Maciej Golebiewski

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/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.

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,

};

#5 lore raw
In reply to Maciej Golebiewski
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