1
0
forked from pool/nfs-utils

Compare commits

...

No commits in common. "devel" and "devel" have entirely different histories.
devel ... devel

10 changed files with 546 additions and 83 deletions

View File

@ -0,0 +1,99 @@
From 20c0797937e9ec43a78a2f5475d4296897f8c537 Mon Sep 17 00:00:00 2001
From: Olga Kornievskaia <kolga@netapp.com>
Date: Mon, 11 Dec 2023 08:46:35 -0500
Subject: [PATCH 1/6] gssd: revert commit a5f3b7ccb01c
In preparation for using rpc_gss_seccreate() function, revert commit
a5f3b7ccb01c "gssd: handle KRB5_AP_ERR_BAD_INTEGRITY for user
credentials"
Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
---
utils/gssd/gssd_proc.c | 2 --
utils/gssd/krb5_util.c | 42 ------------------------------------------
utils/gssd/krb5_util.h | 1 -
3 files changed, 45 deletions(-)
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index a96647df..e5cc1d98 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -419,8 +419,6 @@ create_auth_rpc_client(struct clnt_info *clp,
if (cred == GSS_C_NO_CREDENTIAL)
retval = gssd_refresh_krb5_machine_credential(clp->servername,
"*", NULL, 1);
- else
- retval = gssd_k5_remove_bad_service_cred(clp->servername);
if (!retval) {
auth = authgss_create_default(rpc_clnt, tgtname,
&sec);
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
index 6f66ef4f..f6ce1fec 100644
--- a/utils/gssd/krb5_util.c
+++ b/utils/gssd/krb5_util.c
@@ -1553,48 +1553,6 @@ gssd_acquire_user_cred(gss_cred_id_t *gss_cred)
return ret;
}
-/* Removed a service ticket for nfs/<name> from the ticket cache
- */
-int
-gssd_k5_remove_bad_service_cred(char *name)
-{
- krb5_creds in_creds, out_creds;
- krb5_error_code ret;
- krb5_context context;
- krb5_ccache cache;
- krb5_principal principal;
- int retflags = KRB5_TC_MATCH_SRV_NAMEONLY;
- char srvname[1024];
-
- ret = krb5_init_context(&context);
- if (ret)
- goto out_cred;
- ret = krb5_cc_default(context, &cache);
- if (ret)
- goto out_free_context;
- ret = krb5_cc_get_principal(context, cache, &principal);
- if (ret)
- goto out_close_cache;
- memset(&in_creds, 0, sizeof(in_creds));
- in_creds.client = principal;
- sprintf(srvname, "nfs/%s", name);
- ret = krb5_parse_name(context, srvname, &in_creds.server);
- if (ret)
- goto out_free_principal;
- ret = krb5_cc_retrieve_cred(context, cache, retflags, &in_creds, &out_creds);
- if (ret)
- goto out_free_principal;
- ret = krb5_cc_remove_cred(context, cache, 0, &out_creds);
-out_free_principal:
- krb5_free_principal(context, principal);
-out_close_cache:
- krb5_cc_close(context, cache);
-out_free_context:
- krb5_free_context(context);
-out_cred:
- return ret;
-}
-
#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
/*
* this routine obtains a credentials handle via gss_acquire_cred()
diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h
index 7ef87018..62c91a0e 100644
--- a/utils/gssd/krb5_util.h
+++ b/utils/gssd/krb5_util.h
@@ -22,7 +22,6 @@ char *gssd_k5_err_msg(krb5_context context, krb5_error_code code);
void gssd_k5_get_default_realm(char **def_realm);
int gssd_acquire_user_cred(gss_cred_id_t *gss_cred);
-int gssd_k5_remove_bad_service_cred(char *srvname);
#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
extern int limit_to_legacy_enctypes;
--
2.46.0

View File

@ -0,0 +1,51 @@
From f05af7d9924b5e455f4e750c1e8985c560784fce Mon Sep 17 00:00:00 2001
From: Olga Kornievskaia <kolga@netapp.com>
Date: Mon, 11 Dec 2023 08:50:57 -0500
Subject: [PATCH 2/6] gssd: revert commit 513630d720bd
In preparation for using rpc_gss_seccreate(), revert commit 513630d720bd
"gssd: handle KRB5_AP_ERR_BAD_INTEGRITY for machine credentials"
Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
---
utils/gssd/gssd_proc.c | 16 +---------------
1 file changed, 1 insertion(+), 15 deletions(-)
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index e5cc1d98..4fb6b72d 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -412,27 +412,13 @@ create_auth_rpc_client(struct clnt_info *clp,
tid, tgtname);
auth = authgss_create_default(rpc_clnt, tgtname, &sec);
if (!auth) {
- if (sec.minor_status == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
- printerr(2, "WARNING: server=%s failed context "
- "creation with KRB5_AP_ERR_BAD_INTEGRITY\n",
- clp->servername);
- if (cred == GSS_C_NO_CREDENTIAL)
- retval = gssd_refresh_krb5_machine_credential(clp->servername,
- "*", NULL, 1);
- if (!retval) {
- auth = authgss_create_default(rpc_clnt, tgtname,
- &sec);
- if (auth)
- goto success;
- }
- }
/* Our caller should print appropriate message */
printerr(2, "WARNING: Failed to create krb5 context for "
"user with uid %d for server %s\n",
uid, tgtname);
goto out_fail;
}
-success:
+
/* Success !!! */
rpc_clnt->cl_auth = auth;
*clnt_return = rpc_clnt;
--
2.46.0

