(From OE-Core rev: a0ae76f922816896bbdcd67dfa4e4f2b3e769184) Signed-off-by: Scott Garman <scott.a.garman@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
1278 lines
33 KiB
Diff
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;
|
|
}
|
|
|