We help IT Professionals succeed at work.

su command

marvinm
marvinm asked
on
I have a daemon running as root a on Linux 2.4.7-2enterprise box.  A windows client connects via TCP-IP requesting the server to execute some specific command as a specific user.  The server writes out a batch file and then makes a system() call to execute the batch.  As output I get the following error:
tmp_batch file: line 1: 11479 Segmentation fault      su myuser -c "cd /usr2/mysourcedir/currentversion; mycommand myargs"
the batch that generated this error is:
su myuser -c "cd /usr2/mysourcedir/currentversion; mycommand myargs"

If I run the batch from the command line it works fine.  Also runs fine on an SCO box.

snippet from daemon...................
lfp = fopen(lfile3,"w");
fprintf(lfp,"su %s -c %s",my_user,my_command);
fclose(lfp);
sprintf(lbuf,"chmod 777 %s",lfile3); system(lbuf);
/**
 *  This bloxk is the key for interactivity
 */
{
int liFileToClose;
     
liFileToClose = fileno(stdout);
if (liFileToClose) close(liFileToClose);
dup2(theSocket,liFileToClose);
     
liFileToClose = fileno(stderr);
if (liFileToClose) close(liFileToClose);
dup2(theSocket,liFileToClose);
}
system(lfile3);
     
/**
 *  Clean up, remove the files
 */
sprintf(lbuf,"rm %s",lfile3);
system(lbuf);
shutdown(theSocket,2);
close(theSocket);

Thank YOu!
Comment
Watch Question

Commented:
who are you running as? a daemon can not su to a user unless u supply a passwork, SECURITY problem right there.  
whey don't  you just run the script?  
/something/username/ascript argument

you can chmod the script witha "+s" to give system permission to run

Author

Commented:
the script has to be run as a specific user.  The daemon is running as root.
thank you

Commented:
what I am saying is when you do system(ibuf) , you are still a daemon.  use getenv() function inside to gather information about who U are, id group  etc etc etc.  now it should work it you id is root, 0 but then again I could be wrong
CERTIFIED EXPERT

Commented:
could you please post the first line of your generated batch file.
if you are running as a daemon, you have no shell in the current context.  Your command would need to look like:

/bin/bash -c "su myuser -c /bin/bash --login -c 'cd /usr2/mysourcedir/currentversion; mycommand myargs'"
Also, you should take garboua's comment very seriously.  Doing this will create a huge security vulnerability on your machine.  I make no warranty as to the safety of this command.....

Author

Commented:
Sorry for the delay in getting back into this,
getenv("USER") returns NULL
the first and only line in the batch is:
su myuser -c "cd /usr2/mysourcedir/currentversion; mycommand myargs"
I will try BlackDiamond's suggestion
Thank You

Author

Commented:
Ok, it looks like BlackDiamond's suggestion almost gets me there, but it does not seem like the command is actually being run as the user that I specify, or that the profile is not begin loaded correctly.  $HOME = "root" instead of my specified user's home directory.
Thank You, mm
Ok, easy fix for that.  just add a - between su and the user name.  So the command becomes:

/bin/bash -c "su - myuser -c /bin/bash --login -c 'cd /usr2/mysourcedir/currentversion; mycommand myargs'"


You might not need the --login anymore when you do that, but I didn't test without it.
CERTIFIED EXPERT

Commented:
assuming that mycommand is found in /usr2/mysourcedir, following should also work:
   su myuser -c "cd /usr2/mysourcedir/currentversion; ./mycommand myargs"

But BlackDiamond's suggestion with su - myuser is more save (for example environment variables).
Commented:
Just a comment on the strategy:  It seems to be way more complicated than is needed for this simple problem.  The basic server program is written in C.  So I see no reason to involve a shell, much less two shells (Su runs one) to run 'mycommand'.  

You can just fork() to create a child process, setreuid() and setregid() to set the identity, and execl() to run mycommand.

With this simplicity, you get quicker execution with less resource consumption, less opportunity for something to go wrong, and less exposure to security holes.
CERTIFIED EXPERT

Commented:
> .. you get quicker execution with less resource consumption, less opportunity for something to go wrong ..

. if you know how to handle child processes, exit codes, signals, standard file descriptors (STDIN, STDOUT, STDERR).

Using system() is the quickest way to fork a subprocess, usually. And it's safe too, 'cause the libc does all necessary settings for you which must be done yourself when using fork().
Resources is the drawback for this comfort, but never was a big proble on UNIX ;-)

Commented:
The reason to be scared of system() in a case like this, where a superuser process is running a program on behalf of some nonsuperuser client, is that there are so many fancy things that shells do.  And with the complexity of having 3 extra processes (over and above the one that runs the ultimate 'mycommand' program -- two of them running shells), it can be easy to get misled as to what your program is capable of doing.  For example, if the user supplies what is supposed to be a priority number as an argument, but specifies ">/etc/passwd", and the daemon thinks it is passing that on to mycommand, it might actually be telling a shell to write junk into /etc/passwd, with superuser privilege.

Experience shows you cannot think of all these things.  Shells are complex things that were designed to be used interactively.  So many of us just try to keep our superuser daemons simple -- at least until the setreuid() to drop superuser privilege.

Author

Commented:
When the process is started at boot-up (in rc2.d directory) I still get the Segmentation fault.  If I log in as myself, su, and then start process... all is well.  I will look into fork()ing, but would like to keep current basic logic if possible.  Has worked flawlessly for 2yrs on SCO, but LINUX is barfing on it.  Thank you all for you continued input.

Author

Commented:
Getting in to experts exchange has been quite a chore lately!
Still having a problem if started at bootup, but OK if start manually (see above). I am going to try bryanh's suggestion, but how can I get the user/group id to pass to setreuid/setregid if I know the user/group name?
Thank You, mm

Explore More ContentExplore courses, solutions, and other research materials related to this topic.