diff options
author | Jake Hamby <jhamby@google.com> | 2013-12-03 13:21:40 -0800 |
---|---|---|
committer | Jake Hamby <jhamby@google.com> | 2013-12-03 23:24:38 +0000 |
commit | 023346cf9050c146a36eedd14886d0e9a679dc49 (patch) | |
tree | d902aafb8b004af19288b8f82afd5a74c9751a3a | |
parent | 449cbf85380bd1d6716b7ab002da1efb9493bb02 (diff) | |
download | telephony-023346cf9050c146a36eedd14886d0e9a679dc49.tar.gz |
Fix OOBE crash/DoS after receiving 0-byte WAP push.android-sdk-4.4.2_r1.0.1android-sdk-4.4.2_r1
Add a try/catch block around the code in WapPushOverSms.dispatchWapPdu(),
so we don't get into a reboot trap on receiving weirdly formed messages.
Only catch ArrayIndexOutOfBoundsException, which is difficult to
prevent inside dispatchWapPdu() for 0-byte PDUs or other unusual
contents. The caller should probably catch any unhandled exceptions of other types and log them with stack traces.
Bug: 11967705
Change-Id: Iabfec68d2564dd438d45c80cdba877bf19fa0397
-rwxr-xr-x | src/java/com/android/internal/telephony/WapPushOverSms.java | 293 |
1 files changed, 150 insertions, 143 deletions
diff --git a/src/java/com/android/internal/telephony/WapPushOverSms.java b/src/java/com/android/internal/telephony/WapPushOverSms.java index 87b38109a8..2f22794cbf 100755 --- a/src/java/com/android/internal/telephony/WapPushOverSms.java +++ b/src/java/com/android/internal/telephony/WapPushOverSms.java @@ -90,168 +90,175 @@ public class WapPushOverSms implements ServiceConnection { if (DBG) Rlog.d(TAG, "Rx: " + IccUtils.bytesToHexString(pdu)); - int index = 0; - int transactionId = pdu[index++] & 0xFF; - int pduType = pdu[index++] & 0xFF; - - if ((pduType != WspTypeDecoder.PDU_TYPE_PUSH) && - (pduType != WspTypeDecoder.PDU_TYPE_CONFIRMED_PUSH)) { - index = mContext.getResources().getInteger( - com.android.internal.R.integer.config_valid_wappush_index); - if(index != -1) { - transactionId = pdu[index++] & 0xff; - pduType = pdu[index++] & 0xff; - if (DBG) - Rlog.d(TAG, "index = " + index + " PDU Type = " + pduType + - " transactionID = " + transactionId); - - // recheck wap push pduType - if ((pduType != WspTypeDecoder.PDU_TYPE_PUSH) - && (pduType != WspTypeDecoder.PDU_TYPE_CONFIRMED_PUSH)) { + try { + int index = 0; + int transactionId = pdu[index++] & 0xFF; + int pduType = pdu[index++] & 0xFF; + + if ((pduType != WspTypeDecoder.PDU_TYPE_PUSH) && + (pduType != WspTypeDecoder.PDU_TYPE_CONFIRMED_PUSH)) { + index = mContext.getResources().getInteger( + com.android.internal.R.integer.config_valid_wappush_index); + if (index != -1) { + transactionId = pdu[index++] & 0xff; + pduType = pdu[index++] & 0xff; + if (DBG) + Rlog.d(TAG, "index = " + index + " PDU Type = " + pduType + + " transactionID = " + transactionId); + + // recheck wap push pduType + if ((pduType != WspTypeDecoder.PDU_TYPE_PUSH) + && (pduType != WspTypeDecoder.PDU_TYPE_CONFIRMED_PUSH)) { + if (DBG) Rlog.w(TAG, "Received non-PUSH WAP PDU. Type = " + pduType); + return Intents.RESULT_SMS_HANDLED; + } + } else { if (DBG) Rlog.w(TAG, "Received non-PUSH WAP PDU. Type = " + pduType); return Intents.RESULT_SMS_HANDLED; } - } else { - if (DBG) Rlog.w(TAG, "Received non-PUSH WAP PDU. Type = " + pduType); - return Intents.RESULT_SMS_HANDLED; } - } - - WspTypeDecoder pduDecoder = new WspTypeDecoder(pdu); - /** - * Parse HeaderLen(unsigned integer). - * From wap-230-wsp-20010705-a section 8.1.2 - * The maximum size of a uintvar is 32 bits. - * So it will be encoded in no more than 5 octets. - */ - if (pduDecoder.decodeUintvarInteger(index) == false) { - if (DBG) Rlog.w(TAG, "Received PDU. Header Length error."); - return Intents.RESULT_SMS_GENERIC_ERROR; - } - int headerLength = (int) pduDecoder.getValue32(); - index += pduDecoder.getDecodedDataLength(); - - int headerStartIndex = index; - - /** - * Parse Content-Type. - * From wap-230-wsp-20010705-a section 8.4.2.24 - * - * Content-type-value = Constrained-media | Content-general-form - * Content-general-form = Value-length Media-type - * Media-type = (Well-known-media | Extension-Media) *(Parameter) - * Value-length = Short-length | (Length-quote Length) - * Short-length = <Any octet 0-30> (octet <= WAP_PDU_SHORT_LENGTH_MAX) - * Length-quote = <Octet 31> (WAP_PDU_LENGTH_QUOTE) - * Length = Uintvar-integer - */ - if (pduDecoder.decodeContentType(index) == false) { - if (DBG) Rlog.w(TAG, "Received PDU. Header Content-Type error."); - return Intents.RESULT_SMS_GENERIC_ERROR; - } - - String mimeType = pduDecoder.getValueString(); - long binaryContentType = pduDecoder.getValue32(); - index += pduDecoder.getDecodedDataLength(); + WspTypeDecoder pduDecoder = new WspTypeDecoder(pdu); + + /** + * Parse HeaderLen(unsigned integer). + * From wap-230-wsp-20010705-a section 8.1.2 + * The maximum size of a uintvar is 32 bits. + * So it will be encoded in no more than 5 octets. + */ + if (pduDecoder.decodeUintvarInteger(index) == false) { + if (DBG) Rlog.w(TAG, "Received PDU. Header Length error."); + return Intents.RESULT_SMS_GENERIC_ERROR; + } + int headerLength = (int) pduDecoder.getValue32(); + index += pduDecoder.getDecodedDataLength(); + + int headerStartIndex = index; + + /** + * Parse Content-Type. + * From wap-230-wsp-20010705-a section 8.4.2.24 + * + * Content-type-value = Constrained-media | Content-general-form + * Content-general-form = Value-length Media-type + * Media-type = (Well-known-media | Extension-Media) *(Parameter) + * Value-length = Short-length | (Length-quote Length) + * Short-length = <Any octet 0-30> (octet <= WAP_PDU_SHORT_LENGTH_MAX) + * Length-quote = <Octet 31> (WAP_PDU_LENGTH_QUOTE) + * Length = Uintvar-integer + */ + if (pduDecoder.decodeContentType(index) == false) { + if (DBG) Rlog.w(TAG, "Received PDU. Header Content-Type error."); + return Intents.RESULT_SMS_GENERIC_ERROR; + } - byte[] header = new byte[headerLength]; - System.arraycopy(pdu, headerStartIndex, header, 0, header.length); + String mimeType = pduDecoder.getValueString(); + long binaryContentType = pduDecoder.getValue32(); + index += pduDecoder.getDecodedDataLength(); - byte[] intentData; + byte[] header = new byte[headerLength]; + System.arraycopy(pdu, headerStartIndex, header, 0, header.length); - if (mimeType != null && mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO)) { - intentData = pdu; - } else { - int dataIndex = headerStartIndex + headerLength; - intentData = new byte[pdu.length - dataIndex]; - System.arraycopy(pdu, dataIndex, intentData, 0, intentData.length); - } + byte[] intentData; - /** - * Seek for application ID field in WSP header. - * If application ID is found, WapPushManager substitute the message - * processing. Since WapPushManager is optional module, if WapPushManager - * is not found, legacy message processing will be continued. - */ - if (pduDecoder.seekXWapApplicationId(index, index + headerLength - 1)) { - index = (int) pduDecoder.getValue32(); - pduDecoder.decodeXWapApplicationId(index); - String wapAppId = pduDecoder.getValueString(); - if (wapAppId == null) { - wapAppId = Integer.toString((int) pduDecoder.getValue32()); + if (mimeType != null && mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO)) { + intentData = pdu; + } else { + int dataIndex = headerStartIndex + headerLength; + intentData = new byte[pdu.length - dataIndex]; + System.arraycopy(pdu, dataIndex, intentData, 0, intentData.length); } - String contentType = ((mimeType == null) ? - Long.toString(binaryContentType) : mimeType); - if (DBG) Rlog.v(TAG, "appid found: " + wapAppId + ":" + contentType); - - try { - boolean processFurther = true; - IWapPushManager wapPushMan = mWapPushManager; + /** + * Seek for application ID field in WSP header. + * If application ID is found, WapPushManager substitute the message + * processing. Since WapPushManager is optional module, if WapPushManager + * is not found, legacy message processing will be continued. + */ + if (pduDecoder.seekXWapApplicationId(index, index + headerLength - 1)) { + index = (int) pduDecoder.getValue32(); + pduDecoder.decodeXWapApplicationId(index); + String wapAppId = pduDecoder.getValueString(); + if (wapAppId == null) { + wapAppId = Integer.toString((int) pduDecoder.getValue32()); + } - if (wapPushMan == null) { - if (DBG) Rlog.w(TAG, "wap push manager not found!"); - } else { - Intent intent = new Intent(); - intent.putExtra("transactionId", transactionId); - intent.putExtra("pduType", pduType); - intent.putExtra("header", header); - intent.putExtra("data", intentData); - intent.putExtra("contentTypeParameters", - pduDecoder.getContentParameters()); - - int procRet = wapPushMan.processMessage(wapAppId, contentType, intent); - if (DBG) Rlog.v(TAG, "procRet:" + procRet); - if ((procRet & WapPushManagerParams.MESSAGE_HANDLED) > 0 - && (procRet & WapPushManagerParams.FURTHER_PROCESSING) == 0) { - processFurther = false; + String contentType = ((mimeType == null) ? + Long.toString(binaryContentType) : mimeType); + if (DBG) Rlog.v(TAG, "appid found: " + wapAppId + ":" + contentType); + + try { + boolean processFurther = true; + IWapPushManager wapPushMan = mWapPushManager; + + if (wapPushMan == null) { + if (DBG) Rlog.w(TAG, "wap push manager not found!"); + } else { + Intent intent = new Intent(); + intent.putExtra("transactionId", transactionId); + intent.putExtra("pduType", pduType); + intent.putExtra("header", header); + intent.putExtra("data", intentData); + intent.putExtra("contentTypeParameters", + pduDecoder.getContentParameters()); + + int procRet = wapPushMan.processMessage(wapAppId, contentType, intent); + if (DBG) Rlog.v(TAG, "procRet:" + procRet); + if ((procRet & WapPushManagerParams.MESSAGE_HANDLED) > 0 + && (procRet & WapPushManagerParams.FURTHER_PROCESSING) == 0) { + processFurther = false; + } } + if (!processFurther) { + return Intents.RESULT_SMS_HANDLED; + } + } catch (RemoteException e) { + if (DBG) Rlog.w(TAG, "remote func failed..."); } - if (!processFurther) { - return Intents.RESULT_SMS_HANDLED; - } - } catch (RemoteException e) { - if (DBG) Rlog.w(TAG, "remote func failed..."); } - } - if (DBG) Rlog.v(TAG, "fall back to existing handler"); + if (DBG) Rlog.v(TAG, "fall back to existing handler"); - if (mimeType == null) { - if (DBG) Rlog.w(TAG, "Header Content-Type error."); - return Intents.RESULT_SMS_GENERIC_ERROR; - } + if (mimeType == null) { + if (DBG) Rlog.w(TAG, "Header Content-Type error."); + return Intents.RESULT_SMS_GENERIC_ERROR; + } - String permission; - int appOp; + String permission; + int appOp; - if (mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_MMS)) { - permission = android.Manifest.permission.RECEIVE_MMS; - appOp = AppOpsManager.OP_RECEIVE_MMS; - } else { - permission = android.Manifest.permission.RECEIVE_WAP_PUSH; - appOp = AppOpsManager.OP_RECEIVE_WAP_PUSH; - } + if (mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_MMS)) { + permission = android.Manifest.permission.RECEIVE_MMS; + appOp = AppOpsManager.OP_RECEIVE_MMS; + } else { + permission = android.Manifest.permission.RECEIVE_WAP_PUSH; + appOp = AppOpsManager.OP_RECEIVE_WAP_PUSH; + } - Intent intent = new Intent(Intents.WAP_PUSH_DELIVER_ACTION); - intent.setType(mimeType); - intent.putExtra("transactionId", transactionId); - intent.putExtra("pduType", pduType); - intent.putExtra("header", header); - intent.putExtra("data", intentData); - intent.putExtra("contentTypeParameters", pduDecoder.getContentParameters()); - - // Direct the intent to only the default MMS app. If we can't find a default MMS app - // then sent it to all broadcast receivers. - ComponentName componentName = SmsApplication.getDefaultMmsApplication(mContext, true); - if (componentName != null) { - // Deliver MMS message only to this receiver - intent.setComponent(componentName); - if (DBG) Rlog.v(TAG, "Delivering MMS to: " + componentName.getPackageName() + - " " + componentName.getClassName()); - } + Intent intent = new Intent(Intents.WAP_PUSH_DELIVER_ACTION); + intent.setType(mimeType); + intent.putExtra("transactionId", transactionId); + intent.putExtra("pduType", pduType); + intent.putExtra("header", header); + intent.putExtra("data", intentData); + intent.putExtra("contentTypeParameters", pduDecoder.getContentParameters()); + + // Direct the intent to only the default MMS app. If we can't find a default MMS app + // then sent it to all broadcast receivers. + ComponentName componentName = SmsApplication.getDefaultMmsApplication(mContext, true); + if (componentName != null) { + // Deliver MMS message only to this receiver + intent.setComponent(componentName); + if (DBG) Rlog.v(TAG, "Delivering MMS to: " + componentName.getPackageName() + + " " + componentName.getClassName()); + } - handler.dispatchIntent(intent, permission, appOp, receiver); - return Activity.RESULT_OK; + handler.dispatchIntent(intent, permission, appOp, receiver); + return Activity.RESULT_OK; + } catch (ArrayIndexOutOfBoundsException aie) { + // 0-byte WAP PDU or other unexpected WAP PDU contents can easily throw this; + // log exception string without stack trace and return false. + Rlog.e(TAG, "ignoring dispatchWapPdu() array index exception: " + aie); + return Intents.RESULT_SMS_GENERIC_ERROR; + } } } |