2001-11-20 16:41:15

by Luís Henriques

[permalink] [raw]
Subject: copy to suer space

Hi,
I'm trying to implement a kernel module that will be changing a user
process' code segment. I tried to user copy_to_user to patch the process's
code but, when I tried to read the new code (just to check...), it didn't
worked. Why was that? And what is the solution?

Thanks

Luis Henriques


2001-11-20 17:03:27

by Anton Altaparmakov

[permalink] [raw]
Subject: Re: copy to suer space

At 16:40 20/11/01, Luis Miguel Correia Henriques wrote:
>I'm trying to implement a kernel module that will be changing a user
>process' code segment. I tried to user copy_to_user to patch the process's
>code but, when I tried to read the new code (just to check...), it didn't
>worked. Why was that? And what is the solution?

I don't think what you are trying to do is possible. Even if you somehow
managed to write over the code segment of a user space process (which I
very much doubt would be possible as I assume the memory is mapped
read-only), as soon as the kernel pages out (i.e. discards!) some portion
of the executable due to memory shortage your changes would be lost, since
the paging back into memory would happen by reading the executable back
from disk, which would mean it would read the unmodified code into memory...

Why would you want to do such a thing anyway? Kernel modifying userspace
binaries in memory sounds like a really flawed idea which is just begging
for problems. - Just recompiling the user space program with the smallest
change would make the new binary code incompatible with your predefined
module...

But perhaps I misunderstood you?

Anton


--
"I've not lost my mind. It's backed up on tape somewhere." - Unknown
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Linux NTFS Maintainer / WWW: http://linux-ntfs.sf.net/
ICQ: 8561279 / WWW: http://www-stu.christs.cam.ac.uk/~aia21/

2001-11-20 17:14:17

by Luís Henriques

[permalink] [raw]
Subject: Re: copy to suer space

> I don't think what you are trying to do is possible. Even if you somehow
> managed to write over the code segment of a user space process (which I
> very much doubt would be possible as I assume the memory is mapped
> read-only)

Is there a way to solve this problem? To temporarly turn it read/write?

>, as soon as the kernel pages out (i.e. discards!) some portion
> of the executable due to memory shortage your changes would be lost, since
> the paging back into memory would happen by reading the executable back
> from disk, which would mean it would read the unmodified code into
> memory...

When I'm modifing the code, I'm sure that the page is in memory because my
code is called from the user space, in the exact location where I want to
change it (with a breakpoint interruption...)

The point is that I can't write to the memory location I want... How do I
solve this?

--
Lu?s Henriques

2001-11-20 17:38:47

by Anton Altaparmakov

[permalink] [raw]
Subject: Re: copy to suer space

At 17:08 20/11/01, Lu?s Henriques wrote:
>When I'm modifing the code, I'm sure that the page is in memory because my
>code is called from the user space, in the exact location where I want to
>change it (with a breakpoint interruption...)

There is a time window in which it might get paged out in the mean time but
it's admittedly a very small window. But that is irrelevant as copy_to_user
would take care of the page out case by faulting the page back in (that is
at least my understanding of it).

But that is not the problem I was talking about: Imagine you do
successfully modify the user space code and AFTER THAT the kernel pages out
the code and pages it back in later. Your change is then lost without trace.

That can easily crash your program depending on what modifications you do
to it...

Anton


--
"I've not lost my mind. It's backed up on tape somewhere." - Unknown
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Linux NTFS Maintainer / WWW: http://linux-ntfs.sf.net/
ICQ: 8561279 / WWW: http://www-stu.christs.cam.ac.uk/~aia21/

2001-11-20 17:58:57

by Luís Henriques

[permalink] [raw]
Subject: Re: copy to suer space

> There is a time window in which it might get paged out in the mean time but
> it's admittedly a very small window. But that is irrelevant as copy_to_user
> would take care of the page out case by faulting the page back in (that is
> at least my understanding of it).
>
> But that is not the problem I was talking about: Imagine you do
> successfully modify the user space code and AFTER THAT the kernel pages out
> the code and pages it back in later. Your change is then lost without
> trace.
>
> That can easily crash your program depending on what modifications you do
> to it...
>
> Anton

