Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Browse files Browse the repository at this point in the history
Pull networking fixes from David Miller:

 1) GRO overflow entries are not unlinked properly, resulting in list
    poison pointers being dereferenced.

 2) Fix bridge build with ipv6 disabled, from Nikolay Aleksandrov.

 3) Direct packet access and other fixes in BPF from Daniel Borkmann.

 4) gred_change_table_def() gets passed the wrong pointer, a pointer to
    a set of unparsed attributes instead of the attribute itself. From
    Jakub Kicinski.

 5) Allow macsec device to be brought up even if it's lowerdev is down,
    from Sabrina Dubroca.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net:
  net: diag: document swapped src/dst in udp_dump_one.
  macsec: let the administrator set UP state even if lowerdev is down
  macsec: update operstate when lower device changes
  net: sched: gred: pass the right attribute to gred_change_table_def()
  ptp: drop redundant kasprintf() to create worker name
  net: bridge: remove ipv6 zero address check in mcast queries
  net: Properly unlink GRO packets on overflow.
  bpf: fix wrong helper enablement in cgroup local storage
  bpf: add bpf_jit_limit knob to restrict unpriv allocations
  bpf: make direct packet write unclone more robust
  bpf: fix leaking uninitialized memory on pop/peek helpers
  bpf: fix direct packet write into pop/peek helpers
  bpf: fix cg_skb types to hint access type in may_access_direct_pkt_data
  bpf: fix direct packet access for flow dissector progs
  bpf: disallow direct packet access for unpriv in cg_skb
  bpf: fix test suite to enable all unpriv program types
  bpf, btf: fix a missing check bug in btf_parse
  selftests/bpf: add config fragments BPF_STREAM_PARSER and XDP_SOCKETS
  bpf: devmap: fix wrong interface selection in notifier_call
  • Loading branch information
Linus Torvalds committed Oct 29, 2018
2 parents 53b3b6b + 747569b commit 9f51ae6
Show file tree
Hide file tree
Showing 18 changed files with 155 additions and 63 deletions.
8 changes: 8 additions & 0 deletions Documentation/sysctl/net.txt
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ Values :
0 - disable JIT kallsyms export (default value)
1 - enable JIT kallsyms export for privileged users only

bpf_jit_limit
-------------

This enforces a global limit for memory allocations to the BPF JIT
compiler in order to reject unprivileged JIT requests once it has
been surpassed. bpf_jit_limit contains the value of the global limit
in bytes.

dev_weight
--------------

Expand Down
20 changes: 17 additions & 3 deletions drivers/net/macsec.c
Original file line number Diff line number Diff line change
Expand Up @@ -2812,9 +2812,6 @@ static int macsec_dev_open(struct net_device *dev)
struct net_device *real_dev = macsec->real_dev;
int err;

if (!(real_dev->flags & IFF_UP))
return -ENETDOWN;

err = dev_uc_add(real_dev, dev->dev_addr);
if (err < 0)
return err;
Expand Down Expand Up @@ -3306,6 +3303,9 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
if (err < 0)
goto del_dev;

netif_stacked_transfer_operstate(real_dev, dev);
linkwatch_fire_event(dev);

macsec_generation++;

