Skip to content

Commit 27602e2

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Alexei Starovoitov says: ==================== pull-request: bpf 2019-03-24 The following pull-request contains BPF updates for your *net* tree. The main changes are: 1) libbpf verision fix up from Daniel. 2) fix liveness propagation from Jakub. 3) fix verbose print of refcounted regs from Martin. 4) fix for large map allocations from Martynas. 5) fix use after free in sanitize_ptr_alu from Xu. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 526949e + a7d6ac3 commit 27602e2

File tree

5 files changed

+92
-33
lines changed

5 files changed

+92
-33
lines changed

kernel/bpf/syscall.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -136,21 +136,29 @@ static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
136136

137137
void *bpf_map_area_alloc(size_t size, int numa_node)
138138
{
139-
/* We definitely need __GFP_NORETRY, so OOM killer doesn't
140-
* trigger under memory pressure as we really just want to
141-
* fail instead.
139+
/* We really just want to fail instead of triggering OOM killer
140+
* under memory pressure, therefore we set __GFP_NORETRY to kmalloc,
141+
* which is used for lower order allocation requests.
142+
*
143+
* It has been observed that higher order allocation requests done by
144+
* vmalloc with __GFP_NORETRY being set might fail due to not trying
145+
* to reclaim memory from the page cache, thus we set
146+
* __GFP_RETRY_MAYFAIL to avoid such situations.
142147
*/
143-
const gfp_t flags = __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO;
148+
149+
const gfp_t flags = __GFP_NOWARN | __GFP_ZERO;
144150
void *area;
145151

146152
if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
147-
area = kmalloc_node(size, GFP_USER | flags, numa_node);
153+
area = kmalloc_node(size, GFP_USER | __GFP_NORETRY | flags,
154+
numa_node);
148155
if (area != NULL)
149156
return area;
150157
}
151158

152-
return __vmalloc_node_flags_caller(size, numa_node, GFP_KERNEL | flags,
153-
__builtin_return_address(0));
159+
return __vmalloc_node_flags_caller(size, numa_node,
160+
GFP_KERNEL | __GFP_RETRY_MAYFAIL |
161+
flags, __builtin_return_address(0));
154162
}
155163

156164
void bpf_map_area_free(void *area)

kernel/bpf/verifier.c

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,14 @@ static bool reg_may_point_to_spin_lock(const struct bpf_reg_state *reg)
352352
map_value_has_spin_lock(reg->map_ptr);
353353
}
354354

