Add some more syscalls to the ndhc permit filter. Netlink sockets were

broken before because of too-strict filters.

Move setup_signals under the seccomp filter to give it more testing coverage.

Make the UDP datagram length check much more strict.  If the read buffer
does not match up with the header lengths exactly, it is discarded.

Print a warning to syslog/stdout when ifchd execute_buffer() returns an
error.

Fix a regression introduced in ifchd that would cause the epoll handler to
spin when a client connection closed.
This commit is contained in:
Nicholas J. Kain
2012-07-20 18:48:26 -04:00
parent f9c2059d37
commit 2bf7306bb9
5 changed files with 24 additions and 12 deletions

View File

@@ -2,10 +2,7 @@ project (ifchd)
cmake_minimum_required (VERSION 2.6) cmake_minimum_required (VERSION 2.6)
set(IFCHD_SRCS file(GLOB IFCHD_SRCS "*.c")
ifchd.c
linux.c
)
add_executable(ifchd ${IFCHD_SRCS}) add_executable(ifchd ${IFCHD_SRCS})
target_link_libraries(ifchd ncmlib) target_link_libraries(ifchd ncmlib)

View File

@@ -5,7 +5,7 @@
#define PID_FILE_DEFAULT "/var/run/ifchd.pid" #define PID_FILE_DEFAULT "/var/run/ifchd.pid"
#define IFCHD_VERSION "0.9" #define IFCHD_VERSION "0.9"
#define MAX_BUF 1024 #define MAX_BUF 384
#define SOCK_QUEUE 2 #define SOCK_QUEUE 2
#define CONN_TIMEOUT 60 #define CONN_TIMEOUT 60
#define MAX_IFACES 10 #define MAX_IFACES 10

View File

@@ -664,15 +664,20 @@ static void process_client_fd(int fd)
memset(buf, '\0', sizeof buf); memset(buf, '\0', sizeof buf);
r = safe_read(cl->fd, buf, sizeof buf - 1); r = safe_read(cl->fd, buf, sizeof buf - 1);
if (r == 0) if (r == 0) {
return; // Remote end hung up.
else if (r < 0) { goto fail;
} else if (r < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK)
return;
log_line("error reading from client fd: %s", strerror(errno)); log_line("error reading from client fd: %s", strerror(errno));
goto fail; goto fail;
} }
if (execute_buffer(cl, buf) == -1) if (execute_buffer(cl, buf) == -1) {
log_line("execute_buffer was passed invalid commands");
goto fail; goto fail;
}
return; return;
fail: fail:
ifchd_client_wipe(cl); ifchd_client_wipe(cl);

View File

@@ -283,8 +283,10 @@ static int get_raw_packet(struct client_state_t *cs, struct dhcpmsg *payload)
return -1; return -1;
} }
if (inc > ntohs(packet.ip.tot_len)) if (inc != ntohs(packet.ip.tot_len)) {
log_line("Discarded extra bytes after reading a single UDP datagram."); log_line("UDP length does not match header length fields.");
return -2;
}
if (!cs->using_dhcp_bpf && !get_raw_packet_validate_bpf(&packet)) if (!cs->using_dhcp_bpf && !get_raw_packet_validate_bpf(&packet))
return -2; return -2;

View File

@@ -125,12 +125,19 @@ static int enforce_seccomp(void)
ALLOW_SYSCALL(read), ALLOW_SYSCALL(read),
ALLOW_SYSCALL(write), ALLOW_SYSCALL(write),
ALLOW_SYSCALL(close), ALLOW_SYSCALL(close),
ALLOW_SYSCALL(recvmsg),
ALLOW_SYSCALL(socket), ALLOW_SYSCALL(socket),
ALLOW_SYSCALL(setsockopt), ALLOW_SYSCALL(setsockopt),
ALLOW_SYSCALL(fcntl), ALLOW_SYSCALL(fcntl),
ALLOW_SYSCALL(bind), ALLOW_SYSCALL(bind),
ALLOW_SYSCALL(open), ALLOW_SYSCALL(open),
ALLOW_SYSCALL(connect), ALLOW_SYSCALL(connect),
ALLOW_SYSCALL(getsockname),
// These are for 'write_leasefile()'
ALLOW_SYSCALL(ftruncate),
ALLOW_SYSCALL(lseek),
ALLOW_SYSCALL(fsync),
// These are for 'background()' // These are for 'background()'
ALLOW_SYSCALL(socketpair), ALLOW_SYSCALL(socketpair),
@@ -230,11 +237,12 @@ static void do_work(void)
cs.epollFd = epoll_create1(0); cs.epollFd = epoll_create1(0);
if (cs.epollFd == -1) if (cs.epollFd == -1)
suicide("epoll_create1 failed"); suicide("epoll_create1 failed");
setup_signals(&cs);
if (enforce_seccomp()) if (enforce_seccomp())
log_line("seccomp filter cannot be installed"); log_line("seccomp filter cannot be installed");
setup_signals(&cs);
epoll_add(&cs, cs.nlFd); epoll_add(&cs, cs.nlFd);
set_listen_raw(&cs); set_listen_raw(&cs);
nowts = curms(); nowts = curms();