diff options
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r-- | kernel/bpf/syscall.c | 66 |
1 files changed, 54 insertions, 12 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 0c9276b54c88..b3ce516e5a20 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c | |||
@@ -355,6 +355,18 @@ static int bpf_map_release(struct inode *inode, struct file *filp) | |||
355 | return 0; | 355 | return 0; |
356 | } | 356 | } |
357 | 357 | ||
358 | static fmode_t map_get_sys_perms(struct bpf_map *map, struct fd f) | ||
359 | { | ||
360 | fmode_t mode = f.file->f_mode; | ||
361 | |||
362 | /* Our file permissions may have been overridden by global | ||
363 | * map permissions facing syscall side. | ||
364 | */ | ||
365 | if (READ_ONCE(map->frozen)) | ||
366 | mode &= ~FMODE_CAN_WRITE; | ||
367 | return mode; | ||
368 | } | ||
369 | |||
358 | #ifdef CONFIG_PROC_FS | 370 | #ifdef CONFIG_PROC_FS |
359 | static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp) | 371 | static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp) |
360 | { | 372 | { |
@@ -376,14 +388,16 @@ static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp) | |||
376 | "max_entries:\t%u\n" | 388 | "max_entries:\t%u\n" |
377 | "map_flags:\t%#x\n" | 389 | "map_flags:\t%#x\n" |
378 | "memlock:\t%llu\n" | 390 | "memlock:\t%llu\n" |
379 | "map_id:\t%u\n", | 391 | "map_id:\t%u\n" |
392 | "frozen:\t%u\n", | ||
380 | map->map_type, | 393 | map->map_type, |
381 | map->key_size, | 394 | map->key_size, |
382 | map->value_size, | 395 | map->value_size, |
383 | map->max_entries, | 396 | map->max_entries, |
384 | map->map_flags, | 397 | map->map_flags, |
385 | map->pages * 1ULL << PAGE_SHIFT, | 398 | map->pages * 1ULL << PAGE_SHIFT, |
386 | map->id); | 399 | map->id, |
400 | READ_ONCE(map->frozen)); | ||
387 | 401 | ||
388 | if (owner_prog_type) { | 402 | if (owner_prog_type) { |
389 | seq_printf(m, "owner_prog_type:\t%u\n", | 403 | seq_printf(m, "owner_prog_type:\t%u\n", |
@@ -727,8 +741,7 @@ static int map_lookup_elem(union bpf_attr *attr) | |||
727 | map = __bpf_map_get(f); | 741 | map = __bpf_map_get(f); |
728 | if (IS_ERR(map)) | 742 | if (IS_ERR(map)) |
729 | return PTR_ERR(map); | 743 | return PTR_ERR(map); |
730 | 744 | if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ)) { | |
731 | if (!(f.file->f_mode & FMODE_CAN_READ)) { | ||
732 | err = -EPERM; | 745 | err = -EPERM; |
733 | goto err_put; | 746 | goto err_put; |
734 | } | 747 | } |
@@ -857,8 +870,7 @@ static int map_update_elem(union bpf_attr *attr) | |||
857 | map = __bpf_map_get(f); | 870 | map = __bpf_map_get(f); |
858 | if (IS_ERR(map)) | 871 | if (IS_ERR(map)) |
859 | return PTR_ERR(map); | 872 | return PTR_ERR(map); |
860 | 873 | if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) { | |
861 | if (!(f.file->f_mode & FMODE_CAN_WRITE)) { | ||
862 | err = -EPERM; | 874 | err = -EPERM; |
863 | goto err_put; | 875 | goto err_put; |
864 | } | 876 | } |
@@ -969,8 +981,7 @@ static int map_delete_elem(union bpf_attr *attr) | |||
969 | map = __bpf_map_get(f); | 981 | map = __bpf_map_get(f); |
970 | if (IS_ERR(map)) | 982 | if (IS_ERR(map)) |
971 | return PTR_ERR(map); | 983 | return PTR_ERR(map); |
972 | 984 | if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) { | |
973 | if (!(f.file->f_mode & FMODE_CAN_WRITE)) { | ||
974 | err = -EPERM; | 985 | err = -EPERM; |
975 | goto err_put; | 986 | goto err_put; |
976 | } | 987 | } |
@@ -1021,8 +1032,7 @@ static int map_get_next_key(union bpf_attr *attr) | |||
1021 | map = __bpf_map_get(f); | 1032 | map = __bpf_map_get(f); |
1022 | if (IS_ERR(map)) | 1033 | if (IS_ERR(map)) |
1023 | return PTR_ERR(map); | 1034 | return PTR_ERR(map); |
1024 | 1035 | if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ)) { | |
1025 | if (!(f.file->f_mode & FMODE_CAN_READ)) { | ||
1026 | err = -EPERM; | 1036 | err = -EPERM; |
1027 | goto err_put; | 1037 | goto err_put; |
1028 | } | 1038 | } |
@@ -1089,8 +1099,7 @@ static int map_lookup_and_delete_elem(union bpf_attr *attr) | |||
1089 | map = __bpf_map_get(f); | 1099 | map = __bpf_map_get(f); |
1090 | if (IS_ERR(map)) | 1100 | if (IS_ERR(map)) |
1091 | return PTR_ERR(map); | 1101 | return PTR_ERR(map); |
1092 | 1102 | if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) { | |
1093 | if (!(f.file->f_mode & FMODE_CAN_WRITE)) { | ||
1094 | err = -EPERM; | 1103 | err = -EPERM; |
1095 | goto err_put; | 1104 | goto err_put; |
1096 | } | 1105 | } |
@@ -1132,6 +1141,36 @@ err_put: | |||
1132 | return err; | 1141 | return err; |
1133 | } | 1142 | } |
1134 | 1143 | ||
1144 | #define BPF_MAP_FREEZE_LAST_FIELD map_fd | ||
1145 | |||
1146 | static int map_freeze(const union bpf_attr *attr) | ||
1147 | { | ||
1148 | int err = 0, ufd = attr->map_fd; | ||
1149 | struct bpf_map *map; | ||
1150 | struct fd f; | ||
1151 | |||
1152 | if (CHECK_ATTR(BPF_MAP_FREEZE)) | ||
1153 | return -EINVAL; | ||
1154 | |||
1155 | f = fdget(ufd); | ||
1156 | map = __bpf_map_get(f); | ||
1157 | if (IS_ERR(map)) | ||
1158 | return PTR_ERR(map); | ||
1159 | if (READ_ONCE(map->frozen)) { | ||
1160 | err = -EBUSY; | ||
1161 | goto err_put; | ||
1162 | } | ||
1163 | if (!capable(CAP_SYS_ADMIN)) { | ||
1164 | err = -EPERM; | ||
1165 | goto err_put; | ||
1166 | } | ||
1167 | |||
1168 | WRITE_ONCE(map->frozen, true); | ||
1169 | err_put: | ||
1170 | fdput(f); | ||
1171 | return err; | ||
1172 | } | ||
1173 | |||
1135 | static const struct bpf_prog_ops * const bpf_prog_types[] = { | 1174 | static const struct bpf_prog_ops * const bpf_prog_types[] = { |
1136 | #define BPF_PROG_TYPE(_id, _name) \ | 1175 | #define BPF_PROG_TYPE(_id, _name) \ |
1137 | [_id] = & _name ## _prog_ops, | 1176 | [_id] = & _name ## _prog_ops, |
@@ -2735,6 +2774,9 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz | |||
2735 | case BPF_MAP_GET_NEXT_KEY: | 2774 | case BPF_MAP_GET_NEXT_KEY: |
2736 | err = map_get_next_key(&attr); | 2775 | err = map_get_next_key(&attr); |
2737 | break; | 2776 | break; |
2777 | case BPF_MAP_FREEZE: | ||
2778 | err = map_freeze(&attr); | ||
2779 | break; | ||
2738 | case BPF_PROG_LOAD: | 2780 | case BPF_PROG_LOAD: |
2739 | err = bpf_prog_load(&attr, uattr); | 2781 | err = bpf_prog_load(&attr, uattr); |
2740 | break; | 2782 | break; |