355+
static bool reg_type_may_be_refcounted_or_null(enum bpf_reg_type type)
356+
{
357+
return type == PTR_TO_SOCKET ||
358+
type == PTR_TO_SOCKET_OR_NULL ||
359+
type == PTR_TO_TCP_SOCK ||
360+
type == PTR_TO_TCP_SOCK_OR_NULL;
361+
}
362+
355363
static bool arg_type_may_be_refcounted(enum bpf_arg_type type)
356364
{
357365
return type == ARG_PTR_TO_SOCK_COMMON;
@@ -451,8 +459,9 @@ static void print_verifier_state(struct bpf_verifier_env *env,
451459
if (t == PTR_TO_STACK)
452460
verbose(env, ",call_%d", func(env, reg)->callsite);
453461
} else {
454-
verbose(env, "(id=%d ref_obj_id=%d", reg->id,
455-
reg->ref_obj_id);
462+
verbose(env, "(id=%d", reg->id);
463+
if (reg_type_may_be_refcounted_or_null(t))
464+
verbose(env, ",ref_obj_id=%d", reg->ref_obj_id);
456465
if (t != SCALAR_VALUE)
457466
verbose(env, ",off=%d", reg->off);
458467
if (type_is_pkt_pointer(t))
@@ -3372,7 +3381,7 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
33723381
*dst_reg = *ptr_reg;
33733382
}
33743383
ret = push_stack(env, env->insn_idx + 1, env->insn_idx, true);
3375-
if (!ptr_is_dst_reg)
3384+
if (!ptr_is_dst_reg && ret)
33763385
*dst_reg = tmp;
33773386
return !ret ? -EFAULT : 0;
33783387
}
@@ -6069,15 +6078,17 @@ static int propagate_liveness(struct bpf_verifier_env *env,
60696078
}
60706079
/* Propagate read liveness of registers... */
60716080
BUILD_BUG_ON(BPF_REG_FP + 1 != MAX_BPF_REG);
6072-
/* We don't need to worry about FP liveness because it's read-only */
6073-
for (i = 0; i < BPF_REG_FP; i++) {
6074-
if (vparent->frame[vparent->curframe]->regs[i].live & REG_LIVE_READ)
6075-
continue;
6076-
if (vstate->frame[vstate->curframe]->regs[i].live & REG_LIVE_READ) {
6077-
err = mark_reg_read(env, &vstate->frame[vstate->curframe]->regs[i],
6078-
&vparent->frame[vstate->curframe]->regs[i]);
6079-
if (err)
6080-
return err;
6081+
for (frame = 0; frame <= vstate->curframe; frame++) {
6082+
/* We don't need to worry about FP liveness, it's read-only */
6083+
for (i = frame < vstate->curframe ? BPF_REG_6 : 0; i < BPF_REG_FP; i++) {
6084+
if (vparent->frame[frame]->regs[i].live & REG_LIVE_READ)
6085+
continue;
6086+
if (vstate->frame[frame]->regs[i].live & REG_LIVE_READ) {
6087+
err = mark_reg_read(env, &vstate->frame[frame]->regs[i],
6088+
&vparent->frame[frame]->regs[i]);
6089+
if (err)
6090+
return err;
6091+
}
60816092
}
60826093
}
60836094

tools/lib/bpf/Makefile

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
BPF_VERSION = 0
55
BPF_PATCHLEVEL = 0
6-
BPF_EXTRAVERSION = 1
6+
BPF_EXTRAVERSION = 2
77

88
MAKEFLAGS += --no-print-directory
99

@@ -79,16 +79,17 @@ export prefix libdir src obj
7979
libdir_SQ = $(subst ','\'',$(libdir))
8080
libdir_relative_SQ = $(subst ','\'',$(libdir_relative))
8181

82-
LIB_FILE = libbpf.a libbpf.so
83-
8482
VERSION = $(BPF_VERSION)
8583
PATCHLEVEL = $(BPF_PATCHLEVEL)
8684
EXTRAVERSION = $(BPF_EXTRAVERSION)
8785

8886
OBJ = $@
8987
N =
9088

91-
LIBBPF_VERSION = $(BPF_VERSION).$(BPF_PATCHLEVEL).$(BPF_EXTRAVERSION)
89+
LIBBPF_VERSION = $(BPF_VERSION).$(BPF_PATCHLEVEL).$(BPF_EXTRAVERSION)
90+
91+
LIB_TARGET = libbpf.a libbpf.so.$(LIBBPF_VERSION)
92+
LIB_FILE = libbpf.a libbpf.so*
9293

9394
# Set compile option CFLAGS
9495
ifdef EXTRA_CFLAGS
@@ -128,16 +129,18 @@ all:
128129
export srctree OUTPUT CC LD CFLAGS V
129130
include $(srctree)/tools/build/Makefile.include
130131

131-
BPF_IN := $(OUTPUT)libbpf-in.o
132-
LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE))
133-
VERSION_SCRIPT := libbpf.map
132+
BPF_IN := $(OUTPUT)libbpf-in.o
133+
VERSION_SCRIPT := libbpf.map
134+
135+
LIB_TARGET := $(addprefix $(OUTPUT),$(LIB_TARGET))
136+
LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE))
134137

135138
GLOBAL_SYM_COUNT = $(shell readelf -s --wide $(BPF_IN) | \
136139
awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {s++} END{print s}')
137140
VERSIONED_SYM_COUNT = $(shell readelf -s --wide $(OUTPUT)libbpf.so | \
138141
grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 | sort -u | wc -l)
139142

140-
CMD_TARGETS = $(LIB_FILE)
143+
CMD_TARGETS = $(LIB_TARGET)
141144

142145
CXX_TEST_TARGET = $(OUTPUT)test_libbpf
143146

@@ -170,9 +173,13 @@ $(BPF_IN): force elfdep bpfdep
170173
echo "Warning: Kernel ABI header at 'tools/include/uapi/linux/if_xdp.h' differs from latest version at 'include/uapi/linux/if_xdp.h'" >&2 )) || true
171174
$(Q)$(MAKE) $(build)=libbpf
172175

