sd-daemon: verify socket family, too

This commit is contained in:
Lennart Poettering 2010-05-21 17:06:40 +02:00
parent dde770cfc6
commit 88ce42f694
4 changed files with 70 additions and 37 deletions

2
fixme
View file

@ -47,9 +47,9 @@
- uuidd DONE - uuidd DONE
- nscd DONE - nscd DONE
- dbus DONE - dbus DONE
- rsyslog DONE
- rpcbind (/var/run/rpcbind.sock!) - rpcbind (/var/run/rpcbind.sock!)
- avahi-daemon (/var/run/avahi-daemon/socket) - avahi-daemon (/var/run/avahi-daemon/socket)
- rsyslog
- cups - cups
- ssh CLASSIC - ssh CLASSIC
- postfix, saslauthd - postfix, saslauthd

View file

@ -428,7 +428,7 @@ static int server_init(Server *s, unsigned n_sockets) {
fd = SD_LISTEN_FDS_START+i; fd = SD_LISTEN_FDS_START+i;
if ((r = sd_is_socket(fd, SOCK_STREAM, 1)) < 0) { if ((r = sd_is_socket(fd, AF_UNSPEC, SOCK_STREAM, 1)) < 0) {
log_error("Failed to determine file descriptor type: %s", strerror(-r)); log_error("Failed to determine file descriptor type: %s", strerror(-r));
goto fail; goto fail;
} }

View file

@ -133,7 +133,7 @@ int sd_is_fifo(int fd, const char *path) {
return 1; return 1;
} }
int sd_is_socket(int fd, int type, int listening) { static int sd_is_socket_internal(int fd, int type, int listening) {
struct stat st_fd; struct stat st_fd;
if (fd < 0 || type < 0) if (fd < 0 || type < 0)
@ -176,18 +176,51 @@ int sd_is_socket(int fd, int type, int listening) {
return 1; return 1;
} }
int sd_is_socket_inet(int fd, int type, int listening, uint16_t port) { union sockaddr_union {
union { struct sockaddr sa;
struct sockaddr sa; struct sockaddr_in in4;
struct sockaddr_in in4; struct sockaddr_in6 in6;
struct sockaddr_in6 in6; struct sockaddr_un un;
struct sockaddr_un un; struct sockaddr_storage storage;
struct sockaddr_storage storage; };
} sockaddr;
int sd_is_socket(int fd, int family, int type, int listening) {
int r;
if (family < 0)
return -EINVAL;
if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
return r;
if (family > 0) {
union sockaddr_union sockaddr;
socklen_t l;
memset(&sockaddr, 0, sizeof(sockaddr));
l = sizeof(sockaddr);
if (getsockname(fd, &sockaddr.sa, &l) < 0)
return -errno;
if (l < sizeof(sa_family_t))
return -EINVAL;
return sockaddr.sa.sa_family == family;
}
return 1;
}
int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) {
union sockaddr_union sockaddr;
socklen_t l; socklen_t l;
int r; int r;
if ((r = sd_is_socket(fd, type, listening)) <= 0) if (family != 0 && family != AF_INET && family != AF_INET6)
return -EINVAL;
if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
return r; return r;
memset(&sockaddr, 0, sizeof(sockaddr)); memset(&sockaddr, 0, sizeof(sockaddr));
@ -196,13 +229,17 @@ int sd_is_socket_inet(int fd, int type, int listening, uint16_t port) {
if (getsockname(fd, &sockaddr.sa, &l) < 0) if (getsockname(fd, &sockaddr.sa, &l) < 0)
return -errno; return -errno;
if (l < sizeof(struct sockaddr)) if (l < sizeof(sa_family_t))
return -EINVAL; return -EINVAL;
if (sockaddr.sa.sa_family != AF_INET && if (sockaddr.sa.sa_family != AF_INET &&
sockaddr.sa.sa_family != AF_INET6) sockaddr.sa.sa_family != AF_INET6)
return 0; return 0;
if (family > 0)
if (sockaddr.sa.sa_family != family)
return 0;
if (port > 0) { if (port > 0) {
if (sockaddr.sa.sa_family == AF_INET) { if (sockaddr.sa.sa_family == AF_INET) {
if (l < sizeof(struct sockaddr_in)) if (l < sizeof(struct sockaddr_in))
@ -221,17 +258,11 @@ int sd_is_socket_inet(int fd, int type, int listening, uint16_t port) {
} }
int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) {
union { union sockaddr_union sockaddr;
struct sockaddr sa;
struct sockaddr_in in4;
struct sockaddr_in6 in6;
struct sockaddr_un un;
struct sockaddr_storage storage;
} sockaddr;
socklen_t l; socklen_t l;
int r; int r;
if ((r = sd_is_socket(fd, type, listening)) <= 0) if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
return r; return r;
memset(&sockaddr, 0, sizeof(sockaddr)); memset(&sockaddr, 0, sizeof(sockaddr));

View file

@ -73,24 +73,26 @@ int sd_listen_fds(int unset_environment);
int sd_is_fifo(int fd, const char *path); int sd_is_fifo(int fd, const char *path);
/* Helper call for identifying a passed file descriptor. Returns 1 if /* Helper call for identifying a passed file descriptor. Returns 1 if
* the file descriptor is a socket of the specified type (SOCK_DGRAM, * the file descriptor is a socket of the specified family (AF_INET,
* SOCK_STREAM, ...), 0 otherwise. If type is 0 a socket type check * ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If
* will not be done and the call only verifies if the file descriptor * family is 0 a socket family check will not be done. If type is 0 a
* refers to a socket. If listening is > 0 it is verified that the * socket type check will not be done and the call only verifies if
* socket is in listening mode. (i.e. listen() has been called) If * the file descriptor refers to a socket. If listening is > 0 it is
* listening is == 0 it is verified that the socket is not in * verified that the socket is in listening mode. (i.e. listen() has
* listening mode. If listening is < 0 no listening mode check is * been called) If listening is == 0 it is verified that the socket is
* done. Returns a negative errno style error code on failure. */ * not in listening mode. If listening is < 0 no listening mode check
int sd_is_socket(int fd, int type, int listening); * is done. Returns a negative errno style error code on failure. */
int sd_is_socket(int fd, int family, int type, int listening);
/* Helper call for identifying a passed file descriptor. Returns 1 if /* Helper call for identifying a passed file descriptor. Returns 1 if
* the file descriptor is an Internet socket (either AF_INET or * the file descriptor is an Internet socket, of the specified family
* AF_INET6) of the specified type (SOCK_DGRAM, SOCK_STREAM, ...), 0 * (either AF_INET or AF_INET6) of the specified type (SOCK_DGRAM,
* otherwise. If type is 0 a socket type check will not be done. If * SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version
* port is 0 a socket port check will not be done. The listening flag * check is not done. If type is 0 a socket type check will not be
* is used the same way as in sd_is_socket(). Returns a negative errno * done. If port is 0 a socket port check will not be done. The
* style error code on failure. */ * listening flag is used the same way as in sd_is_socket(). Returns a
int sd_is_socket_inet(int fd, int type, int listening, uint16_t port); * negative errno style error code on failure. */
int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port);
/* Helper call for identifying a passed file descriptor. Returns 1 if /* Helper call for identifying a passed file descriptor. Returns 1 if
* the file descriptor is an AF_UNIX socket of the specified type * the file descriptor is an AF_UNIX socket of the specified type