Merge pull request #200 from simetnicbr/for-upstream/privileged-SO_BINDTODEVICE

fping: retain privileges until after privileged setsockopt
pull/209/head
David Schweikert 4 years ago committed by GitHub
commit eac20347ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -395,6 +395,42 @@ struct event *host_get_timeout_event(HOST_ENTRY *h, int index);
void stats_add(HOST_ENTRY *h, int index, int success, int64_t latency);
void update_current_time();
/************************************************************
Function: p_setsockopt
*************************************************************
Inputs: p_uid: privileged uid. Others as per setsockopt(2)
Description:
Elevates privileges to p_uid when required, calls
setsockopt, and drops privileges back.
************************************************************/
int p_setsockopt(uid_t p_uid, int sockfd, int level, int optname,
const void *optval, socklen_t optlen)
{
const uid_t saved_uid = geteuid();
int res;
if (p_uid != saved_uid && seteuid(p_uid)) {
perror("cannot elevate privileges for setsockopt");
}
res = setsockopt(sockfd, level, optname, optval, optlen);
if (p_uid != saved_uid && seteuid(saved_uid)) {
perror("fatal error: could not drop privileges after setsockopt");
/* continuing would be a security hole */
exit(4);
}
return res;
}
/************************************************************
Function: main
@ -412,7 +448,7 @@ void update_current_time();
int main(int argc, char** argv)
{
int c;
uid_t uid;
const uid_t suid = geteuid();
int tos = 0;
struct optparse optparse_state;
#ifdef USE_SIGACTION
@ -448,9 +484,9 @@ int main(int argc, char** argv)
memset(&src_addr6, 0, sizeof(src_addr6));
#endif
if ((uid = getuid())) {
/* drop privileges */
if (setuid(getuid()) == -1)
if (!suid && suid != getuid()) {
/* *temporarily* drop privileges */
if (seteuid(getuid()) == -1)
perror("cannot setuid");
}
@ -740,14 +776,14 @@ int main(int argc, char** argv)
case 'I':
#ifdef SO_BINDTODEVICE
if (socket4 >= 0) {
if (setsockopt(socket4, SOL_SOCKET, SO_BINDTODEVICE, optparse_state.optarg, strlen(optparse_state.optarg))) {
if (p_setsockopt(suid, socket4, SOL_SOCKET, SO_BINDTODEVICE, optparse_state.optarg, strlen(optparse_state.optarg))) {
perror("binding to specific interface (SO_BINTODEVICE)");
exit(1);
}
}
#ifdef IPV6
if (socket6 >= 0) {
if (setsockopt(socket6, SOL_SOCKET, SO_BINDTODEVICE, optparse_state.optarg, strlen(optparse_state.optarg))) {
if (p_setsockopt(suid, socket6, SOL_SOCKET, SO_BINDTODEVICE, optparse_state.optarg, strlen(optparse_state.optarg))) {
perror("binding to specific interface (SO_BINTODEVICE), IPV6");
exit(1);
}
@ -796,6 +832,13 @@ int main(int argc, char** argv)
}
}
/* permanetly drop privileges */
if (suid != getuid() && setuid(getuid())) {
perror("fatal: failed to permanently drop privileges");
/* continuing would be a security hole */
exit(4);
}
/* validate various option settings */
#ifndef IPV6

Loading…
Cancel
Save