- fix unusual NFS kernel client problem and add several fixes.

This commit is contained in:
Ian Kent 2016-03-04 06:52:13 +08:00
parent c3388d3bdd
commit eb3e266891
7 changed files with 767 additions and 1 deletions

View File

@ -0,0 +1,241 @@
am-utils-6.2 - add NFSv3 nfs_quick_reply() functionality
From: Ian Kent <raven@themaw.net>
The implementation of the NFS v3 server does not use the hack needed
by the nfs_quick_reply() function.
Now that saving the current transort for later use by nfs_quick_reply()
avoids concurrency races it should be ok to use it.
Signed-off-by: Ian Kent <raven@themaw.net>
---
amd/nfs_prot_svc.c | 13 +++++
amd/nfs_subr.c | 137 +++++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 120 insertions(+), 30 deletions(-)
diff --git a/amd/nfs_prot_svc.c b/amd/nfs_prot_svc.c
index cbde172..29b7551 100644
--- a/amd/nfs_prot_svc.c
+++ b/amd/nfs_prot_svc.c
@@ -180,7 +180,7 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
xdr_result = (xdrproc_t) xdr_diropres;
local = (nfssvcproc_t) nfsproc_lookup_2_svc;
/*
- * Cheap way to pass transp down to amfs_auto_lookuppn so it can
+ * Cheap way to pass transp down to amfs_auto_lookup so it can
* be stored in the am_node structure and later used for
* quick_reply().
*/
@@ -327,6 +327,8 @@ nfs_program_3(struct svc_req *rqstp, register SVCXPRT *transp)
xdrproc_t _xdr_argument, _xdr_result;
nfssvcproc_t local;
+ current_transp = NULL;
+
switch (rqstp->rq_proc) {
case AM_NFS3_NULL:
_xdr_argument = (xdrproc_t) xdr_void;
@@ -350,6 +352,12 @@ nfs_program_3(struct svc_req *rqstp, register SVCXPRT *transp)
_xdr_argument = (xdrproc_t) xdr_am_LOOKUP3args;
_xdr_result = (xdrproc_t) xdr_am_LOOKUP3res;
local = (nfssvcproc_t) (char *(*)(char *, struct svc_req *)) am_nfs3_lookup_3_svc;
+ /*
+ * Cheap way to pass transp down to amfs_auto_lookup so it can
+ * be stored in the am_node structure and later used for
+ * quick_reply().
+ */
+ current_transp = transp;
break;
case AM_NFS3_ACCESS:
@@ -476,6 +484,9 @@ nfs_program_3(struct svc_req *rqstp, register SVCXPRT *transp)
}
result = (*local) (&argument, rqstp);
+
+ current_transp = NULL;
+
if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) {
svcerr_systemerr (transp);
}
diff --git a/amd/nfs_subr.c b/amd/nfs_subr.c
index 07d960d..a383618 100644
--- a/amd/nfs_subr.c
+++ b/amd/nfs_subr.c
@@ -87,6 +87,9 @@ struct am_fh3 {
};
/* forward declarations */
+static int nfs_quick_reply2(am_node *mp, int error);
+static int nfs_quick_reply3(am_node *mp, int error);
+
/* converting am-filehandles to mount-points */
static am_node *fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop);
static am_node *fh_to_mp(am_nfs_fh *fhp);
@@ -255,46 +258,65 @@ nfsproc_lookup_2_svc(nfsdiropargs *argp, struct svc_req *rqstp)
return &res;
}
-
void
nfs_quick_reply(am_node *mp, int error)
{
- SVCXPRT *transp = mp->am_transp;
- nfsdiropres res;
- xdrproc_t xdr_result = (xdrproc_t) xdr_diropres;
+ int ret;
/*
- * If there's a transp structure then we can reply to the client's
- * nfs lookup request.
+ * If there's no transp structure then we can't reply to the
+ * client's nfs lookup request.
*/
- if (transp) {
- if (error == 0) {
- /*
- * Construct a valid reply to a lookup request. Same
- * code as in nfsproc_lookup_2_svc() above.
- */
- mp_to_fh(mp, &res.dr_u.dr_drok_u.drok_fhandle);
- res.dr_u.dr_drok_u.drok_attributes = mp->am_fattr;
- res.dr_status = NFS_OK;
- } else
- /*
- * Return the error that was passed to us.
- */
- res.dr_status = nfs_error(error);
+ if (!mp->am_transp)
+ return;
+
+ if (nfs_dispatcher == nfs_program_2)
+ ret = nfs_quick_reply2(mp, error);
+ else
+ ret = nfs_quick_reply3(mp, error);
+
+ if (!ret)
+ svcerr_systemerr(mp->am_transp);
+
+ /*
+ * Free up transp. It's only used for one reply.
+ */
+ put_nfs_xprt(mp->am_transp);
+ mp->am_transp = NULL;
+ dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount);
+}
+
+static int
+nfs_quick_reply2(am_node *mp, int error)
+{
+ SVCXPRT *transp = mp->am_transp;
+ nfsdiropres res;
+ xdrproc_t xdr_result = (xdrproc_t) xdr_diropres;
+ int ret;
+
+ if (error == 0) {
/*
- * Send off our reply
+ * Construct a valid reply to a lookup request. Same
+ * code as in nfsproc_lookup_2_svc() above.
*/
- if (!svc_sendreply(transp, (XDRPROC_T_TYPE) xdr_result, (SVC_IN_ARG_TYPE) & res))
- svcerr_systemerr(transp);
-
+ mp_to_fh(mp, &res.dr_u.dr_drok_u.drok_fhandle);
+ res.dr_u.dr_drok_u.drok_attributes = mp->am_fattr;
+ res.dr_status = NFS_OK;
+ } else
/*
- * Free up transp. It's only used for one reply.
+ * Return the error that was passed to us.
*/
- put_nfs_xprt(mp->am_transp);
- mp->am_transp = NULL;
- dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount);
- }
+ res.dr_status = nfs_error(error);
+
+ /*
+ * Send off our reply
+ */
+ ret = svc_sendreply(transp,
+ (XDRPROC_T_TYPE) xdr_result,
+ (SVC_IN_ARG_TYPE) & res);
+
+ return ret;
}
@@ -890,6 +912,8 @@ mp_to_fh(am_node *mp, am_nfs_fh *fhp)
/* dlog("mp_to_fh: old filehandle: %d", fp->u.s.fhh_id); */
}
}
+
+
void
mp_to_fh3(am_node *mp, am_nfs_fh3 *fhp)
{
@@ -1257,6 +1281,61 @@ am_nfs3_lookup_3_svc(am_LOOKUP3args *argp, struct svc_req *rqstp)
return &result;
}
+
+static int
+nfs_quick_reply3(am_node *mp, int error)
+{
+ SVCXPRT *transp = mp->am_transp;
+ xdrproc_t xdr_result = (xdrproc_t) xdr_am_LOOKUP3res;
+ am_LOOKUP3res result;
+ am_post_op_attr *post_op_dir;
+ am_post_op_attr *post_op_obj;
+ int ret;
+
+ if (error) {
+ /*
+ * Return the error that was passed to us.
+ */
+ post_op_dir->attributes_follow = 0;
+ result.status = nfs_error(error);
+ } else {
+ post_op_dir = &result.res_u.ok.dir_attributes;
+ post_op_obj = &result.res_u.ok.obj_attributes;
+ am_fattr3 *fattr3;
+ nfsfattr *fattr;
+
+ /*
+ * Construct a valid reply to a lookup request. Same
+ * code as in am_nfs3_lookup_3_svc() above.
+ */
+
+ /* dir attributes */
+ post_op_dir->attributes_follow = 1;
+ fattr3 = &post_op_dir->am_post_op_attr_u.attributes;
+ parent_fattr_to_fattr3(mp, fattr3);
+
+ mp_to_fh3(mp, &result.res_u.ok.object);
+
+ /* mount attributes */
+ post_op_obj->attributes_follow = 1;
+ fattr = &mp->am_fattr;
+ fattr3 = &post_op_obj->am_post_op_attr_u.attributes;
+ fattr_to_fattr3(fattr, fattr3);
+
+ result.status = AM_NFS3_OK;
+ }
+
+ /*
+ * Send off our reply
+ */
+ ret = svc_sendreply(transp,
+ (XDRPROC_T_TYPE) xdr_result,
+ (SVC_IN_ARG_TYPE) &result);
+
+ return ret;
+}
+
+
am_ACCESS3res *
am_nfs3_access_3_svc(am_ACCESS3args *argp, struct svc_req *rqstp)
{

View File

@ -0,0 +1,127 @@
am-utils-6.2 - add NFSv3 rpc request validation
From: Ian Kent <raven@themaw.net>
The NFS v2 internal server uses several validation checks for each
RPC request it receives, also add this validation for the NFS v3
internal server.
Signed-off-by: Ian Kent <raven@themaw.net>
---
amd/nfs_prot_svc.c | 65 +++++++++++++++++++++++++++++++---------------------
1 file changed, 39 insertions(+), 26 deletions(-)
diff --git a/amd/nfs_prot_svc.c b/amd/nfs_prot_svc.c
index 29b7551..cae12d4 100644
--- a/amd/nfs_prot_svc.c
+++ b/amd/nfs_prot_svc.c
@@ -71,30 +71,9 @@ dispatcher_t nfs_dispatcher = nfs_program_2;
typedef char *(*nfssvcproc_t)(voidp, struct svc_req *);
-void
-nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
+static int
+validate_rpc_request(struct svc_req *rqstp, SVCXPRT *transp)
{
- union {
- am_nfs_fh nfsproc_getattr_2_arg;
- nfssattrargs nfsproc_setattr_2_arg;
- nfsdiropargs nfsproc_lookup_2_arg;
- am_nfs_fh nfsproc_readlink_2_arg;
- nfsreadargs nfsproc_read_2_arg;
- nfswriteargs nfsproc_write_2_arg;
- nfscreateargs nfsproc_create_2_arg;
- nfsdiropargs nfsproc_remove_2_arg;
- nfsrenameargs nfsproc_rename_2_arg;
- nfslinkargs nfsproc_link_2_arg;
- nfssymlinkargs nfsproc_symlink_2_arg;
- nfscreateargs nfsproc_mkdir_2_arg;
- nfsdiropargs fsproc_rmdir_2_arg;
- nfsreaddirargs nfsproc_readdir_2_arg;
- am_nfs_fh nfsproc_statfs_2_arg;
- } argument;
- char *result;
- xdrproc_t xdr_argument, xdr_result;
- nfssvcproc_t local;
-
#ifdef HAVE_TRANSPORT_TYPE_TLI
/*
* On TLI systems we don't use an INET network type, but a "ticlts" (see
@@ -109,7 +88,7 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
extern int __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid);
if (__rpc_get_local_uid(transp, &u) >= 0 && u != 0) {
plog(XLOG_WARNING, "ignoring request from UID %ld, must be 0", (long) u);
- return;
+ return 0;
}
# else /* not HAVE___RPC_GET_LOCAL_UID */
dlog("cannot verify local uid for rpc request");
@@ -126,7 +105,7 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
plog(XLOG_WARNING, "ignoring request from %s:%u, port not reserved",
inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
ntohs(sinp->sin_port));
- return;
+ return 0;
}
# endif /* MNT2_NFS_OPT_RESVPORT */
/* if the address does not match, ignore the request */
@@ -136,16 +115,47 @@ nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
plog(XLOG_WARNING, "ignoring request from %s:%u, not a local interface",
inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
ntohs(sinp->sin_port));
+ return 0;
}
} else {
plog(XLOG_WARNING, "ignoring request from %s:%u, expected %s",
inet_dquad(dq, sizeof(dq), sinp->sin_addr.s_addr),
ntohs(sinp->sin_port),
inet_dquad(dq2, sizeof(dq2), myipaddr.s_addr));
- return;
+ return 0;
}
}
#endif /* not HAVE_TRANPORT_TYPE_TLI */
+ return 1;
+}
+
+
+void
+nfs_program_2(struct svc_req *rqstp, SVCXPRT *transp)
+{
+ union {
+ am_nfs_fh nfsproc_getattr_2_arg;
+ nfssattrargs nfsproc_setattr_2_arg;
+ nfsdiropargs nfsproc_lookup_2_arg;
+ am_nfs_fh nfsproc_readlink_2_arg;
+ nfsreadargs nfsproc_read_2_arg;
+ nfswriteargs nfsproc_write_2_arg;
+ nfscreateargs nfsproc_create_2_arg;
+ nfsdiropargs nfsproc_remove_2_arg;
+ nfsrenameargs nfsproc_rename_2_arg;
+ nfslinkargs nfsproc_link_2_arg;
+ nfssymlinkargs nfsproc_symlink_2_arg;
+ nfscreateargs nfsproc_mkdir_2_arg;
+ nfsdiropargs fsproc_rmdir_2_arg;
+ nfsreaddirargs nfsproc_readdir_2_arg;
+ am_nfs_fh nfsproc_statfs_2_arg;
+ } argument;
+ char *result;
+ xdrproc_t xdr_argument, xdr_result;
+ nfssvcproc_t local;
+
+ if (!validate_rpc_request(rqstp, transp))
+ return;
current_transp = NULL;
@@ -327,6 +337,9 @@ nfs_program_3(struct svc_req *rqstp, register SVCXPRT *transp)
xdrproc_t _xdr_argument, _xdr_result;
nfssvcproc_t local;
+ if (!validate_rpc_request(rqstp, transp))
+ return;
+
current_transp = NULL;
switch (rqstp->rq_proc) {

View File

@ -0,0 +1,170 @@
am-utils-6.2 - add get_nfs_xprt() and put_nfs_xprt() functions
From: Ian Kent <raven@themaw.net>
The nfs_quick_reply() functionality relies on taking a copy of the
current transport for later use.
The problem with this is the context of the RPC message is kept in
the transport and if any RPC message arrives before nfs_quick_reply()
is called that context will be corrupted.
So add a function get_nfs_xprt() to replace the current transport
with a new one returning the passed in transort so nfs_quick_reply()
can use it later.
A function put_nfs_xprt() is also added (although not really needed
since it just destroys the now unused transport) for completeness.
Signed-off-by: Ian Kent <raven@themaw.net>
---
conf/transp/transp_sockets.c | 44 ++++++++++++++++++++++++++++++++++++++++
conf/transp/transp_tli.c | 46 +++++++++++++++++++++++++++++++++++++++++-
include/am_utils.h | 2 ++
3 files changed, 91 insertions(+), 1 deletion(-)
diff --git a/conf/transp/transp_sockets.c b/conf/transp/transp_sockets.c
index 6326007..98f79c8 100644
--- a/conf/transp/transp_sockets.c
+++ b/conf/transp/transp_sockets.c
@@ -45,6 +45,7 @@
#include <am_defs.h>
#include <amu.h>
+static int soNFS = RPC_ANYSOCK;
/*
* find the IP address that can be used to connect to the local host
@@ -273,9 +274,52 @@ create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*
return 3;
}
+ soNFS = *soNFSp;
+
return 0; /* all is well */
}
+/*
+ * Get a pointer to the current NFS SVCXPRT and replace it
+ * with a new one.
+ */
+SVCXPRT *
+get_nfs_xprt(SVCXPRT *nfs_xprt)
+{
+ SVCXPRT *newxprt;
+ int newfd;
+
+ if (!nfs_xprt || soNFS == RPC_ANYSOCK)
+ return NULL;
+
+ newfd = dup(soNFS);
+ if (newfd < 0)
+ return NULL;
+
+ xprt_unregister(nfs_xprt);
+ newxprt = svcudp_create(newfd);
+ if (!newxprt) {
+ plog(XLOG_FATAL, "Can't switch to new transport");
+ xprt_register(nfs_xprt);
+ close(newfd);
+ return NULL;
+ }
+
+ soNFS = newfd;
+
+ return nfs_xprt;
+}
+
+/*
+ * Destroy a transport previously obtained by get_nfs_xprt().
+ */
+void put_nfs_xprt(SVCXPRT *nfs_xprt)
+{
+ if (!nfs_xprt || soNFS == RPC_ANYSOCK)
+ return;
+
+ svc_destroy(nfs_xprt);
+}
/*
* Create the amq service for amd (both TCP and UDP)
diff --git a/conf/transp/transp_tli.c b/conf/transp/transp_tli.c
index d26a511..ea565cc 100644
--- a/conf/transp/transp_tli.c
+++ b/conf/transp/transp_tli.c
@@ -45,7 +45,8 @@
#include <am_defs.h>
#include <amu.h>
-struct netconfig *nfsncp;
+struct netconfig *nfsncp = NULL;
+static int soNFS = RPC_ANYSOCK;
/*
@@ -456,9 +457,52 @@ create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*
return 1;
}
+ soNFS = *soNFSp;
+
return 0; /* all is well */
}
+/*
+ * Get a pointer to the current NFS SVCXPRT and replace it
+ * with a new one.
+ */
+SVCXPRT *
+get_nfs_xprt(SVCXPRT *nfs_xprt)
+{
+ SVCXPRT *newxprt;
+ int newfd;
+
+ if (!nfs_xprt || soNFS == RPC_ANYSOCK)
+ return NULL;
+
+ newfd = dup(soNFS);
+ if (newfd < 0)
+ return NULL;
+
+ xprt_unregister(nfs_xprt);
+ newxprt = svc_tli_create(newfd, nfsncp, NULL, 0, 0);
+ if (!newxprt) {
+ plog(XLOG_FATAL, "Can't switch to new transport");
+ xprt_register(nfs_xprt);
+ close(newfd);
+ return NULL;
+ }
+
+ soNFS = newfd;
+
+ return nfs_xprt;
+}
+
+/*
+ * Destroy a transport previously obtained by get_nfs_xprt().
+ */
+void put_nfs_xprt(SVCXPRT *nfs_xprt)
+{
+ if (!nfs_xprt || soNFS == RPC_ANYSOCK)
+ return;
+
+ svc_destroy(nfs_xprt);
+}
/*
* Bind to preferred AMQ port.
diff --git a/include/am_utils.h b/include/am_utils.h
index 0de881a..ff13c26 100644
--- a/include/am_utils.h
+++ b/include/am_utils.h
@@ -378,6 +378,8 @@ extern void compute_nfs_args(void *nap, mntent_t *mntp, int genflags, struct net
extern void destroy_nfs_args(void *nap, u_long nfs_version);
extern int create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, struct netconfig **udp_amqncpp, int *tcp_soAMQp, SVCXPRT **tcp_amqpp, struct netconfig **tcp_amqncpp, u_short preferred_amq_port);
extern int create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp), u_long nfs_version);
+extern SVCXPRT *get_nfs_xprt(SVCXPRT *nfs_xprt);
+extern void put_nfs_xprt(SVCXPRT *nfs_xprt);
extern int amu_svc_register(SVCXPRT *, u_long, u_long, void (*)(struct svc_req *, SVCXPRT *), u_long, struct netconfig *);
#ifdef HAVE_TRANSPORT_TYPE_TLI

View File

@ -0,0 +1,52 @@
am-utils-6.2 - fix wcc attr usage in unlink3_or_rmdir3()
From: Ian Kent <raven@themaw.net>
The definition of the wcc post op attributes should be am_fattr3 not
am_wcc_attr in unlink3_or_rmdir3().
Signed-off-by: Ian Kent <raven@themaw.net>
---
amd/nfs_subr.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/amd/nfs_subr.c b/amd/nfs_subr.c
index a383618..b88a40c 100644
--- a/amd/nfs_subr.c
+++ b/amd/nfs_subr.c
@@ -1058,7 +1058,8 @@ static am_nfsstat3 unlink3_or_rmdir3(am_diropargs3 *argp,
am_pre_op_attr *pre_op_dir = &wcc_data->before;
am_post_op_attr *post_op_dir = &wcc_data->after;
nfsfattr *fattr;
- am_wcc_attr *pre_op_wcc_attr, *post_op_wcc_attr;
+ am_wcc_attr *pre_op_wcc_attr;
+ am_fattr3 *post_op_wcc_attr;
am_node *mp, *ap;
int retry;
@@ -1085,7 +1086,7 @@ static am_nfsstat3 unlink3_or_rmdir3(am_diropargs3 *argp,
fattr_to_wcc_attr(fattr, pre_op_wcc_attr);
if (mp->am_fattr.na_type != NFDIR) {
- fattr_to_wcc_attr(fattr, post_op_wcc_attr);
+ fattr_to_fattr3(fattr, post_op_wcc_attr);
res = nfs_error(ENOTDIR);
goto out;
}
@@ -1105,14 +1106,14 @@ static am_nfsstat3 unlink3_or_rmdir3(am_diropargs3 *argp,
*/
else if (retry == ENOENT)
retry = 0;
- fattr_to_wcc_attr(fattr, post_op_wcc_attr);
+ fattr_to_fattr3(fattr, post_op_wcc_attr);
res = nfs_error(retry);
} else {
forcibly_timeout_mp(mp);
/* we can't wait for the expire so use the attributes as
* they are now for the post op wcc attributes.
*/
- fattr_to_wcc_attr(fattr, post_op_wcc_attr);
+ fattr_to_fattr3(fattr, post_op_wcc_attr);
res = AM_NFS3_OK;
}

