xref: /aosp_15_r20/external/perfetto/src/tracing/ipc/memfd.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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