I don't understand... this means that the paging does not save the a code
segment in memory? (sorry, this question is being done by a newbie...) When a
page is back to memory, what happens? Is read again from the binary file
(executable)?

Well... I don't think this will have much impact in my module because what it
does is:

- change the code in a process
- return to the process
- next time the process is scheduled, the code will be stored again in the CS

So, I don't think that the paging will really became a problem as this shall
be quiet fast! The idea of changing the code is just to insert a delay in a
process, but leaving the process ?burning? CPU time...

The point is: I'm not changing the code because of an obscure (to me...)
reason. You told me that the code segment may be protected and I'm
investigating on that but I would like to be sure that the kernel has no
acess to a user CS...

--
Lu?s Henriques

2001-11-20 18:14:57

by Luís Henriques

[permalink] [raw]
Subject: Re: copy to suer space

I remembered something: could it be just a problem with the cache? I mean,
I'm reading a cache with invalid data...

--
Lu?s Henriques

2001-11-20 18:19:27

by Nick LeRoy

[permalink] [raw]
Subject: Re: copy to suer space

On Tuesday 20 November 2001 11:53, Lu?s Henriques wrote:
> > There is a time window in which it might get paged out in the mean time
> > but it's admittedly a very small window. But that is irrelevant as
> > copy_to_user would take care of the page out case by faulting the page
> > back in (that is at least my understanding of it).
> >
> > But that is not the problem I was talking about: Imagine you do
> > successfully modify the user space code and AFTER THAT the kernel pages
> > out the code and pages it back in later. Your change is then lost without
> > trace.
> >
> > That can easily crash your program depending on what modifications you do
> > to it...
> >
> > Anton
>
> I don't understand... this means that the paging does not save the a code
> segment in memory? (sorry, this question is being done by a newbie...) When
> a page is back to memory, what happens? Is read again from the binary file
> (executable)?
>
> Well... I don't think this will have much impact in my module because what
> it does is:
>
> - change the code in a process
> - return to the process
> - next time the process is scheduled, the code will be stored again in the
> CS
>
> So, I don't think that the paging will really became a problem as this
> shall be quiet fast! The idea of changing the code is just to insert a
> delay in a process, but leaving the process ?burning? CPU time...
>
> The point is: I'm not changing the code because of an obscure (to me...)
> reason. You told me that the code segment may be protected and I'm
> investigating on that but I would like to be sure that the kernel has no
> acess to a user CS...

Linux executables are "demand paged". What this means is that they are
loaded as they are "page faulted" in. If low on memory, the kernel may, at
it's discression, discard text pages at any time. When a discarded page is
referenced, a page fault occurs, and the page is re-loaded from the
executable. They are *never* written out to swap space. The kernel fully
expects the text file and the text memory pages to not be modified during
execution.

-Nick

2001-11-20 18:42:53

by Andreas Dilger

[permalink] [raw]
Subject: Re: copy to suer space

On Nov 20, 2001 17:08 +0000, Lu?s Henriques wrote:
> > I don't think what you are trying to do is possible. Even if you somehow
> > managed to write over the code segment of a user space process (which I
> > very much doubt would be possible as I assume the memory is mapped
> > read-only)
>
> Is there a way to solve this problem? To temporarly turn it read/write?
>
> >, as soon as the kernel pages out (i.e. discards!) some portion
> > of the executable due to memory shortage your changes would be lost, since
> > the paging back into memory would happen by reading the executable back
> > from disk, which would mean it would read the unmodified code into
> > memory...
>
> When I'm modifing the code, I'm sure that the page is in memory because my
> code is called from the user space, in the exact location where I want to
> change it (with a breakpoint interruption...)
>
> The point is that I can't write to the memory location I want... How do I
> solve this?

