generic-poky/meta/recipes-devtools/unfs-server/unfs-server-2.1+2.2beta47/006-reiserfs.patch

1278 lines
33 KiB
Diff

Upstream-Status: Inappropriate [other]
Upstream is not making further releases of this software.
Signed-off-by: Scott Garman <scott.a.garman@intel.com>
# Patch origin: nfs-server source RPM from openSUSE 10.3
--- nfs-server/Makefile.in
+++ nfs-server/Makefile.in 2002/11/08 13:59:16
@@ -100,7 +100,7 @@
utimes.c mkdir.c rename.c getopt.c getopt_long.c \
alloca.c mountlist.c xmalloc.c \
xstrdup.c strdup.c strstr.c nfsmounted.c faccess.c \
- haccess.c daemon.c signals.c
+ haccess.c daemon.c signals.c teahash3.c
XDRFILES = mount.x nfs_prot.x
GENFILES = mount.h mount_xdr.c mount_svc.c nfs_prot.h nfs_prot_xdr.c \
ugid.h ugid_xdr.c ugid_clnt.c
@@ -112,7 +112,7 @@
MANPAGES8 = showmount
MANPAGES = $(MANPAGES5) $(MANPAGES8p) $(MANPAGES8)
LIBOBJS = version.o fsusage.o mountlist.o xmalloc.o xstrdup.o \
- nfsmounted.o faccess.o haccess.o daemon.o \
+ nfsmounted.o faccess.o haccess.o daemon.o teahash3.o \
signals.o @LIBOBJS@ @ALLOCA@
OBJS = logging.o fh.o devtab.o auth_init.o auth_clnt.o auth.o
NFSD_OBJS = nfsd.o rpcmisc.o nfs_dispatch.o getattr.o setattr.o \
--- nfs-server/auth.c
+++ nfs-server/auth.c 2002/11/08 13:59:16
@@ -83,6 +83,7 @@
0, /* read-only */
0, /* relative links */
0, /* noaccess */
+ 0, /* hashed inodes */
1, /* cross_mounts */
1, /* allow setuid */
65534, /* default uid */
@@ -100,6 +101,7 @@
0, /* relative links */
0, /* noaccess */
1, /* cross_mounts */
+ 0, /* hashed inodes */
0, /* allow setuid */
65534, /* default uid */
65534, /* default gid */
@@ -991,6 +993,7 @@
if (mp == 0) {
mp = (nfs_mount*) xmalloc(sizeof(nfs_mount));
memset(mp, 0, sizeof(*mp));
+ mp->mount_dev = 0;
mp->origin = cp;
mp->client = cp;
mp->path = xstrdup(path);
@@ -1169,6 +1172,8 @@
default_options.nobody_gid = anon_gid;
anonymous_options.nobody_uid = anon_uid;
anonymous_options.nobody_gid = anon_gid;
+ default_options.cross_mounts = cross_mounts;
+ default_options.hashed_inodes = hashed_inodes;
memset(cached_clients, 0, sizeof(cached_clients));
cached_next = 0;
--- nfs-server/auth.h
+++ nfs-server/auth.h 2002/11/08 13:59:16
@@ -43,15 +43,16 @@
typedef struct nfs_options {
ugid_mapping_t uidmap; /* uid/gid mapping behavior */
- int root_squash;
- int all_squash;
- int some_squash; /* speed up luid() etc. */
- int secure_port;
- int read_only;
- int link_relative;
- int noaccess;
- int cross_mounts;
- int allow_setuid;
+ unsigned root_squash : 1;
+ unsigned all_squash : 1;
+ unsigned some_squash : 1; /* speed up luid() etc. */
+ unsigned secure_port : 1;
+ unsigned read_only : 1;
+ unsigned link_relative : 1;
+ unsigned noaccess : 1;
+ unsigned cross_mounts : 1;
+ unsigned hashed_inodes : 1;
+ unsigned allow_setuid : 1;
uid_t nobody_uid;
gid_t nobody_gid;
char * clnt_nisdomain;
@@ -64,6 +65,7 @@
int length;
char * path;
nfs_options o;
+ dev_t mount_dev;
/* Original NFS client */
struct nfs_client * origin;
} nfs_mount;
@@ -121,6 +123,8 @@
extern void auth_check_all_netmasks(void);
extern void auth_sort_all_mountlists(void);
extern void auth_log_all(void);
+extern int auth_checkdev(nfs_mount *, dev_t dev);
+extern int auth_checkpathdev(char *, dev_t dev);
/* This function lets us set our euid/fsuid temporarily */
extern void auth_override_uid(uid_t);
--- nfs-server/auth_clnt.c
+++ nfs-server/auth_clnt.c 2002/11/08 13:59:16
@@ -89,6 +89,13 @@
return NULL;
}
+ if (!mp->o.cross_mounts && !mp->mount_dev) {
+ struct stat st;
+ if (!lstat(mp->path, &st) < 0)
+ return NULL;
+ mp->mount_dev = st.st_dev;
+ }
+
/* Check request originated on a privileged port. */
if (!allow_non_root && mp->o.secure_port
&& !SECURE_PORT(svc_getcaller(rqstp->rq_xprt)->sin_port)) {
@@ -350,3 +357,28 @@
return 1;
}
#endif
+
+int auth_checkpathdev(char *path, dev_t dev)
+{
+ nfs_mount *mp = auth_match_mount(nfsclient, path);
+ if (!mp)
+ return 0;
+ return auth_checkdev(mp, dev);
+}
+
+int auth_checkdev(nfs_mount *mp, dev_t dev)
+{
+ if (!mp->mount_dev)
+ return 1;
+ if (mp->mount_dev != dev) {
+ struct stat st;
+ /* Restat in case the cd switched */
+ if (efs_lstat(mp->path, &st) < 0) {
+ Dprintf(L_ERROR, "Unable to stat mount point %s\n", mp->path);
+ return 0;
+ }
+ mp->mount_dev = st.st_dev;
+ }
+ return mp->mount_dev == dev;
+}
+
--- nfs-server/auth_init.c
+++ nfs-server/auth_init.c 2002/11/08 13:59:16
@@ -320,6 +320,14 @@
/* knfsd compatibility, ignore */;
else ifkwd(4, "sync")
/* knfsd compatibility, ignore */;
+ else ifkwd(13, "hashed_inodes")
+ mp->o.hashed_inodes = 1;
+ else ifkwd(16, "no_hashed_inodes")
+ mp->o.hashed_inodes = 0;
+ else ifkwd(12, "cross_mounts")
+ mp->o.cross_mounts = 1;
+ else ifkwd(15, "no_cross_mounts")
+ mp->o.cross_mounts = 0;
else {
Dprintf(L_ERROR,
"Unknown keyword \"%.*s\" in export file\n",
--- nfs-server/exports.man
+++ nfs-server/exports.man 2002/11/08 13:59:16
@@ -208,6 +208,17 @@
.IR no_all_squash ,
which is the default setting.
.TP
+.IR hashed_inodes
+Use a special scheme to generate inode numbers that may work better with
+reiserfs filesystems.
+.IR no_hashed_inodes
+which uses a direct mapping is the default.
+.TP
+.IR cross_mounts
+Do not cross mount points in exports. Turning this off with
+.IR no_cross_mounts
+avoids inode number space conflicts when there are too many files.
+.TP
.IR map_daemon
This option turns on dynamic uid/gid mapping. Each uid in an NFS request
will be translated to the equivalent server uid, and each uid in an
--- nfs-server/fh.c
+++ nfs-server/fh.c 2002/11/08 14:11:31
@@ -4,8 +4,9 @@
*
* Interfaces:
* pseudo_inode
- * mostly used internally, but also called from unfsd.c
- * when reporting directory contents.
+ * mostly used internally, for hash tables
+ * visible_inode
+ * generate visible inode shown to the client in the fattr.
* fh_init
* Initializes the queues and 'flush' timer
* fh_pr
@@ -47,6 +48,8 @@
* Note: the original code mistakenly assumes that the overall path
* length remains within the value given by PATH_MAX... that leads
* to interesting buffer overflows all over the place.
+ *
+ * Depends that dev_t only uses 16bits.
*/
#include <assert.h>
@@ -137,9 +140,9 @@
};
/* Forward declared local functions */
-static psi_t path_psi(char *, nfsstat *, struct stat *, int);
+static psi_t path_psi(char *, nfsstat *, struct stat *, int, int *);
static psi_t path_psi_m(char *, nfsstat *, struct stat *,
- struct stat *, int);
+ struct stat *, int, int *);
static int fh_flush_fds(void);
static char * fh_dump(svc_fh *);
static void fh_insert_fdcache(fhcache *fhc);
@@ -173,19 +176,22 @@
fh_list_size++;
/* Insert into hash tab. */
- hash_slot = &(fh_hashed[fhc->h.psi % HASH_TAB_SIZE]);
+ hash_slot = &(fh_hashed[pseudo_inode(fhc->h.ino,fhc->h.dev) % HASH_TAB_SIZE]);
fhc->hash_next = *hash_slot;
*hash_slot = fhc;
}
static fhcache *
-fh_lookup(psi_t psi)
+fh_lookup(ino_t ino, dev_t dev)
{
register fhcache *fhc;
- fhc = fh_hashed[psi % HASH_TAB_SIZE];
- while (fhc != NULL && fhc->h.psi != psi)
+ fhc = fh_hashed[pseudo_inode(ino,dev) % HASH_TAB_SIZE];
+ while (fhc != NULL) {
+ if (fhc->h.ino == ino && fhc->h.dev == dev)
+ break;
fhc = fhc->hash_next;
+ }
return (fhc);
}
@@ -193,7 +199,8 @@
fh_insert_fdcache(fhcache *fhc)
{
#ifdef FHTRACE
- Dprintf(D_FHTRACE, "insert fh %x into fdcache @%d\n", fhc->h.psi, fhc->fd);
+ Dprintf(D_FHTRACE, "insert fh %x,%x into fdcache @%d\n",
+ fhc->h.ino, fhc->h.dev, fhc->fd);
if (fhc->fd < 0) {
fh_complain("fd cache bug: bad fd", fhc);
return;
@@ -289,8 +296,9 @@
#endif
Dprintf(D_FHTRACE|D_FHCACHE,
- "fh_delete: deleting handle %x ('%s', fd=%d)\n",
- fhc, fhc->path ? fhc->path : "<unnamed>", fhc->fd);
+ "fh_delete: deleting handle %x [%x,%x] ('%s', fd=%d)\n",
+ fhc, fhc->h.dev, fhc->h.ino, fhc->path ? fhc->path : "<unnamed>",
+ fhc->fd);
/* Remove from current posn */
fhc->prev->next = fhc->next;
@@ -298,7 +306,7 @@
fh_list_size--;
/* Remove from hash tab */
- hash_slot = &(fh_hashed[fhc->h.psi % HASH_TAB_SIZE]);
+ hash_slot = &(fh_hashed[pseudo_inode(fhc->h.ino,fhc->h.dev) % HASH_TAB_SIZE]);
while (*hash_slot != NULL && *hash_slot != fhc)
hash_slot = &((*hash_slot)->hash_next);
if (*hash_slot == NULL)
@@ -528,6 +536,7 @@
index -= 8;
}
+#if 0
/* If we have an XXL inode number, spew out warning (but at most
* once a second) */
if (inode & ~mask) {
@@ -541,14 +550,34 @@
}
inode &= mask;
}
-
+#endif
return (psi_t) (prefix | inode);
#endif
}
+/* Inode as handed out by attr calls. */
+psi_t
+visible_inode(ino_t ino, dev_t dev, nfs_mount *mount)
+{
+ if (!mount->o.cross_mounts)
+ return ino;
+
+ if (mount->o.hashed_inodes) {
+ extern __u32 teahash3(/*u32 k[2], *//*u8*/const char *msg, int len);
+
+ struct {
+ ino_t ino;
+ dev_t dev;
+ } tup = { ino,dev };
+ return teahash3((char *) &tup, sizeof tup);
+ }
+
+ return pseudo_inode(ino, dev);
+}
+
#if 1
static char *
-fh_buildpath(svc_fh *h)
+fh_buildpath(svc_fh *h, dev_t basedev)
{
char pathbuf[PATH_MAX + NAME_MAX + 1], *path;
long cookie_stack[HP_LEN + 1];
@@ -565,13 +594,17 @@
if (efs_stat("/", &sbuf) < 0)
return (NULL);
- psi = pseudo_inode(sbuf.st_ino, sbuf.st_dev);
if (h->hash_path[0] == 0) {
- if (psi != h->psi)
- return (NULL);
- return xstrdup("/");
+ if (sbuf.st_ino == h->ino && sbuf.st_dev == h->dev)
+ ;
+ else
+ return NULL;
+ strcpy(pathbuf,"/");
+ path = xstrdup(pathbuf);
+ return (path);
}
+ psi = pseudo_inode(sbuf.st_ino, sbuf.st_dev);
if (hash_psi(psi) != h->hash_path[1])
return (NULL);
@@ -599,11 +632,18 @@
psi = pseudo_inode(dp->d_ino, sbuf.st_dev);
if (i == h->hash_path[0] + 1) {
- if (psi != h->psi)
+ if (sbuf.st_dev != h->dev || dp->d_ino != h->ino)
continue;
/* GOT IT */
strcpy(pathbuf + pathlen, dp->d_name);
- path = xstrdup(pathbuf);
+ if (!basedev || sbuf.st_dev == basedev ||
+ auth_checkpathdev(pathbuf, sbuf.st_dev)) {
+ path = xstrdup(pathbuf);
+ } else {
+ dprintf(L_ERROR, "fh_buildpath: basedev %x != dev %x for %s\n",
+ (unsigned)basedev,(unsigned)sbuf.st_dev,pathbuf);
+ path = NULL;
+ }
efs_closedir(dir);
auth_override_uid(auth_uid);
return (path);
@@ -754,16 +794,16 @@
#endif
static psi_t
-path_psi(char *path, nfsstat *status, struct stat *sbp, int svalid)
+path_psi(char *path, nfsstat *status, struct stat *sbp, int svalid, int *mp)
{
struct stat smounted;
- return path_psi_m(path, status, sbp, &smounted, svalid);
+ return path_psi_m(path, status, sbp, &smounted, svalid, mp);
}
static psi_t
path_psi_m(char *path, nfsstat *status,
- struct stat *sbp, struct stat *mbp, int svalid)
+ struct stat *sbp, struct stat *mbp, int svalid, int *mp)
{
struct stat sbuf, ddbuf;
@@ -815,6 +855,8 @@
DIR *dirp;
struct dirent *dp;
+ if (mp) *mp = 1;
+
errno = 0;
dirp = efs_opendir(dname);
fname[-1] = '/'; /* Restore path */
@@ -860,9 +902,70 @@
}
fhcache *
-fh_find(svc_fh *h, int mode)
+fh_newfh(svc_fh *h, int mode, dev_t basedev)
+{
+ fhcache *fhc, *flush;
+
+ ex_state = active;
+ for (flush = fh_tail.prev; fh_list_size > FH_CACHE_LIMIT; flush = fhc) {
+ /* Don't flush current head. */
+ if (flush == &fh_head)
+ break;
+ fhc = flush->prev;
+ fh_delete(flush);
+ }
+ fhc = (fhcache *) xmalloc(sizeof *fhc);
+ if (mode == FHFIND_FCREATE) {
+ /* File will be created */
+ fhc->path = NULL;
+ } else {
+ /* File must exist. Attempt to construct from hash_path */
+ char *path;
+
+ if ((path = fh_buildpath(h, basedev)) == NULL) {
+#ifdef FHTRACE
+ Dprintf(D_FHTRACE, "fh_find: stale fh (hash path)\n");
+ Dprintf(D_FHTRACE, "\tdata: %s\n", fh_dump(h));
+#endif
+ free(fhc);
+ ex_state = inactive;
+ return NULL;
+ }
+ fhc->path = path;
+ }
+ fhc->flags = 0;
+ if (fhc->path && efs_lstat(fhc->path, &fhc->attrs) >= 0) {
+ if (re_export && nfsmounted(fhc->path, &fhc->attrs))
+ fhc->flags |= FHC_NFSMOUNTED;
+ fhc->flags |= FHC_ATTRVALID;
+ }
+ fhc->fd = -1;
+ fhc->last_used = curtime;
+ fhc->h = *h;
+ fhc->last_clnt = NULL;
+ fhc->last_mount = NULL;
+ fhc->last_uid = (uid_t)-1;
+ fhc->fd_next = fhc->fd_prev = NULL;
+ fh_inserthead(fhc);
+ Dprintf(D_FHCACHE,
+ "fh_find: created new handle %x (path `%s' ino:%x dev:%x)\n",
+ fhc, fhc->path ? fhc->path : "<unnamed>", fhc->h.ino, fhc->h.dev);
+ ex_state = inactive;
+ if (fh_list_size > FH_CACHE_LIMIT)
+ flush_cache(0);
+#ifdef FHTRACE
+ if (fhc->h.hash_path[0] == 0xFF) {
+ Dprintf(L_ERROR, "newly created fh instantly flushed?!");
+ return NULL;
+ }
+#endif
+ return (fhc);
+}
+
+fhcache *
+fh_find(svc_fh *h, int mode, dev_t basedev)
{
- register fhcache *fhc, *flush;
+ register fhcache *fhc;
int check;
check = (mode & FHFIND_CHECK);
@@ -877,12 +980,12 @@
ex_state = active;
time(&curtime);
- while ((fhc = fh_lookup(h->psi)) != NULL) {
+ while ((fhc = fh_lookup(h->ino,h->dev)) != NULL) {
struct stat sbuf, *s = NULL;
nfsstat dummy;
- Dprintf(D_FHCACHE, "fh_find: psi=%lx... found '%s', fd=%d\n",
- (unsigned long) h->psi,
+ Dprintf(D_FHCACHE, "fh_find: (%u,%u)... found '%s', fd=%d\n",
+ h->ino, h->dev,
fhc->path ? fhc->path : "<unnamed>",
fhc->fd);
@@ -905,6 +1008,7 @@
Dprintf(D_FHTRACE,
"fh_find: stale fh: lstat: %m\n");
} else {
+ int mp = 0;
/* If device/ino don't match, fhc->path may
* be a mount point (hence lstat() returns
* a different inode number than the readdir()
@@ -915,19 +1019,26 @@
/* Get the dev/ino of the underlying
* mount point. */
- path_psi(fhc->path, &dummy, s, 1);
- if (fh_attrmatch(fhc, s))
- goto fh_return;
+ if (path_psi(fhc->path, &dummy, s, 1, &mp) &&
+ fh_attrmatch(fhc, s)) {
+ if (!mp)
+ Dprintf(D_FHTRACE,"fh_find: should be mount point %x,%x\n",
+ h->dev,h->ino);
+
+ }
- Dprintf(D_FHTRACE, "fh_find: stale fh: %lx",
- (unsigned long) h->psi);
+ Dprintf(D_FHTRACE, "fh_find: stale fh: "
+ "dev/ino %x/%lx ino:%x dev:%x",
+ s->st_dev, s->st_ino,
+ (unsigned)h->ino, (unsigned)h->dev);
}
fh_discard:
#ifdef FHTRACE
Dprintf(D_FHTRACE, "\tdata: %s\n", fh_dump(h));
#endif
- Dprintf(D_FHCACHE, "fh_find: delete cached handle\n");
+ Dprintf(D_FHCACHE, "fh_find: delete cached handle %x,%x <%x>\n",
+ fhc->h.dev,fhc->h.ino,fhc->path ? fhc->path : "no path");
fh_delete(fhc);
break;
}
@@ -947,88 +1058,13 @@
return (fhc);
}
- Dprintf(D_FHCACHE, "fh_find: psi=%lx... not found\n",
- (unsigned long) h->psi);
-
- if (mode == FHFIND_FCACHED) {
- ex_state = inactive;
- return NULL;
- }
-
- for (flush = fh_tail.prev; fh_list_size > FH_CACHE_LIMIT; flush = fhc) {
- /* Don't flush current head. */
- if (flush == &fh_head)
- break;
- fhc = flush->prev;
- fh_delete(flush);
- }
-
- fhc = (fhcache *) xmalloc(sizeof *fhc);
- if (mode == FHFIND_FCREATE) {
- /* File will be created */
- fhc->path = NULL;
- } else {
- /* File must exist. Attempt to construct from hash_path */
- char *path;
-
- if ((path = fh_buildpath(h)) == NULL) {
-#ifdef FHTRACE
- Dprintf(D_FHTRACE, "fh_find: stale fh (hash path)\n");
- Dprintf(D_FHTRACE, "\tdata: %s\n", fh_dump(h));
-#endif
- free(fhc);
- ex_state = inactive;
- return NULL;
- }
- fhc->path = path;
- }
-
- fhc->flags = 0;
- if (fhc->path && efs_lstat(fhc->path, &fhc->attrs) >= 0) {
- if (nfsmounted(fhc->path, &fhc->attrs)) {
- fhc->flags |= FHC_NFSMOUNTED;
-#if 0
- /* We must allow the client to send us the
- * file handle for the NFS mount point itself,
- * but not for entries within an NFS mount.
- * XXX: needs fixing.
- */
- if (!re_export) {
- Dprintf(D_FHTRACE,
- "Attempt to use %s (non-exportable)\n",
- fhc->path);
- free(fhc);
- ex_state = inactive;
- return NULL;
- }
-#endif
- }
- fhc->flags |= FHC_ATTRVALID;
- fhc->dev = fhc->attrs.st_dev;
- fhc->ino = fhc->attrs.st_ino;
- fhc->type = fhc->attrs.st_mode & S_IFMT;
- }
- fhc->fd = -1;
- fhc->last_used = curtime;
- fhc->h = *h;
- fhc->last_clnt = NULL;
- fhc->last_mount = NULL;
- fhc->last_uid = (uid_t)-1;
- fhc->fd_next = fhc->fd_prev = NULL;
- fh_inserthead(fhc);
- Dprintf(D_FHCACHE,
- "fh_find: created new handle %x (path `%s' psi %08x)\n",
- fhc, fhc->path ? fhc->path : "<unnamed>", fhc->h.psi);
ex_state = inactive;
- if (fh_list_size > FH_CACHE_LIMIT)
- flush_cache(0);
-#ifdef FHTRACE
- if (fhc->h.hash_path[0] == 0xFF) {
- Dprintf(L_ERROR, "newly created fh instantly flushed?!");
+
+ Dprintf(D_FHCACHE, "fh_find: (%u,%u) ... not found\n",
+ h->ino, h->dev);
+ if (mode == FHFIND_FCACHED)
return NULL;
- }
-#endif
- return (fhc);
+ return fh_newfh(h, mode, basedev);
}
/*
@@ -1040,7 +1076,7 @@
{
fhcache *h;
- if ((h = fh_find((svc_fh *) fh, FHFIND_FCACHED)) == NULL)
+ if ((h = fh_find((svc_fh *) fh, FHFIND_FCACHED, 0)) == NULL)
return fh_dump((svc_fh *) fh);
return (h->path);
}
@@ -1050,10 +1086,10 @@
{
static char buf[65];
char *sp;
- int i, n = fh->hash_path[0];
+ int i, n = fh->hash_path[0], l;
- sprintf(buf, "%08x %02x ", fh->psi, fh->hash_path[0]);
- for (i = 1, sp = buf + 12; i <= n && i < HP_LEN; i++, sp += 2)
+ l = sprintf(buf, "%08x %04x %02x ", fh->ino, fh->dev, fh->hash_path[0]);
+ for (i = 1, sp = buf + l; i <= n && i < HP_LEN; i++, sp += 2)
sprintf(sp, "%02x", fh->hash_path[i]);
return buf;
}
@@ -1082,7 +1118,7 @@
memset(&key, 0, sizeof(key));
status = NFS_OK;
- if ((psi = path_psi("/", &status, &stb, 0)) == 0)
+ if ((psi = path_psi("/", &status, &stb, 0, NULL)) == 0)
return ((int) status);
s = path;
@@ -1091,7 +1127,7 @@
return ((int) NFSERR_NAMETOOLONG);
key.hash_path[key.hash_path[0]] = hash_psi(psi);
*s = '\0';
- if ((psi = path_psi(path, &status, &stb, 0)) == 0)
+ if ((psi = path_psi(path, &status, &stb, 0, NULL)) == 0)
return ((int) status);
*s = '/';
}
@@ -1099,11 +1135,12 @@
if (++(key.hash_path[0]) >= HP_LEN)
return ((int) NFSERR_NAMETOOLONG);
key.hash_path[key.hash_path[0]] = hash_psi(psi);
- if ((psi = path_psi(path, &status, &stb, 0)) == 0)
+ if ((psi = path_psi(path, &status, &stb, 0, NULL)) == 0)
return ((int) status);
}
- key.psi = psi;
- h = fh_find(&key, FHFIND_FCREATE);
+ key.dev = stb.st_dev;
+ key.ino = stb.st_ino;
+ h = fh_find(&key, FHFIND_FCREATE, 0);
#ifdef FHTRACE
if (!h)
@@ -1123,6 +1160,7 @@
return ((int) status);
}
+#if 0
char *
fh_path(nfs_fh *fh, nfsstat *status)
{
@@ -1135,6 +1173,7 @@
*status = NFS_OK;
return (h->path);
}
+#endif
nfs_fh *
fh_handle(fhcache *h)
@@ -1349,7 +1388,7 @@
if (sbp == NULL)
sbp = &sbuf;
- if ((dirh = fh_find((svc_fh *) &dopa->dir, FHFIND_FEXISTS)) == NULL)
+ if ((dirh = fh_find((svc_fh *) &dopa->dir, FHFIND_FEXISTS, 0)) == NULL)
return NFSERR_STALE;
/*
@@ -1419,8 +1458,22 @@
*new_fh = dopa->dir;
key = (svc_fh *) new_fh;
- if ((key->psi = path_psi_m(pathbuf, &ret, sbp, &smount, 0)) == 0)
+
+ if (path_psi_m(pathbuf, &ret, sbp, &smount, 0, NULL) == 0)
return (ret);
+ key->ino = sbp->st_ino;
+ key->dev = sbp->st_dev;
+
+ if (sbp->st_dev != dirh->h.dev) {
+ nfs_mount *mp = dirh->last_mount;
+ if (!mp)
+ Dprintf(L_ERROR, "no last mount in fh_compose for %s\n", pathbuf);
+ else if (auth_checkdev(mp, sbp->st_dev) == 0) {
+ Dprintf(L_ERROR, "access to no cross path below mountpoint (<%s>, %x<->%x)\n",
+ pathbuf, mp->mount_dev, sbp->st_dev);
+ return NFSERR_STALE;
+ }
+ }
if (is_dd) {
/* Don't cd .. from root, or mysterious ailments will
@@ -1430,11 +1483,12 @@
} else {
if (++(key->hash_path[0]) >= HP_LEN)
return NFSERR_NAMETOOLONG;
- key->hash_path[key->hash_path[0]] = hash_psi(dirh->h.psi);
+ key->hash_path[key->hash_path[0]] = hash_psi(pseudo_inode(dirh->h.ino,
+ dirh->h.dev));
}
/* FIXME: when crossing a mount point, we'll find the real
* dev/ino in sbp and can store it in h... */
- h = fh_find(key, FHFIND_FCREATE);
+ h = fh_find(key, FHFIND_FCREATE, 0);
#ifdef FHTRACE
if (h == NULL)
@@ -1456,7 +1510,7 @@
/* We must have cached an old file under the same inode # */
Dprintf(D_FHTRACE, "Disposing of fh with bad path.\n");
fh_delete(h);
- h = fh_find(key, FHFIND_FCREATE);
+ h = fh_find(key, FHFIND_FCREATE, dirh->last_mount ? dirh->last_mount->mount_dev : 0);
#ifdef FHTRACE
if (!h) return NFSERR_STALE;
#endif
@@ -1511,12 +1565,14 @@
return (NFS_OK);
}
+#if 0
psi_t
fh_psi(nfs_fh *fh)
{
svc_fh *h = (svc_fh *) fh;
return (h->psi);
}
+#endif
void
fh_remove(char *path)
@@ -1524,12 +1580,13 @@
psi_t psi;
nfsstat status;
fhcache *fhc;
+ struct stat st;
- psi = path_psi(path, &status, NULL, 0);
+ psi = path_psi(path, &status, &st, 0, NULL);
if (psi == 0)
return;
ex_state = active;
- fhc = fh_lookup(psi);
+ fhc = fh_lookup(st.st_ino,st.st_dev);
if (fhc != NULL)
fh_delete(fhc);
@@ -1634,6 +1691,11 @@
fh_init(void)
{
static int initialized = 0;
+
+ if (sizeof(svc_fh) > 32) {
+ fprintf(stderr, "filehandle wrong size %d\n", sizeof(svc_fh));
+ exit(10);
+ }
if (initialized)
return;
--- nfs-server/fh.h
+++ nfs-server/fh.h 2002/11/08 13:59:16
@@ -20,6 +20,7 @@
#define FHC_XONLY_PATH 001 /* NOT USED ANYMORE */
#define FHC_ATTRVALID 002
#define FHC_NFSMOUNTED 004
+#define FHC_CROSS 010
/* Modes for fh_find */
#define FHFIND_FEXISTS 0 /* file must exist */
@@ -65,11 +66,12 @@
*
* hash_path[hash_path[0]+1] ... hash_path[HP_LEN-1] == 0
*/
-#define HP_LEN (NFS_FHSIZE - sizeof(psi_t))
+#define HP_LEN (NFS_FHSIZE-sizeof(u_int32_t)-sizeof(u_int16_t))
typedef struct {
- psi_t psi;
+ u_int32_t ino;
+ u_int16_t dev;
__u8 hash_path[HP_LEN];
-} svc_fh;
+} svc_fh __attribute__((packed));
typedef enum { inactive, active } mutex;
@@ -100,6 +102,7 @@
/* These are fixed during the lifetime of this object */
svc_fh h;
+ psi_t psi;
dev_t dev;
ino_t ino;
mode_t type; /* st_mode & S_IFMT */
@@ -122,10 +125,11 @@
/* Global function prototypes. */
extern nfsstat nfs_errno(void);
extern psi_t pseudo_inode(ino_t inode, dev_t dev);
+extern psi_t visible_inode(ino_t inode, dev_t dev, nfs_mount *);
extern void fh_init(void);
extern char *fh_pr(nfs_fh *fh);
extern int fh_create(nfs_fh *fh, char *path);
-extern fhcache *fh_find(svc_fh *h, int create);
+extern fhcache *fh_find(svc_fh *h, int create, dev_t basedev);
extern char *fh_path(nfs_fh *fh, nfsstat *status);
extern int path_open(char *path, int omode, int perm);
extern int fh_fd(fhcache *fhc, nfsstat *status, int omode);
@@ -139,6 +143,7 @@
extern void fh_flush(int force);
extern RETSIGTYPE flush_cache(int sig);
extern int nfsmounted(const char *path, struct stat *sbp);
+extern fhcache *fh_newfh(svc_fh *fh, int mode, dev_t basedev);
#ifdef ENABLE_DEVTAB
extern unsigned int devtab_index(dev_t);
--- nfs-server/getattr.c
+++ nfs-server/getattr.c 2002/11/08 13:59:16
@@ -43,7 +43,7 @@
{
fhcache *fhc;
- if ((fhc = fh_find((svc_fh*)fh, FHFIND_FEXISTS)) == NULL) {
+ if ((fhc = fh_find((svc_fh*)fh, FHFIND_FEXISTS, 0)) == NULL) {
Dprintf(D_CALL, "getattr: failed! No such file.\n");
return (NFSERR_STALE);
}
@@ -103,18 +103,8 @@
#else
attr->blocks = st_blocks(s);
#endif
-#if 0
- if (nfsmount->o.cross_mounts) {
- attr->fsid = 1;
- attr->fileid = fh_psi((nfs_fh *)&(fhc->h));
- } else {
- attr->fsid = s->st_dev;
- attr->fileid = covered_ino(fhc->path);
- }
-#else
- attr->fsid = 1;
- attr->fileid = fh_psi((nfs_fh *)&(fhc->h));
-#endif
+ attr->fsid = 1; // XXX
+ attr->fileid = visible_inode(fhc->h.ino, fhc->h.dev, nfsmount);
/* This may be needed by some Suns... testing */
#define MINTIME (24 * 2600)
--- nfs-server/mountd.c
+++ nfs-server/mountd.c 2002/11/08 13:59:16
@@ -36,6 +36,8 @@
#include "signals.h"
#include <rpc/pmap_clnt.h>
+int cross_mounts = 1;
+int hashed_inodes; /* dummy */
static void usage(FILE *, int);
static void terminate(void);
@@ -58,9 +60,9 @@
{ "no-spoof-trace", 0, 0, 't' },
{ "version", 0, 0, 'v' },
{ "fail-safe", optional_argument, 0, 'z' },
+ { "no-cross-mounts", 0, 0, 'x' },
{ "no-tcp", 0, 0, OPT_NOTCP },
{ "loopback-only", 0, 0, OPT_LOOPBACK },
-
{ NULL, 0, 0, 0 }
};
static const char * shortopts = "Fd:f:hnpP:rtvz::";
@@ -80,6 +82,7 @@
int need_reinit = 0;
int need_flush = 0;
extern char version[];
+nfs_client *nfsclient; /* dummy */
/*
* NULL
@@ -319,6 +322,9 @@
opterr = 0;
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != EOF)
switch (c) {
+ case 'x':
+ cross_mounts = 0;
+ break;
case 'F':
foreground = 1;
break;
@@ -444,7 +450,7 @@
program_name);
fprintf(fp, " [--debug kind] [--help] [--allow-non-root]\n");
fprintf(fp, " [--promiscuous] [--version] [--port portnum]\n");
- fprintf(fp, " [--exports-file=file]\n");
+ fprintf(fp, " [--exports-file=file] [--no-cross-mounts]\n");
exit(n);
}
--- nfs-server/nfsd.c
+++ nfs-server/nfsd.c 2002/11/08 14:20:57
@@ -72,7 +72,7 @@
{ "no-tcp", 0, 0, OPT_NOTCP },
{ "udp-only", 0, 0, OPT_NOTCP },
{ "loopback-only", 0, 0, OPT_LOOPBACK },
-
+ { "hashed-inodes", 0, 0, 'I' },
{ NULL, 0, 0, 0 }
};
static const char * shortopts = "a:d:Ff:hlnP:prR:tvz::";
@@ -91,6 +91,7 @@
int need_flush = 0; /* flush fh cache */
int read_only = 0; /* Global ro forced */
int cross_mounts = 1; /* Transparently cross mnts */
+int hashed_inodes = 0;
int log_transfers = 0; /* Log transfers */
static svc_fh public_fh; /* Public NFSv2 FH */
@@ -122,12 +123,17 @@
{
static int total = 0, cached = 0;
fhcache *fhc;
+ int newfh = 0;
- /* Try to map FH. If not cached, reconstruct path with root priv */
- fhc = fh_find((svc_fh *)fh, FHFIND_FEXISTS|FHFIND_CHECK);
- if (fhc == NULL) {
- *statp = NFSERR_STALE;
- return NULL;
+ /* Try to map FH. */
+ fhc = fh_find((svc_fh *)fh, FHFIND_FCACHED|FHFIND_CHECK, 0);
+ if (!fhc) {
+ fhc = fh_newfh((svc_fh*)fh, FHFIND_FEXISTS|FHFIND_CHECK, 0);
+ if (!fhc) {
+ *statp = NFSERR_STALE;
+ return NULL;
+ }
+ newfh = 1;
}
/* Try to retrieve last client who accessed this fh */
@@ -163,6 +169,16 @@
100 * (double) cached / total);
*/
+ /* Trust the crossmount check of the parent directory for creates */
+ if (newfh &&
+ (fhc->flags & FHC_ATTRVALID) &&
+ auth_checkdev(nfsmount, fhc->attrs.st_dev) == 0) {
+ Dprintf(L_ERROR, "auth_fh: fh crossed mount %s: %x<->%x\n",
+ fhc->path ? fhc->path : "???", nfsmount->mount_dev, fhc->attrs.st_dev);
+ *statp = NFSERR_STALE; /* or ACCES? */
+ return NULL;
+ }
+
if (nfsmount->o.noaccess &&
((flags & CHK_NOACCESS) || strcmp(nfsmount->path, fhc->path))) {
struct in_addr addr = svc_getcaller(rqstp->rq_xprt)->sin_addr;
@@ -195,6 +211,7 @@
fhcache *fhc;
nfsstat status;
char *path = buf, *sp;
+ struct stat st;
/* Authenticate directory file handle */
if ((fhc = auth_fh(rqstp, &dopa->dir, &status, flags)) == NULL)
@@ -219,6 +236,9 @@
if ((nfsmount = auth_path(nfsclient, rqstp, path)) == NULL)
return NFSERR_ACCES;
+ if (efs_lstat(path, &st) >= 0 && !auth_checkdev(nfsmount, st.st_dev))
+ return NFSERR_ACCES;
+
/* XXX: really need to call it again here?
* Already invoked in auth_fh */
if (!auth_user(nfsmount, rqstp))
@@ -318,7 +338,8 @@
int ispublic = 0;
/* First check whether this is the public FH */
- if (((svc_fh *) fh)->psi == 0 && !memcmp(fh, &public_fh, FHSIZE)) {
+ if (((svc_fh *) fh)->dev == 0 && ((svc_fh*)fh)->ino == 0 &&
+ !memcmp(fh, &public_fh, FHSIZE)) {
if (public_root_path == NULL)
return NFSERR_ACCES;
memcpy(&argp->dir, &public_root, NFS_FHSIZE);
@@ -333,6 +354,7 @@
if (!(fhc = auth_fh(rqstp, fh, &status, CHK_READ)))
return status;
+ /* FIXME: does too many stats */
status = fh_compose(argp, &dp->file, &sbuf, -1, -1, ispublic);
if (status != NFS_OK)
return status;
@@ -896,6 +918,9 @@
errno = 0;
if (efs_lstat(h->path, &sbuf) < 0 || !(S_ISDIR(sbuf.st_mode)))
return (NFSERR_NOTDIR);
+ if (!auth_checkdev(h->last_mount, sbuf.st_dev))
+ dotsonly = 1;
+
if ((dirp = efs_opendir(h->path)) == NULL)
return ((errno ? nfs_errno() : NFSERR_NAMETOOLONG));
@@ -923,7 +948,7 @@
}
e = *ep = (entry *) xmalloc(sizeof(entry));
- e->fileid = pseudo_inode(dp->d_ino, sbuf.st_dev);
+ e->fileid = visible_inode(dp->d_ino, sbuf.st_dev, h->last_mount);
e->name = xmalloc(NLENGTH(dp) + 1);
strcpy(e->name, dp->d_name);
dloc = htonl(efs_telldir(dirp));
@@ -1033,6 +1058,9 @@
case 'x':
cross_mounts = 0;
break;
+ case 'I':
+ hashed_inodes = 1;
+ break;
case 'z':
if (optarg)
failsafe_level = atoi(optarg);
@@ -1189,7 +1217,7 @@
" [--debug kind] [--exports-file=file] [--port port]\n"
" [--allow-non-root] [--promiscuous] [--version] [--foreground]\n"
" [--re-export] [--log-transfers] [--public-root path]\n"
-" [--no-spoof-trace] [--help]\n"
+" [--no-spoof-trace] [--no-cross-mounts] [--hashed-inodes] [--help]\n"
, program_name);
exit(n);
}
--- nfs-server/nfsd.h
+++ nfs-server/nfsd.h 2002/11/08 13:59:16
@@ -51,6 +51,7 @@
extern int need_reinit;
extern int need_flush;
extern time_t nfs_dispatch_time;
+extern int cross_mounts, hashed_inodes;
/* Include the other module definitions. */
#include "auth.h"
--- nfs-server/setattr.c
+++ nfs-server/setattr.c 2002/11/08 13:59:16
@@ -17,6 +17,7 @@
#define IGNORE_TIME ((unsigned int) -1)
+#if 0
/*
* Set file attributes based on file handle
*/
@@ -33,6 +34,7 @@
}
return setattr(path, attr, s, rqstp, flags);
}
+#endif
/*
* Set file attributes given the path. The flags argument
--- nfs-server/teahash3.c
+++ nfs-server/teahash3.c 2002/11/08 13:59:16
@@ -0,0 +1,168 @@
+/* Taken from the reiserfs source code and hacked slightly by AK.
+ * This is GPLed. */
+/*
+ * Keyed 32-bit hash function using TEA in a Davis-Meyer function
+ * H0 = Key
+ * Hi = E Mi(Hi-1) + Hi-1
+ *
+ * (see Applied Cryptography, 2nd edition, p448).
+ *
+ * Jeremy Fitzhardinge <jeremy@zip.com.au> 1998
+ *
+ * Jeremy has agreed to the contents of reiserfs/README. -Hans
+ */
+
+#include <assert.h>
+
+#if 0
+/* OK for Intel */
+typedef unsigned long u32;
+typedef const unsigned char u8;
+#else
+#include <inttypes.h>
+typedef uint32_t u32;
+typedef uint8_t u8;
+#endif
+
+
+#define DELTA 0x9E3779B9
+#define FULLROUNDS 10 /* 32 is overkill, 16 is strong crypto */
+#define PARTROUNDS 6 /* 6 gets complete mixing */
+
+/* a, b, c, d - data; h0, h1 - accumulated hash */
+#define TEACORE(rounds) \
+ do { \
+ u32 sum = 0; \
+ int n = rounds; \
+ u32 b0, b1; \
+ \
+ b0 = h0; \
+ b1 = h1; \
+ \
+ do \
+ { \
+ sum += DELTA; \
+ b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); \
+ b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); \
+ } while(--n); \
+ \
+ h0 += b0; \
+ h1 += b1; \
+ } while(0)
+
+u32 teahash3(/*u32 k[2], *//*u8*/const char *msg, int len)
+{
+ u32 k[] = { 0x9464a485, 0x542e1a94, 0x3e846bff, 0xb75bcfc3};
+
+ u32 h0 = k[0], h1 = k[1];
+ u32 a, b, c, d;
+ u32 pad;
+ int i;
+
+ assert(len >= 0 && len < 256);
+
+ pad = (u32)len | ((u32)len << 8);
+ pad |= pad << 16;
+
+ while(len >= 16)
+ {
+ a = (u32)msg[ 0] |
+ (u32)msg[ 1] << 8 |
+ (u32)msg[ 2] << 16|
+ (u32)msg[ 3] << 24;
+ b = (u32)msg[ 4] |
+ (u32)msg[ 5] << 8 |
+ (u32)msg[ 6] << 16|
+ (u32)msg[ 7] << 24;
+ c = (u32)msg[ 8] |
+ (u32)msg[ 9] << 8 |
+ (u32)msg[10] << 16|
+ (u32)msg[11] << 24;
+ d = (u32)msg[12] |
+ (u32)msg[13] << 8 |
+ (u32)msg[14] << 16|
+ (u32)msg[15] << 24;
+
+ TEACORE(PARTROUNDS);
+
+ len -= 16;
+ msg += 16;
+ }
+
+ if (len >= 12)
+ {
+ assert(len < 16);
+
+ a = (u32)msg[ 0] |
+ (u32)msg[ 1] << 8 |
+ (u32)msg[ 2] << 16|
+ (u32)msg[ 3] << 24;
+ b = (u32)msg[ 4] |
+ (u32)msg[ 5] << 8 |
+ (u32)msg[ 6] << 16|
+ (u32)msg[ 7] << 24;
+ c = (u32)msg[ 8] |
+ (u32)msg[ 9] << 8 |
+ (u32)msg[10] << 16|
+ (u32)msg[11] << 24;
+
+ d = pad;
+ for(i = 12; i < len; i++)
+ {
+ d <<= 8;
+ d |= msg[i];
+ }
+ }
+ else if (len >= 8)
+ {
+ assert(len < 12);
+
+ a = (u32)msg[ 0] |
+ (u32)msg[ 1] << 8 |
+ (u32)msg[ 2] << 16|
+ (u32)msg[ 3] << 24;
+ b = (u32)msg[ 4] |
+ (u32)msg[ 5] << 8 |
+ (u32)msg[ 6] << 16|
+ (u32)msg[ 7] << 24;
+
+ c = d = pad;
+ for(i = 8; i < len; i++)
+ {
+ c <<= 8;
+ c |= msg[i];
+ }
+ }
+ else if (len >= 4)
+ {
+ assert(len < 8);
+
+ a = (u32)msg[ 0] |
+ (u32)msg[ 1] << 8 |
+ (u32)msg[ 2] << 16|
+ (u32)msg[ 3] << 24;
+
+ b = c = d = pad;
+ for(i = 4; i < len; i++)
+ {
+ b <<= 8;
+ b |= msg[i];
+ }
+ }
+ else
+ {
+ assert(len < 4);
+
+ a = b = c = d = pad;
+ for(i = 0; i < len; i++)
+ {
+ a <<= 8;
+ a |= msg[i];
+ }
+ }
+
+ TEACORE(FULLROUNDS);
+
+/* return 0;*/
+ return h0^h1;
+}
--- nfs-server/ugid_map.c
+++ nfs-server/ugid_map.c 2002/11/08 13:59:16
@@ -276,8 +276,10 @@
if ((gid == 0 && mountp->o.root_squash) || mountp->o.all_squash)
retgid = mountp->o.nobody_gid;
+#if 0
Dprintf(D_UGID, "lgid(%s, %d) = %d\n",
inet_ntoa(mountp->client->clnt_addr), gid, retgid);
+#endif
return retgid;
}