View File

@ -0,0 +1,60 @@
From 3abf6b5223af0ccf07d217d71978ee7987acce88 Mon Sep 17 00:00:00 2001
From: Olga Kornievskaia <kolga@netapp.com>
Date: Mon, 11 Dec 2023 08:52:47 -0500
Subject: [PATCH 3/6] gssd: switch to using rpc_gss_seccreate()
If available from the libtirpc library, switch to using
rpc_gss_seccreate() instead of authgss_create_default() which does not
expose gss error codes.
Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
---
utils/gssd/gssd_proc.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index 4fb6b72d..99761157 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -70,6 +70,9 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <syscall.h>
+#ifdef HAVE_TIRPC_GSS_SECCREATE
+#include <rpc/rpcsec_gss.h>
+#endif
#include "gssd.h"
#include "err_util.h"
@@ -330,6 +333,11 @@ create_auth_rpc_client(struct clnt_info *clp,
struct timeval timeout;
struct sockaddr *addr = (struct sockaddr *) &clp->addr;
socklen_t salen;
+#ifdef HAVE_TIRPC_GSS_SECCREATE
+ rpc_gss_options_req_t req;
+ rpc_gss_options_ret_t ret;
+ char mechanism[] = "kerberos_v5";
+#endif
pthread_t tid = pthread_self();
sec.qop = GSS_C_QOP_DEFAULT;
@@ -410,7 +418,14 @@ create_auth_rpc_client(struct clnt_info *clp,
printerr(3, "create_auth_rpc_client(0x%lx): creating context with server %s\n",
tid, tgtname);
+#ifdef HAVE_TIRPC_GSS_SECCREATE
+ memset(&req, 0, sizeof(req));
+ req.my_cred = sec.cred;
+ auth = rpc_gss_seccreate(rpc_clnt, tgtname, mechanism,
+ rpcsec_gss_svc_none, NULL, &req, &ret);
+#else
auth = authgss_create_default(rpc_clnt, tgtname, &sec);
+#endif
if (!auth) {
/* Our caller should print appropriate message */
printerr(2, "WARNING: Failed to create krb5 context for "
--
2.46.0

View File

@ -0,0 +1,62 @@
From 2bfb59c6f50eb86c21f8e0c33bbf32ec53480fb8 Mon Sep 17 00:00:00 2001
From: Olga Kornievskaia <kolga@netapp.com>
Date: Mon, 11 Dec 2023 08:55:35 -0500
Subject: [PATCH 4/6] gssd: handle KRB5_AP_ERR_BAD_INTEGRITY for machine
credentials
During context establishment, when the client received
KRB5_AP_ERR_BAD_INTEGRITY error, it might be due to the server
updating its key material. To handle such error, get a new
service ticket and re-try the AP_REQ.
This functionality relies on the new API in libtirpc that
exposes the gss errors.
Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
---
utils/gssd/gssd_proc.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index 99761157..29600a3f 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -427,13 +427,32 @@ create_auth_rpc_client(struct clnt_info *clp,
auth = authgss_create_default(rpc_clnt, tgtname, &sec);
#endif
if (!auth) {
+#ifdef HAVE_TIRPC_GSS_SECCREATE
+ if (ret.minor_status == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
+ printerr(2, "WARNING: server=%s failed context "
+ "creation with KRB5_AP_ERR_BAD_INTEGRITY\n",
+ clp->servername);
+ if (cred == GSS_C_NO_CREDENTIAL)
+ retval = gssd_refresh_krb5_machine_credential(clp->servername,
+ "*", NULL, 1);
+ if (!retval) {
+ auth = rpc_gss_seccreate(rpc_clnt, tgtname,
+ mechanism, rpcsec_gss_svc_none,
+ NULL, &req, &ret);
+ if (auth)
+ goto success;
+ }
+ }
+#endif
/* Our caller should print appropriate message */
printerr(2, "WARNING: Failed to create krb5 context for "
"user with uid %d for server %s\n",
uid, tgtname);
goto out_fail;
}
-
+#ifdef HAVE_TIRPC_GSS_SECCREATE
+success:
+#endif
/* Success !!! */
rpc_clnt->cl_auth = auth;
*clnt_return = rpc_clnt;
--
2.46.0

View File

@ -0,0 +1,101 @@
From 15cd566633b1546f0808d0694ede094b4c99752d Mon Sep 17 00:00:00 2001
From: Olga Kornievskaia <kolga@netapp.com>
Date: Mon, 11 Dec 2023 08:57:28 -0500
Subject: [PATCH 5/6] gssd: handle KRB5_AP_ERR_BAD_INTEGRITY for user
credentials
Unlike the machine credential case, we can't throw away the ticket
cache and use the keytab to renew the credentials. Instead, we
need to remove the service ticket for the server that returned
KRB5_AP_ERR_BAD_INTEGRITY and try again.
Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
---
utils/gssd/gssd_proc.c | 2 ++
utils/gssd/krb5_util.c | 42 ++++++++++++++++++++++++++++++++++++++++++
utils/gssd/krb5_util.h | 1 +
3 files changed, 45 insertions(+)
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index 29600a3f..7629de0b 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -435,6 +435,8 @@ create_auth_rpc_client(struct clnt_info *clp,
if (cred == GSS_C_NO_CREDENTIAL)
retval = gssd_refresh_krb5_machine_credential(clp->servername,
"*", NULL, 1);
+ else
+ retval = gssd_k5_remove_bad_service_cred(clp->servername);
if (!retval) {
auth = rpc_gss_seccreate(rpc_clnt, tgtname,
mechanism, rpcsec_gss_svc_none,
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
index f6ce1fec..6f66ef4f 100644
--- a/utils/gssd/krb5_util.c
+++ b/utils/gssd/krb5_util.c
@@ -1553,6 +1553,48 @@ gssd_acquire_user_cred(gss_cred_id_t *gss_cred)
return ret;
}
+/* Removed a service ticket for nfs/<name> from the ticket cache
+ */
+int
+gssd_k5_remove_bad_service_cred(char *name)
+{
+ krb5_creds in_creds, out_creds;
+ krb5_error_code ret;
+ krb5_context context;
+ krb5_ccache cache;
+ krb5_principal principal;
+ int retflags = KRB5_TC_MATCH_SRV_NAMEONLY;
+ char srvname[1024];
+
+ ret = krb5_init_context(&context);
+ if (ret)
+ goto out_cred;
+ ret = krb5_cc_default(context, &cache);
+ if (ret)
+ goto out_free_context;
+ ret = krb5_cc_get_principal(context, cache, &principal);
+ if (ret)
+ goto out_close_cache;
+ memset(&in_creds, 0, sizeof(in_creds));
+ in_creds.client = principal;
+ sprintf(srvname, "nfs/%s", name);
+ ret = krb5_parse_name(context, srvname, &in_creds.server);
+ if (ret)
+ goto out_free_principal;
+ ret = krb5_cc_retrieve_cred(context, cache, retflags, &in_creds, &out_creds);
+ if (ret)
+ goto out_free_principal;
+ ret = krb5_cc_remove_cred(context, cache, 0, &out_creds);
+out_free_principal:
+ krb5_free_principal(context, principal);
+out_close_cache:
+ krb5_cc_close(context, cache);
+out_free_context:
+ krb5_free_context(context);
+out_cred:
+ return ret;
+}
+
#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
/*
* this routine obtains a credentials handle via gss_acquire_cred()
diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h
index 62c91a0e..7ef87018 100644
--- a/utils/gssd/krb5_util.h
+++ b/utils/gssd/krb5_util.h
@@ -22,6 +22,7 @@ char *gssd_k5_err_msg(krb5_context context, krb5_error_code code);
void gssd_k5_get_default_realm(char **def_realm);
int gssd_acquire_user_cred(gss_cred_id_t *gss_cred);
+int gssd_k5_remove_bad_service_cred(char *srvname);
#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
extern int limit_to_legacy_enctypes;
--
2.46.0

View File

@ -0,0 +1,35 @@
From 49567e7d03a5605c590be2135a24d4de8345fa3c Mon Sep 17 00:00:00 2001
From: Olga Kornievskaia <kolga@netapp.com>
Date: Mon, 11 Dec 2023 08:59:43 -0500
Subject: [PATCH 6/6] configure: check for rpc_gss_seccreate
If we have rpc_gss_sccreate in tirpc library define
HAVE_TIRPC_GSS_SECCREATE, which would allow us to handle bad_integrity
errors.
Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
---
aclocal/libtirpc.m4 | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/aclocal/libtirpc.m4 b/aclocal/libtirpc.m4
index bddae022..ef48a2ae 100644
--- a/aclocal/libtirpc.m4
+++ b/aclocal/libtirpc.m4
@@ -26,6 +26,11 @@ AC_DEFUN([AC_LIBTIRPC], [
[Define to 1 if your tirpc library provides libtirpc_set_debug])],,
[${LIBS}])])
+ AS_IF([test -n "${LIBTIRPC}"],
+ [AC_CHECK_LIB([tirpc], [rpc_gss_seccreate],
+ [AC_DEFINE([HAVE_TIRPC_GSS_SECCREATE], [1],
+ [Define to 1 if your tirpc library provides rpc_gss_seccreate])],,
+ [${LIBS}])])
AC_SUBST([AM_CPPFLAGS])
AC_SUBST(LIBTIRPC)
--
2.46.0

View File

@ -1,14 +1,21 @@
support/export/export.c | 2
support/include/misc.h | 3
support/include/nfslib.h | 1
================================================================================
From 374a756bc6d372d242dbcc1178f9ac2f34e0ab32 Mon Sep 17 00:00:00 2001
From: Petr Vorel <pvorel@suse.cz>
Date: Tue, 29 Oct 2024 11:10:37 +0100
Subject: [PATCH] exports: Ignore mount --bind
References: bcs#229583, https://bugzilla.suse.com/attachment.cgi?id=110519&action=diff
Upstream-status: SUSE specific workaround for nfs-utils 1.0.7 (SLES10-SP1), still needed?
Signed-off-by: Olaf Kirch <okir@suse.com>
Signed-off-by: Petr Vorel <pvorel@suse.cz>
---
support/nfs/exports.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/support/nfs/exports.c b/support/nfs/exports.c
index a6816e60..b9143718 100644
--- a/support/nfs/exports.c
+++ b/support/nfs/exports.c
@@ -684,6 +684,8 @@ bad_option:
@@ -792,6 +792,8 @@ bad_option:
} else if (strncmp(opt, "replicas=", 9) == 0) {
ep->e_fslocmethod = FSLOC_REPLICA;
ep->e_fslocdata = strdup(opt+9);
@ -17,3 +24,6 @@
} else if (strncmp(opt, "sec=", 4) == 0) {
active = parse_flavors(opt+4, ep);
if (!active)
--
2.45.2

3
nfs-utils-2.8.1.tar.xz Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a0be95b08396908048583fcf6b34a7c1ab49d53e8a12eb28673ccfd2eff0c505
size 739048

View File

@ -1,3 +1,43 @@
-------------------------------------------------------------------
Wed Dec 11 03:18:18 UTC 2024 - William Brown <william.brown@suse.com>
- Require system-user-nobody for nfs-client as the statd user relies
on `nogroup` from this package
-------------------------------------------------------------------
Tue Oct 29 10:05:55 UTC 2024 - Petr Vorel <pvorel@suse.cz>
- Update to version 2.8.1
- https://lore.kernel.org/linux-nfs/4a86eea3-973e-4535-8aa5-f3b8b5f7934d@redhat.com/
- https://kernel.org/pub/linux/utils/nfs-utils/2.8.1/2.8.1-Changelog
- Add new binary nfsdctl
- The default number of nfsd threads is now 16 instead of 8
- Removed patchs from previous releases
- 0001-exportfs-remove-warning-if-neither-subtree_check-or-.patch
- 0002-conffile-don-t-report-error-from-conf_init_file.patch
- 0003-conffile-allow-usr-etc-to-provide-any-config-files-e.patch
- 0004-fsidd-call-anonymous-sockets-by-their-name-only-don-.patch
- 0001-gssd-revert-commit-a5f3b7ccb01c.patch
- 0002-gssd-revert-commit-513630d720bd.patch
- 0003-gssd-switch-to-using-rpc_gss_seccreate.patch
- 0004-gssd-handle-KRB5_AP_ERR_BAD_INTEGRITY-for-machine-cr.patch
- 0005-gssd-handle-KRB5_AP_ERR_BAD_INTEGRITY-for-user-crede.patch
- 0006-configure-check-for-rpc_gss_seccreate.patch
- Turn nfs-utils-1.0.7-bind-syntax.patch to git patch (bug reference,
easier to refresh via git, likely it can be now removed)
- Add BuildRequires libnl-3.0, readline
-------------------------------------------------------------------
Tue Aug 20 20:21:14 UTC 2024 - Dirk Müller <dmueller@suse.com>
- add 0001-gssd-revert-commit-a5f3b7ccb01c.patch,
0002-gssd-revert-commit-513630d720bd.patch,
0003-gssd-switch-to-using-rpc_gss_seccreate.patch,
0004-gssd-handle-KRB5_AP_ERR_BAD_INTEGRITY-for-machine-cr.patch,
0005-gssd-handle-KRB5_AP_ERR_BAD_INTEGRITY-for-user-crede.patch,
0006-configure-check-for-rpc_gss_seccreate.patch: fixes for
libtirpc 1.3.5
-------------------------------------------------------------------
Mon Apr 22 02:56:13 UTC 2024 - Neil Brown <nfbrown@suse.com>

View File

@ -22,7 +22,7 @@
%endif
Name: nfs-utils
Version: 2.6.4
Version: 2.8.1
Release: 0
Summary: Support Utilities for Kernel nfsd
License: GPL-2.0-or-later
@ -42,10 +42,6 @@ Source25: rpc-svcgssd.options.conf
Source26: nfs.conf
Source27: nfs-kernel-server.tmpfiles.conf
Patch0: nfs-utils-1.0.7-bind-syntax.patch
Patch1: 0001-exportfs-remove-warning-if-neither-subtree_check-or-.patch
Patch2: 0002-conffile-don-t-report-error-from-conf_init_file.patch
Patch3: 0003-conffile-allow-usr-etc-to-provide-any-config-files-e.patch
Patch4: 0004-fsidd-call-anonymous-sockets-by-their-name-only-don-.patch
BuildRequires: e2fsprogs-devel
BuildRequires: gcc-c++
BuildRequires: libtool
@ -59,9 +55,11 @@ BuildRequires: pkgconfig(krb5)
BuildRequires: pkgconfig(libcap)
BuildRequires: pkgconfig(libevent)
BuildRequires: pkgconfig(libkeyutils)
BuildRequires: pkgconfig(libnl-3.0)
BuildRequires: pkgconfig(libtirpc)
BuildRequires: pkgconfig(libxml-2.0)
BuildRequires: pkgconfig(mount)
BuildRequires: pkgconfig(readline)
BuildRequires: pkgconfig(sqlite3)
Suggests: python-base
%{?systemd_ordering}
@ -77,6 +75,8 @@ Group: Productivity/Networking/NFS
Requires: keyutils
Requires: netcfg
Requires: rpcbind
# The statd user relies on 'nogroup' from system-user-nobody
Requires: system-user-nobody
Requires(post): %fillup_prereq
Requires(pre): permissions
Obsoletes: nfs-utils < 1.1.0
@ -368,6 +368,7 @@ fi
%{_sbindir}/rpc.mountd
%{_sbindir}/rpc.nfsd
%{_sbindir}/nfsdcltrack
%{_sbindir}/nfsdctl
%{_sbindir}/nfsref
%attr(0755,root,root) %{_sbindir}/nfsdclddb
%attr(0755,root,root) %{_sbindir}/nfsdclnts
@ -379,6 +380,7 @@ fi
%{_mandir}/man8/nfsref.8%{ext_man}
%{_mandir}/man8/rpc.mountd.8%{ext_man}
%{_mandir}/man8/rpc.nfsd.8%{ext_man}
%{_mandir}/man8/nfsdctl.8%{ext_man}
%{_mandir}/man8/nfsdcltrack.8%{ext_man}
%config(noreplace) %{_localstatedir}/lib/nfs/etab
%config(noreplace) %{_localstatedir}/lib/nfs/rmtab