Merge pull request #3972 from mjstapp/fix_privs_race

libs: fix race in privs changes
This commit is contained in:
Donald Sharp 2019-03-22 02:32:17 -04:00 committed by GitHub
commit 6e0d7d0dbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -708,12 +708,8 @@ struct zebra_privs_t *_zprivs_raise(struct zebra_privs_t *privs,
/* If we're already elevated, just return */ /* If we're already elevated, just return */
pthread_mutex_lock(&(privs->mutex)); pthread_mutex_lock(&(privs->mutex));
if (++privs->refcount > 1) { {
pthread_mutex_unlock(&(privs->mutex)); if (++(privs->refcount) == 1) {
return privs;
}
pthread_mutex_unlock(&(privs->mutex));
errno = 0; errno = 0;
if (privs->change(ZPRIVS_RAISE)) { if (privs->change(ZPRIVS_RAISE)) {
zlog_err("%s: Failed to raise privileges (%s)", zlog_err("%s: Failed to raise privileges (%s)",
@ -721,6 +717,10 @@ struct zebra_privs_t *_zprivs_raise(struct zebra_privs_t *privs,
} }
errno = save_errno; errno = save_errno;
privs->raised_in_funcname = funcname; privs->raised_in_funcname = funcname;
}
}
pthread_mutex_unlock(&(privs->mutex));
return privs; return privs;
} }
@ -733,19 +733,20 @@ void _zprivs_lower(struct zebra_privs_t **privs)
/* Don't lower privs if there's another caller */ /* Don't lower privs if there's another caller */
pthread_mutex_lock(&(*privs)->mutex); pthread_mutex_lock(&(*privs)->mutex);
if (--((*privs)->refcount) > 0) { {
pthread_mutex_unlock(&(*privs)->mutex); if (--((*privs)->refcount) == 0) {
return;
}
pthread_mutex_unlock(&(*privs)->mutex);
errno = 0; errno = 0;
if ((*privs)->change(ZPRIVS_LOWER)) { if ((*privs)->change(ZPRIVS_LOWER)) {
zlog_err("%s: Failed to lower privileges (%s)", zlog_err("%s: Failed to lower privileges (%s)",
(*privs)->raised_in_funcname, safe_strerror(errno)); (*privs)->raised_in_funcname,
safe_strerror(errno));
} }
errno = save_errno; errno = save_errno;
(*privs)->raised_in_funcname = NULL; (*privs)->raised_in_funcname = NULL;
}
}
pthread_mutex_unlock(&(*privs)->mutex);
*privs = NULL; *privs = NULL;
} }