Add buffer size checks to eliminate security vulnerability. am: 0fef164d3d
Change-Id: Ifb03c3496ac450201fc205708a66de4bc7db5a9c
diff --git a/Android.bp b/Android.bp
index 3dd8f09..7f2d193 100644
--- a/Android.bp
+++ b/Android.bp
@@ -15,8 +15,10 @@
filegroup {
name: "opt-net-voip-srcs",
srcs: [
- "src/java/android/net/**/*.java",
+ "src/java/**/*.java",
+ "src/java/**/I*.aidl",
],
+ path: "src/java",
}
filegroup {
@@ -29,14 +31,9 @@
java_library {
name: "voip-common",
installable: true,
- srcs: [
- "src/java/**/*.java",
- "src/java/**/I*.aidl",
+ srcs: [":opt-net-voip-srcs"],
+ static_libs: [
+ "nist-sip",
],
- aidl: {
- local_include_dirs: [
- "src/java",
- ],
- },
required: ["librtp_jni"],
}
diff --git a/src/java/android/net/rtp/AudioGroup.java b/src/java/android/net/rtp/AudioGroup.java
index 15390d3..9d96006 100644
--- a/src/java/android/net/rtp/AudioGroup.java
+++ b/src/java/android/net/rtp/AudioGroup.java
@@ -16,7 +16,9 @@
package android.net.rtp;
+import android.annotation.NonNull;
import android.app.ActivityThread;
+import android.content.Context;
import android.media.AudioManager;
import java.util.HashMap;
@@ -96,14 +98,26 @@
private int mMode = MODE_ON_HOLD;
private long mNative;
+ private Context mContext;
static {
System.loadLibrary("rtp_jni");
}
/**
* Creates an empty AudioGroup.
+ * @deprecated Replaced by {@link #AudioGroup(Context)}
*/
+ @Deprecated
public AudioGroup() {
+ this(null);
+ }
+
+ /**
+ * Creates an empty AudioGroup.
+ * @param context Context used to get package name
+ */
+ public AudioGroup(@NonNull Context context) {
+ mContext = context;
mStreams = new HashMap<AudioStream, Long>();
}
@@ -153,7 +167,8 @@
long id = nativeAdd(stream.getMode(), stream.getSocket(),
stream.getRemoteAddress().getHostAddress(),
stream.getRemotePort(), codecSpec, stream.getDtmfType(),
- ActivityThread.currentOpPackageName());
+ mContext != null ? mContext.getOpPackageName()
+ : ActivityThread.currentOpPackageName());
mStreams.put(stream, id);
} catch (NullPointerException e) {
throw new IllegalStateException(e);
diff --git a/src/java/android/net/sip/ISipService.aidl b/src/java/android/net/sip/ISipService.aidl
index 84750c7..adbf1cb 100644
--- a/src/java/android/net/sip/ISipService.aidl
+++ b/src/java/android/net/sip/ISipService.aidl
@@ -39,5 +39,5 @@
in ISipSessionListener listener, String opPackageName);
ISipSession getPendingSession(String callId, String opPackageName);
- SipProfile[] getListOfProfiles(String opPackageName);
+ List<SipProfile> getProfiles(String opPackageName);
}
diff --git a/src/java/android/net/sip/SipAudioCall.java b/src/java/android/net/sip/SipAudioCall.java
index ea943e9..363995c 100644
--- a/src/java/android/net/sip/SipAudioCall.java
+++ b/src/java/android/net/sip/SipAudioCall.java
@@ -16,6 +16,9 @@
package android.net.sip;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.content.Context;
import android.media.AudioManager;
import android.net.rtp.AudioCodec;
@@ -27,6 +30,7 @@
import android.os.Message;
import android.telephony.Rlog;
import android.text.TextUtils;
+
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -191,6 +195,7 @@
private int mErrorCode = SipErrorCode.NO_ERROR;
private String mErrorMessage;
+ private final Object mLock;
/**
* Creates a call object with the local SIP profile.
@@ -201,6 +206,7 @@
mContext = context;
mLocalProfile = localProfile;
mWm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ mLock = new Object();
}
/**
@@ -265,7 +271,7 @@
* @return true if the call is established
*/
public boolean isInCall() {
- synchronized (this) {
+ synchronized (mLock) {
return mInCall;
}
}
@@ -276,7 +282,7 @@
* @return true if the call is on hold
*/
public boolean isOnHold() {
- synchronized (this) {
+ synchronized (mLock) {
return mHold;
}
}
@@ -309,7 +315,7 @@
* @return the local SIP profile
*/
public SipProfile getLocalProfile() {
- synchronized (this) {
+ synchronized (mLock) {
return mLocalProfile;
}
}
@@ -320,7 +326,7 @@
* @return the peer's SIP profile
*/
public SipProfile getPeerProfile() {
- synchronized (this) {
+ synchronized (mLock) {
return (mSipSession == null) ? null : mSipSession.getPeerProfile();
}
}
@@ -332,7 +338,7 @@
* @return the session state
*/
public int getState() {
- synchronized (this) {
+ synchronized (mLock) {
if (mSipSession == null) return SipSession.State.READY_TO_CALL;
return mSipSession.getState();
}
@@ -346,7 +352,7 @@
* @hide
*/
public SipSession getSipSession() {
- synchronized (this) {
+ synchronized (mLock) {
return mSipSession;
}
}
@@ -404,7 +410,7 @@
public void onRinging(SipSession session,
SipProfile peerProfile, String sessionDescription) {
// this callback is triggered only for reinvite.
- synchronized (SipAudioCall.this) {
+ synchronized (mLock) {
if ((mSipSession == null) || !mInCall
|| !session.getCallId().equals(
mSipSession.getCallId())) {
@@ -568,7 +574,7 @@
loge("onError():", t);
}
}
- synchronized (this) {
+ synchronized (mLock) {
if ((errorCode == SipErrorCode.DATA_CONNECTION_LOST)
|| !isInCall()) {
close(true);
@@ -591,7 +597,7 @@
throw new SipException("VOIP API is not supported");
}
- synchronized (this) {
+ synchronized (mLock) {
mSipSession = session;
mPeerSd = sessionDescription;
if (DBG) log("attachCall(): " + mPeerSd);
@@ -626,7 +632,7 @@
throw new SipException("VOIP API is not supported");
}
- synchronized (this) {
+ synchronized (mLock) {
mSipSession = sipSession;
try {
mAudioStream = new AudioStream(InetAddress.getByName(
@@ -647,7 +653,7 @@
*/
public void endCall() throws SipException {
if (DBG) log("endCall: mSipSession" + mSipSession);
- synchronized (this) {
+ synchronized (mLock) {
stopCall(RELEASE_SOCKET);
mInCall = false;
@@ -670,7 +676,7 @@
*/
public void holdCall(int timeout) throws SipException {
if (DBG) log("holdCall: mSipSession" + mSipSession + " timeout=" + timeout);
- synchronized (this) {
+ synchronized (mLock) {
if (mHold) return;
if (mSipSession == null) {
loge("holdCall:");
@@ -695,7 +701,7 @@
*/
public void answerCall(int timeout) throws SipException {
if (DBG) log("answerCall: mSipSession" + mSipSession + " timeout=" + timeout);
- synchronized (this) {
+ synchronized (mLock) {
if (mSipSession == null) {
throw new SipException("No call to answer");
}
@@ -724,7 +730,7 @@
*/
public void continueCall(int timeout) throws SipException {
if (DBG) log("continueCall: mSipSession" + mSipSession + " timeout=" + timeout);
- synchronized (this) {
+ synchronized (mLock) {
if (!mHold) return;
mSipSession.changeCall(createContinueOffer().encode(), timeout);
mHold = false;
@@ -854,7 +860,7 @@
/** Toggles mute. */
public void toggleMute() {
- synchronized (this) {
+ synchronized (mLock) {
mMuted = !mMuted;
setAudioGroupMode();
}
@@ -866,7 +872,7 @@
* @return true if the call is muted
*/
public boolean isMuted() {
- synchronized (this) {
+ synchronized (mLock) {
return mMuted;
}
}
@@ -879,7 +885,7 @@
* @param speakerMode set true to enable speaker mode; false to disable
*/
public void setSpeakerMode(boolean speakerMode) {
- synchronized (this) {
+ synchronized (mLock) {
((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE))
.setSpeakerphoneOn(speakerMode);
setAudioGroupMode();
@@ -915,7 +921,7 @@
* @param result the result message to send when done
*/
public void sendDtmf(int code, Message result) {
- synchronized (this) {
+ synchronized (mLock) {
AudioGroup audioGroup = getAudioGroup();
if ((audioGroup != null) && (mSipSession != null)
&& (SipSession.State.IN_CALL == getState())) {
@@ -938,7 +944,7 @@
* @hide
*/
public AudioStream getAudioStream() {
- synchronized (this) {
+ synchronized (mLock) {
return mAudioStream;
}
}
@@ -957,8 +963,9 @@
* @see #getAudioStream
* @hide
*/
- public AudioGroup getAudioGroup() {
- synchronized (this) {
+ @SystemApi
+ public @Nullable AudioGroup getAudioGroup() {
+ synchronized (mLock) {
if (mAudioGroup != null) return mAudioGroup;
return ((mAudioStream == null) ? null : mAudioStream.getGroup());
}
@@ -976,8 +983,9 @@
* @see #getAudioStream
* @hide
*/
- public void setAudioGroup(AudioGroup group) {
- synchronized (this) {
+ @SystemApi
+ public void setAudioGroup(@NonNull AudioGroup group) {
+ synchronized (mLock) {
if (DBG) log("setAudioGroup: group=" + group);
if ((mAudioStream != null) && (mAudioStream.getGroup() != null)) {
mAudioStream.join(group);
@@ -1081,7 +1089,7 @@
// don't create an AudioGroup here; doing so will fail if
// there's another AudioGroup out there that's active
} else {
- if (audioGroup == null) audioGroup = new AudioGroup();
+ if (audioGroup == null) audioGroup = new AudioGroup(mContext);
stream.join(audioGroup);
}
setAudioGroupMode();
diff --git a/src/java/android/net/sip/SipManager.java b/src/java/android/net/sip/SipManager.java
index 0cb1feb..39f66de 100644
--- a/src/java/android/net/sip/SipManager.java
+++ b/src/java/android/net/sip/SipManager.java
@@ -16,6 +16,9 @@
package android.net.sip;
+import android.annotation.NonNull;
+import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
@@ -26,6 +29,8 @@
import android.telephony.Rlog;
import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.List;
/**
* Provides APIs for SIP tasks, such as initiating SIP connections, and provides access to related
@@ -81,19 +86,23 @@
public static final String EXTRA_OFFER_SD = "android:sipOfferSD";
/**
- * Action to broadcast when SipService is up.
- * Internal use only.
+ * Intent action sent when the SipManager becomes available.
* @hide
*/
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ @SystemApi
public static final String ACTION_SIP_SERVICE_UP =
- "android.net.sip.SIP_SERVICE_UP";
+ "android.net.sip.action.SIP_SERVICE_UP";
+
/**
- * Action string for the incoming call intent for the Phone app.
- * Internal use only.
+ * Intent action sent when there is a new incoming SIP call.
* @hide
*/
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ @SystemApi
public static final String ACTION_SIP_INCOMING_CALL =
- "com.android.phone.SIP_INCOMING_CALL";
+ "android.net.sip.action.SIP_INCOMING_CALL";
+
/**
* Action string for the add-phone intent.
* Internal use only.
@@ -101,23 +110,34 @@
*/
public static final String ACTION_SIP_ADD_PHONE =
"com.android.phone.SIP_ADD_PHONE";
- /**
- * Action string for the remove-phone intent.
- * Internal use only.
- * @hide
- */
- public static final String ACTION_SIP_REMOVE_PHONE =
- "com.android.phone.SIP_REMOVE_PHONE";
/**
- * Action string for the SIP call option configuration changed intent.
- * This is used to communicate change to the SIP call option, triggering re-registration of
- * the SIP phone accounts.
- * Internal use only.
+ * Intent action sent when a SIP profile has been removed.
* @hide
*/
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ @SystemApi
+ public static final String ACTION_SIP_REMOVE_PROFILE =
+ "android.net.sip.action.SIP_REMOVE_PROFILE";
+
+ /**
+ * Intent action sent when the SIP accounts or other configuration has changed.
+ * This should trigger a re-registration of the SIP PhoneAccounts.
+ * @hide
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ @SystemApi
public static final String ACTION_SIP_CALL_OPTION_CHANGED =
- "com.android.phone.SIP_CALL_OPTION_CHANGED";
+ "android.net.sip.action.SIP_CALL_OPTION_CHANGED";
+
+ /**
+ * Intent action used by Telephony to start the SIP service after about.
+ * @hide
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ @SystemApi
+ public static final String ACTION_START_SIP =
+ "android.net.sip.action.START_SIP";
/**
* Part of the ACTION_SIP_ADD_PHONE and ACTION_SIP_REMOVE_PHONE intents.
@@ -603,12 +623,13 @@
* (username, password and display name) are crossed out.
* @hide
*/
- public SipProfile[] getListOfProfiles() throws SipException {
+ @SystemApi
+ public @NonNull List<SipProfile> getProfiles() throws SipException {
try {
checkSipServiceConnection();
- return mSipService.getListOfProfiles(mContext.getOpPackageName());
+ return mSipService.getProfiles(mContext.getOpPackageName());
} catch (RemoteException e) {
- return new SipProfile[0];
+ throw new SipException(e.getMessage());
}
}
diff --git a/src/java/android/net/sip/SipProfile.java b/src/java/android/net/sip/SipProfile.java
index 0ef754c..14b0334 100644
--- a/src/java/android/net/sip/SipProfile.java
+++ b/src/java/android/net/sip/SipProfile.java
@@ -16,6 +16,7 @@
package android.net.sip;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -480,7 +481,6 @@
/**
* Sets the calling process's Uid in the sip service.
- * @hide
*/
public void setCallingUid(int uid) {
mCallingUid = uid;
@@ -488,8 +488,11 @@
/**
* Gets the calling process's Uid in the sip settings.
+ *
+ * @return the calling process's Uid in the sip settings.
* @hide
*/
+ @SystemApi
public int getCallingUid() {
return mCallingUid;
}
diff --git a/src/java/com/android/server/sip/SipService.java b/src/java/com/android/server/sip/SipService.java
index d14a8d6..7c6daf8 100644
--- a/src/java/com/android/server/sip/SipService.java
+++ b/src/java/com/android/server/sip/SipService.java
@@ -52,6 +52,7 @@
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
@@ -128,18 +129,19 @@
}
@Override
- public synchronized SipProfile[] getListOfProfiles(String opPackageName) {
- if (!canUseSip(opPackageName, "getListOfProfiles")) {
- return new SipProfile[0];
+ public synchronized List<SipProfile> getProfiles(String opPackageName) throws RemoteException {
+ if (!canUseSip(opPackageName, "getProfiles")) {
+ throw new RemoteException(String.format("Package %s cannot use Sip service",
+ opPackageName));
}
boolean isCallerRadio = isCallerRadio();
- ArrayList<SipProfile> profiles = new ArrayList<SipProfile>();
+ ArrayList<SipProfile> profiles = new ArrayList<>();
for (SipSessionGroupExt group : mSipGroups.values()) {
if (isCallerRadio || isCallerCreator(group)) {
profiles.add(group.getLocalProfile());
}
}
- return profiles.toArray(new SipProfile[profiles.size()]);
+ return profiles;
}
@Override
@@ -350,7 +352,7 @@
private void notifyProfileRemoved(SipProfile localProfile) {
if (DBG) log("notify: profile removed: " + localProfile);
- Intent intent = new Intent(SipManager.ACTION_SIP_REMOVE_PHONE);
+ Intent intent = new Intent(SipManager.ACTION_SIP_REMOVE_PROFILE);
intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString());
mContext.sendBroadcast(intent);
if (mSipGroups.size() == 0) {
diff --git a/src/jni/rtp/Android.bp b/src/jni/rtp/Android.bp
index bdd5071..c938224 100644
--- a/src/jni/rtp/Android.bp
+++ b/src/jni/rtp/Android.bp
@@ -26,13 +26,18 @@
"G711Codec.cpp",
"GsmCodec.cpp",
],
+ header_libs: [
+ "libmedia_headers",
+ ],
+
shared_libs: [
- "libnativehelper",
- "libcutils",
- "libutils",
- "liblog",
"libaudioclient",
+ "libaudiofoundation",
+ "libcutils",
+ "liblog",
+ "libnativehelper",
"libstagefright_amrnb_common",
+ "libutils",
],
static_libs: [
"libgsm",
diff --git a/src/jni/rtp/AudioGroup.cpp b/src/jni/rtp/AudioGroup.cpp
index e01fbca..8bb543c 100644
--- a/src/jni/rtp/AudioGroup.cpp
+++ b/src/jni/rtp/AudioGroup.cpp
@@ -37,10 +37,8 @@
#include <utils/RefBase.h>
#include <utils/threads.h>
#include <utils/SystemClock.h>
-#include <media/AudioSystem.h>
#include <media/AudioRecord.h>
#include <media/AudioTrack.h>
-#include <media/mediarecorder.h>
#include <media/AudioEffect.h>
#include <system/audio_effects/effect_aec.h>
#include <system/audio.h>