From: Vincent Bernat Date: Wed, 13 Jun 2018 05:56:48 +0000 (+0200) Subject: priv: when SNMP AgentX socket is filesystem-based, acquire CAP_FOWNER X-Git-Tag: 1.0.2~16^2~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=06b24ddcb584bc0fb3c733fdcbe105b135bf7aa8;p=thirdparty%2Flldpd.git priv: when SNMP AgentX socket is filesystem-based, acquire CAP_FOWNER --- diff --git a/NEWS b/NEWS index dd0e1e5a..a0881839 100644 --- 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: diff --git a/src/daemon/agent_priv.c b/src/daemon/agent_priv.c index 6a126fe8..d0c5d321 100644 --- a/src/daemon/agent_priv.c +++ b/src/daemon/agent_priv.c @@ -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() { diff --git a/src/daemon/lldpd.c b/src/daemon/lldpd.c index 1914569c..2c41622d 100644 --- a/src/daemon/lldpd.c +++ b/src/daemon/lldpd.c @@ -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 */ diff --git a/src/daemon/lldpd.h b/src/daemon/lldpd.h index 97306a2d..a0838c6b 100644 --- a/src/daemon/lldpd.h +++ b/src/daemon/lldpd.h @@ -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); diff --git a/src/daemon/priv.c b/src/daemon/priv.c index 5a062cf0..a9b0f609 100644 --- a/src/daemon/priv.c +++ b/src/daemon/priv.c @@ -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 = {