summaryrefslogtreecommitdiff
path: root/net/unix
diff options
context:
space:
mode:
Diffstat (limited to 'net/unix')
-rw-r--r--net/unix/af_unix.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 3e60c1074f28..e2413a65bdfc 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -227,15 +227,22 @@ static inline void unix_release_addr(struct unix_address *addr)
* - if started by zero, it is abstract name.
*/
+static int unix_validate_addr(struct sockaddr_un *sunaddr, int addr_len)
+{
+ if (addr_len <= offsetof(struct sockaddr_un, sun_path) ||
+ addr_len > sizeof(*sunaddr))
+ return -EINVAL;
+
+ if (sunaddr->sun_family != AF_UNIX)
+ return -EINVAL;
+
+ return 0;
+}
+
static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned int *hashp)
{
*hashp = 0;
- if (len <= offsetof(struct sockaddr_un, sun_path) ||
- len > sizeof(*sunaddr))
- return -EINVAL;
- if (!sunaddr || sunaddr->sun_family != AF_UNIX)
- return -EINVAL;
if (sunaddr->sun_path[0]) {
/*
* This may look like an off by one error but it is a bit more
@@ -1177,13 +1184,14 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
unsigned int hash;
struct unix_address *addr;
- if (addr_len < offsetofend(struct sockaddr_un, sun_family) ||
- sunaddr->sun_family != AF_UNIX)
- return -EINVAL;
-
- if (addr_len == offsetof(struct sockaddr_un, sun_path))
+ if (addr_len == offsetof(struct sockaddr_un, sun_path) &&
+ sunaddr->sun_family == AF_UNIX)
return unix_autobind(sk);
+ err = unix_validate_addr(sunaddr, addr_len);
+ if (err)
+ return err;
+
err = unix_mkname(sunaddr, addr_len, &hash);
if (err < 0)
return err;
@@ -1246,6 +1254,10 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
goto out;
if (addr->sa_family != AF_UNSPEC) {
+ err = unix_validate_addr(sunaddr, alen);
+ if (err)
+ goto out;
+
err = unix_mkname(sunaddr, alen, &hash);
if (err < 0)
goto out;
@@ -1358,6 +1370,10 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
int err;
long timeo;
+ err = unix_validate_addr(sunaddr, addr_len);
+ if (err)
+ goto out;
+
err = unix_mkname(sunaddr, addr_len, &hash);
if (err < 0)
goto out;
@@ -1810,6 +1826,10 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
goto out;
if (msg->msg_namelen) {
+ err = unix_validate_addr(sunaddr, msg->msg_namelen);
+ if (err)
+ goto out;
+
err = unix_mkname(sunaddr, msg->msg_namelen, &hash);
if (err < 0)
goto out;