home *** CD-ROM | disk | FTP | other *** search
- Xref: sparky comp.sys.sun.apps:3069 comp.unix.programmer:6033 comp.unix.internals:2152
- Path: sparky!uunet!zaphod.mps.ohio-state.edu!magnus.acs.ohio-state.edu!usenet.ins.cwru.edu!agate!dog.ee.lbl.gov!horse.ee.lbl.gov!torek
- From: torek@horse.ee.lbl.gov (Chris Torek)
- Newsgroups: comp.sys.sun.apps,comp.unix.programmer,comp.unix.internals
- Subject: Re: modifying ARGV within a running program
- Date: 23 Jan 1993 13:18:09 GMT
- Organization: Lawrence Berkeley Laboratory, Berkeley CA
- Lines: 94
- Message-ID: <28603@dog.ee.lbl.gov>
- References: <1jqninINNa8l@usenet.INS.CWRU.Edu>
- NNTP-Posting-Host: 128.3.112.15
-
- In article <1jqninINNa8l@usenet.INS.CWRU.Edu> edvax@pyrite.som.cwru.edu
- (Ed Reznichenko) writes:
- >Does anyone know how to SAFELY modify [what ps will show for a process]?
- >Any ideas on how to do this portably (if at all) would be appreciated.
-
- It cannot be done portably. In fact, on some UNIX systems, it cannot
- be done at all. These systems save away the first few arguments at
- process startup, keeping it in a kernel area off limits to normal user
- code. Here the `ps' command reads this kernel area. Since the kernel
- area is read-only, the stuff ps will show is likewise read-only.
-
- Since this is going to comp.sys.sun.apps: on Suns running SunOS, at
- least---I know nothing about the new Solaris systems---the strings ps
- prints are found at the top of the user stack. (This is true in all
- traditional BSD-based systems.) Specifically, on a SPARC, the layout
- is:
-
- [end of user accessible space] 0xf8000000 (approx.)
- --------------------------------- 0xf7ffffff (approx.)
- | <reserved> | < fixed but system-dependent size
- +-------------------------------+
- | strings & <alignment> | < variable size
- +-------------------------------+
- | NULL | ^ higher addresses
- | environ[ne - 1] | |
- | environ[ne - 2] | |
- | ... | |
- | environ[0] | v lower addresses
- +-------------------------------+
- | NULL |
- | argv[argc - 1] |
- | argv[argc - 2] | < each pointer is 4 bytes
- | ... |
- | argv[0] |
- +-------------------------------+
- | argc | < argc is also 4 bytes
- +-------------------------------+
- | <register window> | < exactly 64 bytes
- +-------------------------------+ <-- %sp at program startup
-
- In SunOS, the <reserved> space is probably empty. In 4.4BSD on the
- SPARC, it contains the signal trampoline code and something I will
- get to in a moment.
-
- The strings, plus any needed padding for alignment, appear immediately
- below the reserved space. They are `in order', with the string for
- argv[0] at the lowest address and the last environment string at the
- highest. These are immediately preceded by pointers to each string;
- these make up the environ[] and argv[] arrays. The `ps' program scans
- backwards (under SunOS, and used to under BSD) through the top few user
- pages looking for the argv strings. Since they are in plain old user
- space pages, it is possible to overwrite them. Note, however, that
- overwriting more space than is available will cause trouble. Since the
- environment strings immediately follow the argv strings, it is possible
- to clobber one's own environment, causing library routines such as
- execlp() and getenv() to fail mysteriously. (Under BSD, one could even
- overwrite the signal trampoline code.)
-
- Incidentally, this is also the reason that a large environment can
- make `ps' fail to find arguments. If those strings take up enough
- space, ps's backwards scan fails, as it only reads the last few pages.
-
- In 4.4BSD, the very top of the <reserved> area always contains a
- structure known as `ps_strings', as defined in <sys/exec.h>:
-
- /*
- * The following structure is found at the top of the user stack of each
- * user process. The ps program uses it to locate argv and environment
- * strings. Programs that wish ps to display other information may modify
- * it; normally ps_argvstr points to the text for argv[0], and ps_nargvstr
- * is the same as the program's argc. The fields ps_envstr and ps_nenvstr
- * are the equivalent for the environment.
- */
- struct ps_strings {
- char *ps_argvstr; /* first of 0 or more argument strings */
- int ps_nargvstr; /* the number of argument strings */
- char *ps_envstr; /* first of 0 or more environment strings */
- int ps_nenvstr; /* the number of environment strings */
- };
-
- A C library routine (not yet written, but to be called `setproctitle'
- ---this is the name used in sendmail, ftp, etc) will provide a portable
- interface to altering ps_strings. The `ps' program simply reads the
- pointer and count, then fetchs ps_nargvstr NUL-terminated strings
- starting at ps_argvstr. There is no need to arrange `extra' space in
- advance for long setproctitle()s, as the space can simply be allocated
- on the heap.
-
- Note: all of the above is based on the alpha 4.4BSD SPARC kernel. While
- this kernel runs SunOS binaries, there is no guarantee that the SunOS
- C startup code does not modify the picture somehow.
- --
- In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 510 486 5427)
- Berkeley, CA Domain: torek@ee.lbl.gov
-