Skip to content

Commit ff26728

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Daniel Borkmann says: ==================== pull-request: bpf 2018-06-08 The following pull-request contains BPF updates for your *net* tree. The main changes are: 1) Fix in the BPF verifier to reject modified ctx pointers on helper functions, from Daniel. 2) Fix in BPF kselftests for get_cgroup_id_user() helper to only record the cgroup id for a provided pid in order to reduce test failures from processes interferring with the test, from Yonghong. 3) Fix a crash in AF_XDP's mem accounting when the process owning the sock has CAP_IPC_LOCK capabilities set, from Daniel. 4) Fix an issue for AF_XDP on 32 bit machines where XDP_UMEM_PGOFF_*_RING defines need ULL suffixes and use loff_t type as they are otherwise truncated, from Geert. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 8d97ca6 + c09290c commit ff26728

File tree

7 files changed

+118
-26
lines changed

7 files changed

+118
-26
lines changed

include/uapi/linux/if_xdp.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ struct xdp_statistics {
6363
/* Pgoff for mmaping the rings */
6464
#define XDP_PGOFF_RX_RING 0
6565
#define XDP_PGOFF_TX_RING 0x80000000
66-
#define XDP_UMEM_PGOFF_FILL_RING 0x100000000
67-
#define XDP_UMEM_PGOFF_COMPLETION_RING 0x180000000
66+
#define XDP_UMEM_PGOFF_FILL_RING 0x100000000ULL
67+
#define XDP_UMEM_PGOFF_COMPLETION_RING 0x180000000ULL
6868

6969
/* Rx/Tx descriptor */
7070
struct xdp_desc {

kernel/bpf/verifier.c

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,6 +1617,30 @@ static int get_callee_stack_depth(struct bpf_verifier_env *env,
16171617
}
16181618
#endif
16191619

1620+
static int check_ctx_reg(struct bpf_verifier_env *env,
1621+
const struct bpf_reg_state *reg, int regno)
1622+
{
1623+
/* Access to ctx or passing it to a helper is only allowed in
1624+
* its original, unmodified form.
1625+
*/
1626+
1627+
if (reg->off) {
1628+
verbose(env, "dereference of modified ctx ptr R%d off=%d disallowed\n",
1629+
regno, reg->off);
1630+
return -EACCES;
1631+
}
1632+
1633+
if (!tnum_is_const(reg->var_off) || reg->var_off.value) {
1634+
char tn_buf[48];
1635+
1636+
tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
1637+
verbose(env, "variable ctx access var_off=%s disallowed\n", tn_buf);
1638+
return -EACCES;
1639+
}
1640+
1641+
return 0;
1642+
}
1643+
16201644
/* truncate register to smaller size (in bytes)
16211645
* must be called with size < BPF_REG_SIZE
16221646
*/
@@ -1686,24 +1710,11 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
16861710
verbose(env, "R%d leaks addr into ctx\n", value_regno);
16871711
return -EACCES;
16881712
}
1689-
/* ctx accesses must be at a fixed offset, so that we can
1690-
* determine what type of data were returned.
1691-
*/
1692-
if (reg->off) {
1693-
verbose(env,
1694-
"dereference of modified ctx ptr R%d off=%d+%d, ctx+const is allowed, ctx+const+const is not\n",
1695-
regno, reg->off, off - reg->off);
1696-
return -EACCES;
1697-
}
1698-
if (!tnum_is_const(reg->var_off) || reg->var_off.value) {
1699-
char tn_buf[48];
17001713

1701-
tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
1702-
verbose(env,
1703-
"variable ctx access var_off=%s off=%d size=%d",
1704-
tn_buf, off, size);
1705-
return -EACCES;
1706-
}
1714+
err = check_ctx_reg(env, reg, regno);
1715+
if (err < 0)
1716+
return err;
1717+
17071718
err = check_ctx_access(env, insn_idx, off, size, t, &reg_type);
17081719
if (!err && t == BPF_READ && value_regno >= 0) {
17091720
/* ctx access returns either a scalar, or a
@@ -1984,6 +1995,9 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
19841995
expected_type = PTR_TO_CTX;
19851996
if (type != expected_type)
19861997
goto err_type;
1998+
err = check_ctx_reg(env, reg, regno);
1999+
if (err < 0)
2000+
return err;
19872001
} else if (arg_type_is_mem_ptr(arg_type)) {
19882002
expected_type = PTR_TO_STACK;
19892003
/* One exception here. In case function allows for NULL to be

net/xdp/xdp_umem.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,10 @@ static void xdp_umem_unpin_pages(struct xdp_umem *umem)
132132

133133
static void xdp_umem_unaccount_pages(struct xdp_umem *umem)
134134
{
135-
atomic_long_sub(umem->npgs, &umem->user->locked_vm);
136-
free_uid(umem->user);
135+
if (umem->user) {
136+
atomic_long_sub(umem->npgs, &umem->user->locked_vm);
137+
free_uid(umem->user);
138+
}
137139
}
138140

139141
static void xdp_umem_release(struct xdp_umem *umem)

net/xdp/xsk.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ static int xsk_getsockopt(struct socket *sock, int level, int optname,
643643
static int xsk_mmap(struct file *file, struct socket *sock,
644644
struct vm_area_struct *vma)
645645
{
646-
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
646+
loff_t offset = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
647647
unsigned long size = vma->vm_end - vma->vm_start;
648648
struct xdp_sock *xs = xdp_sk(sock->sk);
649649
struct xsk_queue *q = NULL;

tools/testing/selftests/bpf/get_cgroup_id_kern.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,24 @@ struct bpf_map_def SEC("maps") cg_ids = {
1111
.max_entries = 1,
1212
};
1313

14+
struct bpf_map_def SEC("maps") pidmap = {
15+
.type = BPF_MAP_TYPE_ARRAY,
16+
.key_size = sizeof(__u32),
17+
.value_size = sizeof(__u32),
18+
.max_entries = 1,
19+
};
20+
1421
SEC("tracepoint/syscalls/sys_enter_nanosleep")
1522
int trace(void *ctx)
1623
{
17-
__u32 key = 0;
24+
__u32 pid = bpf_get_current_pid_tgid();
25+
__u32 key = 0, *expected_pid;
1826
__u64 *val;
1927

28+
expected_pid = bpf_map_lookup_elem(&pidmap, &key);
29+
if (!expected_pid || *expected_pid != pid)
30+
return 0;
31+
2032
val = bpf_map_lookup_elem(&cg_ids, &key);
2133
if (val)
2234
*val = bpf_get_current_cgroup_id();

tools/testing/selftests/bpf/get_cgroup_id_user.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ int main(int argc, char **argv)
5050
const char *probe_name = "syscalls/sys_enter_nanosleep";
5151
const char *file = "get_cgroup_id_kern.o";
5252
int err, bytes, efd, prog_fd, pmu_fd;
53+
int cgroup_fd, cgidmap_fd, pidmap_fd;
5354
struct perf_event_attr attr = {};
54-
int cgroup_fd, cgidmap_fd;
5555
struct bpf_object *obj;
5656
__u64 kcgid = 0, ucgid;
57+
__u32 key = 0, pid;
5758
int exit_code = 1;
5859
char buf[256];
59-
__u32 key = 0;
6060

6161
err = setup_cgroup_environment();
6262
if (CHECK(err, "setup_cgroup_environment", "err %d errno %d\n", err,
@@ -81,6 +81,14 @@ int main(int argc, char **argv)
8181
cgidmap_fd, errno))
8282
goto close_prog;
8383

84+
pidmap_fd = bpf_find_map(__func__, obj, "pidmap");
85+
if (CHECK(pidmap_fd < 0, "bpf_find_map", "err %d errno %d\n",
86+
pidmap_fd, errno))
87+
goto close_prog;
88+
89+
pid = getpid();
90+
bpf_map_update_elem(pidmap_fd, &key, &pid, 0);
91+
8492
snprintf(buf, sizeof(buf),
8593
"/sys/kernel/debug/tracing/events/%s/id", probe_name);
8694
efd = open(buf, O_RDONLY, 0);

tools/testing/selftests/bpf/test_verifier.c

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8647,7 +8647,7 @@ static struct bpf_test tests[] = {
86478647
offsetof(struct __sk_buff, mark)),
86488648
BPF_EXIT_INSN(),
86498649
},
8650-
.errstr = "dereference of modified ctx ptr R1 off=68+8, ctx+const is allowed, ctx+const+const is not",
8650+
.errstr = "dereference of modified ctx ptr",
86518651
.result = REJECT,
86528652
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
86538653
},
@@ -12258,6 +12258,62 @@ static struct bpf_test tests[] = {
1225812258
.result = ACCEPT,
1225912259
.retval = 5,
1226012260
},
12261+
{
12262+
"pass unmodified ctx pointer to helper",
12263+
.insns = {
12264+
BPF_MOV64_IMM(BPF_REG_2, 0),
12265+
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
12266+
BPF_FUNC_csum_update),
12267+
BPF_MOV64_IMM(BPF_REG_0, 0),
12268+
BPF_EXIT_INSN(),
12269+
},
12270+
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
12271+
.result = ACCEPT,
12272+
},
12273+
{
12274+
"pass modified ctx pointer to helper, 1",
12275+
.insns = {
12276+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -612),
12277+
BPF_MOV64_IMM(BPF_REG_2, 0),
12278+
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
12279+
BPF_FUNC_csum_update),
12280+
BPF_MOV64_IMM(BPF_REG_0, 0),
12281+
BPF_EXIT_INSN(),
12282+
},
12283+
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
12284+
.result = REJECT,
12285+
.errstr = "dereference of modified ctx ptr",
12286+
},
12287+
{
12288+
"pass modified ctx pointer to helper, 2",
12289+
.insns = {
12290+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -612),
12291+
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
12292+
BPF_FUNC_get_socket_cookie),
12293+
BPF_MOV64_IMM(BPF_REG_0, 0),
12294+
BPF_EXIT_INSN(),
12295+
},
12296+
.result_unpriv = REJECT,
12297+
.result = REJECT,
12298+
.errstr_unpriv = "dereference of modified ctx ptr",
12299+
.errstr = "dereference of modified ctx ptr",
12300+
},
12301+
{
12302+
"pass modified ctx pointer to helper, 3",
12303+
.insns = {
12304+
BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, 0),
12305+
BPF_ALU64_IMM(BPF_AND, BPF_REG_3, 4),
12306+
BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
12307+
BPF_MOV64_IMM(BPF_REG_2, 0),
12308+
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
12309+
BPF_FUNC_csum_update),
12310+
BPF_MOV64_IMM(BPF_REG_0, 0),
12311+
BPF_EXIT_INSN(),
12312+
},
12313+
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
12314+
.result = REJECT,
12315+
.errstr = "variable ctx access var_off=(0x0; 0x4)",
12316+
},
1226112317
};
1226212318

1226312319
static int probe_filter_length(const struct bpf_insn *fp)

0 commit comments

Comments
 (0)