]> git.proxmox.com Git - mirror_frr.git/blobdiff - lib/privs.c
zebra, lib: fix the ZEBRA_INTERFACE_VRF_UPDATE zapi message
[mirror_frr.git] / lib / privs.c
index 81673f84a10b5ca3a0cf875a244fae41b0b69e88..838ff8fc928fae844c6cfad3a9401baf0a45c403 100644 (file)
@@ -24,6 +24,7 @@
 #include "log.h"
 #include "privs.h"
 #include "memory.h"
+#include "lib_errors.h"
 
 #ifdef HAVE_CAPABILITIES
 
@@ -99,131 +100,113 @@ static struct {
        pvalue_t *system_caps;
 } cap_map[ZCAP_MAX] = {
 #ifdef HAVE_LCAPS /* Quagga -> Linux capabilities mappings */
-       [ZCAP_SETID] =
-               {
-                       2,
-                       (pvalue_t[]){CAP_SETGID, CAP_SETUID},
-               },
-       [ZCAP_BIND] =
-               {
-                       1,
-                       (pvalue_t[]){CAP_NET_BIND_SERVICE},
-               },
-       [ZCAP_NET_ADMIN] =
-               {
-                       1,
-                       (pvalue_t[]){CAP_NET_ADMIN},
-               },
-       [ZCAP_NET_RAW] =
-               {
-                       1,
-                       (pvalue_t[]){CAP_NET_RAW},
-               },
-       [ZCAP_CHROOT] =
-               {
-                       1,
-                       (pvalue_t[]){
-                               CAP_SYS_CHROOT,
+               [ZCAP_SETID] =
+                       {
+                               2, (pvalue_t[]){CAP_SETGID, CAP_SETUID},
+                       },
+               [ZCAP_BIND] =
+                       {
+                               1, (pvalue_t[]){CAP_NET_BIND_SERVICE},
+                       },
+               [ZCAP_NET_ADMIN] =
+                       {
+                               1, (pvalue_t[]){CAP_NET_ADMIN},
+                       },
+               [ZCAP_NET_RAW] =
+                       {
+                               1, (pvalue_t[]){CAP_NET_RAW},
+                       },
+               [ZCAP_CHROOT] =
+                       {
+                               1,
+                               (pvalue_t[]){
+                                       CAP_SYS_CHROOT,
+                               },
+                       },
+               [ZCAP_NICE] =
+                       {
+                               1, (pvalue_t[]){CAP_SYS_NICE},
+                       },
+               [ZCAP_PTRACE] =
+                       {
+                               1, (pvalue_t[]){CAP_SYS_PTRACE},
+                       },
+               [ZCAP_DAC_OVERRIDE] =
+                       {
+                               1, (pvalue_t[]){CAP_DAC_OVERRIDE},
+                       },
+               [ZCAP_READ_SEARCH] =
+                       {
+                               1, (pvalue_t[]){CAP_DAC_READ_SEARCH},
+                       },
+               [ZCAP_SYS_ADMIN] =
+                       {
+                               1, (pvalue_t[]){CAP_SYS_ADMIN},
+                       },
+               [ZCAP_FOWNER] =
+                       {
+                               1, (pvalue_t[]){CAP_FOWNER},
                        },
-               },
-       [ZCAP_NICE] =
-               {
-                       1,
-                       (pvalue_t[]){CAP_SYS_NICE},
-               },
-       [ZCAP_PTRACE] =
-               {
-                       1,
-                       (pvalue_t[]){CAP_SYS_PTRACE},
-               },
-       [ZCAP_DAC_OVERRIDE] =
-               {
-                       1,
-                       (pvalue_t[]){CAP_DAC_OVERRIDE},
-               },
-       [ZCAP_READ_SEARCH] =
-               {
-                       1,
-                       (pvalue_t[]){CAP_DAC_READ_SEARCH},
-               },
-       [ZCAP_SYS_ADMIN] =
-               {
-                       1,
-                       (pvalue_t[]){CAP_SYS_ADMIN},
-               },
-       [ZCAP_FOWNER] =
-               {
-                       1,
-                       (pvalue_t[]){CAP_FOWNER},
-               },
 #elif defined(HAVE_SOLARIS_CAPABILITIES) /* HAVE_LCAPS */
-       /* Quagga -> Solaris privilege mappings */
-       [ZCAP_SETID] =
-               {
-                       1,
-                       (pvalue_t[]){PRIV_PROC_SETID},
-               },
-       [ZCAP_BIND] =
-               {
-                       1,
-                       (pvalue_t[]){PRIV_NET_PRIVADDR},
-               },
+               /* Quagga -> Solaris privilege mappings */
+               [ZCAP_SETID] =
+                       {
+                               1, (pvalue_t[]){PRIV_PROC_SETID},
+                       },
+               [ZCAP_BIND] =
+                       {
+                               1, (pvalue_t[]){PRIV_NET_PRIVADDR},
+                       },
 /* IP_CONFIG is a subset of NET_CONFIG and is allowed in zones */
 #ifdef PRIV_SYS_IP_CONFIG
-       [ZCAP_NET_ADMIN] =
-               {
-                       1,
-                       (pvalue_t[]){PRIV_SYS_IP_CONFIG},
-               },
+               [ZCAP_NET_ADMIN] =
+                       {
+                               1, (pvalue_t[]){PRIV_SYS_IP_CONFIG},
+                       },
 #else
-       [ZCAP_NET_ADMIN] =
-               {
-                       1,
-                       (pvalue_t[]){PRIV_SYS_NET_CONFIG},
-               },
+               [ZCAP_NET_ADMIN] =
+                       {
+                               1, (pvalue_t[]){PRIV_SYS_NET_CONFIG},
+                       },
 #endif
-       [ZCAP_NET_RAW] =
-               {
-                       2,
-                       (pvalue_t[]){PRIV_NET_RAWACCESS, PRIV_NET_ICMPACCESS},
-               },
-       [ZCAP_CHROOT] =
-               {
-                       1,
-                       (pvalue_t[]){PRIV_PROC_CHROOT},
-               },
-       [ZCAP_NICE] =
-               {
-                       1,
-                       (pvalue_t[]){PRIV_PROC_PRIOCNTL},
-               },
-       [ZCAP_PTRACE] =
-               {
-                       1,
-                       (pvalue_t[]){PRIV_PROC_SESSION},
-               },
-       [ZCAP_DAC_OVERRIDE] =
-               {
-                       5,
-                       (pvalue_t[]){PRIV_FILE_DAC_EXECUTE, PRIV_FILE_DAC_READ,
-                                    PRIV_FILE_DAC_SEARCH, PRIV_FILE_DAC_WRITE,
-                                    PRIV_FILE_DAC_SEARCH},
-               },
-       [ZCAP_READ_SEARCH] =
-               {
-                       2,
-                       (pvalue_t[]){PRIV_FILE_DAC_SEARCH, PRIV_FILE_DAC_READ},
-               },
-       [ZCAP_SYS_ADMIN] =
-               {
-                       1,
-                       (pvalue_t[]){PRIV_SYS_ADMIN},
-               },
-       [ZCAP_FOWNER] =
-               {
-                       1,
-                       (pvalue_t[]){PRIV_FILE_OWNER},
-               },
+               [ZCAP_NET_RAW] =
+                       {
+                               2, (pvalue_t[]){PRIV_NET_RAWACCESS,
+                                               PRIV_NET_ICMPACCESS},
+                       },
+               [ZCAP_CHROOT] =
+                       {
+                               1, (pvalue_t[]){PRIV_PROC_CHROOT},
+                       },
+               [ZCAP_NICE] =
+                       {
+                               1, (pvalue_t[]){PRIV_PROC_PRIOCNTL},
+                       },
+               [ZCAP_PTRACE] =
+                       {
+                               1, (pvalue_t[]){PRIV_PROC_SESSION},
+                       },
+               [ZCAP_DAC_OVERRIDE] =
+                       {
+                               5, (pvalue_t[]){PRIV_FILE_DAC_EXECUTE,
+                                               PRIV_FILE_DAC_READ,
+                                               PRIV_FILE_DAC_SEARCH,
+                                               PRIV_FILE_DAC_WRITE,
+                                               PRIV_FILE_DAC_SEARCH},
+                       },
+               [ZCAP_READ_SEARCH] =
+                       {
+                               2, (pvalue_t[]){PRIV_FILE_DAC_SEARCH,
+                                               PRIV_FILE_DAC_READ},
+                       },
+               [ZCAP_SYS_ADMIN] =
+                       {
+                               1, (pvalue_t[]){PRIV_SYS_ADMIN},
+                       },
+               [ZCAP_FOWNER] =
+                       {
+                               1, (pvalue_t[]){PRIV_FILE_OWNER},
+                       },
 #endif /* HAVE_SOLARIS_CAPABILITIES */
 };
 
@@ -306,7 +289,8 @@ zebra_privs_current_t zprivs_state_caps(void)
                if (cap_get_flag(zprivs_state.caps,
                                 zprivs_state.syscaps_p->caps[i], CAP_EFFECTIVE,
                                 &val)) {
-                       zlog_warn(
+                       flog_err(
+                               EC_LIB_SYSTEM_CALL,
                                "zprivs_state_caps: could not cap_get_flag, %s",
                                safe_strerror(errno));
                        return ZPRIVS_UNKNOWN;
@@ -714,13 +698,45 @@ static int getgrouplist(const char *user, gid_t group, gid_t *groups,
 }
 #endif /* HAVE_GETGROUPLIST */
 
-void zprivs_init(struct zebra_privs_t *zprivs)
+struct zebra_privs_t *_zprivs_raise(struct zebra_privs_t *privs,
+                                   const char *funcname)
+{
+       int save_errno = errno;
+
+       if (!privs)
+               return NULL;
+
+       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;
+}
+
+void _zprivs_lower(struct zebra_privs_t **privs)
+{
+       int save_errno = errno;
+
+       if (!*privs)
+               return;
+
+       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;
+}
+
+void zprivs_preinit(struct zebra_privs_t *zprivs)
 {
        struct passwd *pwentry = NULL;
        struct group *grentry = NULL;
-       gid_t groups[NGROUPS_MAX];
-       int i, ngroups = 0;
-       int found = 0;
 
        if (!zprivs) {
                fprintf(stderr, "zprivs_init: called with NULL arg!\n");
@@ -769,6 +785,18 @@ void zprivs_init(struct zebra_privs_t *zprivs)
 
                zprivs_state.zgid = grentry->gr_gid;
        }
+}
+
+void zprivs_init(struct zebra_privs_t *zprivs)
+{
+       gid_t groups[NGROUPS_MAX];
+       int i, ngroups = 0;
+       int found = 0;
+
+       /* NULL privs */
+       if (!(zprivs->user || zprivs->group || zprivs->cap_num_p
+             || zprivs->cap_num_i))
+               return;
 
        if (zprivs->user) {
                ngroups = sizeof(groups);
@@ -785,7 +813,7 @@ void zprivs_init(struct zebra_privs_t *zprivs)
 
        if (zprivs->vty_group)
        /* Add the vty_group to the supplementary groups so it can be chowned to
-        */
+          */
        {
                if (zprivs_state.vtygrp == (gid_t)-1) {
                        fprintf(stderr,
@@ -833,6 +861,19 @@ void zprivs_init(struct zebra_privs_t *zprivs)
 
 #ifdef HAVE_CAPABILITIES
        zprivs_caps_init(zprivs);
+
+       /*
+        * If we have initialized the system with no requested
+        * capabilities, change will not have been set
+        * to anything by zprivs_caps_init, As such
+        * we should make sure that when we attempt
+        * to raize privileges that we actually have
+        * a do nothing function to call instead of a
+        * crash :).
+        */
+       if (!zprivs->change)
+               zprivs->change = zprivs_change_null;
+
 #else  /* !HAVE_CAPABILITIES */
        /* we dont have caps. we'll need to maintain rid and saved uid
         * and change euid back to saved uid (who we presume has all neccessary
@@ -865,7 +906,9 @@ void zprivs_terminate(struct zebra_privs_t *zprivs)
        }
 
 #ifdef HAVE_CAPABILITIES
-       zprivs_caps_terminate();
+       if (zprivs->user || zprivs->group || zprivs->cap_num_p
+           || zprivs->cap_num_i)
+               zprivs_caps_terminate();
 #else  /* !HAVE_CAPABILITIES */
        /* only change uid if we don't have the correct one */
        if ((zprivs_state.zuid) && (zprivs_state.zsuid != zprivs_state.zuid)) {