diff options
author | Tom Hughes <tom.hughes@palm.com> | 2010-12-17 17:26:58 -0600 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2010-12-22 10:35:23 -0800 |
commit | 6681024a43207fbb00a041fc324246e627b33f8e (patch) | |
tree | 00552c7fdbcca59bcbc0b46780469762fa19bc36 | |
parent | 6acf3b48585d54ec878dd2747a8f9b61f8a67449 (diff) | |
download | node-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.cc | 70 |
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); } |