Maybe if you describe the actual problem that you are trying to solve, and
not the actual way you are trying to solve it, there may be a better method.
Usually, if something you are trying to do is very hard to do, there is a
different (much better) way of doing it.

Cheers, Andreas
--
Andreas Dilger
http://sourceforge.net/projects/ext2resize/
http://www-mddsp.enel.ucalgary.ca/People/adilger/

2001-11-20 18:51:24

by Luís Henriques

[permalink] [raw]
Subject: Re: copy to suer space


> Maybe if you describe the actual problem that you are trying to solve, and
> not the actual way you are trying to solve it, there may be a better
> method. Usually, if something you are trying to do is very hard to do,
> there is a different (much better) way of doing it.
>
> Cheers, Andreas

OK, here it goes:

I'm developping a kernel module that needs to delay a process, that is, he
receives a PID and, when a specific event occurs, that process shall be
delayed. This delay shall be done in a way that the process keeps burning CPU
time (it can not be, e.g., put in a waiting-list...).
The solution I found was to change its code segment, putting a loop in it.
After a specified period of time, the original code must be restored and the
process must keep going as nothing happened.
The main problem I found was already explained: can't write to the CS!

--
Lu?s Henriques

2001-11-20 19:01:13

by Hua Zhong (hzhong)

[permalink] [raw]
Subject: Re: copy to suer space

Why not SIGSTOP/SIGCONT instead?

I don't see any reason why you should change the code segment (reminded me
some ugly Windows hacks of changing DLL entries).

----- Original Message -----
From: "Lu?s Henriques" <[email protected]>
To: "Andreas Dilger" <[email protected]>
Cc: "Anton Altaparmakov" <[email protected]>; <[email protected]>
Sent: Tuesday, November 20, 2001 10:44 AM
Subject: Re: copy to suer space


>
> > Maybe if you describe the actual problem that you are trying to solve,
and
> > not the actual way you are trying to solve it, there may be a better
> > method. Usually, if something you are trying to do is very hard to do,
> > there is a different (much better) way of doing it.
> >
> > Cheers, Andreas
>
> OK, here it goes:
>
> I'm developping a kernel module that needs to delay a process, that is, he
> receives a PID and, when a specific event occurs, that process shall be
> delayed. This delay shall be done in a way that the process keeps burning
CPU
> time (it can not be, e.g., put in a waiting-list...).
> The solution I found was to change its code segment, putting a loop in it.
> After a specified period of time, the original code must be restored and
the
> process must keep going as nothing happened.
> The main problem I found was already explained: can't write to the CS!
>
> --
> Lu?s Henriques
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/

2001-11-20 19:40:56

by Andreas Dilger

[permalink] [raw]
Subject: Re: copy to suer space

On Nov 20, 2001 18:44 +0000, Lu?s Henriques wrote:
> > Maybe if you describe the actual problem that you are trying to solve, and
> > not the actual way you are trying to solve it, there may be a better
> > method. Usually, if something you are trying to do is very hard to do,
> > there is a different (much better) way of doing it.
>
> I'm developping a kernel module that needs to delay a process, that is, he
> receives a PID and, when a specific event occurs, that process shall be
> delayed. This delay shall be done in a way that the process keeps burning CPU
> time (it can not be, e.g., put in a waiting-list...).

Putting it into a waiting-list is by far the best solution. This is a normal
Unix operation, like SIGSTOP, SIGCONT, and could even be done from user space.

What is the requirement that it keeps burning CPU for? Generally, this is
what you do NOT want to do.

Depending on what that is for, you could just increment the "system time"
ticks in the process, which is kind of a hack, but not nearly so ugly as
changing the user-space code (which is truly dreadful, and I don't think
anyone on this list would ever help you do that, even if they could).

The other alternative is to make your module such that upon entry, the
user process simply busy-waits until the delay is complete. This is also
easy to do, with something like udelay().

Cheers, Andreas
--
Andreas Dilger
http://sourceforge.net/projects/ext2resize/
http://www-mddsp.enel.ucalgary.ca/People/adilger/

2001-11-21 00:07:30

by Mike Fedyk

[permalink] [raw]
Subject: Re: copy to suer space

On Tue, Nov 20, 2001 at 12:39:15PM -0700, Andreas Dilger wrote:
> On Nov 20, 2001 18:44 +0000, Lu?s Henriques wrote:
> > > Maybe if you describe the actual problem that you are trying to solve, and
> > > not the actual way you are trying to solve it, there may be a better
> > > method. Usually, if something you are trying to do is very hard to do,
> > > there is a different (much better) way of doing it.
> >
> > I'm developping a kernel module that needs to delay a process, that is, he
> > receives a PID and, when a specific event occurs, that process shall be
> > delayed. This delay shall be done in a way that the process keeps burning CPU
> > time (it can not be, e.g., put in a waiting-list...).
>
> Putting it into a waiting-list is by far the best solution. This is a normal
> Unix operation, like SIGSTOP, SIGCONT, and could even be done from user space.
>
> What is the requirement that it keeps burning CPU for? Generally, this is
> what you do NOT want to do.
>

This to me looks like the main desire is to fool the user. It looks like it
doing something, but it really isn't...

2001-11-21 10:56:21

by Luís Henriques

[permalink] [raw]
Subject: Re: copy to suer space

On Tuesday 20 November 2001 07:31 pm, Tyler BIRD wrote:
> What is the other "specifc event that occurs" you could write a spinlock
> and the other thread that causes the event could release that lock
> Of course interrups should be enabled when some thing like this should
> happen Is this other event a interrupt?

The specific event is a breakpoint interrupt: when a specific memory address
is used (for opcode fetch/read/write) in the addressing space of a process,
then an exception is raised and a handler for this exception will be called -
this is my module.

>
>
> There are various ways I'll have to look up when I get home.
> you could alter the cs if you change the vma properties especially the
> permissions properties and you can do this I just don't have the details
> now.
>
> the cs is protected by default
> Tyler
>

--
Lu?s Henriques

2001-11-21 10:58:11

by Luís Henriques

[permalink] [raw]
Subject: Re: copy to suer space

> This to me looks like the main desire is to fool the user. It looks like
> it doing something, but it really isn't...

Not really... This may look like an old DOS virus :) but it is not! It's a
fault injection tool - it's purpose (in this case, of corse) is to cause a
very short delay on a critic process.

--
Lu?s Henriques

2001-11-21 14:37:48

by Joerg

[permalink] [raw]
Subject: Re: copy to suer space

Nick LeRoy <[email protected]> wrote:

> Linux executables are "demand paged". What this means is that they are

> loaded as they are "page faulted" in. If low on memory, the kernel
> may, at it's discression, discard text pages at any time. When a
> discarded page is referenced, a page fault occurs, and the page is re-
> loaded from the executable. They are *never* written out to swap
> space. The kernel fully expects the text file and the text memory
> pages to not be modified during execution.

Clean pages are never written to swap space. If the page is dirty, it's
just another data page. If it were otherwise, non-PIC shared libraries
that require fixups from the dynamic linker would not work.

Regards
Joerg


=====
--
Regards
Joerg


__________________________________________________
Do You Yahoo!?
Yahoo! GeoCities - quick and easy web site hosting, just $8.95/month.
http://geocities.yahoo.com/ps/info1

2001-11-22 19:46:10

by Andreas Bombe

[permalink] [raw]
Subject: Re: copy to suer space

On Tue, Nov 20, 2001 at 05:53:24PM +0000, Lu?s Henriques wrote:
> I don't understand... this means that the paging does not save the a code
> segment in memory? (sorry, this question is being done by a newbie...) When a
> page is back to memory, what happens? Is read again from the binary file
> (executable)?

Code and data pages are mapped from the executable. Code is read-only
and can therefore be discarded at any time, since it exists on disk (in
the executable file, no swap needed). Data is mapped copy-on-write
(read-only pages until writes occur, then a writable copy is generated).

