mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-02 18:52:04 +00:00
libs: make privilege escalation thread-safe
Privs escalation is process-wide, and a multi-threaded process can deadlock. This adds a mutex and a counter to the privs object, preventing multiple threads from making the privs escalation system call. Signed-off-by: Mark Stapp <mjs@voltanet.io>
This commit is contained in:
parent
b19abe1131
commit
c5c44d4b41
19
lib/privs.c
19
lib/privs.c
@ -706,6 +706,14 @@ struct zebra_privs_t *_zprivs_raise(struct zebra_privs_t *privs,
|
||||
if (!privs)
|
||||
return NULL;
|
||||
|
||||
/* If we're already elevated, just return */
|
||||
pthread_mutex_lock(&(privs->mutex));
|
||||
if (++privs->refcount > 1) {
|
||||
pthread_mutex_unlock(&(privs->mutex));
|
||||
return privs;
|
||||
}
|
||||
pthread_mutex_unlock(&(privs->mutex));
|
||||
|
||||
errno = 0;
|
||||
if (privs->change(ZPRIVS_RAISE)) {
|
||||
zlog_err("%s: Failed to raise privileges (%s)",
|
||||
@ -723,6 +731,14 @@ void _zprivs_lower(struct zebra_privs_t **privs)
|
||||
if (!*privs)
|
||||
return;
|
||||
|
||||
/* Don't lower privs if there's another caller */
|
||||
pthread_mutex_lock(&(*privs)->mutex);
|
||||
if (--((*privs)->refcount) > 0) {
|
||||
pthread_mutex_unlock(&(*privs)->mutex);
|
||||
return;
|
||||
}
|
||||
pthread_mutex_unlock(&(*privs)->mutex);
|
||||
|
||||
errno = 0;
|
||||
if ((*privs)->change(ZPRIVS_LOWER)) {
|
||||
zlog_err("%s: Failed to lower privileges (%s)",
|
||||
@ -743,6 +759,9 @@ void zprivs_preinit(struct zebra_privs_t *zprivs)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pthread_mutex_init(&(zprivs->mutex), NULL);
|
||||
zprivs->refcount = 0;
|
||||
|
||||
if (zprivs->vty_group) {
|
||||
/* in a "NULL" setup, this is allowed to fail too, but still
|
||||
* try. */
|
||||
|
10
lib/privs.h
10
lib/privs.h
@ -23,6 +23,8 @@
|
||||
#ifndef _ZEBRA_PRIVS_H
|
||||
#define _ZEBRA_PRIVS_H
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -59,6 +61,14 @@ struct zebra_privs_t {
|
||||
zebra_capabilities_t *caps_i; /* caps to allow inheritance of */
|
||||
int cap_num_p; /* number of caps in arrays */
|
||||
int cap_num_i;
|
||||
|
||||
/* Mutex and counter used to avoid race conditions in multi-threaded
|
||||
* processes. The privs elevation is process-wide, so we need to
|
||||
* avoid changing the privilege status across threads.
|
||||
*/
|
||||
pthread_mutex_t mutex;
|
||||
uint32_t refcount;
|
||||
|
||||
const char *user; /* user and group to run as */
|
||||
const char *group;
|
||||
const char *vty_group; /* group to chown vty socket to */
|
||||
|
Loading…
Reference in New Issue
Block a user