]> git.puffer.fish Git - mirror/frr.git/commitdiff
libs: fix race in privs changes 3972/head
authorMark Stapp <mjs@voltanet.io>
Sun, 17 Mar 2019 17:25:16 +0000 (13:25 -0400)
committerMark Stapp <mjs@voltanet.io>
Sun, 17 Mar 2019 17:25:16 +0000 (13:25 -0400)
Use the privs struct mutex more strictly, to ensure that the
privs are at the level the caller expects when the apis
return.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
lib/privs.c

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