diff -Nur openbsc.old/include/openbsc/signal.h openbsc.new/include/openbsc/signal.h
--- openbsc.old/include/openbsc/signal.h	2009-05-23 17:32:16.000000000 +0200
+++ openbsc.new/include/openbsc/signal.h	2009-06-06 09:30:25.000000000 +0200
@@ -37,6 +37,7 @@
 	SS_SMS,
 	SS_ABISIP,
 	SS_NM,
+	SS_LCHAN,
 };
 
 /* SS_PAGING signals */
@@ -55,6 +56,15 @@
 	S_NM_FAIL_REP,		/* GSM 12.21 failure event report */
 };
 
+/* SS_LCHAN signals */
+enum signal_lchan {
+	/*
+	 * The lchan got freed with refcount != 0 and error
+	 * recovery needs to happen right now.
+	 */
+	S_LCHAN_UNEXPECTED_RELEASE,
+};
+
 typedef int signal_cbfn(unsigned int subsys, unsigned int signal,
 			void *handler_data, void *signal_data);
 
diff -Nur openbsc.old/src/chan_alloc.c openbsc.new/src/chan_alloc.c
--- openbsc.old/src/chan_alloc.c	2009-05-23 17:32:17.000000000 +0200
+++ openbsc.new/src/chan_alloc.c	2009-06-06 09:35:17.000000000 +0200
@@ -31,6 +31,7 @@
 #include <openbsc/abis_nm.h>
 #include <openbsc/abis_rsl.h>
 #include <openbsc/debug.h>
+#include <openbsc/signal.h>
 
 static void auto_release_channel(void *_lchan);
 
@@ -193,8 +194,9 @@
 		lchan->subscr = 0;
 	}
 
-	/* We might kill an active channel... FIXME: call cancellations */
+	/* We might kill an active channel... */
 	if (lchan->use_count != 0) {
+		dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, lchan);
 		lchan->use_count = 0;
 	}
 
diff -Nur openbsc.old/src/gsm_04_08.c openbsc.new/src/gsm_04_08.c
--- openbsc.old/src/gsm_04_08.c	2009-06-06 08:52:36.000000000 +0200
+++ openbsc.new/src/gsm_04_08.c	2009-06-06 09:30:25.000000000 +0200
@@ -161,7 +161,7 @@
 	return subscriber->authorized;
 }
 
-static void release_loc_updating_req(struct gsm_lchan *lchan)
+void release_loc_updating_req(struct gsm_lchan *lchan)
 {
 	if (!lchan->loc_operation)
 		return;
@@ -182,6 +182,24 @@
 	memset(lchan->loc_operation, 0, sizeof(*lchan->loc_operation));
 }
 
+static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
+					void *handler_data, void *signal_data)
+{
+	if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
+		return 0;
+
+	/* give up on the loc_operation in case of error */
+	struct gsm_lchan *lchan = (struct gsm_lchan *)handler_data;
+	release_loc_updating_req(lchan);
+
+	return 0;
+}
+
+static __attribute__((constructor)) void on_load_0408(void)
+{
+	register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
+}
+
 static void to_bcd(u_int8_t *bcd, u_int16_t val)
 {
 	bcd[2] = val % 10;
@@ -481,11 +499,6 @@
 	DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
 		mi_type, mi_string);
 
-	/*
-	 * Rogue messages could trick us but so is life
-	 */
-	put_lchan(lchan);
-
 	switch (mi_type) {
 	case GSM_MI_TYPE_IMSI:
 		if (!lchan->subscr)
@@ -568,12 +581,18 @@
 	DEBUGP(DMM, "LUPDREQ: mi_type=0x%02x MI(%s) type=%s\n", mi_type, mi_string,
 		lupd_name(lu->type));
 
+	/* two location updating request on the same lchan... *spoof* */
+	if (lchan->loc_operation) {
+		gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR);
+		return 0;
+	}
+
+
 	allocate_loc_updating_req(lchan);
 
 	switch (mi_type) {
 	case GSM_MI_TYPE_IMSI:
 		/* we always want the IMEI, too */
-		use_lchan(lchan);
 		rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
 		lchan->loc_operation->waiting_for_imei = 1;
 
@@ -582,7 +601,6 @@
 		break;
 	case GSM_MI_TYPE_TMSI:
 		/* we always want the IMEI, too */
-		use_lchan(lchan);
 		rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI);
 		lchan->loc_operation->waiting_for_imei = 1;
 
@@ -590,7 +608,6 @@
 		subscr = subscr_get_by_tmsi(mi_string);
 		if (!subscr) {
 			/* send IDENTITY REQUEST message to get IMSI */
-			use_lchan(lchan);
 			rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
 			lchan->loc_operation->waiting_for_imsi = 1;
 		}
@@ -856,8 +873,6 @@
 	} else
 		DEBUGP(DMM, "Unknown Subscriber ?!?\n");
 
-	put_lchan(msg->lchan);
-
 	return 0;
 }
 
@@ -941,7 +956,6 @@
 	if (!subscr) {
 		DEBUGP(DRR, "<- Can't find any subscriber for this ID\n");
 		/* FIXME: request id? close channel? */
-		return -EINVAL;
 	}
 	DEBUGP(DRR, "<- Channel was requested by %s\n",
 		subscr->name ? subscr->name : subscr->imsi);
