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
1245struct bpf_cg_run_ctx {1245struct bpf_cg_run_ctx {
1246 struct bpf_run_ctx run_ctx;1246 struct bpf_run_ctx run_ctx;
1247 const struct bpf_prog_array_item *prog_item;1247 const struct bpf_prog_array_item *prog_item;
1248 int retval;
1248};1249};
1249 1250
1250struct bpf_trace_run_ctx {1251struct 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
1280static __always_inline int1281static __always_inline int
1281BPF_PROG_RUN_ARRAY_CG_FLAGS(const struct bpf_prog_array __rcu *array_rcu,1282BPF_PROG_RUN_ARRAY_CG_FLAGS(const struct bpf_prog_array __rcu *array_rcu,
1282 const void *ctx, bpf_prog_run_fn run_prog,1283 const void *ctx, bpf_prog_run_fn run_prog,
1283 u32 *ret_flags)1284 int retval, u32 *ret_flags)
1284{1285{
1285 const struct bpf_prog_array_item *item;1286 const struct bpf_prog_array_item *item;
1286 const struct bpf_prog *prog;1287 const struct bpf_prog *prog;
1287 const struct bpf_prog_array *array;1288 const struct bpf_prog_array *array;
1288 struct bpf_run_ctx *old_run_ctx;1289 struct bpf_run_ctx *old_run_ctx;
1289 struct bpf_cg_run_ctx run_ctx;1290 struct bpf_cg_run_ctx run_ctx;
1290 int ret = 0;
1291 u32 func_ret;1291 u32 func_ret;
1292 1292
1293 run_ctx.retval = retval;
1293 migrate_disable();1294 migrate_disable();
1294 rcu_read_lock();1295 rcu_read_lock();
1295 array = rcu_dereference(array_rcu);1296 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
1299 run_ctx.prog_item = item;1300 run_ctx.prog_item = item;
1300 func_ret = run_prog(prog, ctx);1301 func_ret = run_prog(prog, ctx);
1301 if (!(func_ret & 1))1302 if (!(func_ret & 1))
1302 ret = -EPERM;1303 run_ctx.retval = -EPERM;
1303 *(ret_flags) |= (func_ret >> 1);1304 *(ret_flags) |= (func_ret >> 1);
1304 item++;1305 item++;
1305 }1306 }
1306 bpf_reset_run_ctx(old_run_ctx);1307 bpf_reset_run_ctx(old_run_ctx);
1307 rcu_read_unlock();1308 rcu_read_unlock();
1308 migrate_enable();1309 migrate_enable();
1309 return ret;1310 return run_ctx.retval;
1310}1311}
1311 1312
1312static __always_inline int1313static __always_inline int
1313BPF_PROG_RUN_ARRAY_CG(const struct bpf_prog_array __rcu *array_rcu,1314BPF_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)
1315{1317{
1316 const struct bpf_prog_array_item *item;1318 const struct bpf_prog_array_item *item;
1317 const struct bpf_prog *prog;1319 const struct bpf_prog *prog;
1318 const struct bpf_prog_array *array;1320 const struct bpf_prog_array *array;
1319 struct bpf_run_ctx *old_run_ctx;1321 struct bpf_run_ctx *old_run_ctx;
1320 struct bpf_cg_run_ctx run_ctx;1322 struct bpf_cg_run_ctx run_ctx;
1321 int ret = 0;
1322 1323
1324 run_ctx.retval = retval;
1323 migrate_disable();1325 migrate_disable();
1324 rcu_read_lock();1326 rcu_read_lock();
1325 array = rcu_dereference(array_rcu);1327 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
1328 while ((prog = READ_ONCE(item->prog))) {1330 while ((prog = READ_ONCE(item->prog))) {
1329 run_ctx.prog_item = item;1331 run_ctx.prog_item = item;
1330 if (!run_prog(prog, ctx))1332 if (!run_prog(prog, ctx))
1331 ret = -EPERM;1333 run_ctx.retval = -EPERM;
1332 item++;1334 item++;
1333 }1335 }
1334 bpf_reset_run_ctx(old_run_ctx);1336 bpf_reset_run_ctx(old_run_ctx);
1335 rcu_read_unlock();1337 rcu_read_unlock();
1336 migrate_enable();1338 migrate_enable();
1337 return ret;1339 return run_ctx.retval;
1338}1340}
1339 1341
1340static __always_inline u321342static __always_inline u32
@@ -1394,7 +1396,7 @@ out: · 53 unmodified lines
1394 u32 _flags = 0; \1396 u32 _flags = 0; \
1395 bool _cn; \1397 bool _cn; \
1396 u32 _ret; \1398 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); \
1398 _cn = _flags & BPF_RET_SET_CN; \1400 _cn = _flags & BPF_RET_SET_CN; \
1399 if (!_ret) \1401 if (!_ret) \
1400 _ret = (_cn ? NET_XMIT_CN : NET_XMIT_SUCCESS); \1402 _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
1356 s32 level;1356 s32 level;
1357 s32 optname;1357 s32 optname;
1358 s32 optlen;1358 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;
1360};1363};
1361 1364
1362int copy_bpf_fprog_from_user(struct sock_fprog *dst, sockptr_t src, int len);1365int 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