blob: d9185b43a773b67d24173248be0e8d8dec2c5015 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SANDBOX_LINUX_SYSCALL_BROKER_BROKER_SIMPLE_MESSAGE_H_
#define SANDBOX_LINUX_SYSCALL_BROKER_BROKER_SIMPLE_MESSAGE_H_
#include <stdint.h>
#include <sys/types.h>
#include "base/files/scoped_file.h"
#include "sandbox/sandbox_export.h"
namespace sandbox {
namespace syscall_broker {
// This class is meant to provide a very simple messaging mechanism that is
// signal-safe for the broker to utilize. This addresses many of the issues
// outlined in https://crbug.com/255063. In short, the use of the standard
// base::UnixDomainSockets is not possible because it uses base::Pickle and
// std::vector, which are not signal-safe.
//
// In implementation, much of the code for sending and receiving is taken from
// base::UnixDomainSockets and re-used below. Thus, ultimately, it might be
// worthwhile making a first-class base-supported signal-safe set of mechanisms
// that reduces the code duplication.
class SANDBOX_EXPORT BrokerSimpleMessage {
public:
BrokerSimpleMessage();
// Signal-safe
ssize_t SendRecvMsgWithFlags(int fd,
int recvmsg_flags,
int* send_fd,
BrokerSimpleMessage* reply);
// Use sendmsg to write the given msg and the file descriptor |send_fd|.
// Returns true if successful. Signal-safe.
bool SendMsg(int fd, int send_fd);
// Similar to RecvMsg, but allows to specify |flags| for recvmsg(2).
// Guaranteed to return either 1 or 0 fds. Signal-safe.
ssize_t RecvMsgWithFlags(int fd, int flags, base::ScopedFD* return_fd);
// Adds a NUL-terminated C-style string to the message as a raw buffer.
// Returns true if the internal message buffer has room for the data, and the
// data is successfully appended.
bool AddStringToMessage(const char* string);
// Adds a raw data buffer to the message. If the raw data is actually a
// string, be sure to have length explicitly include the '\0' terminating
// character. Returns true if the internal message buffer has room for the
// data, and the data is successfully appended.
bool AddDataToMessage(const char* buffer, size_t length);
// Adds an int to the message. Returns true if the internal message buffer has
// room for the int and the int is successfully added.
bool AddIntToMessage(int int_to_add);
// This returns a pointer to the next available data buffer in |data|. The
// pointer is owned by |this| class. The resulting buffer is a string and
// terminated with a '\0' character.
bool ReadString(const char** string);
// This returns a pointer to the next available data buffer in the message
// in |data|, and the length of the buffer in |length|. The buffer is owned by
// |this| class.
bool ReadData(const char** data, size_t* length);
// This reads the next available int from the message and stores it in
// |result|.
bool ReadInt(int* result);
// The maximum length of a message in the fixed size buffer.
static constexpr size_t kMaxMessageLength = 4096;
private:
friend class BrokerSimpleMessageTestHelper;
enum class EntryType : uint32_t { DATA = 0xBDBDBD80, INT = 0xBDBDBD81 };
// Returns whether or not the next available entry matches the expected entry
// type.
bool ValidateType(EntryType expected_type);
// Set to true once a message is read from, it may never be written to.
bool read_only_;
// Set to true once a message is written to, it may never be read from.
bool write_only_;
// Set when an operation fails, so that all subsequed operations fail,
// including any attempt to send the broken message.
bool broken_;
// The current length of the contents in the |message_| buffer.
size_t length_;
// The pointer to the next location in the |message_| buffer to read from.
uint8_t* read_next_;
// The pointer to the next location in the |message_| buffer to write from.
uint8_t* write_next_;
// The statically allocated buffer of size |kMaxMessageLength|.
uint8_t message_[kMaxMessageLength];
};
} // namespace syscall_broker
} // namespace sandbox
#endif // SANDBOX_LINUX_SYSCALL_BROKER_BROKER_SIMPLE_MESSAGE_H_