So only modified data pages and new mappings not backed by a disk file
need to be saved in swap space.

> Well... I don't think this will have much impact in my module because what it
> does is:
>
> - change the code in a process
> - return to the process
> - next time the process is scheduled, the code will be stored again in the CS

I'm not sure why you would want to actually _change_ code. You could
prepare a page in kernel with the busy loop and map that into user
space.

Then make the kernel return to your busy loop and let it call back to
the kernel again when finished, then remove the mapping to leave no
traces. Maybe that could be done by redirecting a signal handler
pointer and raising that signal.

I don't know how difficult that is, it's just an idea. But it sure
sounds easier than modifying a read-only page without side effects.

--
Andreas Bombe <[email protected]> DSA key 0x04880A44

2001-11-23 13:17:02

by Juan Quintela

[permalink] [raw]
Subject: Re: copy to suer space

>>>>> "lu?s" == Lu?s Henriques <[email protected]> writes:

>> This to me looks like the main desire is to fool the user. It looks like
>> it doing something, but it really isn't...

lu?s> Not really... This may look like an old DOS virus :) but it is not! It's a
lu?s> fault injection tool - it's purpose (in this case, of corse) is to cause a
lu?s> very short delay on a critic process.

What is wrong putting a signal handler in your process for a signal,
and busy wait in that signal all the time that you want?

Later, Juan.


--
In theory, practice and theory are the same, but in practice they
are different -- Larry McVoy

2001-11-23 14:41:23

by Luís Henriques

[permalink] [raw]
Subject: Re: copy to suer space

> What is wrong putting a signal handler in your process for a signal,
> and busy wait in that signal all the time that you want?

The point is that I'm implementing a tool that shall test fault tolerance (in
the user processes, operating system, architecture, ...). The process is not
supposed to know that he is being delayed!

n0ano suggested me another solution (thanks n0ano!!!): instead of altering
the CS, I just put some code to the process stack, return to the SS:ESP
(instead of CS:EIP) and, later, restore the stack and return to the process.

This is not working yet because it's - I'm having some problems with it.
Could anyone look at this code and tell me where it can fail?

rdtsc
movl %eax, %ecx
addl $0x1, %ecx
loop:
rdtsc
cmp %ecx, %eax
jb loop

When I read the timestamp (?rdtsc?), a value is returned to edx:eax. This
code works just fine when I put it in the process stack. The problem is when
I want to compare %edx instead of %eax, that is:

rdtsc
movl %edx, %ecx
addl $0x1, %ecx
loop:
rdtsc
cmp %ecx, %edx
jb loop

This is supposed to take much more time than the other loop. When I write
this code to the stack of my process, a segmentation fault occurs after some
time. Why? I'm not changing the stack at any moment! (By the way, the stack
pointer is pointing to the end of my code...)

--
Lu?s Henriques

2001-11-23 23:54:45

by H. Peter Anvin

[permalink] [raw]
Subject: Re: copy to suer space

Followup to: <[email protected]>
By author: =?iso-8859-1?q?Lu=EDs=20Henriques?=
<[email protected]>
In newsgroup: linux.dev.kernel
>
> When I read the timestamp (?rdtsc?), a value is returned to edx:eax. This
> code works just fine when I put it in the process stack. The problem is when
> I want to compare %edx instead of %eax, that is:
>
> rdtsc
> movl %edx, %ecx
> addl $0x1, %ecx
> loop:
> rdtsc
> cmp %ecx, %edx
> jb loop
>
> This is supposed to take much more time than the other loop. When I write
> this code to the stack of my process, a segmentation fault occurs after some
> time. Why? I'm not changing the stack at any moment! (By the way, the stack
> pointer is pointing to the end of my code...)
>

Did you remember to restore all the registers, including %eax and
%eflags, before you return?

-hpa
--
<[email protected]> at work, <[email protected]> in private!
"Unix gives you enough rope to shoot yourself in the foot."
http://www.zytor.com/~hpa/puzzle.txt <[email protected]>