173-
$(OUTPUT)libbpf.so: $(BPF_IN)
174-
$(QUIET_LINK)$(CC) --shared -Wl,--version-script=$(VERSION_SCRIPT) \
175-
$^ -o $@
176+
$(OUTPUT)libbpf.so: $(OUTPUT)libbpf.so.$(LIBBPF_VERSION)
177+
178+
$(OUTPUT)libbpf.so.$(LIBBPF_VERSION): $(BPF_IN)
179+
$(QUIET_LINK)$(CC) --shared -Wl,-soname,libbpf.so.$(VERSION) \
180+
-Wl,--version-script=$(VERSION_SCRIPT) $^ -o $@
181+
@ln -sf $(@F) $(OUTPUT)libbpf.so
182+
@ln -sf $(@F) $(OUTPUT)libbpf.so.$(VERSION)
176183

177184
$(OUTPUT)libbpf.a: $(BPF_IN)
178185
$(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^
@@ -192,6 +199,12 @@ check_abi: $(OUTPUT)libbpf.so
192199
exit 1; \
193200
fi
194201

202+
define do_install_mkdir
203+
if [ ! -d '$(DESTDIR_SQ)$1' ]; then \
204+
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$1'; \
205+
fi
206+
endef
207+
195208
define do_install
196209
if [ ! -d '$(DESTDIR_SQ)$2' ]; then \
197210
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \
@@ -200,8 +213,9 @@ define do_install
200213
endef
201214

202215
install_lib: all_cmd
203-
$(call QUIET_INSTALL, $(LIB_FILE)) \
204-
$(call do_install,$(LIB_FILE),$(libdir_SQ))
216+
$(call QUIET_INSTALL, $(LIB_TARGET)) \
217+
$(call do_install_mkdir,$(libdir_SQ)); \
218+
cp -fpR $(LIB_FILE) $(DESTDIR)$(libdir_SQ)
205219

206220
install_headers:
207221
$(call QUIET_INSTALL, headers) \
@@ -219,7 +233,7 @@ config-clean:
219233

220234
clean:
221235
$(call QUIET_CLEAN, libbpf) $(RM) $(TARGETS) $(CXX_TEST_TARGET) \
222-
*.o *~ *.a *.so .*.d .*.cmd LIBBPF-CFLAGS
236+
*.o *~ *.a *.so *.so.$(VERSION) .*.d .*.cmd LIBBPF-CFLAGS
223237
$(call QUIET_CLEAN, core-gen) $(RM) $(OUTPUT)FEATURE-DUMP.libbpf
224238

225239

tools/lib/bpf/README.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ starting from ``0.0.1``.
111111

112112
Every time ABI is being changed, e.g. because a new symbol is added or
113113
semantic of existing symbol is changed, ABI version should be bumped.
114+
This bump in ABI version is at most once per kernel development cycle.
114115

115116
For example, if current state of ``libbpf.map`` is:
116117

tools/testing/selftests/bpf/verifier/calls.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1940,3 +1940,28 @@
19401940
.errstr = "!read_ok",
19411941
.result = REJECT,
19421942
},
1943+
{
1944+
"calls: cross frame pruning - liveness propagation",
1945+
.insns = {
1946+
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
1947+
BPF_MOV64_IMM(BPF_REG_8, 0),
1948+
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
1949+
BPF_MOV64_IMM(BPF_REG_8, 1),
1950+
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
1951+
BPF_MOV64_IMM(BPF_REG_9, 0),
1952+
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
1953+
BPF_MOV64_IMM(BPF_REG_9, 1),
1954+
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
1955+
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 4),
1956+
BPF_JMP_IMM(BPF_JEQ, BPF_REG_8, 1, 1),
1957+
BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_2, 0),
1958+
BPF_MOV64_IMM(BPF_REG_0, 0),
1959+
BPF_EXIT_INSN(),
1960+
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 0),
1961+
BPF_EXIT_INSN(),
1962+
},
1963+
.prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
1964+
.errstr_unpriv = "function calls to other bpf functions are allowed for root only",
1965+
.errstr = "!read_ok",
1966+
.result = REJECT,
1967+
},

0 commit comments

Comments
 (0)