Changing owner to nobody
would of course help in your objective. The below describes one way of doing this by using a dedicated helper program which is invisible to the user.
Solution: You can use setuid program to make sure the script is always run as the same user. Because of security reasons, you probably are not allowed to make your shell script setuid, but you can write a simple launcher program, maybe in C:
#include <stdio.h>
#include <unistd.h>
#define PROG "./daemon.sh"
int main(int argc, char** argv)
{
char action[32];
if (argc < 2) {
fprintf(stderr, "Usage: %s { --start | --stop }n", argv[0]);
return 0;
}
snprintf(action, sizeof(action), "%s-the-real-thing", argv[1]);
return execl(PROG, PROG, action, (char *)0);
}
Here we are supposing your script is named daemon.sh
and is in the same directory where you run the script. You can use full path or change in other obvious ways according to your need.
Compile and make setuid as follows (assuming here name launcher.c
and we decide to run as nobody
):
$ gcc -Wall launcher.c -o launcher
$ sudo chown nobody launcher
$ sudo chmod u+s launcher
You need to modify your shell script daemon program slightly:
#!/bin/sh
prog=$(basename $0)
start()
{
i=0
while :; do
i=$(expr $i + 1)
echo "Daemon working like a mad horse... ($i)"
sleep 1
done
}
stop()
{
pids=$(ps axu | grep "$prog.*--start" | grep -v grep | awk '{print $2}')
echo "Killing [$pids]"
[ -n "$pids" ] && exec /bin/kill -KILL $pids
}
case "$1" in
--start|--stop) exec ./launcher $1;;
--start-the-real-thing) start;;
--stop-the-real-thing) stop;;
*) echo "Bad argument \"$1\"";;
esac
Here start
function is where all the interesting funk is done until your kill the program by calling the stop
function. There are some obvious changes required to run this from anywhere, and I am hoping your existing kill
logic is more elegant.
Usage is like before:
./daemon.sh --start
./daemon.sh --stop
Explanation: the above will execute ./launcher --start
or ./launcher --stop
, repectively. This will change the effective user to nobody
(or whatever you chose to setuid the program), and execute either ./daemon.sh --start-the-real-thing
or ./daemon.sh --stop-the-real-thing
which will perform the desired original action.
Because the simple launcher program only allows running the named script, the security is easy to control (just to make sure, you can check in the launcher program that argv[1]
really is --start
or --stop
, then exactly two command line combinations can be run as ).