Post

Replies

Boosts

Views

Activity

MacOS 15.3: Unable to get IOUSBDeviceInterface object when IOKit notification is received for USB Device connection for USB Device monitoring.
Our product is using IOKit framework for monitoring USB device activities. We have used IOKit framework for getting the notification for USB plugin and un-plugins. With the macOS version 15.3 we are started seeing issue with it. When the notification is received during USB plugin/connection, we are unable to get IOUSBDeviceInterface object which will be used for further processing. Currently we are seeing the below error every time, while trying to create the IO plugin interface using IOCreatePlugInInterfaceForService API:
 create plugin Error: (0xe00002be): (iokit/common) resource shortage Due to this the we are unable to proceed with the flow further and the entire flow is broken. These logics work fine in macOS version 15.2 and lower versions without any issues. logic used: USBDevice::initInterfaceInterfaceByIOService(io_service_t entry) { IOCFPlugInInterface** plugInInterface = NULL; IOUSBInterfaceInterface** interface = NULL; SInt32 score = 0; mach_error_code err = IOCreatePlugInInterfaceForService(entry, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); if ((err != 0) || (!plugInInterface)) { os_log_error(OS_LOG_DEFAULT, "Unable to create plugin \n"); return nullptr; } auto result = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID*)&interface); (*plugInInterface)->Release(plugInInterface); if (result || !interface) { os_log_error(OS_LOG_DEFAULT, "Unable to create interface \n"); return nullptr; } return interface; }
