GNetworkMonitorNetlink: make the netlink socket cloexec

Use the same code GSocket does, to try SOCK_CLOEXEC first, and then
fall back to FD_CLOEXEC if it fails. (And fix that code to not call
fcntl if SOCK_CLOEXEC worked.)

https://bugzilla.gnome.org/show_bug.cgi?id=692332
This commit is contained in:
Dan Winship 2013-01-22 16:39:49 -05:00
parent 2476dd24d7
commit 5932e16acd
3 changed files with 57 additions and 36 deletions

View File

@ -34,6 +34,11 @@ gchar * _g_uri_from_authority (const gchar *protocol,
guint port,
const gchar *userinfo);
gint g_socket (gint domain,
gint type,
gint protocol,
GError **error);
G_END_DECLS
#endif /* __G_NETWORKINGPRIVATE_H__ */

View File

@ -89,7 +89,7 @@ g_network_monitor_netlink_initable_init (GInitable *initable,
/* We create the socket the old-school way because sockaddr_netlink
* can't be represented as a GSocketAddress
*/
sockfd = socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
sockfd = g_socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE, NULL);
if (sockfd == -1)
{
int errsv = errno;

View File

@ -59,7 +59,7 @@
#include "gioerror.h"
#include "gioenums.h"
#include "gioerror.h"
#include "gnetworking.h"
#include "gnetworkingprivate.h"
#include "gsocketaddress.h"
#include "gsocketcontrolmessage.h"
#include "gcredentials.h"
@ -482,6 +482,55 @@ g_socket_details_from_fd (GSocket *socket)
socket_strerror (errsv));
}
/* Wrapper around socket() that is shared with gnetworkmonitornetlink.c */
gint
g_socket (gint domain,
gint type,
gint protocol,
GError **error)
{
int fd;
#ifdef SOCK_CLOEXEC
fd = socket (domain, type | SOCK_CLOEXEC, protocol);
if (fd != -1)
return fd;
/* It's possible that libc has SOCK_CLOEXEC but the kernel does not */
if (fd < 0 && errno == EINVAL)
#endif
fd = socket (domain, type, protocol);
if (fd < 0)
{
int errsv = get_socket_errno ();
g_set_error (error, G_IO_ERROR, socket_io_error_from_errno (errsv),
_("Unable to create socket: %s"), socket_strerror (errsv));
errno = errsv;
return -1;
}
#ifndef G_OS_WIN32
{
int flags;
/* We always want to set close-on-exec to protect users. If you
need to so some weird inheritance to exec you can re-enable this
using lower level hacks with g_socket_get_fd(). */
flags = fcntl (fd, F_GETFD, 0);
if (flags != -1 &&
(flags & FD_CLOEXEC) == 0)
{
flags |= FD_CLOEXEC;
fcntl (fd, F_SETFD, flags);
}
}
#endif
return fd;
}
static gint
g_socket_create_socket (GSocketFamily family,
GSocketType type,
@ -489,7 +538,6 @@ g_socket_create_socket (GSocketFamily family,
GError **error)
{
gint native_type;
gint fd;
switch (type)
{
@ -523,39 +571,7 @@ g_socket_create_socket (GSocketFamily family,
return -1;
}
#ifdef SOCK_CLOEXEC
fd = socket (family, native_type | SOCK_CLOEXEC, protocol);
/* It's possible that libc has SOCK_CLOEXEC but the kernel does not */
if (fd < 0 && errno == EINVAL)
#endif
fd = socket (family, native_type, protocol);
if (fd < 0)
{
int errsv = get_socket_errno ();
g_set_error (error, G_IO_ERROR, socket_io_error_from_errno (errsv),
_("Unable to create socket: %s"), socket_strerror (errsv));
}
#ifndef G_OS_WIN32
{
int flags;
/* We always want to set close-on-exec to protect users. If you
need to so some weird inheritance to exec you can re-enable this
using lower level hacks with g_socket_get_fd(). */
flags = fcntl (fd, F_GETFD, 0);
if (flags != -1 &&
(flags & FD_CLOEXEC) == 0)
{
flags |= FD_CLOEXEC;
fcntl (fd, F_SETFD, flags);
}
}
#endif
return fd;
return g_socket (family, native_type, protocol, error);
}
static void