LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Writing Linux Daemons and secutiry (https://www.linuxquestions.org/questions/programming-9/writing-linux-daemons-and-secutiry-703301/)

tomq42 02-09-2009 04:12 AM

Writing Linux Daemons and security
 
I'm converting a process to run as a Linux daemon, but have a few issues/areas of misunderstanding.

I've done the basic work (calling daemon(), or generally following the guidance of forking yourself twice, closing file handles, chdir to root, set umask etc).
The questions I had related to security and how daemons work and interact with init.d scripts.

Because the daemon forks itself I write its process ID to a file in /var/run so that if the daemon is run with a "-stop" argument it can read this file and then signal the daemon to stop. This seems to be what Apache HTTPD does. It's not clear whether this is strictly necessary though as some (all?) Linux ditros seem to provide facilities for searching for process with given name to work out the pid in order to work out how to stop it. However I've so far not found any worthwhile documentation on how to write init.d scripts, or generally now to write a daemon and its associated init.d script.

My bigger concern is one of security. My understanding is that in general daemons get run as root. That is the init.d script that launches the daemon runs as root. I've seen various comments that a daemon should "drop its privileges as soon as possible", but it's unclear what exactly that means. I can use setuid to change the user id of a process, but to what? Any if I do that and I prohibited from changing back to root again?
Trouble with dropping privileges is that you can no longer write log files to /var/log, so if I want to write logs that roll over, or the log name should be based on the date for example, then dropping your privileges means you can't now open new files in /var/log for example.

Running as root seems a dangerous thing to do, but maybe that's just what daemons do on Linux (I've not got a great deal of experience under Linux). Are simple daemons on Linux just written carefully so that running under root is not a problem? I know it depends on what the daemon does (httpd has to run as root at least initially to bind to port 80, but then seems to farm out requests to child processes running as apache), but is there any "normal" behaviour?


Many thanks.
Tom Quarendon

SciYro 02-09-2009 05:53 AM

'normal' is whatever works. Yes, root running daemons must be made carefully.

Do not worry about init scripts, they vary from one distro to another and its the responsibility of the distribution (or whoever distributes the package for that distro) to ship with the proper scripts. init scripts are typically just shell scripts tho. How they are written depends on the distro, so youll have to read the distro's documentation, or simply look at other init scripts and immitate those.

The init script need not run a program as root. If its possible for your program to not run as root, then the init script can be made to run it as a normal-ish user. If your daemon shouldnt ever run as root, you can check if its running as root and exit (this will force init script writers to not run it as root). As for logging, arent the default logging facilities good enough for your daemon? If you can use them, then you would have no need to access /var/log directly.

You can change user to your daemon's user if it must run as root on startup. If you cannot find such a user, then simply exit with a error. And I believe that yes, once you change user IDs its impossible to revert, tho I do not know for sure (it should be noted in the libc manual tho).

tomq42 02-09-2009 07:25 AM

> Yes, root running daemons must be made carefully.

Any advice anywhere on what care needs to be taken when writing such daemons?

> Do not worry about init scripts
I'm writing a third party product -- if the product includes a daemon, then I need to provide an init script with it surely, so I do need to worry about init scripts and how to write them, or am I missing something about init scripts?


> The init script need not run a program as root.
I can make the init script su to a different user to run my program, but then I can't write a PID file to the /var/run directory as it seems like you're supposed to (according to Filesystem Hierarchy Standard pid files should be written to /var/run -- maybe this only applies to Linux "subsystem" daemons, and not "user" daemons). This is what I find confusing. Maybe I'm not supposed to use a pid file and rely on the facilities provided by the init.d framework to search the process list for the right process name to find which one to stop? If so, where are these guidelines documented? Apache httpd writes its own pid file so that it can implement its own stopping control, I'm assuming that this is to make it more portable and not rely on particular init.d facilities. My product needs to be equally portable.

