--- zzzz-none-000/linux-3.10.107/net/unix/af_unix.c 2017-06-27 09:49:32.000000000 +0000 +++ vr9-7490-729/linux-3.10.107/net/unix/af_unix.c 2021-11-10 11:53:56.000000000 +0000 @@ -216,15 +216,16 @@ 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 - * subtle. 108 is the longest valid AF_UNIX path for a binding. - * sun_path[108] doesn't as such exist. However in kernel space - * we are guaranteed that it is a valid memory location in our - * kernel address buffer. - */ + unsigned char value; + if(len == sizeof(*sunaddr)) len--; /*--- mbahr@avm: don't write over struct-boundary ! ---*/ + value = ((unsigned char *)sunaddr)[len]; ((char *)sunaddr)[len] = 0; len = strlen(sunaddr->sun_path)+1+sizeof(short); + if(value && (len == sizeof(*sunaddr))) { + /*--- mbahr@avm: check - UNIX_MAX_PATH include zero-termination! ---*/ + printk(KERN_ERR"%s: error sun_path exceeded '%s%c'\n", __func__, sunaddr->sun_path, value); + return -EINVAL; + } return len; } @@ -1719,7 +1720,12 @@ goto out_unlock; } - if (unlikely(unix_peer(other) != sk && unix_recvq_full(other))) { + /* other == sk && unix_peer(other) != sk if + * - unix_peer(sk) == NULL, destination address bound to sk + * - unix_peer(sk) == sk by time of get but disconnected before lock + */ + if (other != sk && + unlikely(unix_peer(other) != sk && unix_recvq_full(other))) { if (timeo) { timeo = unix_wait_for_peer(other, timeo);