diff options
| author | David S. Miller <davem@davemloft.net> | 2015-01-26 20:20:48 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-01-26 20:20:48 -0500 |
| commit | 412d2907c41531b60c7ea1f38cfe1116daf2a229 (patch) | |
| tree | 05f6de4541734b82240629d9a21cb3df1b83d7ef | |
| parent | 600ddd6825543962fb807884169e57b580dba208 (diff) | |
| parent | ba1a68bf1308a71a07d2462f4c38c242e08f92ba (diff) | |
Merge branch 'bpf'
Alexei Starovoitov says:
====================
bpf: fix two bugs
Michael Holzheu caught two issues (in bpf syscall and in the test).
Fix them. Details in corresponding patches.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | kernel/bpf/syscall.c | 25 | ||||
| -rw-r--r-- | samples/bpf/test_maps.c | 4 |
2 files changed, 19 insertions, 10 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 088ac0b1b106..536edc2be307 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c | |||
| @@ -150,7 +150,7 @@ static int map_lookup_elem(union bpf_attr *attr) | |||
| 150 | int ufd = attr->map_fd; | 150 | int ufd = attr->map_fd; |
| 151 | struct fd f = fdget(ufd); | 151 | struct fd f = fdget(ufd); |
| 152 | struct bpf_map *map; | 152 | struct bpf_map *map; |
| 153 | void *key, *value; | 153 | void *key, *value, *ptr; |
| 154 | int err; | 154 | int err; |
| 155 | 155 | ||
| 156 | if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM)) | 156 | if (CHECK_ATTR(BPF_MAP_LOOKUP_ELEM)) |
| @@ -169,20 +169,29 @@ static int map_lookup_elem(union bpf_attr *attr) | |||
| 169 | if (copy_from_user(key, ukey, map->key_size) != 0) | 169 | if (copy_from_user(key, ukey, map->key_size) != 0) |
| 170 | goto free_key; | 170 | goto free_key; |
| 171 | 171 | ||
| 172 | err = -ENOENT; | 172 | err = -ENOMEM; |
| 173 | rcu_read_lock(); | 173 | value = kmalloc(map->value_size, GFP_USER); |
| 174 | value = map->ops->map_lookup_elem(map, key); | ||
| 175 | if (!value) | 174 | if (!value) |
| 176 | goto err_unlock; | 175 | goto free_key; |
| 176 | |||
| 177 | rcu_read_lock(); | ||
| 178 | ptr = map->ops->map_lookup_elem(map, key); | ||
| 179 | if (ptr) | ||
| 180 | memcpy(value, ptr, map->value_size); | ||
| 181 | rcu_read_unlock(); | ||
| 182 | |||
| 183 | err = -ENOENT; | ||
| 184 | if (!ptr) | ||
| 185 | goto free_value; | ||
| 177 | 186 | ||
| 178 | err = -EFAULT; | 187 | err = -EFAULT; |
| 179 | if (copy_to_user(uvalue, value, map->value_size) != 0) | 188 | if (copy_to_user(uvalue, value, map->value_size) != 0) |
| 180 | goto err_unlock; | 189 | goto free_value; |
| 181 | 190 | ||
| 182 | err = 0; | 191 | err = 0; |
| 183 | 192 | ||
| 184 | err_unlock: | 193 | free_value: |
| 185 | rcu_read_unlock(); | 194 | kfree(value); |
| 186 | free_key: | 195 | free_key: |
| 187 | kfree(key); | 196 | kfree(key); |
| 188 | err_put: | 197 | err_put: |
diff --git a/samples/bpf/test_maps.c b/samples/bpf/test_maps.c index e286b42307f3..6299ee95cd11 100644 --- a/samples/bpf/test_maps.c +++ b/samples/bpf/test_maps.c | |||
| @@ -69,9 +69,9 @@ static void test_hashmap_sanity(int i, void *data) | |||
| 69 | 69 | ||
| 70 | /* iterate over two elements */ | 70 | /* iterate over two elements */ |
| 71 | assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 && | 71 | assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 && |
| 72 | next_key == 2); | 72 | (next_key == 1 || next_key == 2)); |
| 73 | assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 && | 73 | assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 && |
| 74 | next_key == 1); | 74 | (next_key == 1 || next_key == 2)); |
| 75 | assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 && | 75 | assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 && |
| 76 | errno == ENOENT); | 76 | errno == ENOENT); |
| 77 | 77 | ||
