| From foo@baz Tue Jan 26 21:35:03 PST 2016 |
| From: Xin Long <lucien.xin@gmail.com> |
| Date: Tue, 29 Dec 2015 17:49:25 +0800 |
| Subject: sctp: sctp should release assoc when sctp_make_abort_user return NULL in sctp_close |
| |
| From: Xin Long <lucien.xin@gmail.com> |
| |
| [ Upstream commit 068d8bd338e855286aea54e70d1c101569284b21 ] |
| |
| In sctp_close, sctp_make_abort_user may return NULL because of memory |
| allocation failure. If this happens, it will bypass any state change |
| and never free the assoc. The assoc has no chance to be freed and it |
| will be kept in memory with the state it had even after the socket is |
| closed by sctp_close(). |
| |
| So if sctp_make_abort_user fails to allocate memory, we should abort |
| the asoc via sctp_primitive_ABORT as well. Just like the annotation in |
| sctp_sf_cookie_wait_prm_abort and sctp_sf_do_9_1_prm_abort said, |
| "Even if we can't send the ABORT due to low memory delete the TCB. |
| This is a departure from our typical NOMEM handling". |
| |
| But then the chunk is NULL (low memory) and the SCTP_CMD_REPLY cmd would |
| dereference the chunk pointer, and system crash. So we should add |
| SCTP_CMD_REPLY cmd only when the chunk is not NULL, just like other |
| places where it adds SCTP_CMD_REPLY cmd. |
| |
| Signed-off-by: Xin Long <lucien.xin@gmail.com> |
| Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/sctp/sm_statefuns.c | 6 ++++-- |
| net/sctp/socket.c | 3 +-- |
| 2 files changed, 5 insertions(+), 4 deletions(-) |
| |
| --- a/net/sctp/sm_statefuns.c |
| +++ b/net/sctp/sm_statefuns.c |
| @@ -4829,7 +4829,8 @@ sctp_disposition_t sctp_sf_do_9_1_prm_ab |
| |
| retval = SCTP_DISPOSITION_CONSUME; |
| |
| - sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); |
| + if (abort) |
| + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); |
| |
| /* Even if we can't send the ABORT due to low memory delete the |
| * TCB. This is a departure from our typical NOMEM handling. |
| @@ -4966,7 +4967,8 @@ sctp_disposition_t sctp_sf_cookie_wait_p |
| SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); |
| retval = SCTP_DISPOSITION_CONSUME; |
| |
| - sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); |
| + if (abort) |
| + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); |
| |
| sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
| SCTP_STATE(SCTP_STATE_CLOSED)); |
| --- a/net/sctp/socket.c |
| +++ b/net/sctp/socket.c |
| @@ -1513,8 +1513,7 @@ static void sctp_close(struct sock *sk, |
| struct sctp_chunk *chunk; |
| |
| chunk = sctp_make_abort_user(asoc, NULL, 0); |
| - if (chunk) |
| - sctp_primitive_ABORT(net, asoc, chunk); |
| + sctp_primitive_ABORT(net, asoc, chunk); |
| } else |
| sctp_primitive_SHUTDOWN(net, asoc, NULL); |
| } |