diff options
author | silby <silby@FreeBSD.org> | 2002-04-26 02:07:46 +0000 |
---|---|---|
committer | silby <silby@FreeBSD.org> | 2002-04-26 02:07:46 +0000 |
commit | dd3cd5fed6df2d8b97036107ac5ef6e2b04bf7e8 (patch) | |
tree | e3d11ae343cdd5c86800f10650b42963d5e33da1 /sys/kern | |
parent | 522debf4fd85d981f5118693ad97663ad0d16c6b (diff) | |
download | FreeBSD-src-dd3cd5fed6df2d8b97036107ac5ef6e2b04bf7e8.zip FreeBSD-src-dd3cd5fed6df2d8b97036107ac5ef6e2b04bf7e8.tar.gz |
Make sure that sockets undergoing accept filtering are aborted in a
LRU fashion when the listen queue fills up. Previously, there was
no mechanism to kick out old sockets, leading to an easy DoS of
daemons using accept filtering.
Reviewed by: alfred
MFC after: 3 days
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/uipc_sockbuf.c | 8 | ||||
-rw-r--r-- | sys/kern/uipc_socket.c | 3 | ||||
-rw-r--r-- | sys/kern/uipc_socket2.c | 8 |
3 files changed, 15 insertions, 4 deletions
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c index 47bf7bb..1a8afd3 100644 --- a/sys/kern/uipc_sockbuf.c +++ b/sys/kern/uipc_sockbuf.c @@ -127,6 +127,7 @@ soisconnected(so) head->so_incqlen--; so->so_state &= ~SS_INCOMP; TAILQ_INSERT_TAIL(&head->so_comp, so, so_list); + head->so_qlen++; so->so_state |= SS_COMP; sorwakeup(head); wakeup_one(&head->so_timeo); @@ -202,12 +203,17 @@ sonewconn(head, connstatus) if (connstatus) { TAILQ_INSERT_TAIL(&head->so_comp, so, so_list); so->so_state |= SS_COMP; + head->so_qlen++; } else { + if (head->so_incqlen >= head->so_qlimit) { + struct socket *sp; + sp = TAILQ_FIRST(&head->so_incomp); + (void) soabort(sp); + } TAILQ_INSERT_TAIL(&head->so_incomp, so, so_list); so->so_state |= SS_INCOMP; head->so_incqlen++; } - head->so_qlen++; if (connstatus) { sorwakeup(head); wakeup((caddr_t)&head->so_timeo); diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 6c68a79..0e0fbd9 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -281,7 +281,6 @@ sofree(so) } else { panic("sofree: not queued"); } - head->so_qlen--; so->so_state &= ~SS_INCOMP; so->so_head = NULL; } @@ -1674,7 +1673,7 @@ filt_solisten(struct knote *kn, long hint) { struct socket *so = (struct socket *)kn->kn_fp->f_data; - kn->kn_data = so->so_qlen - so->so_incqlen; + kn->kn_data = so->so_qlen; return (! TAILQ_EMPTY(&so->so_comp)); } diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c index 47bf7bb..1a8afd3 100644 --- a/sys/kern/uipc_socket2.c +++ b/sys/kern/uipc_socket2.c @@ -127,6 +127,7 @@ soisconnected(so) head->so_incqlen--; so->so_state &= ~SS_INCOMP; TAILQ_INSERT_TAIL(&head->so_comp, so, so_list); + head->so_qlen++; so->so_state |= SS_COMP; sorwakeup(head); wakeup_one(&head->so_timeo); @@ -202,12 +203,17 @@ sonewconn(head, connstatus) if (connstatus) { TAILQ_INSERT_TAIL(&head->so_comp, so, so_list); so->so_state |= SS_COMP; + head->so_qlen++; } else { + if (head->so_incqlen >= head->so_qlimit) { + struct socket *sp; + sp = TAILQ_FIRST(&head->so_incomp); + (void) soabort(sp); + } TAILQ_INSERT_TAIL(&head->so_incomp, so, so_list); so->so_state |= SS_INCOMP; head->so_incqlen++; } - head->so_qlen++; if (connstatus) { sorwakeup(head); wakeup((caddr_t)&head->so_timeo); |