Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

unmapping the executeable

0 views
Skip to first unread message

phil-new...@ipal.net

unread,
Jul 31, 2001, 2:15:35 AM7/31/01
to
Is there a way for a process to determine in some simple way what
addresses the executeable has been mapped into? I want to be able
completely severe ties with the executeable file in order to be
able to umount() the filesystem it was loaded from (after having
copied executeable code into the heap or stack somewhere). This
process will have no library linked (it hasn't been mounted at
the time the executeable is run), so it needs to be something
not too elaborate, like a syscall or information in /proc.

--
-----------------------------------------------------------------
| Phil Howard - KA9WGN | Dallas | http://linuxhomepage.com/ |
| phil-...@ipal.net | Texas, USA | http://phil.ipal.org/ |
-----------------------------------------------------------------

John Reiser

unread,
Jul 31, 2001, 9:39:27 AM7/31/01
to
> Is there a way for a process to determine in some simple way what
> addresses the executeable has been mapped into?

Probably not "in some simple way," and this is a deficiency of Linux.
There ought to be an equivalent to the VirtualQuery() of Win32, but
the best that Linux offers in that line is to parse /proc/self/maps
and avoid files whose names contain '\n' or "rw-p" etc.

If you are dealing with vanilla ELF, then
-----
#include <link.h>
#include <dlfcn.h> /* cc ... -ldl */

main()
{
struct link_map const *const lm = dlopen(0, RTLD_LAZY);
/* look at .l_addr in the list *lm, *lm->l_next, ... */

return 0;
}
-----
comes close in many ways. However, for an ET_EXEC file, link_map.l_addr
is 0 because l_addr is actually a relocation value, not a base
address; an ET_EXEC file needs no relocation. glibc 2.2.* has
hidden the fields .l_map_start and .l_map_end, which provide some
clues (see the full structure definition in the elf/ directory
of the glibc sources.) The fields .l_phdr and .l_phnum are also
useful, but also hidden.

Another entrance to this problem is the DT_DEBUG field of PT_DYNAMIC
(see <elf.h>) or "extern Elf32_Dyn _DYNAMIC[];". See <link.h>.

The pseudo file /proc/self/exe can also be parsed for Elf32_Ehdr
and Elf32_Phdr; or readlink()ed, etc.

And if your program doesn't do putenv(), then the Elf32_auxv_t
array which follows the 0 that terminates the pointers to
environment strings can be inspected for AT_PHDR etc.

--
John Reiser, jre...@BitWagon.com

John Reiser

unread,
Jul 31, 2001, 11:49:55 AM7/31/01
to
Here's an initial proposal for an ioctl() on /proc/pid/maps
which supports query of the kernel vma.

#include <asm/ioctl.h>
struct vma_info {
int64 offset; /* in fd below */
unsigned long address; /* IN: query address; OUT: base of region */
unsigned long length; /* of region */
unsigned int flags; /* VM_* flags */
int fd; /* apply fstat(), etc; remember to close(). */
};
/* If no vma covers an address, then a pseudo-region is returned,
such that length+address is the beginning of the next vma,
and flags will be all-zero [or something...], and ~0==fd.
*/

#define VMA_GET _IOWR('V', 1, struct vma_info)

/* example: enumerate the address space */
int const maps = open("/proc/self/maps", O_RDONLY, 0);
unsigned long addr = 0;
for (;;) {
struct vma_info info;
info.address = addr;
if (0!=ioctl(maps, VMA_GET, &info)) {
/* check errno, etc. */
break; /* done enumerating */
}
/* examine info _now_ */

close(info.fd);
addr += info.length;
}
close(maps);

--
John Reiser, jre...@BitWagon.com

Eric Taylor

unread,
Jul 31, 2001, 1:02:04 PM7/31/01
to

phil-new...@ipal.net wrote:

Couldn't you copy your executable into a ram disk and
run from there? I assume you want to umount some other "real"
disk. If not, please ignore me.

eric


phil-new...@ipal.net

unread,
Jul 31, 2001, 7:00:58 PM7/31/01
to

Actually, that _is_ where it is running from. It is the ram disk
I want to unmount.

I'm considering just grabbing some memory via mmap(), copying the
program code into there (hopefully that part gets done right) then
unmapping everything else in the whole address space.

Kasper Dupont

unread,
Aug 1, 2001, 5:26:59 AM8/1/01
to
phil-new...@ipal.net wrote:
>
> On Tue, 31 Jul 2001 17:02:04 GMT Eric Taylor <e...@rocketship1.com> wrote:
>
> | phil-new...@ipal.net wrote:
> |
> |> Is there a way for a process to determine in some simple way what
> |> addresses the executeable has been mapped into? I want to be able
> |> completely severe ties with the executeable file in order to be
> |> able to umount() the filesystem it was loaded from (after having
> |> copied executeable code into the heap or stack somewhere). This
> |> process will have no library linked (it hasn't been mounted at
> |> the time the executeable is run), so it needs to be something
> |> not too elaborate, like a syscall or information in /proc.
> |>
> |> --
> |> -----------------------------------------------------------------
> |> | Phil Howard - KA9WGN | Dallas | http://linuxhomepage.com/ |
> |> | phil-...@ipal.net | Texas, USA | http://phil.ipal.org/ |
> |> -----------------------------------------------------------------
> |
> | Couldn't you copy your executable into a ram disk and
> | run from there? I assume you want to umount some other "real"
> | disk. If not, please ignore me.
>
> Actually, that _is_ where it is running from. It is the ram disk
> I want to unmount.
>
> I'm considering just grabbing some memory via mmap(), copying the
> program code into there (hopefully that part gets done right) then
> unmapping everything else in the whole address space.
>

I think you can just munmap() everything except
the few ranges you need to preserve. It is legal
to munmap ranges that are not currently mapped.

I had something similar to this in mind

{
int psize=getpagesize();
munmap(psize,protected-psize);
munmap(protected+psize,
(((stackpointer-protected)/psize)-3)*psize);
}

--
Kasper Dupont

0 new messages