summaryrefslogtreecommitdiffstats
path: root/meta/packages/unfs-server/unfs-server-2.2beta47/001-2.2b47-2.2b51.patch
diff options
context:
space:
mode:
authorScott Garman <scott.a.garman@intel.com>2010-08-12 21:02:58 -0700
committerRichard Purdie <rpurdie@linux.intel.com>2010-08-20 16:20:09 +0100
commitb5b3825ce6df45b16e1f3e15001da213bc8b0a55 (patch)
treeb2577de0765074d6e2bdbbdf1862220b52e8d7c1 /meta/packages/unfs-server/unfs-server-2.2beta47/001-2.2b47-2.2b51.patch
parent735210556dc709b3c2367389fa6ea9c0109412b1 (diff)
downloadpoky-b5b3825ce6df45b16e1f3e15001da213bc8b0a55.tar.gz
unfs-server: new userspace nfs recipe
This is a simple userspace NFS server, derived from one which was previously used in openSUSE 10.x. Wind River contributed many of the patches. This package is not intended for target installations, only -native and -nativesdk use. Enabling nativesdk for readline, sqlite3, and pseudo was required, as well as a few new autoconf siteconfig entries. Signed-off-by: Scott Garman <scott.a.garman@intel.com>
Diffstat (limited to 'meta/packages/unfs-server/unfs-server-2.2beta47/001-2.2b47-2.2b51.patch')
-rw-r--r--meta/packages/unfs-server/unfs-server-2.2beta47/001-2.2b47-2.2b51.patch2344
1 files changed, 2344 insertions, 0 deletions
diff --git a/meta/packages/unfs-server/unfs-server-2.2beta47/001-2.2b47-2.2b51.patch b/meta/packages/unfs-server/unfs-server-2.2beta47/001-2.2b47-2.2b51.patch
new file mode 100644
index 0000000000..886ce92b34
--- /dev/null
+++ b/meta/packages/unfs-server/unfs-server-2.2beta47/001-2.2b47-2.2b51.patch
@@ -0,0 +1,2344 @@
1# Patch origin: nfs-server source RPM from openSUSE 10.3
2
3diff -urN nfs-server-2.2beta47/.version nfs-server-2.2beta51/.version
4--- nfs-server-2.2beta47/.version Tue Sep 7 09:47:27 1999
5+++ nfs-server-2.2beta51/.version Fri Nov 8 14:45:36 2002
6@@ -1 +1 @@
7-2.2beta46
8+2.2beta51
9diff -urN nfs-server-2.2beta47/ChangeLog nfs-server-2.2beta51/ChangeLog
10--- nfs-server-2.2beta47/ChangeLog Wed Nov 10 10:17:51 1999
11+++ nfs-server-2.2beta51/ChangeLog Fri Nov 8 14:45:36 2002
12@@ -1,8 +1,59 @@
13+Thu Nov 9 17:03:05 2000
14+
15+ * No longer use OPEN_MAX
16+
17+ * Reworked configure.in, BUILD script no longer needed
18+ (nor functioning)
19+
20+ * Be more anal about matching cached fh's and real files.
21+ In addition to the psi, we also store dev/ino/type now
22+ and match that in fh_find.
23+
24+ * Write pidfiles
25+
26+ * Support nosetuid
27+
28+Wed Feb 9 14:52:34 2000
29+
30+ * auth_init.c didn't properly parse options--rot_squash
31+ which is obviously a typo was parsed as ro.
32+ Thanks to Jan Steffan for complaining about this :-)
33+
34+Mon Jan 31 11:48:34 2000
35+
36+ * Fixed Y2K bug in logging.c.
37+ Thanks to Jonathan Hankins <jhankins@homewood.k12.al.us>.
38+
39+Thu Dec 9 11:14:21 1999
40+
41+ * Fix handling of NFS-mounted and /proc directories.
42+ They weren't properly hidden.
43+ Thanks to Dick Streefland <dick_streefland@tasking.com>
44+ for the report and a first patch.
45+
46 Wed Nov 10 10:17:16 1999
47
48 * Security fix for buffer overflow in fh_buildpath
49 No thanks to Mariusz who reported it to bugtraq
50 rather than me.
51+
52+Wed Nov 09 17:10:00 1999
53+
54+ * Workaround for broken Solaris clients that can't handle
55+ atime/mtime/ctime of 0.
56+ Thanks to Frank Wuebbelin for his problem report and
57+ testing the fix.
58+
59+ * Fixed typo in exports.man
60+
61+Tue Nov 2 10:31:14 1999
62+
63+ * Patch for mode 0100 and 0100 executables by
64+ Michael Deutschmann <michael@talamasca.wkpowerlink.com>
65+
66+ * Common startup stuff for all daemons.
67+ Inspired by code sent to me by someone (sorry, I forgot
68+ your name, and the mail's gone!)
69
70 Wed Sep 8 09:07:38 1999
71
72diff -urN nfs-server-2.2beta47/Makefile.in nfs-server-2.2beta51/Makefile.in
73--- nfs-server-2.2beta47/Makefile.in Tue Jun 22 14:53:10 1999
74+++ nfs-server-2.2beta51/Makefile.in Fri Nov 8 14:45:36 2002
75@@ -17,23 +17,30 @@
76
77 #### Start of system configuration section. ####
78
79-srcdir = @srcdir@
80-VPATH = @srcdir@
81+srcdir = @srcdir@
82+VPATH = @srcdir@
83
84-CC = @CC@
85-AR = ar
86-RANLIB = @RANLIB@
87-
88-INSTALL = @INSTALL@
89-INSTALL_PROGRAM = @INSTALL_PROGRAM@ -m 755
90-INSTALL_DATA = @INSTALL_DATA@
91-MAKEINFO = makeinfo
92-TEXI2DVI = texi2dvi
93-RPCGEN = @RPCGEN@ @RPCGEN_C@
94+CC = @CC@
95+AR = ar
96+RANLIB = @RANLIB@
97+
98+INSTALL = @INSTALL@
99+INSTALL_PROGRAM = @INSTALL_PROGRAM@ -m 755
100+INSTALL_DATA = @INSTALL_DATA@
101+MAKEINFO = makeinfo
102+TEXI2DVI = texi2dvi
103+RPCGEN = @RPCGEN@ @RPCGEN_C@
104
105 # General compile options and libs:
106-DEFS = @DEFS@ $(NFSD_DEFS)
107-LIBS = libnfs.a @LIBS@
108+DEFS = @DEFS@ $(NFSD_DEFS)
109+LIBS = libnfs.a @LIBS@
110+
111+# Ugidd support
112+UGIDD_PROG = @UGIDD_PROG@
113+UGIDD_MAN = @UGIDD_MAN@
114+
115+# New inode mapping scheme
116+DEVTAB_FILE = $(install_prefix)@PATH_DEVTAB@
117
118 # Compile options for nfsd:
119 # CALL_PROFILING
120@@ -80,9 +87,6 @@
121
122 #### End of system configuration section. ####
123
124-# include site-specific defintions generated by BUILD.
125-include site.mk
126-
127 SHELL = /bin/sh
128
129 SRCS = version.c logging.c fh.c devtab.c \
130@@ -96,19 +100,19 @@
131 utimes.c mkdir.c rename.c getopt.c getopt_long.c \
132 alloca.c mountlist.c xmalloc.c \
133 xstrdup.c strdup.c strstr.c nfsmounted.c faccess.c \
134- haccess.c failsafe.c signals.c
135+ haccess.c daemon.c signals.c
136 XDRFILES = mount.x nfs_prot.x
137 GENFILES = mount.h mount_xdr.c mount_svc.c nfs_prot.h nfs_prot_xdr.c \
138 ugid.h ugid_xdr.c ugid_clnt.c
139 HDRS = system.h nfsd.h auth.h fh.h logging.h fakefsuid.h \
140 rpcmisc.h faccess.h rquotad.h rquota.h haccess.h
141-LIBHDRS = fsusage.h getopt.h mountlist.h failsafe.h signals.h
142+LIBHDRS = fsusage.h getopt.h mountlist.h daemon.h signals.h
143 MANPAGES5 = exports
144 MANPAGES8p = mountd nfsd $(UGIDD_MAN)
145 MANPAGES8 = showmount
146 MANPAGES = $(MANPAGES5) $(MANPAGES8p) $(MANPAGES8)
147 LIBOBJS = version.o fsusage.o mountlist.o xmalloc.o xstrdup.o \
148- nfsmounted.o faccess.o haccess.o failsafe.o \
149+ nfsmounted.o faccess.o haccess.o daemon.o \
150 signals.o @LIBOBJS@ @ALLOCA@
151 OBJS = logging.o fh.o devtab.o auth_init.o auth_clnt.o auth.o
152 NFSD_OBJS = nfsd.o rpcmisc.o nfs_dispatch.o getattr.o setattr.o \
153@@ -174,15 +178,13 @@
154 ${srcdir}/mkinstalldirs $(bindir) $(man5dir) $(man8dir)
155
156 $(rpcprefix)mountd: $(MOUNTD_OBJS) libnfs.a
157- $(CC) $(LDFLAGS) -o $@ $(MOUNTD_OBJS) $(LIBS) \
158- $(LIBWRAP_DIR) $(LIBWRAP_LIB)
159+ $(CC) $(LDFLAGS) -o $@ $(MOUNTD_OBJS) $(LIBS)
160
161 $(rpcprefix)nfsd: $(NFSD_OBJS) libnfs.a
162 $(CC) $(LDFLAGS) -o $@ $(NFSD_OBJS) $(LIBS)
163
164 $(rpcprefix)ugidd: $(UGIDD_OBJS) libnfs.a
165- $(CC) $(LDFLAGS) -o $@ $(UGIDD_OBJS) $(LIBS) \
166- $(LIBWRAP_DIR) $(LIBWRAP_LIB)
167+ $(CC) $(LDFLAGS) -o $@ $(UGIDD_OBJS) $(LIBS)
168
169 showmount: $(SHOWMOUNT_OBJS) libnfs.a
170 $(CC) $(LDFLAGS) -o $@ $(SHOWMOUNT_OBJS) $(LIBS)
171diff -urN nfs-server-2.2beta47/aclocal.m4 nfs-server-2.2beta51/aclocal.m4
172--- nfs-server-2.2beta47/aclocal.m4 Fri Jun 11 12:04:22 1999
173+++ nfs-server-2.2beta51/aclocal.m4 Fri Nov 8 14:45:36 2002
174@@ -221,20 +221,14 @@
175 ])dnl
176 dnl *********** libwrap bug **************
177 define(AC_LIBWRAP_BUG,
178- [if test -f site.mk; then
179- . ./site.mk
180- fi
181- if test ! -z "$LIBWRAP_DIR"; then
182+ [if test "$ac_cv_lib_wrap_main" = yes; then
183 AC_MSG_CHECKING(for link problem with libwrap.a)
184 AC_CACHE_VAL(nfsd_cv_lib_wrap_bug,
185- [ac_save_LIBS=$LIBS
186- LIBS="$LIBS $LIBWRAP_DIR $LIBWRAP_LIB"
187- AC_TRY_LINK([
188+ [AC_TRY_LINK([
189 extern int deny_severity;
190 ],[
191 deny_severity=1;
192 ], nfsd_cv_lib_wrap_bug=no, nfsd_cv_lib_wrap_bug=yes)
193- LIBS=$ac_save_LIBS
194 ]) dnl
195 AC_MSG_RESULT($nfsd_cv_lib_wrap_bug)
196 test $nfsd_cv_lib_wrap_bug = yes && AC_DEFINE(HAVE_LIBWRAP_BUG)
197diff -urN nfs-server-2.2beta47/auth.c nfs-server-2.2beta51/auth.c
198--- nfs-server-2.2beta47/auth.c Mon Sep 13 16:56:03 1999
199+++ nfs-server-2.2beta51/auth.c Fri Nov 8 14:45:36 2002
200@@ -84,8 +84,9 @@
201 0, /* relative links */
202 0, /* noaccess */
203 1, /* cross_mounts */
204- (uid_t)-2, /* default uid */
205- (gid_t)-2, /* default gid */
206+ 1, /* allow setuid */
207+ 65534, /* default uid */
208+ 65534, /* default gid */
209 0, /* no NIS domain */
210 };
211
212@@ -99,8 +100,9 @@
213 0, /* relative links */
214 0, /* noaccess */
215 1, /* cross_mounts */
216- (uid_t)-2, /* default uid */
217- (gid_t)-2, /* default gid */
218+ 0, /* allow setuid */
219+ 65534, /* default uid */
220+ 65534, /* default gid */
221 0, /* no NIS domain */
222 };
223
224@@ -673,6 +675,7 @@
225 cpp = &unknown_clients;
226 } else {
227 cpp = &known_clients;
228+ cp->clnt_addr = *(struct in_addr *) hp->h_addr;
229 auth_hash_host(cp, hp);
230 }
231 cp->next = *cpp;
232diff -urN nfs-server-2.2beta47/auth.h nfs-server-2.2beta51/auth.h
233--- nfs-server-2.2beta47/auth.h Thu Apr 8 14:47:56 1999
234+++ nfs-server-2.2beta51/auth.h Fri Nov 8 14:45:36 2002
235@@ -23,14 +23,6 @@
236 extern char * public_root_path;
237 extern struct nfs_fh public_root;
238
239-#if defined(linux) && defined(i386) && !defined(HAVE_SETFSUID)
240-# define MAYBE_HAVE_SETFSUID
241-#endif
242-
243-#ifdef MAYBE_HAVE_SETFSUID
244-extern int have_setfsuid;
245-#endif
246-
247 /*
248 * These externs are set in the dispatcher (dispatch.c) and auth_fh
249 * (nfsd.c) so that we can determine access rights, export options,
250@@ -59,6 +51,7 @@
251 int link_relative;
252 int noaccess;
253 int cross_mounts;
254+ int allow_setuid;
255 uid_t nobody_uid;
256 gid_t nobody_gid;
257 char * clnt_nisdomain;
258@@ -112,7 +105,7 @@
259 extern void auth_free_lists(void);
260 extern nfs_client *auth_clnt(struct svc_req *rqstp);
261 extern nfs_mount *auth_path(nfs_client *, struct svc_req *, char *);
262-extern void auth_user(nfs_mount *, struct svc_req *);
263+extern int auth_user(nfs_mount *, struct svc_req *);
264
265 extern nfs_client *auth_get_client(char *);
266 extern nfs_mount *auth_match_mount(nfs_client *, char *);
267diff -urN nfs-server-2.2beta47/auth_clnt.c nfs-server-2.2beta51/auth_clnt.c
268--- nfs-server-2.2beta47/auth_clnt.c Wed Nov 10 10:18:06 1999
269+++ nfs-server-2.2beta51/auth_clnt.c Fri Nov 8 14:45:36 2002
270@@ -12,20 +12,17 @@
271 */
272
273
274+#include <sys/fsuid.h>
275 #include "system.h"
276 #include "nfsd.h"
277-#include "fakefsuid.h"
278-
279-#ifndef svc_getcaller
280-#define svc_getcaller(x) ((struct sockaddr_in *) &(x)->xp_rtaddr.buf)
281-#endif
282+#include "rpcmisc.h"
283
284
285-#if defined(HAVE_SETFSUID) || defined(MAYBE_HAVE_SETFSUID)
286-static void setfsids(uid_t, gid_t, gid_t *, int);
287+#if defined(HAVE_SETFSUID)
288+static int setfsids(uid_t, gid_t, gid_t *, int);
289 #endif
290 #ifndef HAVE_SETFSUID
291-static void seteids(uid_t, gid_t, gid_t *, int);
292+static int seteids(uid_t, gid_t, gid_t *, int);
293 #endif
294
295 uid_t auth_uid = 0; /* Current effective user ids */
296@@ -43,6 +40,17 @@
297 short *gid, short *nrgids, int *groups);
298 #endif
299
300+/*
301+ * The following crap is required for glibc 2.1 which has 32bit uids
302+ * in user land mapped to 16bit uids in the Linux kernel
303+ */
304+#if defined(HAVE_BROKEN_SETFSUID)
305+# define native_uid(u) ((unsigned short)(u))
306+# define native_gid(g) ((unsigned short)(g))
307+#else
308+# define native_uid(u) (u)
309+# define native_gid(g) (g)
310+#endif
311
312 /*
313 * For an RPC request, look up the NFS client info along with the
314@@ -92,8 +100,9 @@
315 }
316
317 if (logging_enabled(D_AUTH)) {
318- Dprintf(D_AUTH, "auth_path(%s): mount point %s, (%s%s%s%s%s)\n",
319- path, mp->path,
320+ Dprintf(D_AUTH, "auth_path(%s, %s): "
321+ "mount point %s, (%s%s%s%s%s)\n",
322+ inet_ntoa(cp->clnt_addr), path, mp->path,
323 mp->o.all_squash? "all_squash " : (
324 mp->o.root_squash? "root_squash " : ""),
325 (mp->o.uidmap == map_daemon)? "uidmap " : "",
326@@ -105,7 +114,8 @@
327 return mp;
328 }
329
330-void auth_user(nfs_mount *mp, struct svc_req *rqstp)
331+int
332+auth_user(nfs_mount *mp, struct svc_req *rqstp)
333 {
334 uid_t cuid;
335 gid_t cgid;
336@@ -160,23 +170,18 @@
337 else if (cred_len > NGRPS)
338 cred_len = NGRPS;
339
340- cuid = luid(cred_uid, mp, rqstp);
341- cgid = lgid(cred_gid, mp, rqstp);
342+ cuid = luid(native_uid(cred_uid), mp, rqstp);
343+ cgid = lgid(native_gid(cred_gid), mp, rqstp);
344 clen = cred_len;
345 for (i = 0; i < cred_len; i++)
346- cgids[i] = lgid(cred_gids[i], mp, rqstp);
347+ cgids[i] = lgid(native_gid(cred_gids[i]), mp, rqstp);
348 } else {
349 /* On systems that have 32bit uid_t in user space but
350 * 16bit in the kernel, we need to truncate the
351 * nobody ID (default -2).
352 */
353-#if !defined(HAVE_BROKEN_SETFSUID)
354- cuid = mp->o.nobody_uid;
355- cgid = mp->o.nobody_gid;
356-#else
357- cuid = (unsigned short) mp->o.nobody_uid;
358- cgid = (unsigned short) mp->o.nobody_gid;
359-#endif
360+ cuid = native_uid(mp->o.nobody_uid);
361+ cgid = native_gid(mp->o.nobody_gid);
362 /* Construct a list of one gid. */
363 cgids[0] = cgid;
364 clen = 1;
365@@ -193,14 +198,9 @@
366 * upper 16 bits set (including our default nobody uid -2).
367 */
368 #if defined(HAVE_SETFSUID)
369- setfsids(cuid, cgid, cgids, clen);
370+ return setfsids(cuid, cgid, cgids, clen);
371 #else
372-#if defined(MAYBE_HAVE_SETFSUID)
373- if (have_setfsuid)
374- setfsids(cuid, cgid, cgids, clen);
375- else
376-#endif
377- seteids(cuid, cgid, cgids, clen);
378+ return seteids(cuid, cgid, cgids, clen);
379 #endif
380 }
381
382@@ -210,6 +210,8 @@
383 void
384 auth_override_uid(uid_t uid)
385 {
386+ int res;
387+
388 /* extension hooks: */
389 efs_setfsuid(uid);
390
391@@ -217,19 +219,18 @@
392 uid = (unsigned short) uid;
393 #endif
394 #if defined(HAVE_SETFSUID)
395- setfsuid(uid);
396+ res = setfsuid(uid);
397 #else
398-#if defined(MAYBE_HAVE_SETFSUID)
399- if (have_setfsuid)
400- setfsuid(uid);
401- else
402-#endif
403- seteuid(uid);
404+ res = seteuid(uid);
405 #endif
406+ /* should never happen */
407+ if (res < 0)
408+ Dprintf(L_FATAL, "auth_override_uid(%d) failed: %s",
409+ uid, strerror(errno));
410 }
411
412-#if defined(HAVE_SETFSUID) || defined(MAYBE_HAVE_SETFSUID)
413-static void
414+#if defined(HAVE_SETFSUID)
415+static int
416 setfsids(uid_t cred_uid, gid_t cred_gid, gid_t *cred_gids, int cred_len)
417 {
418 /* extension hooks: */
419@@ -238,43 +239,47 @@
420
421 /* First, set the user ID. */
422 if (auth_uid != cred_uid) {
423- if (setfsuid(cred_uid) < 0)
424+ if (setfsuid(cred_uid) < 0) {
425 Dprintf(L_ERROR, "Unable to setfsuid %d: %s\n",
426 cred_uid, strerror(errno));
427- else
428- auth_uid = cred_uid;
429+ return 0;
430+ }
431+ auth_uid = cred_uid;
432 }
433
434 /* Next, the group ID. */
435 if (auth_gid != cred_gid) {
436- if (setfsgid(cred_gid) < 0)
437+ if (setfsgid(cred_gid) < 0) {
438 Dprintf(L_ERROR, "Unable to setfsgid %d: %s\n",
439 cred_gid, strerror(errno));
440- else
441- auth_gid = cred_gid;
442+ return 0;
443+ }
444+ auth_gid = cred_gid;
445 }
446
447 #ifdef HAVE_SETGROUPS
448 /* Finally, set the supplementary group IDs if possible. */
449- if (cred_len < 0 || cred_len > NGRPS)
450+ if (cred_len < 0 || cred_len > NGRPS) {
451 Dprintf(L_ERROR, "Negative or huge cred_len: %d\n", cred_len);
452- else if (cred_len != auth_gidlen
453- || memcmp(cred_gids, auth_gids, auth_gidlen*sizeof(gid_t))) {
454- if (setgroups(cred_len, cred_gids) < 0)
455+ return 0;
456+ }
457+ if (cred_len != auth_gidlen
458+ || memcmp(cred_gids, auth_gids, auth_gidlen*sizeof(gid_t))) {
459+ if (setgroups(cred_len, cred_gids) < 0) {
460 Dprintf(L_ERROR, "Unable to setgroups: %s\n",
461 strerror(errno));
462- else {
463- memcpy(auth_gids, cred_gids, cred_len*sizeof(gid_t));
464- auth_gidlen = cred_len;
465+ return 0;
466 }
467+ memcpy(auth_gids, cred_gids, cred_len*sizeof(gid_t));
468+ auth_gidlen = cred_len;
469 }
470 #endif /* HAVE_SETGROUPS */
471-
472+ return 1;
473 }
474 #endif
475
476 #if !defined(HAVE_SETFSUID)
477-static void
478+static int
479 seteids(uid_t cred_uid, gid_t cred_gid, gid_t *cred_gids, int cred_len)
480 {
481 /* extension hooks: */
482@@ -286,52 +291,62 @@
483 /* First set the group ID. */
484 if (auth_gid != cred_gid) {
485 if (auth_uid != ROOT_UID) {
486- if (seteuid(ROOT_UID) < 0)
487+ if (seteuid(ROOT_UID) < 0) {
488 Dprintf(L_ERROR, "Unable to seteuid(%d): %s\n",
489 ROOT_UID, strerror(errno));
490- else
491- auth_uid = ROOT_UID;
492+ return 0;
493+ }
494+ auth_uid = ROOT_UID;
495 }
496- if (setegid(cred_gid) < 0)
497+ if (setegid(cred_gid) < 0) {
498 Dprintf(L_ERROR, "Unable to setegid(%d): %s\n",
499 cred_gid, strerror(errno));
500- else
501- auth_gid = cred_gid;
502+ return 0;
503+ }
504+ auth_gid = cred_gid;
505 }
506
507 #ifdef HAVE_SETGROUPS
508 /* Next set the supplementary group IDs if possible. */
509- if (cred_len < 0 || cred_len > NGRPS)
510+ if (cred_len < 0 || cred_len > NGRPS) {
511 Dprintf(L_ERROR, "Negative or huge cred_len: %d\n", cred_len);
512- else if (cred_len != auth_gidlen
513- || memcmp(cred_gids, auth_gids, auth_gidlen*sizeof(gid_t))) {
514+ return 0;
515+ }
516+ if (cred_len != auth_gidlen
517+ || memcmp(cred_gids, auth_gids, auth_gidlen*sizeof(gid_t))) {
518 if (auth_uid != ROOT_UID) {
519- if (seteuid(ROOT_UID) < 0)
520+ if (seteuid(ROOT_UID) < 0) {
521 Dprintf(L_ERROR, "Unable to seteuid(%d): %s\n",
522 ROOT_UID, strerror(errno));
523- else
524- auth_uid = ROOT_UID;
525+ return 0;
526+ }
527+ auth_uid = ROOT_UID;
528 }
529- if (setgroups(cred_len, cred_gids) < 0)
530+ if (setgroups(cred_len, cred_gids) < 0) {
531 Dprintf(L_ERROR, "Unable to setgroups: %s\n",
532 strerror(errno));
533- else {
534- memcpy(auth_gids, cred_gids, cred_len*sizeof(gid_t));
535- auth_gidlen = cred_len;
536+ return 0;
537 }
538+ memcpy(auth_gids, cred_gids, cred_len*sizeof(gid_t));
539+ auth_gidlen = cred_len;
540 }
541 #endif /* HAVE_SETGROUPS */
542
543 /* Finally, set the user ID. */
544 if (auth_uid != cred_uid) {
545- if (auth_uid != ROOT_UID && seteuid(ROOT_UID) < 0)
546+ if (auth_uid != ROOT_UID && seteuid(ROOT_UID) < 0) {
547 Dprintf(L_ERROR, "Unable to seteuid(%d): %s\n",
548 ROOT_UID, strerror(errno));
549- if (seteuid(cred_uid) < 0)
550+ return 0;
551+ }
552+ if (seteuid(cred_uid) < 0) {
553 Dprintf(L_ERROR, "Unable to seteuid(%d): %s\n",
554 cred_uid, strerror(errno));
555- else
556- auth_uid = cred_uid;
557+ return 0;
558+ }
559+ auth_uid = cred_uid;
560 }
561+
562+ return 1;
563 }
564 #endif
565diff -urN nfs-server-2.2beta47/auth_init.c nfs-server-2.2beta51/auth_init.c
566--- nfs-server-2.2beta47/auth_init.c Mon Apr 19 14:01:21 1999
567+++ nfs-server-2.2beta51/auth_init.c Fri Nov 8 14:45:36 2002
568@@ -13,7 +13,6 @@
569 */
570
571 #include "nfsd.h"
572-#include "fakefsuid.h"
573 #include <pwd.h>
574
575 #define LINE_SIZE 1024
576@@ -263,55 +262,63 @@
577 cp++;
578 while (*cp != terminator) {
579 kwd = cp;
580- while (isalpha(*cp) || *cp == '_' || *cp == '=') {
581- /* break out of loop after = sign */
582- if (*cp++ == '=')
583- break;
584- }
585+ /* Gobble up keyword and "=" if there is one */
586+ while (isalpha(*cp) || *cp == '_')
587+ ++cp;
588+ if (*cp == '=')
589+ ++cp;
590+
591 klen = cp - kwd;
592
593 /* process keyword */
594- if (strncmp(kwd, "secure", 6) == 0)
595+#define ifkwd(n, string) \
596+ if (klen == (n) && !strncmp(kwd, string, (n)))
597+
598+ ifkwd(2, "ro")
599+ mp->o.read_only = 1;
600+ else ifkwd(2, "rw")
601+ mp->o.read_only = 0;
602+ else ifkwd(6, "secure")
603 mp->o.secure_port = 1;
604- else if (strncmp(kwd, "insecure", 8) == 0)
605+ else ifkwd(8, "insecure")
606 mp->o.secure_port = 0;
607- else if (strncmp(kwd, "root_squash", 11) == 0)
608+ else ifkwd(11, "root_squash")
609 mp->o.root_squash = 1;
610- else if (strncmp(kwd, "no_root_squash", 14) == 0)
611+ else ifkwd(14, "no_root_squash")
612 mp->o.root_squash = 0;
613- else if (strncmp(kwd, "ro", 2) == 0)
614- mp->o.read_only = 1;
615- else if (strncmp(kwd, "rw", 2) == 0)
616- mp->o.read_only = 0;
617- else if (strncmp(kwd, "link_relative", 13) == 0)
618+ else ifkwd(13, "link_relative")
619 mp->o.link_relative = 1;
620- else if (strncmp(kwd, "link_absolute", 13) == 0)
621+ else ifkwd(13, "link_absolute")
622 mp->o.link_relative = 0;
623- else if (strncmp(kwd, "map_daemon", 10) == 0)
624+ else ifkwd(10, "map_daemon")
625 mp->o.uidmap = map_daemon;
626- else if (strncmp(kwd, "map_nis=", 8) == 0)
627+ else ifkwd(8, "map_nis=")
628 parse_nis_uidmap(mp, &cp);
629- else if (strncmp(kwd, "map_static=", 11) == 0)
630+ else ifkwd(11, "map_static=")
631 parse_static_uidmap(mp, &cp);
632- else if (strncmp(kwd, "map_identity", 12) == 0)
633+ else ifkwd(12, "map_identity")
634 mp->o.uidmap = identity;
635- else if (strncmp(kwd, "all_squash", 10) == 0)
636+ else ifkwd(10, "all_squash")
637 mp->o.all_squash = 1;
638- else if (strncmp(kwd, "no_all_squash", 13) == 0)
639+ else ifkwd(13, "no_all_squash")
640 mp->o.all_squash = 0;
641- else if (strncmp(kwd, "noaccess", 8) == 0)
642+ else ifkwd(8, "noaccess")
643 mp->o.noaccess = 1;
644- else if (strncmp(kwd, "squash_uids=", 12) == 0)
645+ else ifkwd(12, "squash_uids=")
646 parse_squash(mp, 1, &cp);
647- else if (strncmp(kwd, "squash_gids=", 12) == 0)
648+ else ifkwd(12, "squash_gids=")
649 parse_squash(mp, 0, &cp);
650- else if (strncmp(kwd, "anonuid=", 8) == 0)
651+ else ifkwd(8, "anonuid=")
652 mp->o.nobody_uid = parse_num(&cp);
653- else if (strncmp(kwd, "anongid=", 8) == 0)
654+ else ifkwd(8, "anongid=")
655 mp->o.nobody_gid = parse_num(&cp);
656- else if (strncmp(kwd, "async", 5) == 0)
657+ else ifkwd(6, "setuid")
658+ mp->o.allow_setuid = 1;
659+ else ifkwd(8, "nosetuid")
660+ mp->o.allow_setuid = 0;
661+ else ifkwd(5, "async")
662 /* knfsd compatibility, ignore */;
663- else if (strncmp(kwd, "sync", 4) == 0)
664+ else ifkwd(4, "sync")
665 /* knfsd compatibility, ignore */;
666 else {
667 Dprintf(L_ERROR,
668@@ -566,11 +573,6 @@
669 auth_check_all_wildcards();
670 auth_sort_all_mountlists();
671 auth_log_all();
672-
673-#if defined(MAYBE_HAVE_SETFSUID) && !defined(HAVE_SETFSUID)
674- /* check if the a.out setfsuid syscall works on this machine */
675- have_setfsuid = (setfsuid(0) >= 0);
676-#endif
677
678 auth_initialized = 1;
679 }
680diff -urN nfs-server-2.2beta47/config.h.in nfs-server-2.2beta51/config.h.in
681--- nfs-server-2.2beta47/config.h.in Fri Jun 11 12:01:22 1999
682+++ nfs-server-2.2beta51/config.h.in Fri Nov 8 14:45:36 2002
683@@ -3,7 +3,7 @@
684 /* Define if on AIX 3.
685 System headers sometimes define this.
686 We just want to avoid a redefinition error message. */
687-#ifndef _ALL_SOURCE
688+#ifdef _ALL_SOURCE
689 #undef _ALL_SOURCE
690 #endif
691
692diff -urN nfs-server-2.2beta47/configure.in nfs-server-2.2beta51/configure.in
693--- nfs-server-2.2beta47/configure.in Fri Jun 11 11:58:10 1999
694+++ nfs-server-2.2beta51/configure.in Fri Nov 8 14:45:36 2002
695@@ -2,7 +2,36 @@
696 dnl Updated for autoconf 2.
697 dnl
698 AC_INIT(nfsd.c)
699-AC_CONFIG_HEADER(config.h)
700+AC_CONFIG_HEADER(config.h site.h)
701+
702+dnl **************************************************************
703+dnl * handle --enable options
704+dnl **************************************************************
705+AC_ARG_ENABLE(new-inodes,
706+ [ --enable-new-inodes Enable new-style inode inodes])
707+AC_ARG_WITH(devtab,
708+ [ --with-devtab=file Specify location for devtab [/var/lib/nfs/devtab]],
709+ PATH_DEVTAB=$withval,
710+ PATH_DEVTAB=/var/lib/nfs/devtab)
711+AC_ARG_ENABLE(ugid-dynamic,
712+ [ --enable-ugid-dynamic Enable uid mapping using rpc.ugidd (not recommended)])
713+AC_ARG_ENABLE(ugid-nis,
714+ [ --enable-ugid-nis Enable NIS-based uid mapping])
715+AC_ARG_ENABLE(host-access,
716+ [ --enable-host-access Enable host access checking])
717+AC_ARG_ENABLE(mount-logging,
718+ [ --disable-mount-logging Do not log mount operations to syslog],,
719+ enable_mount_logging=yes)
720+AC_ARG_WITH(exports-uid,
721+ [ --with-exports-uid=N Make sure that /etc/exports is owned by uid N],,
722+ with_exports_uid=0)
723+AC_ARG_WITH(exports-gid,
724+ [ --with-exports-gid=N Make sure that /etc/exports is owned by gid N],,
725+ with_exports_gid=0)
726+
727+dnl **************************************************************
728+dnl * Check for all kinds of stuff
729+dnl **************************************************************
730 AC_PROG_CC
731 # If we're using gcc, we want warning flags
732 test -n "$GCC" &&
733@@ -19,7 +48,7 @@
734 AC_MINIX
735 AC_ISC_POSIX
736 AC_PROG_INSTALL
737-AC_CROSS_CHECK
738+dnl AC_CROSS_CHECK
739 AC_STDC_HEADERS
740 AC_GNULIBC
741 AC_CONST
742@@ -52,14 +81,45 @@
743 AC_CHECK_LIB(rpc, main)
744 AC_CHECK_LIB(crypt, main)
745 AC_CHECK_LIB(nys, main)
746-AC_REPLACE_FUNCS(strerror realpath mkdir rename utimes strdup strstr getopt getopt_long)
747 AC_HAVE_FUNCS(getcwd seteuid setreuid getdtablesize setgroups lchown setsid setfsuid setfsgid innetgr quotactl authdes_getucred)
748 AC_AUTHDES_GETUCRED
749 AC_BROKEN_SETFSUID
750 AC_MOUNTLIST
751 AC_FSUSAGE
752+AC_CHECK_LIB(wrap, main)
753 AC_LIBWRAP_BUG
754 AC_BSD_SIGNALS
755+
756+dnl **************************************************************
757+dnl * Munge user specified options
758+dnl **************************************************************
759+if test "$enable_new_inodes" = yes; then
760+ AC_DEFINE(ENABLE_DEVTAB)
761+fi
762+if test "$enable_ugid_dynamic" = yes; then
763+ AC_DEFINE(ENABLE_UGID_DAEMON)
764+ UGIDD_PROG=\${rpcprefix}.ugidd
765+ UGIDD_MAN=ugidd
766+fi
767+if test "$enable_ugid_nis" = yes; then
768+ AC_DEFINE(ENABLE_UGID_NIS)
769+fi
770+if test "$enable_host_access" = yes; then
771+ AC_DEFINE(HOSTS_ACCESS)
772+fi
773+if test "$enable_mount_logging" = yes; then
774+ AC_DEFINE(WANT_LOG_MOUNTS)
775+fi
776+AC_DEFINE_UNQUOTED(EXPORTSOWNERUID, $with_exports_uid)
777+AC_DEFINE_UNQUOTED(EXPORTSOWNERGID, $with_exports_gid)
778+AC_SUBST(PATH_DEVTAB)
779+AC_SUBST(UGIDD_PROG)
780+AC_SUBST(UGIDD_MAN)
781+
782+dnl **************************************************************
783+dnl * Output CFLAGS and LDFLAGS
784+dnl **************************************************************
785 AC_SUBST(LDFLAGS)
786 AC_SUBST(CFLAGS)
787+
788 AC_OUTPUT(Makefile)
789diff -urN nfs-server-2.2beta47/daemon.c nfs-server-2.2beta51/daemon.c
790--- nfs-server-2.2beta47/daemon.c Thu Jan 1 01:00:00 1970
791+++ nfs-server-2.2beta51/daemon.c Fri Nov 8 14:45:52 2002
792@@ -0,0 +1,270 @@
793+/*
794+ * daemon.c
795+ *
796+ * Copyright (C) 1998, <okir@monad.swb.de>
797+ *
798+ * Implements common daemon stuff and
799+ * fail-safe mode for nfsd/mountd.
800+ */
801+
802+#include "system.h"
803+#include "logging.h"
804+#include "signals.h"
805+#include <sys/wait.h>
806+
807+static const char * pidfilename = 0;
808+static const char * get_signame(int signo);
809+
810+/*
811+ * Do the Crawley Thing
812+ */
813+void
814+daemonize(void)
815+{
816+ int c;
817+
818+ /* Ignore SIGHUP so the parent can exit while we're still
819+ * in limbo */
820+ ignore_signal(SIGHUP);
821+
822+ /* Now fork */
823+ c = fork();
824+ if (c < 0)
825+ Dprintf(L_FATAL, "unable to fork: %s", strerror(errno));
826+
827+ /* Parent process: exit */
828+ if (c > 0)
829+ exit(0);
830+
831+ /* Do the session stuff */
832+ close(0);
833+ close(1);
834+ close(2);
835+#ifdef HAVE_SETSID
836+ setsid();
837+#else
838+ if ((c = open("/dev/tty", O_RDWR)) >= 0) {
839+ ioctl(c, TIOCNOTTY, (char *) NULL);
840+ close(c);
841+ }
842+#endif
843+
844+ /* Stop stderr logging */
845+ background_logging();
846+}
847+
848+void
849+setpidpath(const char *filename)
850+{
851+ pidfilename = filename;
852+}
853+
854+void
855+writepid(pid_t pid, int clear)
856+{
857+ FILE *fp;
858+
859+ fp = fopen(pidfilename, clear? "w" : "a");
860+ if (fp == NULL)
861+ Dprintf(L_FATAL, "Unable to open %s: %m", pidfilename);
862+ fprintf(fp, "%d\n", pid);
863+ fclose(fp);
864+ return;
865+}
866+
867+void
868+failsafe(int level, int ncopies)
869+{
870+ int *servers, running, child, i;
871+ int pid, signo, status;
872+ time_t last_restart = 0, now;
873+ int restarts = 0, backoff = 60;
874+
875+ servers = (int *) xmalloc(ncopies * sizeof(int));
876+ memset(servers, 0, ncopies * sizeof(int));
877+
878+ /* Loop forever, until we get SIGTERM */
879+ running = 0;
880+ while (1) {
881+ /* Rewrite the pidfile */
882+ writepid(getpid(), 1);
883+ for (i = 0; i < ncopies; i++) {
884+ if (servers[i] != 0)
885+ writepid(servers[i], 0);
886+ }
887+
888+ while (running < ncopies) {
889+ if ((now = time(NULL)) == last_restart) {
890+ if (++restarts > 2 * ncopies) {
891+ Dprintf(L_ERROR,
892+ "Servers restarting too "
893+ "quickly, backing off.");
894+ if (backoff < 60 * 60)
895+ backoff <<= 1;
896+ sleep(backoff);
897+ }
898+ } else {
899+ last_restart = now;
900+ restarts = 0;
901+ backoff = 60;
902+ }
903+
904+ /* Locate a free pid slot */
905+ for (i = 0, child = -1; i < ncopies; i++) {
906+ if (servers[i] == 0) {
907+ child = i;
908+ break;
909+ }
910+ }
911+
912+ if (child < 0)
913+ Dprintf(L_FATAL, "failsafe: no pid slot?!");
914+
915+ Dprintf(D_GENERAL,
916+ "starting server thread %d...\n", child + 1);
917+
918+ pid = fork();
919+ if (pid < 0)
920+ Dprintf(L_FATAL,
921+ "Unable to fork for failsafe: %s",
922+ strerror(errno));
923+
924+ if (pid == 0) {
925+ /* Child process: continue with execution. */
926+ return;
927+ }
928+
929+ writepid(pid, 0);
930+ servers[child] = pid;
931+ running++;
932+ }
933+
934+ /* Ignore some signals */
935+ ignore_signal(SIGTERM);
936+ ignore_signal(SIGHUP);
937+ ignore_signal(SIGINT);
938+ ignore_signal(SIGCHLD);
939+
940+ if ((pid = wait(&status)) < 0) {
941+ Dprintf((errno == ECHILD)? L_FATAL : L_WARNING,
942+ "failsafe: wait(): %s", strerror(errno));
943+ continue;
944+ }
945+
946+ /* Locate the child */
947+ for (i = 0, child = -1; i < ncopies; i++) {
948+ if (servers[i] == pid) {
949+ child = i;
950+ break;
951+ }
952+ }
953+
954+ if (child < 0) {
955+ Dprintf(L_WARNING,
956+ "failsafe: unknown child (pid %d) terminated",
957+ pid);
958+ continue;
959+ }
960+
961+ /* Book-keeping */
962+ servers[child] = 0;
963+ running--;
964+
965+ if (WIFSIGNALED(status)) {
966+ signo = WTERMSIG(status);
967+ if (signo == SIGTERM) {
968+ Dprintf(L_NOTICE, "failsafe: "
969+ "child %d terminated by SIGTERM. %s.",
970+ pid, running? "Continue" : "Exit");
971+ } else {
972+ Dprintf(L_WARNING, "failsafe: "
973+ "child %d terminated by %s. "
974+ "Restarting.",
975+ pid, get_signame(signo));
976+ child = -1; /* Restart */
977+ }
978+ } else if (WIFEXITED(status)) {
979+ Dprintf(L_NOTICE, "failsafe: "
980+ "child %d exited, status %d.",
981+ pid, WEXITSTATUS(status));
982+ } else {
983+ Dprintf(L_ERROR, "failsafe: "
984+ "abnormal child termination, "
985+ "pid=%d status=%d. Restarting.",
986+ pid, status);
987+ child = -1; /* Restart */
988+ }
989+
990+ /* If child >= 0, we should not restart */
991+ if (child >= 0) {
992+ if (!running) {
993+ Dprintf(D_GENERAL,
994+ "No more children, exiting.");
995+ exit(0);
996+ }
997+ for (i = child; i < ncopies-1; i++)
998+ servers[i] = servers[i+1];
999+ ncopies--; /* Make sure we start no new servers */
1000+ }
1001+ }
1002+}
1003+
1004+/*
1005+ * Failsafe session, catch core file.
1006+ *
1007+ * Not yet implemented.
1008+ * General outline: we need to fork first, because nfsd changes
1009+ * uids frequently, and the kernel won't write out a core file after
1010+ * that. The forked proc starts out with a clean dumpable flag though.
1011+ *
1012+ * After the fork, we might want to make sure we end up in some common
1013+ * directory that the failsafe loop knows about.
1014+ */
1015+void
1016+failsafe_loop(int level, void (*function)(void))
1017+{
1018+ /* NOP */
1019+}
1020+
1021+static const char *
1022+get_signame(int signo)
1023+{
1024+ static char namebuf[30];
1025+
1026+ switch (signo) {
1027+ case SIGHUP: return "SIGHUP";
1028+ case SIGINT: return "SIGINT";
1029+ case SIGQUIT: return "SIGQUIT";
1030+ case SIGILL: return "SIGILL";
1031+ case SIGTRAP: return "SIGTRAP";
1032+ case SIGIOT: return "SIGIOT";
1033+ case SIGBUS: return "SIGBUS";
1034+ case SIGFPE: return "SIGFPE";
1035+ case SIGKILL: return "SIGKILL";
1036+ case SIGUSR1: return "SIGUSR1";
1037+ case SIGSEGV: return "SIGSEGV";
1038+ case SIGUSR2: return "SIGUSR2";
1039+ case SIGPIPE: return "SIGPIPE";
1040+ case SIGALRM: return "SIGALRM";
1041+ case SIGTERM: return "SIGTERM";
1042+ case SIGCHLD: return "SIGCHLD";
1043+ case SIGCONT: return "SIGCONT";
1044+ case SIGSTOP: return "SIGSTOP";
1045+ case SIGTSTP: return "SIGTSTP";
1046+ case SIGTTIN: return "SIGTTIN";
1047+ case SIGTTOU: return "SIGTTOU";
1048+ case SIGURG: return "SIGURG";
1049+ case SIGXCPU: return "SIGXCPU";
1050+ case SIGXFSZ: return "SIGXFSZ";
1051+ case SIGVTALRM: return "SIGVTALRM";
1052+ case SIGPROF: return "SIGPROF";
1053+ case SIGWINCH: return "SIGWINCH";
1054+ case SIGIO: return "SIGIO";
1055+#ifdef SIGPWR
1056+ case SIGPWR: return "SIGPWR";
1057+#endif
1058+ }
1059+
1060+ sprintf(namebuf, "signal #%d", signo);
1061+ return namebuf;
1062+}
1063diff -urN nfs-server-2.2beta47/daemon.h nfs-server-2.2beta51/daemon.h
1064--- nfs-server-2.2beta47/daemon.h Thu Jan 1 01:00:00 1970
1065+++ nfs-server-2.2beta51/daemon.h Fri Nov 8 14:45:52 2002
1066@@ -0,0 +1,18 @@
1067+/*
1068+ * daemon.h
1069+ *
1070+ * Daemon support
1071+ */
1072+
1073+#ifndef CRAWLEY_H
1074+#define CRAWLEY_H
1075+
1076+#define _PATH_NFSD_PIDFILE "/var/run/nfsd.pid"
1077+#define _PATH_MOUNTD_PIDFILE "/var/run/mountd.pid"
1078+
1079+extern void daemonize(void);
1080+extern void setpidpath(const char *);
1081+extern void writepid(pid_t, int);
1082+extern void failsafe(int level, int ncopies);
1083+
1084+#endif /* CRAWLEY_H */
1085diff -urN nfs-server-2.2beta47/exports.man nfs-server-2.2beta51/exports.man
1086--- nfs-server-2.2beta47/exports.man Wed Nov 10 10:18:49 1999
1087+++ nfs-server-2.2beta51/exports.man Fri Nov 8 14:45:36 2002
1088@@ -45,6 +45,12 @@
1089 simultaneously. This is done by specifying an IP address and netmask pair
1090 as
1091 .IR address/netmask .
1092+.IP "world
1093+You can export a directory to the world (i.e. to all computers that
1094+are able to reach your NFS server network-wise) by using the empty
1095+hostname. When exporting to the world, the
1096+.BR root_squash ", " all_squash ", " ro " and " nosetuid
1097+options are turned on by default.
1098 .TP
1099 .B =public
1100 This is a special ``hostname'' that identifies the given directory name
1101@@ -81,6 +87,12 @@
1102 by using the
1103 .IR ro " option.
1104 .TP
1105+.I setuid
1106+This allows clients to assert the setuid and setgid bits on regular
1107+files. For non-anonymous exports, this option is on by default.
1108+For anonymous exports, the default is
1109+.IR nosetuid .
1110+.TP
1111 .I noaccess
1112 This makes everything below the directory inaccessible for the named
1113 client. This is useful when you want to export a directory hierarchy to
1114@@ -296,6 +308,22 @@
1115 .I /usr/X11R6
1116 entry apply. This is also true when the latter is a wildcard or netgroup
1117 entry.
1118+.PP
1119+You should also be careful about where you place spaces in the
1120+exports file. For instance, the following may appear as if you've
1121+exported
1122+.BR /pub " readonly to host " foozle ,
1123+but what this does in fact is export the directory to
1124+.B foozle
1125+with the default options,
1126+.I and
1127+export it to the world with the readonly option:
1128+.PP
1129+.nf
1130+.ta +3i
1131+# bad: export to the world
1132+/pub foozle (ro)
1133+.fi
1134 .SH FILES
1135 /etc/exports
1136 .SH DIAGNOSTICS
1137diff -urN nfs-server-2.2beta47/fh.c nfs-server-2.2beta51/fh.c
1138--- nfs-server-2.2beta47/fh.c Wed Nov 10 10:41:14 1999
1139+++ nfs-server-2.2beta51/fh.c Fri Nov 8 14:45:36 2002
1140@@ -95,17 +95,14 @@
1141 static int fh_list_size;
1142 static time_t curtime;
1143
1144-#ifndef FOPEN_MAX
1145-#define FOPEN_MAX 256
1146-#endif
1147-
1148 #ifndef FHTRACE
1149 #undef D_FHTRACE
1150 #define D_FHTRACE D_FHCACHE
1151 #endif
1152
1153-static fhcache * fd_cache[FOPEN_MAX] = { NULL };
1154+static fhcache ** fd_cache = NULL;
1155 static int fd_cache_size = 0;
1156+static int fd_cache_max = 0;
1157
1158 #ifndef NFSERR_INVAL /* that Sun forgot */
1159 #define NFSERR_INVAL 22
1160@@ -141,10 +138,13 @@
1161
1162 /* Forward declared local functions */
1163 static psi_t path_psi(char *, nfsstat *, struct stat *, int);
1164+static psi_t path_psi_m(char *, nfsstat *, struct stat *,
1165+ struct stat *, int);
1166 static int fh_flush_fds(void);
1167 static char * fh_dump(svc_fh *);
1168 static void fh_insert_fdcache(fhcache *fhc);
1169 static void fh_unlink_fdcache(fhcache *fhc);
1170+static void fh_complain(const char *msg, fhcache *fhc);
1171
1172 static void
1173 fh_move_to_front(fhcache *fhc)
1174@@ -192,6 +192,13 @@
1175 static void
1176 fh_insert_fdcache(fhcache *fhc)
1177 {
1178+#ifdef FHTRACE
1179+ Dprintf(D_FHTRACE, "insert fh %x into fdcache @%d\n", fhc->h.psi, fhc->fd);
1180+ if (fhc->fd < 0) {
1181+ fh_complain("fd cache bug: bad fd", fhc);
1182+ return;
1183+ }
1184+#endif
1185 if (fhc == fd_lru_head)
1186 return;
1187 if (fhc->fd_next || fhc->fd_prev)
1188@@ -203,9 +210,20 @@
1189 fhc->fd_next = fd_lru_head;
1190 fd_lru_head = fhc;
1191
1192+ if (fhc->fd >= fd_cache_max) {
1193+ int oldmax = fd_cache_max, newmax;
1194+
1195+ newmax = (fhc->fd + 8) & ~7;
1196+ fd_cache = (fhcache **) xrealloc(fd_cache, newmax * sizeof(fhcache *));
1197+ memset(fd_cache + oldmax, 0, (newmax - oldmax) * sizeof(fhcache *));
1198+ fd_cache_max = newmax;
1199+ }
1200+
1201 #ifdef FHTRACE
1202 if (fd_cache[fhc->fd] != NULL) {
1203- Dprintf(L_ERROR, "fd cache inconsistency!\n");
1204+ Dprintf(L_ERROR, "fd cache inconsistency (two fh's for same fd)");
1205+ fh_complain("new fh", fhc);
1206+ fh_complain("old fh", fd_cache[fhc->fd]);
1207 return;
1208 }
1209 #endif
1210@@ -225,7 +243,7 @@
1211 } else if (fd_lru_tail == fhc) {
1212 fd_lru_tail = prev;
1213 } else {
1214- Dprintf(L_ERROR, "fd cache inconsistency\n");
1215+ fh_complain("fd cache inconsistency (no next and not at tail)", fhc);
1216 return;
1217 }
1218 if (prev) {
1219@@ -233,13 +251,13 @@
1220 } else if (fd_lru_head == fhc) {
1221 fd_lru_head = next;
1222 } else {
1223- Dprintf(L_ERROR, "fd cache inconsistency\n");
1224+ fh_complain("fd cache inconsistency (no prev and not at head)", fhc);
1225 return;
1226 }
1227
1228 #ifdef FHTRACE
1229 if (fd_cache[fhc->fd] != fhc) {
1230- Dprintf(L_ERROR, "fd cache inconsistency!\n");
1231+ fh_complain("fd cache inconsistency (fd cache ptr mismatch)", fhc);
1232 return;
1233 }
1234 #endif
1235@@ -285,7 +303,7 @@
1236 hash_slot = &((*hash_slot)->hash_next);
1237 if (*hash_slot == NULL)
1238 Dprintf(L_ERROR,
1239- "internal inconsistency -- fhc(%x) not in hash table\n",
1240+ "internal inconsistency -- fhc(%x) not in hash table!\n",
1241 fhc);
1242 else
1243 *hash_slot = fhc->hash_next;
1244@@ -572,7 +590,7 @@
1245 efs_seekdir(dir, cookie_stack[i]);
1246 while ((dp = efs_readdir(dir))) {
1247 char *name = dp->d_name;
1248- int n = strlen(name);
1249+ int n = strlen(name); /* or: dp->d_reclen */
1250
1251 if (pathlen + n + 1 >= NFS_MAXPATHLEN
1252 || (name[0] == '.'
1253@@ -738,7 +756,16 @@
1254 static psi_t
1255 path_psi(char *path, nfsstat *status, struct stat *sbp, int svalid)
1256 {
1257- struct stat sbuf;
1258+ struct stat smounted;
1259+
1260+ return path_psi_m(path, status, sbp, &smounted, svalid);
1261+}
1262+
1263+static psi_t
1264+path_psi_m(char *path, nfsstat *status,
1265+ struct stat *sbp, struct stat *mbp, int svalid)
1266+{
1267+ struct stat sbuf, ddbuf;
1268
1269 if (sbp == NULL)
1270 sbp = &sbuf;
1271@@ -746,10 +773,10 @@
1272 *status = nfs_errno();
1273 return (0);
1274 }
1275+ *mbp = *sbp;
1276 if (S_ISDIR(sbp->st_mode) && strcmp(path, "/") != 0) {
1277 /* Special case for directories--test for mount point. */
1278- struct stat ddbuf;
1279- char *fname;
1280+ char *fname;
1281
1282 /* Find start of last component of path. */
1283 #if 1
1284@@ -819,6 +846,19 @@
1285 return (pseudo_inode(sbp->st_ino, sbp->st_dev));
1286 }
1287
1288+/*
1289+ * Match attributes to make sure we're still referring to the original file
1290+ */
1291+static inline int
1292+fh_attrmatch(struct fhcache *fhc, struct stat *attr)
1293+{
1294+ if (fhc->dev == attr->st_dev
1295+ && fhc->ino == attr->st_ino
1296+ && fhc->type == (attr->st_mode & S_IFMT))
1297+ return 1;
1298+ return 0;
1299+}
1300+
1301 fhcache *
1302 fh_find(svc_fh *h, int mode)
1303 {
1304@@ -838,6 +878,9 @@
1305 ex_state = active;
1306 time(&curtime);
1307 while ((fhc = fh_lookup(h->psi)) != NULL) {
1308+ struct stat sbuf, *s = NULL;
1309+ nfsstat dummy;
1310+
1311 Dprintf(D_FHCACHE, "fh_find: psi=%lx... found '%s', fd=%d\n",
1312 (unsigned long) h->psi,
1313 fhc->path ? fhc->path : "<unnamed>",
1314@@ -857,33 +900,27 @@
1315 * If it doesn't try to rebuild the path.
1316 */
1317 if (check) {
1318- struct stat *s = &fhc->attrs;
1319- psi_t psi;
1320- nfsstat dummy;
1321-
1322+ s = &sbuf;
1323 if (efs_lstat(fhc->path, s) < 0) {
1324 Dprintf(D_FHTRACE,
1325 "fh_find: stale fh: lstat: %m\n");
1326 } else {
1327- fhc->flags |= FHC_ATTRVALID;
1328- /* If pseudo-inos don't match, we fhc->path
1329- * may be a mount point (hence lstat() returns
1330+ /* If device/ino don't match, fhc->path may
1331+ * be a mount point (hence lstat() returns
1332 * a different inode number than the readdir()
1333 * stuff used in path_psi)
1334 */
1335- psi = pseudo_inode(s->st_ino, s->st_dev);
1336- if (h->psi == psi)
1337+ if (fh_attrmatch(fhc, s))
1338 goto fh_return;
1339
1340- /* Try again by computing the path psi */
1341- psi = path_psi(fhc->path, &dummy, s, 1);
1342- if (h->psi == psi)
1343+ /* Get the dev/ino of the underlying
1344+ * mount point. */
1345+ path_psi(fhc->path, &dummy, s, 1);
1346+ if (fh_attrmatch(fhc, s))
1347 goto fh_return;
1348
1349- Dprintf(D_FHTRACE, "fh_find: stale fh: "
1350- "dev/ino %x/%lx psi %lx",
1351- s->st_dev, s->st_ino,
1352- (unsigned long) psi);
1353+ Dprintf(D_FHTRACE, "fh_find: stale fh: %lx",
1354+ (unsigned long) h->psi);
1355 }
1356
1357 fh_discard:
1358@@ -896,6 +933,12 @@
1359 }
1360
1361 fh_return:
1362+ /* Valid attributes; cache them */
1363+ if (s != NULL) {
1364+ memcpy(&fhc->attrs, s, sizeof(*s));
1365+ fhc->flags |= FHC_ATTRVALID;
1366+ }
1367+
1368 /* The cached fh seems valid */
1369 if (fhc != fh_head.next)
1370 fh_move_to_front(fhc);
1371@@ -905,7 +948,8 @@
1372 }
1373
1374 Dprintf(D_FHCACHE, "fh_find: psi=%lx... not found\n",
1375- (unsigned long) h->psi);
1376+ (unsigned long) h->psi);
1377+
1378 if (mode == FHFIND_FCACHED) {
1379 ex_state = inactive;
1380 return NULL;
1381@@ -918,6 +962,7 @@
1382 fhc = flush->prev;
1383 fh_delete(flush);
1384 }
1385+
1386 fhc = (fhcache *) xmalloc(sizeof *fhc);
1387 if (mode == FHFIND_FCREATE) {
1388 /* File will be created */
1389@@ -937,11 +982,31 @@
1390 }
1391 fhc->path = path;
1392 }
1393+
1394 fhc->flags = 0;
1395 if (fhc->path && efs_lstat(fhc->path, &fhc->attrs) >= 0) {
1396- if (re_export && nfsmounted(fhc->path, &fhc->attrs))
1397+ if (nfsmounted(fhc->path, &fhc->attrs)) {
1398 fhc->flags |= FHC_NFSMOUNTED;
1399+#if 0
1400+ /* We must allow the client to send us the
1401+ * file handle for the NFS mount point itself,
1402+ * but not for entries within an NFS mount.
1403+ * XXX: needs fixing.
1404+ */
1405+ if (!re_export) {
1406+ Dprintf(D_FHTRACE,
1407+ "Attempt to use %s (non-exportable)\n",
1408+ fhc->path);
1409+ free(fhc);
1410+ ex_state = inactive;
1411+ return NULL;
1412+ }
1413+#endif
1414+ }
1415 fhc->flags |= FHC_ATTRVALID;
1416+ fhc->dev = fhc->attrs.st_dev;
1417+ fhc->ino = fhc->attrs.st_ino;
1418+ fhc->type = fhc->attrs.st_mode & S_IFMT;
1419 }
1420 fhc->fd = -1;
1421 fhc->last_used = curtime;
1422@@ -993,6 +1058,14 @@
1423 return buf;
1424 }
1425
1426+static void
1427+fh_complain(const char *msg, fhcache *fhc)
1428+{
1429+ Dprintf(L_ERROR, "%s: ptr=%p fd=%d path=%s\n", msg,
1430+ fhc, fhc->fd,
1431+ fhc->path? fhc->path : "<unnamed>");
1432+}
1433+
1434 /*
1435 * This routine is only used by the mount daemon.
1436 * It creates the initial file handle.
1437@@ -1000,23 +1073,25 @@
1438 int
1439 fh_create(nfs_fh *fh, char *path)
1440 {
1441- svc_fh key;
1442- fhcache *h;
1443- psi_t psi;
1444- nfsstat status;
1445- char *s;
1446+ struct stat stb;
1447+ svc_fh key;
1448+ fhcache *h;
1449+ psi_t psi;
1450+ nfsstat status;
1451+ char *s;
1452
1453 memset(&key, 0, sizeof(key));
1454 status = NFS_OK;
1455- if ((psi = path_psi("/", &status, NULL, 0)) == 0)
1456+ if ((psi = path_psi("/", &status, &stb, 0)) == 0)
1457 return ((int) status);
1458+
1459 s = path;
1460 while ((s = strchr(s + 1, '/')) != NULL) {
1461 if (++(key.hash_path[0]) >= HP_LEN)
1462 return ((int) NFSERR_NAMETOOLONG);
1463 key.hash_path[key.hash_path[0]] = hash_psi(psi);
1464 *s = '\0';
1465- if ((psi = path_psi(path, &status, NULL, 0)) == 0)
1466+ if ((psi = path_psi(path, &status, &stb, 0)) == 0)
1467 return ((int) status);
1468 *s = '/';
1469 }
1470@@ -1024,7 +1099,7 @@
1471 if (++(key.hash_path[0]) >= HP_LEN)
1472 return ((int) NFSERR_NAMETOOLONG);
1473 key.hash_path[key.hash_path[0]] = hash_psi(psi);
1474- if ((psi = path_psi(path, &status, NULL, 0)) == 0)
1475+ if ((psi = path_psi(path, &status, &stb, 0)) == 0)
1476 return ((int) status);
1477 }
1478 key.psi = psi;
1479@@ -1037,9 +1112,12 @@
1480
1481 /* assert(h != NULL); */
1482 if (h->path == NULL) {
1483- h->fd = -1;
1484- h->path = xstrdup(path);
1485+ h->fd = -1;
1486+ h->path = xstrdup(path);
1487 h->flags = 0;
1488+ h->dev = stb.st_dev;
1489+ h->ino = stb.st_ino;
1490+ h->type = stb.st_mode & S_IFMT;
1491 }
1492 memcpy(fh, &key, sizeof(key));
1493 return ((int) status);
1494@@ -1064,6 +1142,44 @@
1495 return ((nfs_fh*)&(h->h));
1496 }
1497
1498+
1499+static inline int
1500+access_override(int omode, int perm, struct stat *buf)
1501+{
1502+ /* Be suspicous of flags, particularly O_CREAT/O_TRUNC. A previous
1503+ * comment said:
1504+ *
1505+ * "[Not checking this] would truncate read-only files on creat()
1506+ * calls. Of course, ftruncate(fd, 0) should still be legal for
1507+ * the user when the file was chmoded *after* opening it, but we
1508+ * have no way to tell, and a semi-succeding `cp foo readonly-file'
1509+ * is much more unintuitive and destructive than a failing
1510+ * ftruncate()."
1511+ */
1512+ if (omode & ~O_ACCMODE)
1513+ return 0;
1514+
1515+ /* Users can do anything to their own files. Harmless (since they
1516+ * could chown anyway), and helps to mask NFSes statelessness.
1517+ *
1518+ * (in passing, this also handles mode 0100 execution)
1519+ */
1520+ if (buf->st_uid == auth_uid)
1521+ return 1;
1522+
1523+ /* Henceforth, we are considering granting read access to facilitate
1524+ * exec access. This is read only */
1525+ if (omode != O_RDONLY)
1526+ return 0;
1527+
1528+ /* Mode 0110 execution */
1529+ if (buf->st_gid == auth_gid)
1530+ return (buf->st_mode & S_IXGRP) != 0;
1531+
1532+ /* Mode 0111 execution */
1533+ return (buf->st_mode & S_IXOTH) != 0;
1534+}
1535+
1536 int
1537 path_open(char *path, int omode, int perm)
1538 {
1539@@ -1113,30 +1229,15 @@
1540 * lishes two things: first, it gives the file owner r/w access to
1541 * the file whatever the permissions are, so that files are still
1542 * accessible after an fchown(fd, 0). The second part of the
1543- * condition allows read access to mode 0111 executables.
1544- *
1545- * The old conditon read like this:
1546- * if (fd < 0 && oerrno == EACCES) {
1547- * if (oerrno == EACCES && (buf.st_uid == auth_uid
1548- * || (omode == O_RDONLY && (buf.st_mode & S_IXOTH)))) {
1549- * override uid; etc...
1550- * }
1551- * }
1552- * This would truncate read-only files on creat() calls. Now
1553- * ftruncate(fd, 0) should still be legal for the user when the
1554- * file was chmoded *after* opening it, but we have no way to tell,
1555- * and a semi-succeding `cp foo readonly-file' is much more
1556- * unintuitive and destructive than a failing ftruncate().
1557+ * condition allows read access to `execute-only' files.
1558 */
1559- if (fd < 0 && oerrno == EACCES && !(omode & (O_CREAT|O_TRUNC))) {
1560- if ((buf.st_uid == auth_uid && (omode & O_ACCMODE) == omode)
1561- || ((buf.st_mode & S_IXOTH) && omode == O_RDONLY)) {
1562- auth_override_uid(ROOT_UID);
1563- fd = efs_open(path, omode, perm);
1564- oerrno = errno;
1565- auth_override_uid(auth_uid);
1566- }
1567+ if (fd < 0 && oerrno == EACCES && access_override(omode, perm, &buf)) {
1568+ auth_override_uid(ROOT_UID);
1569+ fd = efs_open(path, omode, perm);
1570+ oerrno = errno;
1571+ auth_override_uid(auth_uid);
1572 }
1573+
1574
1575 if (fd < 0) {
1576 Dprintf(D_FHCACHE,
1577@@ -1241,7 +1342,7 @@
1578 char *sindx;
1579 int is_dd;
1580 nfsstat ret;
1581- struct stat sbuf;
1582+ struct stat sbuf, smount;
1583 char pathbuf[PATH_MAX + NAME_MAX + 1], *fname;
1584
1585 /* should not happen */
1586@@ -1318,7 +1419,7 @@
1587
1588 *new_fh = dopa->dir;
1589 key = (svc_fh *) new_fh;
1590- if ((key->psi = path_psi(pathbuf, &ret, sbp, 0)) == 0)
1591+ if ((key->psi = path_psi_m(pathbuf, &ret, sbp, &smount, 0)) == 0)
1592 return (ret);
1593
1594 if (is_dd) {
1595@@ -1344,6 +1445,10 @@
1596 h->h.hash_path[0]);
1597 return NFSERR_STALE;
1598 }
1599+ if (sbp->st_dev != smount.st_dev) {
1600+ Dprintf(D_FHTRACE, "fh_compose: %s hit%s mount point\n",
1601+ pathbuf, nfsmounted(pathbuf, &smount)? " NFS" : "");
1602+ }
1603 #endif
1604
1605 /* New code added by Don Becker */
1606@@ -1356,7 +1461,8 @@
1607 if (!h) return NFSERR_STALE;
1608 #endif
1609 if (h->path)
1610- Dprintf(L_ERROR, "Internal inconsistency: double entry (path '%s', now '%s').\n",
1611+ Dprintf(L_ERROR,
1612+ "internal inconsistency: double entry (path '%s', now '%s').\n",
1613 h->path, pathbuf);
1614 }
1615 Dprintf(D_FHCACHE, "fh_compose: using handle %x ('%s', fd=%d)\n",
1616@@ -1365,9 +1471,18 @@
1617
1618 /* assert(h != NULL); */
1619 if (h->path == 0) {
1620- h->path = xstrdup(pathbuf);
1621+ h->path = xstrdup(pathbuf);
1622 h->flags = 0;
1623- if (!re_export && nfsmounted(pathbuf, sbp))
1624+ h->dev = sbp->st_dev;
1625+ h->ino = sbp->st_ino;
1626+ h->type = sbp->st_mode & S_IFMT;
1627+
1628+ /* Note: in the case of a mount point,
1629+ * sbp contains the stats of the mount point, while
1630+ * ddbuf has the dev/ino of the underlying directory
1631+ */
1632+ if (sbp->st_dev != smount.st_dev
1633+ && nfsmounted(pathbuf, &smount))
1634 h->flags |= FHC_NFSMOUNTED;
1635 #ifdef FHTRACE
1636 Dprintf(D_FHTRACE, "fh_compose: created handle %s\n", h->path);
1637diff -urN nfs-server-2.2beta47/fh.h nfs-server-2.2beta51/fh.h
1638--- nfs-server-2.2beta47/fh.h Mon Nov 23 12:15:43 1998
1639+++ nfs-server-2.2beta51/fh.h Fri Nov 8 14:45:36 2002
1640@@ -97,7 +97,13 @@
1641 struct fhcache * hash_next;
1642 struct fhcache * fd_next;
1643 struct fhcache * fd_prev;
1644+
1645+ /* These are fixed during the lifetime of this object */
1646 svc_fh h;
1647+ dev_t dev;
1648+ ino_t ino;
1649+ mode_t type; /* st_mode & S_IFMT */
1650+
1651 int fd;
1652 int omode;
1653 char * path;
1654diff -urN nfs-server-2.2beta47/getattr.c nfs-server-2.2beta51/getattr.c
1655--- nfs-server-2.2beta47/getattr.c Fri Oct 30 18:10:11 1998
1656+++ nfs-server-2.2beta51/getattr.c Fri Nov 8 14:45:36 2002
1657@@ -115,6 +115,16 @@
1658 attr->fsid = 1;
1659 attr->fileid = fh_psi((nfs_fh *)&(fhc->h));
1660 #endif
1661+
1662+ /* This may be needed by some Suns... testing */
1663+#define MINTIME (24 * 2600)
1664+ if (s->st_atime < MINTIME)
1665+ s->st_atime = MINTIME;
1666+ if (s->st_mtime < MINTIME)
1667+ s->st_mtime = MINTIME;
1668+ if (s->st_ctime < MINTIME)
1669+ s->st_ctime = MINTIME;
1670+
1671 attr->atime.seconds = s->st_atime;
1672 attr->atime.useconds = 0;
1673 attr->mtime.seconds = s->st_mtime;
1674diff -urN nfs-server-2.2beta47/logging.c nfs-server-2.2beta51/logging.c
1675--- nfs-server-2.2beta47/logging.c Fri Oct 30 17:11:22 1998
1676+++ nfs-server-2.2beta51/logging.c Fri Nov 8 14:45:36 2002
1677@@ -147,8 +147,9 @@
1678 (void) time(&now);
1679 tm = localtime(&now);
1680 fprintf(log_fp, "%s %02d/%02d/%02d %02d:%02d %s",
1681- log_name, tm->tm_mon + 1, tm->tm_mday, tm->tm_year,
1682- tm->tm_hour, tm->tm_min, buff);
1683+ log_name, tm->tm_mon + 1, tm->tm_mday,
1684+ tm->tm_year % 100,
1685+ tm->tm_hour, tm->tm_min, buff);
1686 if (strchr(buff, '\n') == NULL)
1687 fputc('\n', log_fp);
1688 }
1689@@ -182,7 +183,8 @@
1690 tm = localtime(&unix_cred->aup_time);
1691 snprintf(buffer + len, total - len,
1692 "%d/%d/%d %02d:%02d:%02d %s %d.%d",
1693- tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
1694+ tm->tm_year %100,
1695+ tm->tm_mon + 1, tm->tm_mday,
1696 tm->tm_hour, tm->tm_min, tm->tm_sec,
1697 unix_cred->aup_machname,
1698 unix_cred->aup_uid,
1699diff -urN nfs-server-2.2beta47/mountd.c nfs-server-2.2beta51/mountd.c
1700--- nfs-server-2.2beta47/mountd.c Wed Jun 2 14:10:33 1999
1701+++ nfs-server-2.2beta51/mountd.c Fri Nov 8 14:45:36 2002
1702@@ -32,7 +32,7 @@
1703 #include "rpcmisc.h"
1704 #include "rmtab.h"
1705 #include "haccess.h"
1706-#include "failsafe.h"
1707+#include "daemon.h"
1708 #include "signals.h"
1709 #include <rpc/pmap_clnt.h>
1710
1711@@ -44,6 +44,8 @@
1712 /*
1713 * Option table for mountd
1714 */
1715+#define OPT_NOTCP 300
1716+#define OPT_LOOPBACK 301
1717 static struct option longopts[] =
1718 {
1719 { "debug", required_argument, 0, 'd' },
1720@@ -56,6 +58,8 @@
1721 { "no-spoof-trace", 0, 0, 't' },
1722 { "version", 0, 0, 'v' },
1723 { "fail-safe", optional_argument, 0, 'z' },
1724+ { "no-tcp", 0, 0, OPT_NOTCP },
1725+ { "loopback-only", 0, 0, OPT_LOOPBACK },
1726
1727 { NULL, 0, 0, 0 }
1728 };
1729@@ -358,6 +362,12 @@
1730 break;
1731 case 0:
1732 break;
1733+ case OPT_NOTCP:
1734+ udp_only = 1;
1735+ break;
1736+ case OPT_LOOPBACK:
1737+ loopback_only = 1;
1738+ break;
1739 case '?':
1740 default:
1741 usage(stderr, 1);
1742@@ -384,38 +394,27 @@
1743 /* Create services and register with portmapper */
1744 rpc_init("mountd", MOUNTPROG, mountd_versions, mount_dispatch, port, 0);
1745
1746- if (!foreground && !_rpcpmstart) {
1747-#ifndef RPC_SVC_FG
1748- /* We first fork off a child. */
1749- if ((c = fork()) > 0)
1750- exit(0);
1751- if (c < 0) {
1752- Dprintf(L_FATAL, "mountd: cannot fork: %s\n",
1753- strerror(errno));
1754- }
1755- /* No more logging to stderr */
1756- background_logging();
1757+ if (_rpcpmstart) {
1758+ /* Always foreground mode */
1759+ foreground = 1;
1760
1761- /* Now we remove ourselves from the foreground. */
1762- (void) close(0);
1763- (void) close(1);
1764- (void) close(2);
1765-#ifdef TIOCNOTTY
1766- if ((c = open("/dev/tty", O_RDWR)) >= 0) {
1767- (void) ioctl(c, TIOCNOTTY, (char *) NULL);
1768- (void) close(c);
1769- }
1770-#else
1771- setsid();
1772-#endif
1773-#endif /* not RPC_SVC_FG */
1774+ /* ... but no logging */
1775+ background_logging();
1776 }
1777
1778+ /* Become a daemon */
1779+ if (!foreground)
1780+ daemonize();
1781+
1782 /* Initialize the FH module. */
1783 fh_init();
1784
1785 /* Initialize the AUTH module. */
1786 auth_init(auth_file);
1787+
1788+ /* Write pidfile */
1789+ setpidpath(_PATH_MOUNTD_PIDFILE);
1790+ writepid(getpid(), 1);
1791
1792 /* Failsafe mode */
1793 if (failsafe_level)
1794diff -urN nfs-server-2.2beta47/mountd.man nfs-server-2.2beta51/mountd.man
1795--- nfs-server-2.2beta47/mountd.man Wed Jun 2 14:12:21 1999
1796+++ nfs-server-2.2beta51/mountd.man Fri Nov 8 14:45:36 2002
1797@@ -14,6 +14,8 @@
1798 .B "[\ \-\-allow\-non\-root\ ]"
1799 .B "[\ \-\-re\-export\ ]"
1800 .B "[\ \-\-no\-spoof\-trace\ ]"
1801+.B "[\ \-\-no\-tcp ]"
1802+.B "[\ \-\-loopback\-only ]"
1803 .B "[\ \-\-version\ ]"
1804 .ad b
1805 .SH DESCRIPTION
1806@@ -123,6 +125,18 @@
1807 .TP
1808 .BR \-v " or " \-\-version
1809 Report the current version number of the program.
1810+.TP
1811+.BR \-\-no\-tcp
1812+Force
1813+.I mountd
1814+to register only the UDP transport, but no TCP.
1815+This is an experimental option.
1816+.TP
1817+.BR \-\-loopback\-only
1818+Force
1819+.I mountd
1820+to bind to the loopback interface.
1821+This is an experimental option.
1822 .SS Access Control
1823 For enhanced security, access to
1824 .I mountd
1825diff -urN nfs-server-2.2beta47/nfsd.c nfs-server-2.2beta51/nfsd.c
1826--- nfs-server-2.2beta47/nfsd.c Wed Nov 10 10:33:28 1999
1827+++ nfs-server-2.2beta51/nfsd.c Fri Nov 8 14:45:36 2002
1828@@ -21,7 +21,7 @@
1829 #include "getopt.h"
1830 #include "fsusage.h"
1831 #include "rpcmisc.h"
1832-#include "failsafe.h"
1833+#include "daemon.h"
1834 #include "signals.h"
1835 #ifdef __linux__ /* XXX - MvS: for UNIX sockets. */
1836 # include <sys/un.h>
1837@@ -30,7 +30,6 @@
1838 # include <syslog.h>
1839 #endif
1840
1841-#define MULTIPLE_SERVERS
1842
1843 /* Flags for auth_fh */
1844 #define CHK_READ 0
1845@@ -51,6 +50,8 @@
1846 /*
1847 * Option table
1848 */
1849+#define OPT_NOTCP 300
1850+#define OPT_LOOPBACK 301
1851 static struct option longopts[] = {
1852 { "auth-deamon", required_argument, 0, 'a' },
1853 { "debug", required_argument, 0, 'd' },
1854@@ -68,6 +69,9 @@
1855 { "version", 0, 0, 'v' },
1856 { "no-cross-mounts", 0, 0, 'x' },
1857 { "fail-safe", optional_argument, 0, 'z' },
1858+ { "no-tcp", 0, 0, OPT_NOTCP },
1859+ { "udp-only", 0, 0, OPT_NOTCP },
1860+ { "loopback-only", 0, 0, OPT_LOOPBACK },
1861
1862 { NULL, 0, 0, 0 }
1863 };
1864@@ -173,7 +177,10 @@
1865 return NULL;
1866 }
1867
1868- auth_user(nfsmount, rqstp);
1869+ if (!auth_user(nfsmount, rqstp)) {
1870+ *statp = NFSERR_ACCES;
1871+ return NULL;
1872+ }
1873
1874 *statp = NFS_OK;
1875 return fhc;
1876@@ -211,7 +218,11 @@
1877
1878 if ((nfsmount = auth_path(nfsclient, rqstp, path)) == NULL)
1879 return NFSERR_ACCES;
1880- auth_user(nfsmount, rqstp);
1881+
1882+ /* XXX: really need to call it again here?
1883+ * Already invoked in auth_fh */
1884+ if (!auth_user(nfsmount, rqstp))
1885+ return NFSERR_ACCES;
1886
1887 return (NFS_OK);
1888 }
1889@@ -575,7 +586,8 @@
1890 #endif
1891
1892 /* MvS: Some clients use chardev 0xFFFF for a FIFO. */
1893- if (S_ISCHR(argp->attributes.mode) && dev == 0xFFFF) {
1894+ if (S_ISCHR(argp->attributes.mode)
1895+ && (dev == 0xFFFF || dev == (dev_t) -1)) {
1896 is_borc = 0;
1897 dev = 0;
1898 argp->attributes.mode &= ~S_IFMT;
1899@@ -623,7 +635,7 @@
1900 flags = (argp->attributes.size == 0 ?
1901 CREATE_OMODE | O_TRUNC : CREATE_OMODE);
1902 if (!exists)
1903- flags |= O_CREAT;
1904+ flags |= O_CREAT|O_EXCL;
1905 tmpfd = path_open(pathbuf, flags,
1906 argp->attributes.mode & ~S_IFMT);
1907 if (tmpfd < 0)
1908@@ -965,9 +977,7 @@
1909 int nfsport = 0;
1910 int failsafe_level = 0;
1911 int c;
1912-#ifdef MULTIPLE_SERVERS
1913 int i, ncopies = 1;
1914-#endif
1915
1916 program_name = argv[0];
1917 chdir("/");
1918@@ -1031,12 +1041,17 @@
1919 break;
1920 case 0:
1921 break;
1922+ case OPT_NOTCP:
1923+ udp_only = 1;
1924+ break;
1925+ case OPT_LOOPBACK:
1926+ loopback_only = 1;
1927+ break;
1928 case '?':
1929 default:
1930 usage(stderr, 1);
1931 }
1932
1933-#ifdef MULTIPLE_SERVERS
1934 if (optind == argc-1 && isdigit(argv[optind][0])) {
1935 ncopies = atoi(argv[optind++]);
1936 if (ncopies <= 0) {
1937@@ -1051,7 +1066,6 @@
1938 ncopies = 1;
1939 }
1940 }
1941-#endif
1942
1943 /* No more arguments allowed. */
1944 if (optind != argc)
1945@@ -1075,72 +1089,54 @@
1946 rpc_init("nfsd", NFS_PROGRAM, nfsd_versions, nfs_dispatch,
1947 nfsport, NFS_MAXDATA);
1948
1949- /* No more than 1 copy when run from inetd */
1950- if (_rpcpmstart && ncopies > 1) {
1951- Dprintf(L_WARNING,
1952- "nfsd: warning: can run only "
1953- "one server in inetd mode\n");
1954- ncopies = 1;
1955+ if (_rpcpmstart) {
1956+ /* Always do foreground mode */
1957+ foreground = 1;
1958+
1959+ /* ... but don't log to stderr */
1960+ background_logging();
1961+
1962+ /* No more than 1 copy when run from inetd */
1963+ if (ncopies > 1) {
1964+ Dprintf(L_WARNING,
1965+ "nfsd: warning: can run only "
1966+ "one server in inetd mode\n");
1967+ ncopies = 1;
1968+ }
1969 }
1970
1971-#ifndef MULTIPLE_SERVERS_READWRITE
1972 if (ncopies > 1)
1973 read_only = 1;
1974-#endif
1975
1976- /* We first fork off a child. */
1977- if (!foreground) {
1978- if ((c = fork()) > 0)
1979- exit(0);
1980- if (c < 0) {
1981- Dprintf(L_FATAL, "nfsd: cannot fork: %s\n",
1982- strerror(errno));
1983- }
1984- }
1985+ /*
1986+ * We first fork off a child and detach from tty
1987+ */
1988+ if (!foreground)
1989+ daemonize();
1990
1991 /* Initialize the AUTH module. */
1992 auth_init(auth_file);
1993
1994+ setpidpath(_PATH_NFSD_PIDFILE);
1995 if (failsafe_level == 0) {
1996 /* Start multiple copies of the server */
1997+ writepid(getpid(), 1);
1998 for (i = 1; i < ncopies; i++) {
1999+ pid_t pid;
2000+
2001 Dprintf(D_GENERAL, "Forking server thread...\n");
2002- if ((c = fork()) < 0) {
2003+ if ((pid = fork()) < 0) {
2004 Dprintf(L_ERROR, "Unable to fork: %s",
2005 strerror(errno));
2006- } else if (c == 0) {
2007- /* Child process */
2008- break;
2009+ } else if (pid != 0) {
2010+ writepid(pid, 0);
2011+ } else {
2012+ break; /* Child process */
2013 }
2014 }
2015 } else {
2016 /* Init for failsafe mode */
2017 failsafe(failsafe_level, ncopies);
2018- }
2019-
2020- /* Now that we've done all the required forks, we make do all the
2021- * session magic.
2022- */
2023- if (!foreground) {
2024- /* No more logging to stderr */
2025- background_logging();
2026-
2027- /* Now we remove ourselves from the foreground. */
2028- close(0);
2029- close(1);
2030- close(2);
2031-#ifdef HAVE_SETSID
2032- setsid();
2033-#else
2034- {
2035- int fd;
2036-
2037- if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
2038- ioctl(fd, TIOCNOTTY, (char *) NULL);
2039- close(fd);
2040- }
2041- }
2042-#endif
2043 }
2044
2045 /*
2046diff -urN nfs-server-2.2beta47/nfsd.man nfs-server-2.2beta51/nfsd.man
2047--- nfs-server-2.2beta47/nfsd.man Wed Jun 2 14:13:37 1999
2048+++ nfs-server-2.2beta51/nfsd.man Fri Nov 8 14:45:36 2002
2049@@ -8,7 +8,7 @@
2050 .B "[\ \-d\ facility\ ]"
2051 .B "[\ \-P\ port\ ]"
2052 .B "[\ \-R\ dirname\ ]"
2053-.B "[\ \-Fhlnprstv\ ]"
2054+.B "[\ \-Fhlnprstuv\ ]"
2055 .B "[\ \-\-debug\ facility\ ]"
2056 .B "[\ \-\-exports\-file=file\ ]"
2057 .B "[\ \-\-foreground\ ]"
2058@@ -18,6 +18,8 @@
2059 .B "[\ \-\-public\-root\ dirname\ ]"
2060 .\".B "[\ \-\-synchronous\-writes\ ]"
2061 .B "[\ \-\-no\-spoof\-trace\ ]"
2062+.B "[\ \-\-no\-tcp ]"
2063+.B "[\ \-\-loopback-only ]"
2064 .B "[\ \-\-port\ port\ ]"
2065 .B "[\ \-\-log-transfers\ ]"
2066 .B "[\ \-\-version\ ]"
2067@@ -56,7 +58,7 @@
2068 .PP
2069 When run from
2070 .IR inetd ,
2071-.i nfsd
2072+.I nfsd
2073 will terminate after a certain period of inactivity.
2074 .SH OPTIONS
2075 .TP
2076@@ -167,6 +169,14 @@
2077 .BR \-v " or " \-\-version
2078 Report the current version number of the program.
2079 .TP
2080+.BR \-\-no\-tcp
2081+Force nfsd to only register a UDP transport, but not TCP.
2082+This is an experimental option.
2083+.TP
2084+.BR \-\-loopback\-only
2085+Force nfsd to bind to the loopback interface.
2086+This is an experimental option.
2087+.TP
2088 .BR numcopies
2089 This is an experimental feature that lets you run several instances of
2090 .I nfsd
2091@@ -174,15 +184,8 @@
2092 .B numcopies
2093 greater than one,
2094 .I nfsd
2095-will fork as many times as specified by this value.
2096-However, the servers do not share a common file handle
2097-cache, which makes certain file operations impossible.
2098-.IP
2099-For this reason,
2100-.I nfsd
2101-will disallow all write operations when invoked with this option. Although
2102-this is very limiting, this feature may still prove useful for exporting
2103-public FTP areas or Usenet News spools.
2104+will fork as many times as specified by this value so it is able to
2105+handle that many NFS requests in parallel.
2106 .SS WebNFS Support
2107 WebNFS is an extension to the normal NFS protocol developed by Sun
2108 that is particularly well-suited for file retrieval over the
2109@@ -268,6 +271,19 @@
2110 .I nfsd
2111 writes out a transfer record whenever it encounters a READ or WRITE
2112 request at offset zero.
2113+.SS Generating a debug trace
2114+When suspecting a bug in nfsd, it is helpful to look at a debug trace
2115+of what's going on. You can create such a trace by first killing nfsd,
2116+and then restarting it as
2117+.PP
2118+.nf
2119+.ta +3i
2120+/usr/sbin/rpc.nfsd -F -d all
2121+.fi
2122+.PP
2123+Instead of
2124+.BR all ,
2125+you can use less verbose debug facilities as described above.
2126 .SH "SEE ALSO"
2127 exports(5), mountd(8), ugidd(8C)
2128 .SH AUTHORS
2129diff -urN nfs-server-2.2beta47/rmtab.c nfs-server-2.2beta51/rmtab.c
2130--- nfs-server-2.2beta47/rmtab.c Fri Feb 6 09:43:25 1998
2131+++ nfs-server-2.2beta51/rmtab.c Fri Nov 8 14:45:36 2002
2132@@ -8,6 +8,7 @@
2133
2134 #include "nfsd.h"
2135 #include "rmtab.h"
2136+#include "rpcmisc.h"
2137
2138 static char * rmtab_gethost(struct svc_req *);
2139 static int rmtab_insert(char *, char *);
2140diff -urN nfs-server-2.2beta47/rpcmisc.c nfs-server-2.2beta51/rpcmisc.c
2141--- nfs-server-2.2beta47/rpcmisc.c Tue Sep 7 10:42:58 1999
2142+++ nfs-server-2.2beta51/rpcmisc.c Fri Nov 8 14:45:36 2002
2143@@ -39,6 +39,8 @@
2144 int _rpcfdtype = 0;
2145 int _rpcsvcdirty = 0;
2146 const char * auth_daemon = 0;
2147+int udp_only = 0;
2148+int loopback_only = 0;
2149
2150 #ifdef AUTH_DAEMON
2151 static bool_t (*tcp_rendevouser)(SVCXPRT *, struct rpc_msg *);
2152@@ -96,7 +98,7 @@
2153 }
2154 }
2155
2156- if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) {
2157+ if ((_rpcfdtype == 0 && !udp_only) || (_rpcfdtype == SOCK_STREAM)) {
2158 if (_rpcfdtype == 0 && defport != 0)
2159 sock = makesock(defport, IPPROTO_TCP, bufsiz);
2160 transp = svctcp_create(sock, 0, 0);
2161@@ -199,6 +201,9 @@
2162 sin.sin_family = AF_INET;
2163 sin.sin_addr.s_addr = INADDR_ANY;
2164 sin.sin_port = htons(port);
2165+
2166+ if (loopback_only)
2167+ sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
2168
2169 #ifdef DEBUG
2170 {
2171diff -urN nfs-server-2.2beta47/rpcmisc.h nfs-server-2.2beta51/rpcmisc.h
2172--- nfs-server-2.2beta47/rpcmisc.h Tue Sep 7 10:37:38 1999
2173+++ nfs-server-2.2beta51/rpcmisc.h Fri Nov 8 14:45:36 2002
2174@@ -9,6 +9,8 @@
2175 extern int _rpcpmstart;
2176 extern int _rpcfdtype;
2177 extern int _rpcsvcdirty;
2178+extern int udp_only;
2179+extern int loopback_only;
2180 extern const char * auth_daemon;
2181
2182 extern void rpc_init(const char *name, int prog, int *verstbl,
2183@@ -16,5 +18,13 @@
2184 int defport, int bufsize);
2185 extern void rpc_exit(int prog, int *verstbl);
2186 extern void rpc_closedown(void);
2187+
2188+/*
2189+ * Some older systems don't have svc_getcaller.
2190+ * Some, like glibc 2.2, have it but it returns some type that's
2191+ * not a sockaddr_in anymore.
2192+ */
2193+#undef svc_getcaller
2194+#define svc_getcaller(xprt) ((struct sockaddr_in *) (&(xprt)->xp_raddr))
2195
2196 #endif /* RPCMISC_H */
2197diff -urN nfs-server-2.2beta47/setattr.c nfs-server-2.2beta51/setattr.c
2198--- nfs-server-2.2beta47/setattr.c Fri Oct 30 18:29:42 1998
2199+++ nfs-server-2.2beta51/setattr.c Fri Nov 8 14:45:36 2002
2200@@ -103,6 +103,10 @@
2201 if (flags & SATTR_CHMOD) {
2202 unsigned int mode = attr->mode;
2203
2204+ /* If setuid is not allowed, silently squash them */
2205+ if (!nfsmount->o.allow_setuid && S_ISREG(s->st_mode))
2206+ mode &= ~(S_ISUID|S_ISGID) | s->st_mode;
2207+
2208 if (mode != -1 && mode != 0xFFFF /* ultrix bug */
2209 && (mode & 07777) != (s->st_mode & 07777)) {
2210 if (efs_chmod(path, mode) < 0)
2211diff -urN nfs-server-2.2beta47/showmount.c nfs-server-2.2beta51/showmount.c
2212--- nfs-server-2.2beta47/showmount.c Wed Jun 12 22:31:04 1996
2213+++ nfs-server-2.2beta51/showmount.c Fri Nov 8 14:45:36 2002
2214@@ -162,17 +162,13 @@
2215 break;
2216 }
2217
2218- if (hostname[0] >= '0' && hostname[0] <= '9') {
2219- server_addr.sin_family = AF_INET;
2220- server_addr.sin_addr.s_addr = inet_addr(hostname);
2221- }
2222- else {
2223+ server_addr.sin_family = AF_INET;
2224+ if (!inet_aton(hostname, &server_addr.sin_addr)) {
2225 if ((hp = gethostbyname(hostname)) == NULL) {
2226 fprintf(stderr, "%s: can't get address for %s\n",
2227 program_name, hostname);
2228 exit(1);
2229 }
2230- server_addr.sin_family = AF_INET;
2231 memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
2232 }
2233
2234diff -urN nfs-server-2.2beta47/site.h.in nfs-server-2.2beta51/site.h.in
2235--- nfs-server-2.2beta47/site.h.in Thu Jan 1 01:00:00 1970
2236+++ nfs-server-2.2beta51/site.h.in Fri Nov 8 14:45:57 2002
2237@@ -0,0 +1,50 @@
2238+/*
2239+ * Site-specific configuration options generated by BUILD.
2240+ * Please do not edit.
2241+ */
2242+
2243+/*
2244+ * If ENABLE_DEVTAB is defined, nfsd will use the new inode
2245+ * number generation scheme for avoiding inode number clashes
2246+ * on big hard disks.
2247+ */
2248+#undef ENABLE_DEVTAB
2249+
2250+/*
2251+ * If MULTIPLE_SERVER_READWRITE is defined, you will be able
2252+ * to run several nfsd process in parallel servicing all NFS
2253+ * requests.
2254+ */
2255+#define MULTIPLE_SERVERS_READWRITE
2256+
2257+/*
2258+ * If ENABLE_UGID_DAEMON is defined, the real rpc.ugidd is built,
2259+ * nfsd is built to support ugidd queries.
2260+ * Otherwise, a dummy program is created
2261+ */
2262+#undef ENABLE_UGID_DAEMON
2263+
2264+/*
2265+ * If ENABLE_UGID_NIS is defined, nfsd will support user mapping
2266+ * vie the client's NIS server.
2267+ */
2268+#undef ENABLE_UGID_NIS
2269+
2270+/*
2271+ * if HOSTS_ACCESS is defined, ugidd uses host access control
2272+ * provided by libwrap.a from tcp_wrappers
2273+ */
2274+#define HOSTS_ACCESS
2275+
2276+/*
2277+ * Define correct ownership of export control file
2278+ */
2279+#define EXPORTSOWNERUID 0
2280+#define EXPORTSOWNERGID 0
2281+
2282+/*
2283+ * If WANT_LOG_MOUNTS is defined, every mount request will be logged
2284+ * to syslogd with the name of source site and a path that was
2285+ * it requested
2286+ */
2287+#define WANT_LOG_MOUNTS
2288diff -urN nfs-server-2.2beta47/ugidd.c nfs-server-2.2beta51/ugidd.c
2289--- nfs-server-2.2beta47/ugidd.c Wed Dec 10 12:34:16 1997
2290+++ nfs-server-2.2beta51/ugidd.c Fri Nov 8 14:45:36 2002
2291@@ -43,9 +43,7 @@
2292 };
2293
2294 int
2295-main(argc, argv)
2296-int argc;
2297-char **argv;
2298+main(int argc, char **argv)
2299 {
2300 SVCXPRT *transp;
2301 int c, longind;
2302@@ -92,32 +90,11 @@
2303 exit(1);
2304 }
2305
2306- if (!foreground) {
2307- if ((c = fork()) > 0)
2308- exit(0);
2309- if (c < 0) {
2310- fprintf(stderr, "ugidd: cannot fork: %s\n",
2311- strerror(errno));
2312- exit(-1);
2313- }
2314- close(0);
2315- close(1);
2316- close(2);
2317-#ifdef HAVE_SETSID
2318- setsid();
2319-#else
2320- {
2321- int fd;
2322-
2323- if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
2324- ioctl(fd, TIOCNOTTY, (char *) NULL);
2325- close(fd);
2326- }
2327- }
2328-#endif
2329- }
2330-
2331 log_open("ugidd", foreground);
2332+
2333+ /* Become a daemon */
2334+ if (!foreground)
2335+ daemonize();
2336
2337 svc_run();
2338 Dprintf(L_ERROR, "svc_run returned\n");
2339diff -urN nfs-server-2.2beta47/version.c nfs-server-2.2beta51/version.c
2340--- nfs-server-2.2beta47/version.c Wed Nov 10 10:33:33 1999
2341+++ nfs-server-2.2beta51/version.c Fri Nov 8 14:45:36 2002
2342@@ -1 +1 @@
2343-char version[] = "Universal NFS Server 2.2beta47";
2344+char version[] = "Universal NFS Server 2.2beta51";