return 0;
Expand Down Expand Up @@ -3490,6 +3490,20 @@ static int macsec_notify(struct notifier_block *this, unsigned long event,
return NOTIFY_DONE;

switch (event) {
case NETDEV_DOWN:
case NETDEV_UP:
case NETDEV_CHANGE: {
struct macsec_dev *m, *n;
struct macsec_rxh_data *rxd;

rxd = macsec_data_rtnl(real_dev);
list_for_each_entry_safe(m, n, &rxd->secys, secys) {
struct net_device *dev = m->secy.netdev;

netif_stacked_transfer_operstate(real_dev, dev);
}
break;
}
case NETDEV_UNREGISTER: {
struct macsec_dev *m, *n;
struct macsec_rxh_data *rxd;
Expand Down
6 changes: 1 addition & 5 deletions drivers/ptp/ptp_clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,8 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
init_waitqueue_head(&ptp->tsev_wq);

if (ptp->info->do_aux_work) {
char *worker_name = kasprintf(GFP_KERNEL, "ptp%d", ptp->index);

kthread_init_delayed_work(&ptp->aux_work, ptp_aux_kworker);
ptp->kworker = kthread_create_worker(0, worker_name ?
worker_name : info->name);
kfree(worker_name);
ptp->kworker = kthread_create_worker(0, "ptp%d", ptp->index);
if (IS_ERR(ptp->kworker)) {
err = PTR_ERR(ptp->kworker);
pr_err("failed to create ptp aux_worker %d\n", err);
Expand Down
1 change: 1 addition & 0 deletions include/linux/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,7 @@ bpf_run_sk_reuseport(struct sock_reuseport *reuse, struct sock *sk,
extern int bpf_jit_enable;
extern int bpf_jit_harden;
extern int bpf_jit_kallsyms;
extern int bpf_jit_limit;

typedef void (*bpf_jit_fill_hole_t)(void *area, unsigned int size);

Expand Down
58 changes: 25 additions & 33 deletions kernel/bpf/btf.c
Original file line number Diff line number Diff line change
Expand Up @@ -2067,56 +2067,47 @@ static int btf_check_sec_info(struct btf_verifier_env *env,
return 0;
}

static int btf_parse_hdr(struct btf_verifier_env *env, void __user *btf_data,
u32 btf_data_size)
static int btf_parse_hdr(struct btf_verifier_env *env)
{
u32 hdr_len, hdr_copy, btf_data_size;
const struct btf_header *hdr;
u32 hdr_len, hdr_copy;
/*
* Minimal part of the "struct btf_header" that
* contains the hdr_len.
*/
struct btf_min_header {
u16 magic;
u8 version;
u8 flags;
u32 hdr_len;
} __user *min_hdr;
struct btf *btf;
int err;

btf = env->btf;
min_hdr = btf_data;
btf_data_size = btf->data_size;

if (btf_data_size < sizeof(*min_hdr)) {
if (btf_data_size <
offsetof(struct btf_header, hdr_len) + sizeof(hdr->hdr_len)) {
btf_verifier_log(env, "hdr_len not found");
return -EINVAL;
}

if (get_user(hdr_len, &min_hdr->hdr_len))
return -EFAULT;

hdr = btf->data;
hdr_len = hdr->hdr_len;
if (btf_data_size < hdr_len) {
btf_verifier_log(env, "btf_header not found");
return -EINVAL;
}

err = bpf_check_uarg_tail_zero(btf_data, sizeof(btf->hdr), hdr_len);
if (err) {
if (err == -E2BIG)
btf_verifier_log(env, "Unsupported btf_header");
return err;
/* Ensure the unsupported header fields are zero */
if (hdr_len > sizeof(btf->hdr)) {
u8 *expected_zero = btf->data + sizeof(btf->hdr);
u8 *end = btf->data + hdr_len;

for (; expected_zero < end; expected_zero++) {
if (*expected_zero) {
btf_verifier_log(env, "Unsupported btf_header");
return -E2BIG;
}
}
}

hdr_copy = min_t(u32, hdr_len, sizeof(btf->hdr));
if (copy_from_user(&btf->hdr, btf_data, hdr_copy))
return -EFAULT;
memcpy(&btf->hdr, btf->data, hdr_copy);

hdr = &btf->hdr;

if (hdr->hdr_len != hdr_len)
return -EINVAL;

btf_verifier_log_hdr(env, btf_data_size);

if (hdr->magic != BTF_MAGIC) {
Expand Down Expand Up @@ -2186,10 +2177,6 @@ static struct btf *btf_parse(void __user *btf_data, u32 btf_data_size,
}
env->btf = btf;

err = btf_parse_hdr(env, btf_data, btf_data_size);
if (err)
goto errout;

data = kvmalloc(btf_data_size, GFP_KERNEL | __GFP_NOWARN);
if (!data) {
err = -ENOMEM;
Expand All @@ -2198,13 +2185,18 @@ static struct btf *btf_parse(void __user *btf_data, u32 btf_data_size,

btf->data = data;
btf->data_size = btf_data_size;
btf->nohdr_data = btf->data + btf->hdr.hdr_len;

if (copy_from_user(data, btf_data, btf_data_size)) {
err = -EFAULT;
goto errout;
}

err = btf_parse_hdr(env);
if (err)
goto errout;

btf->nohdr_data = btf->data + btf->hdr.hdr_len;

err = btf_parse_str_sec(env);
if (err)
goto errout;
Expand Down
49 changes: 46 additions & 3 deletions kernel/bpf/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -365,10 +365,13 @@ void bpf_prog_kallsyms_del_all(struct bpf_prog *fp)
}

#ifdef CONFIG_BPF_JIT
# define BPF_JIT_LIMIT_DEFAULT (PAGE_SIZE * 40000)

/* All BPF JIT sysctl knobs here. */
int bpf_jit_enable __read_mostly = IS_BUILTIN(CONFIG_BPF_JIT_ALWAYS_ON);
int bpf_jit_harden __read_mostly;
int bpf_jit_kallsyms __read_mostly;
int bpf_jit_limit __read_mostly = BPF_JIT_LIMIT_DEFAULT;

static __always_inline void
bpf_get_prog_addr_region(const struct bpf_prog *prog,
Expand Down Expand Up @@ -577,27 +580,64 @@ int bpf_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
return ret;
}

static atomic_long_t bpf_jit_current;

#if defined(MODULES_VADDR)
static int __init bpf_jit_charge_init(void)
{
/* Only used as heuristic here to derive limit. */
bpf_jit_limit = min_t(u64, round_up((MODULES_END - MODULES_VADDR) >> 2,
PAGE_SIZE), INT_MAX);
return 0;
}
pure_initcall(bpf_jit_charge_init);
#endif

static int bpf_jit_charge_modmem(u32 pages)
{
if (atomic_long_add_return(pages, &bpf_jit_current) >
(bpf_jit_limit >> PAGE_SHIFT)) {
if (!capable(CAP_SYS_ADMIN)) {
atomic_long_sub(pages, &bpf_jit_current);
return -EPERM;
}
}

return 0;
}

static void bpf_jit_uncharge_modmem(u32 pages)
{
atomic_long_sub(pages, &bpf_jit_current);
}

struct bpf_binary_header *
bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr,
unsigned int alignment,
bpf_jit_fill_hole_t bpf_fill_ill_insns)
{
struct bpf_binary_header *hdr;
unsigned int size, hole, start;
u32 size, hole, start, pages;

/* Most of BPF filters are really small, but if some of them
* fill a page, allow at least 128 extra bytes to insert a
* random section of illegal instructions.
*/
size = round_up(proglen + sizeof(*hdr) + 128, PAGE_SIZE);
pages = size / PAGE_SIZE;

if (bpf_jit_charge_modmem(pages))
return NULL;
hdr = module_alloc(size);
if (hdr == NULL)
if (!hdr) {
bpf_jit_uncharge_modmem(pages);
return NULL;
}

/* Fill space with illegal/arch-dep instructions. */
bpf_fill_ill_insns(hdr, size);

hdr->pages = size / PAGE_SIZE;
hdr->pages = pages;
hole = min_t(unsigned int, size - (proglen + sizeof(*hdr)),
PAGE_SIZE - sizeof(*hdr));
start = (get_random_int() % hole) & ~(alignment - 1);
Expand All @@ -610,7 +650,10 @@ bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr,

void bpf_jit_binary_free(struct bpf_binary_header *hdr)
{
u32 pages = hdr->pages;

module_memfree(hdr);
bpf_jit_uncharge_modmem(pages);
}

/* This symbol is only overridden by archs that have different
Expand Down
3 changes: 1 addition & 2 deletions kernel/bpf/devmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,8 +512,7 @@ static int dev_map_notification(struct notifier_block *notifier,
struct bpf_dtab_netdev *dev, *odev;

dev = READ_ONCE(dtab->netdev_map[i]);
if (!dev ||
dev->dev->ifindex != netdev->ifindex)
if (!dev || netdev != dev->dev)
continue;
odev = cmpxchg(&dtab->netdev_map[i], dev, NULL);
if (dev == odev)
Expand Down
2 changes: 0 additions & 2 deletions kernel/bpf/helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ BPF_CALL_2(bpf_map_pop_elem, struct bpf_map *, map, void *, value)
const struct bpf_func_proto bpf_map_pop_elem_proto = {
.func = bpf_map_pop_elem,
.gpl_only = false,
.pkt_access = true,
.ret_type = RET_INTEGER,
.arg1_type = ARG_CONST_MAP_PTR,
.arg2_type = ARG_PTR_TO_UNINIT_MAP_VALUE,
Expand All @@ -113,7 +112,6 @@ BPF_CALL_2(bpf_map_peek_elem, struct bpf_map *, map, void *, value)
const struct bpf_func_proto bpf_map_peek_elem_proto = {
.func = bpf_map_pop_elem,
.gpl_only = false,
.pkt_access = true,
.ret_type = RET_INTEGER,
.arg1_type = ARG_CONST_MAP_PTR,
.arg2_type = ARG_PTR_TO_UNINIT_MAP_VALUE,
Expand Down
2 changes: 2 additions & 0 deletions kernel/bpf/queue_stack_maps.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ static int __queue_map_get(struct bpf_map *map, void *value, bool delete)
raw_spin_lock_irqsave(&qs->lock, flags);

if (queue_stack_map_is_empty(qs)) {
memset(value, 0, qs->map.value_size);
err = -ENOENT;
goto out;
}
Expand Down Expand Up @@ -151,6 +152,7 @@ static int __stack_map_get(struct bpf_map *map, void *value, bool delete)
raw_spin_lock_irqsave(&qs->lock, flags);

if (queue_stack_map_is_empty(qs)) {
memset(value, 0, qs->map.value_size);
err = -ENOENT;
goto out;
}
Expand Down
13 changes: 10 additions & 3 deletions kernel/bpf/verifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -1387,21 +1387,24 @@ static bool may_access_direct_pkt_data(struct bpf_verifier_env *env,
enum bpf_access_type t)
{
switch (env->prog->type) {
/* Program types only with direct read access go here! */
case BPF_PROG_TYPE_LWT_IN:
case BPF_PROG_TYPE_LWT_OUT:
case BPF_PROG_TYPE_LWT_SEG6LOCAL:
case BPF_PROG_TYPE_SK_REUSEPORT:
/* dst_input() and dst_output() can't write for now */
case BPF_PROG_TYPE_FLOW_DISSECTOR:
case BPF_PROG_TYPE_CGROUP_SKB:
if (t == BPF_WRITE)
return false;
/* fallthrough */

/* Program types with direct read + write access go here! */
case BPF_PROG_TYPE_SCHED_CLS:
case BPF_PROG_TYPE_SCHED_ACT:
case BPF_PROG_TYPE_XDP:
case BPF_PROG_TYPE_LWT_XMIT:
case BPF_PROG_TYPE_SK_SKB:
case BPF_PROG_TYPE_SK_MSG:
case BPF_PROG_TYPE_FLOW_DISSECTOR:
if (meta)
return meta->pkt_access;

Expand Down Expand Up @@ -5706,7 +5709,11 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
bool is_narrower_load;
u32 target_size;

if (ops->gen_prologue) {
if (ops->gen_prologue || env->seen_direct_write) {
if (!ops->gen_prologue) {
verbose(env, "bpf verifier is misconfigured\n");
return -EINVAL;
}
cnt = ops->gen_prologue(insn_buf, env->seen_direct_write,
env->prog);
if (cnt >= ARRAY_SIZE(insn_buf)) {
Expand Down
3 changes: 1 addition & 2 deletions net/bridge/br_multicast.c
Original file line number Diff line number Diff line change
Expand Up @@ -1428,8 +1428,7 @@ static void br_multicast_query_received(struct net_bridge *br,
* is 0.0.0.0 should not be added to router port list.
*/
if ((saddr->proto == htons(ETH_P_IP) && saddr->u.ip4) ||
(saddr->proto == htons(ETH_P_IPV6) &&
!ipv6_addr_any(&saddr->u.ip6)))
saddr->proto == htons(ETH_P_IPV6))
br_multicast_mark_router(br, port);
}

Expand Down
2 changes: 1 addition & 1 deletion net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -5457,7 +5457,7 @@ static void gro_flush_oldest(struct list_head *head)
/* Do not adjust napi->gro_hash[].count, caller is adding a new
* SKB to the chain.
*/
list_del(&oldest->list);
skb_list_del_init(oldest);
napi_gro_complete(oldest);
}

Expand Down
Loading

0 comments on commit 9f51ae6

Please sign in to comment.