1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2020 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker *
4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker *
8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker *
10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker */
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker #include "src/tracing/ipc/memfd.h"
18*6dbdd20aSAndroid Build Coastguard Worker
19*6dbdd20aSAndroid Build Coastguard Worker #include <errno.h>
20*6dbdd20aSAndroid Build Coastguard Worker
21*6dbdd20aSAndroid Build Coastguard Worker #define PERFETTO_MEMFD_ENABLED() \
22*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
23*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX)
24*6dbdd20aSAndroid Build Coastguard Worker
25*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_MEMFD_ENABLED()
26*6dbdd20aSAndroid Build Coastguard Worker
27*6dbdd20aSAndroid Build Coastguard Worker #include <stdio.h>
28*6dbdd20aSAndroid Build Coastguard Worker #include <string.h>
29*6dbdd20aSAndroid Build Coastguard Worker #include <sys/syscall.h>
30*6dbdd20aSAndroid Build Coastguard Worker #include <sys/utsname.h>
31*6dbdd20aSAndroid Build Coastguard Worker #include <unistd.h>
32*6dbdd20aSAndroid Build Coastguard Worker
33*6dbdd20aSAndroid Build Coastguard Worker // Some android build bots use a sysroot that doesn't support memfd when
34*6dbdd20aSAndroid Build Coastguard Worker // compiling for the host, so we redefine it if necessary.
35*6dbdd20aSAndroid Build Coastguard Worker #if !defined(__NR_memfd_create)
36*6dbdd20aSAndroid Build Coastguard Worker #if defined(__x86_64__)
37*6dbdd20aSAndroid Build Coastguard Worker #define __NR_memfd_create 319
38*6dbdd20aSAndroid Build Coastguard Worker #elif defined(__i386__)
39*6dbdd20aSAndroid Build Coastguard Worker #define __NR_memfd_create 356
40*6dbdd20aSAndroid Build Coastguard Worker #elif defined(__aarch64__)
41*6dbdd20aSAndroid Build Coastguard Worker #define __NR_memfd_create 279
42*6dbdd20aSAndroid Build Coastguard Worker #elif defined(__arm__)
43*6dbdd20aSAndroid Build Coastguard Worker #define __NR_memfd_create 385
44*6dbdd20aSAndroid Build Coastguard Worker #else
45*6dbdd20aSAndroid Build Coastguard Worker #error "unsupported sysroot without memfd support"
46*6dbdd20aSAndroid Build Coastguard Worker #endif
47*6dbdd20aSAndroid Build Coastguard Worker #endif // !defined(__NR_memfd_create)
48*6dbdd20aSAndroid Build Coastguard Worker
49*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
HasMemfdSupport()50*6dbdd20aSAndroid Build Coastguard Worker bool HasMemfdSupport() {
51*6dbdd20aSAndroid Build Coastguard Worker static bool kSupportsMemfd = [] {
52*6dbdd20aSAndroid Build Coastguard Worker // Check kernel version supports memfd_create(). Some older kernels segfault
53*6dbdd20aSAndroid Build Coastguard Worker // executing memfd_create() rather than returning ENOSYS (b/116769556).
54*6dbdd20aSAndroid Build Coastguard Worker static constexpr int kRequiredMajor = 3;
55*6dbdd20aSAndroid Build Coastguard Worker static constexpr int kRequiredMinor = 17;
56*6dbdd20aSAndroid Build Coastguard Worker struct utsname uts;
57*6dbdd20aSAndroid Build Coastguard Worker int major, minor;
58*6dbdd20aSAndroid Build Coastguard Worker if (uname(&uts) == 0 && strcmp(uts.sysname, "Linux") == 0 &&
59*6dbdd20aSAndroid Build Coastguard Worker sscanf(uts.release, "%d.%d", &major, &minor) == 2 &&
60*6dbdd20aSAndroid Build Coastguard Worker ((major < kRequiredMajor ||
61*6dbdd20aSAndroid Build Coastguard Worker (major == kRequiredMajor && minor < kRequiredMinor)))) {
62*6dbdd20aSAndroid Build Coastguard Worker return false;
63*6dbdd20aSAndroid Build Coastguard Worker }
64*6dbdd20aSAndroid Build Coastguard Worker
65*6dbdd20aSAndroid Build Coastguard Worker base::ScopedFile fd;
66*6dbdd20aSAndroid Build Coastguard Worker fd.reset(static_cast<int>(syscall(__NR_memfd_create, "perfetto_shmem",
67*6dbdd20aSAndroid Build Coastguard Worker MFD_CLOEXEC | MFD_ALLOW_SEALING)));
68*6dbdd20aSAndroid Build Coastguard Worker return !!fd;
69*6dbdd20aSAndroid Build Coastguard Worker }();
70*6dbdd20aSAndroid Build Coastguard Worker return kSupportsMemfd;
71*6dbdd20aSAndroid Build Coastguard Worker }
72*6dbdd20aSAndroid Build Coastguard Worker
CreateMemfd(const char * name,unsigned int flags)73*6dbdd20aSAndroid Build Coastguard Worker base::ScopedFile CreateMemfd(const char* name, unsigned int flags) {
74*6dbdd20aSAndroid Build Coastguard Worker if (!HasMemfdSupport()) {
75*6dbdd20aSAndroid Build Coastguard Worker errno = ENOSYS;
76*6dbdd20aSAndroid Build Coastguard Worker return base::ScopedFile();
77*6dbdd20aSAndroid Build Coastguard Worker }
78*6dbdd20aSAndroid Build Coastguard Worker return base::ScopedFile(
79*6dbdd20aSAndroid Build Coastguard Worker static_cast<int>(syscall(__NR_memfd_create, name, flags)));
80*6dbdd20aSAndroid Build Coastguard Worker }
81*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto
82*6dbdd20aSAndroid Build Coastguard Worker
83*6dbdd20aSAndroid Build Coastguard Worker #else // PERFETTO_MEMFD_ENABLED()
84*6dbdd20aSAndroid Build Coastguard Worker
85*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
HasMemfdSupport()86*6dbdd20aSAndroid Build Coastguard Worker bool HasMemfdSupport() {
87*6dbdd20aSAndroid Build Coastguard Worker return false;
88*6dbdd20aSAndroid Build Coastguard Worker }
CreateMemfd(const char *,unsigned int)89*6dbdd20aSAndroid Build Coastguard Worker base::ScopedFile CreateMemfd(const char*, unsigned int) {
90*6dbdd20aSAndroid Build Coastguard Worker errno = ENOSYS;
91*6dbdd20aSAndroid Build Coastguard Worker return base::ScopedFile();
92*6dbdd20aSAndroid Build Coastguard Worker }
93*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto
94*6dbdd20aSAndroid Build Coastguard Worker
95*6dbdd20aSAndroid Build Coastguard Worker #endif // PERFETTO_MEMFD_ENABLED()
96