1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "BpfUtils"
18
19 #include "bpf/BpfUtils.h"
20
21 #include <elf.h>
22 #include <inttypes.h>
23 #include <linux/bpf.h>
24 #include <linux/if_ether.h>
25 #include <linux/in.h>
26 #include <linux/pfkeyv2.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/mman.h>
30 #include <sys/resource.h>
31 #include <sys/socket.h>
32 #include <sys/stat.h>
33 #include <sys/utsname.h>
34 #include <sstream>
35 #include <string>
36
37 #include <android-base/unique_fd.h>
38 #include <log/log.h>
39 #include <processgroup/processgroup.h>
40
41 using android::base::unique_fd;
42
43 // The buffer size for the buffer that records program loading logs, needs to be large enough for
44 // the largest kernel program.
45
46 namespace android {
47 namespace bpf {
48
getSocketCookie(int sockFd)49 uint64_t getSocketCookie(int sockFd) {
50 uint64_t sock_cookie;
51 socklen_t cookie_len = sizeof(sock_cookie);
52 int res = getsockopt(sockFd, SOL_SOCKET, SO_COOKIE, &sock_cookie, &cookie_len);
53 if (res < 0) {
54 res = -errno;
55 ALOGE("Failed to get socket cookie: %s\n", strerror(errno));
56 errno = -res;
57 // 0 is an invalid cookie. See sock_gen_cookie.
58 return NONEXISTENT_COOKIE;
59 }
60 return sock_cookie;
61 }
62
synchronizeKernelRCU()63 int synchronizeKernelRCU() {
64 // This is a temporary hack for network stats map swap on devices running
65 // 4.9 kernels. The kernel code of socket release on pf_key socket will
66 // explicitly call synchronize_rcu() which is exactly what we need.
67 int pfSocket = socket(AF_KEY, SOCK_RAW | SOCK_CLOEXEC, PF_KEY_V2);
68
69 if (pfSocket < 0) {
70 int ret = -errno;
71 ALOGE("create PF_KEY socket failed: %s", strerror(errno));
72 return ret;
73 }
74
75 // When closing socket, synchronize_rcu() gets called in sock_release().
76 if (close(pfSocket)) {
77 int ret = -errno;
78 ALOGE("failed to close the PF_KEY socket: %s", strerror(errno));
79 return ret;
80 }
81 return 0;
82 }
83
setrlimitForTest()84 int setrlimitForTest() {
85 // Set the memory rlimit for the test process if the default MEMLOCK rlimit is not enough.
86 struct rlimit limit = {
87 .rlim_cur = 1073741824, // 1 GiB
88 .rlim_max = 1073741824, // 1 GiB
89 };
90 int res = setrlimit(RLIMIT_MEMLOCK, &limit);
91 if (res) {
92 ALOGE("Failed to set the default MEMLOCK rlimit: %s", strerror(errno));
93 }
94 return res;
95 }
96
kernelVersion()97 unsigned kernelVersion() {
98 struct utsname buf;
99 int ret = uname(&buf);
100 if (ret) return 0;
101
102 unsigned kver_major;
103 unsigned kver_minor;
104 unsigned kver_sub;
105 char dummy;
106 ret = sscanf(buf.release, "%u.%u.%u%c", &kver_major, &kver_minor, &kver_sub, &dummy);
107 // Check the device kernel version
108 if (ret < 3) return 0;
109
110 return KVER(kver_major, kver_minor, kver_sub);
111 }
112
113 } // namespace bpf
114 } // namespace android
115