View File

@ -0,0 +1,93 @@
am-utils-6.2 - use Linux libtirpc if present
From: Ian Kent <raven@themaw.net>
For Linux systems, if the header files and shared libraries of libtirpc
are present use them instead of the glibc RPC implementation.
Signed-off-by: Ian Kent <raven@themaw.net>
---
Makefile.am | 3 ++-
configure.ac | 4 ++++
include/am_compat.h | 8 ++++++--
m4/macros/check_linux_libtirpc.m4 | 13 +++++++++++++
4 files changed, 25 insertions(+), 3 deletions(-)
create mode 100644 m4/macros/check_linux_libtirpc.m4
diff --git a/Makefile.am b/Makefile.am
index bae4615..e094e95 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -146,7 +146,8 @@ EXTRA_DIST_M4 = \
m4/macros/type_xdrproc_t.m4 \
m4/macros/type_xfs_args.m4 \
m4/macros/type_yp_order_outorder.m4 \
- m4/macros/with_addon.m4
+ m4/macros/with_addon.m4 \
+ m4/macros/check_linux_libtirpc.m4
EXTRA_DIST_CONF = \
conf/autofs/autofs_default.h \
diff --git a/configure.ac b/configure.ac
index ce61925..98b444d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -222,6 +222,9 @@ dnl lots of code. So I am forced to use a special purpose macro that sets
dnl the libraries based on the OS. Sigh. -Erez.
AMU_CHECK_OS_LIBS
+dnl use Linux libtirpc if possible
+AMU_CHECK_LIBTIRPC
+
dnl librpc and librpcsvc are needed on Solaris
AC_CHECK_LIB(rpc, clnt_sperrno)
AC_CHECK_LIB(rpcsvc, xdr_fhandle)
@@ -433,6 +436,7 @@ AC_CHECK_HEADERS( \
arpa/nameser.h \
arpa/inet.h \
bsd/rpc/rpc.h \
+ tirpc/netconfig.h \
cdfs/cdfsmount.h \
cdfs/cdfs_mount.h \
fs/udf/udf_mount.h \
diff --git a/include/am_compat.h b/include/am_compat.h
index 3463f3f..d6826fc 100644
--- a/include/am_compat.h
+++ b/include/am_compat.h
@@ -454,11 +454,15 @@ struct hsfs_args {
/*
* Define a dummy struct netconfig for non-TLI systems
*/
-#if !defined(HAVE_NETCONFIG_H) && !defined(HAVE_SYS_NETCONFIG_H)
+#if !defined(HAVE_NETCONFIG_H)
+# if !defined(HAVE_SYS_NETCONFIG_H)
+# if !defined(HAVE_TIRPC_NETCONFIG_H)
struct netconfig {
int dummy;
};
-#endif /* not HAVE_NETCONFIG_H and not HAVE_SYS_NETCONFIG_H */
+# endif /* not HAVE_TIRPC_NETCONFIG_H */
+# endif /* not HAVE_SYS_NETCONFIG_H */
+#endif /* not HAVE_NETCONFIG_H */
/* some OSs don't define INADDR_NONE and assume it's unsigned -1 */
#ifndef INADDR_NONE
diff --git a/m4/macros/check_linux_libtirpc.m4 b/m4/macros/check_linux_libtirpc.m4
new file mode 100644
index 0000000..918423c
--- /dev/null
+++ b/m4/macros/check_linux_libtirpc.m4
@@ -0,0 +1,13 @@
+dnl ######################################################################
+dnl Check for Linux libtirpc library
+AC_DEFUN([AMU_CHECK_LIBTIRPC],[
+TIRPC_CPPFLAGS=""
+TIRPC_LIBS=""
+
+AC_CHECK_HEADER(tirpc/netconfig.h,[
+ TIRPC_CPPFLAGS="-I/usr/include/tirpc"
+ AC_DEFINE(HAVE_LIBTIRPC, 1, [Define to 1 if you have libtirpc headers installed])
+ AC_CHECK_LIB(tirpc, clnt_tli_create, [TIRPC_LIBS="-ltirpc"], [TIRPC_CPPFLAGS=""])])
+ AMU_CFLAGS="$ANU_CFLAGS $TIRPC_CPPFLAGS"
+ LIBS="$LIBS $TIRPC_LIBS"
+])

View File

@ -0,0 +1,60 @@
am-utils-6.2 - use new get_nfs_xprt() and put_nfs_xprt() functions
From: Ian Kent <raven@themaw.net>
The nfs_quick_reply() function needs to know the current RPC transport
outside of the NFS LOOKUP method call. It needs this to reply to the
NFS LOOKUP call that initiated the mount.
Now there are functions that avoid transport corruption if another
request comes in during the backgroud mount make nfs_quick_reply()
use them.
Signed-off-by: Ian Kent <raven@themaw.net>
---
amd/amfs_generic.c | 3 +--
amd/map.c | 2 +-
amd/nfs_subr.c | 3 ++-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/amd/amfs_generic.c b/amd/amfs_generic.c
index c352a32..86d0ab7 100644
--- a/amd/amfs_generic.c
+++ b/amd/amfs_generic.c
@@ -1129,8 +1129,7 @@ amfs_generic_mount_child(am_node *new_mp, int *error_return)
*/
if (current_transp && !new_mp->am_transp) {
dlog("Saving RPC transport for %s", new_mp->am_path);
- new_mp->am_transp = (SVCXPRT *) xmalloc(sizeof(SVCXPRT));
- *(new_mp->am_transp) = *current_transp;
+ new_mp->am_transp = get_nfs_xprt(current_transp);
}
if (error && new_mp->am_al && new_mp->am_al->al_mnt &&
(new_mp->am_al->al_mnt->mf_ops == &amfs_error_ops))
diff --git a/amd/map.c b/amd/map.c
index 0d404cf..bcb2156 100644
--- a/amd/map.c
+++ b/amd/map.c
@@ -471,7 +471,7 @@ free_map(am_node *mp)
XFREE(mp->am_name);
XFREE(mp->am_path);
XFREE(mp->am_pref);
- XFREE(mp->am_transp);
+ put_nfs_xprt(mp->am_transp);
if (mp->am_al)
free_loc(mp->am_al);
diff --git a/amd/nfs_subr.c b/amd/nfs_subr.c
index 0a43b98..07d960d 100644
--- a/amd/nfs_subr.c
+++ b/amd/nfs_subr.c
@@ -291,7 +291,8 @@ nfs_quick_reply(am_node *mp, int error)
/*
* Free up transp. It's only used for one reply.
*/
- XFREE(mp->am_transp);
+ put_nfs_xprt(mp->am_transp);
+ mp->am_transp = NULL;
dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount);
}
}

