History

bpf: Move getsockopt retval to struct bpf_cg_run_ctx

The retval value is moved to struct bpf_cg_run_ctx for ease of access in different prog types with different context structs layouts. The helper implementation (to be added in a later patch in the series) can simply perform a container_of from current->bpf_ctx to retrieve bpf_cg_run_ctx. Unfortunately, there is no easy way to access the current task_struct via the verifier BPF bytecode rewrite, aside from possibly calling a helper, so a pointer to current task is added to struct bpf_sockopt_kern so that the rewritten BPF bytecode can access struct bpf_cg_run_ctx with an indirection. For backward compatibility, if a getsockopt program rejects a syscall by returning 0, an -EPERM will be generated, by having the BPF_PROG_RUN_ARRAY_CG family macros automatically set the retval to -EPERM. Unlike prior to this patch, this -EPERM will be visible to ctx->retval for any other hooks down the line in the prog array. Additionally, the restriction that getsockopt filters can only set the retval to 0 is removed, considering that certain getsockopt implementations may return optlen. Filters are now able to set the value arbitrarily.

YiFei Zhu committed 4 years ago

Commit c4dcfdd1 parent f10d0593 files · +63 −44Browse files

Showing the changes to include (2 of 3 files). Show all

Unified · Split

2 files
  1. include/linux/bpf.h +11 −9
  2. include/linux/filter.h +4 −1
include/linux/bpf.h+11−9
@@ -1245,6 +1245,7 @@ struct bpf_run_ctx {}; · 1244 unmodified lines
12451245 struct bpf_cg_run_ctx {
12461246 struct bpf_run_ctx run_ctx;
12471247 const struct bpf_prog_array_item *prog_item;
1248+ int retval;
12481249 };
12491250
12501251 struct bpf_trace_run_ctx {
@@ -1280,16 +1281,16 @@ typedef u32 (*bpf_prog_run_fn)(const struct bpf_prog *prog, const void *ctx); · 29 unmodified lines
12801281 static __always_inline int
12811282 BPF_PROG_RUN_ARRAY_CG_FLAGS(const struct bpf_prog_array __rcu *array_rcu,
12821283 const void *ctx, bpf_prog_run_fn run_prog,
1283− u32 *ret_flags)
1284+ int retval, u32 *ret_flags)
12841285 {
12851286 const struct bpf_prog_array_item *item;
12861287 const struct bpf_prog *prog;
12871288 const struct bpf_prog_array *array;
12881289 struct bpf_run_ctx *old_run_ctx;
12891290 struct bpf_cg_run_ctx run_ctx;
1290− int ret = 0;
12911291 u32 func_ret;
12921292
1293+ run_ctx.retval = retval;
12931294 migrate_disable();
12941295 rcu_read_lock();
12951296 array = rcu_dereference(array_rcu);
@@ -1299,27 +1300,28 @@ BPF_PROG_RUN_ARRAY_CG_FLAGS(const struct bpf_prog_array __rcu *array_rcu, · 3 unmodified lines
12991300 run_ctx.prog_item = item;
13001301 func_ret = run_prog(prog, ctx);
13011302 if (!(func_ret & 1))
1302− ret = -EPERM;
1303+ run_ctx.retval = -EPERM;
13031304 *(ret_flags) |= (func_ret >> 1);
13041305 item++;
13051306 }
13061307 bpf_reset_run_ctx(old_run_ctx);
13071308 rcu_read_unlock();
13081309 migrate_enable();
1309− return ret;
1310+ return run_ctx.retval;
13101311 }
13111312
13121313 static __always_inline int
13131314 BPF_PROG_RUN_ARRAY_CG(const struct bpf_prog_array __rcu *array_rcu,
1314− const void *ctx, bpf_prog_run_fn run_prog)
1315+ const void *ctx, bpf_prog_run_fn run_prog,
1316+ int retval)
13151317 {
13161318 const struct bpf_prog_array_item *item;
13171319 const struct bpf_prog *prog;
13181320 const struct bpf_prog_array *array;
13191321 struct bpf_run_ctx *old_run_ctx;
13201322 struct bpf_cg_run_ctx run_ctx;
1321− int ret = 0;
13221323
1324+ run_ctx.retval = retval;
13231325 migrate_disable();
13241326 rcu_read_lock();
13251327 array = rcu_dereference(array_rcu);
@@ -1328,13 +1330,13 @@ BPF_PROG_RUN_ARRAY_CG(const struct bpf_prog_array __rcu *array_rcu, · 2 unmodified lines
13281330 while ((prog = READ_ONCE(item->prog))) {
13291331 run_ctx.prog_item = item;
13301332 if (!run_prog(prog, ctx))
1331− ret = -EPERM;
1333+ run_ctx.retval = -EPERM;
13321334 item++;
13331335 }
13341336 bpf_reset_run_ctx(old_run_ctx);
13351337 rcu_read_unlock();
13361338 migrate_enable();
1337− return ret;
1339+ return run_ctx.retval;
13381340 }
13391341
13401342 static __always_inline u32
@@ -1394,7 +1396,7 @@ out: · 53 unmodified lines
13941396 u32 _flags = 0; \
13951397 bool _cn; \
13961398 u32 _ret; \
1397− _ret = BPF_PROG_RUN_ARRAY_CG_FLAGS(array, ctx, func, &_flags); \
1399+ _ret = BPF_PROG_RUN_ARRAY_CG_FLAGS(array, ctx, func, 0, &_flags); \
13981400 _cn = _flags & BPF_RET_SET_CN; \
13991401 if (!_ret) \
14001402 _ret = (_cn ? NET_XMIT_CN : NET_XMIT_SUCCESS); \
include/linux/filter.h+4−1
@@ -1356,7 +1356,10 @@ struct bpf_sockopt_kern { · 1355 unmodified lines
13561356 s32 level;
13571357 s32 optname;
13581358 s32 optlen;
1359− s32 retval;
1359+ /* for retval in struct bpf_cg_run_ctx */
1360+ struct task_struct *current_task;
1361+ /* Temporary "register" for indirect stores to ppos. */
1362+ u64 tmp_reg;
13601363 };
13611364
13621365 int copy_bpf_fprog_from_user(struct sock_fprog *dst, sockptr_t src, int len);

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