This series backports bugfixes already merged in linux upstream
which we found these issues in our commerical products, which
are serious and should be fixed immediately.
Note that it also includes some xarray modification since
upcoming patches heavily needs it, which can reduce more
conflicts later.
All patches have been tested again as a whole.
Thanks,
Gao Xiang
Chen Gong (1):
staging: erofs: replace BUG_ON with DBG_BUGON in data.c
Gao Xiang (11):
staging: erofs: fix a bug when appling cache strategy
staging: erofs: complete error handing of z_erofs_do_read_page
staging: erofs: drop multiref support temporarily
staging: erofs: remove the redundant d_rehash() for the root dentry
staging: erofs: fix race when the managed cache is enabled
staging: erofs: atomic_cond_read_relaxed on ref-locked workgroup
staging: erofs: fix `erofs_workgroup_{try_to_freeze, unfreeze}'
staging: erofs: add a full barrier in erofs_workgroup_unfreeze
staging: erofs: {dir,inode,super}.c: rectify BUG_ONs
staging: erofs: unzip_{pagevec.h,vle.c}: rectify BUG_ONs
staging: erofs: unzip_vle_lz4.c,utils.c: rectify BUG_ONs
drivers/staging/erofs/data.c | 31 ++++---
drivers/staging/erofs/dir.c | 7 +-
drivers/staging/erofs/inode.c | 10 ++-
drivers/staging/erofs/internal.h | 71 ++++++++++------
drivers/staging/erofs/super.c | 19 ++---
drivers/staging/erofs/unzip_pagevec.h | 2 +-
drivers/staging/erofs/unzip_vle.c | 97 ++++++++--------------
drivers/staging/erofs/unzip_vle.h | 12 +--
drivers/staging/erofs/unzip_vle_lz4.c | 2 +-
drivers/staging/erofs/utils.c | 150 +++++++++++++++++++++++-----------
include/linux/xarray.h | 48 +++++++++++
11 files changed, 271 insertions(+), 178 deletions(-)
--
2.14.4
On Fri, Jan 18, 2019 at 07:48:59AM -0800, tip-bot for Jiaxun Yang wrote:
> Commit-ID: 0237199186e7a4aa5310741f0a6498a20c820fd7
> Gitweb: https://git.kernel.org/tip/0237199186e7a4aa5310741f0a6498a20c820fd7
> Author: Jiaxun Yang <jiaxun.yang(a)flygoat.com>
> AuthorDate: Tue, 20 Nov 2018 11:00:18 +0800
> Committer: Borislav Petkov <bp(a)suse.de>
> CommitDate: Fri, 18 Jan 2019 16:44:03 +0100
>
> x86/CPU/AMD: Set the CPB bit unconditionally on F17h
>
> Some F17h models do not have CPB set in CPUID even though the CPU
> supports it. Set the feature bit unconditionally on all F17h.
>
> [ bp: Rewrite commit message and patch. ]
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang(a)flygoat.com>
> Signed-off-by: Borislav Petkov <bp(a)suse.de>
> Acked-by: Tom Lendacky <thomas.lendacky(a)amd.com>
> Cc: "H. Peter Anvin" <hpa(a)zytor.com>
> Cc: Ingo Molnar <mingo(a)redhat.com>
> Cc: Sherry Hurwitz <sherry.hurwitz(a)amd.com>
> Cc: Suravee Suthikulpanit <suravee.suthikulpanit(a)amd.com>
> Cc: Thomas Gleixner <tglx(a)linutronix.de>
> Cc: x86-ml <x86(a)kernel.org>
> Link: https://lkml.kernel.org/r/20181120030018.5185-1-jiaxun.yang@flygoat.com
> ---
> arch/x86/kernel/cpu/amd.c | 8 +++-----
> 1 file changed, 3 insertions(+), 5 deletions(-)
>
> diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
> index 69f6bbb41be0..01004bfb1a1b 100644
> --- a/arch/x86/kernel/cpu/amd.c
> +++ b/arch/x86/kernel/cpu/amd.c
> @@ -819,11 +819,9 @@ static void init_amd_bd(struct cpuinfo_x86 *c)
> static void init_amd_zn(struct cpuinfo_x86 *c)
> {
> set_cpu_cap(c, X86_FEATURE_ZEN);
> - /*
> - * Fix erratum 1076: CPB feature bit not being set in CPUID. It affects
> - * all up to and including B1.
> - */
> - if (c->x86_model <= 1 && c->x86_stepping <= 1)
> +
> + /* Fix erratum 1076: CPB feature bit not being set in CPUID. */
> + if (!cpu_has(c, X86_FEATURE_CPB))
> set_cpu_cap(c, X86_FEATURE_CPB);
Stable folks, please take this one above into those stable trees which
have backported
f7f3dc00f612 ("x86/cpu/AMD: Fix erratum 1076 (CPB bit)")
Thx.
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
From: Eric Biggers <ebiggers(a)google.com>
If drm_gem_handle_create() fails in vkms_gem_create(), then the
vkms_gem_object is freed twice: once when the reference is dropped by
drm_gem_object_put_unlocked(), and again by the extra calls to
drm_gem_object_release() and kfree().
Fix it by skipping the second release and free.
This bug was originally found in the vgem driver by syzkaller using
fault injection, but I noticed it's also present in the vkms driver.
Fixes: 559e50fd34d1 ("drm/vkms: Add dumb operations")
Cc: Rodrigo Siqueira <rodrigosiqueiramelo(a)gmail.com>
Cc: Haneen Mohammed <hamohammed.sa(a)gmail.com>
Cc: Daniel Vetter <daniel.vetter(a)ffwll.ch>
Cc: Chris Wilson <chris(a)chris-wilson.co.uk>
Cc: stable(a)vger.kernel.org
Signed-off-by: Eric Biggers <ebiggers(a)google.com>
---
drivers/gpu/drm/vkms/vkms_gem.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_gem.c b/drivers/gpu/drm/vkms/vkms_gem.c
index 138b0bb325cf9..69048e73377dc 100644
--- a/drivers/gpu/drm/vkms/vkms_gem.c
+++ b/drivers/gpu/drm/vkms/vkms_gem.c
@@ -111,11 +111,8 @@ struct drm_gem_object *vkms_gem_create(struct drm_device *dev,
ret = drm_gem_handle_create(file, &obj->gem, handle);
drm_gem_object_put_unlocked(&obj->gem);
- if (ret) {
- drm_gem_object_release(&obj->gem);
- kfree(obj);
+ if (ret)
return ERR_PTR(ret);
- }
return &obj->gem;
}
--
2.21.0.rc2.261.ga7da99ff1b-goog
Commit-ID: 120e4e76857ddbc9268e1aa3f9de61a498e84618
Gitweb: https://git.kernel.org/tip/120e4e76857ddbc9268e1aa3f9de61a498e84618
Author: Kangjie Lu <kjlu(a)umn.edu>
AuthorDate: Wed, 9 Jan 2019 01:45:24 -0600
Committer: Ingo Molnar <mingo(a)kernel.org>
CommitDate: Mon, 21 Jan 2019 11:26:17 +0100
sched/core: Fix a potential double-fetch bug in sched_copy_attr()
"uattr->size" is copied in from user space and checked. However, it is
copied in again after the security check. A malicious user may race to
change it. The fix sets uattr->size to be the checked size.
Signed-off-by: Kangjie Lu <kjlu(a)umn.edu>
Signed-off-by: Peter Zijlstra (Intel) <peterz(a)infradead.org>
Cc: Linus Torvalds <torvalds(a)linux-foundation.org>
Cc: Peter Zijlstra <peterz(a)infradead.org>
Cc: Thomas Gleixner <tglx(a)linutronix.de>
Cc: pakki001(a)umn.edu
Cc: <stable(a)vger.kernel.org>
Link: https://lkml.kernel.org/r/20190109074524.10176-1-kjlu@umn.edu
Signed-off-by: Ingo Molnar <mingo(a)kernel.org>
---
kernel/sched/core.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index a674c7db2f29..d4d3514c4fe9 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -4499,6 +4499,9 @@ static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *a
if (ret)
return -EFAULT;
+ /* In case attr->size was changed by user-space: */
+ attr->size = size;
+
/*
* XXX: Do we want to be lenient like existing syscalls; or do we want
* to be strict and return an error on out-of-bounds values?
A successful call to NOTIFY_RETRIEVE by filesystem carries promise from
the kernel to send back NOTIFY_REPLY message. However if the filesystem
is not reading requests with fuse_conn->max_pages capacity,
fuse_dev_do_read might see that the "request is too large" and decide to
"reply with an error and restart the read". "Reply with an error" has
underlying assumption that there is a "requester thread" that is waiting
for request completion, which is true for most requests, but is not true
for NOTIFY_REPLY: NOTIFY_RETRIEVE handler completes with OK status right
after it could successfully queue NOTIFY_REPLY message without waiting
for NOTIFY_REPLY completion. This leads to situation when filesystem
requested to retrieve inode data with NOTIFY_RETRIEVE, got err=OK for
that notification request, but NOTIFY_REPLY is not coming back.
More, since there is no "requester thread" to handle the error, the
situation shows itself as /sys/fs/fuse/connections/X/waiting=1 _and_
/dev/fuse read(s) queued. Which is misleading since NOTIFY_REPLY request
was removed from pending queue and abandoned.
One way to fix would be to change NOTIFY_RETRIEVE handler to wait until
queued NOTIFY_REPLY is actually read back to the server and only then
return NOTIFY_RETRIEVE status. However this is change in behaviour and
would require filesystems to have at least 2 threads. In particular a
single-threaded filesystem that was previously successfully using
NOTIFY_RETRIEVE would become stuck after the change. This way of fixing
is thus not acceptable.
However we can fix it another way - by always returning NOTIFY_REPLY
irregardless of its original size - with so much data as provided read
buffer could fit. This aligns with the way NOTIFY_RETRIEVE handler
works, which already unconditionally caps requested retrieve size to
fuse_conn->max_pages. This way it should not hurt NOTIFY_RETRIEVE
semantic if we return less data than was originally requested.
This fix requires another behaviour change however - to be sure that
read buffer has enough capacity to always fit fixed NOTIFY_REPLY part
plus at least some (0 or more) data, we have to precheck the buffer
before dequeuing and handling a request. And if the buffer is very small -
return EINVAL to read in filesystem with semantic that queued read was
invalid from the viewpoint of FUSE protocol. Even though this is also
behaviour change, this should not practically cause problems: 1d3d752b47
(fuse: clean up request size limit checking), which originally removed
such EINVAL return and reworked fuse_dev_do_read to loop and retry, also
added FUSE_MIN_READ_BUFFER=8K to user-visible fuse.h with comment that
"The read buffer is required to be at least 8k ..." Even though
FUSE_MIN_READ_BUFFER is not currently checked anywhere in the kernel,
libfuse always initializes session with bufsize=32·pages and, since its
beginning, (at least from 2005) issues a warning should user modify
fuse_session->bufsize directly to be sure that queued buffers are at
least as large as that sane minimum:
https://github.com/libfuse/libfuse/blob/fuse-3.3.0-22-g63d53ecc3a/lib/fuse_…https://github.com/libfuse/libfuse/blob/fuse-3.3.0-22-g63d53ecc3a/lib/fuse_…
(semantic added in https://github.com/libfuse/libfuse/commit/044da2e9e0)
This way we should be safe to add the check for minimum read buffer size.
I've hit this bug for real with my filesystem that is using
https://github.com/hanwen/go-fuse: there was no NOTIFY_REPLY after
successful NOTIFY_RETRIEVE and the filesystem was stuck waiting,
because FUSE protocol (definition scattered through many places) states
that NOTIFY_REPLY is guaranteed to come after successful NOTIFY_RETRIEVE
(see 2d45ba381a "fuse: add retrieve request"). After inspecting
/sys/fs/fuse/connections/X/waiting and seeing it was 1, I was initially
suspecting that it was user-space who is not issuing /dev/fuse reads and
NOTIFY_REPLY is there but stuck in kernel pending queue. However tracing
what is going on in /dev/fuse exchange and in both kernel and userspace
(see https://lab.nexedi.com/kirr/wendelin.core/blob/13d2d1f8/wcfs/fusetrace)
showed that there are correctly queued /dev/fuse reads still pending
after NOTIFY_RETRIEVE returns and it is the kernel who is not replying back:
...
P2 2.215710 /dev/fuse <- qread wcfs/11399_4_r:
syscall.Syscall+48
syscall.Read+73
github.com/hanwen/go-fuse/fuse.(*Server).readRequest.func1+85github.com/hanwen/go-fuse/fuse.handleEINTR+39github.com/hanwen/go-fuse/fuse.(*Server).readRequest+355github.com/hanwen/go-fuse/fuse.(*Server).loop+107
runtime.goexit+1
P2 2.215810 /dev/fuse -> read wcfs/11399_4_r:
.56 RELEASE i8 ... (ret=64)
P2 2.215859 /dev/fuse <- write wcfs/11399_5_w:
.56 (0) ...
syscall.Syscall+48
syscall.Write+73
github.com/hanwen/go-fuse/fuse.(*Server).systemWrite.func1+76github.com/hanwen/go-fuse/fuse.handleEINTR+39github.com/hanwen/go-fuse/fuse.(*Server).systemWrite+931github.com/hanwen/go-fuse/fuse.(*Server).write+194github.com/hanwen/go-fuse/fuse.(*Server).handleRequest+179github.com/hanwen/go-fuse/fuse.(*Server).loop+399
runtime.goexit+1
P2 2.215871 /dev/fuse -> write_ack wcfs/11399_5_w (ret=16)
P2 2.215876 /dev/fuse <- qread wcfs/11399_5_r: <-- NOTE
syscall.Syscall+48
syscall.Read+73
github.com/hanwen/go-fuse/fuse.(*Server).readRequest.func1+85github.com/hanwen/go-fuse/fuse.handleEINTR+39github.com/hanwen/go-fuse/fuse.(*Server).readRequest+355github.com/hanwen/go-fuse/fuse.(*Server).loop+107
runtime.goexit+1
P0 2.221527 /dev/fuse <- qread wcfs/11401_1_r: <-- NOTE
syscall.Syscall+48
syscall.Read+73
github.com/hanwen/go-fuse/fuse.(*Server).readRequest.func1+85github.com/hanwen/go-fuse/fuse.handleEINTR+39github.com/hanwen/go-fuse/fuse.(*Server).readRequest+355github.com/hanwen/go-fuse/fuse.(*Server).loop+107
runtime.goexit+1
P1 2.239384 /dev/fuse -> read wcfs/11398_6_r: # woken read that was queued before "..."
.57 READ i5 ... (ret=80)
P0 2.239626 /dev/fuse <- write wcfs/11397_0_w:
NOTIFY_RETRIEVE ...
syscall.Syscall+48
syscall.Write+73
github.com/hanwen/go-fuse/fuse.(*Server).systemWrite.func1+76github.com/hanwen/go-fuse/fuse.handleEINTR+39github.com/hanwen/go-fuse/fuse.(*Server).systemWrite+931github.com/hanwen/go-fuse/fuse.(*Server).write+194github.com/hanwen/go-fuse/fuse.(*Server).InodeRetrieveCache+764github.com/hanwen/go-fuse/fuse/nodefs.(*FileSystemConnector).FileRetrieveCa…
main.(*BigFile).invalidateBlk+232
main.(*Root).zδhandle1.func1+72
golang.org/x/sync/errgroup.(*Group).Go.func1+87
runtime.goexit+1
P0 2.239660 /dev/fuse -> write_ack wcfs/11397_0_w (ret=48)
# stuck
# (full trace: https://lab.nexedi.com/kirr/wendelin.core/commit/96416aaabd)
with queued / served read analysis confirming that two reads were indeed queued
and not served:
grep -w -e '<- qread\>' y.log |awk {'print $6'} |sort >qread.txt
grep -w -e '-> read\>' y.log |awk {'print $6'} |sort >read.txt
# xdiff qread.txt read.txt
diff --git a/qread.txt b/read.txt
index 4ab50d7..fdd2be1 100644
--- a/qread.txt
+++ b/read.txt
@@ -53,7 +53,5 @@ wcfs/11399_1_r:
wcfs/11399_2_r:
wcfs/11399_3_r:
wcfs/11399_4_r:
-wcfs/11399_5_r:
wcfs/11400_0_r:
wcfs/11401_0_r:
-wcfs/11401_1_r:
The bug was hit because go-fuse by default uses 64K for read buffer size
https://github.com/hanwen/go-fuse/blob/33711add/fuse/server.go#L142
and the kernel presets fuse_conn->max_pages to be 128K (= 32·4K pages).
Go-fuse will be likely fixed to both use bufsize=kernel's and to
correctly handle size > bufsize in InodeRetrieveCache. However we should
also fix the kernel to always deliver NOTIFY_REPLY once NOTIFY_RETRIEVE
was successful, so that FUSE protocol guarantee always holds
irregardless of whether userspace used default or other valid buffer
size setting, and so that filesystems can count not to get stuck waiting
for kernel who promised a reply.
This way this patch is here.
Signed-off-by: Kirill Smelkov <kirr(a)nexedi.com>
Cc: Han-Wen Nienhuys <hanwen(a)google.com>
Cc: Jakob Unterwurzacher <jakobunt(a)gmail.com>
Cc: <stable(a)vger.kernel.org> # v2.6.36+
---
First patch version was sent 1 week ago, but got no response:
https://marc.info/?l=linux-fsdevel&m=155000277921155&w=2
Changes since v1: don't forget to also update req->misc.retrieve_in.size
after truncation.
( This is my first patch to fs/fuse, so please forgive me if I missed anything. )
fs/fuse/dev.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 65 insertions(+), 6 deletions(-)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 8a63e52785e9..93deb8e54d88 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -381,6 +381,40 @@ static void queue_request(struct fuse_iqueue *fiq, struct fuse_req *req)
kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
}
+/*
+ * fuse_req_truncate_data truncates data in request that has paged data
+ * (req.in.argpages=1), so that whole request, when serialized, is <= nbytes.
+ *
+ * nbytes must be >= size(request without data).
+ */
+static void fuse_req_truncate_data(struct fuse_req *req, unsigned nbytes) {
+ unsigned size, n;
+
+ BUG_ON(!req->in.argpages);
+ BUG_ON(req->in.numargs < 1);
+
+ /* request size without data */
+ size = sizeof(struct fuse_in_header) +
+ len_args(req->in.numargs - 1, (struct fuse_arg *) req->in.args);
+ BUG_ON(nbytes < size);
+
+ /* truncate paged data */
+ for (n = 0; n < req->num_pages; n++) {
+ struct fuse_page_desc *p = &req->page_descs[n];
+
+ if (size >= nbytes) {
+ p->length = 0;
+ } else {
+ p->length = min_t(unsigned, p->length, nbytes - size);
+ }
+
+ size += p->length;
+ }
+
+ /* update whole request length in the header */
+ req->in.h.len = size;
+}
+
void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget,
u64 nodeid, u64 nlookup)
{
@@ -1317,6 +1351,15 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
unsigned reqsize;
unsigned int hash;
+ /*
+ * Require sane minimum read buffer - that has capacity for fixed part
+ * of any request + some room for data. If the requirement is not
+ * satisfied return EINVAL to the filesystem without dequeueing /
+ * aborting any request.
+ */
+ if (nbytes < FUSE_MIN_READ_BUFFER)
+ return -EINVAL;
+
restart:
spin_lock(&fiq->waitq.lock);
err = -EAGAIN;
@@ -1358,12 +1401,28 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
/* If request is too large, reply with an error and restart the read */
if (nbytes < reqsize) {
- req->out.h.error = -EIO;
- /* SETXATTR is special, since it may contain too large data */
- if (in->h.opcode == FUSE_SETXATTR)
- req->out.h.error = -E2BIG;
- request_end(fc, req);
- goto restart;
+ switch (in->h.opcode) {
+ default:
+ req->out.h.error = -EIO;
+ /* SETXATTR is special, since it may contain too large data */
+ if (in->h.opcode == FUSE_SETXATTR)
+ req->out.h.error = -E2BIG;
+ request_end(fc, req);
+ goto restart;
+
+ /*
+ * NOTIFY_REPLY is special: if it was queued we already
+ * promised to filesystem to deliver it when handling
+ * NOTIFY_RETRIVE. We know that read buffer has capacity for at
+ * least some data. Truncate retrieved data to read buffer size
+ * and deliver it to stay to the promise.
+ */
+ case FUSE_NOTIFY_REPLY:
+ fuse_req_truncate_data(req, nbytes);
+ req->misc.retrieve_in.size -= reqsize - in->h.len;
+ reqsize = in->h.len;
+ }
+
}
spin_lock(&fpq->lock);
list_add(&req->list, &fpq->io);
--
2.21.0.rc0.269.g1a574e7a28
Hi Jason and Doug,
Here are some fixes that didn't quite make the boat for 5.0-rc. So we can
go ahead and send them to -next. The third patch here is really a v2 of:
https://patchwork.kernel.org/patch/10769005/
---
Michael J. Ruhl (2):
IB/rdmavt: Fix concurrency panics in QP post_send and modify to error
IB/hfi1: Close race condition on user context disable and close
Mike Marciniszyn (1):
IB/rdmavt: Fix loopback send with invalidate ordering
drivers/infiniband/hw/hfi1/hfi.h | 2 +
drivers/infiniband/hw/hfi1/init.c | 14 ++++++---
drivers/infiniband/sw/rdmavt/qp.c | 59 ++++++++++++++++++++++++-------------
3 files changed, 49 insertions(+), 26 deletions(-)
--
-Denny