If I want to run as a non-root user is it up to me to provide such a suitable user? Should my product install create one (like apache) for the purpose? Is there a sensible default user that can be used (such as "nobody"?), in the way that the default for a service on Windows is "Local system", which is fine for a lot of cases?

I don't know whether I can make use of syslog facilities for logging. I'm not sure what the volume of messages that it is expected that you write to syslogd is. I'm writing a log that's a bit like the apache HTTPD activity log, potentially logging lots or requests, with the log file rolling over based on the hour of the day, day of the week etc.
Maybe such log files should go somewhere in my own installation directory somewhere, or somewhere other than /var/log, but again it's a bit unclear.

irey 02-09-2009 08:00 AM

Quote:

Any advice anywhere on what care needs to be taken when writing such daemons?
Too many to report them here. You should get a book on security. However the most important thing is writing clean code, cause any bug may be exploited by a potential attacker. The worst case is a buffer overflow: it may lead to the execution of injected malicious code (so check all array limits!).
Quote:

Running as root seems a dangerous thing to do, but maybe that's just what daemons do on Linux
Most daemons start as root but they become another user later. See the manpages for setuid() and seteuid(). This way your daemon can open files, write it's pid, start logging, open TCP ports, etc. and then continue to operate normally as an unpriviledged user. An example that works this way is Apache web server.
Quote:

If I want to run as a non-root user is it up to me to provide such a suitable user?
Your program should start running as root (if it needs to perform priviledged actions), then read a username from a configuration file, lookup the uid for that user and become him by setuid().

chrism01 02-09-2009 06:04 PM

The reason SOME daemons start as root is because you have to be root to bind to a port num < 1024.
If you don't need to do this, you probably don't need to run as root. It really depends whether you need access to privileged areas.
If you are providing a service, create a new user just for that. If you need to start as root, drop privs asap and/or provide child procs (unpriv).
See the src for Apache for example.

tomq42 02-10-2009 02:51 AM

I still don't get entirely how I'm supposed to write a daemon, whether or not I run as root.

Sounds like relying on init.d framework to search the process list for a process of a certain name and then send that a signal is a little dangerous. Maybe there's more than one of my service running, perhaps there's a production one running as a daemon and I'm running a dev one as well. Apache httpd seems to rely on writing it's own pid file, presumably because it works off child processes, so there are lots of httpd processes running and telling which one to signal would be hard. You can't just record the pid of the process that the init.d script launches into a file for the init.d script to use later, because the daemon will fork itself, so the process that's running has a different pid.
So I'm assuming that I need to take the approach of my daemon writing its pid in a file somewhere. Research seemed to suggest that the "correct" place was in /var/run, but that's only writable by root.So either my daemon has to be launched as root, or I need to find another place to write my pid file. I took the former approach and then specify a userid on the command line and setuid to that user once I'm up and running.

I guess my problem is that I've no idea whether this is "sensible" or "expected" behaviour of a daemon on Linux/UNIX. Sounds fairly reasonable to me, but I've not got a lot of experience of administering Linux machines, or of what "normal" behaviour is for daemons. I'm just doing on a sample of 2, one being httpd and the other being the jsvc project from apache commons. The latter I assume is written by people who understand, so I've taken lessons from that.

I have to say though, that it's all a lot more vague and uncertain that writing Windows services.

irey 02-10-2009 03:15 AM

Quote:

search the process list for a process of a certain name and then send that a signal is a little dangerous.
Right, there may be more than one process with a given name. The pid file is a better approach.

Quote:

So I'm assuming that I need to take the approach of my daemon writing its pid in a file somewhere. Research seemed to suggest that the "correct" place was in /var/run, but that's only writable by root.
That's a good example of priviledged action. In this situation normal behaviour would be starting your daemon as root, writing the pid file, and giving up root priviledges trough setuid() when they are no longer needed.


All times are GMT -5. The time now is 11:25 PM.