summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Hughes <tom.hughes@palm.com>2010-12-17 17:26:58 -0600
committerRyan Dahl <ry@tinyclouds.org>2010-12-22 10:35:23 -0800
commit6681024a43207fbb00a041fc324246e627b33f8e (patch)
tree00552c7fdbcca59bcbc0b46780469762fa19bc36
parent6acf3b48585d54ec878dd2747a8f9b61f8a67449 (diff)
downloadnode-6681024a43207fbb00a041fc324246e627b33f8e.tar.gz
Fix memory corruption with unnamed AF_UNIX sockets.
AF_UNIX sockets can have a pathname, be unnamed, or abstract (Linux only). If an unnamed socket is returned by getsockname, getpeername, or accept, sun_path should not be inspected.
-rw-r--r--src/node_net.cc70
1 files changed, 44 insertions, 26 deletions
diff --git a/src/node_net.cc b/src/node_net.cc
index de3bb6bf6..7c4eb5f9d 100644
--- a/src/node_net.cc
+++ b/src/node_net.cc
@@ -372,34 +372,52 @@ static Handle<Value> Connect(const Arguments& args) {
return Undefined();
}
-#define ADDRESS_TO_JS(info, address_storage) \
+#define ADDRESS_TO_JS(info, address_storage, addrlen) \
do { \
char ip[INET6_ADDRSTRLEN]; \
int port; \
struct sockaddr_in *a4; \
struct sockaddr_in6 *a6; \
struct sockaddr_un *au; \
- switch ((address_storage).ss_family) { \
- case AF_INET6: \
- a6 = (struct sockaddr_in6*)&(address_storage); \
- inet_ntop(AF_INET6, &(a6->sin6_addr), ip, INET6_ADDRSTRLEN); \
- port = ntohs(a6->sin6_port); \
- (info)->Set(address_symbol, String::New(ip)); \
- (info)->Set(port_symbol, Integer::New(port)); \
- break; \
- case AF_INET: \
- a4 = (struct sockaddr_in*)&(address_storage); \
- inet_ntop(AF_INET, &(a4->sin_addr), ip, INET6_ADDRSTRLEN); \
- port = ntohs(a4->sin_port); \
- (info)->Set(address_symbol, String::New(ip)); \
- (info)->Set(port_symbol, Integer::New(port)); \
- break; \
- case AF_UNIX: \
- au = (struct sockaddr_un*)&(address_storage); \
- (info)->Set(address_symbol, String::New(au->sun_path)); \
- break; \
- default: \
- (info)->Set(address_symbol, String::Empty()); \
+ if (addrlen == 0) { \
+ (info)->Set(address_symbol, String::Empty()); \
+ } else { \
+ switch ((address_storage).ss_family) { \
+ case AF_INET6: \
+ a6 = (struct sockaddr_in6*)&(address_storage); \
+ inet_ntop(AF_INET6, &(a6->sin6_addr), ip, INET6_ADDRSTRLEN); \
+ port = ntohs(a6->sin6_port); \
+ (info)->Set(address_symbol, String::New(ip)); \
+ (info)->Set(port_symbol, Integer::New(port)); \
+ break; \
+ case AF_INET: \
+ a4 = (struct sockaddr_in*)&(address_storage); \
+ inet_ntop(AF_INET, &(a4->sin_addr), ip, INET6_ADDRSTRLEN); \
+ port = ntohs(a4->sin_port); \
+ (info)->Set(address_symbol, String::New(ip)); \
+ (info)->Set(port_symbol, Integer::New(port)); \
+ break; \
+ case AF_UNIX: \
+ /*
+ * Three types of addresses (see man 7 unix):
+ * * unnamed: sizeof(sa_family_t) (sun_path should not be used)
+ * * abstract (Linux extension): sizeof(struct sockaddr_un)
+ * * pathname: sizeof(sa_family_t) + strlen(sun_path) + 1
+ */ \
+ au = (struct sockaddr_un*)&(address_storage); \
+ if (addrlen == sizeof(sa_family_t)) { \
+ (info)->Set(address_symbol, String::Empty()); \
+ } else if (addrlen == sizeof(struct sockaddr_un)) { \
+ /* first byte is '\0' and all remaining bytes are name;
+ * it is not NUL-terminated and may contain embedded NULs */ \
+ (info)->Set(address_symbol, String::New(au->sun_path + 1, sizeof(au->sun_path - 1))); \
+ } else { \
+ (info)->Set(address_symbol, String::New(au->sun_path)); \
+ } \
+ break; \
+ default: \
+ (info)->Set(address_symbol, String::Empty()); \
+ } \
} \
} while (0)
@@ -420,7 +438,7 @@ static Handle<Value> GetSockName(const Arguments& args) {
Local<Object> info = Object::New();
- ADDRESS_TO_JS(info, address_storage);
+ ADDRESS_TO_JS(info, address_storage, len);
return scope.Close(info);
}
@@ -442,7 +460,7 @@ static Handle<Value> GetPeerName(const Arguments& args) {
Local<Object> info = Object::New();
- ADDRESS_TO_JS(info, address_storage);
+ ADDRESS_TO_JS(info, address_storage, len);
return scope.Close(info);
}
@@ -498,7 +516,7 @@ static Handle<Value> Accept(const Arguments& args) {
peer_info->Set(fd_symbol, Integer::New(peer_fd));
- ADDRESS_TO_JS(peer_info, address_storage);
+ ADDRESS_TO_JS(peer_info, address_storage, len);
return scope.Close(peer_info);
}
@@ -615,7 +633,7 @@ static Handle<Value> RecvFrom(const Arguments& args) {
info->Set(size_symbol, Integer::New(bytes_read));
- ADDRESS_TO_JS(info, address_storage);
+ ADDRESS_TO_JS(info, address_storage, addrlen);
return scope.Close(info);
}