History

bpf: rcu lock must not be held when calling copy_to_user()

BUG: sleeping function called from invalid context at mm/memory.c:3732 in_atomic(): 0, irqs_disabled(): 0, pid: 671, name: test_maps 1 lock held by test_maps/671: #0: (rcu_read_lock){......}, at: [<0000000000264190>] map_lookup_elem+0xe8/0x260 Call Trace: ([<0000000000115b7e>] show_trace+0x12e/0x150) [<0000000000115c40>] show_stack+0xa0/0x100 [<00000000009b163c>] dump_stack+0x74/0xc8 [<000000000017424a>] ___might_sleep+0x23a/0x248 [<00000000002b58e8>] might_fault+0x70/0xe8 [<0000000000264230>] map_lookup_elem+0x188/0x260 [<0000000000264716>] SyS_bpf+0x20e/0x840 Fix it by allocating temporary buffer to store map element value.

Alexei Starovoitov committed 11 years ago

Commit 8ebe6671 parent 600ddd61 file · +17 −8Browse files

Showing the changes to kernel (1 of 1 file). Show all

Unified · Split

kernel/bpf/syscall.c+17−8
@@ -150,7 +150,7 @@ static int map_lookup_elem(union bpf_attr *attr) · 149 unmodified lines
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) · 12 unmodified lines
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
184err_unlock:193free_value:
185 rcu_read_unlock();194 kfree(value);
186free_key:195free_key:
187 kfree(key);196 kfree(key);
188err_put:197err_put:

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t