clnt_broadcast(3): don't free function pointers
Replace use of thr_getspecific/thr_setspecific to stash the function pointer we're smuggling between clnt_broadcast and rpc_wrap_bcast with a simple thread local variable. Clear it after use so the reference doesn't linger. In the relatively unlikely event clnt_broadcast was called from threads that exited prior to program termination, the previous code called free on a function pointer, which is undefined and might corrupted allocator state. Effort: CHERI upstreaming Reviewed by: glebius, jhb Sponsored by: DARPA, AFRL Differential Revision: https://reviews.freebsd.org/D54939
This commit is contained in:
+10
-25
@@ -307,19 +307,10 @@ registerrpc(int prognum, int versnum, int procnum,
|
||||
}
|
||||
|
||||
/*
|
||||
* All the following clnt_broadcast stuff is convulated; it supports
|
||||
* the earlier calling style of the callback function
|
||||
* Support the earlier calling style of the callback function with a
|
||||
* per-thread temporary copy of the real callback.
|
||||
*/
|
||||
static thread_key_t clnt_broadcast_key;
|
||||
static resultproc_t clnt_broadcast_result_main;
|
||||
static once_t clnt_broadcast_once = ONCE_INITIALIZER;
|
||||
|
||||
static void
|
||||
clnt_broadcast_key_init(void)
|
||||
{
|
||||
|
||||
thr_keycreate(&clnt_broadcast_key, free);
|
||||
}
|
||||
static _Thread_local resultproc_t clnt_broadcast_result;
|
||||
|
||||
/*
|
||||
* Need to translate the netbuf address into sockaddr_in address.
|
||||
@@ -334,14 +325,8 @@ rpc_wrap_bcast(char *resultp, struct netbuf *addr, struct netconfig *nconf)
|
||||
* struct netconfig *nconf; // Netconf of the transport
|
||||
*/
|
||||
{
|
||||
resultproc_t clnt_broadcast_result;
|
||||
|
||||
if (strcmp(nconf->nc_netid, "udp"))
|
||||
return (FALSE);
|
||||
if (thr_main())
|
||||
clnt_broadcast_result = clnt_broadcast_result_main;
|
||||
else
|
||||
clnt_broadcast_result = (resultproc_t)thr_getspecific(clnt_broadcast_key);
|
||||
return (*clnt_broadcast_result)(resultp,
|
||||
(struct sockaddr_in *)addr->buf);
|
||||
}
|
||||
@@ -363,16 +348,16 @@ clnt_broadcast(u_long prog, u_long vers, u_long proc, xdrproc_t xargs,
|
||||
* resultproc_t eachresult; // call with each result obtained
|
||||
*/
|
||||
{
|
||||
enum clnt_stat ret;
|
||||
|
||||
if (thr_main())
|
||||
clnt_broadcast_result_main = eachresult;
|
||||
else {
|
||||
thr_once(&clnt_broadcast_once, clnt_broadcast_key_init);
|
||||
thr_setspecific(clnt_broadcast_key, (void *) eachresult);
|
||||
}
|
||||
return rpc_broadcast((rpcprog_t)prog, (rpcvers_t)vers,
|
||||
clnt_broadcast_result = eachresult;
|
||||
|
||||
ret = rpc_broadcast((rpcprog_t)prog, (rpcvers_t)vers,
|
||||
(rpcproc_t)proc, xargs, argsp, xresults, resultsp,
|
||||
(resultproc_t) rpc_wrap_bcast, "udp");
|
||||
|
||||
clnt_broadcast_result = NULL;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user