]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
priv: when SNMP AgentX socket is filesystem-based, acquire CAP_FOWNER
authorVincent Bernat <vincent@bernat.im>
Wed, 13 Jun 2018 05:56:48 +0000 (07:56 +0200)
committerVincent Bernat <vincent@bernat.im>
Sat, 16 Jun 2018 15:08:28 +0000 (17:08 +0200)
NEWS
src/daemon/agent_priv.c
src/daemon/lldpd.c
src/daemon/lldpd.h
src/daemon/priv.c

diff --git a/NEWS b/NEWS
index dd0e1e5a96804e8c40452a341e1d711a0612344f..a08818398ed88cab829d3954603cc35ac75acd65 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,8 +2,8 @@ lldpd (1.0.2)
   * Changes:
     + On Linux, the monitor process will now drop its privileges
       instead of running as root. It will keep CAP_NET_RAW and
-      CAP_NET_ADMIN capabilities. When using SNMP AgentX feature, the
-      access to the socket may require to grant access to _lldpd user.
+      CAP_NET_ADMIN capabilities. When SNMP support is enabled, it may
+      also require CAP_FOWNER.
 
 lldpd (1.0.1)
   * Fix:
index 6a126fe84134d616961b2326cecc15007035aae6..d0c5d32164bd066ad402b5f21a17259c1fcbc820 100644 (file)
@@ -222,6 +222,12 @@ agent_priv_unix_create_ostring(const u_char * o, size_t o_len, int local)
        return agent_priv_unix_transport((char *)o, o_len, local);
 }
 
+const char *
+agent_default_agentx_socket()
+{
+       return NETSNMP_AGENTX_SOCKET;
+}
+
 void
 agent_priv_register_domain()
 {
index 1914569cb6104bc7cc8dc132a4dc18adae6e286b..2c41622d962de8897a7b956de3d9217e0aa5b652 100644 (file)
@@ -1825,9 +1825,15 @@ lldpd_main(int argc, char *argv[], char *envp[])
 
        log_debug("main", "initialize privilege separation");
 #ifdef ENABLE_PRIVSEP
-       priv_init(PRIVSEP_CHROOT, ctl, uid, gid);
+       priv_init(PRIVSEP_CHROOT, ctl, uid, gid,
+#ifdef USE_SNMP
+           (agentx ? agentx : agent_default_agentx_socket())[0] == '/'
+#else
+           0
+#endif
+       );
 #else
-       priv_init(PRIVSEP_CHROOT, ctl, 0, 0);
+       priv_init(PRIVSEP_CHROOT, ctl, 0, 0, 0);
 #endif
 
        /* Initialization of global configuration */
index 97306a2d47733e241d6ab512e0427b27df473f92..a0838c6b7233ec710878f9f08ac31402a7c98122 100644 (file)
@@ -179,6 +179,7 @@ void                 agent_notify(struct lldpd_hardware *, int, struct lldpd_port *);
 #ifdef ENABLE_PRIVSEP
 /* agent_priv.c */
 void            agent_priv_register_domain(void);
+const char     *agent_default_agentx_socket(void);
 #endif
 
 /* client.c */
@@ -190,7 +191,7 @@ client_handle_client(struct lldpd *cfg,
     int*);
 
 /* priv.c */
-void    priv_init(const char*, int, uid_t, gid_t);
+void    priv_init(const char*, int, uid_t, gid_t, int);
 void    priv_wait(void);
 void    priv_ctl_cleanup(const char *ctlname);
 char           *priv_gethostname(void);
index 5a062cf06a2457e6aea956ac7916331c2aa4f675..a9b0f60981f20176973cf7a825e2e255312bd8b4 100644 (file)
@@ -625,12 +625,21 @@ priv_drop(uid_t uid, gid_t gid)
 }
 
 void
-priv_caps(uid_t uid, gid_t gid)
+priv_caps(uid_t uid, gid_t gid, int fowner)
 {
 #ifdef HAVE_LINUX_CAPABILITIES
        cap_t caps;
-       log_debug("privsep", "getting CAP_NET_RAW/ADMIN privilege");
-       if (!(caps = cap_from_text("cap_net_raw,cap_net_admin,cap_setuid,cap_setgid=pe")))
+       const char *caps_strings[2];
+       if (fowner) {
+               log_debug("privsep", "getting CAP_NET_RAW/ADMIN and CAP_FOWNER privilege");
+               caps_strings[0] = "cap_fowner,cap_net_raw,cap_net_admin,cap_setuid,cap_setgid=pe";
+               caps_strings[1] = "cap_fowner,cap_net_raw,cap_net_admin=pe";
+       } else {
+               log_debug("privsep", "getting CAP_NET_RAW/ADMIN privilege");
+               caps_strings[0] = "cap_net_raw,cap_net_admin,cap_setuid,cap_setgid=pe";
+               caps_strings[1] = "cap_net_raw,cap_net_admin=pe";
+       }
+       if (!(caps = cap_from_text(caps_strings[0])))
                fatal("privsep", "unable to convert caps");
        if (cap_set_proc(caps) == -1) {
                log_warn("privsep", "unable to drop privileges, monitor running as root");
@@ -644,7 +653,7 @@ priv_caps(uid_t uid, gid_t gid)
        priv_drop(uid, gid);
 
        log_debug("privsep", "dropping extra capabilities");
-       if (!(caps = cap_from_text("cap_net_raw,cap_net_admin=pe")))
+       if (!(caps = cap_from_text(caps_strings[1])))
                fatal("privsep", "unable to convert caps");
        if (cap_set_proc(caps) == -1)
                fatal("privsep", "unable to drop extra privileges");
@@ -655,7 +664,7 @@ priv_caps(uid_t uid, gid_t gid)
 }
 
 void
-priv_init(const char *chrootdir, int ctl, uid_t uid, gid_t gid)
+priv_init(const char *chrootdir, int ctl, uid_t uid, gid_t gid, int fowner)
 {
 
        int pair[2];
@@ -696,7 +705,7 @@ priv_init(const char *chrootdir, int ctl, uid_t uid, gid_t gid)
                if (atexit(priv_exit) != 0)
                        fatal("privsep", "unable to set exit function");
 
-               priv_caps(uid, gid);
+               priv_caps(uid, gid, fowner);
 
                /* Install signal handlers */
                const struct sigaction pass_to_child = {