* [PATCH] nfs-utils - 1 of 6 - statd - drop privs
@ 2003-06-18 17:33 Steve Dickson
2003-07-02 6:17 ` Neil Brown
0 siblings, 1 reply; 5+ messages in thread
From: Steve Dickson @ 2003-06-18 17:33 UTC (permalink / raw)
To: nfs
[-- Attachment #1: Type: text/plain, Size: 355 bytes --]
The following 6 patches have been ported to the
1.0.3 release the nfs-utils package. I'm hopefully
that Neil will incorate these so I no longer
have to continue porting them... ;-)
This first patch allows statd to run as a non-root
user. If there is not an rpcuser account (which
there is in our world) it will try to use the
nobody account.
SteveD.
[-- Attachment #2: nfs-utils-1.0.3-01-statd-dropprivs.patch --]
[-- Type: text/plain, Size: 3534 bytes --]
--- ./utils/statd/statd.c.orig 2003-06-02 14:57:03.000000000 -0400
+++ ./utils/statd/statd.c 2003-06-02 14:57:15.000000000 -0400
@@ -17,6 +17,10 @@
#include <rpc/rpc.h>
#include <rpc/pmap_clnt.h>
#include <rpcmisc.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <fcntl.h>
#include "statd.h"
#include "version.h"
@@ -34,6 +38,7 @@
char * SM_BAK_DIR = DEFAULT_SM_BAK_DIR;
char * SM_STAT_PATH = DEFAULT_SM_STAT_PATH;
+
/* ----- end of state directory path stuff ------- */
short int restart = 0;
@@ -66,6 +71,47 @@
extern void simulator (int, char **);
#endif
+/*
+ * Privilege dropper
+ */
+static void
+drop_privs(void)
+{
+ /* First locate user to jump to */
+ /* Prefer _not_ to use nobody as we'll own some files */
+ struct passwd* pw;
+
+ pw = getpwnam(RUN_AS_USER);
+ if (pw == NULL)
+ {
+ /* i.e. nobody */
+ log (L_WARNING, "Warning: You should really create user %s\n",
+ RUN_AS_USER);
+ pw = getpwnam(RUN_AS_FALLBACK);
+ }
+ if (pw == NULL)
+ {
+ die("Cannot start - cannot drop privs: getpwnam()\n");
+ }
+
+ initgroups(pw->pw_name, pw->pw_gid);
+
+ setgid(pw->pw_gid);
+ setuid(pw->pw_uid);
+
+ if (getgid() == 0)
+ {
+ die("Cannot start - cannot drop privs: getgid()\n");
+ }
+ else if (getuid() == 0)
+ {
+ die("Cannot start - cannot drop privs: getuid()\n");
+ }
+
+ /* Good enough */
+}
+
+
#ifdef HAVE_TCP_WRAPPER
#include "tcpwrapper.h"
@@ -264,8 +310,6 @@
daemon mode. */
}
- log_init (name_p,version_p);
-
log_modes();
#ifdef SIMULATIONS
@@ -298,6 +342,8 @@
}
}
+ log_init (name_p, version_p);
+
/* Child. */
signal (SIGHUP, killer);
signal (SIGINT, killer);
@@ -305,9 +351,33 @@
/* WARNING: the following works on Linux and SysV, but not BSD! */
signal(SIGCHLD, SIG_IGN);
+
+ /* cevans - we're going to drop root privs, but before we do that,
+ * make sure to get our port <1024 socket
+ */
+
+ /* Insist on starting as root - this means that when we setuid() away
+ * from root, we'll keep current->dumpable=0 and prevent being messed
+ * with (we may revert to user "nobody" - it's better than root
+ */
+ if (getuid() != 0)
+ die("Startup failed: Please start rpc.statd as root\n");
+
+ /* Arm the ****** resolver before chroot() so it doesn't fail
+ * trying to open /etc/ for the dozenth time
+ */
+ sethostent(1);
+
/* initialize out_port */
statd_get_socket(out_port);
+ /* Drop privs */
+ drop_privs();
+
+ /* After dropping privs, verify we can access all the files we need */
+ if (access(".", R_OK|W_OK|X_OK) != 0)
+ die("Cannot access current directory after dropping privs: access()\n");
+
for (;;) {
if (!(run_mode & MODE_NOTIFY_ONLY)) {
/* Do not do pmap_unset() when running in notify mode.
--- ./utils/statd/statd.h.orig 2003-06-02 14:57:03.000000000 -0400
+++ ./utils/statd/statd.h 2003-06-02 15:00:10.000000000 -0400
@@ -10,3 +10,10 @@
#include "system.h"
#include "log.h"
+/* Users we try and run as (prefer non-nobody because nobody is overloaded */
+/* Also, the user we run as will own some important nfs state files */
+#define RUN_AS_USER "rpcuser"
+/* Bah */
+#define RUN_AS_FALLBACK "nobody"
+
+
--- ./utils/statd/log.c.orig 2003-06-02 14:57:03.000000000 -0400
+++ ./utils/statd/log.c 2003-06-02 14:57:15.000000000 -0400
@@ -32,7 +32,7 @@
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();
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] nfs-utils - 1 of 6 - statd - drop privs
2003-06-18 17:33 [PATCH] nfs-utils - 1 of 6 - statd - drop privs Steve Dickson
@ 2003-07-02 6:17 ` Neil Brown
2003-07-03 11:42 ` Steve Dickson
0 siblings, 1 reply; 5+ messages in thread
From: Neil Brown @ 2003-07-02 6:17 UTC (permalink / raw)
To: Steve Dickson; +Cc: nfs
On Wednesday June 18, SteveD@redhat.com wrote:
> The following 6 patches have been ported to the
> 1.0.3 release the nfs-utils package. I'm hopefully
> that Neil will incorate these so I no longer
> have to continue porting them... ;-)
Sorry for not looking at these sooner...
>
>
> This first patch allows statd to run as a non-root
> user. If there is not an rpcuser account (which
> there is in our world) it will try to use the
> nobody account.
An effect of this patch is that if someone does a 'make install',
statd won't work anymore without some chowning.
What would you think if just getting stat to run as whichever users
owns /var/lib/nfs, and printing a warning if it is root.
Also the patch makes references to 'chroot' but never actually uses
chroot.
The second patch uses:
/var/run/rpc.statd/rpc.statd.pid
as a pid file, which doesn't seem like the right sort of name.
Either
/var/run/rpc.statd.pid
or
/var/run/nfs/rpc.statd.pid
would seem more appropriate, or is there some RedHat standard you are
following.
If we did do a chroot in statd we wouldn't be able to remove the pid
file any more. We could if it went in /var/lib/nfs, but I don't think
that is the right place.
Maybe if we held a fd of the pid file open and used ftruncate to
remove the pid. Would that work ok?
And I wish I knew why you thought mountd needed protection against
SIGPIPE, though I guess it cannot hurt.
NeilBrown
-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100006ave/direct;at.asp_061203_01/01
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] nfs-utils - 1 of 6 - statd - drop privs
2003-07-02 6:17 ` Neil Brown
@ 2003-07-03 11:42 ` Steve Dickson
2003-07-04 2:26 ` Neil Brown
0 siblings, 1 reply; 5+ messages in thread
From: Steve Dickson @ 2003-07-03 11:42 UTC (permalink / raw)
To: Neil Brown; +Cc: nfs
Hello,
Neil Brown wrote:
>>This first patch allows statd to run as a non-root
>>user. If there is not an rpcuser account (which
>>there is in our world) it will try to use the
>>nobody account.
>>
>>
>
>An effect of this patch is that if someone does a 'make install',
>statd won't work anymore without some chowning.
>
True.... We do an adduser during the package installation...
>What would you think if just getting stat to run as whichever users
>owns /var/lib/nfs, and printing a warning if it is root.
>
Looking around it appears root owns /var/lib/nfs.. and the
point of the patch is not to run a root..... I guess it all comes
do to how secure you want statd.... security is never free.... :)
Maybe you could add a compilation flag allowing people
to control it that way...
>The second patch uses:
> /var/run/rpc.statd/rpc.statd.pid
>as a pid file, which doesn't seem like the right sort of name.
>Either
> /var/run/rpc.statd.pid
>or
> /var/run/nfs/rpc.statd.pid
>
>would seem more appropriate, or is there some RedHat standard you are
>following.
>
I had to make it a directory so the pid file could be removed
after the privs have been dropped (i.e. not longer running as root).
>If we did do a chroot in statd we wouldn't be able to remove the pid
>file any more. We could if it went in /var/lib/nfs, but I don't think
>that is the right place.
>
>Maybe if we held a fd of the pid file open and used ftruncate to
>remove the pid. Would that work ok?
>
The privs dropping patch (i.e the first patch) makes the chroot no longer
necessary... but holding might work but how would the unlink occur?
>And I wish I knew why you thought mountd needed protection against
>SIGPIPE, though I guess it cannot hurt.
>
TCP aborts.... If a sender has a socket open and the receiver close()s the
socket with data still unread, the sender gets a SIGPIPE.
SteveD.
-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100006ave/direct;at.asp_061203_01/01
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] nfs-utils - 1 of 6 - statd - drop privs
2003-07-03 11:42 ` Steve Dickson
@ 2003-07-04 2:26 ` Neil Brown
2003-07-04 4:26 ` Neil Brown
0 siblings, 1 reply; 5+ messages in thread
From: Neil Brown @ 2003-07-04 2:26 UTC (permalink / raw)
To: Steve Dickson; +Cc: nfs
On Thursday July 3, SteveD@RedHat.com wrote:
> >An effect of this patch is that if someone does a 'make install',
> >statd won't work anymore without some chowning.
> >
> True.... We do an adduser during the package installation...
>
> >What would you think if just getting stat to run as whichever users
> >owns /var/lib/nfs, and printing a warning if it is root.
> >
> Looking around it appears root owns /var/lib/nfs.. and the
> point of the patch is not to run a root..... I guess it all comes
> do to how secure you want statd.... security is never free.... :)
> Maybe you could add a compilation flag allowing people
> to control it that way...
I had assumed that /var/lib/nfs would need to be chowned to "rpcuser"
for statd to work, but I guess it doesn't.
However "state", "sm" and "sm.bak" must already exist and be owned by
whoever state runs as.
So this is what I think I will do:
If 'sm' exists, statd takes on the identity of the owner, otherwise
it takes on the identity of the owner of /var/lib/nfs.
The "make install" script creates state, sm, and sm.bak and chowns
them to $SOMEUSER
The configure script sets $SOMEUSER to rpcuser if that is in
/etc/passwd, or nobody, but this setting can be over-ridden via a
config option
statd will create /var/run/rpc.statd.pid as root and will keep and
open filehandle for it to ftruncate later. Scripts which check
for this existance of the need to
[ -s /var/run/rpc.statd.pid ]
This allows for trouble free upgrading, a normal pid filename,
and still allows and even encourages good security.
> >And I wish I knew why you thought mountd needed protection against
> >SIGPIPE, though I guess it cannot hurt.
> >
> TCP aborts.... If a sender has a socket open and the receiver close()s the
> socket with data still unread, the sender gets a SIGPIPE.
Arh, that makes sense. The patch has already gone in anyway.
NeilBrown
-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100006ave/direct;at.asp_061203_01/01
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] nfs-utils - 1 of 6 - statd - drop privs
2003-07-04 2:26 ` Neil Brown
@ 2003-07-04 4:26 ` Neil Brown
0 siblings, 0 replies; 5+ messages in thread
From: Neil Brown @ 2003-07-04 4:26 UTC (permalink / raw)
To: Steve Dickson; +Cc: nfs
On Friday July 4, neilb@cse.unsw.edu.au wrote:
> So this is what I think I will do:
>
> If 'sm' exists, statd takes on the identity of the owner, otherwise
> it takes on the identity of the owner of /var/lib/nfs.
> The "make install" script creates state, sm, and sm.bak and chowns
> them to $SOMEUSER
> The configure script sets $SOMEUSER to rpcuser if that is in
> /etc/passwd, or nobody, but this setting can be over-ridden via a
> config option
>
> statd will create /var/run/rpc.statd.pid as root and will keep and
> open filehandle for it to ftruncate later. Scripts which check
> for this existance of the need to
> [ -s /var/run/rpc.statd.pid ]
Ok, I've just commited the following patch (plus new configure
generated by autoconf) to nfs-utils CVS. Hopefully it does most of
what you need.
Are you interested in submitting your current 'rc' scripts or an
updated .spec file?
NeilBrown
2003-07-04 NeilBrown <neilb@cse.unsw.edu.au>
Steve Dickson <SteveD@redhat.com>
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
Index: Makefile
===================================================================
RCS file: /cvsroot/nfs/nfs-utils/Makefile,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 Makefile
--- Makefile 18 Oct 1999 23:21:12 -0000 1.1.1.1
+++ Makefile 4 Jul 2003 04:15:00 -0000
@@ -20,3 +20,7 @@
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
Index: config.mk.in
===================================================================
RCS file: /cvsroot/nfs/nfs-utils/config.mk.in,v
retrieving revision 1.8
diff -u -r1.8 config.mk.in
--- config.mk.in 3 Jul 2003 06:14:10 -0000 1.8
+++ config.mk.in 4 Jul 2003 04:15:00 -0000
@@ -10,6 +10,7 @@
SBINDIR = @sbindir@
MANDIR = @mandir@
STATEDIR = $(install_prefix)@statedir@
+STATDUSER = @statduser@
##################################################################
# This is the prefix that will be used for nfsd and mountd. Leave this
Index: configure.in
===================================================================
RCS file: /cvsroot/nfs/nfs-utils/configure.in,v
retrieving revision 1.35
diff -u -r1.35 configure.in
--- configure.in 3 Jul 2003 02:37:15 -0000 1.35
+++ configure.in 4 Jul 2003 04:15:26 -0000
@@ -20,6 +20,15 @@
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,
Index: utils/statd/log.c
===================================================================
RCS file: /cvsroot/nfs/nfs-utils/utils/statd/log.c,v
retrieving revision 1.5
diff -u -r1.5 log.c
--- utils/statd/log.c 17 Feb 2001 17:22:53 -0000 1.5
+++ utils/statd/log.c 4 Jul 2003 04:15:26 -0000
@@ -32,7 +32,7 @@
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();
Index: utils/statd/statd.c
===================================================================
RCS file: /cvsroot/nfs/nfs-utils/utils/statd/statd.c,v
retrieving revision 1.13
diff -u -r1.13 statd.c
--- utils/statd/statd.c 11 Oct 2002 06:17:59 -0000 1.13
+++ utils/statd/statd.c 4 Jul 2003 04:15:26 -0000
@@ -12,11 +12,13 @@
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
+#include <errno.h>
#include <string.h>
#include <getopt.h>
#include <rpc/rpc.h>
#include <rpc/pmap_clnt.h>
#include <rpcmisc.h>
+#include <grp.h>
#include "statd.h"
#include "version.h"
@@ -147,6 +149,57 @@
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 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 @@
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 @@
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 @@
/* 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 @@
}
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;
-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100006ave/direct;at.asp_061203_01/01
_______________________________________________
NFS maillist - NFS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nfs
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2003-07-04 4:26 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-06-18 17:33 [PATCH] nfs-utils - 1 of 6 - statd - drop privs Steve Dickson
2003-07-02 6:17 ` Neil Brown
2003-07-03 11:42 ` Steve Dickson
2003-07-04 2:26 ` Neil Brown
2003-07-04 4:26 ` Neil Brown
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.