This is a note to let you know that I've just added the patch titled
usb: misc: usb3503: make sure reset is low for at least 100us
to the 3.18-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=sum…
The filename of the patch is:
usb-misc-usb3503-make-sure-reset-is-low-for-at-least-100us.patch
and it can be found in the queue-3.18 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <stable(a)vger.kernel.org> know about it.
>From b8626f1dc29d3eee444bfaa92146ec7b291ef41c Mon Sep 17 00:00:00 2001
From: Stefan Agner <stefan(a)agner.ch>
Date: Thu, 11 Jan 2018 14:47:40 +0100
Subject: usb: misc: usb3503: make sure reset is low for at least 100us
From: Stefan Agner <stefan(a)agner.ch>
commit b8626f1dc29d3eee444bfaa92146ec7b291ef41c upstream.
When using a GPIO which is high by default, and initialize the
driver in USB Hub mode, initialization fails with:
[ 111.757794] usb3503 0-0008: SP_ILOCK failed (-5)
The reason seems to be that the chip is not properly reset.
Probe does initialize reset low, however some lines later the
code already set it back high, which is not long enouth.
Make sure reset is asserted for at least 100us by inserting a
delay after initializing the reset pin during probe.
Signed-off-by: Stefan Agner <stefan(a)agner.ch>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
---
drivers/usb/misc/usb3503.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -291,6 +291,8 @@ static int usb3503_probe(struct usb3503
if (gpio_is_valid(hub->gpio_reset)) {
err = devm_gpio_request_one(dev, hub->gpio_reset,
GPIOF_OUT_INIT_LOW, "usb3503 reset");
+ /* Datasheet defines a hardware reset to be at least 100us */
+ usleep_range(100, 10000);
if (err) {
dev_err(dev,
"unable to request GPIO %d as reset pin (%d)\n",
Patches currently in stable-queue which might be from stefan(a)agner.ch are
queue-3.18/usb-misc-usb3503-make-sure-reset-is-low-for-at-least-100us.patch
This is a note to let you know that I've just added the patch titled
USB: serial: cp210x: add new device ID ELV ALC 8xxx
to the 3.18-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=sum…
The filename of the patch is:
usb-serial-cp210x-add-new-device-id-elv-alc-8xxx.patch
and it can be found in the queue-3.18 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <stable(a)vger.kernel.org> know about it.
>From d14ac576d10f865970bb1324d337e5e24d79aaf4 Mon Sep 17 00:00:00 2001
From: Christian Holl <cyborgx1(a)gmail.com>
Date: Wed, 3 Jan 2018 19:53:02 +0100
Subject: USB: serial: cp210x: add new device ID ELV ALC 8xxx
From: Christian Holl <cyborgx1(a)gmail.com>
commit d14ac576d10f865970bb1324d337e5e24d79aaf4 upstream.
This adds the ELV ALC 8xxx Battery Charging device
to the list of USB IDs of drivers/usb/serial/cp210x.c
Signed-off-by: Christian Holl <cyborgx1(a)gmail.com>
Signed-off-by: Johan Hovold <johan(a)kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
---
drivers/usb/serial/cp210x.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -169,6 +169,7 @@ static const struct usb_device_id id_tab
{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
{ USB_DEVICE(0x18EF, 0xE025) }, /* ELV Marble Sound Board 1 */
+ { USB_DEVICE(0x18EF, 0xE030) }, /* ELV ALC 8xxx Battery Charger */
{ USB_DEVICE(0x18EF, 0xE032) }, /* ELV TFD500 Data Logger */
{ USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */
{ USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */
Patches currently in stable-queue which might be from cyborgx1(a)gmail.com are
queue-3.18/usb-serial-cp210x-add-new-device-id-elv-alc-8xxx.patch
This is a note to let you know that I've just added the patch titled
USB: serial: cp210x: add IDs for LifeScan OneTouch Verio IQ
to the 3.18-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=sum…
The filename of the patch is:
usb-serial-cp210x-add-ids-for-lifescan-onetouch-verio-iq.patch
and it can be found in the queue-3.18 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <stable(a)vger.kernel.org> know about it.
>From 4307413256ac1e09b8f53e8715af3df9e49beec3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Diego=20Elio=20Petten=C3=B2?= <flameeyes(a)flameeyes.eu>
Date: Fri, 29 Dec 2017 09:54:25 +0000
Subject: USB: serial: cp210x: add IDs for LifeScan OneTouch Verio IQ
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
From: Diego Elio Pettenò <flameeyes(a)flameeyes.eu>
commit 4307413256ac1e09b8f53e8715af3df9e49beec3 upstream.
Add IDs for the OneTouch Verio IQ that comes with an embedded
USB-to-serial converter.
Signed-off-by: Diego Elio Pettenò <flameeyes(a)flameeyes.eu>
Signed-off-by: Johan Hovold <johan(a)kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
---
drivers/usb/serial/cp210x.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -119,6 +119,7 @@ static const struct usb_device_id id_tab
{ USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
{ USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */
{ USB_DEVICE(0x10C4, 0x84B6) }, /* Starizona Hyperion */
+ { USB_DEVICE(0x10C4, 0x85A7) }, /* LifeScan OneTouch Verio IQ */
{ USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */
{ USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */
{ USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */
Patches currently in stable-queue which might be from flameeyes(a)flameeyes.eu are
queue-3.18/usb-serial-cp210x-add-ids-for-lifescan-onetouch-verio-iq.patch
This is a note to let you know that I've just added the patch titled
USB: fix usbmon BUG trigger
to the 3.18-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=sum…
The filename of the patch is:
usb-fix-usbmon-bug-trigger.patch
and it can be found in the queue-3.18 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <stable(a)vger.kernel.org> know about it.
>From 46eb14a6e1585d99c1b9f58d0e7389082a5f466b Mon Sep 17 00:00:00 2001
From: Pete Zaitcev <zaitcev(a)redhat.com>
Date: Mon, 8 Jan 2018 15:46:41 -0600
Subject: USB: fix usbmon BUG trigger
From: Pete Zaitcev <zaitcev(a)redhat.com>
commit 46eb14a6e1585d99c1b9f58d0e7389082a5f466b upstream.
Automated tests triggered this by opening usbmon and accessing the
mmap while simultaneously resizing the buffers. This bug was with
us since 2006, because typically applications only size the buffers
once and thus avoid racing. Reported by Kirill A. Shutemov.
Reported-by: <syzbot+f9831b881b3e849829fc(a)syzkaller.appspotmail.com>
Signed-off-by: Pete Zaitcev <zaitcev(a)redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
---
drivers/usb/mon/mon_bin.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -1000,7 +1000,9 @@ static long mon_bin_ioctl(struct file *f
break;
case MON_IOCQ_RING_SIZE:
+ mutex_lock(&rp->fetch_lock);
ret = rp->b_size;
+ mutex_unlock(&rp->fetch_lock);
break;
case MON_IOCT_RING_SIZE:
@@ -1227,12 +1229,16 @@ static int mon_bin_vma_fault(struct vm_a
unsigned long offset, chunk_idx;
struct page *pageptr;
+ mutex_lock(&rp->fetch_lock);
offset = vmf->pgoff << PAGE_SHIFT;
- if (offset >= rp->b_size)
+ if (offset >= rp->b_size) {
+ mutex_unlock(&rp->fetch_lock);
return VM_FAULT_SIGBUS;
+ }
chunk_idx = offset / CHUNK_SIZE;
pageptr = rp->b_vec[chunk_idx].pg;
get_page(pageptr);
+ mutex_unlock(&rp->fetch_lock);
vmf->page = pageptr;
return 0;
}
Patches currently in stable-queue which might be from zaitcev(a)redhat.com are
queue-3.18/usb-fix-usbmon-bug-trigger.patch
This is a note to let you know that I've just added the patch titled
staging: android: ashmem: fix a race condition in ASHMEM_SET_SIZE ioctl
to the 3.18-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=sum…
The filename of the patch is:
staging-android-ashmem-fix-a-race-condition-in-ashmem_set_size-ioctl.patch
and it can be found in the queue-3.18 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <stable(a)vger.kernel.org> know about it.
>From 443064cb0b1fb4569fe0a71209da7625129fb760 Mon Sep 17 00:00:00 2001
From: Viktor Slavkovic <viktors(a)google.com>
Date: Mon, 8 Jan 2018 10:43:03 -0800
Subject: staging: android: ashmem: fix a race condition in ASHMEM_SET_SIZE ioctl
From: Viktor Slavkovic <viktors(a)google.com>
commit 443064cb0b1fb4569fe0a71209da7625129fb760 upstream.
A lock-unlock is missing in ASHMEM_SET_SIZE ioctl which can result in a
race condition when mmap is called. After the !asma->file check, before
setting asma->size, asma->file can be set in mmap. That would result in
having different asma->size than the mapped memory size. Combined with
ASHMEM_UNPIN ioctl and shrinker invocation, this can result in memory
corruption.
Signed-off-by: Viktor Slavkovic <viktors(a)google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
---
drivers/staging/android/ashmem.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/staging/android/ashmem.c
+++ b/drivers/staging/android/ashmem.c
@@ -759,10 +759,12 @@ static long ashmem_ioctl(struct file *fi
break;
case ASHMEM_SET_SIZE:
ret = -EINVAL;
+ mutex_lock(&ashmem_mutex);
if (!asma->file) {
ret = 0;
asma->size = (size_t) arg;
}
+ mutex_unlock(&ashmem_mutex);
break;
case ASHMEM_GET_SIZE:
ret = asma->size;
Patches currently in stable-queue which might be from viktors(a)google.com are
queue-3.18/staging-android-ashmem-fix-a-race-condition-in-ashmem_set_size-ioctl.patch
The patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable(a)vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
>From 7ae2c3c280db183ca9ada2675c34ec2f7378abfa Mon Sep 17 00:00:00 2001
From: Alan Stern <stern(a)rowland.harvard.edu>
Date: Wed, 3 Jan 2018 12:51:51 -0500
Subject: [PATCH] USB: UDC core: fix double-free in usb_add_gadget_udc_release
The error-handling pathways in usb_add_gadget_udc_release() are messed
up. Aside from the uninformative statement labels, they can deallocate
the udc structure after calling put_device(), which is a double-free.
This was observed by KASAN in automatic testing.
This patch cleans up the routine. It preserves the requirement that
when any failure occurs, we call put_device(&gadget->dev).
Signed-off-by: Alan Stern <stern(a)rowland.harvard.edu>
Reported-by: Fengguang Wu <fengguang.wu(a)intel.com>
CC: <stable(a)vger.kernel.org>
Reviewed-by: Peter Chen <peter.chen(a)nxp.com>
Acked-by: Felipe Balbi <felipe.balbi(a)linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index 93eff7dec2f5..1b3efb14aec7 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -1147,11 +1147,7 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
udc = kzalloc(sizeof(*udc), GFP_KERNEL);
if (!udc)
- goto err1;
-
- ret = device_add(&gadget->dev);
- if (ret)
- goto err2;
+ goto err_put_gadget;
device_initialize(&udc->dev);
udc->dev.release = usb_udc_release;
@@ -1160,7 +1156,11 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
udc->dev.parent = parent;
ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
if (ret)
- goto err3;
+ goto err_put_udc;
+
+ ret = device_add(&gadget->dev);
+ if (ret)
+ goto err_put_udc;
udc->gadget = gadget;
gadget->udc = udc;
@@ -1170,7 +1170,7 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
ret = device_add(&udc->dev);
if (ret)
- goto err4;
+ goto err_unlist_udc;
usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
udc->vbus = true;
@@ -1178,27 +1178,25 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
/* pick up one of pending gadget drivers */
ret = check_pending_gadget_drivers(udc);
if (ret)
- goto err5;
+ goto err_del_udc;
mutex_unlock(&udc_lock);
return 0;
-err5:
+ err_del_udc:
device_del(&udc->dev);
-err4:
+ err_unlist_udc:
list_del(&udc->list);
mutex_unlock(&udc_lock);
-err3:
- put_device(&udc->dev);
device_del(&gadget->dev);
-err2:
- kfree(udc);
+ err_put_udc:
+ put_device(&udc->dev);
-err1:
+ err_put_gadget:
put_device(&gadget->dev);
return ret;
}
Hi,
Fedora got a bug report on 4.14.11 of a panic when booting a
Fedora guest in a CentOS 6 VM, not reproducible with nopti.
The issue is still present as of 4.14.13 as well. The only
report is a panic screenshot
https://bugzilla.redhat.com/show_bug.cgi?id=1532458
I've lost track of all the fixes that have been flying around,
is this a new issue or has a fix not yet made it to stable?
Thanks,
Laura
Hi,
this is a backport of these patches which I did for our kernels:
c237ee5eb33b bpf: add bpf_patch_insn_single helper
3df126f35f88 bpf: don't (ab)use instructions to store state
e245c5c6a565 bpf: move fixup_bpf_calls() function
79741b3bdec0 bpf: refactor fixup_bpf_calls()
8041902dae52 bpf: adjust insn_aux_data when patching insns
b2157399cc98 bpf: prevent out-of-bounds speculation
I offer it here for use in stable 4.4, if there is no better/simpler
backport available yet.
Alexei Starovoitov (4):
bpf: move fixup_bpf_calls() function
bpf: refactor fixup_bpf_calls()
bpf: adjust insn_aux_data when patching insns
bpf: prevent out-of-bounds speculation
Daniel Borkmann (1):
bpf: add bpf_patch_insn_single helper
Jakub Kicinski (1):
bpf: don't (ab)use instructions to store state
include/linux/bpf.h | 2 +
include/linux/filter.h | 3 +
kernel/bpf/arraymap.c | 24 ++++--
kernel/bpf/core.c | 71 ++++++++++++++++
kernel/bpf/syscall.c | 54 ------------
kernel/bpf/verifier.c | 217 +++++++++++++++++++++++++++++++++++--------------
6 files changed, 252 insertions(+), 119 deletions(-)
--
2.15.1
This is a note to let you know that I've just added the patch titled
bpf: prevent out-of-bounds speculation
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=sum…
The filename of the patch is:
bpf-prevent-out-of-bounds-speculation.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <stable(a)vger.kernel.org> know about it.
>From b2157399cc9898260d6031c5bfe45fe137c1fbe7 Mon Sep 17 00:00:00 2001
From: Alexei Starovoitov <ast(a)kernel.org>
Date: Sun, 7 Jan 2018 17:33:02 -0800
Subject: bpf: prevent out-of-bounds speculation
From: Alexei Starovoitov <ast(a)kernel.org>
commit b2157399cc9898260d6031c5bfe45fe137c1fbe7 upstream.
Under speculation, CPUs may mis-predict branches in bounds checks. Thus,
memory accesses under a bounds check may be speculated even if the
bounds check fails, providing a primitive for building a side channel.
To avoid leaking kernel data round up array-based maps and mask the index
after bounds check, so speculated load with out of bounds index will load
either valid value from the array or zero from the padded area.
Unconditionally mask index for all array types even when max_entries
are not rounded to power of 2 for root user.
When map is created by unpriv user generate a sequence of bpf insns
that includes AND operation to make sure that JITed code includes
the same 'index & index_mask' operation.
If prog_array map is created by unpriv user replace
bpf_tail_call(ctx, map, index);
with
if (index >= max_entries) {
index &= map->index_mask;
bpf_tail_call(ctx, map, index);
}
(along with roundup to power 2) to prevent out-of-bounds speculation.
There is secondary redundant 'if (index >= max_entries)' in the interpreter
and in all JITs, but they can be optimized later if necessary.
Other array-like maps (cpumap, devmap, sockmap, perf_event_array, cgroup_array)
cannot be used by unpriv, so no changes there.
That fixes bpf side of "Variant 1: bounds check bypass (CVE-2017-5753)" on
all architectures with and without JIT.
v2->v3:
Daniel noticed that attack potentially can be crafted via syscall commands
without loading the program, so add masking to those paths as well.
Signed-off-by: Alexei Starovoitov <ast(a)kernel.org>
Acked-by: John Fastabend <john.fastabend(a)gmail.com>
Signed-off-by: Daniel Borkmann <daniel(a)iogearbox.net>
Cc: Jiri Slaby <jslaby(a)suse.cz>
[ Backported to 4.9 - gregkh ]
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
---
include/linux/bpf.h | 2 ++
include/linux/bpf_verifier.h | 5 ++++-
kernel/bpf/arraymap.c | 31 ++++++++++++++++++++++---------
kernel/bpf/verifier.c | 42 +++++++++++++++++++++++++++++++++++++++---
4 files changed, 67 insertions(+), 13 deletions(-)
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -43,6 +43,7 @@ struct bpf_map {
u32 max_entries;
u32 map_flags;
u32 pages;
+ bool unpriv_array;
struct user_struct *user;
const struct bpf_map_ops *ops;
struct work_struct work;
@@ -189,6 +190,7 @@ struct bpf_prog_aux {
struct bpf_array {
struct bpf_map map;
u32 elem_size;
+ u32 index_mask;
/* 'ownership' of prog_array is claimed by the first program that
* is going to use this map or by the first program which FD is stored
* in the map to make sure that all callers and callees have the same
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -67,7 +67,10 @@ struct bpf_verifier_state_list {
};
struct bpf_insn_aux_data {
- enum bpf_reg_type ptr_type; /* pointer type for load/store insns */
+ union {
+ enum bpf_reg_type ptr_type; /* pointer type for load/store insns */
+ struct bpf_map *map_ptr; /* pointer for call insn into lookup_elem */
+ };
bool seen; /* this insn was processed by the verifier */
};
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -46,9 +46,10 @@ static int bpf_array_alloc_percpu(struct
static struct bpf_map *array_map_alloc(union bpf_attr *attr)
{
bool percpu = attr->map_type == BPF_MAP_TYPE_PERCPU_ARRAY;
+ u32 elem_size, index_mask, max_entries;
+ bool unpriv = !capable(CAP_SYS_ADMIN);
struct bpf_array *array;
u64 array_size;
- u32 elem_size;
/* check sanity of attributes */
if (attr->max_entries == 0 || attr->key_size != 4 ||
@@ -63,11 +64,20 @@ static struct bpf_map *array_map_alloc(u
elem_size = round_up(attr->value_size, 8);
+ max_entries = attr->max_entries;
+ index_mask = roundup_pow_of_two(max_entries) - 1;
+
+ if (unpriv)
+ /* round up array size to nearest power of 2,
+ * since cpu will speculate within index_mask limits
+ */
+ max_entries = index_mask + 1;
+
array_size = sizeof(*array);
if (percpu)
- array_size += (u64) attr->max_entries * sizeof(void *);
+ array_size += (u64) max_entries * sizeof(void *);
else
- array_size += (u64) attr->max_entries * elem_size;
+ array_size += (u64) max_entries * elem_size;
/* make sure there is no u32 overflow later in round_up() */
if (array_size >= U32_MAX - PAGE_SIZE)
@@ -77,6 +87,8 @@ static struct bpf_map *array_map_alloc(u
array = bpf_map_area_alloc(array_size);
if (!array)
return ERR_PTR(-ENOMEM);
+ array->index_mask = index_mask;
+ array->map.unpriv_array = unpriv;
/* copy mandatory map attributes */
array->map.map_type = attr->map_type;
@@ -110,7 +122,7 @@ static void *array_map_lookup_elem(struc
if (unlikely(index >= array->map.max_entries))
return NULL;
- return array->value + array->elem_size * index;
+ return array->value + array->elem_size * (index & array->index_mask);
}
/* Called from eBPF program */
@@ -122,7 +134,7 @@ static void *percpu_array_map_lookup_ele
if (unlikely(index >= array->map.max_entries))
return NULL;
- return this_cpu_ptr(array->pptrs[index]);
+ return this_cpu_ptr(array->pptrs[index & array->index_mask]);
}
int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value)
@@ -142,7 +154,7 @@ int bpf_percpu_array_copy(struct bpf_map
*/
size = round_up(map->value_size, 8);
rcu_read_lock();
- pptr = array->pptrs[index];
+ pptr = array->pptrs[index & array->index_mask];
for_each_possible_cpu(cpu) {
bpf_long_memcpy(value + off, per_cpu_ptr(pptr, cpu), size);
off += size;
@@ -190,10 +202,11 @@ static int array_map_update_elem(struct
return -EEXIST;
if (array->map.map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
- memcpy(this_cpu_ptr(array->pptrs[index]),
+ memcpy(this_cpu_ptr(array->pptrs[index & array->index_mask]),
value, map->value_size);
else
- memcpy(array->value + array->elem_size * index,
+ memcpy(array->value +
+ array->elem_size * (index & array->index_mask),
value, map->value_size);
return 0;
}
@@ -227,7 +240,7 @@ int bpf_percpu_array_update(struct bpf_m
*/
size = round_up(map->value_size, 8);
rcu_read_lock();
- pptr = array->pptrs[index];
+ pptr = array->pptrs[index & array->index_mask];
for_each_possible_cpu(cpu) {
bpf_long_memcpy(per_cpu_ptr(pptr, cpu), value + off, size);
off += size;
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1187,7 +1187,7 @@ static void clear_all_pkt_pointers(struc
}
}
-static int check_call(struct bpf_verifier_env *env, int func_id)
+static int check_call(struct bpf_verifier_env *env, int func_id, int insn_idx)
{
struct bpf_verifier_state *state = &env->cur_state;
const struct bpf_func_proto *fn = NULL;
@@ -1238,6 +1238,13 @@ static int check_call(struct bpf_verifie
err = check_func_arg(env, BPF_REG_2, fn->arg2_type, &meta);
if (err)
return err;
+ if (func_id == BPF_FUNC_tail_call) {
+ if (meta.map_ptr == NULL) {
+ verbose("verifier bug\n");
+ return -EINVAL;
+ }
+ env->insn_aux_data[insn_idx].map_ptr = meta.map_ptr;
+ }
err = check_func_arg(env, BPF_REG_3, fn->arg3_type, &meta);
if (err)
return err;
@@ -3019,7 +3026,7 @@ static int do_check(struct bpf_verifier_
return -EINVAL;
}
- err = check_call(env, insn->imm);
+ err = check_call(env, insn->imm, insn_idx);
if (err)
return err;
@@ -3372,7 +3379,11 @@ static int fixup_bpf_calls(struct bpf_ve
struct bpf_insn *insn = prog->insnsi;
const struct bpf_func_proto *fn;
const int insn_cnt = prog->len;
- int i;
+ struct bpf_insn insn_buf[16];
+ struct bpf_prog *new_prog;
+ struct bpf_map *map_ptr;
+ int i, cnt, delta = 0;
+
for (i = 0; i < insn_cnt; i++, insn++) {
if (insn->code != (BPF_JMP | BPF_CALL))
@@ -3390,6 +3401,31 @@ static int fixup_bpf_calls(struct bpf_ve
*/
insn->imm = 0;
insn->code |= BPF_X;
+
+ /* instead of changing every JIT dealing with tail_call
+ * emit two extra insns:
+ * if (index >= max_entries) goto out;
+ * index &= array->index_mask;
+ * to avoid out-of-bounds cpu speculation
+ */
+ map_ptr = env->insn_aux_data[i + delta].map_ptr;
+ if (!map_ptr->unpriv_array)
+ continue;
+ insn_buf[0] = BPF_JMP_IMM(BPF_JGE, BPF_REG_3,
+ map_ptr->max_entries, 2);
+ insn_buf[1] = BPF_ALU32_IMM(BPF_AND, BPF_REG_3,
+ container_of(map_ptr,
+ struct bpf_array,
+ map)->index_mask);
+ insn_buf[2] = *insn;
+ cnt = 3;
+ new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
+ if (!new_prog)
+ return -ENOMEM;
+
+ delta += cnt - 1;
+ env->prog = prog = new_prog;
+ insn = new_prog->insnsi + i + delta;
continue;
}
Patches currently in stable-queue which might be from ast(a)kernel.org are
queue-4.9/bpf-refactor-fixup_bpf_calls.patch
queue-4.9/bpf-array-fix-overflow-in-max_entries-and-undefined-behavior-in-index_mask.patch
queue-4.9/bpf-prevent-out-of-bounds-speculation.patch
queue-4.9/bpf-move-fixup_bpf_calls-function.patch