• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "dynlink_rand.h"
17 
18 #include <stdlib.h>
19 #include <sys/mman.h>
20 #include <sys/random.h>
21 #include <unistd.h>
22 
23 #include "malloc_impl.h"
24 
25 #define HANDLE_INCREASE 2
26 #define TASK_BASE_CAPACITY 8
27 
28 // linked list node for handle randomization
29 struct handle_node {
30     struct handle_node *next;
31     void *handle;
32     struct dso *dso;
33 };
34 
35 // linked list for handle randomization
36 static struct handle_node *handle_map_list = NULL;
37 
38 static uintptr_t saved_handle = 0;
39 
add_handle_node(void * handle,struct dso * dso)40 void *add_handle_node(void *handle, struct dso *dso)
41 {
42     struct handle_node *node = internal_malloc(sizeof(*node));
43     if (!node) {
44         return NULL;
45     }
46     node->handle = handle;
47     node->dso = dso;
48     node->next = handle_map_list;
49     handle_map_list = node;
50     return node;
51 }
52 
find_dso_by_handle(void * handle)53 struct dso *find_dso_by_handle(void *handle)
54 {
55     struct handle_node *node = handle_map_list;
56     while (node) {
57         if (node->handle == handle) {
58             return node->dso;
59         }
60         node = node->next;
61     }
62     return NULL;
63 }
64 
find_handle_by_dso(struct dso * dso)65 static void *find_handle_by_dso(struct dso *dso)
66 {
67     struct handle_node *node = handle_map_list;
68     while (node) {
69         if (node->dso == dso) {
70             return node->handle;
71         }
72         node = node->next;
73     }
74     return 0;
75 }
76 
remove_handle_node(void * handle)77 void remove_handle_node(void *handle)
78 {
79     struct handle_node *node = handle_map_list;
80     struct handle_node *pre_node = NULL;
81     while (node) {
82         if (node->handle == handle) {
83             if (pre_node) {
84                 pre_node->next = node->next;
85             } else {
86                 handle_map_list = node->next;
87             }
88             internal_free(node);
89             return;
90         } else {
91             pre_node = node;
92             node = node->next;
93         }
94     }
95 }
96 
gen_handle(void)97 static void *gen_handle(void)
98 {
99     uintptr_t handle = saved_handle;
100     do {
101         if (getrandom(&handle, sizeof handle, GRND_RANDOM | GRND_NONBLOCK) == -1) {
102             handle += HANDLE_INCREASE;
103             saved_handle = handle;
104         }
105     } while (find_dso_by_handle((void *)handle) || handle == 0);
106     return (void *)handle;
107 }
108 
assign_valid_handle(struct dso * p)109 void *assign_valid_handle(struct dso *p)
110 {
111     void *handle = find_handle_by_dso(p);
112     if (handle == 0) {
113         handle = gen_handle();
114         if (!add_handle_node(handle, p)) {
115             handle = 0;
116         }
117     }
118     return handle;
119 }
120 
create_loadtasks(void)121 struct loadtasks *create_loadtasks(void)
122 {
123     struct loadtasks *tasks = internal_malloc(sizeof(struct loadtasks));
124     if (tasks) {
125         tasks->array = NULL;
126         tasks->capacity = 0;
127         tasks->length = 0;
128         return tasks;
129     }
130     return NULL;
131 }
132 
append_loadtasks(struct loadtasks * tasks,struct loadtask * item)133 bool append_loadtasks(struct loadtasks *tasks, struct loadtask *item)
134 {
135     if (tasks->length + 1 > tasks->capacity) {
136         size_t new_cap = 0;
137         new_cap = tasks->capacity + TASK_BASE_CAPACITY;
138         void *realloced = NULL;
139         if (tasks->array) {
140             realloced = internal_realloc(tasks->array, new_cap * sizeof(struct loadtask *));
141         } else {
142             realloced = internal_malloc(TASK_BASE_CAPACITY * sizeof(struct loadtask *));
143         }
144         if (realloced) {
145             tasks->array = realloced;
146             tasks->capacity = new_cap;
147         } else {
148             return false;
149         }
150     }
151     tasks->array[tasks->length] = item;
152     tasks->length += 1;
153     return true;
154 }
155 
free_task(struct loadtask * task)156 void free_task(struct loadtask *task)
157 {
158     if (task == NULL) {
159         return;
160     }
161     if (task->name) {
162         internal_free(task->name);
163         task->name = NULL;
164     }
165     if (task->allocated_buf) {
166         internal_free(task->allocated_buf);
167         task->allocated_buf = NULL;
168     }
169     if (task->dyn_map_len) {
170         munmap(task->dyn_map, task->dyn_map_len);
171         task->dyn_map = NULL;
172         task->dyn_map_len = 0;
173     }
174     if (task->str_map_len) {
175         munmap(task->str_map, task->str_map_len);
176         task->str_map = NULL;
177         task->str_map_len = 0;
178     }
179     if (task->fd != -1 && task->fd) {
180         close(task->fd);
181         task->fd = -1;
182     }
183     internal_free(task);
184 }
185 
get_loadtask(struct loadtasks * tasks,size_t index)186 struct loadtask *get_loadtask(struct loadtasks *tasks, size_t index)
187 {
188     if (tasks && tasks->array && (index < tasks->length)) {
189         return tasks->array[index];
190     } else {
191         return NULL;
192     }
193 }
194 
free_loadtasks(struct loadtasks * tasks)195 void free_loadtasks(struct loadtasks *tasks)
196 {
197     if (tasks) {
198         if (tasks->length) {
199             for (int i = 0; i < tasks->length; i++) {
200                 free_task(get_loadtask(tasks, i));
201             }
202             tasks->length = 0;
203         }
204         if (tasks->array) {
205             internal_free(tasks->array);
206             tasks->array = NULL;
207         }
208         tasks->capacity = 0;
209         internal_free(tasks);
210     }
211 }
212 
shuffle_loadtasks(struct loadtasks * tasks)213 void shuffle_loadtasks(struct loadtasks *tasks)
214 {
215     size_t index = 0;
216     struct loadtask *task = NULL;
217     for (size_t i = 0; i < tasks->length; i++) {
218         if (getrandom(&index, sizeof index, GRND_RANDOM | GRND_NONBLOCK) == -1) {
219             return;
220         } else {
221             index %= tasks->length;
222             task = tasks->array[i];
223             tasks->array[i] = tasks->array[index];
224             tasks->array[index] = task;
225         }
226     }
227 }
228 
create_loadtask(const char * name,struct dso * needed_by,ns_t * ns,bool check_inherited)229 struct loadtask *create_loadtask(const char *name, struct dso *needed_by, ns_t *ns, bool check_inherited)
230 {
231     size_t name_len = strlen(name);
232     char *name_buf = (char *)internal_malloc(name_len + 1);
233     if (!name_buf) {
234         return NULL;
235     }
236     struct loadtask *task = internal_calloc(1, sizeof(struct loadtask));
237     if (!task) {
238         return NULL;
239     }
240     strcpy(name_buf, name);
241     task->name = name_buf;
242     task->needed_by = needed_by;
243     task->namespace = ns;
244     task->check_inherited = check_inherited;
245     return task;
246 }
247