aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/bpf/syscall.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r--kernel/bpf/syscall.c58
1 files changed, 43 insertions, 15 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index a31a1ba0f8ea..7958252a4d29 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -181,32 +181,60 @@ int bpf_map_precharge_memlock(u32 pages)
181 return 0; 181 return 0;
182} 182}
183 183
184static int bpf_map_charge_memlock(struct bpf_map *map) 184static int bpf_charge_memlock(struct user_struct *user, u32 pages)
185{ 185{
186 struct user_struct *user = get_current_user(); 186 unsigned long memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
187 unsigned long memlock_limit;
188 187
189 memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; 188 if (atomic_long_add_return(pages, &user->locked_vm) > memlock_limit) {
189 atomic_long_sub(pages, &user->locked_vm);
190 return -EPERM;
191 }
192 return 0;
193}
190 194
191 atomic_long_add(map->pages, &user->locked_vm); 195static void bpf_uncharge_memlock(struct user_struct *user, u32 pages)
196{
197 atomic_long_sub(pages, &user->locked_vm);
198}
199
200static int bpf_map_init_memlock(struct bpf_map *map)
201{
202 struct user_struct *user = get_current_user();
203 int ret;
192 204
193 if (atomic_long_read(&user->locked_vm) > memlock_limit) { 205 ret = bpf_charge_memlock(user, map->pages);
194 atomic_long_sub(map->pages, &user->locked_vm); 206 if (ret) {
195 free_uid(user); 207 free_uid(user);
196 return -EPERM; 208 return ret;
197 } 209 }
198 map->user = user; 210 map->user = user;
199 return 0; 211 return ret;
200} 212}
201 213
202static void bpf_map_uncharge_memlock(struct bpf_map *map) 214static void bpf_map_release_memlock(struct bpf_map *map)
203{ 215{
204 struct user_struct *user = map->user; 216 struct user_struct *user = map->user;
205 217 bpf_uncharge_memlock(user, map->pages);
206 atomic_long_sub(map->pages, &user->locked_vm);
207 free_uid(user); 218 free_uid(user);
208} 219}
209 220
221int bpf_map_charge_memlock(struct bpf_map *map, u32 pages)
222{
223 int ret;
224
225 ret = bpf_charge_memlock(map->user, pages);
226 if (ret)
227 return ret;
228 map->pages += pages;
229 return ret;
230}
231
232void bpf_map_uncharge_memlock(struct bpf_map *map, u32 pages)
233{
234 bpf_uncharge_memlock(map->user, pages);
235 map->pages -= pages;
236}
237
210static int bpf_map_alloc_id(struct bpf_map *map) 238static int bpf_map_alloc_id(struct bpf_map *map)
211{ 239{
212 int id; 240 int id;
@@ -256,7 +284,7 @@ static void bpf_map_free_deferred(struct work_struct *work)
256{ 284{
257 struct bpf_map *map = container_of(work, struct bpf_map, work); 285 struct bpf_map *map = container_of(work, struct bpf_map, work);
258 286
259 bpf_map_uncharge_memlock(map); 287 bpf_map_release_memlock(map);
260 security_bpf_map_free(map); 288 security_bpf_map_free(map);
261 /* implementation dependent freeing */ 289 /* implementation dependent freeing */
262 map->ops->map_free(map); 290 map->ops->map_free(map);
@@ -492,7 +520,7 @@ static int map_create(union bpf_attr *attr)
492 if (err) 520 if (err)
493 goto free_map_nouncharge; 521 goto free_map_nouncharge;
494 522
495 err = bpf_map_charge_memlock(map); 523 err = bpf_map_init_memlock(map);
496 if (err) 524 if (err)
497 goto free_map_sec; 525 goto free_map_sec;
498 526
@@ -515,7 +543,7 @@ static int map_create(union bpf_attr *attr)
515 return err; 543 return err;
516 544
517free_map: 545free_map:
518 bpf_map_uncharge_memlock(map); 546 bpf_map_release_memlock(map);
519free_map_sec: 547free_map_sec:
520 security_bpf_map_free(map); 548 security_bpf_map_free(map);
521free_map_nouncharge: 549free_map_nouncharge: