diff options
Diffstat (limited to 'lib/privs.h')
| -rw-r--r-- | lib/privs.h | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/lib/privs.h b/lib/privs.h index 7fe59328b2..b061370b75 100644 --- a/lib/privs.h +++ b/lib/privs.h @@ -62,6 +62,7 @@ struct zebra_privs_t { int (*change)(zebra_privs_ops_t); /* change privileges, 0 on success */ zebra_privs_current_t (*current_state)( void); /* current privilege state */ + const char *raised_in_funcname; }; struct zprivs_ids_t { @@ -81,4 +82,42 @@ extern void zprivs_terminate(struct zebra_privs_t *); /* query for runtime uid's and gid's, eg vty needs this */ extern void zprivs_get_ids(struct zprivs_ids_t *); +/* + * Wrapper around zprivs, to be used as: + * frr_elevate_privs(&privs) { + * ... code ... + * if (error) + * break; -- break can be used to get out of the block + * ... code ... + * } + * + * The argument to frr_elevate_privs() can be NULL to leave privileges as-is + * (mostly useful for conditional privilege-raising, i.e.:) + * frr_elevate_privs(cond ? &privs : NULL) {} + * + * NB: The code block is always executed, regardless of whether privileges + * could be raised or not, or whether NULL was given or not. This is fully + * intentional; the user may have configured some RBAC or similar that we + * are not aware of, but that allows our code to proceed without privileges. + * + * The point of this wrapper is to prevent accidental bugs where privileges + * are elevated but then not dropped. This can happen when, for example, a + * "return", "goto" or "break" in the middle of the elevated-privilege code + * skips past the privilege dropping call. + * + * The macro below uses variable cleanup to drop privileges as soon as the + * code block is left in any way (and thus the _privs variable goes out of + * scope.) _once is just a trick to run the loop exactly once. + */ +extern struct zebra_privs_t *_zprivs_raise(struct zebra_privs_t *privs, + const char *funcname); +extern void _zprivs_lower(struct zebra_privs_t **privs); + +#define frr_elevate_privs(privs) \ + for (struct zebra_privs_t *_once = NULL, \ + *_privs __attribute__( \ + (unused, cleanup(_zprivs_lower))) = \ + _zprivs_raise(privs, __func__); \ + _once == NULL; _once = (void *)1) + #endif /* _ZEBRA_PRIVS_H */ |
