aMule Forum
English => Feature requests => Topic started by: Meeni on March 14, 2005, 12:31:40 AM
-
Hi guys.
I noticed when i wanted to install amuled as a boot daemon that it is hard to make it run under another user.
I tried the following to start amule at boot time (on slackware) :
#!/bin/sh
# Start/stop/restart amuled
#
# To start amuled and amuleweb at boot, be sure to chmod 755 /etc/rc.d/rc.amule
amuled_start() {
if [ -x /usr/local/bin/amuled ]; then
if [ -r /var/run/amuled.pid ]; then
if ! ps axc | grep amuled 1> /dev/null 2>/dev/null; then
echo "Cleaning up old /var/run/amule/amuled.pid."
rm -f /var/run/amuled.pid
fi
fi
/usr/local/bin/amuled -o 2>&1 >/var/log/amuled.log &
echo "$!" > /var/run/amuled.pid
fi
}
amuled_stop() {
# If there is no PID file, ignore this request...
if [ -r /var/run/amuled.pid ]; then
kill `cat /var/run/amuled.pid`
wait `cat /var/run/amuled.pid`
rm -f /var/run/amuled.pid
fi
}
amuled_restart() {
amuled_stop
amuled_start
}
case "$1" in
'start')
amuled_start
;;
'stop')
amuled_stop
;;
'restart')
amuled_restart
;;
*)
echo "Usage $0 start|stop|restart"
esac
In order to avoid amuled (and so amuleweb) running as root, I have setuid amuled, and given it to a fake user 'amule'. However, this does not work well, because amuled tries to read configuration files from ~/.aMule, which points to /root/.aMule. Second issue is that it is a security breach to allow amule user to modify /usr/local/bin/amuled binary (as it is the owner of the file, for setuid, whatever the file is chmoded does not change anything).
I suggest that amuled includes a new feature :
1) detach from controling tty.
2) perform setuid trough the setuid system call, thus loosing root privileges.
3) read configuration file from ~/.amule or from a command line argument specified path (what's not possible for now).
Good job for amuled, that rocks !
-
#!/bin/sh
# Start/stop/restart amuled/amuleweb
# To start amuled and amuleweb at boot, be sure to chmod 755 /etc/rc.d/rc.amule
amuled_start() {
echo "Starting aMule P2P file sharing daemon."
if [ -x /usr/local/bin/amuled ]; then
if [ -r /var/run/amuled.pid ]; then
if ! ps axc | grep amuled 1> /dev/null 2>/dev/null; then
echo "Cleaning up old /var/run/amule/amuled.pid."
rm -f /var/run/amuled.pid
else
echo "Another amule [`cat /var/run/amuled.pid`] is running: aborting."
exit
fi
fi
sudo -u emule -H /usr/local/bin/amuled -o 2>&1 1>/var/log/amuled &
echo "$!" > /var/run/amuled.pid
fi
}
amuled_stop() {
# If there is no PID file, ignore this request...
if [ -r /var/run/amuled.pid ]; then
AMULEDPID=`cat /var/run/amuled.pid`
echo "Shutting down aMule P2P file sharing daemon [$AMULEDPID]."
if ! ps axc | grep $AMULEDPID 2>/dev/null | grep amuled 1>/dev/null 2>/dev/null; then
echo "Pid file [$AMULEDPID] does not match any running aMule daemon: aborting."
exit
fi
kill $AMULEDPID
# Wait at least one minute for it to exit, as we don't know how much time it takes to flush part files...
for second in 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 \
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 60 ; do
if ! ps axc | grep $AMULEDPID 2>/dev/null | grep amuled 1>/dev/null 2>/dev/null; then
break;
fi
sleep 1
done
if [ "$second" = "60" ]; then
echo "WARNING: Gave up waiting for amuled [$AMULEDPID] to exit!"
sleep 15
echo "Killing now amuled [$AMULEDPID]"
kill -KILL $AMULEDPID
fi
rm -f /var/run/amuled.pid
else
echo "No pid file, are you sure amuled is running ?";
fi
}
amuled_restart() {
amuled_stop
amuled_start
}
case "$1" in
'start')
amuled_start
;;
'stop')
amuled_stop
;;
'restart')
amuled_restart
;;
*)
echo "Usage $0 start|stop|restart"
esac
this one works well without giving amuled binary to emule user. However I think it is steel important to add at least configuration files path as command line parameter.
I guess it would be very pleasant for users just to set username to use for amuled in some place in the config file, without having to cope with sudoers files and so on.
-
1) detach from controling tty.
2) perform setuid trough the setuid system call, thus loosing root privileges.
(what's not possible for now).
I agree, that every "pretend-to-be-daemon" program must have it.
But, those features are quite OS dependent. And as being so, requires more testing. I think I will work on it after we have 2.0 stable release.
3) read configuration file from ~/.amule or from a command line argument specified path
I think you can setenv $HOME
You did not mentioned that setting additional user requires adjusting his permissions and home dir right, so you can access downloaded files later. Now, you will have to change permissions on your shared files too.
-
You're right, maybe just setenv $HOME at the same time setuid is performed is sufficient. On the other hand, some fake user may not have a home dir and just read configuration files from /etc/amule or any other 'system wide' place would be logical for a daemon. Just letting the user choose wether he wants to let amuled find the configuration files (in ~/.aMule) or use a provided configuration file (like the --amule-config-file=/some/where/aMule.conf used in amuleweb) would be fine for this.
-
You right, place like /etc/amule/... is more reasonable then fake user dir. I will deal with all those issues after 2.0 release.
-
So just come to see how progress is made in, 2 or 3 years.
-
I found a couple of POSIX funcs that may help :
getppid : if result is equal to 1, we are already detached from tty
setsid : change process group to group 1
close 0 1 2 may be sufficient to kill stdout/in/err.
lockf : if lock of a created pid file does not succeed have to abort, this imply another instance of the daemon is running.
a fast and dirty daemonize func would be
void makedaemon(void)
{
int fd;
char pid[PID_MAX_LEN + 2];
// stdio stuff
close(0); close(1); close(2);
fd = open("/dev/null",O_RDWR); dup(fd); dup(fd); // handle standart I/O (may redirect to some logger facility instead)
if(fd < 0) errorstuff();
// controling tty stuff
if(getppid() == 1) return; // already a daemon
switch(fork())
{
-1: errorstuff();
0: exit(0); //parent terminates
default : setsid(); // get a new group
}
// check multiple instance stuff
fd = open(LOCKFILE, O_CREATE | O_SYNC | O_WRONLY);
if(fd < 0) errorstuff();
if (lockf(fd, F_TLOCK, 0) < 0) alreadyrunningstuff();
n = sprintf(pid, "%d\n", getpid());
write(fd, pid, n); // keep it open to keep lock
umask(getUmaskFromConfigFileStuff());
chdir(getRunningDirFromConfigFileStuff());
}
Should work on any decent OS. Don't know wether this works on windows or not. I think amule should not try to be more windowish than emule : windows should try to be posix :]
-
Originally posted by Meeni
Should work on any decent OS. Don't know wether this works on windows or not. I think amule should not try to be more windowish than emule : windows should try to be posix :]
That was a good one... A M$ product caring about any standards... Haven't laughed that hard in ages :D
-
Have you checked it on Mac ? I have no idea about how posix mac is.
Now, have you checked this before posting:
NAME
daemon - run in the background
SYNOPSIS
#include
int daemon(int nochdir, int noclose);
This is easy part of daemon. Hard part is change effective user , adjust permissions and drop root rights
-
OS X is posix, OS 9 is definitively not a decent OS
daemon function is a shortcut for the code I provided. Unfortunately, this shortcut is only bsd4.4 compliant, and not Posix or SysV. So, it may (or not) work on various unix flavour.
-
I will work on it after 2.0 release
-
Regarding run-as-user, isn't that what the 'start-stop-daemon' utility is for?