summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@linux.intel.com>2010-12-30 10:12:14 +0000
committerRichard Purdie <rpurdie@linux.intel.com>2010-12-30 10:12:14 +0000
commit59ad91a880695808c5b4efe88fa46286662e4cfc (patch)
tree52a40efec182c732157be1553609c9bb0d74892d /meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47
parentacf3b8e884657101b736d32f4216655b96659f49 (diff)
downloadpoky-59ad91a880695808c5b4efe88fa46286662e4cfc.tar.gz
unfs-server: Fix PV so it obeys the version number policy
Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47')
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/001-2.2b47-2.2b51.patch2344
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/002-destdir.patch68
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/003-manpages.patch28
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/004-strsignal.patch48
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/005-sys-time.patch29
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/006-reiserfs.patch1272
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/007-map.patch78
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/008-configure.patch13
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/009-multirw.patch15
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/010-realpath.patch30
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/011-fno-strict-aliasing.patch13
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/012-nostrip.patch13
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/013-mntpathlen.patch32
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/014-uninitialized.patch12
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/015-setattr.patch26
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/016-makefile.in.patch14
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/017-wrs-dynamic-rpc.patch258
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/018-remove-tcp-wrappers.patch20
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/019-pid-before-fork.patch125
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/020-undefined-chmod-fix.patch18
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/021-nolibwrap.patch20
-rw-r--r--meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/022-add-close-on-exec-descriptors.patch61
22 files changed, 4537 insertions, 0 deletions
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/001-2.2b47-2.2b51.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/001-2.2b47-2.2b51.patch
new file mode 100644
index 0000000000..886ce92b34
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+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";
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/002-destdir.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/002-destdir.patch
new file mode 100644
index 0000000000..9388332675
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/002-destdir.patch
@@ -0,0 +1,68 @@
1# Patch origin: nfs-server source RPM from openSUSE 10.3
2
3--- nfs-server/Makefile.in 2002/11/07 16:56:07 1.1
4+++ nfs-server/Makefile.in 2002/11/07 17:08:41
5@@ -74,10 +74,10 @@
6
7 bindir = $(exec_prefix)/sbin
8 #vardir = $(install_prefix)/var/lib/nfs
9-infodir = $(prefix)/info
10-man5dir = $(prefix)/man/man5
11+infodir = $(prefix)/share/info
12+man5dir = $(prefix)/share/man/man5
13 man5ext = .5
14-man8dir = $(prefix)/man/man8
15+man8dir = $(prefix)/share/man/man8
16 man8ext = .8
17
18 # Prefix to be prepended to each installed RPC program, normally `rpc.'.
19@@ -145,37 +145,37 @@
20 .PHONY: install installdirs
21 install: $(DAEMONS) $(CLIENTS) installdirs
22 @for prog in $(DAEMONS) $(CLIENTS); do \
23- echo "installing $$prog in $(bindir)"; \
24- $(INSTALL_PROGRAM) $$prog $(bindir)/$$prog; \
25+ echo "installing $$prog in $(DESTDIR)$(bindir)"; \
26+ $(INSTALL_PROGRAM) $$prog $(DESTDIR)$(bindir)/$$prog; \
27 done
28 @for manp in $(MANPAGES5); do \
29- echo "installing $$manp$(man5ext) in $(man5dir)"; \
30+ echo "installing $$manp$(man5ext) in $(DESTDIR)$(man5dir)"; \
31 $(INSTALL_DATA) $(srcdir)/$$manp.man \
32- $(man5dir)/$$manp$(man5ext); \
33+ $(DESTDIR)$(man5dir)/$$manp$(man5ext); \
34 done
35 @for manp in $(MANPAGES8p); do \
36- echo "installing $$manp$(man8ext) in $(man8dir)"; \
37+ echo "installing $$manp$(man8ext) in $(DESTDIR)$(man8dir)"; \
38 $(INSTALL_DATA) $(srcdir)/$$manp.man \
39- $(man8dir)/$$manp$(man8ext); \
40+ $(DESTDIR)$(man8dir)/$$manp$(man8ext); \
41 if [ 'x$(rpcprefix)' != 'x' ]; then \
42 rm -f $(man8dir)/$(rpcprefix)$$manp$(man8ext); \
43 ln -s $$manp$(man8ext) \
44- $(man8dir)/$(rpcprefix)$$manp$(man8ext); \
45+ $(DESTDIR)$(man8dir)/$(rpcprefix)$$manp$(man8ext); \
46 fi; \
47 done
48 @for manp in $(MANPAGES8); do \
49- echo "installing $$manp$(man8ext) in $(man8dir)"; \
50+ echo "installing $$manp$(man8ext) in $(DESTDIR)$(man8dir)"; \
51 $(INSTALL_DATA) $(srcdir)/$$manp.man \
52- $(man8dir)/$$manp$(man8ext); \
53+ $(DESTDIR)$(man8dir)/$$manp$(man8ext); \
54 done
55 @if [ -n "$(DEVTAB_FILE)" -a ! -f "$(DEVTAB_FILE)" ]; then \
56 echo "Initializing $(DEVTAB_FILE)"; \
57- $(INSTALL) -m 755 -d `dirname $(DEVTAB_FILE)`; \
58- echo "# Device mapping for unfsd" > "$(DEVTAB_FILE)"; \
59+ $(INSTALL) -m 755 -d `dirname $(DESTDIR)$(DEVTAB_FILE)`; \
60+ echo "# Device mapping for unfsd" > $(DESTDIR)"$(DEVTAB_FILE)"; \
61 fi
62
63 installdirs:
64- ${srcdir}/mkinstalldirs $(bindir) $(man5dir) $(man8dir)
65+ ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(man5dir) $(DESTDIR)$(man8dir)
66
67 $(rpcprefix)mountd: $(MOUNTD_OBJS) libnfs.a
68 $(CC) $(LDFLAGS) -o $@ $(MOUNTD_OBJS) $(LIBS)
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/003-manpages.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/003-manpages.patch
new file mode 100644
index 0000000000..a17a8dcf55
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/003-manpages.patch
@@ -0,0 +1,28 @@
1# Patch origin: nfs-server source RPM from openSUSE 10.3
2
3--- nfs-server/exports.man 2002/11/07 17:15:59 1.1
4+++ nfs-server/exports.man 2002/11/07 17:17:19
5@@ -110,6 +110,14 @@
6 .TP
7 .IR link_absolute
8 Leave all symbolic link as they are. This is the default operation.
9+.SS Anonymous Entries
10+.PP
11+Entries where hosts are not specified are known as anonymous entries. They
12+have different default settings compared to normal entries. The differences
13+include
14+.IR all_squash ,
15+.IR no_secure ", and"
16+.IR ro .
17 .SS User ID Mapping
18 .PP
19 .I nfsd
20@@ -231,7 +239,7 @@
21 # Mapping for client foobar:
22 # remote local
23 uid 0-99 - # squash these
24-uid 100-500 1000 # map 100-500 to 1000-1500
25+uid 100-500 1000 # map 100-500 to 1000-1400
26 gid 0-49 - # squash these
27 gid 50-100 700 # map 50-100 to 700-750
28 .fi
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/004-strsignal.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/004-strsignal.patch
new file mode 100644
index 0000000000..3ac4ed740c
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/004-strsignal.patch
@@ -0,0 +1,48 @@
1# Patch origin: nfs-server source RPM from openSUSE 10.3
2
3--- nfs-server/failsafe.c 2002/11/07 17:12:46 1.1
4+++ nfs-server/failsafe.c 2002/11/07 17:15:16
5@@ -10,8 +10,12 @@
6 #include "logging.h"
7 #include "signals.h"
8 #include <sys/wait.h>
9+#ifdef HAVE_STRSIGNAL
10+#include <string.h>
11+#else
12
13 static const char * get_signame(int signo);
14+#endif
15
16 void
17 failsafe(int level, int ncopies)
18@@ -111,9 +115,17 @@
19 pid, running? "Continue" : "Exit");
20 } else {
21 Dprintf(L_WARNING, "failsafe: "
22+#ifdef HAVE_STRSIGNAL
23+ "child %d terminated by: %s. "
24+#else
25 "child %d terminated by %s. "
26+#endif
27 "Restarting.",
28+#ifdef HAVE_STRSIGNAL
29+ pid, strsignal(signo));
30+#else
31 pid, get_signame(signo));
32+#endif
33 child = -1; /* Restart */
34 }
35 } else if (WIFEXITED(status)) {
36@@ -159,6 +171,7 @@
37 /* NOP */
38 }
39
40+#ifndef HAVE_STRSIGNAL
41 static const char *
42 get_signame(int signo)
43 {
44@@ -199,3 +212,4 @@
45 sprintf(namebuf, "signal #%d", signo);
46 return namebuf;
47 }
48+#endif
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/005-sys-time.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/005-sys-time.patch
new file mode 100644
index 0000000000..c21fb05e8d
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/005-sys-time.patch
@@ -0,0 +1,29 @@
1# Patch origin: nfs-server source RPM from openSUSE 10.3
2
3--- nfs-server/system.h 2002/11/07 17:10:47 1.1
4+++ nfs-server/system.h 2002/11/07 17:11:53
5@@ -66,20 +66,16 @@
6 # include <grp.h> /* for setgroups */
7 #endif
8
9-#ifdef TIME_WITH_SYS_TIME
10+#ifdef HAVE_SYS_TIME_H
11 # include <sys/time.h>
12 # include <time.h>
13-#else /* not TIME_WITH_SYS_TIME */
14-# ifdef HAVE_SYS_TIME_H
15-# include <sys/time.h>
16-# else /* not HAVE_SYS_TIME_H */
17-# include <time.h>
18+#else /* not HAVE_SYS_TIME_H */
19+# include <time.h>
20 struct timeval {
21 long tv_sec;
22 long tv_usec;
23 };
24-# endif /* not HAVE_SYS_TIME_H */
25-#endif /* not TIME_WITH_SYS_TIME */
26+#endif /* not HAVE_SYS_TIME_H */
27 #ifdef HAVE_SYS_FILE_H
28 # include <sys/file.h>
29 #endif
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/006-reiserfs.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/006-reiserfs.patch
new file mode 100644
index 0000000000..abdc67476e
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/006-reiserfs.patch
@@ -0,0 +1,1272 @@
1# Patch origin: nfs-server source RPM from openSUSE 10.3
2
3--- nfs-server/Makefile.in
4+++ nfs-server/Makefile.in 2002/11/08 13:59:16
5@@ -100,7 +100,7 @@
6 utimes.c mkdir.c rename.c getopt.c getopt_long.c \
7 alloca.c mountlist.c xmalloc.c \
8 xstrdup.c strdup.c strstr.c nfsmounted.c faccess.c \
9- haccess.c daemon.c signals.c
10+ haccess.c daemon.c signals.c teahash3.c
11 XDRFILES = mount.x nfs_prot.x
12 GENFILES = mount.h mount_xdr.c mount_svc.c nfs_prot.h nfs_prot_xdr.c \
13 ugid.h ugid_xdr.c ugid_clnt.c
14@@ -112,7 +112,7 @@
15 MANPAGES8 = showmount
16 MANPAGES = $(MANPAGES5) $(MANPAGES8p) $(MANPAGES8)
17 LIBOBJS = version.o fsusage.o mountlist.o xmalloc.o xstrdup.o \
18- nfsmounted.o faccess.o haccess.o daemon.o \
19+ nfsmounted.o faccess.o haccess.o daemon.o teahash3.o \
20 signals.o @LIBOBJS@ @ALLOCA@
21 OBJS = logging.o fh.o devtab.o auth_init.o auth_clnt.o auth.o
22 NFSD_OBJS = nfsd.o rpcmisc.o nfs_dispatch.o getattr.o setattr.o \
23--- nfs-server/auth.c
24+++ nfs-server/auth.c 2002/11/08 13:59:16
25@@ -83,6 +83,7 @@
26 0, /* read-only */
27 0, /* relative links */
28 0, /* noaccess */
29+ 0, /* hashed inodes */
30 1, /* cross_mounts */
31 1, /* allow setuid */
32 65534, /* default uid */
33@@ -100,6 +101,7 @@
34 0, /* relative links */
35 0, /* noaccess */
36 1, /* cross_mounts */
37+ 0, /* hashed inodes */
38 0, /* allow setuid */
39 65534, /* default uid */
40 65534, /* default gid */
41@@ -991,6 +993,7 @@
42 if (mp == 0) {
43 mp = (nfs_mount*) xmalloc(sizeof(nfs_mount));
44 memset(mp, 0, sizeof(*mp));
45+ mp->mount_dev = 0;
46 mp->origin = cp;
47 mp->client = cp;
48 mp->path = xstrdup(path);
49@@ -1169,6 +1172,8 @@
50 default_options.nobody_gid = anon_gid;
51 anonymous_options.nobody_uid = anon_uid;
52 anonymous_options.nobody_gid = anon_gid;
53+ default_options.cross_mounts = cross_mounts;
54+ default_options.hashed_inodes = hashed_inodes;
55
56 memset(cached_clients, 0, sizeof(cached_clients));
57 cached_next = 0;
58--- nfs-server/auth.h
59+++ nfs-server/auth.h 2002/11/08 13:59:16
60@@ -43,15 +43,16 @@
61
62 typedef struct nfs_options {
63 ugid_mapping_t uidmap; /* uid/gid mapping behavior */
64- int root_squash;
65- int all_squash;
66- int some_squash; /* speed up luid() etc. */
67- int secure_port;
68- int read_only;
69- int link_relative;
70- int noaccess;
71- int cross_mounts;
72- int allow_setuid;
73+ unsigned root_squash : 1;
74+ unsigned all_squash : 1;
75+ unsigned some_squash : 1; /* speed up luid() etc. */
76+ unsigned secure_port : 1;
77+ unsigned read_only : 1;
78+ unsigned link_relative : 1;
79+ unsigned noaccess : 1;
80+ unsigned cross_mounts : 1;
81+ unsigned hashed_inodes : 1;
82+ unsigned allow_setuid : 1;
83 uid_t nobody_uid;
84 gid_t nobody_gid;
85 char * clnt_nisdomain;
86@@ -64,6 +65,7 @@
87 int length;
88 char * path;
89 nfs_options o;
90+ dev_t mount_dev;
91 /* Original NFS client */
92 struct nfs_client * origin;
93 } nfs_mount;
94@@ -121,6 +123,8 @@
95 extern void auth_check_all_netmasks(void);
96 extern void auth_sort_all_mountlists(void);
97 extern void auth_log_all(void);
98+extern int auth_checkdev(nfs_mount *, dev_t dev);
99+extern int auth_checkpathdev(char *, dev_t dev);
100
101 /* This function lets us set our euid/fsuid temporarily */
102 extern void auth_override_uid(uid_t);
103--- nfs-server/auth_clnt.c
104+++ nfs-server/auth_clnt.c 2002/11/08 13:59:16
105@@ -89,6 +89,13 @@
106 return NULL;
107 }
108
109+ if (!mp->o.cross_mounts && !mp->mount_dev) {
110+ struct stat st;
111+ if (!lstat(mp->path, &st) < 0)
112+ return NULL;
113+ mp->mount_dev = st.st_dev;
114+ }
115+
116 /* Check request originated on a privileged port. */
117 if (!allow_non_root && mp->o.secure_port
118 && !SECURE_PORT(svc_getcaller(rqstp->rq_xprt)->sin_port)) {
119@@ -350,3 +357,28 @@
120 return 1;
121 }
122 #endif
123+
124+int auth_checkpathdev(char *path, dev_t dev)
125+{
126+ nfs_mount *mp = auth_match_mount(nfsclient, path);
127+ if (!mp)
128+ return 0;
129+ return auth_checkdev(mp, dev);
130+}
131+
132+int auth_checkdev(nfs_mount *mp, dev_t dev)
133+{
134+ if (!mp->mount_dev)
135+ return 1;
136+ if (mp->mount_dev != dev) {
137+ struct stat st;
138+ /* Restat in case the cd switched */
139+ if (efs_lstat(mp->path, &st) < 0) {
140+ Dprintf(L_ERROR, "Unable to stat mount point %s\n", mp->path);
141+ return 0;
142+ }
143+ mp->mount_dev = st.st_dev;
144+ }
145+ return mp->mount_dev == dev;
146+}
147+
148--- nfs-server/auth_init.c
149+++ nfs-server/auth_init.c 2002/11/08 13:59:16
150@@ -320,6 +320,14 @@
151 /* knfsd compatibility, ignore */;
152 else ifkwd(4, "sync")
153 /* knfsd compatibility, ignore */;
154+ else ifkwd(13, "hashed_inodes")
155+ mp->o.hashed_inodes = 1;
156+ else ifkwd(16, "no_hashed_inodes")
157+ mp->o.hashed_inodes = 0;
158+ else ifkwd(12, "cross_mounts")
159+ mp->o.cross_mounts = 1;
160+ else ifkwd(15, "no_cross_mounts")
161+ mp->o.cross_mounts = 0;
162 else {
163 Dprintf(L_ERROR,
164 "Unknown keyword \"%.*s\" in export file\n",
165--- nfs-server/exports.man
166+++ nfs-server/exports.man 2002/11/08 13:59:16
167@@ -208,6 +208,17 @@
168 .IR no_all_squash ,
169 which is the default setting.
170 .TP
171+.IR hashed_inodes
172+Use a special scheme to generate inode numbers that may work better with
173+reiserfs filesystems.
174+.IR no_hashed_inodes
175+which uses a direct mapping is the default.
176+.TP
177+.IR cross_mounts
178+Do not cross mount points in exports. Turning this off with
179+.IR no_cross_mounts
180+avoids inode number space conflicts when there are too many files.
181+.TP
182 .IR map_daemon
183 This option turns on dynamic uid/gid mapping. Each uid in an NFS request
184 will be translated to the equivalent server uid, and each uid in an
185--- nfs-server/fh.c
186+++ nfs-server/fh.c 2002/11/08 14:11:31
187@@ -4,8 +4,9 @@
188 *
189 * Interfaces:
190 * pseudo_inode
191- * mostly used internally, but also called from unfsd.c
192- * when reporting directory contents.
193+ * mostly used internally, for hash tables
194+ * visible_inode
195+ * generate visible inode shown to the client in the fattr.
196 * fh_init
197 * Initializes the queues and 'flush' timer
198 * fh_pr
199@@ -47,6 +48,8 @@
200 * Note: the original code mistakenly assumes that the overall path
201 * length remains within the value given by PATH_MAX... that leads
202 * to interesting buffer overflows all over the place.
203+ *
204+ * Depends that dev_t only uses 16bits.
205 */
206
207 #include <assert.h>
208@@ -137,9 +140,9 @@
209 };
210
211 /* Forward declared local functions */
212-static psi_t path_psi(char *, nfsstat *, struct stat *, int);
213+static psi_t path_psi(char *, nfsstat *, struct stat *, int, int *);
214 static psi_t path_psi_m(char *, nfsstat *, struct stat *,
215- struct stat *, int);
216+ struct stat *, int, int *);
217 static int fh_flush_fds(void);
218 static char * fh_dump(svc_fh *);
219 static void fh_insert_fdcache(fhcache *fhc);
220@@ -173,19 +176,22 @@
221 fh_list_size++;
222
223 /* Insert into hash tab. */
224- hash_slot = &(fh_hashed[fhc->h.psi % HASH_TAB_SIZE]);
225+ hash_slot = &(fh_hashed[pseudo_inode(fhc->h.ino,fhc->h.dev) % HASH_TAB_SIZE]);
226 fhc->hash_next = *hash_slot;
227 *hash_slot = fhc;
228 }
229
230 static fhcache *
231-fh_lookup(psi_t psi)
232+fh_lookup(ino_t ino, dev_t dev)
233 {
234 register fhcache *fhc;
235
236- fhc = fh_hashed[psi % HASH_TAB_SIZE];
237- while (fhc != NULL && fhc->h.psi != psi)
238+ fhc = fh_hashed[pseudo_inode(ino,dev) % HASH_TAB_SIZE];
239+ while (fhc != NULL) {
240+ if (fhc->h.ino == ino && fhc->h.dev == dev)
241+ break;
242 fhc = fhc->hash_next;
243+ }
244 return (fhc);
245 }
246
247@@ -193,7 +199,8 @@
248 fh_insert_fdcache(fhcache *fhc)
249 {
250 #ifdef FHTRACE
251- Dprintf(D_FHTRACE, "insert fh %x into fdcache @%d\n", fhc->h.psi, fhc->fd);
252+ Dprintf(D_FHTRACE, "insert fh %x,%x into fdcache @%d\n",
253+ fhc->h.ino, fhc->h.dev, fhc->fd);
254 if (fhc->fd < 0) {
255 fh_complain("fd cache bug: bad fd", fhc);
256 return;
257@@ -289,8 +296,9 @@
258 #endif
259
260 Dprintf(D_FHTRACE|D_FHCACHE,
261- "fh_delete: deleting handle %x ('%s', fd=%d)\n",
262- fhc, fhc->path ? fhc->path : "<unnamed>", fhc->fd);
263+ "fh_delete: deleting handle %x [%x,%x] ('%s', fd=%d)\n",
264+ fhc, fhc->h.dev, fhc->h.ino, fhc->path ? fhc->path : "<unnamed>",
265+ fhc->fd);
266
267 /* Remove from current posn */
268 fhc->prev->next = fhc->next;
269@@ -298,7 +306,7 @@
270 fh_list_size--;
271
272 /* Remove from hash tab */
273- hash_slot = &(fh_hashed[fhc->h.psi % HASH_TAB_SIZE]);
274+ hash_slot = &(fh_hashed[pseudo_inode(fhc->h.ino,fhc->h.dev) % HASH_TAB_SIZE]);
275 while (*hash_slot != NULL && *hash_slot != fhc)
276 hash_slot = &((*hash_slot)->hash_next);
277 if (*hash_slot == NULL)
278@@ -528,6 +536,7 @@
279 index -= 8;
280 }
281
282+#if 0
283 /* If we have an XXL inode number, spew out warning (but at most
284 * once a second) */
285 if (inode & ~mask) {
286@@ -541,14 +550,34 @@
287 }
288 inode &= mask;
289 }
290-
291+#endif
292 return (psi_t) (prefix | inode);
293 #endif
294 }
295
296+/* Inode as handed out by attr calls. */
297+psi_t
298+visible_inode(ino_t ino, dev_t dev, nfs_mount *mount)
299+{
300+ if (!mount->o.cross_mounts)
301+ return ino;
302+
303+ if (mount->o.hashed_inodes) {
304+ extern __u32 teahash3(/*u32 k[2], *//*u8*/const char *msg, int len);
305+
306+ struct {
307+ ino_t ino;
308+ dev_t dev;
309+ } tup = { ino,dev };
310+ return teahash3((char *) &tup, sizeof tup);
311+ }
312+
313+ return pseudo_inode(ino, dev);
314+}
315+
316 #if 1
317 static char *
318-fh_buildpath(svc_fh *h)
319+fh_buildpath(svc_fh *h, dev_t basedev)
320 {
321 char pathbuf[PATH_MAX + NAME_MAX + 1], *path;
322 long cookie_stack[HP_LEN + 1];
323@@ -565,13 +594,17 @@
324
325 if (efs_stat("/", &sbuf) < 0)
326 return (NULL);
327- psi = pseudo_inode(sbuf.st_ino, sbuf.st_dev);
328 if (h->hash_path[0] == 0) {
329- if (psi != h->psi)
330- return (NULL);
331- return xstrdup("/");
332+ if (sbuf.st_ino == h->ino && sbuf.st_dev == h->dev)
333+ ;
334+ else
335+ return NULL;
336+ strcpy(pathbuf,"/");
337+ path = xstrdup(pathbuf);
338+ return (path);
339 }
340
341+ psi = pseudo_inode(sbuf.st_ino, sbuf.st_dev);
342 if (hash_psi(psi) != h->hash_path[1])
343 return (NULL);
344
345@@ -599,11 +632,18 @@
346
347 psi = pseudo_inode(dp->d_ino, sbuf.st_dev);
348 if (i == h->hash_path[0] + 1) {
349- if (psi != h->psi)
350+ if (sbuf.st_dev != h->dev || dp->d_ino != h->ino)
351 continue;
352 /* GOT IT */
353 strcpy(pathbuf + pathlen, dp->d_name);
354- path = xstrdup(pathbuf);
355+ if (!basedev || sbuf.st_dev == basedev ||
356+ auth_checkpathdev(pathbuf, sbuf.st_dev)) {
357+ path = xstrdup(pathbuf);
358+ } else {
359+ dprintf(L_ERROR, "fh_buildpath: basedev %x != dev %x for %s\n",
360+ (unsigned)basedev,(unsigned)sbuf.st_dev,pathbuf);
361+ path = NULL;
362+ }
363 efs_closedir(dir);
364 auth_override_uid(auth_uid);
365 return (path);
366@@ -754,16 +794,16 @@
367 #endif
368
369 static psi_t
370-path_psi(char *path, nfsstat *status, struct stat *sbp, int svalid)
371+path_psi(char *path, nfsstat *status, struct stat *sbp, int svalid, int *mp)
372 {
373 struct stat smounted;
374
375- return path_psi_m(path, status, sbp, &smounted, svalid);
376+ return path_psi_m(path, status, sbp, &smounted, svalid, mp);
377 }
378
379 static psi_t
380 path_psi_m(char *path, nfsstat *status,
381- struct stat *sbp, struct stat *mbp, int svalid)
382+ struct stat *sbp, struct stat *mbp, int svalid, int *mp)
383 {
384 struct stat sbuf, ddbuf;
385
386@@ -815,6 +855,8 @@
387 DIR *dirp;
388 struct dirent *dp;
389
390+ if (mp) *mp = 1;
391+
392 errno = 0;
393 dirp = efs_opendir(dname);
394 fname[-1] = '/'; /* Restore path */
395@@ -860,9 +902,70 @@
396 }
397
398 fhcache *
399-fh_find(svc_fh *h, int mode)
400+fh_newfh(svc_fh *h, int mode, dev_t basedev)
401+{
402+ fhcache *fhc, *flush;
403+
404+ ex_state = active;
405+ for (flush = fh_tail.prev; fh_list_size > FH_CACHE_LIMIT; flush = fhc) {
406+ /* Don't flush current head. */
407+ if (flush == &fh_head)
408+ break;
409+ fhc = flush->prev;
410+ fh_delete(flush);
411+ }
412+ fhc = (fhcache *) xmalloc(sizeof *fhc);
413+ if (mode == FHFIND_FCREATE) {
414+ /* File will be created */
415+ fhc->path = NULL;
416+ } else {
417+ /* File must exist. Attempt to construct from hash_path */
418+ char *path;
419+
420+ if ((path = fh_buildpath(h, basedev)) == NULL) {
421+#ifdef FHTRACE
422+ Dprintf(D_FHTRACE, "fh_find: stale fh (hash path)\n");
423+ Dprintf(D_FHTRACE, "\tdata: %s\n", fh_dump(h));
424+#endif
425+ free(fhc);
426+ ex_state = inactive;
427+ return NULL;
428+ }
429+ fhc->path = path;
430+ }
431+ fhc->flags = 0;
432+ if (fhc->path && efs_lstat(fhc->path, &fhc->attrs) >= 0) {
433+ if (re_export && nfsmounted(fhc->path, &fhc->attrs))
434+ fhc->flags |= FHC_NFSMOUNTED;
435+ fhc->flags |= FHC_ATTRVALID;
436+ }
437+ fhc->fd = -1;
438+ fhc->last_used = curtime;
439+ fhc->h = *h;
440+ fhc->last_clnt = NULL;
441+ fhc->last_mount = NULL;
442+ fhc->last_uid = (uid_t)-1;
443+ fhc->fd_next = fhc->fd_prev = NULL;
444+ fh_inserthead(fhc);
445+ Dprintf(D_FHCACHE,
446+ "fh_find: created new handle %x (path `%s' ino:%x dev:%x)\n",
447+ fhc, fhc->path ? fhc->path : "<unnamed>", fhc->h.ino, fhc->h.dev);
448+ ex_state = inactive;
449+ if (fh_list_size > FH_CACHE_LIMIT)
450+ flush_cache(0);
451+#ifdef FHTRACE
452+ if (fhc->h.hash_path[0] == 0xFF) {
453+ Dprintf(L_ERROR, "newly created fh instantly flushed?!");
454+ return NULL;
455+ }
456+#endif
457+ return (fhc);
458+}
459+
460+fhcache *
461+fh_find(svc_fh *h, int mode, dev_t basedev)
462 {
463- register fhcache *fhc, *flush;
464+ register fhcache *fhc;
465 int check;
466
467 check = (mode & FHFIND_CHECK);
468@@ -877,12 +980,12 @@
469
470 ex_state = active;
471 time(&curtime);
472- while ((fhc = fh_lookup(h->psi)) != NULL) {
473+ while ((fhc = fh_lookup(h->ino,h->dev)) != NULL) {
474 struct stat sbuf, *s = NULL;
475 nfsstat dummy;
476
477- Dprintf(D_FHCACHE, "fh_find: psi=%lx... found '%s', fd=%d\n",
478- (unsigned long) h->psi,
479+ Dprintf(D_FHCACHE, "fh_find: (%u,%u)... found '%s', fd=%d\n",
480+ h->ino, h->dev,
481 fhc->path ? fhc->path : "<unnamed>",
482 fhc->fd);
483
484@@ -905,6 +1008,7 @@
485 Dprintf(D_FHTRACE,
486 "fh_find: stale fh: lstat: %m\n");
487 } else {
488+ int mp = 0;
489 /* If device/ino don't match, fhc->path may
490 * be a mount point (hence lstat() returns
491 * a different inode number than the readdir()
492@@ -915,19 +1019,26 @@
493
494 /* Get the dev/ino of the underlying
495 * mount point. */
496- path_psi(fhc->path, &dummy, s, 1);
497- if (fh_attrmatch(fhc, s))
498- goto fh_return;
499+ if (path_psi(fhc->path, &dummy, s, 1, &mp) &&
500+ fh_attrmatch(fhc, s)) {
501+ if (!mp)
502+ Dprintf(D_FHTRACE,"fh_find: should be mount point %x,%x\n",
503+ h->dev,h->ino);
504+
505+ }
506
507- Dprintf(D_FHTRACE, "fh_find: stale fh: %lx",
508- (unsigned long) h->psi);
509+ Dprintf(D_FHTRACE, "fh_find: stale fh: "
510+ "dev/ino %x/%lx ino:%x dev:%x",
511+ s->st_dev, s->st_ino,
512+ (unsigned)h->ino, (unsigned)h->dev);
513 }
514
515 fh_discard:
516 #ifdef FHTRACE
517 Dprintf(D_FHTRACE, "\tdata: %s\n", fh_dump(h));
518 #endif
519- Dprintf(D_FHCACHE, "fh_find: delete cached handle\n");
520+ Dprintf(D_FHCACHE, "fh_find: delete cached handle %x,%x <%x>\n",
521+ fhc->h.dev,fhc->h.ino,fhc->path ? fhc->path : "no path");
522 fh_delete(fhc);
523 break;
524 }
525@@ -947,88 +1058,13 @@
526 return (fhc);
527 }
528
529- Dprintf(D_FHCACHE, "fh_find: psi=%lx... not found\n",
530- (unsigned long) h->psi);
531-
532- if (mode == FHFIND_FCACHED) {
533- ex_state = inactive;
534- return NULL;
535- }
536-
537- for (flush = fh_tail.prev; fh_list_size > FH_CACHE_LIMIT; flush = fhc) {
538- /* Don't flush current head. */
539- if (flush == &fh_head)
540- break;
541- fhc = flush->prev;
542- fh_delete(flush);
543- }
544-
545- fhc = (fhcache *) xmalloc(sizeof *fhc);
546- if (mode == FHFIND_FCREATE) {
547- /* File will be created */
548- fhc->path = NULL;
549- } else {
550- /* File must exist. Attempt to construct from hash_path */
551- char *path;
552-
553- if ((path = fh_buildpath(h)) == NULL) {
554-#ifdef FHTRACE
555- Dprintf(D_FHTRACE, "fh_find: stale fh (hash path)\n");
556- Dprintf(D_FHTRACE, "\tdata: %s\n", fh_dump(h));
557-#endif
558- free(fhc);
559- ex_state = inactive;
560- return NULL;
561- }
562- fhc->path = path;
563- }
564-
565- fhc->flags = 0;
566- if (fhc->path && efs_lstat(fhc->path, &fhc->attrs) >= 0) {
567- if (nfsmounted(fhc->path, &fhc->attrs)) {
568- fhc->flags |= FHC_NFSMOUNTED;
569-#if 0
570- /* We must allow the client to send us the
571- * file handle for the NFS mount point itself,
572- * but not for entries within an NFS mount.
573- * XXX: needs fixing.
574- */
575- if (!re_export) {
576- Dprintf(D_FHTRACE,
577- "Attempt to use %s (non-exportable)\n",
578- fhc->path);
579- free(fhc);
580- ex_state = inactive;
581- return NULL;
582- }
583-#endif
584- }
585- fhc->flags |= FHC_ATTRVALID;
586- fhc->dev = fhc->attrs.st_dev;
587- fhc->ino = fhc->attrs.st_ino;
588- fhc->type = fhc->attrs.st_mode & S_IFMT;
589- }
590- fhc->fd = -1;
591- fhc->last_used = curtime;
592- fhc->h = *h;
593- fhc->last_clnt = NULL;
594- fhc->last_mount = NULL;
595- fhc->last_uid = (uid_t)-1;
596- fhc->fd_next = fhc->fd_prev = NULL;
597- fh_inserthead(fhc);
598- Dprintf(D_FHCACHE,
599- "fh_find: created new handle %x (path `%s' psi %08x)\n",
600- fhc, fhc->path ? fhc->path : "<unnamed>", fhc->h.psi);
601 ex_state = inactive;
602- if (fh_list_size > FH_CACHE_LIMIT)
603- flush_cache(0);
604-#ifdef FHTRACE
605- if (fhc->h.hash_path[0] == 0xFF) {
606- Dprintf(L_ERROR, "newly created fh instantly flushed?!");
607+
608+ Dprintf(D_FHCACHE, "fh_find: (%u,%u) ... not found\n",
609+ h->ino, h->dev);
610+ if (mode == FHFIND_FCACHED)
611 return NULL;
612- }
613-#endif
614- return (fhc);
615+ return fh_newfh(h, mode, basedev);
616 }
617
618 /*
619@@ -1040,7 +1076,7 @@
620 {
621 fhcache *h;
622
623- if ((h = fh_find((svc_fh *) fh, FHFIND_FCACHED)) == NULL)
624+ if ((h = fh_find((svc_fh *) fh, FHFIND_FCACHED, 0)) == NULL)
625 return fh_dump((svc_fh *) fh);
626 return (h->path);
627 }
628@@ -1050,10 +1086,10 @@
629 {
630 static char buf[65];
631 char *sp;
632- int i, n = fh->hash_path[0];
633+ int i, n = fh->hash_path[0], l;
634
635- sprintf(buf, "%08x %02x ", fh->psi, fh->hash_path[0]);
636- for (i = 1, sp = buf + 12; i <= n && i < HP_LEN; i++, sp += 2)
637+ l = sprintf(buf, "%08x %04x %02x ", fh->ino, fh->dev, fh->hash_path[0]);
638+ for (i = 1, sp = buf + l; i <= n && i < HP_LEN; i++, sp += 2)
639 sprintf(sp, "%02x", fh->hash_path[i]);
640 return buf;
641 }
642@@ -1082,7 +1118,7 @@
643
644 memset(&key, 0, sizeof(key));
645 status = NFS_OK;
646- if ((psi = path_psi("/", &status, &stb, 0)) == 0)
647+ if ((psi = path_psi("/", &status, &stb, 0, NULL)) == 0)
648 return ((int) status);
649
650 s = path;
651@@ -1091,7 +1127,7 @@
652 return ((int) NFSERR_NAMETOOLONG);
653 key.hash_path[key.hash_path[0]] = hash_psi(psi);
654 *s = '\0';
655- if ((psi = path_psi(path, &status, &stb, 0)) == 0)
656+ if ((psi = path_psi(path, &status, &stb, 0, NULL)) == 0)
657 return ((int) status);
658 *s = '/';
659 }
660@@ -1099,11 +1135,12 @@
661 if (++(key.hash_path[0]) >= HP_LEN)
662 return ((int) NFSERR_NAMETOOLONG);
663 key.hash_path[key.hash_path[0]] = hash_psi(psi);
664- if ((psi = path_psi(path, &status, &stb, 0)) == 0)
665+ if ((psi = path_psi(path, &status, &stb, 0, NULL)) == 0)
666 return ((int) status);
667 }
668- key.psi = psi;
669- h = fh_find(&key, FHFIND_FCREATE);
670+ key.dev = stb.st_dev;
671+ key.ino = stb.st_ino;
672+ h = fh_find(&key, FHFIND_FCREATE, 0);
673
674 #ifdef FHTRACE
675 if (!h)
676@@ -1123,6 +1160,7 @@
677 return ((int) status);
678 }
679
680+#if 0
681 char *
682 fh_path(nfs_fh *fh, nfsstat *status)
683 {
684@@ -1135,6 +1173,7 @@
685 *status = NFS_OK;
686 return (h->path);
687 }
688+#endif
689
690 nfs_fh *
691 fh_handle(fhcache *h)
692@@ -1349,7 +1388,7 @@
693 if (sbp == NULL)
694 sbp = &sbuf;
695
696- if ((dirh = fh_find((svc_fh *) &dopa->dir, FHFIND_FEXISTS)) == NULL)
697+ if ((dirh = fh_find((svc_fh *) &dopa->dir, FHFIND_FEXISTS, 0)) == NULL)
698 return NFSERR_STALE;
699
700 /*
701@@ -1419,8 +1458,22 @@
702
703 *new_fh = dopa->dir;
704 key = (svc_fh *) new_fh;
705- if ((key->psi = path_psi_m(pathbuf, &ret, sbp, &smount, 0)) == 0)
706+
707+ if (path_psi_m(pathbuf, &ret, sbp, &smount, 0, NULL) == 0)
708 return (ret);
709+ key->ino = sbp->st_ino;
710+ key->dev = sbp->st_dev;
711+
712+ if (sbp->st_dev != dirh->h.dev) {
713+ nfs_mount *mp = dirh->last_mount;
714+ if (!mp)
715+ Dprintf(L_ERROR, "no last mount in fh_compose for %s\n", pathbuf);
716+ else if (auth_checkdev(mp, sbp->st_dev) == 0) {
717+ Dprintf(L_ERROR, "access to no cross path below mountpoint (<%s>, %x<->%x)\n",
718+ pathbuf, mp->mount_dev, sbp->st_dev);
719+ return NFSERR_STALE;
720+ }
721+ }
722
723 if (is_dd) {
724 /* Don't cd .. from root, or mysterious ailments will
725@@ -1430,11 +1483,12 @@
726 } else {
727 if (++(key->hash_path[0]) >= HP_LEN)
728 return NFSERR_NAMETOOLONG;
729- key->hash_path[key->hash_path[0]] = hash_psi(dirh->h.psi);
730+ key->hash_path[key->hash_path[0]] = hash_psi(pseudo_inode(dirh->h.ino,
731+ dirh->h.dev));
732 }
733 /* FIXME: when crossing a mount point, we'll find the real
734 * dev/ino in sbp and can store it in h... */
735- h = fh_find(key, FHFIND_FCREATE);
736+ h = fh_find(key, FHFIND_FCREATE, 0);
737
738 #ifdef FHTRACE
739 if (h == NULL)
740@@ -1456,7 +1510,7 @@
741 /* We must have cached an old file under the same inode # */
742 Dprintf(D_FHTRACE, "Disposing of fh with bad path.\n");
743 fh_delete(h);
744- h = fh_find(key, FHFIND_FCREATE);
745+ h = fh_find(key, FHFIND_FCREATE, dirh->last_mount ? dirh->last_mount->mount_dev : 0);
746 #ifdef FHTRACE
747 if (!h) return NFSERR_STALE;
748 #endif
749@@ -1511,12 +1565,14 @@
750 return (NFS_OK);
751 }
752
753+#if 0
754 psi_t
755 fh_psi(nfs_fh *fh)
756 {
757 svc_fh *h = (svc_fh *) fh;
758 return (h->psi);
759 }
760+#endif
761
762 void
763 fh_remove(char *path)
764@@ -1524,12 +1580,13 @@
765 psi_t psi;
766 nfsstat status;
767 fhcache *fhc;
768+ struct stat st;
769
770- psi = path_psi(path, &status, NULL, 0);
771+ psi = path_psi(path, &status, &st, 0, NULL);
772 if (psi == 0)
773 return;
774 ex_state = active;
775- fhc = fh_lookup(psi);
776+ fhc = fh_lookup(st.st_ino,st.st_dev);
777 if (fhc != NULL)
778 fh_delete(fhc);
779
780@@ -1634,6 +1691,11 @@
781 fh_init(void)
782 {
783 static int initialized = 0;
784+
785+ if (sizeof(svc_fh) > 32) {
786+ fprintf(stderr, "filehandle wrong size %d\n", sizeof(svc_fh));
787+ exit(10);
788+ }
789
790 if (initialized)
791 return;
792--- nfs-server/fh.h
793+++ nfs-server/fh.h 2002/11/08 13:59:16
794@@ -20,6 +20,7 @@
795 #define FHC_XONLY_PATH 001 /* NOT USED ANYMORE */
796 #define FHC_ATTRVALID 002
797 #define FHC_NFSMOUNTED 004
798+#define FHC_CROSS 010
799
800 /* Modes for fh_find */
801 #define FHFIND_FEXISTS 0 /* file must exist */
802@@ -65,11 +66,12 @@
803 *
804 * hash_path[hash_path[0]+1] ... hash_path[HP_LEN-1] == 0
805 */
806-#define HP_LEN (NFS_FHSIZE - sizeof(psi_t))
807+#define HP_LEN (NFS_FHSIZE-sizeof(u_int32_t)-sizeof(u_int16_t))
808 typedef struct {
809- psi_t psi;
810+ u_int32_t ino;
811+ u_int16_t dev;
812 __u8 hash_path[HP_LEN];
813-} svc_fh;
814+} svc_fh __attribute__((packed));
815
816 typedef enum { inactive, active } mutex;
817
818@@ -100,6 +102,7 @@
819
820 /* These are fixed during the lifetime of this object */
821 svc_fh h;
822+ psi_t psi;
823 dev_t dev;
824 ino_t ino;
825 mode_t type; /* st_mode & S_IFMT */
826@@ -122,10 +125,11 @@
827 /* Global function prototypes. */
828 extern nfsstat nfs_errno(void);
829 extern psi_t pseudo_inode(ino_t inode, dev_t dev);
830+extern psi_t visible_inode(ino_t inode, dev_t dev, nfs_mount *);
831 extern void fh_init(void);
832 extern char *fh_pr(nfs_fh *fh);
833 extern int fh_create(nfs_fh *fh, char *path);
834-extern fhcache *fh_find(svc_fh *h, int create);
835+extern fhcache *fh_find(svc_fh *h, int create, dev_t basedev);
836 extern char *fh_path(nfs_fh *fh, nfsstat *status);
837 extern int path_open(char *path, int omode, int perm);
838 extern int fh_fd(fhcache *fhc, nfsstat *status, int omode);
839@@ -139,6 +143,7 @@
840 extern void fh_flush(int force);
841 extern RETSIGTYPE flush_cache(int sig);
842 extern int nfsmounted(const char *path, struct stat *sbp);
843+extern fhcache *fh_newfh(svc_fh *fh, int mode, dev_t basedev);
844
845 #ifdef ENABLE_DEVTAB
846 extern unsigned int devtab_index(dev_t);
847--- nfs-server/getattr.c
848+++ nfs-server/getattr.c 2002/11/08 13:59:16
849@@ -43,7 +43,7 @@
850 {
851 fhcache *fhc;
852
853- if ((fhc = fh_find((svc_fh*)fh, FHFIND_FEXISTS)) == NULL) {
854+ if ((fhc = fh_find((svc_fh*)fh, FHFIND_FEXISTS, 0)) == NULL) {
855 Dprintf(D_CALL, "getattr: failed! No such file.\n");
856 return (NFSERR_STALE);
857 }
858@@ -103,18 +103,8 @@
859 #else
860 attr->blocks = st_blocks(s);
861 #endif
862-#if 0
863- if (nfsmount->o.cross_mounts) {
864- attr->fsid = 1;
865- attr->fileid = fh_psi((nfs_fh *)&(fhc->h));
866- } else {
867- attr->fsid = s->st_dev;
868- attr->fileid = covered_ino(fhc->path);
869- }
870-#else
871- attr->fsid = 1;
872- attr->fileid = fh_psi((nfs_fh *)&(fhc->h));
873-#endif
874+ attr->fsid = 1; // XXX
875+ attr->fileid = visible_inode(fhc->h.ino, fhc->h.dev, nfsmount);
876
877 /* This may be needed by some Suns... testing */
878 #define MINTIME (24 * 2600)
879--- nfs-server/mountd.c
880+++ nfs-server/mountd.c 2002/11/08 13:59:16
881@@ -36,6 +36,8 @@
882 #include "signals.h"
883 #include <rpc/pmap_clnt.h>
884
885+int cross_mounts = 1;
886+int hashed_inodes; /* dummy */
887
888 static void usage(FILE *, int);
889 static void terminate(void);
890@@ -58,9 +60,9 @@
891 { "no-spoof-trace", 0, 0, 't' },
892 { "version", 0, 0, 'v' },
893 { "fail-safe", optional_argument, 0, 'z' },
894+ { "no-cross-mounts", 0, 0, 'x' },
895 { "no-tcp", 0, 0, OPT_NOTCP },
896 { "loopback-only", 0, 0, OPT_LOOPBACK },
897-
898 { NULL, 0, 0, 0 }
899 };
900 static const char * shortopts = "Fd:f:hnpP:rtvz::";
901@@ -80,6 +82,7 @@
902 int need_reinit = 0;
903 int need_flush = 0;
904 extern char version[];
905+nfs_client *nfsclient; /* dummy */
906
907 /*
908 * NULL
909@@ -319,6 +322,9 @@
910 opterr = 0;
911 while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != EOF)
912 switch (c) {
913+ case 'x':
914+ cross_mounts = 0;
915+ break;
916 case 'F':
917 foreground = 1;
918 break;
919@@ -444,7 +450,7 @@
920 program_name);
921 fprintf(fp, " [--debug kind] [--help] [--allow-non-root]\n");
922 fprintf(fp, " [--promiscuous] [--version] [--port portnum]\n");
923- fprintf(fp, " [--exports-file=file]\n");
924+ fprintf(fp, " [--exports-file=file] [--no-cross-mounts]\n");
925 exit(n);
926 }
927
928--- nfs-server/nfsd.c
929+++ nfs-server/nfsd.c 2002/11/08 14:20:57
930@@ -72,7 +72,7 @@
931 { "no-tcp", 0, 0, OPT_NOTCP },
932 { "udp-only", 0, 0, OPT_NOTCP },
933 { "loopback-only", 0, 0, OPT_LOOPBACK },
934-
935+ { "hashed-inodes", 0, 0, 'I' },
936 { NULL, 0, 0, 0 }
937 };
938 static const char * shortopts = "a:d:Ff:hlnP:prR:tvz::";
939@@ -91,6 +91,7 @@
940 int need_flush = 0; /* flush fh cache */
941 int read_only = 0; /* Global ro forced */
942 int cross_mounts = 1; /* Transparently cross mnts */
943+int hashed_inodes = 0;
944 int log_transfers = 0; /* Log transfers */
945 static svc_fh public_fh; /* Public NFSv2 FH */
946
947@@ -122,12 +123,17 @@
948 {
949 static int total = 0, cached = 0;
950 fhcache *fhc;
951+ int newfh = 0;
952
953- /* Try to map FH. If not cached, reconstruct path with root priv */
954- fhc = fh_find((svc_fh *)fh, FHFIND_FEXISTS|FHFIND_CHECK);
955- if (fhc == NULL) {
956- *statp = NFSERR_STALE;
957- return NULL;
958+ /* Try to map FH. */
959+ fhc = fh_find((svc_fh *)fh, FHFIND_FCACHED|FHFIND_CHECK, 0);
960+ if (!fhc) {
961+ fhc = fh_newfh((svc_fh*)fh, FHFIND_FEXISTS|FHFIND_CHECK, 0);
962+ if (!fhc) {
963+ *statp = NFSERR_STALE;
964+ return NULL;
965+ }
966+ newfh = 1;
967 }
968
969 /* Try to retrieve last client who accessed this fh */
970@@ -163,6 +169,16 @@
971 100 * (double) cached / total);
972 */
973
974+ /* Trust the crossmount check of the parent directory for creates */
975+ if (newfh &&
976+ (fhc->flags & FHC_ATTRVALID) &&
977+ auth_checkdev(nfsmount, fhc->attrs.st_dev) == 0) {
978+ Dprintf(L_ERROR, "auth_fh: fh crossed mount %s: %x<->%x\n",
979+ fhc->path ? fhc->path : "???", nfsmount->mount_dev, fhc->attrs.st_dev);
980+ *statp = NFSERR_STALE; /* or ACCES? */
981+ return NULL;
982+ }
983+
984 if (nfsmount->o.noaccess &&
985 ((flags & CHK_NOACCESS) || strcmp(nfsmount->path, fhc->path))) {
986 struct in_addr addr = svc_getcaller(rqstp->rq_xprt)->sin_addr;
987@@ -195,6 +211,7 @@
988 fhcache *fhc;
989 nfsstat status;
990 char *path = buf, *sp;
991+ struct stat st;
992
993 /* Authenticate directory file handle */
994 if ((fhc = auth_fh(rqstp, &dopa->dir, &status, flags)) == NULL)
995@@ -219,6 +236,9 @@
996 if ((nfsmount = auth_path(nfsclient, rqstp, path)) == NULL)
997 return NFSERR_ACCES;
998
999+ if (efs_lstat(path, &st) >= 0 && !auth_checkdev(nfsmount, st.st_dev))
1000+ return NFSERR_ACCES;
1001+
1002 /* XXX: really need to call it again here?
1003 * Already invoked in auth_fh */
1004 if (!auth_user(nfsmount, rqstp))
1005@@ -318,7 +338,8 @@
1006 int ispublic = 0;
1007
1008 /* First check whether this is the public FH */
1009- if (((svc_fh *) fh)->psi == 0 && !memcmp(fh, &public_fh, FHSIZE)) {
1010+ if (((svc_fh *) fh)->dev == 0 && ((svc_fh*)fh)->ino == 0 &&
1011+ !memcmp(fh, &public_fh, FHSIZE)) {
1012 if (public_root_path == NULL)
1013 return NFSERR_ACCES;
1014 memcpy(&argp->dir, &public_root, NFS_FHSIZE);
1015@@ -333,6 +354,7 @@
1016 if (!(fhc = auth_fh(rqstp, fh, &status, CHK_READ)))
1017 return status;
1018
1019+ /* FIXME: does too many stats */
1020 status = fh_compose(argp, &dp->file, &sbuf, -1, -1, ispublic);
1021 if (status != NFS_OK)
1022 return status;
1023@@ -896,6 +918,9 @@
1024 errno = 0;
1025 if (efs_lstat(h->path, &sbuf) < 0 || !(S_ISDIR(sbuf.st_mode)))
1026 return (NFSERR_NOTDIR);
1027+ if (!auth_checkdev(h->last_mount, sbuf.st_dev))
1028+ dotsonly = 1;
1029+
1030 if ((dirp = efs_opendir(h->path)) == NULL)
1031 return ((errno ? nfs_errno() : NFSERR_NAMETOOLONG));
1032
1033@@ -923,7 +948,7 @@
1034 }
1035
1036 e = *ep = (entry *) xmalloc(sizeof(entry));
1037- e->fileid = pseudo_inode(dp->d_ino, sbuf.st_dev);
1038+ e->fileid = visible_inode(dp->d_ino, sbuf.st_dev, h->last_mount);
1039 e->name = xmalloc(NLENGTH(dp) + 1);
1040 strcpy(e->name, dp->d_name);
1041 dloc = htonl(efs_telldir(dirp));
1042@@ -1033,6 +1058,9 @@
1043 case 'x':
1044 cross_mounts = 0;
1045 break;
1046+ case 'I':
1047+ hashed_inodes = 1;
1048+ break;
1049 case 'z':
1050 if (optarg)
1051 failsafe_level = atoi(optarg);
1052@@ -1189,7 +1217,7 @@
1053 " [--debug kind] [--exports-file=file] [--port port]\n"
1054 " [--allow-non-root] [--promiscuous] [--version] [--foreground]\n"
1055 " [--re-export] [--log-transfers] [--public-root path]\n"
1056-" [--no-spoof-trace] [--help]\n"
1057+" [--no-spoof-trace] [--no-cross-mounts] [--hashed-inodes] [--help]\n"
1058 , program_name);
1059 exit(n);
1060 }
1061--- nfs-server/nfsd.h
1062+++ nfs-server/nfsd.h 2002/11/08 13:59:16
1063@@ -51,6 +51,7 @@
1064 extern int need_reinit;
1065 extern int need_flush;
1066 extern time_t nfs_dispatch_time;
1067+extern int cross_mounts, hashed_inodes;
1068
1069 /* Include the other module definitions. */
1070 #include "auth.h"
1071--- nfs-server/setattr.c
1072+++ nfs-server/setattr.c 2002/11/08 13:59:16
1073@@ -17,6 +17,7 @@
1074
1075 #define IGNORE_TIME ((unsigned int) -1)
1076
1077+#if 0
1078 /*
1079 * Set file attributes based on file handle
1080 */
1081@@ -33,6 +34,7 @@
1082 }
1083 return setattr(path, attr, s, rqstp, flags);
1084 }
1085+#endif
1086
1087 /*
1088 * Set file attributes given the path. The flags argument
1089--- nfs-server/teahash3.c
1090+++ nfs-server/teahash3.c 2002/11/08 13:59:16
1091@@ -0,0 +1,168 @@
1092+/* Taken from the reiserfs source code and hacked slightly by AK.
1093+ * This is GPLed. */
1094+/*
1095+ * Keyed 32-bit hash function using TEA in a Davis-Meyer function
1096+ * H0 = Key
1097+ * Hi = E Mi(Hi-1) + Hi-1
1098+ *
1099+ * (see Applied Cryptography, 2nd edition, p448).
1100+ *
1101+ * Jeremy Fitzhardinge <jeremy@zip.com.au> 1998
1102+ *
1103+ * Jeremy has agreed to the contents of reiserfs/README. -Hans
1104+ */
1105+
1106+#include <assert.h>
1107+
1108+#if 0
1109+/* OK for Intel */
1110+typedef unsigned long u32;
1111+typedef const unsigned char u8;
1112+#else
1113+#include <inttypes.h>
1114+typedef uint32_t u32;
1115+typedef uint8_t u8;
1116+#endif
1117+
1118+
1119+#define DELTA 0x9E3779B9
1120+#define FULLROUNDS 10 /* 32 is overkill, 16 is strong crypto */
1121+#define PARTROUNDS 6 /* 6 gets complete mixing */
1122+
1123+/* a, b, c, d - data; h0, h1 - accumulated hash */
1124+#define TEACORE(rounds) \
1125+ do { \
1126+ u32 sum = 0; \
1127+ int n = rounds; \
1128+ u32 b0, b1; \
1129+ \
1130+ b0 = h0; \
1131+ b1 = h1; \
1132+ \
1133+ do \
1134+ { \
1135+ sum += DELTA; \
1136+ b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); \
1137+ b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); \
1138+ } while(--n); \
1139+ \
1140+ h0 += b0; \
1141+ h1 += b1; \
1142+ } while(0)
1143+
1144+u32 teahash3(/*u32 k[2], *//*u8*/const char *msg, int len)
1145+{
1146+ u32 k[] = { 0x9464a485, 0x542e1a94, 0x3e846bff, 0xb75bcfc3};
1147+
1148+ u32 h0 = k[0], h1 = k[1];
1149+ u32 a, b, c, d;
1150+ u32 pad;
1151+ int i;
1152+
1153+ assert(len >= 0 && len < 256);
1154+
1155+ pad = (u32)len | ((u32)len << 8);
1156+ pad |= pad << 16;
1157+
1158+ while(len >= 16)
1159+ {
1160+ a = (u32)msg[ 0] |
1161+ (u32)msg[ 1] << 8 |
1162+ (u32)msg[ 2] << 16|
1163+ (u32)msg[ 3] << 24;
1164+ b = (u32)msg[ 4] |
1165+ (u32)msg[ 5] << 8 |
1166+ (u32)msg[ 6] << 16|
1167+ (u32)msg[ 7] << 24;
1168+ c = (u32)msg[ 8] |
1169+ (u32)msg[ 9] << 8 |
1170+ (u32)msg[10] << 16|
1171+ (u32)msg[11] << 24;
1172+ d = (u32)msg[12] |
1173+ (u32)msg[13] << 8 |
1174+ (u32)msg[14] << 16|
1175+ (u32)msg[15] << 24;
1176+
1177+ TEACORE(PARTROUNDS);
1178+
1179+ len -= 16;
1180+ msg += 16;
1181+ }
1182+
1183+ if (len >= 12)
1184+ {
1185+ assert(len < 16);
1186+
1187+ a = (u32)msg[ 0] |
1188+ (u32)msg[ 1] << 8 |
1189+ (u32)msg[ 2] << 16|
1190+ (u32)msg[ 3] << 24;
1191+ b = (u32)msg[ 4] |
1192+ (u32)msg[ 5] << 8 |
1193+ (u32)msg[ 6] << 16|
1194+ (u32)msg[ 7] << 24;
1195+ c = (u32)msg[ 8] |
1196+ (u32)msg[ 9] << 8 |
1197+ (u32)msg[10] << 16|
1198+ (u32)msg[11] << 24;
1199+
1200+ d = pad;
1201+ for(i = 12; i < len; i++)
1202+ {
1203+ d <<= 8;
1204+ d |= msg[i];
1205+ }
1206+ }
1207+ else if (len >= 8)
1208+ {
1209+ assert(len < 12);
1210+
1211+ a = (u32)msg[ 0] |
1212+ (u32)msg[ 1] << 8 |
1213+ (u32)msg[ 2] << 16|
1214+ (u32)msg[ 3] << 24;
1215+ b = (u32)msg[ 4] |
1216+ (u32)msg[ 5] << 8 |
1217+ (u32)msg[ 6] << 16|
1218+ (u32)msg[ 7] << 24;
1219+
1220+ c = d = pad;
1221+ for(i = 8; i < len; i++)
1222+ {
1223+ c <<= 8;
1224+ c |= msg[i];
1225+ }
1226+ }
1227+ else if (len >= 4)
1228+ {
1229+ assert(len < 8);
1230+
1231+ a = (u32)msg[ 0] |
1232+ (u32)msg[ 1] << 8 |
1233+ (u32)msg[ 2] << 16|
1234+ (u32)msg[ 3] << 24;
1235+
1236+ b = c = d = pad;
1237+ for(i = 4; i < len; i++)
1238+ {
1239+ b <<= 8;
1240+ b |= msg[i];
1241+ }
1242+ }
1243+ else
1244+ {
1245+ assert(len < 4);
1246+
1247+ a = b = c = d = pad;
1248+ for(i = 0; i < len; i++)
1249+ {
1250+ a <<= 8;
1251+ a |= msg[i];
1252+ }
1253+ }
1254+
1255+ TEACORE(FULLROUNDS);
1256+
1257+/* return 0;*/
1258+ return h0^h1;
1259+}
1260--- nfs-server/ugid_map.c
1261+++ nfs-server/ugid_map.c 2002/11/08 13:59:16
1262@@ -276,8 +276,10 @@
1263 if ((gid == 0 && mountp->o.root_squash) || mountp->o.all_squash)
1264 retgid = mountp->o.nobody_gid;
1265
1266+#if 0
1267 Dprintf(D_UGID, "lgid(%s, %d) = %d\n",
1268 inet_ntoa(mountp->client->clnt_addr), gid, retgid);
1269+#endif
1270 return retgid;
1271 }
1272
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/007-map.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/007-map.patch
new file mode 100644
index 0000000000..89baabe1c2
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/007-map.patch
@@ -0,0 +1,78 @@
1# Patch origin: nfs-server source RPM from openSUSE 10.3
2
3--- nfs-server/auth.c
4+++ nfs-server/auth.c 2002/11/08 12:49:13
5@@ -595,7 +595,6 @@
6 cp->clnt_addr.s_addr = INADDR_ANY;
7 cp->flags = 0;
8 cp->m = NULL;
9- cp->umap = NULL;
10
11 if (hname == NULL) {
12 if (anonymous_client != NULL) {
13@@ -1200,10 +1199,9 @@
14 free (mp->path);
15 if (mp->o.clnt_nisdomain)
16 free(mp->o.clnt_nisdomain);
17+ if (mp->umap)
18+ ugid_free_map(mp->umap);
19 free (mp);
20- }
21- if (cp->umap != NULL) {
22- ugid_free_map(cp->umap);
23 }
24 free (cp);
25 }
26--- nfs-server/auth.h
27+++ nfs-server/auth.h 2002/11/08 12:50:24
28@@ -66,6 +66,11 @@
29 char * path;
30 nfs_options o;
31 dev_t mount_dev;
32+ /*
33+ * This is the uid/gid map.
34+ * See ugid_map.c for details
35+ */
36+ struct ugid_map * umap;
37 /* Original NFS client */
38 struct nfs_client * origin;
39 } nfs_mount;
40@@ -77,12 +82,6 @@
41 char * clnt_name;
42 unsigned short flags;
43 nfs_mount * m;
44-
45- /*
46- * This is the uid/gid map.
47- * See ugid_map.c for details
48- */
49- struct ugid_map * umap;
50 } nfs_client;
51
52 #define AUTH_CLNT_WILDCARD 0x0001
53--- nfs-server/ugid_map.c
54+++ nfs-server/ugid_map.c 2002/11/08 12:49:14
55@@ -401,12 +401,11 @@
56 static ugid_map *
57 ugid_get_map(nfs_mount *mountp)
58 {
59- nfs_client *clientp = mountp->client;
60 struct ugid_map *umap;
61 unsigned int how;
62
63- if (clientp->umap == NULL) {
64- clientp->umap = umap = (ugid_map *) xmalloc(sizeof(ugid_map));
65+ if (mountp->umap == NULL) {
66+ mountp->umap = umap = (ugid_map *) xmalloc(sizeof(ugid_map));
67 memset(umap, 0, sizeof(ugid_map));
68
69 for (how = 0; how < 4; how++) {
70@@ -415,7 +414,7 @@
71 }
72 }
73
74- return clientp->umap;
75+ return mountp->umap;
76 }
77
78 static void
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/008-configure.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/008-configure.patch
new file mode 100644
index 0000000000..a6d45993ee
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/008-configure.patch
@@ -0,0 +1,13 @@
1# Patch origin: nfs-server source RPM from openSUSE 10.3
2
3--- nfs-server/configure.in 2002/11/08 14:24:55 1.1
4+++ nfs-server/configure.in 2002/11/08 14:25:27
5@@ -98,7 +98,7 @@
6 fi
7 if test "$enable_ugid_dynamic" = yes; then
8 AC_DEFINE(ENABLE_UGID_DAEMON)
9- UGIDD_PROG=\${rpcprefix}.ugidd
10+ UGIDD_PROG=\${rpcprefix}ugidd
11 UGIDD_MAN=ugidd
12 fi
13 if test "$enable_ugid_nis" = yes; then
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/009-multirw.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/009-multirw.patch
new file mode 100644
index 0000000000..65b0b9eee5
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/009-multirw.patch
@@ -0,0 +1,15 @@
1# Patch origin: nfs-server source RPM from openSUSE 10.3
2
3--- nfs-server/nfsd.c
4+++ nfs-server/nfsd.c
5@@ -1133,8 +1133,8 @@
6 }
7 }
8
9- if (ncopies > 1)
10- read_only = 1;
11+ /* if (ncopies > 1)
12+ read_only = 1; */
13
14 /*
15 * We first fork off a child and detach from tty
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/010-realpath.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/010-realpath.patch
new file mode 100644
index 0000000000..c3b5d58151
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/010-realpath.patch
@@ -0,0 +1,30 @@
1# Patch origin: nfs-server source RPM from openSUSE 10.3
2
3--- nfs-server/configure.in
4+++ nfs-server/configure.in
5@@ -81,7 +81,7 @@
6 AC_CHECK_LIB(rpc, main)
7 AC_CHECK_LIB(crypt, main)
8 AC_CHECK_LIB(nys, main)
9-AC_HAVE_FUNCS(getcwd seteuid setreuid getdtablesize setgroups lchown setsid setfsuid setfsgid innetgr quotactl authdes_getucred)
10+AC_HAVE_FUNCS(getcwd seteuid setreuid getdtablesize setgroups lchown setsid setfsuid setfsgid innetgr quotactl authdes_getucred realpath)
11 AC_AUTHDES_GETUCRED
12 AC_BROKEN_SETFSUID
13 AC_MOUNTLIST
14--- nfs-server/realpath.c
15+++ nfs-server/realpath.c
16@@ -53,6 +53,8 @@
17
18 #define MAX_READLINKS 32
19
20+#ifndef HAVE_REALPATH
21+
22 #ifdef __STDC__
23 char *realpath(const char *path, char resolved_path [])
24 #else
25@@ -173,3 +175,5 @@
26 strcpy (resolved_path, got_path);
27 return resolved_path;
28 }
29+
30+#endif /* HAVE_REALPATH */
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/011-fno-strict-aliasing.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/011-fno-strict-aliasing.patch
new file mode 100644
index 0000000000..695b8c7d19
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/011-fno-strict-aliasing.patch
@@ -0,0 +1,13 @@
1# Patch origin: nfs-server source RPM from openSUSE 10.3
2
3--- nfs-server/Makefile.in
4+++ nfs-server/Makefile.in
5@@ -225,7 +225,7 @@
6 $(RPCGEN) -l -o $@ $?
7
8 nfs_prot_xdr.o: nfs_prot_xdr.c
9- $(COMPILE) $(RPC_WARNFLAGS) -c nfs_prot_xdr.c
10+ $(COMPILE) $(RPC_WARNFLAGS) -fno-strict-aliasing -c nfs_prot_xdr.c
11 mount_xdr.o: mount_xdr.c
12 $(COMPILE) $(RPC_WARNFLAGS) -c mount_xdr.c
13 mount_svc.o: mount_svc.c
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/012-nostrip.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/012-nostrip.patch
new file mode 100644
index 0000000000..a815ee4373
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/012-nostrip.patch
@@ -0,0 +1,13 @@
1# Patch origin: nfs-server source RPM from openSUSE 10.3
2
3--- nfs-server/Makefile.in.xx 2006-01-12 12:43:09.000000000 +0100
4+++ nfs-server/Makefile.in 2006-01-12 12:43:10.000000000 +0100
5@@ -64,7 +64,7 @@
6 NFSD_DEFS =
7
8 CFLAGS = @CFLAGS@
9-LDFLAGS = @LDFLAGS@ -s
10+LDFLAGS = @LDFLAGS@
11 WARNFLAGS = @WARNFLAGS@
12 RPC_WARNFLAGS = @RPC_WARNFLAGS@
13 TRANSPORTFLAGS = @RPCGEN_I@ -s udp -s tcp
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/013-mntpathlen.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/013-mntpathlen.patch
new file mode 100644
index 0000000000..1f10d3c941
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/013-mntpathlen.patch
@@ -0,0 +1,32 @@
1# Patch origin: nfs-server source RPM from openSUSE 10.3
2
3--- nfs-server/mountd.c 2006/01/12 14:00:13 1.13
4+++ nfs-server/mountd.c 2006/01/12 14:37:35
5@@ -76,7 +76,7 @@
6 0
7 };
8
9-char argbuf[MNTPATHLEN + 1];
10+char argbuf[PATH_MAX + 1];
11 char *auth_file = NULL;
12 static char *program_name;
13 int need_reinit = 0;
14@@ -97,6 +97,9 @@
15 /*
16 * MOUNT
17 * This is what the whole protocol is all about
18+ *
19+ * Note: librpc gets us MNTPATHLEN length strings, but realpath
20+ * needs a PATH_MAX length output buffer.
21 */
22 fhstatus *
23 mountproc_mnt_1_svc(dirpath *argp, struct svc_req *rqstp)
24@@ -105,7 +108,7 @@
25 struct stat stbuf;
26 nfs_client *cp;
27 nfs_mount *mp;
28- char nargbuf[MNTPATHLEN + 1];
29+ char nargbuf[PATH_MAX + 1];
30 int saved_errno = 0;
31 #ifdef WANT_LOG_MOUNTS
32 struct in_addr addr;
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/014-uninitialized.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/014-uninitialized.patch
new file mode 100644
index 0000000000..233c08a2f3
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/014-uninitialized.patch
@@ -0,0 +1,12 @@
1# Patch origin: nfs-server source RPM from openSUSE 10.3
2
3--- nfs-server/mountd.c
4+++ nfs-server/mountd.c
5@@ -278,6 +278,7 @@
6 || (mp = auth_path(cp, rqstp, dir)) == NULL
7 || mp->o.noaccess) {
8 #ifdef WANT_LOG_MOUNTS
9+ addr = svc_getcaller(rqstp->rq_xprt)->sin_addr;
10 Dprintf(L_WARNING, "Blocked attempt of %s to pathconf(%s)\n",
11 inet_ntoa(addr), dir);
12 #endif /* WANT_LOG_MOUNTS */
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/015-setattr.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/015-setattr.patch
new file mode 100644
index 0000000000..cbfb8e8214
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/015-setattr.patch
@@ -0,0 +1,26 @@
1# Patch origin: nfs-server source RPM from openSUSE 10.3
2
3--- nfs-server/setattr.c.orig 2006-07-28 16:38:26.000000000 +0200
4+++ nfs-server/setattr.c 2006-07-28 16:42:28.000000000 +0200
5@@ -97,7 +97,20 @@
6 tvp[1].tv_sec = s->st_mtime;
7 tvp[1].tv_usec = 0;
8 }
9- if (efs_utimes(path, tvp) < 0)
10+ if (m_secs != IGNORE_TIME && attr->mtime.useconds == 1000000) {
11+ /*
12+ * from kernel/fs/nfsd/nfsxdr.c:
13+ * Passing the invalid value useconds=1000000 for mtime
14+ * is a Sun convention for "set both mtime and atime to
15+ * current server time". It's needed to make permissions
16+ * checks for the "touch" program across v2 mounts to
17+ * Solaris and Irix boxes work correctly. See description of
18+ * sattr in section 6.1 of "NFS Illustrated" by
19+ * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
20+ */
21+ if (utime(path, (struct utimbuf *)0) < 0)
22+ goto failure;
23+ } else if (efs_utimes(path, tvp) < 0)
24 goto failure;
25 }
26 }
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/016-makefile.in.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/016-makefile.in.patch
new file mode 100644
index 0000000000..634ce46090
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/016-makefile.in.patch
@@ -0,0 +1,14 @@
1# Makefile fix for staging to work correctly.
2# Scott Garman <scott.a.garman@intel.com>
3
4--- nfs-server-2.2beta47/Makefile.in.orig 2010-08-03 20:55:05.000000000 -0700
5+++ nfs-server-2.2beta47/Makefile.in 2010-08-03 20:55:42.000000000 -0700
6@@ -69,7 +69,7 @@
7 RPC_WARNFLAGS = @RPC_WARNFLAGS@
8 TRANSPORTFLAGS = @RPCGEN_I@ -s udp -s tcp
9
10-prefix = $(install_prefix)/usr
11+prefix = @prefix@
12 exec_prefix = $(prefix)
13
14 bindir = $(exec_prefix)/sbin
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/017-wrs-dynamic-rpc.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/017-wrs-dynamic-rpc.patch
new file mode 100644
index 0000000000..18e12de789
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/017-wrs-dynamic-rpc.patch
@@ -0,0 +1,258 @@
1# Add the ability to choose alternate RPC ports at runtime and disable
2# security so that it can run as a userland process
3# Patch origin: Wind River
4
5Index: nfs-server-2.2beta47/auth_init.c
6===================================================================
7--- nfs-server-2.2beta47.orig/auth_init.c
8+++ nfs-server-2.2beta47/auth_init.c
9@@ -409,6 +409,7 @@ auth_init(char *fname)
10 fname = EXPORTSFILE;
11 auth_file = fname; /* Save for re-initialization */
12
13+#ifdef ROOT_LEVEL_SECURITY
14 /* Check protection of exports file. */
15 switch(iCheckAccess(auth_file, EXPORTSOWNERUID, EXPORTSOWNERGID)) {
16 case FACCESSWRITABLE:
17@@ -424,6 +425,7 @@ auth_init(char *fname)
18 Dprintf(L_ERROR, "exiting because of security violation.\n");
19 exit(1);
20 }
21+#endif
22
23 if ((ef = fopen(fname, "r")) == NULL) {
24 Dprintf(L_ERROR, "Could not open exports file %s: %s\n",
25Index: nfs-server-2.2beta47/nfsd.c
26===================================================================
27--- nfs-server-2.2beta47.orig/nfsd.c
28+++ nfs-server-2.2beta47/nfsd.c
29@@ -46,6 +46,7 @@ static char pathbuf_1[NFS_MAXPATHLEN + N
30
31 extern char version[];
32 static char *program_name;
33+static int nfs_prog = NFS_PROGRAM;
34
35 /*
36 * Option table
37@@ -60,6 +61,7 @@ static struct option longopts[] = {
38 { "help", 0, 0, 'h' },
39 { "log-transfers", 0, 0, 'l' },
40 { "allow-non-root", 0, 0, 'n' },
41+ { "prog", required_argument, 0, 'g' },
42 { "port", required_argument, 0, 'P' },
43 { "promiscuous", 0, 0, 'p' },
44 { "re-export", 0, 0, 'r' },
45@@ -73,9 +75,10 @@ static struct option longopts[] = {
46 { "udp-only", 0, 0, OPT_NOTCP },
47 { "loopback-only", 0, 0, OPT_LOOPBACK },
48 { "hashed-inodes", 0, 0, 'I' },
49+ { "nfs-pid", required_argument, 0, 'N' },
50 { NULL, 0, 0, 0 }
51 };
52-static const char * shortopts = "a:d:Ff:hlnP:prR:tvz::";
53+static const char * shortopts = "a:d:Ff:g:hlnN:P:prR:tvz::";
54
55 /*
56 * Table of supported versions
57@@ -1003,6 +1006,8 @@ main(int argc, char **argv)
58 int failsafe_level = 0;
59 int c;
60 int i, ncopies = 1;
61+ char *nfs_pid_file = NULL;
62+
63
64 program_name = argv[0];
65 chdir("/");
66@@ -1026,9 +1031,15 @@ main(int argc, char **argv)
67 case 'f':
68 auth_file = optarg;
69 break;
70+ case 'g':
71+ nfs_prog = atoi(optarg);
72+ break;
73 case 'l':
74 log_transfers = 1;
75 break;
76+ case 'N':
77+ nfs_pid_file = strdup(optarg);
78+ break;
79 case 'n':
80 allow_non_root = 1;
81 break;
82@@ -1114,7 +1125,7 @@ main(int argc, char **argv)
83 log_open("nfsd", foreground);
84
85 /* Initialize RPC stuff */
86- rpc_init("nfsd", NFS_PROGRAM, nfsd_versions, nfs_dispatch,
87+ rpc_init("nfsd", nfs_prog, nfsd_versions, nfs_dispatch,
88 nfsport, NFS_MAXDATA);
89
90 if (_rpcpmstart) {
91@@ -1145,7 +1156,10 @@ main(int argc, char **argv)
92 /* Initialize the AUTH module. */
93 auth_init(auth_file);
94
95- setpidpath(_PATH_NFSD_PIDFILE);
96+ if (nfs_pid_file == 0)
97+ nfs_pid_file = _PATH_NFSD_PIDFILE;
98+ setpidpath(nfs_pid_file);
99+
100 if (failsafe_level == 0) {
101 /* Start multiple copies of the server */
102 writepid(getpid(), 1);
103@@ -1215,9 +1229,11 @@ usage(FILE *fp, int n)
104 fprintf(fp,
105 "Usage: %s [-Fhnpv] [-d kind] [-f exports-file] [-P port] [--version]\n"
106 " [--debug kind] [--exports-file=file] [--port port]\n"
107+" [--prog alternate_rpc_port_nubmer]\n"
108 " [--allow-non-root] [--promiscuous] [--version] [--foreground]\n"
109 " [--re-export] [--log-transfers] [--public-root path]\n"
110 " [--no-spoof-trace] [--no-cross-mounts] [--hashed-inodes] [--help]\n"
111+" [--nfs-pid file]\n"
112 , program_name);
113 exit(n);
114 }
115@@ -1234,7 +1250,7 @@ sigterm(int sig)
116 static void
117 terminate(void)
118 {
119- rpc_exit(NFS_PROGRAM, nfsd_versions);
120+ rpc_exit(nfs_prog, nfsd_versions);
121 efs_shutdown();
122 }
123
124Index: nfs-server-2.2beta47/mountd.c
125===================================================================
126--- nfs-server-2.2beta47.orig/mountd.c
127+++ nfs-server-2.2beta47/mountd.c
128@@ -42,6 +42,7 @@ int hashed_inodes; /* dummy */
129 static void usage(FILE *, int);
130 static void terminate(void);
131 static RETSIGTYPE sigterm(int sig);
132+int mount_prog = MOUNTPROG;
133
134 /*
135 * Option table for mountd
136@@ -55,6 +56,7 @@ static struct option longopts[] =
137 { "help", 0, 0, 'h' },
138 { "allow-non-root", 0, 0, 'n' },
139 { "port", required_argument, 0, 'P' },
140+ { "prog", required_argument, 0, 'g' },
141 { "promiscous", 0, 0, 'p' },
142 { "re-export", 0, 0, 'r' },
143 { "no-spoof-trace", 0, 0, 't' },
144@@ -63,9 +65,11 @@ static struct option longopts[] =
145 { "no-cross-mounts", 0, 0, 'x' },
146 { "no-tcp", 0, 0, OPT_NOTCP },
147 { "loopback-only", 0, 0, OPT_LOOPBACK },
148+ { "mount-pid", required_argument, 0, 'N' },
149+ { "rmtab", required_argument, 0, 'R' },
150 { NULL, 0, 0, 0 }
151 };
152-static const char * shortopts = "Fd:f:hnpP:rtvz::";
153+static const char * shortopts = "Fd:f:g:hnN:pP:rRtvz::";
154
155 /*
156 * Table of supported versions
157@@ -318,6 +322,7 @@ main(int argc, char **argv)
158 int failsafe_level = 0;
159 int port = 0;
160 int c;
161+ char *mount_pid_file = NULL;
162
163 program_name = argv[0];
164
165@@ -340,9 +345,15 @@ main(int argc, char **argv)
166 case 'f':
167 auth_file = optarg;
168 break;
169+ case 'g':
170+ mount_prog = port = atoi(optarg);
171+ break;
172 case 'n':
173 allow_non_root = 1;
174 break;
175+ case 'N':
176+ mount_pid_file = strdup(optarg);
177+ break;
178 case 'P':
179 port = atoi(optarg);
180 if (port <= 0 || port > 65535) {
181@@ -354,6 +365,9 @@ main(int argc, char **argv)
182 case 'p':
183 promiscuous = 1;
184 break;
185+ case 'R':
186+ _PATH_RMTAB = strdup(optarg);
187+ break;
188 case 'r':
189 re_export = 1;
190 break;
191@@ -401,7 +415,7 @@ main(int argc, char **argv)
192 log_open("mountd", foreground);
193
194 /* Create services and register with portmapper */
195- rpc_init("mountd", MOUNTPROG, mountd_versions, mount_dispatch, port, 0);
196+ rpc_init("mountd", mount_prog, mountd_versions, mount_dispatch, port, 0);
197
198 if (_rpcpmstart) {
199 /* Always foreground mode */
200@@ -422,7 +436,9 @@ main(int argc, char **argv)
201 auth_init(auth_file);
202
203 /* Write pidfile */
204- setpidpath(_PATH_MOUNTD_PIDFILE);
205+ if (mount_pid_file == 0)
206+ mount_pid_file = _PATH_MOUNTD_PIDFILE;
207+ setpidpath(mount_pid_file);
208 writepid(getpid(), 1);
209
210 /* Failsafe mode */
211@@ -453,7 +469,9 @@ usage(FILE *fp, int n)
212 program_name);
213 fprintf(fp, " [--debug kind] [--help] [--allow-non-root]\n");
214 fprintf(fp, " [--promiscuous] [--version] [--port portnum]\n");
215+ fprintf(fp, " [--prog alternate_rpc_port_nubmer]\n");
216 fprintf(fp, " [--exports-file=file] [--no-cross-mounts]\n");
217+ fprintf(fp, " [--mount-pid file] [--rmtab file]\n");
218 exit(n);
219 }
220
221@@ -467,7 +485,7 @@ sigterm(int sig)
222 static void
223 terminate(void)
224 {
225- rpc_exit(MOUNTPROG, mountd_versions);
226+ rpc_exit(mount_prog, mountd_versions);
227 }
228
229 RETSIGTYPE
230Index: nfs-server-2.2beta47/rmtab.c
231===================================================================
232--- nfs-server-2.2beta47.orig/rmtab.c
233+++ nfs-server-2.2beta47/rmtab.c
234@@ -14,6 +14,8 @@ static char * rmtab_gethost(struct svc_r
235 static int rmtab_insert(char *, char *);
236 static void rmtab_file(char);
237
238+char *_PATH_RMTAB = _PATH_RMTAB_VAL;
239+
240 /*
241 * global top to linklist
242 */
243Index: nfs-server-2.2beta47/rmtab.h
244===================================================================
245--- nfs-server-2.2beta47.orig/rmtab.h
246+++ nfs-server-2.2beta47/rmtab.h
247@@ -11,8 +11,9 @@
248 * Location of rmtab file. /etc/rmtab is the standard on most systems.
249 */
250 #include <paths.h>
251-#ifndef _PATH_RMTAB
252-#define _PATH_RMTAB "/etc/rmtab"
253+extern char *_PATH_RMTAB;
254+#ifndef _PATH_RMTAB_VAL
255+#define _PATH_RMTAB_VAL "/etc/rmtab"
256 #endif
257
258 extern void rmtab_add_client(dirpath, struct svc_req *);
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/018-remove-tcp-wrappers.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/018-remove-tcp-wrappers.patch
new file mode 100644
index 0000000000..95ecdee611
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/018-remove-tcp-wrappers.patch
@@ -0,0 +1,20 @@
1# Remove the requirement to link with libwrap
2# Patch origin: Wind River
3
4Index: nfs-server-2.2beta47/haccess.c
5===================================================================
6--- nfs-server-2.2beta47.orig/haccess.c 1999-04-08 08:47:19.000000000 -0400
7+++ nfs-server-2.2beta47/haccess.c 2006-08-07 17:05:31.868221639 -0400
8@@ -79,8 +79,12 @@
9 clients[hash] = hp;
10
11 hp->clnt_addr = addr;
12+#ifdef USE_TCP_WRAPPERS
13 hp->status = hosts_ctl(rpcprog, "unknown",
14 inet_ntoa(addr), "root");
15+#else
16+ hp->status = 1;
17+#endif
18 nrhosts++;
19 }
20
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/019-pid-before-fork.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/019-pid-before-fork.patch
new file mode 100644
index 0000000000..960ca8e47f
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/019-pid-before-fork.patch
@@ -0,0 +1,125 @@
1# Write a pid file before forking
2# Patch origin: Wind River
3
4Index: nfs-server-2.2beta47/daemon.c
5===================================================================
6--- nfs-server-2.2beta47.orig/daemon.c
7+++ nfs-server-2.2beta47/daemon.c
8@@ -15,6 +15,19 @@
9 static const char * pidfilename = 0;
10 static const char * get_signame(int signo);
11
12+void
13+writepid(pid_t pid, int clear)
14+{
15+ FILE *fp;
16+
17+ fp = fopen(pidfilename, clear? "w" : "a");
18+ if (fp == NULL)
19+ Dprintf(L_FATAL, "Unable to open %s: %m", pidfilename);
20+ fprintf(fp, "%d\n", pid);
21+ fclose(fp);
22+ return;
23+}
24+
25 /*
26 * Do the Crawley Thing
27 */
28@@ -33,8 +46,10 @@ daemonize(void)
29 Dprintf(L_FATAL, "unable to fork: %s", strerror(errno));
30
31 /* Parent process: exit */
32- if (c > 0)
33+ if (c > 0) {
34+ writepid(c, 1);
35 exit(0);
36+ }
37
38 /* Do the session stuff */
39 close(0);
40@@ -60,19 +75,6 @@ setpidpath(const char *filename)
41 }
42
43 void
44-writepid(pid_t pid, int clear)
45-{
46- FILE *fp;
47-
48- fp = fopen(pidfilename, clear? "w" : "a");
49- if (fp == NULL)
50- Dprintf(L_FATAL, "Unable to open %s: %m", pidfilename);
51- fprintf(fp, "%d\n", pid);
52- fclose(fp);
53- return;
54-}
55-
56-void
57 failsafe(int level, int ncopies)
58 {
59 int *servers, running, child, i;
60Index: nfs-server-2.2beta47/mountd.c
61===================================================================
62--- nfs-server-2.2beta47.orig/mountd.c
63+++ nfs-server-2.2beta47/mountd.c
64@@ -425,9 +425,6 @@ main(int argc, char **argv)
65 background_logging();
66 }
67
68- /* Become a daemon */
69- if (!foreground)
70- daemonize();
71
72 /* Initialize the FH module. */
73 fh_init();
74@@ -435,11 +432,15 @@ main(int argc, char **argv)
75 /* Initialize the AUTH module. */
76 auth_init(auth_file);
77
78- /* Write pidfile */
79 if (mount_pid_file == 0)
80 mount_pid_file = _PATH_MOUNTD_PIDFILE;
81 setpidpath(mount_pid_file);
82- writepid(getpid(), 1);
83+
84+ /* Become a daemon */
85+ if (!foreground)
86+ daemonize();
87+ else
88+ writepid(getpid(), 1);
89
90 /* Failsafe mode */
91 if (failsafe_level)
92Index: nfs-server-2.2beta47/nfsd.c
93===================================================================
94--- nfs-server-2.2beta47.orig/nfsd.c
95+++ nfs-server-2.2beta47/nfsd.c
96@@ -1147,11 +1147,6 @@ main(int argc, char **argv)
97 /* if (ncopies > 1)
98 read_only = 1; */
99
100- /*
101- * We first fork off a child and detach from tty
102- */
103- if (!foreground)
104- daemonize();
105
106 /* Initialize the AUTH module. */
107 auth_init(auth_file);
108@@ -1160,9 +1155,16 @@ main(int argc, char **argv)
109 nfs_pid_file = _PATH_NFSD_PIDFILE;
110 setpidpath(nfs_pid_file);
111
112+ /*
113+ * We first fork off a child and detach from tty
114+ */
115+ if (!foreground)
116+ daemonize();
117+ else
118+ writepid(getpid(), 1);
119+
120 if (failsafe_level == 0) {
121 /* Start multiple copies of the server */
122- writepid(getpid(), 1);
123 for (i = 1; i < ncopies; i++) {
124 pid_t pid;
125
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/020-undefined-chmod-fix.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/020-undefined-chmod-fix.patch
new file mode 100644
index 0000000000..0f1108c214
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/020-undefined-chmod-fix.patch
@@ -0,0 +1,18 @@
1# Fix a problem with chmod attributes when using no_squash_all
2# Patch origin: Wind River
3
4---
5 setattr.c | 2 +-
6 1 file changed, 1 insertion(+), 1 deletion(-)
7
8--- a/setattr.c
9+++ b/setattr.c
10@@ -115,7 +115,7 @@ nfsstat setattr(char *path, sattr *attr,
11 }
12 }
13
14- if (flags & SATTR_CHMOD) {
15+ if (flags & SATTR_CHMOD && attr->mode != -1) {
16 unsigned int mode = attr->mode;
17
18 /* If setuid is not allowed, silently squash them */
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/021-nolibwrap.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/021-nolibwrap.patch
new file mode 100644
index 0000000000..c0901fadcc
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/021-nolibwrap.patch
@@ -0,0 +1,20 @@
1# Remove libwrap linkage
2# Patch origin: Wind River
3
4---
5 configure.in | 4 ++--
6 1 file changed, 2 insertions(+), 2 deletions(-)
7
8--- a/configure.in
9+++ b/configure.in
10@@ -86,8 +86,8 @@ AC_AUTHDES_GETUCRED
11 AC_BROKEN_SETFSUID
12 AC_MOUNTLIST
13 AC_FSUSAGE
14-AC_CHECK_LIB(wrap, main)
15-AC_LIBWRAP_BUG
16+dnl AC_CHECK_LIB(wrap, main)
17+dnl AC_LIBWRAP_BUG
18 AC_BSD_SIGNALS
19
20 dnl **************************************************************
diff --git a/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/022-add-close-on-exec-descriptors.patch b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/022-add-close-on-exec-descriptors.patch
new file mode 100644
index 0000000000..011ae74cde
--- /dev/null
+++ b/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/022-add-close-on-exec-descriptors.patch
@@ -0,0 +1,61 @@
1# Force socket fds to close on exec when used in conjunction with pseudo
2# Patch origin: Wind River
3
4---
5 nfsd.c | 8 ++++++++
6 rpcmisc.c | 9 +++++++++
7 ugidd.c | 8 ++++++++
8 3 files changed, 25 insertions(+)
9
10--- a/nfsd.c
11+++ b/nfsd.c
12@@ -630,6 +630,14 @@ nfsd_nfsproc_create_2(createargs *argp,
13 if (S_ISSOCK(argp->attributes.mode)) {
14 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
15 return(nfs_errno());
16+ /* if there is a pseudo exec mark the socket to be
17+ * closed automatically
18+ */
19+ {
20+ long f_flags;
21+ f_flags = fcntl(s, F_GETFD);
22+ f_flags = fcntl(s, F_SETFD, f_flags | FD_CLOEXEC);
23+ }
24 sa.sun_family = AF_UNIX;
25 strncpy(sa.sun_path, pathbuf, sizeof(sa.sun_path));
26 sa.sun_path[sizeof(sa.sun_path)-1] = '\0';
27--- a/rpcmisc.c
28+++ b/rpcmisc.c
29@@ -197,6 +197,15 @@ makesock(int port, int proto, int socksz
30 Dprintf(L_FATAL, "Could not make a %s socket: %s\n",
31 prot_name, strerror(errno));
32
33+ /* if there is a pseudo exec mark the socket to be
34+ * closed automatically
35+ */
36+ {
37+ long f_flags;
38+ f_flags = fcntl(s, F_GETFD);
39+ f_flags = fcntl(s, F_SETFD, f_flags | FD_CLOEXEC);
40+ }
41+ fcntl(s, FD_CLOEXEC, 1);
42 memset((char *) &sin, 0, sizeof(sin));
43 sin.sin_family = AF_INET;
44 sin.sin_addr.s_addr = INADDR_ANY;
45--- a/ugidd.c
46+++ b/ugidd.c
47@@ -195,6 +195,14 @@ authenticate_1_svc(argp, rqstp)
48 destaddr.sin_port = htons(*argp);
49 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
50 goto bad;
51+ /* if there is a pseudo exec mark the socket to be
52+ * closed automatically
53+ */
54+ {
55+ long f_flags;
56+ f_flags = fcntl(s, F_GETFD);
57+ f_flags = fcntl(s, F_SETFD, f_flags | FD_CLOEXEC);
58+ }
59 setsockopt(s, SOL_SOCKET, SO_LINGER, 0, 0);
60 bzero((char *) &sendaddr, sizeof sendaddr);
61 /* find a reserved port */