Hi all :))
I'm not sure whether this issue belongs to the kernel or to the
libc, but I think that is more on the kernel side, that's why I ask
here.
Let's go to the matter: I want to change the argv[0] a program
shows, in order to be pretty-printed when issuing 'ps', 'top' or
other commands. What I'm doing now is just writing over the existing
argv[0] string, but then I must use a *shorter-or-equal* string in
order to fit it on the existing space. What if I need to put a
*larger* string on argv[0]? Is this possible at all?
Thanks in advance :)
Ra?l
Hi Richard :)
> > libc, but I think that is more on the kernel side, that's why I ask
> Last time I checked argv[0] was 512 bytes. Many daemons overwrite
> it with no problem.
Any header where I can see the length for argv[0] or is this some
kind of unoficial standard? Just doing strcpy seems dangerous to me
(you can read 'paranoid'...).
Thanks a lot for your answer, Richard :)
Ra?l
On Tue, 14 Jan 2003, DervishD wrote:
> Hi all :))
>
> I'm not sure whether this issue belongs to the kernel or to the
> libc, but I think that is more on the kernel side, that's why I ask
> here.
>
Last time I checked argv[0] was 512 bytes. Many daemons overwrite
it with no problem.
PID TTY STAT TIME COMMAND
126 4 S 0:00 /sbin/agetty 38400 tty4
127 5 S 0:00 /sbin/agetty 38400 tty5
128 6 S 0:00 /sbin/agetty 38400 tty6
5241 2 S 0:00 -bash
13476 1 S 0:00 How-long-do-you-want-this-string-to-be?--is-this-long-enoug
13489 3 R 0:00 ps
27498 3 S 0:00 -bash
31011 1 S 0:00 -bash
#include <stdio.h>
#include <string.h>
int main(int cnt, char *argv[]) {
strcpy(argv[0], "How-long-do-you-want-this-string-to-be?--is-this-long-enough?");
pause();
return 0;
}
Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
Why is the government concerned about the lunatic fringe? Think about it.
On Tue, 14 Jan 2003, DervishD wrote:
> Hi Richard :)
>
> > > libc, but I think that is more on the kernel side, that's why I ask
> > Last time I checked argv[0] was 512 bytes. Many daemons overwrite
> > it with no problem.
>
> Any header where I can see the length for argv[0] or is this some
> kind of unoficial standard? Just doing strcpy seems dangerous to me
> (you can read 'paranoid'...).
>
> Thanks a lot for your answer, Richard :)
> Ra?l
>
They need to have space for _POSIX_PATH_MAX (512 bytes), to
claim POSIX compatibility so any POSIX system will have at
least 512 bytes available because the pathname of the executable
normally goes there.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
Why is the government concerned about the lunatic fringe? Think about it.
Hi Richard :)
> > Any header where I can see the length for argv[0] or is this some
> > kind of unoficial standard? Just doing strcpy seems dangerous to me
> > (you can read 'paranoid'...).
> They need to have space for _POSIX_PATH_MAX (512 bytes), to
> claim POSIX compatibility so any POSIX system will have at
> least 512 bytes available because the pathname of the executable
> normally goes there.
Enough for me, then. Thanks a lot :)) Just one more thing: in my
Single Unix Spec v3 says that the minimum value of _POSIX_PATH_MAX is
256, not 512, and the libc manual says just the same :??
Anyway, 256 bytes is a fair large amount ;))))
Thanks again, Richard.
Ra?l
On Tue, 14 Jan 2003, DervishD wrote:
> Hi Richard :)
>
> > > Any header where I can see the length for argv[0] or is this some
> > > kind of unoficial standard? Just doing strcpy seems dangerous to me
> > > (you can read 'paranoid'...).
> > They need to have space for _POSIX_PATH_MAX (512 bytes), to
> > claim POSIX compatibility so any POSIX system will have at
> > least 512 bytes available because the pathname of the executable
> > normally goes there.
>
> Enough for me, then. Thanks a lot :)) Just one more thing: in my
> Single Unix Spec v3 says that the minimum value of _POSIX_PATH_MAX is
> 256, not 512, and the libc manual says just the same :??
>
> Anyway, 256 bytes is a fair large amount ;))))
>
> Thanks again, Richard.
>
> Ra?l
>
Well I just grepped through usr/include/bits/posix1_lim.h and it
shows 255 (with this 'C' library) so you are probably right.
In any event, a "whole line of text" isn't going to overrun it.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
Why is the government concerned about the lunatic fringe? Think about it.
On Tue, 14 Jan 2003, Mark Mielke wrote:
> On Tue, Jan 14, 2003 at 02:56:35PM -0500, Richard B. Johnson wrote:
> > Well I just grepped through usr/include/bits/posix1_lim.h and it
> > shows 255 (with this 'C' library) so you are probably right.
> > In any event, a "whole line of text" isn't going to overrun it.
>
> Looking at the code, it looks to me as if argv[0] can be any size up to
> _SC_ARG_MAX, with the restraining factor being that the environment
> variables and the other arguments must fit in the same space.
>
> Is this not correct?
>
> mark
Don't think so. In my headers _SC_ARG_MAX is an enumerated type
that is numerically equal to 0. It's in confname.h, the first
element in the enumerated list.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
Why is the government concerned about the lunatic fringe? Think about it.
On Tue, Jan 14, 2003 at 02:56:35PM -0500, Richard B. Johnson wrote:
> Well I just grepped through usr/include/bits/posix1_lim.h and it
> shows 255 (with this 'C' library) so you are probably right.
> In any event, a "whole line of text" isn't going to overrun it.
Looking at the code, it looks to me as if argv[0] can be any size up to
_SC_ARG_MAX, with the restraining factor being that the environment
variables and the other arguments must fit in the same space.
Is this not correct?
mark
--
[email protected]/[email protected]/[email protected] __________________________
. . _ ._ . . .__ . . ._. .__ . . . .__ | Neighbourhood Coder
|\/| |_| |_| |/ |_ |\/| | |_ | |/ |_ |
| | | | | \ | \ |__ . | | .|. |__ |__ | \ |__ | Ottawa, Ontario, Canada
One ring to rule them all, one ring to find them, one ring to bring them all
and in the darkness bind them...
http://mark.mielke.cc/
"Richard B. Johnson" <[email protected]> writes:
> On Tue, 14 Jan 2003, DervishD wrote:
>
> > Hi all :))
> >
> > I'm not sure whether this issue belongs to the kernel or to the
> > libc, but I think that is more on the kernel side, that's why I ask
> > here.
> >
>
> Last time I checked argv[0] was 512 bytes. Many daemons overwrite
> it with no problem.
Last time must have been in an alternate reality.
You just overwrote all your arguments (argv[0] and others) and part of
the environment.
Try this for a change:
#include <stdio.h>
#include <string.h>
extern char ** _environ;
int main(int cnt, char *argv[]) {
char **eptr;
for ( eptr = _environ; *eptr; ++eptr )
printf("ENV before: %s\n", *eptr);
strcpy(argv[0], "How-long-do-you-want-this-string-to-be?--is-this-long-enough?");
for ( eptr = _environ; *eptr; ++eptr )
printf("ENV after: %s\n", *eptr);
pause();
return 0;
}
Phil.
On 14 Jan 2003, Philippe Troin wrote:
> "Richard B. Johnson" <[email protected]> writes:
>
> > On Tue, 14 Jan 2003, DervishD wrote:
> >
> > > Hi all :))
> > >
> > > I'm not sure whether this issue belongs to the kernel or to the
> > > libc, but I think that is more on the kernel side, that's why I ask
> > > here.
> > >
> >
> > Last time I checked argv[0] was 512 bytes. Many daemons overwrite
> > it with no problem.
>
> Last time must have been in an alternate reality.
>
> You just overwrote all your arguments (argv[0] and others) and part of
> the environment.
>
It seems to depend upon the machine, maybe the 'C' runtime library.
uname -a
Linux chaos 2.4.18 #15 SMP Mon Jul 15 14:19:43 EDT 2002 i686
This machine is a composite, made from stuff dating back over
5 years, but with two 'C' runtime library updates and many
of the programs/utilities re-compiled.
Script started on Tue Jan 14 15:45:11 2003
[9;0]# xxx
ENV before: LOGNAME=root
ENV before: NLSPATH=/usr/man:/usr/X11/man:/usr/openwin/man:/opt/schily/man
ENV before: MINICOM=-c on
ENV before: VISUAL=/bin/vi
ENV before: MAIL=/var/spool/mail/root
ENV before: LD_LIBRARY_PATH=/lib:/usr/lib/:/opt/intel/compiler50/ia32/lib:/usr/X11R6/lib:/opt/Office50/lib:/usr/java/lib/i686
ENV before: TERMCAP=vt100|vt100-am|dec vt100 (w/advanced video):am:mi:ms:xn:xo:co#80:it#8:li#25:vt#3:@8=\EOM:DO=\E[%dB:K1=\EOq:K2=\EOr:K3=\EOs:K4=\EOp:K5=\EOn:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:ac=\140\140aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:ae=^O:
as=^N:bl=^G:cb=\E[1K:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:do=^J:eA=\E(B\E)0:ho=\E[H:k0=\EOy:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\EOt:k6=\EOu:k7=\EOv:k8=\EOl:k9=\EOw:k;=\EOx:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:ks=\
E[?1h\E=:ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:me=\E[m\017:mr=\E[7m:nd=\E[C:is=\E<\E)0:r2=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rc=\E8:sc=\E7:se=\E[m:sf=^J:so=\E[1;7m:sr=\EM:st=\EH:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:
ENV before: TERM=vt100-am
ENV before: HOSTTYPE=i386
ENV before: PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/opt/schily/bin:/usr/bin/X11:/sbin/:/usr/TeX/bin:/usr/openwin/bin:/opt/intel/compiler50/ia32/bin:/usr/games:.:/usr/local/Office50/bin:/usr/java/bin:/home/users/root/tools:/home/users/root/tools
ENV before: PRINTER=mcd
ENV before: HOME=/root
ENV before: PS_SYSTEM_MAP=/System.map
ENV before: SHELL=/bin/bash
ENV before: LINES=25
ENV before: PS1=#
ENV before: PS2=>
ENV before: MANPATH=/usr/man:/usr/X11/man:/usr/openwin/man:/opt/schily/man
ENV before: LESS=-MM
ENV before: COLUMNS=80
ENV before: LIB=/usr/X11R6/lib:/usr/X11/lib:/usr/X11/lib
ENV before: GNUHELP=/usr/local/lib/gnuplot/gnuplot.gih
ENV before: JAVA_HOME=/usr/java
ENV before: DISPLAY=:0
ENV before: LANG=en_US.88591
ENV before: OSTYPE=Linux
ENV before: OPENWINHOME=/usr/openwin
ENV before: SHLVL=2
ENV before: EDITOR=/bin/vi
ENV before: LS_COLORS=no=00:fi=40;32:di=01;34:ln=01;36:pi=40;33:so=01;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=01;33:*.cmd=01;32:*.o=40;32:*.c=01;26:*.S=01;26:*.h=01;32:*.exe=01;32:*.com=01;32:*.btm=01;32:*.bat=01;32:*.tar=01;31:*.tgz=0
1;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.jpg=01;35:*.gif=01;35:*.bmp=01;35:*.xbm=01;35:*.xpm=01;35:
ENV before: TZ=US/Eastern
ENV before: _=./xxx
ENV after: LOGNAME=root
ENV after: NLSPATH=/usr/man:/usr/X11/man:/usr/openwin/man:/opt/schily/man
ENV after: MINICOM=-c on
ENV after: VISUAL=/bin/vi
ENV after: MAIL=/var/spool/mail/root
ENV after: LD_LIBRARY_PATH=/lib:/usr/lib/:/opt/intel/compiler50/ia32/lib:/usr/X11R6/lib:/opt/Office50/lib:/usr/java/lib/i686
ENV after: TERMCAP=vt100|vt100-am|dec vt100 (w/advanced video):am:mi:ms:xn:xo:co#80:it#8:li#25:vt#3:@8=\EOM:DO=\E[%dB:K1=\EOq:K2=\EOr:K3=\EOs:K4=\EOp:K5=\EOn:LE=\E[%dD:RI=\E[%dC:UP=\E[%dA:ac=\140\140aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:ae=^O:a
s=^N:bl=^G:cb=\E[1K:cd=\E[J:ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:do=^J:eA=\E(B\E)0:ho=\E[H:k0=\EOy:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\EOt:k6=\EOu:k7=\EOv:k8=\EOl:k9=\EOw:k;=\EOx:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:kr=\EOC:ks=\E
[?1h\E=:ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:me=\E[m\017:mr=\E[7m:nd=\E[C:is=\E<\E)0:r2=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rc=\E8:sc=\E7:se=\E[m:sf=^J:so=\E[1;7m:sr=\EM:st=\EH:ta=^I:ue=\E[m:up=\E[A:us=\E[4m:
ENV after: TERM=vt100-am
ENV after: HOSTTYPE=i386
ENV after: PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/opt/schily/bin:/usr/bin/X11:/sbin/:/usr/TeX/bin:/usr/openwin/bin:/opt/intel/compiler50/ia32/bin:/usr/games:.:/usr/local/Office50/bin:/usr/java/bin:/home/users/root/tools:/home/users/root/tools
ENV after: PRINTER=mcd
ENV after: HOME=/root
ENV after: PS_SYSTEM_MAP=/System.map
ENV after: SHELL=/bin/bash
ENV after: LINES=25
ENV after: PS1=#
ENV after: PS2=>
ENV after: MANPATH=/usr/man:/usr/X11/man:/usr/openwin/man:/opt/schily/man
ENV after: LESS=-MM
ENV after: COLUMNS=80
ENV after: LIB=/usr/X11R6/lib:/usr/X11/lib:/usr/X11/lib
ENV after: GNUHELP=/usr/local/lib/gnuplot/gnuplot.gih
ENV after: JAVA_HOME=/usr/java
ENV after: DISPLAY=:0
ENV after: LANG=en_US.88591
ENV after: OSTYPE=Linux
ENV after: OPENWINHOME=/usr/openwin
ENV after: SHLVL=2
ENV after: EDITOR=/bin/vi
ENV after: LS_COLORS=no=00:fi=40;32:di=01;34:ln=01;36:pi=40;33:so=01;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=01;33:*.cmd=01;32:*.o=40;32:*.c=01;26:*.S=01;26:*.h=01;32:*.exe=01;32:*.com=01;32:*.btm=01;32:*.bat=01;32:*.tar=01;31:*.tgz=01
;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.jpg=01;35:*.gif=01;35:*.bmp=01;35:*.xbm=01;35:*.xpm=01;35:
ENV after: TZ=US/Eastern
ENV after: _=./xxx
# exit
Script done on Tue Jan 14 15:45:48 2003
My Sun.......
Script started on Tue Jan 14 15:47:18 2003
# uname -a
SunOS hal 5.5.1 Generic sun4m sparc SUNW,SPARCstation-5
# ./xxx
ENV before: HOME=/
ENV before: HZ=100
ENV before: LD_LIBRARY_PATH=/usr/ucblib:/usr/lib:/usr/local/lib:/usr/local/lib/gcc-lib:/lib
ENV before: LOGNAME=root
ENV before: MAIL=/var/mail/root
ENV before: PATH=/usr/bin:/usr/local/bin:/usr/sbin:/usr/ccs/bin:/usr/openwin/bin:/sbin/:.
ENV before: SHELL=/sbin/sh
ENV before: TERM=vt100-am
ENV before: TZ=US/Eastern
ENV after: ng-do-you-want-this-string-to-be?--is-this-long-enough?
ENV after: ou-want-this-string-to-be?--is-this-long-enough?
ENV after: -this-string-to-be?--is-this-long-enough?
ENV after: LOGNAME=root
ENV after: MAIL=/var/mail/root
ENV after: PATH=/usr/bin:/usr/local/bin:/usr/sbin:/usr/ccs/bin:/usr/openwin/bin:/sbin/:.
ENV after: SHELL=/sbin/sh
ENV after: TERM=vt100-am
ENV after: TZ=US/Eastern
^C# exit
script done on Tue Jan 14 15:47:34 2003
My red-hat 7.0 machine shows the environment overwrite also.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
Why is the government concerned about the lunatic fringe? Think about it.
On Tue, Jan 14, 2003 at 03:28:23PM -0500, Richard B. Johnson wrote:
> On Tue, 14 Jan 2003, Mark Mielke wrote:
> > On Tue, Jan 14, 2003 at 02:56:35PM -0500, Richard B. Johnson wrote:
> > > Well I just grepped through usr/include/bits/posix1_lim.h and it
> > > shows 255 (with this 'C' library) so you are probably right.
> > > In any event, a "whole line of text" isn't going to overrun it.
> > Looking at the code, it looks to me as if argv[0] can be any size up to
> > _SC_ARG_MAX, with the restraining factor being that the environment
> > variables and the other arguments must fit in the same space.
> > Is this not correct?
> Don't think so. In my headers _SC_ARG_MAX is an enumerated type
> that is numerically equal to 0. It's in confname.h, the first
> element in the enumerated list.
_SC_ARG_MAX is one of the identifiers that are used with sysconf() to
lookup a system-wide configuration value:
$ perl -MPOSIX -e 'print sysconf(_SC_ARG_MAX), "\n"'
131072
The environment size for a program invoked using exec() can be up to
131072 bytes long (my configuration). This environment holds the
command arguments as well as the environment.
On my system, _SC_ARG_MAX is telling me that it is possible to have
argv[0] be just under 131072 bytes long.
mark
--
[email protected]/[email protected]/[email protected] __________________________
. . _ ._ . . .__ . . ._. .__ . . . .__ | Neighbourhood Coder
|\/| |_| |_| |/ |_ |\/| | |_ | |/ |_ |
| | | | | \ | \ |__ . | | .|. |__ |__ | \ |__ | Ottawa, Ontario, Canada
One ring to rule them all, one ring to find them, one ring to bring them all
and in the darkness bind them...
http://mark.mielke.cc/
In article <[email protected]>,
Richard B. Johnson <[email protected]> wrote:
>On Tue, 14 Jan 2003, DervishD wrote:
>
>> I'm not sure whether this issue belongs to the kernel or to the
>> libc, but I think that is more on the kernel side, that's why I ask
>> here.
>
>Last time I checked argv[0] was 512 bytes. Many daemons overwrite
>it with no problem.
No cigar. This stuff is all set up by the kernel on the stack;
in order you have
Top of stack at 0xbfffffff
environ[0]\0environ[1]\0\0 From high ..
argv[0]\0argv[1]\0\0
*environ[];
*argv[]; .. to low.
The kernel only reserves space as needed. If you have an empty
environment, and you copy 512 bytes over argv[0], you'll end
up with a SEGV.
If you want to modify argv[0] etc, loop over argv[], count howmuch
space there is (strlen(argv[0] + 1 + strlen(argv[1] + 1 ... etc)
and make sure you do NOT write a string longer than that. Also
make sure that you end the string with a double \0
Mike.
--
They all laughed when I said I wanted to build a joke-telling machine.
Well, I showed them! Nobody's laughing *now*! -- [email protected]
On Tue, 14 Jan 2003 21:55:02 GMT, Miquel van Smoorenburg <[email protected]> said:
> If you want to modify argv[0] etc, loop over argv[], count howmuch
> space there is (strlen(argv[0] + 1 + strlen(argv[1] + 1 ... etc)
> and make sure you do NOT write a string longer than that. Also
> make sure that you end the string with a double \0
Or steal the code that's already been done - sendmail and wu-ftpd both have
code to do this....
--
Valdis Kletnieks
Computer Systems Senior Engineer
Virginia Tech
Hi Philippe :)
> You just overwrote all your arguments (argv[0] and others) and part of
> the environment.
Oh, sh*t, you're true, and that is the problem I was afraid to
suffer from. Then, all I can do is overwrite argv[0] with a new
string whose length is less or equal than the existing one.
Well, I suppose I must go with that limitation.
Thanks, Philippe, for the code snipped and the explanation.
Ra?l
Hi Mark :)
> > In any event, a "whole line of text" isn't going to overrun it.
> Looking at the code, it looks to me as if argv[0] can be any size up to
> _SC_ARG_MAX, with the restraining factor being that the environment
> variables and the other arguments must fit in the same space.
> Is this not correct?
This is correct, but it is a maximum, not a minimum.
Ra?l
>>>>> "Richard" == Richard B Johnson <[email protected]> writes:
Richard> On Tue, 14 Jan 2003, DervishD wrote:
>> Hi Richard :)
>>
>>>> Any header where I can see the length for argv[0] or is this SOME
>>>> kind of unoficial standard? Just doing strcpy seems dangerous to
>>>> me (you can read 'paranoid'...).
>> They need to have space for _POSIX_PATH_MAX (512 bytes), to claim POSIX
>> compatibility so any POSIX system will have at least 512 bytes
>> available because the pathname of the executable normally goes
>> there.
No, because argv[0] is followed immediately by a NUL then argv[1],
then argv[2], etc. They're not fixed length strings -- the kernel
allocates just enough for the actual arguments, rounded up to
PAGESIZE.
So if you copy more than strlen(argv[0]), you'll start overwriting
argv[1].
--
Dr Peter Chubb [email protected]
You are lost in a maze of BitKeeper repositories, all almost the same.
On Tue, Jan 14, 2003 at 11:04:01PM +0100, DervishD wrote:
> Hi Philippe :)
>
> > You just overwrote all your arguments (argv[0] and others) and part of
> > the environment.
>
> Oh, sh*t, you're true, and that is the problem I was afraid to
> suffer from. Then, all I can do is overwrite argv[0] with a new
> string whose length is less or equal than the existing one.
>
> Well, I suppose I must go with that limitation.
>
> Thanks, Philippe, for the code snipped and the explanation.
>
> Ra?l
> -
Or you can copy your all your args and env to a temporary place and
then re-build your args and env with the new argv[0] in it's place.
But you must be carefull that your new argv[0] length plus the
length of all remaining args, envp and pointers is not greater than
the system defined size for this space.
--
Bob Miller Email: [email protected]
Open Source Development Lab Phone: 503.626.2455 Ext. 17
On Tue, Jan 14, 2003 at 03:04:18PM -0800, Bob Miller wrote:
> On Tue, Jan 14, 2003 at 11:04:01PM +0100, DervishD wrote:
> > Hi Philippe :)
> >
> > > You just overwrote all your arguments (argv[0] and others) and part of
> > > the environment.
> >
> > Oh, sh*t, you're true, and that is the problem I was afraid to
> > suffer from. Then, all I can do is overwrite argv[0] with a new
> > string whose length is less or equal than the existing one.
> >
> > Well, I suppose I must go with that limitation.
> >
> > Thanks, Philippe, for the code snipped and the explanation.
> >
> > Ra?l
> > -
>
> Or you can copy your all your args and env to a temporary place and
> then re-build your args and env with the new argv[0] in it's place.
> But you must be carefull that your new argv[0] length plus the
> length of all remaining args, envp and pointers is not greater than
> the system defined size for this space.
>
In thinking about this more this will NOT work. The user stack starts
right after your envp. So, writing more info there would blow away
your stack.
--
Bob Miller Email: [email protected]
Open Source Development Lab Phone: 503.626.2455 Ext. 17
On Tue, Jan 14, 2003 at 03:11:41PM -0800, Bob Miller wrote:
> On Tue, Jan 14, 2003 at 03:04:18PM -0800, Bob Miller wrote:
> > Or you can copy your all your args and env to a temporary place and
> > then re-build your args and env with the new argv[0] in it's place.
> > But you must be carefull that your new argv[0] length plus the
> > length of all remaining args, envp and pointers is not greater than
> > the system defined size for this space.
> In thinking about this more this will NOT work. The user stack starts
> right after your envp. So, writing more info there would blow away
> your stack.
I can smell the next hack... memmove() the stack down to make room... :-)
mark
--
[email protected]/[email protected]/[email protected] __________________________
. . _ ._ . . .__ . . ._. .__ . . . .__ | Neighbourhood Coder
|\/| |_| |_| |/ |_ |\/| | |_ | |/ |_ |
| | | | | \ | \ |__ . | | .|. |__ |__ | \ |__ | Ottawa, Ontario, Canada
One ring to rule them all, one ring to find them, one ring to bring them all
and in the darkness bind them...
http://mark.mielke.cc/
On Tue, Jan 14, 2003 at 11:46:44PM -0500, Mark Mielke wrote:
> On Tue, Jan 14, 2003 at 03:11:41PM -0800, Bob Miller wrote:
> > On Tue, Jan 14, 2003 at 03:04:18PM -0800, Bob Miller wrote:
> > > Or you can copy your all your args and env to a temporary place and
> > > then re-build your args and env with the new argv[0] in it's place.
> > > But you must be carefull that your new argv[0] length plus the
> > > length of all remaining args, envp and pointers is not greater than
> > > the system defined size for this space.
> > In thinking about this more this will NOT work. The user stack starts
> > right after your envp. So, writing more info there would blow away
> > your stack.
>
> I can smell the next hack... memmove() the stack down to make room... :-)
No need. You can memcpy the environment. See setenv(3),
putenv(3) and related library routines.
Once you've parsed your argv who cares if you overwrite it,
put a double NULL at the end, set argc = 1 and argv[1] =
NULL. If argv[argc] - argv[0] + strlen(argv[argc] is
shorter than what you overwrite it with you won't even need
to relocate the environment block if you wish to preserve
that. Just don't leave any loose ends to confuse /proc and
the ps utils.
--
________________________________________________________________
J.W. Schultz Pegasystems Technologies
email address: [email protected]
Remember Cernan and Schmitt
Hi JW :)
> > > right after your envp. So, writing more info there would blow away
> > > your stack.
> > I can smell the next hack... memmove() the stack down to make room... :-)
> No need. You can memcpy the environment. See setenv(3),
> putenv(3) and related library routines.
I'm afraid that the best solution, well, the one which involves
less code and less problems (no need to relocate the environment or
things like that) is to write to argv[0] a shorter string that the
existing one, and overwrite with nulls the rest of arguments, just in
case the stack layout is not what expected.
Really, I'm thinking seriously about not rewritting argv[0] at
all. The problem is that may confuse the user when issuing 'ps' or
looking at /proc :((
Ra?l
Hi Bob :)
> Or you can copy your all your args and env to a temporary place and
> then re-build your args and env with the new argv[0] in it's place.
Yes, this is a good solution, too. The problem with all solutions
is that they involve a good bunch of code for a thing that doesn't
deserve it ;))
Moreover, since I must preserve the environment and I'm pretty
sure that there is no arg except argv[0], I end up with the same
problem. The user may install this bit of crap under name '/i', for
example, and then I have only two characters for the new name :((
Thanks for your help :)
Ra?l
Hi Miquel :))
> >Last time I checked argv[0] was 512 bytes. Many daemons overwrite
> >it with no problem.
> No cigar. This stuff is all set up by the kernel on the stack;
Thanks a lot for your help :)) FYI, this question is related to
the virtual-console-only init clone that I wrote some time ago (I
used sysvinit for inspiration and good advice), I think I wrote you
about this. Anyway, you are in the acknowledgement list doubly, now
;))) I'm going to release this init in a week or so, after having
using it for more than a year at home without problems.
> If you want to modify argv[0] etc, loop over argv[], count howmuch
> space there is (strlen(argv[0] + 1 + strlen(argv[1] + 1 ... etc)
> and make sure you do NOT write a string longer than that. Also
> make sure that you end the string with a double \0
How about portability? Not that worries me, since this code will
go to a Linux-only program, just curiosity. Other OSes do the same
stack layout?
Ra?l
On Wed, Jan 15, 2003 at 12:41:30PM +0100, DervishD wrote:
> Hi JW :)
>
> > > > right after your envp. So, writing more info there would blow away
> > > > your stack.
> > > I can smell the next hack... memmove() the stack down to make room... :-)
> > No need. You can memcpy the environment. See setenv(3),
> > putenv(3) and related library routines.
>
> I'm afraid that the best solution, well, the one which involves
> less code and less problems (no need to relocate the environment or
> things like that) is to write to argv[0] a shorter string that the
> existing one, and overwrite with nulls the rest of arguments, just in
> case the stack layout is not what expected.
>
> Really, I'm thinking seriously about not rewritting argv[0] at
> all. The problem is that may confuse the user when issuing 'ps' or
> looking at /proc :((
What about
int main(int argc, char **argv) {
if (argc != 2 || (argv == 2 && !strcmp(argv[1], "--very-magic"))) {
char argv0[512];
memcpy(argv0, 'a', 511);
argv0[511] = 0;
char *const args[] = { argv0, "--very-magic", 0 };
execv(argv[0], args);
}
strcpy(argv[0], "my proggy");
/* your code here */
}
This should ensure that you have 511 bytes of argv[0] storage available,
if I read the previous posts correctly.
For the same effect without the --very-magic argument, you could simply
do an "if (argc != 2 || strlen(argv[0]) != 511)" instead.
Am I smoking crack, or could the above work?
--
................................................................
: [email protected] : And I see the elder races, :
:.........................: putrid forms of man :
: Jakob ?stergaard : See him rise and claim the earth, :
: OZ9ABN : his downfall is at hand. :
:.........................:............{Konkhra}...............:
On Tue, 14 Jan 2003, Mark Mielke wrote:
> On Tue, Jan 14, 2003 at 03:28:23PM -0500, Richard B. Johnson wrote:
> > On Tue, 14 Jan 2003, Mark Mielke wrote:
> > > On Tue, Jan 14, 2003 at 02:56:35PM -0500, Richard B. Johnson wrote:
> > > > Well I just grepped through usr/include/bits/posix1_lim.h and it
> > > > shows 255 (with this 'C' library) so you are probably right.
> > > > In any event, a "whole line of text" isn't going to overrun it.
> > > Looking at the code, it looks to me as if argv[0] can be any size up to
> > > _SC_ARG_MAX, with the restraining factor being that the environment
> > > variables and the other arguments must fit in the same space.
> > > Is this not correct?
> > Don't think so. In my headers _SC_ARG_MAX is an enumerated type
> > that is numerically equal to 0. It's in confname.h, the first
> > element in the enumerated list.
>
> _SC_ARG_MAX is one of the identifiers that are used with sysconf() to
> lookup a system-wide configuration value:
>
> $ perl -MPOSIX -e 'print sysconf(_SC_ARG_MAX), "\n"'
> 131072
>
> The environment size for a program invoked using exec() can be up to
> 131072 bytes long (my configuration). This environment holds the
> command arguments as well as the environment.
>
> On my system, _SC_ARG_MAX is telling me that it is possible to have
> argv[0] be just under 131072 bytes long.
>
> mark
>
The following program shows why it's not "safe" to do anything
with argv[0].
#include <stdio.h>
int main(int c, char *argv[], char *env[])
{
int i;
i = 0;
printf("Stack is at %p\n", &i);
while(argv[i])
{
printf("Pointer at %p = %s\n", argv[i], argv[i]);
i++;
}
i = 0;
while(env[i])
{
printf("Pointer at %p = %s\n", env[i], env[i]);
i++;
}
return 0;
}
Everything is lined-up, sitting on the stack, and all variable-
length.
I looked at sendmail and it just does:
strcpy(argv[0] ,"sendmail:accepting connections");
But sendmail doesn't use the environment so if it gets trashed
it doesn't make any difference. It looks as though, if the
environment was small, i.e., only "TERM=vt100", sendmail might
have problems if main() ever returns to _start. The stack
will be trashed. But, most 'C' code doesn't do "return N;" from
main, certainly not a daemon, most call exit().
Anyway, overwriting argv[0] is done, but it's not "safe".
Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
Why is the government concerned about the lunatic fringe? Think about it.
Hi Jakob :)
> > Really, I'm thinking seriously about not rewritting argv[0] at
> > all. The problem is that may confuse the user when issuing 'ps' or
> > looking at /proc :((
> What about
[...]
Mmm, interesting idea. A simpler solution is just copy the needed
argv0. In your example, about 500 bytes are wasted ;))) By using the
needed size at argv0, we have the space needed.
If execv doesn't do any magic with the supplied argv array, then
this should work.
> For the same effect without the --very-magic argument, you could simply
> do an "if (argc != 2 || strlen(argv[0]) != 511)" instead.
No, because the len of argv[0] being 'my proggy' is 9, that is not
511 ;)) We cannot tell the allocated space, I'm afraid O:)
> Am I smoking crack, or could the above work?
I should smoke crack, definitely. That way I would not mess with
that argv thing XDDDD
Thanks :)
Ra?l
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>
extern char **environ;
size_t init_settitle(char *argv[], char *env[])
{
size_t i, len;
char *limit;
char *var;
i = 0;
while(env[i] != NULL)
{
len = strlen(env[i]) + 1; /* Room for the '\0' */
var = (char *) malloc(len);
memcpy(var, env[i], len); /* Copy the '\0' also */
limit = env[i]; /* Start of last string */
env[i++] = var; /* New environment ptr */
}
while(*limit) /* End of last string */
limit++;
return (limit - argv[0]); /* Space we can use */
}
int main(int c, char *argv[], char *env[])
{
size_t len, i;
len = init_settitle(argv, env);
i = 0;
while(environ[i] != NULL)
puts(environ[i++]);
printf("Length allowed = %u\n", len);
fflush(stdout);
strncpy(argv[0], "Antidesestablishmentarianism", len);
i = 0;
while(environ[i] != NULL)
puts(environ[i++]);
fflush(stdout);
pause();
return 0;
}
On Wed, Jan 15, 2003 at 05:22:19PM +0100, DervishD wrote:
> Hi Jakob :)
>
> > > Really, I'm thinking seriously about not rewritting argv[0] at
> > > all. The problem is that may confuse the user when issuing 'ps' or
> > > looking at /proc :((
> > What about
> [...]
>
> Mmm, interesting idea. A simpler solution is just copy the needed
> argv0. In your example, about 500 bytes are wasted ;))) By using the
> needed size at argv0, we have the space needed.
The point of the program is to exec() it once again, but with a larger
argv[0].
So what happens is that if the program is not called with --very-magic,
then it will call itself, with the following changes:
1) argv[0] is 512 bytes long (511 bytes usable)
2) --very-magic is supplied
Change 512 to whatever the limit you need is. But the program should
(well that was the idea at least) never reach later parts of main()
unless it has a 512 (or whatever) byte argv[0].
>
> If execv doesn't do any magic with the supplied argv array, then
> this should work.
Yep, that's what I though. Can anyone shoot this down? ;)
>
> > For the same effect without the --very-magic argument, you could simply
> > do an "if (argc != 2 || strlen(argv[0]) != 511)" instead.
>
> No, because the len of argv[0] being 'my proggy' is 9, that is not
> 511 ;)) We cannot tell the allocated space, I'm afraid O:)
Ok, I commented it to try to explain what it was I really meant to
say... ;)
int main(int argc, char **argv)
{
/* Check the length of argv[0] - we wat to make sure that 512 bytes are
* allocated */
if (strlen(argv[0]) != 511) {
/* argv[0] is shorter than 511 non-zero bytes, so we can't be sure
* it's really allocated big enough. Now build an argv[0] buffer the
* size we want it to be */
char argv0[512];
memcpy(argv0, 'a', 511);
argv0[511] = 0;
char *const args[] = { argv0, 0 };
/* Exec ourselves, with the new argv[0] supplied - this means, we
* will actually just re-execute ourselves, but our new "self" will
* have a bigger argv[0] - since it's filled with 511 'a' characters,
* our initial if() statement will evaluate to false and we will
* not enter this block again */
execv(argv[0], args);
/* never to return... Let's play it safe and make sure nothing bad
* happens */
perror("You're fscked... execv says"); abort();
}
/* Cool - argv[0] was big - let's put a meaningful name in there */
strcpy(argv[0], "my proggy");
/* your code here - argv[0] is now 512 bytes long - putting the short
* string into it just above, doesn't change the allocation of course */
}
Can anyone point out a problem in the above? I'd be happy to see it shot
down, mainly because it's ugly - and I hate programs that mess with
argv[0].
--
................................................................
: [email protected] : And I see the elder races, :
:.........................: putrid forms of man :
: Jakob ?stergaard : See him rise and claim the earth, :
: OZ9ABN : his downfall is at hand. :
:.........................:............{Konkhra}...............:
Hi Richard :)
> Well, I just can't give this up!
It's an interesting issue ;)))
> If you don't like me pretending that main() gets the environment
> after args[], you can access environ directly anyway with the
> same result. Have fun!
Anyway, I'm not sure that all argv members are contiguous. I
mean, you can have argv[0] at 0x0c123456, length 3, and argv[1] not
at 0x0c123459, but at 0xdeadbeaf. I know, this is VERY improbable,
but argv is just an array of strings :((
Anyway this code is brilliant ;)) Nice solution :)
Ra?l
Hi Jakob :)
> > If execv doesn't do any magic with the supplied argv array, then
> > this should work.
> Yep, that's what I though. Can anyone shoot this down? ;)
Not me ;)) The only problem would arise if the argv[0] passed to
exec is 511 bytes long but its strlen is low, because exec can choose
to copy the array to a new location (in fact, I think it does it...).
If you provide a filled argv[0], and soon after the exec you
change it to a proper value, there is only a brief chunk of time
where argv[0] will have long and strange contents. It doesn't matter,
because you can use spaces and anyway this is not important.
[Code snippet... snipped]
> Can anyone point out a problem in the above? I'd be happy to see it shot
> down, mainly because it's ugly - and I hate programs that mess with
> argv[0].
I like your code ;))) I don't think it's ugly, on the contrary, I
find it quite elegant ;)) And I hate programs that mess with argv[0],
too. In fact, I'm against that, but I need it... You deserve an
explanation: it's a virtual console only init clone, and has a
builtin getty and login, and a builtin syslogd+klogd, too, all in
less than 17k... Well, due to the 'builtin nature' of this program,
we don't want ps show '/sbin/init' or just 'init' for the klogd
process, for example, or in the login process. We want 'ps' to show
'login' for the login process or 'klogd' for the klog builtin
emulator. That's all.
By now I just assumed that at least I had four spare characters,
but this is not true anymore when testing, since I provided init=/i
to lilo, for example. And anybody can use that parameter and screw my
init totally, just for the sake of the proc string issue :((
Your exec solution seems to be the easiest and cleanest one, and
should work, IMHO... I'm going to test right now ;))
Thanks for your help.
Ra?l
Hi Jakob :)
Your solution of exec'ing ourselves MUST undoubtly work (well, I
know that this an affirmation that I will lament XDDDD), because it
only relies on 'exec()' passing the argv[0] you provide as the
argv[0] of the invoked binary, and that should work or programs like
'/bin/login' will stop working... They rely on the same principle,
since they need to prepend an '-' to the shell name to make it a
login shell :))) Didn't remember this until now!
So, if you do 'execl(ourselves, "my new name", ..., NULL)', the
argv[0] received by the binary specified in 'ourselves' MUST be 'my
new name'. Otherwise '/bin/login' and a good bunch of shells won't
work...
If you happen to come to Spain at any point in the future, just
tell me, I'll buy you a beer (or crack, or whatever you use XDDD).
Thanks :)
Ra?l
Jakob Oestergaard <[email protected]> writes:
|> Can anyone point out a problem in the above? I'd be happy to see it shot
|> down, mainly because it's ugly - and I hate programs that mess with
|> argv[0].
argv[0] is not required to point to the actual file name of the
executable, and in fact, most of the time it won't.
Btw, don't use it for setuid programs, it's a huge security hole you can
drive a truck through.
Andreas.
--
Andreas Schwab, SuSE Labs, [email protected]
SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 N?rnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
On Wednesday 15 January 2003 03:26 pm, Andreas Schwab wrote:
> Jakob Oestergaard <[email protected]> writes:
> |> Can anyone point out a problem in the above? I'd be happy to see it shot
> |> down, mainly because it's ugly - and I hate programs that mess with
> |> argv[0].
>
> argv[0] is not required to point to the actual file name of the
> executable, and in fact, most of the time it won't.
And don't count on it for portability - Some systems take a copy of arg0 for
the process tables, and changing it will NOT alter the process name. It is
only the default action for shell programs. All others can make arg0 anything
they want - as login effectively does ..
execl ("pathtoshell", "-", 0)
--
-------------------------------------------------------------------------
Jesse I Pollard, II
Email: [email protected]
Any opinions expressed are solely my own.
Hi Andreas :)
> |> down, mainly because it's ugly - and I hate programs that mess with
> |> argv[0].
> argv[0] is not required to point to the actual file name of the
> executable, and in fact, most of the time it won't.
> Btw, don't use it for setuid programs, it's a huge security hole you can
> drive a truck through.
Yes, I suppose that exec'ing whatever is in argv0 is not a good
idea :((( Didn't think about it.
Any suggestion on how to get the binary name from the core image?
Thanks a lot for the warning, Andreas :)
Ra?l
On Thursday 16 January 2003 00:03, DervishD wrote:
> Yes, I suppose that exec'ing whatever is in argv0 is not a good
> idea :((( Didn't think about it.
> Any suggestion on how to get the binary name from the core image?
Does it have to be an exec?
Perhaps something like this:
int main(int argc, char **argv)
{
if (fork ()) {
strcpy (argv[0], "Fake name 00001");
setpgrp (); /* very important when dealing with stuff like this */
pause(); /* code for personality "Fake name 00001" */
return 0;
}
strcpy (argv[0], "Fake name 00002");
setpgrp ();
pause(); /* code for personality "Fake name 00002" */
}
this thing works - at least on my box...
But, of course, I could be mistaken, and I miss to see some other
important details. Good luck.
Dorin.
--
Dorin "sp00ky" Lazar, programmer
Registered Linux user #162515
> Any suggestion on how to get the binary name from the core image?
How about:
exec("/proc/self/exe", ...)
I found something like this handy when writing an self extracting compressed
executable a while ago.
Jon
Hi Jon :)
> exec("/proc/self/exe", ...)
That's good, but I would like to avoid to mount procfs: what if
the mount point '/proc' doesn't exist? If you create it, you must
mount root rw and remount ro again, not a very good idea if it
haven't been fscked yet, for example. You can mount under /tmp, if it
exists at all, but that simply displaces the problem. What if
/proc/self/exe is not part form procfs, but from some evil user ;))
Thanks a lot for your answer :)
Ra?l
Ra?l wrote:
> That's good, but I would like to avoid to mount procfs:
> what if the mount point '/proc' doesn't exist?
> If you create it, you must mount root rw and remount ro
> again,
Surely that is an admin problem to make sure that /mount
exists on the root fs. When your messing with something as
fundamental as init you should be able to insist on this.
It is easy to do a mount() system call, the rootfs can be ro.
> What if /proc/self/exe is not part form procfs,
> but from some evil user ;))
Would the user not need root privilegdes to mess with /proc?
Is there any good reason why init should not be executable
by root only?
Jon
Hi Jon :)
> It is easy to do a mount() system call, the rootfs can be ro.
Yes, but you still need a mountpoint. Lot of worries for
something as trivial and useless as changing the ps identity ;))
> > What if /proc/self/exe is not part form procfs,
> > but from some evil user ;))
> Would the user not need root privilegdes to mess with /proc?
/proc/self/exe doesn't need to be in procfs... If proc is not
mounted... Anyway it was just an example. The degree of evil-user
intrusion in a machine for doing something like that is quite high.
There are simpler ways of attacking a machine if you can forge
/proc/self/exe :))
> Is there any good reason why init should not be executable
> by root only?
My init refuses to run if not called by the superuser ;) because
I think the same as you and anyway my init doesn't need a shutdown
command, it works with a keycombo that root controls.
Ra?l
Hi Tethys :)
> > See the previous messages. I want to avoid mounting /proc.
> Yes, I'd read them, but obviously missed the need to avoid /proc.
Let's say that there is no need to avoid /proc, but things like
those must be the last resort, because the problems they introduce
are bigger than the problem they help to solve :)
> I assume the idea behind this is for some very low memory embedded
> device. Sounds interesting (and actually, one of the few legitimate
> reasons I've seen for wanting to override argv[0]!).
Yes, vcinit was designed for a reduced embedded device. And it
was very interesting (well, at first...) but now the work rests in
the heaven of abandonware ;)))
> Without /proc, I can't think of any easy way of doing it, short of
> wading through /dev/kmem :-)
Ouch! ;)))
Ra?l
On Tue, 14 Jan 2003, DervishD wrote:
> > > libc, but I think that is more on the kernel side, that's why I ask
> > Last time I checked argv[0] was 512 bytes. Many daemons overwrite
> > it with no problem.
>
> Any header where I can see the length for argv[0] or is this some
> kind of unoficial standard? Just doing strcpy seems dangerous to me
> (you can read 'paranoid'...).
The method used in INN is to make arg 1 some space. So
nnrpd -s' ' -D ...
You can check that argv[1] is -s, and what its length is, then happily
write over argv[0]. That's portable in practical terms, since most C
implementations just have the variable length args in sequence, while a
few have a fixed length array for args. You're safe in either case.
Ex:
if (strncmp(argv[1], "-s", 2) && strlen(argv[1]) > REPLACELEN) {
sprintf(argv[0], "format", atuff...);
}
Some systems have setproctitle() but it doesn't appear to be posix.
--
bill davidsen <[email protected]>
CTO, TMR Associates, Inc
Doing interesting things with little computers since 1979.
> The method used in INN is to make arg 1 some space. So
Unfortunately, the process in this case is 'init', so we cannot
easily do this :((
> Some systems have setproctitle() but it doesn't appear to be posix.
Linux doesn't have setproctitle(), AFAIK, and seems to belong to
NetBSD :??? What a pity, because will be a very clean solution :7
Thanks a lot for answering :)
Ra?l
On Wed, 2003-01-15 at 00:59, DervishD wrote:
>
> I want to change the argv[0] a program shows, in order
> to be pretty-printed when issuing 'ps', 'top' or
> other commands.
Sorry about the late reply.
This is done nicely in PostgreSQL. Check source at early
initializing parts of the postmaster.
Anuradha
--
Debian GNU/Linux (kernel 2.4.20)
It may be better to be a live jackal than a dead lion, but it is better
still to be a live lion. And usually easier.
-- Lazarus Long