Skip to content

Commit 2ebc3c8

Browse files
NodefulNodeful
authored andcommitted
implemented more secure hiding showing of the driver
1 parent d86e82b commit 2ebc3c8

12 files changed

Lines changed: 106 additions & 53 deletions

File tree

native/app/Embedded/eqMac.driver/Contents/Info.plist

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<string>com.bitgapp.eqmac.xpc</string>
88
</array>
99
<key>BuildMachineOSBuild</key>
10-
<string>19C57</string>
10+
<string>19F101</string>
1111
<key>CFBundleDevelopmentRegion</key>
1212
<string>en</string>
1313
<key>CFBundleExecutable</key>
@@ -21,15 +21,15 @@
2121
<key>CFBundlePackageType</key>
2222
<string>BNDL</string>
2323
<key>CFBundleShortVersionString</key>
24-
<string>1.1.1</string>
24+
<string>1.2</string>
2525
<key>CFBundleSignature</key>
2626
<string>????</string>
2727
<key>CFBundleSupportedPlatforms</key>
2828
<array>
2929
<string>MacOSX</string>
3030
</array>
3131
<key>CFBundleVersion</key>
32-
<string>1.1.1</string>
32+
<string>1.2</string>
3333
<key>CFPlugInFactories</key>
3434
<dict>
3535
<key>7080ba34-76cc-40b2-b2b3-819d28460e7e</key>
-22.2 KB
Binary file not shown.

native/app/Podfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ target 'eqMac' do
2020
pod 'SwiftLint'
2121
pod 'Sparkle'
2222
pod 'Sentry', '~> 4.1'
23-
pod 'EmitterKit', '~> 5.2'
23+
pod 'EmitterKit', '~> 5.2.2'
2424
pod 'SwiftyJSON', '~> 4.2'
2525
pod 'SwiftyUserDefaults', '4.0'
2626
# pod 'Swifter', '~> 1.4'

native/app/Podfile.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ DEPENDENCIES:
2626
- Alamofire (~> 5.1)
2727
- AMCoreAudio (~> 3.3.1)
2828
- AudioKit (= 4.9.5)
29-
- EmitterKit (~> 5.2)
29+
- EmitterKit (~> 5.2.2)
3030
- KeychainSwift (~> 13.0)
3131
- ReachabilitySwift
3232
- ReSwift
@@ -83,6 +83,6 @@ SPEC CHECKSUMS:
8383
WebViewJavascriptBridge: 7f5bc4d3581e672e8f32bd0f812d54bc69bb8e29
8484
Zip: 8877eede3dda76bcac281225c20e71c25270774c
8585

86-
PODFILE CHECKSUM: 3850edcd366592498848f4adaf654cc1d56c6dc8
86+
PODFILE CHECKSUM: c1a005dd8338743c78b678ca45a079aaeb33bdbc
8787

88-
COCOAPODS: 1.9.1
88+
COCOAPODS: 1.9.3

