1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
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 * http://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
16 #include <linux/bpf.h>
17 #include <linux/if_packet.h>
18 #include <stddef.h>
19 #include <stdint.h>
20
21 #include "bpf/bpf_helpers.h"
22 #include "bpf_def.h"
23
24 #define SEC(NAME) __attribute__((section(NAME), used))
25
26 // network stats begin
27 bpf_map_def SEC("maps") iface_stats_map = {
28 .type = BPF_MAP_TYPE_HASH,
29 .key_size = sizeof(uint64_t),
30 .value_size = sizeof(iface_stats_value),
31 .max_entries = IFACE_STATS_MAP_SIZE,
32 .map_flags = 0,
33 .inner_map_idx = 0,
34 .numa_node = 0,
35 };
36
37 bpf_map_def SEC("maps") app_uid_stats_map = {
38 .type = BPF_MAP_TYPE_HASH,
39 .key_size = sizeof(uint64_t),
40 .value_size = sizeof(app_uid_stats_value),
41 .max_entries = APP_STATS_MAP_SIZE,
42 .map_flags = 0,
43 .inner_map_idx = 0,
44 .numa_node = 0,
45 };
46
47 bpf_map_def SEC("maps") app_uid_if_stats_map = {
48 .type = BPF_MAP_TYPE_HASH,
49 .key_size = sizeof(app_uid_if_stats_key),
50 .value_size = sizeof(app_uid_if_stats_value),
51 .max_entries = IFACE_NAME_MAP_SIZE,
52 .map_flags = 0,
53 .inner_map_idx = 0,
54 .numa_node = 0,
55 };
56
57 SEC("cgroup_skb/uid/ingress")
bpf_cgroup_skb_uid_ingress(struct __sk_buff * skb)58 int bpf_cgroup_skb_uid_ingress(struct __sk_buff *skb)
59 {
60 if (skb == NULL) {
61 return 1;
62 }
63 if (skb->pkt_type == PACKET_LOOPBACK) {
64 return 1;
65 }
66 uint64_t sock_uid = bpf_get_socket_uid(skb);
67 app_uid_stats_value *value = bpf_map_lookup_elem(&app_uid_stats_map, &sock_uid);
68 if (value == NULL) {
69 app_uid_stats_value newValue = {};
70 bpf_map_update_elem(&app_uid_stats_map, &sock_uid, &newValue, BPF_NOEXIST);
71 value = bpf_map_lookup_elem(&app_uid_stats_map, &sock_uid);
72 }
73 if (value != NULL) {
74 __sync_fetch_and_add(&value->rxPackets, 1);
75 __sync_fetch_and_add(&value->rxBytes, skb->len);
76 }
77 app_uid_if_stats_key key = {.uId = sock_uid, .ifIndex = skb->ifindex};
78 app_uid_if_stats_value *value_uid_if = bpf_map_lookup_elem(&app_uid_if_stats_map, &key);
79 if (value_uid_if == NULL) {
80 app_uid_if_stats_value newValue = {};
81 bpf_map_update_elem(&app_uid_if_stats_map, &key, &newValue, BPF_NOEXIST);
82 value_uid_if = bpf_map_lookup_elem(&app_uid_if_stats_map, &key);
83 }
84 if (value_uid_if != NULL) {
85 __sync_fetch_and_add(&value_uid_if->rxPackets, 1);
86 __sync_fetch_and_add(&value_uid_if->rxBytes, skb->len);
87 }
88 uint64_t ifindex = skb->ifindex;
89 iface_stats_value *value_if = bpf_map_lookup_elem(&iface_stats_map, &ifindex);
90 if (value_if == NULL) {
91 iface_stats_value newValue = {};
92 bpf_map_update_elem(&iface_stats_map, &ifindex, &newValue, BPF_NOEXIST);
93 value_if = bpf_map_lookup_elem(&iface_stats_map, &ifindex);
94 }
95 if (value_if != NULL) {
96 __sync_fetch_and_add(&value_if->rxPackets, 1);
97 __sync_fetch_and_add(&value_if->rxBytes, skb->len);
98 }
99 return 1;
100 }
101
102 SEC("cgroup_skb/uid/egress")
bpf_cgroup_skb_uid_egress(struct __sk_buff * skb)103 int bpf_cgroup_skb_uid_egress(struct __sk_buff *skb)
104 {
105 if (skb == NULL) {
106 return 1;
107 }
108 if (skb->pkt_type == PACKET_LOOPBACK) {
109 return 1;
110 }
111 uint64_t sock_uid = bpf_get_socket_uid(skb);
112 app_uid_stats_value *value = bpf_map_lookup_elem(&app_uid_stats_map, &sock_uid);
113 if (value == NULL) {
114 app_uid_stats_value newValue = {};
115 bpf_map_update_elem(&app_uid_stats_map, &sock_uid, &newValue, BPF_NOEXIST);
116 value = bpf_map_lookup_elem(&app_uid_stats_map, &sock_uid);
117 }
118 if (value != NULL) {
119 __sync_fetch_and_add(&value->txPackets, 1);
120 __sync_fetch_and_add(&value->txBytes, skb->len);
121 }
122 app_uid_if_stats_key key = {.uId = sock_uid, .ifIndex = skb->ifindex};
123 app_uid_if_stats_value *value_uid_if = bpf_map_lookup_elem(&app_uid_if_stats_map, &key);
124 if (value_uid_if == NULL) {
125 app_uid_if_stats_value newValue = {};
126 bpf_map_update_elem(&app_uid_if_stats_map, &key, &newValue, BPF_NOEXIST);
127 value_uid_if = bpf_map_lookup_elem(&app_uid_if_stats_map, &key);
128 }
129 if (value_uid_if != NULL) {
130 __sync_fetch_and_add(&value_uid_if->txPackets, 1);
131 __sync_fetch_and_add(&value_uid_if->txBytes, skb->len);
132 }
133 uint64_t ifindex = skb->ifindex;
134 iface_stats_value *value_if = bpf_map_lookup_elem(&iface_stats_map, &ifindex);
135 if (value_if == NULL) {
136 iface_stats_value newValue = {};
137 bpf_map_update_elem(&iface_stats_map, &ifindex, &newValue, BPF_NOEXIST);
138 value_if = bpf_map_lookup_elem(&iface_stats_map, &ifindex);
139 }
140 if (value_if != NULL) {
141 __sync_fetch_and_add(&value_if->txPackets, 1);
142 __sync_fetch_and_add(&value_if->txBytes, skb->len);
143 }
144 return 1;
145 }
146 // network stats end
147
148 // internet permission begin
149 bpf_map_def SEC("maps") sock_permission_map = {
150 .type = BPF_MAP_TYPE_HASH,
151 .key_size = sizeof(sock_permission_key),
152 .value_size = sizeof(sock_permission_value),
153 .max_entries = 65536,
154 };
155
156 SEC("cgroup_sock/inet_create_socket")
inet_create_socket(struct bpf_sock * sk)157 int inet_create_socket(struct bpf_sock *sk)
158 {
159 __u64 gid_uid = bpf_get_current_uid_gid();
160 __u32 uid = (__u32)(gid_uid & 0x00000000FFFFFFFF);
161 sock_permission_value *value = bpf_map_lookup_elem(&sock_permission_map, &uid);
162 // value == NULL means that the process attached to this uid is not a hap process which started by appspawn
163 // it is a native process, native process should have this permission
164 if (value == NULL) {
165 return 1;
166 }
167 // *value == 0 means no permission
168 if (*value == 0) {
169 return 0;
170 }
171 return 1;
172 }
173 // internet permission end
174 char g_license[] SEC("license") = "GPL";
175