Bug 1732343 - Part 4: Use attached handles for Windows FileDescriptor serialization, r=handyman

Differential Revision: https://phabricator.services.mozilla.com/D126566
This commit is contained in:
Nika Layzell 2021-11-04 19:20:18 +00:00
parent 4bd83c851e
commit aa3b31b0e4
2 changed files with 9 additions and 74 deletions

View File

@ -35,14 +35,6 @@ FileDescriptor::FileDescriptor(PlatformHandleType aHandle)
FileDescriptor::FileDescriptor(UniquePlatformHandle&& aHandle)
: mHandle(std::move(aHandle)) {}
FileDescriptor::FileDescriptor(const IPDLPrivate&, PickleType aPickle) {
#ifdef XP_WIN
mHandle.reset(aPickle);
#else
mHandle = std::move(aPickle);
#endif
}
FileDescriptor::~FileDescriptor() = default;
FileDescriptor& FileDescriptor::operator=(const FileDescriptor& aOther) {
@ -59,33 +51,6 @@ FileDescriptor& FileDescriptor::operator=(FileDescriptor&& aOther) {
return *this;
}
FileDescriptor::PickleType FileDescriptor::ShareTo(
const FileDescriptor::IPDLPrivate&,
FileDescriptor::ProcessId aTargetPid) const {
PlatformHandleType newHandle;
#ifdef XP_WIN
if (IsValid()) {
if (mozilla::ipc::DuplicateHandle(mHandle.get(), aTargetPid, &newHandle, 0,
DUPLICATE_SAME_ACCESS)) {
return newHandle;
}
NS_WARNING("Failed to duplicate file handle for other process!");
}
return INVALID_HANDLE_VALUE;
#else // XP_WIN
if (IsValid()) {
newHandle = dup(mHandle.get());
if (newHandle >= 0) {
return UniquePlatformHandle(newHandle);
}
NS_WARNING("Failed to duplicate file handle for other process!");
}
return nullptr;
#endif
MOZ_CRASH("Must not get here!");
}
bool FileDescriptor::IsValid() const { return mHandle != nullptr; }
FileDescriptor::UniquePlatformHandle FileDescriptor::ClonePlatformHandle()
@ -130,30 +95,19 @@ FileDescriptor::UniquePlatformHandle FileDescriptor::Clone(
void IPDLParamTraits<FileDescriptor>::Write(IPC::Message* aMsg,
IProtocol* aActor,
const FileDescriptor& aParam) {
#ifdef XP_WIN
FileDescriptor::PickleType pfd =
aParam.ShareTo(FileDescriptor::IPDLPrivate(), aActor->OtherPid());
#else
// The pid returned by OtherPID() is only required for Windows to
// send file descriptors. For the use case of the fork server,
// aActor is always null. Since it is only for the special case of
// Windows, here we skip it for other platforms.
FileDescriptor::PickleType pfd =
aParam.ShareTo(FileDescriptor::IPDLPrivate(), 0);
#endif
WriteIPDLParam(aMsg, aActor, std::move(pfd));
WriteIPDLParam(aMsg, aActor, aParam.ClonePlatformHandle());
}
bool IPDLParamTraits<FileDescriptor>::Read(const IPC::Message* aMsg,
PickleIterator* aIter,
IProtocol* aActor,
FileDescriptor* aResult) {
FileDescriptor::PickleType pfd;
if (!ReadIPDLParam(aMsg, aIter, aActor, &pfd)) {
UniqueFileHandle handle;
if (!ReadIPDLParam(aMsg, aIter, aActor, &handle)) {
return false;
}
*aResult = FileDescriptor(FileDescriptor::IPDLPrivate(), std::move(pfd));
*aResult = FileDescriptor(std::move(handle));
if (!aResult->IsValid()) {
printf_stderr("IPDL protocol Error: Received an invalid file descriptor\n");
}

View File

@ -15,17 +15,13 @@ namespace mozilla {
namespace ipc {
// This class is used by IPDL to share file descriptors across processes. When
// sending a FileDescriptor IPDL will first duplicate a platform-specific file
// handle type ('PlatformHandleType') into a handle that is valid in the other
// process. Then IPDL will convert the duplicated handle into a type suitable
// for pickling ('PickleType') and then send that through the IPC pipe. In the
// receiving process the pickled data is converted into a platform-specific file
// handle and then returned to the receiver.
// sending a FileDescriptor, IPDL will transfer a duplicate of the handle into
// the remote process.
//
// To use this class add 'FileDescriptor' as an argument in the IPDL protocol
// and then pass a file descriptor from C++ to the Call/Send method. The
// Answer/Recv method will receive a FileDescriptor& on which PlatformHandle()
// can be called to return the platform file handle.
// and then pass a file descriptor from C++ to the Send method. The Recv method
// will receive a FileDescriptor& on which PlatformHandle() can be called to
// return the platform file handle.
class FileDescriptor {
public:
typedef base::ProcessId ProcessId;
@ -33,12 +29,6 @@ class FileDescriptor {
using UniquePlatformHandle = mozilla::UniqueFileHandle;
using PlatformHandleType = UniquePlatformHandle::ElementType;
#ifdef XP_WIN
typedef PlatformHandleType PickleType;
#else
typedef UniquePlatformHandle PickleType;
#endif
// This should only ever be created by IPDL.
struct IPDLPrivate {};
@ -56,21 +46,12 @@ class FileDescriptor {
explicit FileDescriptor(UniquePlatformHandle&& aHandle);
// This constructor WILL NOT duplicate the handle.
// FileDescriptor takes the ownership from IPC message.
FileDescriptor(const IPDLPrivate&, PickleType aPickle);
~FileDescriptor();
FileDescriptor& operator=(const FileDescriptor& aOther);
FileDescriptor& operator=(FileDescriptor&& aOther);
// Performs platform-specific actions to duplicate mHandle in the other
// process (e.g. dup() on POSIX, DuplicateHandle() on Windows). Returns a
// pickled value that can be passed to the other process via IPC.
PickleType ShareTo(const IPDLPrivate&, ProcessId aTargetPid) const;
// Tests mHandle against a well-known invalid platform-specific file handle
// (e.g. -1 on POSIX, INVALID_HANDLE_VALUE on Windows).
bool IsValid() const;