xref: /aosp_15_r20/external/sandboxed-api/sandboxed_api/sandbox2/buffer.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "sandboxed_api/sandbox2/buffer.h"
16 
17 #include <sys/mman.h>
18 #include <sys/stat.h>
19 #include <unistd.h>
20 
21 #include <cerrno>
22 #include <cstddef>
23 #include <cstdint>
24 #include <memory>
25 #include <utility>
26 
27 #include "absl/memory/memory.h"
28 #include "absl/status/status.h"
29 #include "absl/status/statusor.h"
30 #include "sandboxed_api/sandbox2/util.h"
31 
32 namespace sandbox2 {
33 
34 // Creates a new Buffer that is backed by the specified file descriptor.
CreateFromFd(int fd)35 absl::StatusOr<std::unique_ptr<Buffer>> Buffer::CreateFromFd(int fd) {
36   // Using `new` to access a non-public constructor.
37   auto buffer = absl::WrapUnique(new Buffer());
38 
39   struct stat stat_buf;
40   if (fstat(fd, &stat_buf) != 0) {
41     return absl::ErrnoToStatus(errno, "Could not stat buffer fd");
42   }
43   size_t size = stat_buf.st_size;
44   int prot = PROT_READ | PROT_WRITE;
45   int flags = MAP_SHARED;
46   off_t offset = 0;
47   buffer->buf_ =
48       reinterpret_cast<uint8_t*>(mmap(nullptr, size, prot, flags, fd, offset));
49   if (buffer->buf_ == MAP_FAILED) {
50     return absl::ErrnoToStatus(errno, "Could not map buffer fd");
51   }
52   buffer->fd_ = fd;
53   buffer->size_ = size;
54   return std::move(buffer);  // GCC 7 needs the move (C++ DR #1579)
55 }
56 
57 // Creates a new Buffer of the specified size, backed by a temporary file that
58 // will be immediately deleted.
CreateWithSize(size_t size)59 absl::StatusOr<std::unique_ptr<Buffer>> Buffer::CreateWithSize(size_t size) {
60   int fd;
61   if (!util::CreateMemFd(&fd)) {
62     return absl::InternalError("Could not create buffer temp file");
63   }
64   if (ftruncate(fd, size) != 0) {
65     return absl::ErrnoToStatus(errno, "Could not extend buffer fd");
66   }
67   return CreateFromFd(fd);
68 }
69 
~Buffer()70 Buffer::~Buffer() {
71   if (buf_ != nullptr) {
72     munmap(buf_, size_);
73   }
74   if (fd_ != -1) {
75     close(fd_);
76   }
77 }
78 
79 }  // namespace sandbox2
80