• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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