| From 09358972bff5ce99de496bbba97c85d417b3c054 Mon Sep 17 00:00:00 2001 |
| From: Robin Holt <holt@sgi.com> |
| Date: Tue, 26 Oct 2010 14:21:15 -0700 |
| Subject: sgi-xp: incoming XPC channel messages can come in after the channel's partition structures have been torn down |
| |
| From: Robin Holt <holt@sgi.com> |
| |
| commit 09358972bff5ce99de496bbba97c85d417b3c054 upstream. |
| |
| Under some workloads, some channel messages have been observed being |
| delayed on the sending side past the point where the receiving side has |
| been able to tear down its partition structures. |
| |
| This condition is already detected in xpc_handle_activate_IRQ_uv(), but |
| that information is not given to xpc_handle_activate_mq_msg_uv(). As a |
| result, xpc_handle_activate_mq_msg_uv() assumes the structures still exist |
| and references them, causing a NULL-pointer deref. |
| |
| Signed-off-by: Robin Holt <holt@sgi.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| drivers/misc/sgi-xp/xpc_uv.c | 17 +++++++++++++++++ |
| 1 file changed, 17 insertions(+) |
| |
| --- a/drivers/misc/sgi-xp/xpc_uv.c |
| +++ b/drivers/misc/sgi-xp/xpc_uv.c |
| @@ -409,6 +409,7 @@ xpc_process_activate_IRQ_rcvd_uv(void) |
| static void |
| xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, |
| struct xpc_activate_mq_msghdr_uv *msg_hdr, |
| + int part_setup, |
| int *wakeup_hb_checker) |
| { |
| unsigned long irq_flags; |
| @@ -473,6 +474,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc |
| case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV: { |
| struct xpc_activate_mq_msg_chctl_closerequest_uv *msg; |
| |
| + if (!part_setup) |
| + break; |
| + |
| msg = container_of(msg_hdr, struct |
| xpc_activate_mq_msg_chctl_closerequest_uv, |
| hdr); |
| @@ -489,6 +493,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc |
| case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV: { |
| struct xpc_activate_mq_msg_chctl_closereply_uv *msg; |
| |
| + if (!part_setup) |
| + break; |
| + |
| msg = container_of(msg_hdr, struct |
| xpc_activate_mq_msg_chctl_closereply_uv, |
| hdr); |
| @@ -503,6 +510,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc |
| case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV: { |
| struct xpc_activate_mq_msg_chctl_openrequest_uv *msg; |
| |
| + if (!part_setup) |
| + break; |
| + |
| msg = container_of(msg_hdr, struct |
| xpc_activate_mq_msg_chctl_openrequest_uv, |
| hdr); |
| @@ -520,6 +530,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc |
| case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV: { |
| struct xpc_activate_mq_msg_chctl_openreply_uv *msg; |
| |
| + if (!part_setup) |
| + break; |
| + |
| msg = container_of(msg_hdr, struct |
| xpc_activate_mq_msg_chctl_openreply_uv, hdr); |
| args = &part->remote_openclose_args[msg->ch_number]; |
| @@ -537,6 +550,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc |
| case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV: { |
| struct xpc_activate_mq_msg_chctl_opencomplete_uv *msg; |
| |
| + if (!part_setup) |
| + break; |
| + |
| msg = container_of(msg_hdr, struct |
| xpc_activate_mq_msg_chctl_opencomplete_uv, hdr); |
| spin_lock_irqsave(&part->chctl_lock, irq_flags); |
| @@ -613,6 +629,7 @@ xpc_handle_activate_IRQ_uv(int irq, void |
| |
| part_referenced = xpc_part_ref(part); |
| xpc_handle_activate_mq_msg_uv(part, msg_hdr, |
| + part_referenced, |
| &wakeup_hb_checker); |
| if (part_referenced) |
| xpc_part_deref(part); |