Index: util/win/exception_handler_server.cc |
diff --git a/util/win/exception_handler_server.cc b/util/win/exception_handler_server.cc |
index ce5687d74b7ba6f853708f68acf5e4f25390f5b0..6753f494b52b9cfc44c96540f8fab1a91951515d 100644 |
--- a/util/win/exception_handler_server.cc |
+++ b/util/win/exception_handler_server.cc |
@@ -14,6 +14,8 @@ |
#include "util/win/exception_handler_server.h" |
+#include <aclapi.h> |
+#include <sddl.h> |
#include <string.h> |
#include "base/logging.h" |
@@ -30,6 +32,7 @@ |
#include "util/win/get_function.h" |
#include "util/win/handle.h" |
#include "util/win/registration_protocol_win.h" |
+#include "util/win/scoped_local_free.h" |
#include "util/win/xp_compat.h" |
namespace crashpad { |
@@ -45,18 +48,74 @@ const size_t kPipeInstances = 2; |
// If first_instance is true, the named pipe instance will be created with |
// FILE_FLAG_FIRST_PIPE_INSTANCE. This ensures that the the pipe name is not |
// already in use when created. |
+// |
+// The integrity level of the pipe is lowered so that it can be connected to by |
+// processes at any integrity level. |
HANDLE CreateNamedPipeInstance(const std::wstring& pipe_name, |
bool first_instance) { |
- return CreateNamedPipe(pipe_name.c_str(), |
- PIPE_ACCESS_DUPLEX | |
- (first_instance ? FILE_FLAG_FIRST_PIPE_INSTANCE |
- : 0), |
- PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, |
- kPipeInstances, |
- 512, |
- 512, |
- 0, |
- nullptr); |
+ ScopedFileHandle pipe(CreateNamedPipe( |
+ pipe_name.c_str(), |
+ PIPE_ACCESS_DUPLEX | (first_instance ? FILE_FLAG_FIRST_PIPE_INSTANCE : 0), |
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, |
+ kPipeInstances, |
+ 512, |
+ 512, |
+ 0, |
+ nullptr)); |
+ if (!pipe.is_valid()) { |
+ PLOG(ERROR) << "CreateNamedPipe"; |
+ return INVALID_HANDLE_VALUE; |
+ } |
+ |
+ // We only need to set the integrity level on the first instance of the pipe. |
+ if (!first_instance) |
+ return pipe.release(); |
+ |
+ // Lower the integrity of the pipe so that it can be connected to from |
+ // processes at any integrity level. This only applies to Vista and later. |
+ const DWORD version = GetVersion(); |
+ const DWORD major_version = LOBYTE(LOWORD(version)); |
+ const bool is_pre_vista = major_version < 6; |
+ if (is_pre_vista) |
+ return pipe.release(); |
+ |
+ // Mandatory Label, no ACE flags, no ObjectType, integrity level untrusted. |
+ const wchar_t kSddl[] = L"S:(ML;;;;;S-1-16-0)"; |
+ |
+ SECURITY_DESCRIPTOR* sec_desc = nullptr; |
+ |
+ PACL* sacl = nullptr; |
Mark Mentovai
2015/11/05 21:36:15
ACL**?
scottmg
2015/11/05 22:29:59
Oops.
Sadly, now that I try, um, compiling, ACL*
|
+ if (!ConvertStringSecurityDescriptorToSecurityDescriptor( |
+ kSddl, SDDL_REVISION, &sec_desc, nullptr)) { |
Mark Mentovai
2015/11/05 21:36:15
Be explicit about the format of the string you’re
scottmg
2015/11/05 22:29:59
Done.
|
+ PLOG(ERROR) << "ConvertStringSecurityDescriptorToSecurityDescriptor"; |
+ return INVALID_HANDLE_VALUE; |
+ } |
+ |
+ // Take ownership of the allocated SECURITY_DESCRIPTOR. |
+ ScopedLocalFree scoped_sec_desc(sec_desc); |
+ |
+ BOOL sacl_present = FALSE; |
+ BOOL sacl_defaulted = FALSE; |
+ if (!GetSecurityDescriptorSacl( |
+ sec_desc, &sacl_present, &sacl, &sacl_defaulted)) { |
Mark Mentovai
2015/11/05 21:36:15
sacl points to something in sec_desc, so no need t
scottmg
2015/11/05 22:29:59
Yes, that's my understanding from the docs. Maybe
|
+ PLOG(ERROR) << "GetSecurityDescriptorSacl"; |
+ return INVALID_HANDLE_VALUE; |
+ } |
+ |
+ DWORD error = SetSecurityInfo(pipe.get(), |
+ SE_KERNEL_OBJECT, |
+ LABEL_SECURITY_INFORMATION, |
+ nullptr, |
+ nullptr, |
+ nullptr, |
+ sacl); |
+ if (error != ERROR_SUCCESS) { |
+ LOG(ERROR) << "SetSecurityInfo: " |
+ << logging::SystemErrorCodeToString(error); |
+ return INVALID_HANDLE_VALUE; |
+ } |
+ |
+ return pipe.release(); |
} |
decltype(GetNamedPipeClientProcessId)* GetNamedPipeClientProcessIdFunction() { |
@@ -320,7 +379,7 @@ void ExceptionHandlerServer::Run(Delegate* delegate) { |
if (first_pipe_instance_.is_valid()) { |
pipe = first_pipe_instance_.release(); |
} else { |
- pipe = CreateNamedPipeInstance(pipe_name_, false); |
+ pipe = CreateNamedPipeInstance(pipe_name_, i == 0); |
PCHECK(pipe != INVALID_HANDLE_VALUE) << "CreateNamedPipe"; |
} |
Mark Mentovai
2015/11/05 21:39:11
Maybe this works out better from that perspective
scottmg
2015/11/05 22:29:59
Yeah, that seems better. Done.
...
Hmm, it would
|