* - 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
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;
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;
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;
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;