00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <sys/types.h>
00037
00038 #define _XOPEN_SOURCE
00039
00040
00041 #define _XOPEN_SOURCE_EXTENDED
00042 #define __USE_XOPEN_EXTENDED
00043 #define __EXTENSIONS__
00044
00045
00046 #include <signal.h>
00047 #include <errno.h>
00048 #include <string.h>
00049 #include <stdio.h>
00050 #include <stdlib.h>
00051 #include <sys/time.h>
00052 #include <sys/resource.h>
00053 #include <unistd.h>
00054 #ifdef __OS_linux
00055 #include <sys/prctl.h>
00056 #endif
00057
00058 #include "daemonize.h"
00059 #include "globals.h"
00060 #include "dprint.h"
00061
00062
00063
00064
00065
00066
00067 int daemonize(int * own_pgid)
00068 {
00069 FILE *pid_stream;
00070 pid_t pid;
00071 int r, p;
00072
00073 p=-1;
00074
00075
00076
00077
00078
00079 setbuf(stdout, 0);
00080 setbuf(stderr, 0);
00081 if (chroot_dir&&(chroot(chroot_dir)<0)){
00082 LM_CRIT("Cannot chroot to %s: %s\n", chroot_dir, strerror(errno));
00083 goto error;
00084 }
00085
00086 if (chdir(working_dir)<0){
00087 LM_CRIT("Cannot chdir to %s: %s\n", working_dir, strerror(errno));
00088 goto error;
00089 }
00090
00091
00092 if ((pid=fork())<0){
00093 LM_CRIT("Cannot fork:%s\n", strerror(errno));
00094 goto error;
00095 }else if (pid!=0){
00096
00097 exit(0);
00098 }
00099
00100 if (setsid()<0){
00101 LM_WARN("setsid failed: %s\n",strerror(errno));
00102 }else{
00103 *own_pgid=1;
00104 }
00105
00106 if ((pid=fork())<0){
00107 LM_CRIT("Cannot fork:%s\n", strerror(errno));
00108 goto error;
00109 }else if (pid!=0){
00110
00111 exit(0);
00112 }
00113
00114 #ifdef __OS_linux
00115
00116 if ( !disable_core_dump && prctl(PR_SET_DUMPABLE, 1)) {
00117 LM_ERR("Cannot enable core dumping after setuid\n");
00118 }
00119 #endif
00120
00121
00122 if (pid_file!=0){
00123
00124 if ((pid_stream=fopen(pid_file, "r"))!=NULL){
00125 if (fscanf(pid_stream, "%d", &p) < 0) {
00126 LM_WARN("could not parse pid file %s\n", pid_file);
00127 }
00128 fclose(pid_stream);
00129 if (p==-1){
00130 LM_WARN("pid file %s exists, but doesn't contain a valid"
00131 " pid number, replacing...\n", pid_file);
00132 } else
00133 if (kill((pid_t)p, 0)==0 || errno==EPERM){
00134 LM_CRIT("running process found in the pid file %s\n",
00135 pid_file);
00136 goto error;
00137 }else{
00138 LM_WARN("pid file contains old pid, replacing pid\n");
00139 }
00140 }
00141 pid=getpid();
00142 if ((pid_stream=fopen(pid_file, "w"))==NULL){
00143 LM_ERR("unable to create pid file %s: %s\n",
00144 pid_file, strerror(errno));
00145 goto error;
00146 }else{
00147 r = fprintf(pid_stream, "%i\n", (int)pid);
00148 if (r<=0) {
00149 LM_ERR("unable to write pid to file %s: %s\n",
00150 pid_file, strerror(errno));
00151 goto error;
00152 }
00153 fclose(pid_stream);
00154 }
00155 }
00156
00157 if (pgid_file!=0){
00158 if ((pid_stream=fopen(pgid_file, "r"))!=NULL){
00159 if (fscanf(pid_stream, "%d", &p) < 0) {
00160 LM_WARN("could not parse pgid file %s\n", pgid_file);
00161 }
00162 fclose(pid_stream);
00163 if (p==-1){
00164 LM_WARN("pgid file %s exists, but doesn't contain a valid"
00165 " pgid number, replacing...\n", pgid_file);
00166 }
00167 }
00168 if (own_pgid){
00169 pid=getpgid(0);
00170 if ((pid_stream=fopen(pgid_file, "w"))==NULL){
00171 LM_ERR("unable to create pgid file %s: %s\n",
00172 pgid_file, strerror(errno));
00173 goto error;
00174 }else{
00175 r = fprintf(pid_stream, "%i\n", (int)pid);
00176 if (r<=0) {
00177 LM_ERR("unable to write pgid to file %s: %s\n",
00178 pid_file, strerror(errno));
00179 goto error;
00180 }
00181 fclose(pid_stream);
00182 }
00183 }else{
00184 LM_WARN("we don't have our own process so we won't save"
00185 " our pgid\n");
00186 unlink(pgid_file);
00187
00188 }
00189 }
00190
00191
00192 if (freopen("/dev/null", "r", stdin)==0){
00193 LM_WARN("unable to replace stdin with /dev/null: %s\n",
00194 strerror(errno));
00195
00196 };
00197 if (freopen("/dev/null", "w", stdout)==0){
00198 LM_WARN("unable to replace stdout with /dev/null: %s\n",
00199 strerror(errno));
00200
00201 };
00202
00203 if ( (!log_stderr) && (freopen("/dev/null", "w", stderr)==0)){
00204 LM_WARN("unable to replace stderr with /dev/null: %s\n",
00205 strerror(errno));
00206
00207 };
00208
00209
00210
00211 for (r=3; r < 32; r++){
00212 close(r);
00213 }
00214 return 0;
00215
00216 error:
00217 return -1;
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227 int do_suid(const int uid, const int gid)
00228 {
00229 if (gid){
00230 if(setgid(gid)<0){
00231 LM_CRIT("cannot change gid to %d: %s\n", gid, strerror(errno));
00232 goto error;
00233 }
00234 }
00235
00236 if(uid){
00237 if(setuid(uid)<0){
00238 LM_CRIT("cannot change uid to %d: %s\n", uid, strerror(errno));
00239 goto error;
00240 }
00241 }
00242
00243 #ifdef __OS_linux
00244
00245 if ( !disable_core_dump && prctl(PR_SET_DUMPABLE, 1)) {
00246 LM_ERR("Cannot enable core dumping after setuid\n");
00247 }
00248 #endif
00249
00250 return 0;
00251 error:
00252 return -1;
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
00262 int increase_open_fds(unsigned int target)
00263 {
00264 struct rlimit lim, orig;
00265
00266 if (getrlimit(RLIMIT_NOFILE, &lim)<0){
00267 LM_CRIT("cannot get the maximum number of file descriptors: %s\n",
00268 strerror(errno));
00269 goto error;
00270 }
00271 orig=lim;
00272 LM_DBG("current open file limits: %lu/%lu\n",
00273 (unsigned long)lim.rlim_cur, (unsigned long)lim.rlim_max);
00274 if ((lim.rlim_cur==RLIM_INFINITY) || (target<=lim.rlim_cur))
00275
00276 goto done;
00277 else if ((lim.rlim_max==RLIM_INFINITY) || (target<=lim.rlim_max)){
00278 lim.rlim_cur=target;
00279 }else{
00280
00281 LM_INFO("trying to increase the open file limit"
00282 " past the hard limit (%ld -> %d)\n",
00283 (unsigned long)lim.rlim_max, target);
00284 lim.rlim_max=target;
00285 lim.rlim_cur=target;
00286 }
00287 LM_DBG("increasing open file limits to: %lu/%lu\n",
00288 (unsigned long)lim.rlim_cur, (unsigned long)lim.rlim_max);
00289 if (setrlimit(RLIMIT_NOFILE, &lim)<0){
00290 LM_CRIT("cannot increase the open file limit to"
00291 " %lu/%lu: %s\n",
00292 (unsigned long)lim.rlim_cur, (unsigned long)lim.rlim_max,
00293 strerror(errno));
00294 if (orig.rlim_max>orig.rlim_cur){
00295
00296
00297 lim.rlim_max=orig.rlim_max;
00298 lim.rlim_cur=orig.rlim_max;
00299 if (setrlimit(RLIMIT_NOFILE, &lim)==0){
00300 LM_CRIT("maximum number of file descriptors increased to"
00301 " %u\n",(unsigned)orig.rlim_max);
00302 }
00303 }
00304 goto error;
00305 }
00306 done:
00307 return 0;
00308 error:
00309 return -1;
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 int set_core_dump(int enable, unsigned int size)
00321 {
00322 struct rlimit lim, newlim;
00323
00324 if (enable){
00325 if (getrlimit(RLIMIT_CORE, &lim)<0){
00326 LM_CRIT("cannot get the maximum core size: %s\n",
00327 strerror(errno));
00328 goto error;
00329 }
00330 if (lim.rlim_cur<size){
00331
00332 newlim.rlim_max=RLIM_INFINITY;
00333 newlim.rlim_cur=newlim.rlim_max;
00334 if (setrlimit(RLIMIT_CORE, &newlim)==0) goto done;
00335
00336 if (lim.rlim_max<size){
00337 newlim.rlim_max=size;
00338 }
00339 newlim.rlim_cur=newlim.rlim_max;
00340 if (setrlimit(RLIMIT_CORE, &newlim)==0) goto done;
00341
00342 newlim.rlim_max=lim.rlim_max;
00343 newlim.rlim_cur=newlim.rlim_max;
00344 if (setrlimit(RLIMIT_CORE, &newlim)<0){
00345 LM_CRIT("could increase core limits at all: %s\n",
00346 strerror (errno));
00347 }else{
00348 LM_CRIT("core limits increased only to %lu\n",
00349 (unsigned long)lim.rlim_max);
00350 }
00351 goto error;
00352 }
00353 goto done;
00354 }else{
00355
00356 newlim.rlim_cur=0;
00357 newlim.rlim_max=0;
00358 if (setrlimit(RLIMIT_CORE, &newlim)<0){
00359 LM_CRIT("failed to disable core dumps: %s\n",
00360 strerror(errno));
00361 goto error;
00362 }
00363 }
00364 done:
00365 LM_DBG("core dump limits set to %lu\n", (unsigned long)newlim.rlim_cur);
00366 return 0;
00367 error:
00368 return -1;
00369 }