Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 2 Apr 2019 23:51:09 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r345818 - head/sys/rpc/rpcsec_gss
Message-ID:  <201904022351.x32Np9Lh002428@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Tue Apr  2 23:51:08 2019
New Revision: 345818
URL: https://svnweb.freebsd.org/changeset/base/345818

Log:
  Fix a race in the RPCSEC_GSS server code that caused crashes.
  
  When a new client structure was allocated, it was added to the list
  so that it was visible to other threads before the expiry time was
  initialized, with only a single reference count.
  The caller would increment the reference count, but it was possible
  for another thread to decrement the reference count to zero and free
  the structure before the caller incremented the reference count.
  This could occur because the expiry time was still set to zero when
  the new client structure was inserted in the list and the list was
  unlocked.
  
  This patch fixes the race by initializing the reference count to two
  and initializing all fields, including the expiry time, before inserting
  it in the list.
  
  Tested by:	peter@ifm.liu.se
  PR:		235582
  MFC after:	2 weeks

Modified:
  head/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c

Modified: head/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c
==============================================================================
--- head/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c	Tue Apr  2 20:27:56 2019	(r345817)
+++ head/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c	Tue Apr  2 23:51:08 2019	(r345818)
@@ -568,19 +568,13 @@ svc_rpc_gss_create_client(void)
 
 	client = mem_alloc(sizeof(struct svc_rpc_gss_client));
 	memset(client, 0, sizeof(struct svc_rpc_gss_client));
-	refcount_init(&client->cl_refs, 1);
+	refcount_init(&client->cl_refs, 2);
 	sx_init(&client->cl_lock, "GSS-client");
 	getcredhostid(curthread->td_ucred, &hostid);
 	client->cl_id.ci_hostid = hostid;
 	getboottime(&boottime);
 	client->cl_id.ci_boottime = boottime.tv_sec;
 	client->cl_id.ci_id = svc_rpc_gss_next_clientid++;
-	list = &svc_rpc_gss_client_hash[client->cl_id.ci_id % svc_rpc_gss_client_hash_size];
-	sx_xlock(&svc_rpc_gss_lock);
-	TAILQ_INSERT_HEAD(list, client, cl_link);
-	TAILQ_INSERT_HEAD(&svc_rpc_gss_clients, client, cl_alllink);
-	svc_rpc_gss_client_count++;
-	sx_xunlock(&svc_rpc_gss_lock);
 
 	/*
 	 * Start the client off with a short expiration time. We will
@@ -590,6 +584,12 @@ svc_rpc_gss_create_client(void)
 	client->cl_locked = FALSE;
 	client->cl_expiration = time_uptime + 5*60;
 
+	list = &svc_rpc_gss_client_hash[client->cl_id.ci_id % svc_rpc_gss_client_hash_size];
+	sx_xlock(&svc_rpc_gss_lock);
+	TAILQ_INSERT_HEAD(list, client, cl_link);
+	TAILQ_INSERT_HEAD(&svc_rpc_gss_clients, client, cl_alllink);
+	svc_rpc_gss_client_count++;
+	sx_xunlock(&svc_rpc_gss_lock);
 	return (client);
 }
 
@@ -1287,7 +1287,6 @@ svc_rpc_gss(struct svc_req *rqst, struct rpc_msg *msg)
 			goto out;
 		}
 		client = svc_rpc_gss_create_client();
-		refcount_acquire(&client->cl_refs);
 	} else {
 		struct svc_rpc_gss_clientid *p;
 		if (gc.gc_handle.length != sizeof(*p)) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201904022351.x32Np9Lh002428>