summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/lockd/mon.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 99aec744474c..8ae4c02d7dfd 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -9,6 +9,8 @@
#include <linux/types.h>
#include <linux/utsname.h>
#include <linux/kernel.h>
+#include <linux/ktime.h>
+
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/xprtsock.h>
#include <linux/sunrpc/svc.h>
@@ -240,13 +242,25 @@ static struct nsm_handle *nsm_lookup_priv(const struct nsm_private *priv)
* returned via NLMPROC_SM_NOTIFY, in the "priv" field of these
* requests.
*
- * Linux provides the raw IP address of the monitored host,
- * left in network byte order.
+ * The NSM protocol requires that these cookies be unique while the
+ * system is running. We prefer a stronger requirement of making them
+ * unique across reboots. If user space bugs cause a stale cookie to
+ * be sent to the kernel, it could cause the wrong host to lose its
+ * lock state if cookies were not unique across reboots.
+ *
+ * The cookies are exposed only to local user space via loopback. They
+ * do not appear on the physical network. If we want greater security
+ * for some reason, nsm_init_private() could perform a one-way hash to
+ * obscure the contents of the cookie.
*/
static void nsm_init_private(struct nsm_handle *nsm)
{
- __be32 *p = (__be32 *)&nsm->sm_priv.data;
- *p = nsm_addr_in(nsm)->sin_addr.s_addr;
+ u64 *p = (u64 *)&nsm->sm_priv.data;
+ struct timespec ts;
+
+ ktime_get_ts(&ts);
+ *p++ = timespec_to_ns(&ts);
+ *p = (unsigned long)nsm;
}
static struct nsm_handle *nsm_create_handle(const struct sockaddr *sap,
@@ -351,11 +365,7 @@ struct nsm_handle *nsm_reboot_lookup(const struct nlm_reboot *info)
spin_lock(&nsm_lock);
- if (nsm_use_hostnames && info->mon != NULL)
- cached = nsm_lookup_hostname(info->mon, info->len);
- else
- cached = nsm_lookup_priv(&info->priv);
-
+ cached = nsm_lookup_priv(&info->priv);
if (unlikely(cached == NULL)) {
spin_unlock(&nsm_lock);
dprintk("lockd: never saw rebooted peer '%.*s' before\n",