Seg fault while running C script as non root

F

forrest stanley

Hello all,
I am attempting to run this C script as a non root user. (its actually
run from a webpage). The code runs as expected as root. This is a
password changing script. I have removed some of the mail message sent
out, and a few other items. I have tried to set the bit file to make
this script have rrot powers as its run (chmod u+x), but this did not
help. Included is a slightly stripped version of the password changer.
I was hoping someone might be able to review the code, and point out
what could be causing a segmentation fault.


#include <iostream>
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
char npword[9];
char * username;
char * useremail;

username = argv[1];
useremail = argv[2];

//open a shell and generate password, read output
FILE* fnp = popen("/usr/bin/tr -dc 'A-z' < /dev/urandom | fold -7 |
head -1","r");
for (int i=0; i<8; i++) {
npword = fgetc(fnp);
}
pclose(fnp);
npword[8] = '\0';


//system call to set password file
FILE* fep = fopen("/tmp/newpw","w+");
fprintf(fep,"%s",npword);
fclose(fep);

//create email template
FILE* fne = fopen("/tmp/resetpassword","w+");
fprintf(fne,"
Login
%s
Password
%s
",username, npword);
fclose(fne);


//system call to send email
char mailpword[100];
char mailSubject[50] = "Your new password";
sprintf(mailpword,"mutt %s -s \"%s\" <
/tmp/resetpassword",useremail,mailSubject);
system(mailpword);

return 0;
}
 
J

Jack Klein

Hello all,
I am attempting to run this C script as a non root user. (its actually
run from a webpage). The code runs as expected as root. This is a
password changing script. I have removed some of the mail message sent
out, and a few other items. I have tried to set the bit file to make
this script have rrot powers as its run (chmod u+x), but this did not
help. Included is a slightly stripped version of the password changer.
I was hoping someone might be able to review the code, and point out
what could be causing a segmentation fault.

This is not a C language issue, C knows nothing at all about root,
chmod, or passwords. All of these things are features of your
operating system, not defined or supported by the C language.
#include <iostream>
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
char npword[9];
char * username;
char * useremail;

username = argv[1];
useremail = argv[2];

Regardless of system-specific extensions, this code can invoke
undefined behavior and probably crash if it is called with fewer than
two command line arguments.
//open a shell and generate password, read output
FILE* fnp = popen("/usr/bin/tr -dc 'A-z' < /dev/urandom | fold -7 |
head -1","r");

No such function as popen() in the standard C library.
for (int i=0; i<8; i++) {
npword = fgetc(fnp);
}
pclose(fnp);


Ditto for pclose().
npword[8] = '\0';


//system call to set password file
FILE* fep = fopen("/tmp/newpw","w+");
fprintf(fep,"%s",npword);

Another potential crash if the fopen() failed for any reason. Always
check the a NULL return from fopen().
fclose(fep);

//create email template
FILE* fne = fopen("/tmp/resetpassword","w+");
fprintf(fne,"
Login
%s
Password
%s
",username, npword);

Again, crash if fopen() fails.
fclose(fne);


//system call to send email
char mailpword[100];
char mailSubject[50] = "Your new password";
sprintf(mailpword,"mutt %s -s \"%s\" <
/tmp/resetpassword",useremail,mailSubject);
system(mailpword);

return 0;
}

Your problems with functions like popen() and root levels are not
language issues, and you need to discuss them in
or perhaps a group for your specific *NIX
flavor, line those in
But it is quite possible that your crash is the result of calling
fprintf() and fclose() on NULL file pointers. Perhaps your program
does not have access writes to create or write to those files, so the
fopen() is failing.

ALWAYS test the return of fopen() for NULL before using the FILE
pointer.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
 
M

Martin Ambuhl

(e-mail address removed) (forrest stanley) wrote (25 Jun 2003) in
/ comp.lang.c:
Hello all,
I am attempting to run this C script as a non root user.

Some red flags are raised immediately by this, and they are borne out by
the rest of your message. A question about your OS belongs in an
OS-specific newsgroup. And C is not a scripting language. But it gets
*much* worse:
#include <iostream>

<iostream> is not a C header. C++ questions belong in a newsgroup for
that language. comp.lang.c++ comes to mind. Of course, you will mend
your ways and check the FAQ and the back-traffic before posting there/
#include <stdlib. (its actually
h>

This garbage is, of course, not part of any computer language.
In C, this would be #include <stdlib.h>
In C++, it would be #include <cstdlib>
In neither language do you just stick comments without delimiters into
code.
#include <stdio.h>

Before posting your question to comp.lang.c++, learn that the C++ header
FILE* fnp = popen("/usr/bin/tr -dc 'A-z' < /dev/urandom | fold -7 |
head -1","r");

popen() is not part of either C or C++. This again means that you need
to go to a platform- or implementation-specific newsgroup where these
additional functions are supported.
pclose(fnp);

which is of course true for pclose() as well.
fprintf(fne,"
Login
%s
Password
%s
",username, npword);

This breaking of a literal string across lines should have triggered
some diagnostics. If it didn't, you probably need to crank up your
diagnostics. I suppose you mean
fprintf(fne,"\n"
"Login\n"
"%s\n"
"Password\n"
"%s\n", username, npword);
 
G

Gordon Burditt

I am attempting to run this C script as a non root user. (its actually

What on Earth is a "C script"?
run from a webpage). The code runs as expected as root. This is a

If something is expected to run as root, then it would be a REALLY
good idea to check whether your calls to fopen() fail before
attempting to use the result. Don't be too surprised if fopen()
fails when running with insufficient privileges.
password changing script. I have removed some of the mail message sent
out, and a few other items. I have tried to set the bit file to make
this script have rrot powers as its run (chmod u+x), but this did not
help. Included is a slightly stripped version of the password changer.
I was hoping someone might be able to review the code, and point out
what could be causing a segmentation fault.

Passing a NULL FILE * parameter to functions like fprintf() because
you didn't check whether fopen() failed is one way you might get a
smegmentation fault.

#include <iostream>
^^^^^^^^^^
This sure doesn't look like C to me.
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
char npword[9];
char * username;
char * useremail;

username = argv[1];
useremail = argv[2];

//open a shell and generate password, read output
FILE* fnp = popen("/usr/bin/tr -dc 'A-z' < /dev/urandom | fold -7 |
head -1","r");
for (int i=0; i<8; i++) {
npword = fgetc(fnp);
}
pclose(fnp);
npword[8] = '\0';


//system call to set password file
FILE* fep = fopen("/tmp/newpw","w+");
fprintf(fep,"%s",npword);
fclose(fep);

//create email template
FILE* fne = fopen("/tmp/resetpassword","w+");
fprintf(fne,"
Login
%s
Password
%s
",username, npword);
fclose(fne);


//system call to send email
char mailpword[100];
char mailSubject[50] = "Your new password";
sprintf(mailpword,"mutt %s -s \"%s\" <
/tmp/resetpassword",useremail,mailSubject);
system(mailpword);


What does the above do when someone tries to change the password
for the username:
x"`rm -rf /`"x
(The quotes are part of the username). Hint: the results will
not be pretty. Maybe you shouldn't be running programs that
are setuid-root invoked from web servers without CAREFULLY
checking your input?
return 0;
}

Gordon L. Burditt
 
M

Micah Cowan

Hello all,
I am attempting to run this C script as a non root user. (its actually
run from a webpage). The code runs as expected as root. This is a
password changing script. I have removed some of the mail message sent
out, and a few other items. I have tried to set the bit file to make
this script have rrot powers as its run (chmod u+x), but this did not
help. Included is a slightly stripped version of the password changer.
I was hoping someone might be able to review the code, and point out
what could be causing a segmentation fault.


#include <iostream>

The above is not a standard C header, and therefore off-topic here.

It *is* a standard C++ header, but as you do not seem to be writing
standard C++ (no std namespace), you should probably just remove it.
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
char npword[9];
char * username;
char * useremail;

username = argv[1];
useremail = argv[2];

//open a shell and generate password, read output
FILE* fnp = popen("/usr/bin/tr -dc 'A-z' < /dev/urandom | fold -7 |
head -1","r");

The above function is not defined by either you or the C standard. If
you want the POSIX version (off-topic here), you should stick

#define _POSIX_C_SOURCE 199506L

or similar before #including any headers--for maximum
standards-compliance and portability.

And then you should take this thread to .

Also, since you never check the return value of popen(), or any of
your fopen() calls, you don't know if you're getting NULL, in which
case a segfault is likely.

Also, you don't check to see if argv[1] and argv[2] exist, so you'd
better damn well hope they do :)
for (int i=0; i<8; i++) {

OK: since you are declaring i here, you are either writing
non-standard C++, or you are writing in C99. If the former, you are
off-topic here.
npword = fgetc(fnp);
}
pclose(fnp);
npword[8] = '\0';


//system call to set password file
FILE* fep = fopen("/tmp/newpw","w+");
fprintf(fep,"%s",npword);
fclose(fep);

//create email template
FILE* fne = fopen("/tmp/resetpassword","w+");
fprintf(fne,"
Login
%s
Password
%s
",username, npword);
fclose(fne);


//system call to send email
char mailpword[100];
char mailSubject[50] = "Your new password";
sprintf(mailpword,"mutt %s -s \"%s\" <
/tmp/resetpassword",useremail,mailSubject);


It would be quite easy to overflow mailpword[] here, also causing a
segfault (if you're *lucky*...)
system(mailpword);

return 0;
}

-Micah
 
V

Vijay B

Well Micah,

From my experience in C segfaults occur when you
1) Do not malloc for a pointer(In this case space has already been
allocated by the declaration of an array)
2) The file you are opening does not exist.
Generally good coding standards will be to check if fp is
null...So if we have a file names foo.data then the code would look
like this

File *fp = fopen("foo.data","r");
if(fp==NULL) {
printf("Error message");
return;
}
/* Code to do the manipulation of the file starts here */
3) Another place where your code could be buggy is when you try to
access the command line args. Once again u should ensure that the 2
arguments are present (keep in mind the args vector starts from 0) .
No assumptions should ever be made abt the number of inputs a user can
give. This will coz the code to crash at times.

Check and see if my above suggestions work. I have a lot of
experience with segfaults :). The best way to tackle this problem if
the above solutions dont work is to either use GDB or to use a lot of
printf statements to trap the exact line of code which causes the code
to segfault.

Hope this helps

Vijay


Micah Cowan said:
Hello all,
I am attempting to run this C script as a non root user. (its actually
run from a webpage). The code runs as expected as root. This is a
password changing script. I have removed some of the mail message sent
out, and a few other items. I have tried to set the bit file to make
this script have rrot powers as its run (chmod u+x), but this did not
help. Included is a slightly stripped version of the password changer.
I was hoping someone might be able to review the code, and point out
what could be causing a segmentation fault.


#include <iostream>

The above is not a standard C header, and therefore off-topic here.

It *is* a standard C++ header, but as you do not seem to be writing
standard C++ (no std namespace), you should probably just remove it.
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
char npword[9];
char * username;
char * useremail;

username = argv[1];
useremail = argv[2];

//open a shell and generate password, read output
FILE* fnp = popen("/usr/bin/tr -dc 'A-z' < /dev/urandom | fold -7 |
head -1","r");

The above function is not defined by either you or the C standard. If
you want the POSIX version (off-topic here), you should stick

#define _POSIX_C_SOURCE 199506L

or similar before #including any headers--for maximum
standards-compliance and portability.

And then you should take this thread to .

Also, since you never check the return value of popen(), or any of
your fopen() calls, you don't know if you're getting NULL, in which
case a segfault is likely.

Also, you don't check to see if argv[1] and argv[2] exist, so you'd
better damn well hope they do :)
for (int i=0; i<8; i++) {

OK: since you are declaring i here, you are either writing
non-standard C++, or you are writing in C99. If the former, you are
off-topic here.
npword = fgetc(fnp);
}
pclose(fnp);
npword[8] = '\0';


//system call to set password file
FILE* fep = fopen("/tmp/newpw","w+");
fprintf(fep,"%s",npword);
fclose(fep);

//create email template
FILE* fne = fopen("/tmp/resetpassword","w+");
fprintf(fne,"
Login
%s
Password
%s
",username, npword);
fclose(fne);


//system call to send email
char mailpword[100];
char mailSubject[50] = "Your new password";
sprintf(mailpword,"mutt %s -s \"%s\" <
/tmp/resetpassword",useremail,mailSubject);


It would be quite easy to overflow mailpword[] here, also causing a
segfault (if you're *lucky*...)
system(mailpword);

return 0;
}

-Micah
 
M

Mark McIntyre

Pay heed to the Sixth
Commandment, unbeliever!

"If a function be advertised to return an error code
in the event of difficulties, thou shalt check for
that code, yea, even though the checks triple the size
of thy code and produce aches in thy typing fingers,
for if thou thinkest ``it cannot happen to me'', the
gods shall surely punish thee for thy arrogance."

I seem to remember that quote ending " in the presence of thy most
valued Client"...

ah, not quite, but nearly...
 
M

Micah Cowan

Well Micah,

From my experience in C segfaults occur when you
1) Do not malloc for a pointer(In this case space has already been
allocated by the declaration of an array)
2) The file you are opening does not exist.
Generally good coding standards will be to check if fp is
null...So if we have a file names foo.data then the code would look
like this

File *fp = fopen("foo.data","r");
if(fp==NULL) {
printf("Error message");
return;
}
/* Code to do the manipulation of the file starts here */
3) Another place where your code could be buggy is when you try to
access the command line args. Once again u should ensure that the 2
arguments are present (keep in mind the args vector starts from 0) .
No assumptions should ever be made abt the number of inputs a user can
give. This will coz the code to crash at times.

Check and see if my above suggestions work. I have a lot of
experience with segfaults :). The best way to tackle this problem if
the above solutions dont work is to either use GDB or to use a lot of
printf statements to trap the exact line of code which causes the code
to segfault.

Er, thanks Vijay, but I didn't write the problematic code you are
referring to; and in the message you responded to, I made exactly the
same recommendations you are making here.

Except that I didn't top-post :)

-Micah
 
M

Micah Cowan

Ahh, how I love the newsgroup. Always expect a few flames from
friendly people with nothing to do at work (or at home, sorry, get
layed off?).

<grin> -- you really think those were *flames*? They seemed pretty
cordial to me, especially considering you obviously had failed to have
the common decency to read the FAQ, and you had posted code which
didn't look too terribly much like ISO C, the only legal topic for
this newsgroup (besides meta-topics such as topicality).
This code had no intentions of running as root, I was
just stating that it would fail on non-root access. Anyways, luckily
some of the people offered some constructive critisism, and I found my
error. This new code works as intended. Also, this code can only be
called by another script, and the other script performs any error
checking required before it goes through.

Well, as other people have pointed out, this assertion is completely
unbelievable, considering that you still don't check the return of
fopen().

But, even if you could 100% guarantee that fopen() will succeed every
time, this style of coding is desipicable to me. If at least for the
sake of pride in your own work, isn't it worth building it with the
least little bit of *quality*?
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
char npword[8];
char * username;
char * useremail;
char * userpass;

username = argv[1];
useremail = argv[2];
userpass = argv[3];

FILE* fnp = fopen("/foo/pw","w+");
for (int i1 = 0; i1 < 6; i1++)
fprintf(fnp,"%c",userpass[i1]);
fclose(fnp);

FILE* fgp = fopen("/foo/pw","r");
fgets(npword,8,fgp);
fclose(fgp);

FILE* fne = fopenfoo/rp","w+");
fprintf(fne,"\n"
"Login\n"
"%s\n"
"Password\n"
"%s\n"
,username, npword);
fclose(fne);

//system call to send email
char mailpword[100];
char mailSubject[50] = "Your new password";
sprintf(mailpword,"mutt %s -s \"%s\" <
/foo/rp",useremail,mailSubject);
system(mailpword);

return 0;
}
 
J

Joona I Palaste

<grin> -- you really think those were *flames*? They seemed pretty
cordial to me, especially considering you obviously had failed to have
the common decency to read the FAQ, and you had posted code which
didn't look too terribly much like ISO C, the only legal topic for
this newsgroup (besides meta-topics such as topicality).

No, *this* is a flame (albeit milder than what some people could come
up with):

http://groups.google.com/[email protected]&rnum=1

--
/-- Joona Palaste ([email protected]) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"How come even in my fantasies everyone is a jerk?"
- Daria Morgendorfer
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,227
Latest member
Daniella65

Latest Threads

Top