0
1
250
3w
Issue in Sequoia OS(15.2) with USB FAT32 remounting, when monitored with ES_EVENT_TYPE_AUTH_MOUNT event
Description: The issue with USB FAT32 is seen in Sequoia OS. Most of the times issue is seen when FAT32 USB is mounted along with other USBs like XFAT. The scenario is where USB mounting is monitored using Endpoint Security framework event ES_EVENT_TYPE_AUTH_MOUNT and when event is received, it will be denied for mounting is it is in read-write mode. And, program tries to mount the USB in read-only mode. Steps to Reproduce: Use the xcode program (which will be sent) for testing. Run the executable on macos having Sequoia OS. start executing the binary after successful compilation. Make sure it's running. Take 2 USB drives one with FAT32 and another one with XFAT. Try to mount the USBs and watch the logs on the terminal where the binary is running. We can see, the USB mounting in read-only mode fails for FAT32 where as it passes for other USB. The issue with mounting is not seen always, but, seen when more than 1 USB mounted and FAT32 we see most of the times. Once the mounting fails for the USB, we keep seeing this issue if we try to mount the USB using command line or any other way, until we remove the device and reconnect it. #include <EndpointSecurity/EndpointSecurity.h> #include <bsm/libbsm.h> #include <iostream> #include <os/log.h> #define MAX_THREADS_LIMIT 64 es_client_t *g_client = nullptr; dispatch_queue_t dispatchQueue; static std::atomic<int> m_numThreads; bool mountVolumeCommandLine(const std::string diskPath, const bool &isReadOnly) { std::string command(""); const std::string quote = "\""; if(isReadOnly) { command = "diskutil mount readOnly "+ quote + diskPath + quote; } else { command = "diskutil mount "+ quote + diskPath + quote; } FILE *mount = popen(command.c_str(), "r"); if (mount == NULL) { os_log_error(OS_LOG_DEFAULT, "Failure!! mounting of %{public}s failed using command = %{public}s", diskPath.c_str(),command.c_str()); return false; } else { std::string result = ""; os_log(OS_LOG_DEFAULT, "successful!! executed mount for %{public}s using command = %{public}s ",diskPath.c_str(), command.c_str()); } pclose(mount); return true; } void handleEvents(const es_message_t *msg) { m_numThreads++; switch(msg->event_type) { case ES_EVENT_TYPE_AUTH_MOUNT: { std::string diskPath = msg->event.mount.statfs->f_mntfromname; std::string volumePath = msg->event.mount.statfs->f_mntonname; mountVolumeCommandLine(diskPath, true); break; } default: break; } m_numThreads--; } bool sendAuthResponse(const es_message_t *msg, const es_auth_result_t &result) { es_respond_result_t res = es_respond_auth_result(g_client, msg, result, false); if (res != ES_RESPOND_RESULT_SUCCESS) { os_log_error(OS_LOG_DEFAULT, "SampleEndpointSecurity Failed to respond to auth event error"); return false; } return true; } int createESClient(const es_handler_block_t &handler) { dispatchQueue = dispatch_queue_create("com.test.es_notify", DISPATCH_QUEUE_SERIAL); dispatch_set_target_queue(dispatchQueue, dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)); while(1) { es_new_client_result_t res = es_new_client(&g_client, handler); if(ES_NEW_CLIENT_RESULT_SUCCESS != res) { g_client = nullptr; std::cout<<"client creation failed"<<std::endl; if(ES_NEW_CLIENT_RESULT_ERR_NOT_ENTITLED == res) { os_log_error(OS_LOG_DEFAULT, "SampleEndpointSecurity ESClient creation Error: Program requires proper entitlement"); sleep(300); } else if(ES_NEW_CLIENT_RESULT_ERR_NOT_PERMITTED == res) { os_log_error(OS_LOG_DEFAULT,"SampleEndpointSecurity ESClient creation Error: Program needs proper permission for using ESClient"); } else { os_log_error(OS_LOG_DEFAULT,"SampleEndpointSecurity ESClient creation Error: %d", res); } return 1; } else { break; } } es_clear_cache_result_t resCache = es_clear_cache(g_client); if(ES_CLEAR_CACHE_RESULT_SUCCESS != resCache) { os_log_error(OS_LOG_DEFAULT, "\n SampleEndpointSecurity es_clear_cache: %d\n", resCache); return 1; } return 0; } int main() { es_handler_block_t handler = ^void(es_client_t * _Nonnull, const es_message_t * _Nonnull msg){ bool processEvent = false; if(!msg->process->is_es_client) { switch(msg->event_type) { case ES_EVENT_TYPE_AUTH_MOUNT: { std::string diskPath = msg->event.mount.statfs->f_mntfromname; std::string volumePath = msg->event.mount.statfs->f_mntonname; long flags = msg->event.mount.statfs->f_flags; if(flags & MNT_RDONLY) { os_log(OS_LOG_DEFAULT, "ALLOW readOnly mount event for volumePath= %{public}s and diskPath=%{public}s", volumePath.c_str(), diskPath.c_str()); sendAuthResponse(msg, ES_AUTH_RESULT_ALLOW); } else { os_log(OS_LOG_DEFAULT, "DENY the mount event for volumePath=%{public}s and diskPath=%{public}s", volumePath.c_str(), diskPath.c_str()); sendAuthResponse(msg, ES_AUTH_RESULT_DENY); processEvent = true; } break; } default: { os_log(OS_LOG_DEFAULT,"SampleEndpointSecurity default case event_type: (%d)", msg->event_type); break; // Not interested } } if(processEvent && m_numThreads.load() < MAX_THREADS_LIMIT) { es_retain_message(msg); dispatch_async(dispatchQueue, ^{ handleEvents(msg); es_release_message(msg); }); } } }; if(createESClient(handler) == 1) { return 1; } es_event_type_t events[] = {ES_EVENT_TYPE_AUTH_MOUNT }; es_return_t subscribed = es_subscribe(g_client, events, // Count of es_event_type_t entries stored in events[] sizeof(events) / sizeof(es_event_type_t) ); if(ES_RETURN_ERROR == subscribed) { os_log_error(OS_LOG_DEFAULT, "SampleEndpointSecurity es_subscribe: ES_RETURN_ERROR\n"); return 1; } dispatch_main(); return 0; }
1
1
205
Jan ’25
[MacOS] Is there a way to get or implement Virtual USB drive?
I would like to use(or emulate) a virtual USB drive which behaves as a physical USB drive. Using this, I could try to mount/unmount the Virtual USB and copy(or modify) required files and folders into that(similar to physical USB drive activity). Is there a way to get or implement this in MacOS(BigSur) system? Could anyone please confirm.  If yes, how this can be achieved.
1
2
2.9k
Mar ’22