native/app/Source/Application.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class Application {
7575
// AudioKit Engine fucks with Driver installation, eqMac doesn't use it's engine anyway
7676
try? AudioKit.stop()
7777
try? AudioKit.shutdown()
78+
7879
AKSettings.audioInputEnabled = false
7980
AKSettings.enableRouteChangeHandling = false
8081
AKSettings.notificationsEnabled = false
@@ -195,9 +196,8 @@ class Application {
195196
private static var showPasshtroughDeviceChecks: Int = 0
196197
private static var showPassthroughDeviceCheckQueue: DispatchQueue?
197198
private static func showPassthroughDevice (_ completion: @escaping() -> Void) {
198-
let driverIsHidden = Driver.getDeviceIsHidden(device: .passthrough)
199-
if (driverIsHidden) {
200-
Driver.showDevice(device: .passthrough)
199+
if (Driver.hidden) {
200+
Driver.shown = true
201201
showPasshtroughDeviceChecks = 0
202202
showPassthroughDeviceCheckQueue = DispatchQueue(label: "check-driver-shown", qos: .userInteractive)
203203
showPassthroughDeviceCheckQueue!.asyncAfter(deadline: .now() + .milliseconds(500)) {
@@ -504,7 +504,7 @@ class Application {
504504
stopListeners()
505505
stopEngines()
506506
switchBackToLastKnownDevice()
507-
Driver.hideDevice(device: .passthrough)
507+
Driver.hidden = true
508508
Storage.synchronize()
509509
NSApp.terminate(nil)
510510
}

native/app/Source/Audio/Sources/System/Driver.swift

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ enum DriverDeviceIsActiveProperty: String {
2424
enum CustomProperties: String {
2525
case kAudioDeviceCustomPropertyLatency = "cltc"
2626
case kAudioDeviceCustomPropertySafetyOffset = "csfo"
27+
case kAudioDeviceCustomPropertyShown = "shwn"
2728
}
2829

2930
class Driver {
@@ -108,7 +109,7 @@ class Driver {
108109
]
109110
}
110111

111-
static func getDeviceIsShown (device: DriverDevice) -> Bool {
112+
static func getDeviceIsActive (device: DriverDevice) -> Bool {
112113
if Driver.device != nil { return true }
113114
if let pluginId = self.pluginId {
114115
var address = AudioObjectPropertyAddress(
@@ -127,26 +128,6 @@ class Driver {
127128
return false
128129
}
129130

130-
static func getDeviceIsHidden (device: DriverDevice) -> Bool {
131-
return !getDeviceIsShown(device: device)
132-
}
133-
134-
static func hideDevice (device: DriverDevice) {
135-
return setDeviceIsHidden(device: device, true)
136-
}
137-
138-
static func showDevice (device: DriverDevice) {
139-
return setDeviceIsShown(device: device, true)
140-
}
141-
142-
static func setDeviceIsShown (device: DriverDevice, _ shown: Bool) {
143-
return setDeviceIsHidden(device: device, !shown)
144-
}
145-
146-
static func setDeviceIsHidden (device: DriverDevice, _ hidden: Bool) {
147-
return setDeviceIsActive(device: device, !hidden)
148-
}
149-
150131
private static func setDeviceIsActive (device: DriverDevice, _ active: Bool) {
151132
if let pluginId = self.pluginId {
152133
var mSelector: AudioObjectPropertySelector = getPropertySelectorFromString(getDeviceIsActiveProperty(device).rawValue)
@@ -225,6 +206,43 @@ class Driver {
225206
}
226207
}
227208

209+
static var shown: Bool {
210+
get {
211+
if Driver.device == nil { return false }
212+
var address = AudioObjectPropertyAddress(
213+
mSelector: getPropertySelectorFromString(CustomProperties.kAudioDeviceCustomPropertyShown.rawValue),
214+
mScope: kAudioObjectPropertyScopeGlobal,
215+
mElement: kAudioObjectPropertyElementMaster
216+
)
217+
218+
var size: UInt32 = UInt32(MemoryLayout<CFBoolean>.size)
219+
220+
var shown = kCFBooleanFalse
221+
222+
checkErr(AudioObjectGetPropertyData(Driver.device!.id, &address, 0, nil, &size, &shown))
223+
return CFBooleanGetValue(shown!)
224+
}
225+
set {
226+
if Driver.device == nil { return }
227+
228+
var address = AudioObjectPropertyAddress(
229+
mSelector: getPropertySelectorFromString(CustomProperties.kAudioDeviceCustomPropertyShown.rawValue),
230+
mScope: kAudioObjectPropertyScopeGlobal,
231+
mElement: kAudioObjectPropertyElementMaster
232+
)
233+
234+
let size: UInt32 = UInt32(MemoryLayout<CFBoolean>.size)
235+
var shown: CFBoolean = newValue.cfBooleanValue
236+
237+
checkErr(AudioObjectSetPropertyData(Driver.device!.id, &address, 0, nil, size, &shown))
238+
}
239+
}
240+
241+
static var hidden: Bool {
242+
get { return !shown }
243+
set { shown = !newValue }
244+
}
245+
228246
static var device: AudioDevice? {
229247
return AudioDevice.lookup(by: Constants.PASSTHROUGH_DEVICE_UID)
230248
}

native/driver/Driver.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@
597597
CODE_SIGN_IDENTITY = "Developer ID Application";
598598
CODE_SIGN_STYLE = Manual;
599599
COMBINE_HIDPI_IMAGES = YES;
600-
CURRENT_PROJECT_VERSION = 1.1.1;
600+
CURRENT_PROJECT_VERSION = 1.2;
601601
DEBUG_INFORMATION_FORMAT = dwarf;
602602
DEVELOPMENT_TEAM = JZA6C97KJA;
603603
GCC_C_LANGUAGE_STANDARD = "compiler-default";
@@ -610,7 +610,7 @@
610610
GCC_WARN_UNUSED_VARIABLE = YES;
611611
INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist";
612612
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Audio/Plug-Ins/HAL";
613-
MARKETING_VERSION = 1.1.1;
613+
MARKETING_VERSION = 1.2;
614614
MTL_ENABLE_DEBUG_INFO = YES;
615615
ONLY_ACTIVE_ARCH = YES;
616616
PRODUCT_BUNDLE_IDENTIFIER = com.bitgapp.eqmac.driver;
@@ -637,7 +637,7 @@
637637
CODE_SIGN_IDENTITY = "Developer ID Application";
638638
CODE_SIGN_STYLE = Manual;
639639
COMBINE_HIDPI_IMAGES = YES;
640-
CURRENT_PROJECT_VERSION = 1.1.1;
640+
CURRENT_PROJECT_VERSION = 1.2;
641641
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
642642
DEVELOPMENT_TEAM = JZA6C97KJA;
643643
ENABLE_NS_ASSERTIONS = NO;
@@ -650,7 +650,7 @@
650650
GCC_WARN_UNUSED_VARIABLE = YES;
651651
INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist";
652652
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Audio/Plug-Ins/HAL";
653-
MARKETING_VERSION = 1.1.1;
653+
MARKETING_VERSION = 1.2;
654654
MTL_ENABLE_DEBUG_INFO = NO;
655655
PRODUCT_BUNDLE_IDENTIFIER = com.bitgapp.eqmac.driver;
656656
PRODUCT_NAME = "$(TARGET_NAME)";

native/driver/Scripts/build.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ fi
77
if [ "${CONFIGURATION}" = "Debug" ]; then
88
export SUDO_ASKPASS=~/askpass.sh
99
# Uninstall any new driver leftovers
10-
sudo rm -rf /Library/Audio/Plug-Ins/HAL/eqMac.driver/
10+
sudo -A rm -rf /Library/Audio/Plug-Ins/HAL/eqMac.driver/
1111
# Install the new driver
12-
sudo cp -f -r "$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME" /Library/Audio/Plug-Ins/HAL/
12+
sudo -A cp -f -r "$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME" /Library/Audio/Plug-Ins/HAL/
1313
# Restart CoreAudio
14-
sudo launchctl kickstart -kp system/com.apple.audio.coreaudiod
14+
sudo -A launchctl kickstart -kp system/com.apple.audio.coreaudiod
1515
fi
1616

native/driver/Source/EQM_Device.cpp

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,14 @@ void EQM_Device::StaticInitializer()
6868
kObjectID_Mute_Output_Master);
6969
sInstance->Activate();
7070

71-
if (
72-
!EQM_Utils::process_at_path_running("/Applications/eqMac.app/Contents/MacOS/eqMac")
73-
&& !EQM_Utils::process_at_path_running("/Applications/Xcode.app/Contents/MacOS/Xcode")
74-
) {
75-
// Activate the Driver only if eqMac or Xcode are running from /Application folder
76-
sInstance->Deactivate();
77-
} else {
78-
}
71+
// if (
72+
// !EQM_Utils::process_at_path_running("/Applications/eqMac.app/Contents/MacOS/eqMac")
73+
// && !EQM_Utils::process_at_path_running("/Applications/Xcode.app/Contents/MacOS/Xcode")
74+
// ) {
75+
// // Activate the Driver only if eqMac or Xcode are running from /Application folder
76+
// sInstance->Deactivate();
77+
// } else {
78+
// }
7979

8080
// The instance for system (UI) sounds.
8181
sUISoundsInstance = new EQM_Device(kObjectID_Device_UI_Sounds,
@@ -139,6 +139,7 @@ mMuteControl(inOutputMuteControlID, GetObjectID(), kAudioObjectPropertyScopeOutp
139139
SetSampleRate(kSampleRateDefault);
140140
SetSafetyOffset(kSafetyOffsetDefault);
141141
SetLatency(kLatencyDefault);
142+
SetShown(kShownDefault);
142143
}
143144

144145
EQM_Device::~EQM_Device()
@@ -323,6 +324,7 @@ bool EQM_Device::Device_HasProperty(AudioObjectID inObjectID, pid_t inClientPID,
323324
case kAudioDevicePropertySafetyOffset:
324325
case kAudioDeviceCustomPropertyLatency:
325326
case kAudioDeviceCustomPropertySafetyOffset:
327+
case kAudioDeviceCustomPropertyShown:
326328
theAnswer = true;
327329
break;
328330

@@ -368,6 +370,7 @@ bool EQM_Device::Device_IsPropertySettable(AudioObjectID inObjectID, pid_t inCli
368370
case kAudioDeviceCustomPropertyEnabledOutputControls:
369371
case kAudioDeviceCustomPropertyLatency:
370372
case kAudioDeviceCustomPropertySafetyOffset:
373+
case kAudioDeviceCustomPropertyShown:
371374
theAnswer = true;
372375
break;
373376

@@ -454,7 +457,7 @@ UInt32 EQM_Device::Device_GetPropertyDataSize(AudioObjectID inObjectID, pid_t in
454457
break;
455458

456459
case kAudioObjectPropertyCustomPropertyInfoList:
457-
theAnswer = sizeof(AudioServerPlugInCustomPropertyInfo) * 8;
460+
theAnswer = sizeof(AudioServerPlugInCustomPropertyInfo) * 9;
458461
break;
459462

460463
case kAudioDeviceCustomPropertyDeviceAudibleState:
@@ -488,6 +491,10 @@ UInt32 EQM_Device::Device_GetPropertyDataSize(AudioObjectID inObjectID, pid_t in
488491
theAnswer = sizeof(CFNumberRef);
489492
break;
490493

494+
case kAudioDeviceCustomPropertyShown:
495+
theAnswer = sizeof(CFBooleanRef);
496+
break;
497+
491498
default:
492499
theAnswer = EQM_AbstractDevice::GetPropertyDataSize(inObjectID, inClientPID, inAddress, inQualifierDataSize, inQualifierData);
493500
break;
@@ -675,7 +682,7 @@ void EQM_Device::Device_GetPropertyData(AudioObjectID inObjectID, pid_t inClient
675682
"kAudioDevicePropertyDeviceCanBeDefaultDevice for the device");
676683
// TODO: Add a field for this and set it in EQM_Device::StaticInitializer so we don't
677684
// have to handle a specific instance differently here.
678-
*reinterpret_cast<UInt32*>(outData) = (GetObjectID() == kObjectID_Device_UI_Sounds ? 0 : 1);
685+
*reinterpret_cast<UInt32*>(outData) = mShown ? 1 : 0;
679686
outDataSize = sizeof(UInt32);
680687
break;
681688

@@ -903,9 +910,9 @@ void EQM_Device::Device_GetPropertyData(AudioObjectID inObjectID, pid_t inClient
903910
theNumberItemsToFetch = inDataSize / sizeof(AudioServerPlugInCustomPropertyInfo);
904911

905912
// clamp it to the number of items we have
906-
if(theNumberItemsToFetch > 8)
913+
if(theNumberItemsToFetch > 9)
907914
{
908-
theNumberItemsToFetch = 8;
915+
theNumberItemsToFetch = 9;
909916
}
910917

911918
if(theNumberItemsToFetch > 0)
@@ -958,6 +965,13 @@ void EQM_Device::Device_GetPropertyData(AudioObjectID inObjectID, pid_t inClient
958965
((AudioServerPlugInCustomPropertyInfo*)outData)[6].mQualifierDataType = kAudioServerPlugInCustomPropertyDataTypeNone;
959966
}
960967

968+
if(theNumberItemsToFetch > 8)
969+
{
970+
((AudioServerPlugInCustomPropertyInfo*)outData)[6].mSelector = kAudioDeviceCustomPropertyShown;
971+
((AudioServerPlugInCustomPropertyInfo*)outData)[6].mPropertyDataType = kAudioServerPlugInCustomPropertyDataTypeCFPropertyList;
972+
((AudioServerPlugInCustomPropertyInfo*)outData)[6].mQualifierDataType = kAudioServerPlugInCustomPropertyDataTypeNone;
973+
}
974+
961975
outDataSize = theNumberItemsToFetch * sizeof(AudioServerPlugInCustomPropertyInfo);
962976
break;
963977

@@ -1064,6 +1078,17 @@ void EQM_Device::Device_SetPropertyData(AudioObjectID inObjectID, pid_t inClient
10641078
break;
10651079
}
10661080

1081+
case kAudioDeviceCustomPropertyShown:
1082+
{
1083+
ThrowIf(inDataSize < sizeof(CFBooleanRef),
1084+
CAException(kAudioHardwareBadPropertySizeError),
1085+
"EQM_Device::Device_SetPropertyData: wrong size for the data for kAudioDeviceCustomPropertyShown");
1086+
CFBooleanRef shownRef = *reinterpret_cast<const CFBooleanRef*>(inData);
1087+
bool shown = CFBooleanGetValue(shownRef);
1088+
SetShown(shown);
1089+
break;
1090+
}
1091+
10671092
case kAudioDevicePropertyNominalSampleRate: {
10681093
ThrowIf(inDataSize < sizeof(Float64),
10691094
CAException(kAudioHardwareBadPropertySizeError),
@@ -1846,6 +1871,12 @@ void EQM_Device::SetLatency(UInt32 inLatency)
18461871
mLatency = inLatency;
18471872
}
18481873

1874+
void EQM_Device::SetShown(bool shown)
1875+
{
1876+
CAMutex::Locker theStateLocker(mStateMutex);
1877+
mShown = shown;
1878+
}
1879+
18491880
bool EQM_Device::IsStreamID(AudioObjectID inObjectID) const noexcept
18501881
{
18511882
return (inObjectID == mInputStream.GetObjectID()) || (inObjectID == mOutputStream.GetObjectID());

native/driver/Source/EQM_Device.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ public EQM_AbstractDevice
156156
void SetSampleRate(Float64 inNewSampleRate, bool force = false);
157157
void SetSafetyOffset(UInt32 inNewSafetyOffset);
158158
void SetLatency(UInt32 inNewLatency);
159+
void SetShown(bool shown);
159160

160161
/*! @return True if inObjectID is the ID of one of this device's streams. */
161162
inline bool IsStreamID(AudioObjectID inObjectID) const noexcept;
@@ -214,6 +215,7 @@ public EQM_AbstractDevice
214215
const Float64 kSampleRateDefault = 44100.0;
215216
const UInt32 kSafetyOffsetDefault = 0;
216217
const UInt32 kLatencyDefault = 0;
218+
const bool kShownDefault = false;
217219
// Before we can change sample rate, the host has to stop the device. The new sample rate is
218220
// stored here while it does.
219221
Float64 mPendingSampleRate;
@@ -228,6 +230,7 @@ public EQM_AbstractDevice
228230
Float64 mLoopbackSampleRate;
229231
UInt32 mSafetyOffset;
230232
UInt32 mLatency;
233+
bool mShown;
231234
Float32 mLoopbackRingBuffer[kLoopbackRingBufferFrameSize * 2];
232235
// TODO: a comment explaining why we need a clock for loopback-only mode
233236
struct {

0 commit comments

Comments
 (0)