Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fping: retain privileges until after privileged setsockopt #200

Merged
merged 1 commit into from
Oct 17, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 49 additions & 6 deletions src/fping.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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");
}

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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
Expand Down