View File

@ -2,7 +2,7 @@ Summary: Automount utilities including an updated version of Amd
Name: am-utils
Version: 6.2.0
%define upstream_version 6.2
Release: 11%{?dist}
Release: 12%{?dist}
License: BSD
Epoch: 5
Group: System Environment/Daemons
@ -27,11 +27,13 @@ BuildRequires: systemd-units
BuildRequires: texinfo
BuildRequires: gcc
BuildRequires: m4
BuildRequires: libtirpc-devel
Requires: rpcbind
Requires: grep
Requires: gawk
Requires: findutils
Requires: libtirpc
Requires(pre): /bin/grep
Requires(post): /sbin/install-info
@ -51,6 +53,12 @@ Patch5: am-utils-6.2-fix-NFSv3-readdir-post_op_dir-attributes-return.patch
Patch6: am-utils-6.2-fix-NFSv3-unlink3_or_rmdir3-post_op-attributes-return.patch
Patch7: am-utils-6.2-fix-Linux-NFS-recognition-of-umounts.patch
Patch8: am-utils-6.2-add-get_nfs_xprt-and-put_nfs_xprt-functions.patch
Patch9: am-utils-6.2-use-new-get_nfs_xprt-and-put_nfs_xprt-functions.patch
Patch10: am-utils-6.2-add-NFSv3-nfs_quick_reply-functionality.patch
Patch11: am-utils-6.2-add-NFSv3-rpc-request-validation.patch
Patch12: am-utils-6.2-fix-wcc-attr-usage-in-unlink3_or_rmdir3.patch
Patch13: am-utils-6.2-use-linux-libtirpc-if-present.patch
# Not needed since autoreconf/libtool appear to do this automatically
# Leaving it set doesn't appear to be a problem so leave it set in
@ -82,6 +90,12 @@ mounting and unmounting filesystems.
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
./bootstrap
@ -193,6 +207,15 @@ fi
%{_libdir}/libamu.so*
%changelog
* Wed Mar 2 2016 Ian Kent <ikent@redhat.com> - 5:6.2.0-12
- add get_nfs_xprt() and put_nfs_xprt() functions.
- use new get_nfs_xprt() and put_nfs_xprt() functions.
- add NFSv3 nfs_quick_reply() functionality.
- use libtirpc instead of glibc RPC.
- add NFSv3 rpc request validation.
- fix wcc attr usage in unlink3_or_rmdir3().
- use Linux libtirpc if present.
* Mon Feb 29 2016 Ian Kent <ikent@redhat.com> - 5:6.2.0-11
- fix Linux NFS recognition of umounts.
- add systemd dependency on nfs-lock.service.