Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to keep effective uid in awk 'system()' calls

Status
Not open for further replies.

dchoulette

Programmer
Jun 25, 2002
245
FR
Hello.

I run an awk script owned by root with suid bit on.

The effective uid of the process running the awk script is root as expected (I can access to file only readable by root), but within the awk 'system' function the effective uids are lost.

For example, in my script the command:
system("id");
show only uid and gid and no more 'euid' or 'egid'.

The only explaination I see is that awk fork a shell (usr/bin/sh) to execute the system command and that the shell reset effective uids to the real uids if launched without the flag -p (as explained in 'man sh').

I tried the following:
system("/usr/bin/sh -p -c 'id'");
without success.

Is there a way to execute system commands in awk without losing the effective uid ?

Thanks for your help.
 
suid shell scripts. hmm.
I mean that is basically what you are proposing
here right?

What platform and why don't you just su before you run
the script?
 
Hi,

I'm working on Solaris 8.
I can't use su because this awk script is intended to be used by users who do not know the root password.
I want this awk script to parse a file (the configuration file of a deamon), read user input, do some integrity checks on this user input, update the file and run a shell command (to restart the deamon).
The file must only by writable by root and should be updated only by means of this script.

I made my awk script executable and with the suid bit set
Code:
# chmod a+x,u+s myAwkScript

When I run it under a user account (say user somebody) the awk script has its effective uid set to root: it can access files only readable by root. So it can parse the file and update it.
The last action, however, is to restart the deamon and I have to use the awk system() function.

And within the awk system() the effective uid is reset to the real uid (somebody) it is not possible to restart the deamon, operation needing root privileges.

It is not vital, there are other solutions to my problem:

1) I can make a shell script with suid bit set that run the awk script then restart the deamon.
Pb: I'd prefer to keep all stuff in one file. This way it is easier not to forget something when you transfert the file from host to host.

2) Then, I can embed my awk script in my shell script using <<EOF
Pb: my awk script is pretty large (>1000 lines). (Yep, the format of the file to parse is not that simple). It will result in a large shell file with only 10 shell lines out of 1000. It seems more logical to make a large awk script with only 1 embedded shell line in a system() call.

3) I can rewrite all this stuff in perl.
Pb: Well ... I have to rewrite all this stuff in perl.

I'm just curious to see if someone has a solution or information about the awk system() call.

Thanks.
 
This is why I originally commented on suid shell scripts.
Chances are that a malicious user could break this to
his/her advantage. But this may be OT in your env..
The awk system call is standard as afaik. so:
From man system();

&quot;Do not use system() from a program with suid or sgid ileges, because strange values for some environment ables might be used to subvert system integrity. Us exec(3) family of functions instead, but not execlp execvp(3). system() will not, in fact, work properl programs with suid or sgid privileges on systems on /bin/sh is bash version 2, since bash 2 drops priv on startup. (Debian uses a modified bash which do do this when invoked as sh.)&quot;
 
Thank you for your explanation.

In fact I do not fear so much malicious usage than wrong usage.
But you are right with the system function. I will no more use it.
I think I will try to embed my awk script within a shell script.
Resetting environment variables such as PATH or LD_LIBRARY_PATH to standard values at the beginning of the script and using absolute path for standard commands (/usr/bin/nawk or /usr/bin/cp) should lessen the risk of malevolent usage (you can't be too carefull).

Thanks again.
 
Hello,
Does anyone know how to use awk in execvp?
I need to get the size of a file. the unix cmd is &quot;ls -l file | awk '{print $5}'. But now I need to get the result of it in a c program. I have two processes, 1st one execvp the 'ls -l file'. Then with a pipe, the output of this process is transferred to the second child process 'awk '{print $5}'. The command for execvp is like:
char* c[3];
char* awk = &quot;awk&quot;;
char* op1 = &quot;{print $5}&quot;;
c[0] = awk;
c[1] = op1;
c[2] = NULL;
close(0);
dup( pipes[0] );
//use the output from 'ls..' as input

/*char temp[50];
if( read(0, temp, 50) < 0 ){
cerr << &quot;can not read result of list -l&quot; << strerror(errno) << endl;
exit(1);
}
cout<<&quot;In child2, input is &quot;<<temp<<endl;*/

close(1);
dup( pipes[1] ); //put the output for parent
execvp(*c,c);

I printed the input from first child, it is correct, but the second process does not end forever. Could someone tell me how to do it?
Thank you

 
if the awk is a script

#!/bin/sh
awk ....

try
#!/bin/sh -p
awk ....

vox clamantis in deserto.
 
aren't there better alternatives in C/C++ to get the size of the file [other then execvp a process that's contains multiple piped command]?

man stat/fstat
vlad
+---------------------------+
|#include<disclaimer.h> |
+---------------------------+
 
If you insist on the exec paradigm - 'man popen'.

vlad
+---------------------------+
|#include<disclaimer.h> |
+---------------------------+
 
Thank you vlad.
Here's an example.
Much easier ways to do this.

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

void printstat(struct stat mystat);

int main(int argc, char *argv[]) {
struct stat ms;

if (argc == 2) {
printf(&quot;Processing %s\n&quot;, argv[1]);
if (stat(argv[1], &ms) != -1) {
printstat(ms);
return 0;
} else {
perror(&quot;stat()&quot;);
return 1;
}
}
printf(&quot;No filename passed to proggy\n&quot;);
return 1;
}


void printstat(struct stat mystat) {
printf(&quot;Size in bytes : %d\n Size in KB %f\n&quot;, mystat.st_size, (float) mystat.st_size / 1024);
}
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top