Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Terminate process on invalid netlink response from kernel [BZ #12926]
The recvmsg system calls for netlink sockets have been particularly prone to picking up unrelated data after a file descriptor race (where the descriptor is closed and reopened concurrently in a multi-threaded process, as the result of a file descriptor management issue elsewhere). This commit adds additional error checking and aborts the process if a datagram of unexpected length (without the netlink header) is received, or an error code which cannot happen due to the way the netlink socket is used. [BZ #12926] Terminate process on invalid netlink response. * sysdeps/unix/sysv/linux/netlinkaccess.h (__netlink_assert_response): Declare. * sysdeps/unix/sysv/linux/netlink_assert_response.c: New file. * sysdeps/unix/sysv/linux/Makefile [$(subdir) == inet] (sysdep_routines): Add netlink_assert_response. * sysdeps/unix/sysv/linux/check_native.c (__check_native): Call __netlink_assert_response. * sysdeps/unix/sysv/linux/check_pf.c (make_request): Likewise. * sysdeps/unix/sysv/linux/ifaddrs.c (__netlink_request): Likewise. * sysdeps/unix/sysv/linux/Versions (GLIBC_PRIVATE): Add __netlink_assert_response.
- Loading branch information
Florian Weimer
committed
Nov 9, 2015
1 parent
f3d18ef
commit 2eecc8a
Showing
9 changed files
with
145 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* Check recvmsg results for netlink sockets. | ||
Copyright (C) 2015 Free Software Foundation, Inc. | ||
This file is part of the GNU C Library. | ||
The GNU C Library is free software; you can redistribute it and/or | ||
modify it under the terms of the GNU Lesser General Public | ||
License as published by the Free Software Foundation; either | ||
version 2.1 of the License, or (at your option) any later version. | ||
The GNU C Library is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
Lesser General Public License for more details. | ||
You should have received a copy of the GNU Lesser General Public | ||
License along with the GNU C Library; if not, see | ||
<http://www.gnu.org/licenses/>. */ | ||
|
||
#include <errno.h> | ||
#include <fcntl.h> | ||
#include <stdio.h> | ||
#include <sys/socket.h> | ||
|
||
#include "netlinkaccess.h" | ||
|
||
static int | ||
get_address_family (int fd) | ||
{ | ||
struct sockaddr_storage sa; | ||
socklen_t sa_len = sizeof (sa); | ||
if (__getsockname (fd, (struct sockaddr *) &sa, &sa_len) < 0) | ||
return -1; | ||
/* Check that the socket family number is preserved despite in-band | ||
signaling. */ | ||
_Static_assert (sizeof (sa.ss_family) < sizeof (int), "address family size"); | ||
_Static_assert (0 < (__typeof__ (sa.ss_family)) -1, | ||
"address family unsigned"); | ||
return sa.ss_family; | ||
} | ||
|
||
void | ||
internal_function | ||
__netlink_assert_response (int fd, ssize_t result) | ||
{ | ||
if (result < 0) | ||
{ | ||
/* Check if the error is unexpected. */ | ||
bool terminate = false; | ||
int error_code = errno; | ||
int family = get_address_family (fd); | ||
if (family != AF_NETLINK) | ||
/* If the address family does not match (or getsockname | ||
failed), report the original error. */ | ||
terminate = true; | ||
else if (error_code == EBADF | ||
|| error_code == ENOTCONN | ||
|| error_code == ENOTSOCK | ||
|| error_code == ECONNREFUSED) | ||
/* These errors indicate that the descriptor is not a | ||
connected socket. */ | ||
terminate = true; | ||
else if (error_code == EAGAIN || error_code == EWOULDBLOCK) | ||
{ | ||
/* The kernel might return EAGAIN for other reasons than a | ||
non-blocking socket. But if the socket is not blocking, | ||
it is not ours, so report the error. */ | ||
int mode = __fcntl (fd, F_GETFL, 0); | ||
if (mode < 0 || (mode & O_NONBLOCK) != 0) | ||
terminate = true; | ||
} | ||
if (terminate) | ||
{ | ||
char message[200]; | ||
if (family < 0) | ||
__snprintf (message, sizeof (message), | ||
"Unexpected error %d on netlink descriptor %d", | ||
error_code, fd); | ||
else | ||
__snprintf (message, sizeof (message), | ||
"Unexpected error %d on netlink descriptor %d" | ||
" (address family %d)", | ||
error_code, fd, family); | ||
__libc_fatal (message); | ||
} | ||
else | ||
/* Restore orignal errno value. */ | ||
__set_errno (error_code); | ||
} | ||
else if (result < sizeof (struct nlmsghdr)) | ||
{ | ||
char message[200]; | ||
int family = get_address_family (fd); | ||
if (family < 0) | ||
__snprintf (message, sizeof (message), | ||
"Unexpected netlink response of size %zd" | ||
" on descriptor %d", | ||
result, fd); | ||
else | ||
__snprintf (message, sizeof (message), | ||
"Unexpected netlink response of size %zd" | ||
" on descriptor %d (address family %d)", | ||
result, fd, family); | ||
__libc_fatal (message); | ||
} | ||
} | ||
libc_hidden_def (__netlink_assert_response) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters