diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 4ab9c286bfa6..94e8e6405e5f 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -514,9 +514,12 @@ B2A58722143119810092BFBA /* SBWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = B2A58721143119810092BFBA /* SBWatchpoint.h */; settings = {ATTRIBUTES = (Public, ); }; }; B2A58724143119D50092BFBA /* SBWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2A58723143119D50092BFBA /* SBWatchpoint.cpp */; }; ED236E0814F84F6800153F6F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDB919B414F6F10D008FF64B /* Security.framework */; }; + ED88244E15114A9200BC98B9 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDB919B414F6F10D008FF64B /* Security.framework */; }; + ED88245015114CA200BC98B9 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED88244F15114CA200BC98B9 /* main.mm */; }; + ED88245115114CA200BC98B9 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED88244F15114CA200BC98B9 /* main.mm */; }; + ED88245315114CFC00BC98B9 /* LauncherRootXPCService.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED88245215114CFC00BC98B9 /* LauncherRootXPCService.mm */; }; EDB919B714F6F22D008FF64B /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDB919B414F6F10D008FF64B /* Security.framework */; }; EDC6D4AA14E5C49E001B75F8 /* LauncherXPCService.mm in Sources */ = {isa = PBXBuildFile; fileRef = EDC6D49414E5C15C001B75F8 /* LauncherXPCService.mm */; }; - EDE274E414EDCE1F005B0F75 /* LauncherXPCService.mm in Sources */ = {isa = PBXBuildFile; fileRef = EDC6D49414E5C15C001B75F8 /* LauncherXPCService.mm */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -1534,6 +1537,8 @@ B2A58723143119D50092BFBA /* SBWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBWatchpoint.cpp; path = source/API/SBWatchpoint.cpp; sourceTree = ""; }; B2A5872514313B480092BFBA /* SBWatchpoint.i */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; path = SBWatchpoint.i; sourceTree = ""; }; B2D3033612EFA5C500F84EB3 /* InstructionUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InstructionUtils.h; path = Utility/InstructionUtils.h; sourceTree = ""; }; + ED88244F15114CA200BC98B9 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; + ED88245215114CFC00BC98B9 /* LauncherRootXPCService.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LauncherRootXPCService.mm; sourceTree = ""; }; EDB919B214F6EC85008FF64B /* LauncherXPCService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LauncherXPCService.h; sourceTree = ""; }; EDB919B414F6F10D008FF64B /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = ""; }; EDC6D49214E5C15C001B75F8 /* LauncherXPCService-Info.plist */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; path = "LauncherXPCService-Info.plist"; sourceTree = ""; }; @@ -1602,6 +1607,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + ED88244E15114A9200BC98B9 /* Security.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3101,8 +3107,10 @@ EDC6D49214E5C15C001B75F8 /* LauncherXPCService-Info.plist */, EDE274E114EDCE0D005B0F75 /* LauncherRootXPCService-Info.plist */, EDC6D49314E5C15C001B75F8 /* LauncherXPCService.entitlements */, + ED88244F15114CA200BC98B9 /* main.mm */, EDB919B214F6EC85008FF64B /* LauncherXPCService.h */, EDC6D49414E5C15C001B75F8 /* LauncherXPCService.mm */, + ED88245215114CFC00BC98B9 /* LauncherRootXPCService.mm */, ); name = launcherXPCService; path = source/Host/macosx/launcherXPCService; @@ -3920,6 +3928,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + ED88245015114CA200BC98B9 /* main.mm in Sources */, EDC6D4AA14E5C49E001B75F8 /* LauncherXPCService.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -3928,7 +3937,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - EDE274E414EDCE1F005B0F75 /* LauncherXPCService.mm in Sources */, + ED88245115114CA200BC98B9 /* main.mm in Sources */, + ED88245315114CFC00BC98B9 /* LauncherRootXPCService.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/lldb/source/Host/macosx/Host.mm b/lldb/source/Host/macosx/Host.mm index 443a28344995..6514489b43f7 100644 --- a/lldb/source/Host/macosx/Host.mm +++ b/lldb/source/Host/macosx/Host.mm @@ -1287,7 +1287,6 @@ getXPCAuthorization (ProcessLaunchInfo &launch_info) { CFDictionaryRef dict = NULL; OSStatus osStatus; - const char *rightName = "com.apple.lldb.LaunchUsingXPC"; AuthorizationFlags authorizationFlags = kAuthorizationFlagDefaults; if (!authorizationRef) @@ -1296,17 +1295,15 @@ getXPCAuthorization (ProcessLaunchInfo &launch_info) if (osStatus != errAuthorizationSuccess) { error.SetError(1, eErrorTypeGeneric); + error.SetErrorString("Can't create authorizationRef."); if (log) { - error.PutToLog(log.get(), "Can't create authorizationRef."); - } - else { - error.SetErrorString("Can't create authorizationRef."); + error.PutToLog(log.get(), "%s", error.AsCString()); } return error; } - - osStatus = AuthorizationRightGet(rightName, &dict); + + osStatus = AuthorizationRightGet(LaunchUsingXPCRightName, &dict); if (dict) CFRelease(dict); if (osStatus != errAuthorizationSuccess) { @@ -1317,16 +1314,16 @@ getXPCAuthorization (ProcessLaunchInfo &launch_info) CFTypeRef values[] = { prompt }; CFDictionaryRef promptDict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFStringRef keys1[] = { CFSTR("class"), CFSTR("group"), CFSTR("comment"), CFSTR("default-prompt"), CFSTR("shared") }; - CFTypeRef values1[] = { CFSTR("user"), CFSTR("admin"), CFSTR("com.apple.lldb.LaunchUsingXPC"), promptDict, kCFBooleanFalse }; + CFStringRef keys1[] = { CFSTR("class"), CFSTR("group"), CFSTR("comment"), CFSTR("default-prompt"), CFSTR("shared") }; + CFTypeRef values1[] = { CFSTR("user"), CFSTR("admin"), CFSTR(LaunchUsingXPCRightName), promptDict, kCFBooleanFalse }; dict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys1, (const void **)values1, 5, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - osStatus = AuthorizationRightSet(authorizationRef, rightName, dict, NULL, NULL, NULL); + osStatus = AuthorizationRightSet(authorizationRef, LaunchUsingXPCRightName, dict, NULL, NULL, NULL); CFRelease(promptDict); CFRelease(dict); } } - AuthorizationItem item1 = { rightName, 0, NULL, 0 }; + AuthorizationItem item1 = { LaunchUsingXPCRightName, 0, NULL, 0 }; AuthorizationItem items[] = {item1}; AuthorizationRights requestedRights = {1, items }; authorizationFlags = kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights; @@ -1337,13 +1334,10 @@ getXPCAuthorization (ProcessLaunchInfo &launch_info) // logged in in the current audit session, we will need the trick in gdb where // we ask the user to type in the root passwd in the terminal. error.SetError(2, eErrorTypeGeneric); + error.SetErrorStringWithFormat("Launching as root needs root authorization."); if (log) { - error.PutToLog(log.get(), "Launching as root needs root authorization."); - } - else - { - error.SetErrorStringWithFormat("Launching as root needs root authorization."); + error.PutToLog(log.get(), "%s", error.AsCString()); } } } @@ -1364,24 +1358,37 @@ LaunchProcessXPC (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t uid_t requested_uid = launch_info.GetUserID(); const char *xpc_service = nil; + bool send_auth = false; + AuthorizationExternalForm extForm; if ((requested_uid == UINT32_MAX) || (requested_uid == Host::GetEffectiveUserID())) { xpc_service = "com.apple.lldb.launcherXPCService"; } else if (requested_uid == 0) { + if (AuthorizationMakeExternalForm(authorizationRef, &extForm) == errAuthorizationSuccess) + { + send_auth = true; + } + else + { + error.SetError(2, eErrorTypeGeneric); + error.SetErrorStringWithFormat("Launching root via XPC needs to externalize authorization reference."); + if (log) + { + error.PutToLog(log.get(), "%s", error.AsCString()); + } + return error; + } xpc_service = "com.apple.lldb.launcherRootXPCService"; } else { - error.SetError(2, eErrorTypeGeneric); + error.SetError(3, eErrorTypeGeneric); + error.SetErrorStringWithFormat("Launching via XPC is only currently available for either the login user or root."); if (log) { - error.PutToLog(log.get(), "Launching via XPC is only currently available for either the login user or root."); - } - else - { - error.SetErrorStringWithFormat("Launching via XPC is only currently available for either the login user or root."); + error.PutToLog(log.get(), "%s", error.AsCString()); } return error; } @@ -1415,6 +1422,11 @@ LaunchProcessXPC (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t xpc_connection_resume (conn); xpc_object_t message = xpc_dictionary_create (nil, nil, 0); + if (send_auth) + { + xpc_dictionary_set_data(message, LauncherXPCServiceAuthKey, extForm.bytes, sizeof(AuthorizationExternalForm)); + } + PackageXPCArguments(message, LauncherXPCServiceArgPrefxKey, launch_info.GetArguments()); PackageXPCArguments(message, LauncherXPCServiceEnvPrefxKey, launch_info.GetEnvironmentEntries()); @@ -1431,12 +1443,10 @@ LaunchProcessXPC (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t int errorCode = xpc_dictionary_get_int64(reply, LauncherXPCServiceCodeTypeKey); error.SetError(errorCode, eErrorTypeGeneric); + error.SetErrorStringWithFormat("Problems with launching via XPC. Error type : %i, code : %i", errorType, errorCode); if (log) { - error.PutToLog(log.get(), "Problems with launching via XPC. Error type : %i, code : %i", errorType, errorCode); - } - else { - error.SetErrorStringWithFormat("Problems with launching via XPC. Error type : %i, code : %i", errorType, errorCode); + error.PutToLog(log.get(), "%s", error.AsCString()); } } diff --git a/lldb/source/Host/macosx/launcherXPCService/LauncherRootXPCService.mm b/lldb/source/Host/macosx/launcherXPCService/LauncherRootXPCService.mm new file mode 100644 index 000000000000..192c1bb0fa6d --- /dev/null +++ b/lldb/source/Host/macosx/launcherXPCService/LauncherRootXPCService.mm @@ -0,0 +1,42 @@ +#include + +#if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 +#define BUILDING_ON_SNOW_LEOPARD 1 +#endif + +#if !BUILDING_ON_SNOW_LEOPARD +#define __XPC_PRIVATE_H__ +#include +#include +#include "LauncherXPCService.h" + +// Returns 0 if successful. +int _validate_authorization(xpc_object_t message) +{ + size_t data_length = 0ul; + const char *data_bytes = (const char *)xpc_dictionary_get_data(message, LauncherXPCServiceAuthKey, &data_length); + + AuthorizationExternalForm extAuth; + if (data_length < sizeof(extAuth.bytes)) + return 1; + + memcpy(extAuth.bytes, data_bytes, sizeof(extAuth.bytes)); + AuthorizationRef authRef; + if (AuthorizationCreateFromExternalForm(&extAuth, &authRef) != errAuthorizationSuccess) + return 2; + + AuthorizationItem item1 = { LaunchUsingXPCRightName, 0, NULL, 0 }; + AuthorizationItem items[] = {item1}; + AuthorizationRights requestedRights = {1, items }; + AuthorizationRights *outAuthorizedRights = NULL; + OSStatus status = AuthorizationCopyRights(authRef, &requestedRights, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &outAuthorizedRights); + + // Given a set of rights, return the subset that is currently authorized by the AuthorizationRef given; count(subset) > 0 -> success. + bool auth_success = (status == errAuthorizationSuccess && outAuthorizedRights && outAuthorizedRights->count > 0) ? true : false; + + if (outAuthorizedRights) AuthorizationFreeItemSet(outAuthorizedRights); + + return auth_success ? 0 : 3; +} + +#endif diff --git a/lldb/source/Host/macosx/launcherXPCService/LauncherXPCService.h b/lldb/source/Host/macosx/launcherXPCService/LauncherXPCService.h index 071cea79e59e..53172513dc18 100644 --- a/lldb/source/Host/macosx/launcherXPCService/LauncherXPCService.h +++ b/lldb/source/Host/macosx/launcherXPCService/LauncherXPCService.h @@ -1,7 +1,10 @@ #ifndef LLDB_LauncherXPCService_h #define LLDB_LauncherXPCService_h +#define LaunchUsingXPCRightName "com.apple.lldb.LaunchUsingXPC" + // These XPC messaging keys are used for communication between Host.mm and the XPC service. +#define LauncherXPCServiceAuthKey "auth-key" #define LauncherXPCServiceArgPrefxKey "arg" #define LauncherXPCServiceEnvPrefxKey "env" #define LauncherXPCServiceCPUTypeKey "cpuType" diff --git a/lldb/source/Host/macosx/launcherXPCService/LauncherXPCService.mm b/lldb/source/Host/macosx/launcherXPCService/LauncherXPCService.mm index a5c0c6a2093a..5ec3be0a1c6f 100644 --- a/lldb/source/Host/macosx/launcherXPCService/LauncherXPCService.mm +++ b/lldb/source/Host/macosx/launcherXPCService/LauncherXPCService.mm @@ -1,9 +1,3 @@ -// -// LauncherXPCService.m -// LauncherXPCService -// -// Copyright (c) 2012 Apple Inc. All rights reserved. -// #include #if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 @@ -13,174 +7,11 @@ #if !BUILDING_ON_SNOW_LEOPARD #define __XPC_PRIVATE_H__ #include -#include -#include -#include -#include "LauncherXPCService.h" -// Returns 0 if successful. -int _setup_posixspawn_attributes_file_actions(xpc_object_t message, posix_spawnattr_t *attr, posix_spawn_file_actions_t *file_actions) +// Returns 0 if successful. This is launching as self. No need for further authorization. +int _validate_authorization(xpc_object_t message) { - *attr = 0; - - int errorCode = posix_spawnattr_init(attr); - if (errorCode) - return errorCode; - - cpu_type_t cpuType = xpc_dictionary_get_int64(message, LauncherXPCServiceCPUTypeKey); - if (cpuType == -2) { - cpuType= CPU_TYPE_ANY; - } - size_t realCount; - errorCode = posix_spawnattr_setbinpref_np(attr, 1, &cpuType, &realCount); - if (errorCode) - return errorCode; - - sigset_t no_signals; - sigset_t all_signals; - sigemptyset (&no_signals); - sigfillset (&all_signals); - posix_spawnattr_setsigmask(attr, &no_signals); - posix_spawnattr_setsigdefault(attr, &all_signals); - - short flags = xpc_dictionary_get_int64(message, LauncherXPCServicePosixspawnFlagsKey); - errorCode = posix_spawnattr_setflags(attr, flags); - if (errorCode) - return errorCode; - - // Setup any file actions. Here we are emulating what debugserver would do normally in Host.mm since the XPC service meant only for debugserver. - errorCode = posix_spawn_file_actions_init(file_actions); - if (errorCode) - return errorCode; - errorCode = posix_spawn_file_actions_addclose(file_actions, STDIN_FILENO); - if (errorCode) - return errorCode; - errorCode = posix_spawn_file_actions_addclose(file_actions, STDOUT_FILENO); - if (errorCode) - return errorCode; - errorCode = posix_spawn_file_actions_addclose(file_actions, STDERR_FILENO); - - return errorCode; -} - -bool extract_args(xpc_object_t message, const char *prefix, const char ***argsOut) -{ - char buf[50]; // long enough for 'argXXX' - memset(buf, 0, 50); - sprintf(buf, "%sCount", prefix); - int argsCount = xpc_dictionary_get_int64(message, buf); - if (argsCount == 0) { - return true; - } - - const char **argsp = NULL; - argsp = (const char **)malloc((argsCount+1) * sizeof(argsp[0])); - if (argsp == NULL) { - return false; - } - - for (int i=0; i + +#if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 +#define BUILDING_ON_SNOW_LEOPARD 1 +#endif + +#if !BUILDING_ON_SNOW_LEOPARD +#define __XPC_PRIVATE_H__ +#include +#include +#include +#include +#include "LauncherXPCService.h" + +// Declaration. Returns 0 if successful. +int _validate_authorization(xpc_object_t message); + +// Returns 0 if successful. +int _setup_posixspawn_attributes_file_actions(xpc_object_t message, posix_spawnattr_t *attr, posix_spawn_file_actions_t *file_actions) +{ + *attr = 0; + + int errorCode = posix_spawnattr_init(attr); + if (errorCode) + return errorCode; + + cpu_type_t cpuType = xpc_dictionary_get_int64(message, LauncherXPCServiceCPUTypeKey); + if (cpuType == -2) { + cpuType= CPU_TYPE_ANY; + } + size_t realCount; + errorCode = posix_spawnattr_setbinpref_np(attr, 1, &cpuType, &realCount); + if (errorCode) + return errorCode; + + sigset_t no_signals; + sigset_t all_signals; + sigemptyset (&no_signals); + sigfillset (&all_signals); + posix_spawnattr_setsigmask(attr, &no_signals); + posix_spawnattr_setsigdefault(attr, &all_signals); + + short flags = xpc_dictionary_get_int64(message, LauncherXPCServicePosixspawnFlagsKey); + errorCode = posix_spawnattr_setflags(attr, flags); + if (errorCode) + return errorCode; + + // Setup any file actions. Here we are emulating what debugserver would do normally in Host.mm since the XPC service meant only for debugserver. + errorCode = posix_spawn_file_actions_init(file_actions); + if (errorCode) + return errorCode; + errorCode = posix_spawn_file_actions_addclose(file_actions, STDIN_FILENO); + if (errorCode) + return errorCode; + errorCode = posix_spawn_file_actions_addclose(file_actions, STDOUT_FILENO); + if (errorCode) + return errorCode; + errorCode = posix_spawn_file_actions_addclose(file_actions, STDERR_FILENO); + + return errorCode; +} + +bool extract_args(xpc_object_t message, const char *prefix, const char ***argsOut) +{ + char buf[50]; // long enough for 'argXXX' + memset(buf, 0, 50); + sprintf(buf, "%sCount", prefix); + int argsCount = xpc_dictionary_get_int64(message, buf); + if (argsCount == 0) { + return true; + } + + const char **argsp = NULL; + argsp = (const char **)malloc((argsCount+1) * sizeof(argsp[0])); + if (argsp == NULL) { + return false; + } + + for (int i=0; i