From 8b5bc63a7d56666950d4e3cd0937ab5187e84730 Mon Sep 17 00:00:00 2001 From: neilbrown Date: Fri, 4 Jul 2003 04:22:01 +0000 Subject: [PATCH] statd cleanup --- ChangeLog | 16 ++++++ Makefile | 4 ++ config.mk.in | 1 + configure | 120 +++++++++++++++++++++++++------------------- configure.in | 9 ++++ utils/statd/log.c | 2 +- utils/statd/statd.c | 111 ++++++++++++++++++++++++++++++++++++---- 7 files changed, 200 insertions(+), 63 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6eda83a..f1890c3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,22 @@ This is a 'pre-release' for 1.1.0 Hopefully 1.1.0 will be the baseline for 2.6 and 2.8. I.e. it should continue to work right through the 2.8 (or 3.0) kernel series. Previous releases wont. + +2003-07-04 NeilBrown + Steve Dickson + + statd cleanup: + * utils/statd/statd.c: create a pidfile with pid of statd, and + truncate it when statd exists. + * utils/statd/statd.c: drop privs by setuid to owner of SM_DIR, + and warn if this is root. + * utils/statd/statd.c: when statd forks, connect child to parent + with a pipe, and send a byte down the pipe once the child is + working properly. + * Makefile: create and chown sm, sm.bak, state when "make install" + * configure.in: add --with-statduser= option which defaults to + "rpcuser" or "nobody" + * config.mk.in: pass "statduser" through to Makefile 2003-07-03 NeilBrown diff --git a/Makefile b/Makefile index 2789f00..dcc6b36 100644 --- a/Makefile +++ b/Makefile @@ -20,3 +20,7 @@ install:: installman touch $(STATEDIR)/xtab; chmod 644 $(STATEDIR)/xtab touch $(STATEDIR)/etab; chmod 644 $(STATEDIR)/etab touch $(STATEDIR)/rmtab; chmod 644 $(STATEDIR)/rmtab + mkdir -p $(STATEDIR)/sm $(STATEDIR)/sm.bak + touch $(STATEDIR)/state + chmod go-rwx $(STATEDIR)/sm $(STATEDIR)/sm.bak $(STATEDIR)/state + chown $(STATDUSER) $(STATEDIR)/sm $(STATEDIR)/sm.bak $(STATEDIR)/state diff --git a/config.mk.in b/config.mk.in index d2cbea0..67f3d01 100644 --- a/config.mk.in +++ b/config.mk.in @@ -10,6 +10,7 @@ BINDIR = @bindir@ SBINDIR = @sbindir@ MANDIR = @mandir@ STATEDIR = $(install_prefix)@statedir@ +STATDUSER = @statduser@ ################################################################## # This is the prefix that will be used for nfsd and mountd. Leave this diff --git a/configure b/configure index 8038764..0922048 100755 --- a/configure +++ b/configure @@ -16,6 +16,8 @@ ac_help="$ac_help --with-release=XXX set release to XXX [1]" ac_help="$ac_help --with-statedir=/foo use state dir /foo [/var/lib/nfs]" +ac_help="$ac_help + --with-statduser=rpcuser user for statd to run under [rpcuser or nobody]" ac_help="$ac_help --enable-nfsv3 enable support for NFSv3" ac_help="$ac_help @@ -558,6 +560,19 @@ else fi +# Check whether --with-statduser or --without-statduser was given. +if test "${with_statduser+set}" = set; then + withval="$with_statduser" + statduser=$withval +else + if grep -s '^rpcuser:' /etc/passwd > /dev/null; then + statduser=rpcuser + else + statduser=nobody + fi +fi + + # Check whether --enable-nfsv3 or --disable-nfsv3 was given. if test "${enable_nfsv3+set}" = set; then enableval="$enable_nfsv3" @@ -618,7 +633,7 @@ fi # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:622: checking for $ac_word" >&5 +echo "configure:637: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -648,7 +663,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:652: checking for $ac_word" >&5 +echo "configure:667: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -699,7 +714,7 @@ fi # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:703: checking for $ac_word" >&5 +echo "configure:718: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -731,7 +746,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:735: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:750: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -742,12 +757,12 @@ cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 746 "configure" +#line 761 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:751: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:766: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -773,12 +788,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:777: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:792: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:782: checking whether we are using GNU C" >&5 +echo "configure:797: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -787,7 +802,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:791: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:806: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -806,7 +821,7 @@ ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:810: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:825: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -838,7 +853,7 @@ else fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:842: checking how to run the C preprocessor" >&5 +echo "configure:857: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -853,13 +868,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:863: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:878: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -870,13 +885,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:880: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:895: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -887,13 +902,13 @@ else rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:897: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:912: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -948,7 +963,7 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:952: checking for a BSD compatible install" >&5 +echo "configure:967: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1011,7 +1026,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:1015: checking host system type" >&5 +echo "configure:1030: checking host system type" >&5 host_alias=$host case "$host_alias" in @@ -1032,7 +1047,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$host" 1>&6 echo $ac_n "checking build system type""... $ac_c" 1>&6 -echo "configure:1036: checking build system type" >&5 +echo "configure:1051: checking build system type" >&5 build_alias=$build case "$build_alias" in @@ -1058,7 +1073,7 @@ fi # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1062: checking for $ac_word" >&5 +echo "configure:1077: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1090,7 +1105,7 @@ if test -n "$ac_tool_prefix"; then # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1094: checking for $ac_word" >&5 +echo "configure:1109: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1125,7 +1140,7 @@ fi # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1129: checking for $ac_word" >&5 +echo "configure:1144: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1157,7 +1172,7 @@ fi # Extract the first word of "${ac_tool_prefix}ld", so it can be a program name with args. set dummy ${ac_tool_prefix}ld; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1161: checking for $ac_word" >&5 +echo "configure:1176: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_LD'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1188,12 +1203,12 @@ fi echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:1192: checking for ANSI C header files" >&5 +echo "configure:1207: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1201,7 +1216,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1205: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1220: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1218,7 +1233,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -1236,7 +1251,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -1257,7 +1272,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -1268,7 +1283,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:1272: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1287: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -1292,12 +1307,12 @@ EOF fi echo $ac_n "checking for GNU libc2""... $ac_c" 1>&6 -echo "configure:1296: checking for GNU libc2" >&5 +echo "configure:1311: checking for GNU libc2" >&5 if eval "test \"`echo '$''{'knfsd_cv_glibc2'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -1306,7 +1321,7 @@ else #endif EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1310: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1325: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1329,7 +1344,7 @@ fi echo $ac_n "checking for main in -lsocket""... $ac_c" 1>&6 -echo "configure:1333: checking for main in -lsocket" >&5 +echo "configure:1348: checking for main in -lsocket" >&5 ac_lib_var=`echo socket'_'main | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1337,14 +1352,14 @@ else ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1363: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1365,7 +1380,7 @@ else fi echo $ac_n "checking for main in -lnsl""... $ac_c" 1>&6 -echo "configure:1369: checking for main in -lnsl" >&5 +echo "configure:1384: checking for main in -lnsl" >&5 ac_lib_var=`echo nsl'_'main | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1373,14 +1388,14 @@ else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1399: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1401,7 +1416,7 @@ else fi echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6 -echo "configure:1405: checking for crypt in -lcrypt" >&5 +echo "configure:1420: checking for crypt in -lcrypt" >&5 ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1409,7 +1424,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lcrypt $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1439: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1442,7 +1457,7 @@ fi if test "$knfsd_cv_glibc2" = no; then echo $ac_n "checking for daemon in -lbsd""... $ac_c" 1>&6 -echo "configure:1446: checking for daemon in -lbsd" >&5 +echo "configure:1461: checking for daemon in -lbsd" >&5 ac_lib_var=`echo bsd'_'daemon | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1450,7 +1465,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lbsd $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1480: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1488,14 +1503,14 @@ fi echo $ac_n "checking for the tcp wrapper library""... $ac_c" 1>&6 -echo "configure:1492: checking for the tcp wrapper library" >&5 +echo "configure:1507: checking for the tcp wrapper library" >&5 if eval "test \"`echo '$''{'knfsd_cv_tcp_wrapper'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else old_LIBS="$LIBS" LIBS="$LIBS -lwrap $LIBNSL" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1523: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* knfsd_cv_tcp_wrapper=yes else @@ -1530,12 +1545,12 @@ fi for ac_func in innetgr do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1534: checking for $ac_func" >&5 +echo "configure:1549: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1577: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1727,6 +1742,7 @@ s%@mandir@%$mandir%g s%@VERSION@%$VERSION%g s%@RELEASE@%$RELEASE%g s%@statedir@%$statedir%g +s%@statduser@%$statduser%g s%@enable_nfsv3@%$enable_nfsv3%g s%@kprefix@%$kprefix%g s%@secure_statd@%$secure_statd%g diff --git a/configure.in b/configure.in index d96a5da..017e795 100644 --- a/configure.in +++ b/configure.in @@ -20,6 +20,15 @@ AC_ARG_WITH(statedir, statedir=$withval, statedir=/var/lib/nfs) AC_SUBST(statedir) +AC_ARG_WITH(statduser, + [ --with-statduser=rpcuser user for statd to run under [rpcuser or nobody]], + statduser=$withval, + if grep -s '^rpcuser:' /etc/passwd > /dev/null; then + statduser=rpcuser + else + statduser=nobody + fi) + AC_SUBST(statduser) AC_ARG_ENABLE(nfsv3, [ --enable-nfsv3 enable support for NFSv3], enable_nfsv3=$enableval, diff --git a/utils/statd/log.c b/utils/statd/log.c index 104dee9..a8414b7 100644 --- a/utils/statd/log.c +++ b/utils/statd/log.c @@ -32,7 +32,7 @@ static int opt_debug = 0; /* Will be command-line option, eventually */ void log_init() { if (!(run_mode & MODE_LOG_STDERR)) - openlog(name_p, LOG_PID, LOG_DAEMON); + openlog(name_p, LOG_PID | LOG_NDELAY, LOG_DAEMON); mypid = getpid(); diff --git a/utils/statd/statd.c b/utils/statd/statd.c index 127e258..dbd73b3 100644 --- a/utils/statd/statd.c +++ b/utils/statd/statd.c @@ -12,11 +12,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include "statd.h" #include "version.h" @@ -147,6 +149,57 @@ usage() fprintf(stderr," -N Run in notify only mode.\n"); } +static const char *pidfile = "/var/run/rpc.statd.pid"; + +int pidfd = -1; +static void create_pidfile(void) +{ + FILE *fp; + + unlink(pidfile); + fp = fopen(pidfile, "w"); + if (!fp) + die("Opening %s failed: %s\n", + pidfile, strerror(errno)); + fprintf(fp, "%d\n", getpid()); + pidfd = dup(fileno(fp)); + if (fclose(fp) < 0) + log(L_WARNING, "Flushing pid file failed.\n"); +} + +static void truncate_pidfile(void) +{ + if (pidfd >= 0) + ftruncate(pidfd, 0); +} + +static void drop_privs(void) +{ + struct stat st; + + if (stat(SM_DIR, &st) == -1 && + stat(DIR_BASE, &st) == -1) + st.st_uid = 0; + + if (st.st_uid == 0) { + log(L_WARNING, "statd running as root. chown %s to choose different user\n", + SM_DIR); + return; + } + /* better chown the pid file before dropping, as if it + * if over nfs we might loose access + */ + if (pidfd >= 0) + fchown(pidfd, st.st_uid, st.st_gid); + + setgroups(0, NULL); + if (setgid(st.st_gid) == -1 + || setuid(st.st_uid) == -1) { + log(L_ERROR, "Fail to drop privileges"); + exit(1); + } +} + /* * Entry routine/main loop. */ @@ -157,6 +210,9 @@ int main (int argc, char **argv) int arg; int port = 0, out_port = 0; + int pipefds[2] = { -1, -1}; + char status; + /* Default: daemon mode, no other options */ run_mode = 0; @@ -264,10 +320,6 @@ int main (int argc, char **argv) daemon mode. */ } - log_init (name_p,version_p); - - log_modes(); - #ifdef SIMULATIONS if (argc > 1) /* LH - I _really_ need to update simulator... */ @@ -277,28 +329,54 @@ int main (int argc, char **argv) if (!(run_mode & MODE_NODAEMON)) { int filedes, fdmax, tempfd; + if (pipe(pipefds)<0) { + perror("statd: unable to create pipe"); + exit(1); + } if ((pid = fork ()) < 0) { - perror ("Could not fork"); + perror ("statd: Could not fork"); exit (1); } else if (pid != 0) { - /* Parent. */ + /* Parent. + * Wait for status from child. + */ + close(pipefds[1]); + if (read(pipefds[0], &status, 1) != 1) + exit(1); exit (0); } /* Child. */ + close(pipefds[0]); setsid (); - chdir (DIR_BASE); + if (chdir (DIR_BASE) == -1) { + perror("statd: Could not chdir"); + exit(1); + } + while (pipefds[1] <= 2) { + pipefds[1] = dup(pipefds[1]); + if (pipefds[1]<0) { + perror("statd: dup"); + exit(1); + } + } tempfd = open("/dev/null", O_RDWR); close(0); dup2(tempfd, 0); close(1); dup2(tempfd, 1); close(2); dup2(tempfd, 2); fdmax = sysconf (_SC_OPEN_MAX); - for (filedes = 3; filedes < fdmax; filedes++) { - close (filedes); - } + for (filedes = 3; filedes < fdmax; filedes++) + if (filedes != pipefds[1]) + close (filedes); + } /* Child. */ + + log_init (name_p,version_p); + + log_modes(); + signal (SIGHUP, killer); signal (SIGINT, killer); signal (SIGTERM, killer); @@ -308,6 +386,10 @@ int main (int argc, char **argv) /* initialize out_port */ statd_get_socket(out_port); + create_pidfile(); + atexit(truncate_pidfile); + drop_privs(); + for (;;) { if (!(run_mode & MODE_NOTIFY_ONLY)) { /* Do not do pmap_unset() when running in notify mode. @@ -319,6 +401,15 @@ int main (int argc, char **argv) } change_state (); shuffle_dirs (); /* Move directory names around */ + + /* If we got this far, we have successfully started, so notify parent */ + if (pipefds[1] > 0) { + status = 0; + write(pipefds[1], &status, 1); + close(pipefds[1]); + pipefds[1] = -1; + } + notify_hosts (); /* Send out notify requests */ ++restart; -- 2.39.2