The ioctl() calls using FIONREAD, FIONWRITE, FIONSPACE, and SIOCATMARK

access the socket send or receive buffer. This is not possible for
listening sockets since r319722.
Because send()/recv() calls fail on listening sockets, fail also ioctl()
indicating EINVAL.

PR:			250366
Reported by:		Yong-Hao Zou
Reviewed by:		glebius, rscheff
MFC after:		1 week
Sponsored by:		Netflix, Inc.
Differential Revision:	https://reviews.freebsd.org/D26897
This commit is contained in:
Michael Tuexen 2020-11-07 21:17:49 +00:00
parent ce558a3f33
commit f908d8247e

View File

@ -207,21 +207,34 @@ soo_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *active_cred,
case FIONREAD:
/* Unlocked read. */
*(int *)data = sbavail(&so->so_rcv);
if (SOLISTENING(so)) {
error = EINVAL;
} else {
*(int *)data = sbavail(&so->so_rcv);
}
break;
case FIONWRITE:
/* Unlocked read. */
*(int *)data = sbavail(&so->so_snd);
if (SOLISTENING(so)) {
error = EINVAL;
} else {
*(int *)data = sbavail(&so->so_snd);
}
break;
case FIONSPACE:
/* Unlocked read. */
if ((so->so_snd.sb_hiwat < sbused(&so->so_snd)) ||
(so->so_snd.sb_mbmax < so->so_snd.sb_mbcnt))
*(int *)data = 0;
else
*(int *)data = sbspace(&so->so_snd);
if (SOLISTENING(so)) {
error = EINVAL;
} else {
if ((so->so_snd.sb_hiwat < sbused(&so->so_snd)) ||
(so->so_snd.sb_mbmax < so->so_snd.sb_mbcnt)) {
*(int *)data = 0;
} else {
*(int *)data = sbspace(&so->so_snd);
}
}
break;
case FIOSETOWN:
@ -242,7 +255,11 @@ soo_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *active_cred,
case SIOCATMARK:
/* Unlocked read. */
*(int *)data = (so->so_rcv.sb_state & SBS_RCVATMARK) != 0;
if (SOLISTENING(so)) {
error = EINVAL;
} else {
*(int *)data = (so->so_rcv.sb_state & SBS_RCVATMARK) != 0;
}
break;
default:
/*