2021-01-07 14:37:16

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 00/13] 5.4.88-rc1 review

This is the start of the stable review cycle for the 5.4.88 release.
There are 13 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.

Responses should be made by Sat, 09 Jan 2021 14:30:35 +0000.
Anything received after that time might be too late.

The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.4.88-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.4.y
and the diffstat can be found below.

thanks,

greg k-h

-------------
Pseudo-Shortlog of commits:

Greg Kroah-Hartman <[email protected]>
Linux 5.4.88-rc1

Zhang Xiaohui <[email protected]>
mwifiex: Fix possible buffer overflows in mwifiex_cmd_802_11_ad_hoc_start

Eric W. Biederman <[email protected]>
exec: Transform exec_update_mutex into a rw_semaphore

Eric W. Biederman <[email protected]>
rwsem: Implement down_read_interruptible

Eric W. Biederman <[email protected]>
rwsem: Implement down_read_killable_nested

[email protected] <[email protected]>
perf: Break deadlock involving exec_update_mutex

Miklos Szeredi <[email protected]>
fuse: fix bad inode

Jonathan Cameron <[email protected]>
iio:imu:bmi160: Fix alignment and data leak issues

Josh Poimboeuf <[email protected]>
kdev_t: always inline major/minor helper functions

Yu Kuai <[email protected]>
dmaengine: at_hdmac: add missing kfree() call in at_dma_xlate()

Yu Kuai <[email protected]>
dmaengine: at_hdmac: add missing put_device() call in at_dma_xlate()

Tudor Ambarus <[email protected]>
dmaengine: at_hdmac: Substitute kzalloc with kmalloc

Felix Fietkau <[email protected]>
Revert "mtd: spinand: Fix OOB read"

Alex Deucher <[email protected]>
Revert "drm/amd/display: Fix memory leaks in S3 resume"


-------------

Diffstat:

Makefile | 4 +-
drivers/dma/at_hdmac.c | 11 +++--
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-
drivers/iio/imu/bmi160/bmi160.h | 7 +++
drivers/iio/imu/bmi160/bmi160_core.c | 6 +--
drivers/mtd/nand/spi/core.c | 4 --
drivers/net/wireless/marvell/mwifiex/join.c | 2 +
fs/exec.c | 12 +++---
fs/fuse/acl.c | 6 +++
fs/fuse/dir.c | 37 +++++++++++++---
fs/fuse/file.c | 19 +++++----
fs/fuse/fuse_i.h | 12 ++++++
fs/fuse/inode.c | 4 +-
fs/fuse/readdir.c | 4 +-
fs/fuse/xattr.c | 9 ++++
fs/proc/base.c | 10 ++---
include/linux/kdev_t.h | 22 +++++-----
include/linux/rwsem.h | 3 ++
include/linux/sched/signal.h | 11 ++---
init/init_task.c | 2 +-
kernel/events/core.c | 52 +++++++++++------------
kernel/fork.c | 6 +--
kernel/kcmp.c | 30 ++++++-------
kernel/locking/rwsem.c | 40 +++++++++++++++++
24 files changed, 212 insertions(+), 104 deletions(-)



2021-01-07 14:37:30

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 08/13] fuse: fix bad inode

From: Miklos Szeredi <[email protected]>

[ Upstream commit 5d069dbe8aaf2a197142558b6fb2978189ba3454 ]

Jan Kara's analysis of the syzbot report (edited):

The reproducer opens a directory on FUSE filesystem, it then attaches
dnotify mark to the open directory. After that a fuse_do_getattr() call
finds that attributes returned by the server are inconsistent, and calls
make_bad_inode() which, among other things does:

inode->i_mode = S_IFREG;

This then confuses dnotify which doesn't tear down its structures
properly and eventually crashes.

Avoid calling make_bad_inode() on a live inode: switch to a private flag on
the fuse inode. Also add the test to ops which the bad_inode_ops would
have caught.

This bug goes back to the initial merge of fuse in 2.6.14...

Reported-by: [email protected]
Signed-off-by: Miklos Szeredi <[email protected]>
Tested-by: Jan Kara <[email protected]>
Cc: <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
---
fs/fuse/acl.c | 6 ++++++
fs/fuse/dir.c | 37 ++++++++++++++++++++++++++++++++-----
fs/fuse/file.c | 19 +++++++++++--------
fs/fuse/fuse_i.h | 12 ++++++++++++
fs/fuse/inode.c | 4 ++--
fs/fuse/readdir.c | 4 ++--
fs/fuse/xattr.c | 9 +++++++++
7 files changed, 74 insertions(+), 17 deletions(-)

diff --git a/fs/fuse/acl.c b/fs/fuse/acl.c
index 5a48cee6d7d33..f529075a2ce87 100644
--- a/fs/fuse/acl.c
+++ b/fs/fuse/acl.c
@@ -19,6 +19,9 @@ struct posix_acl *fuse_get_acl(struct inode *inode, int type)
void *value = NULL;
struct posix_acl *acl;

+ if (fuse_is_bad(inode))
+ return ERR_PTR(-EIO);
+
if (!fc->posix_acl || fc->no_getxattr)
return NULL;

@@ -53,6 +56,9 @@ int fuse_set_acl(struct inode *inode, struct posix_acl *acl, int type)
const char *name;
int ret;

+ if (fuse_is_bad(inode))
+ return -EIO;
+
if (!fc->posix_acl || fc->no_setxattr)
return -EOPNOTSUPP;

diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index ee190119f45cc..60378f3baaae1 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -201,7 +201,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
int ret;

inode = d_inode_rcu(entry);
- if (inode && is_bad_inode(inode))
+ if (inode && fuse_is_bad(inode))
goto invalid;
else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
(flags & LOOKUP_REVAL)) {
@@ -386,6 +386,9 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
bool outarg_valid = true;
bool locked;

+ if (fuse_is_bad(dir))
+ return ERR_PTR(-EIO);
+
locked = fuse_lock_inode(dir);
err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
&outarg, &inode);
@@ -529,6 +532,9 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
struct fuse_conn *fc = get_fuse_conn(dir);
struct dentry *res = NULL;

+ if (fuse_is_bad(dir))
+ return -EIO;
+
if (d_in_lookup(entry)) {
res = fuse_lookup(dir, entry, 0);
if (IS_ERR(res))
@@ -577,6 +583,9 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args,
int err;
struct fuse_forget_link *forget;

+ if (fuse_is_bad(dir))
+ return -EIO;
+
forget = fuse_alloc_forget();
if (!forget)
return -ENOMEM;
@@ -704,6 +713,9 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
struct fuse_conn *fc = get_fuse_conn(dir);
FUSE_ARGS(args);

+ if (fuse_is_bad(dir))
+ return -EIO;
+
args.opcode = FUSE_UNLINK;
args.nodeid = get_node_id(dir);
args.in_numargs = 1;
@@ -740,6 +752,9 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
struct fuse_conn *fc = get_fuse_conn(dir);
FUSE_ARGS(args);

+ if (fuse_is_bad(dir))
+ return -EIO;
+
args.opcode = FUSE_RMDIR;
args.nodeid = get_node_id(dir);
args.in_numargs = 1;
@@ -818,6 +833,9 @@ static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
struct fuse_conn *fc = get_fuse_conn(olddir);
int err;

+ if (fuse_is_bad(olddir))
+ return -EIO;
+
if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
return -EINVAL;

@@ -953,7 +971,7 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
if (!err) {
if (fuse_invalid_attr(&outarg.attr) ||
(inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
- make_bad_inode(inode);
+ fuse_make_bad(inode);
err = -EIO;
} else {
fuse_change_attributes(inode, &outarg.attr,
@@ -1155,6 +1173,9 @@ static int fuse_permission(struct inode *inode, int mask)
bool refreshed = false;
int err = 0;

+ if (fuse_is_bad(inode))
+ return -EIO;
+
if (!fuse_allow_current_process(fc))
return -EACCES;

@@ -1250,7 +1271,7 @@ static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
int err;

err = -EIO;
- if (is_bad_inode(inode))
+ if (fuse_is_bad(inode))
goto out_err;

if (fc->cache_symlinks)
@@ -1298,7 +1319,7 @@ static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
struct fuse_conn *fc = get_fuse_conn(inode);
int err;

- if (is_bad_inode(inode))
+ if (fuse_is_bad(inode))
return -EIO;

if (fc->no_fsyncdir)
@@ -1575,7 +1596,7 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,

if (fuse_invalid_attr(&outarg.attr) ||
(inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
- make_bad_inode(inode);
+ fuse_make_bad(inode);
err = -EIO;
goto error;
}
@@ -1631,6 +1652,9 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
int ret;

+ if (fuse_is_bad(inode))
+ return -EIO;
+
if (!fuse_allow_current_process(get_fuse_conn(inode)))
return -EACCES;

@@ -1689,6 +1713,9 @@ static int fuse_getattr(const struct path *path, struct kstat *stat,
struct inode *inode = d_inode(path->dentry);
struct fuse_conn *fc = get_fuse_conn(inode);

+ if (fuse_is_bad(inode))
+ return -EIO;
+
if (!fuse_allow_current_process(fc))
return -EACCES;

diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index ab4fc1255aca8..1e1aef1bc20b3 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -222,6 +222,9 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
fc->atomic_o_trunc &&
fc->writeback_cache;

+ if (fuse_is_bad(inode))
+ return -EIO;
+
err = generic_file_open(inode, file);
if (err)
return err;
@@ -443,7 +446,7 @@ static int fuse_flush(struct file *file, fl_owner_t id)
FUSE_ARGS(args);
int err;

- if (is_bad_inode(inode))
+ if (fuse_is_bad(inode))
return -EIO;

if (fc->no_flush)
@@ -506,7 +509,7 @@ static int fuse_fsync(struct file *file, loff_t start, loff_t end,
struct fuse_conn *fc = get_fuse_conn(inode);
int err;

- if (is_bad_inode(inode))
+ if (fuse_is_bad(inode))
return -EIO;

inode_lock(inode);
@@ -830,7 +833,7 @@ static int fuse_readpage(struct file *file, struct page *page)
int err;

err = -EIO;
- if (is_bad_inode(inode))
+ if (fuse_is_bad(inode))
goto out;

err = fuse_do_readpage(file, page);
@@ -973,7 +976,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
int err;

err = -EIO;
- if (is_bad_inode(inode))
+ if (fuse_is_bad(inode))
goto out;

data.file = file;
@@ -1569,7 +1572,7 @@ static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
struct file *file = iocb->ki_filp;
struct fuse_file *ff = file->private_data;

- if (is_bad_inode(file_inode(file)))
+ if (fuse_is_bad(file_inode(file)))
return -EIO;

if (!(ff->open_flags & FOPEN_DIRECT_IO))
@@ -1583,7 +1586,7 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
struct file *file = iocb->ki_filp;
struct fuse_file *ff = file->private_data;

- if (is_bad_inode(file_inode(file)))
+ if (fuse_is_bad(file_inode(file)))
return -EIO;

if (!(ff->open_flags & FOPEN_DIRECT_IO))
@@ -2133,7 +2136,7 @@ static int fuse_writepages(struct address_space *mapping,
int err;

err = -EIO;
- if (is_bad_inode(inode))
+ if (fuse_is_bad(inode))
goto out;

data.inode = inode;
@@ -2911,7 +2914,7 @@ long fuse_ioctl_common(struct file *file, unsigned int cmd,
if (!fuse_allow_current_process(fc))
return -EACCES;

- if (is_bad_inode(inode))
+ if (fuse_is_bad(inode))
return -EIO;

return fuse_do_ioctl(file, cmd, arg, flags);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index d7cde216fc871..e3688312e9f1b 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -158,6 +158,8 @@ enum {
FUSE_I_INIT_RDPLUS,
/** An operation changing file size is in progress */
FUSE_I_SIZE_UNSTABLE,
+ /* Bad inode */
+ FUSE_I_BAD,
};

struct fuse_conn;
@@ -787,6 +789,16 @@ static inline u64 fuse_get_attr_version(struct fuse_conn *fc)
return atomic64_read(&fc->attr_version);
}

+static inline void fuse_make_bad(struct inode *inode)
+{
+ set_bit(FUSE_I_BAD, &get_fuse_inode(inode)->state);
+}
+
+static inline bool fuse_is_bad(struct inode *inode)
+{
+ return unlikely(test_bit(FUSE_I_BAD, &get_fuse_inode(inode)->state));
+}
+
/** Device operations */
extern const struct file_operations fuse_dev_operations;

diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index f58ab84b09fb3..aa1d5cf1bc3a4 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -115,7 +115,7 @@ static void fuse_evict_inode(struct inode *inode)
fuse_queue_forget(fc, fi->forget, fi->nodeid, fi->nlookup);
fi->forget = NULL;
}
- if (S_ISREG(inode->i_mode) && !is_bad_inode(inode)) {
+ if (S_ISREG(inode->i_mode) && !fuse_is_bad(inode)) {
WARN_ON(!list_empty(&fi->write_files));
WARN_ON(!list_empty(&fi->queued_writes));
}
@@ -306,7 +306,7 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
unlock_new_inode(inode);
} else if ((inode->i_mode ^ attr->mode) & S_IFMT) {
/* Inode has changed type, any I/O on the old should fail */
- make_bad_inode(inode);
+ fuse_make_bad(inode);
iput(inode);
goto retry;
}
diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c
index 6a40f75a0d25e..70f685b61e3a5 100644
--- a/fs/fuse/readdir.c
+++ b/fs/fuse/readdir.c
@@ -207,7 +207,7 @@ retry:
dput(dentry);
goto retry;
}
- if (is_bad_inode(inode)) {
+ if (fuse_is_bad(inode)) {
dput(dentry);
return -EIO;
}
@@ -568,7 +568,7 @@ int fuse_readdir(struct file *file, struct dir_context *ctx)
struct inode *inode = file_inode(file);
int err;

- if (is_bad_inode(inode))
+ if (fuse_is_bad(inode))
return -EIO;

mutex_lock(&ff->readdir.lock);
diff --git a/fs/fuse/xattr.c b/fs/fuse/xattr.c
index 20d052e08b3be..28fed52957707 100644
--- a/fs/fuse/xattr.c
+++ b/fs/fuse/xattr.c
@@ -113,6 +113,9 @@ ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
struct fuse_getxattr_out outarg;
ssize_t ret;

+ if (fuse_is_bad(inode))
+ return -EIO;
+
if (!fuse_allow_current_process(fc))
return -EACCES;

@@ -178,6 +181,9 @@ static int fuse_xattr_get(const struct xattr_handler *handler,
struct dentry *dentry, struct inode *inode,
const char *name, void *value, size_t size)
{
+ if (fuse_is_bad(inode))
+ return -EIO;
+
return fuse_getxattr(inode, name, value, size);
}

@@ -186,6 +192,9 @@ static int fuse_xattr_set(const struct xattr_handler *handler,
const char *name, const void *value, size_t size,
int flags)
{
+ if (fuse_is_bad(inode))
+ return -EIO;
+
if (!value)
return fuse_removexattr(inode, name);

--
2.27.0



2021-01-07 14:37:53

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 12/13] exec: Transform exec_update_mutex into a rw_semaphore

From: Eric W. Biederman <[email protected]>

[ Upstream commit f7cfd871ae0c5008d94b6f66834e7845caa93c15 ]

Recently syzbot reported[0] that there is a deadlock amongst the users
of exec_update_mutex. The problematic lock ordering found by lockdep
was:

perf_event_open (exec_update_mutex -> ovl_i_mutex)
chown (ovl_i_mutex -> sb_writes)
sendfile (sb_writes -> p->lock)
by reading from a proc file and writing to overlayfs
proc_pid_syscall (p->lock -> exec_update_mutex)

While looking at possible solutions it occured to me that all of the
users and possible users involved only wanted to state of the given
process to remain the same. They are all readers. The only writer is
exec.

There is no reason for readers to block on each other. So fix
this deadlock by transforming exec_update_mutex into a rw_semaphore
named exec_update_lock that only exec takes for writing.

Cc: Jann Horn <[email protected]>
Cc: Vasiliy Kulikov <[email protected]>
Cc: Al Viro <[email protected]>
Cc: Bernd Edlinger <[email protected]>
Cc: Oleg Nesterov <[email protected]>
Cc: Christopher Yeoh <[email protected]>
Cc: Cyrill Gorcunov <[email protected]>
Cc: Sargun Dhillon <[email protected]>
Cc: Christian Brauner <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Fixes: eea9673250db ("exec: Add exec_update_mutex to replace cred_guard_mutex")
[0] https://lkml.kernel.org/r/[email protected]
Reported-by: [email protected]
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Eric W. Biederman <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
---
fs/exec.c | 12 ++++++------
fs/proc/base.c | 10 +++++-----
include/linux/sched/signal.h | 11 ++++++-----
init/init_task.c | 2 +-
kernel/events/core.c | 12 ++++++------
kernel/fork.c | 6 +++---
kernel/kcmp.c | 30 +++++++++++++++---------------
kernel/locking/rwsem.c | 4 ++--
8 files changed, 44 insertions(+), 43 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index 2441eb1a1e2d0..1b4d2206d53a1 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1009,8 +1009,8 @@ EXPORT_SYMBOL(read_code);

/*
* Maps the mm_struct mm into the current task struct.
- * On success, this function returns with the mutex
- * exec_update_mutex locked.
+ * On success, this function returns with exec_update_lock
+ * held for writing.
*/
static int exec_mmap(struct mm_struct *mm)
{
@@ -1023,7 +1023,7 @@ static int exec_mmap(struct mm_struct *mm)
old_mm = current->mm;
exec_mm_release(tsk, old_mm);

- ret = mutex_lock_killable(&tsk->signal->exec_update_mutex);
+ ret = down_write_killable(&tsk->signal->exec_update_lock);
if (ret)
return ret;

@@ -1038,7 +1038,7 @@ static int exec_mmap(struct mm_struct *mm)
down_read(&old_mm->mmap_sem);
if (unlikely(old_mm->core_state)) {
up_read(&old_mm->mmap_sem);
- mutex_unlock(&tsk->signal->exec_update_mutex);
+ up_write(&tsk->signal->exec_update_lock);
return -EINTR;
}
}
@@ -1450,7 +1450,7 @@ static void free_bprm(struct linux_binprm *bprm)
free_arg_pages(bprm);
if (bprm->cred) {
if (bprm->called_exec_mmap)
- mutex_unlock(&current->signal->exec_update_mutex);
+ up_write(&current->signal->exec_update_lock);
mutex_unlock(&current->signal->cred_guard_mutex);
abort_creds(bprm->cred);
}
@@ -1500,7 +1500,7 @@ void install_exec_creds(struct linux_binprm *bprm)
* credentials; any time after this it may be unlocked.
*/
security_bprm_committed_creds(bprm);
- mutex_unlock(&current->signal->exec_update_mutex);
+ up_write(&current->signal->exec_update_lock);
mutex_unlock(&current->signal->cred_guard_mutex);
}
EXPORT_SYMBOL(install_exec_creds);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index b690074e65ffa..653c2d8aa1cd7 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -403,11 +403,11 @@ print0:

static int lock_trace(struct task_struct *task)
{
- int err = mutex_lock_killable(&task->signal->exec_update_mutex);
+ int err = down_read_killable(&task->signal->exec_update_lock);
if (err)
return err;
if (!ptrace_may_access(task, PTRACE_MODE_ATTACH_FSCREDS)) {
- mutex_unlock(&task->signal->exec_update_mutex);
+ up_read(&task->signal->exec_update_lock);
return -EPERM;
}
return 0;
@@ -415,7 +415,7 @@ static int lock_trace(struct task_struct *task)

static void unlock_trace(struct task_struct *task)
{
- mutex_unlock(&task->signal->exec_update_mutex);
+ up_read(&task->signal->exec_update_lock);
}

#ifdef CONFIG_STACKTRACE
@@ -2769,7 +2769,7 @@ static int do_io_accounting(struct task_struct *task, struct seq_file *m, int wh
unsigned long flags;
int result;

- result = mutex_lock_killable(&task->signal->exec_update_mutex);
+ result = down_read_killable(&task->signal->exec_update_lock);
if (result)
return result;

@@ -2805,7 +2805,7 @@ static int do_io_accounting(struct task_struct *task, struct seq_file *m, int wh
result = 0;

out_unlock:
- mutex_unlock(&task->signal->exec_update_mutex);
+ up_read(&task->signal->exec_update_lock);
return result;
}

diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
index a29df79540ce6..baf58f4cb0578 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -226,12 +226,13 @@ struct signal_struct {
* credential calculations
* (notably. ptrace)
* Deprecated do not use in new code.
- * Use exec_update_mutex instead.
- */
- struct mutex exec_update_mutex; /* Held while task_struct is being
- * updated during exec, and may have
- * inconsistent permissions.
+ * Use exec_update_lock instead.
*/
+ struct rw_semaphore exec_update_lock; /* Held while task_struct is
+ * being updated during exec,
+ * and may have inconsistent
+ * permissions.
+ */
} __randomize_layout;

/*
diff --git a/init/init_task.c b/init/init_task.c
index bd403ed3e4184..df7041be96fca 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -26,7 +26,7 @@ static struct signal_struct init_signals = {
.multiprocess = HLIST_HEAD_INIT,
.rlim = INIT_RLIMITS,
.cred_guard_mutex = __MUTEX_INITIALIZER(init_signals.cred_guard_mutex),
- .exec_update_mutex = __MUTEX_INITIALIZER(init_signals.exec_update_mutex),
+ .exec_update_lock = __RWSEM_INITIALIZER(init_signals.exec_update_lock),
#ifdef CONFIG_POSIX_TIMERS
.posix_timers = LIST_HEAD_INIT(init_signals.posix_timers),
.cputimer = {
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 18dbdf248ed81..2ef33e9a75910 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1254,7 +1254,7 @@ static void put_ctx(struct perf_event_context *ctx)
* function.
*
* Lock order:
- * exec_update_mutex
+ * exec_update_lock
* task_struct::perf_event_mutex
* perf_event_context::mutex
* perf_event::child_mutex;
@@ -11128,14 +11128,14 @@ SYSCALL_DEFINE5(perf_event_open,
}

if (task) {
- err = mutex_lock_interruptible(&task->signal->exec_update_mutex);
+ err = down_read_interruptible(&task->signal->exec_update_lock);
if (err)
goto err_file;

/*
* Preserve ptrace permission check for backwards compatibility.
*
- * We must hold exec_update_mutex across this and any potential
+ * We must hold exec_update_lock across this and any potential
* perf_install_in_context() call for this new event to
* serialize against exec() altering our credentials (and the
* perf_event_exit_task() that could imply).
@@ -11298,7 +11298,7 @@ SYSCALL_DEFINE5(perf_event_open,
mutex_unlock(&ctx->mutex);

if (task) {
- mutex_unlock(&task->signal->exec_update_mutex);
+ up_read(&task->signal->exec_update_lock);
put_task_struct(task);
}

@@ -11322,7 +11322,7 @@ err_locked:
mutex_unlock(&ctx->mutex);
err_cred:
if (task)
- mutex_unlock(&task->signal->exec_update_mutex);
+ up_read(&task->signal->exec_update_lock);
err_file:
fput(event_file);
err_context:
@@ -11639,7 +11639,7 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn)
/*
* When a child task exits, feed back event values to parent events.
*
- * Can be called with exec_update_mutex held when called from
+ * Can be called with exec_update_lock held when called from
* install_exec_creds().
*/
void perf_event_exit_task(struct task_struct *child)
diff --git a/kernel/fork.c b/kernel/fork.c
index 419fff8eb9e55..50f37d5afb32b 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1221,7 +1221,7 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
struct mm_struct *mm;
int err;

- err = mutex_lock_killable(&task->signal->exec_update_mutex);
+ err = down_read_killable(&task->signal->exec_update_lock);
if (err)
return ERR_PTR(err);

@@ -1231,7 +1231,7 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
mmput(mm);
mm = ERR_PTR(-EACCES);
}
- mutex_unlock(&task->signal->exec_update_mutex);
+ up_read(&task->signal->exec_update_lock);

return mm;
}
@@ -1586,7 +1586,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
sig->oom_score_adj_min = current->signal->oom_score_adj_min;

mutex_init(&sig->cred_guard_mutex);
- mutex_init(&sig->exec_update_mutex);
+ init_rwsem(&sig->exec_update_lock);

return 0;
}
diff --git a/kernel/kcmp.c b/kernel/kcmp.c
index b3ff9288c6cc9..c0d2ad9b4705d 100644
--- a/kernel/kcmp.c
+++ b/kernel/kcmp.c
@@ -75,25 +75,25 @@ get_file_raw_ptr(struct task_struct *task, unsigned int idx)
return file;
}

-static void kcmp_unlock(struct mutex *m1, struct mutex *m2)
+static void kcmp_unlock(struct rw_semaphore *l1, struct rw_semaphore *l2)
{
- if (likely(m2 != m1))
- mutex_unlock(m2);
- mutex_unlock(m1);
+ if (likely(l2 != l1))
+ up_read(l2);
+ up_read(l1);
}

-static int kcmp_lock(struct mutex *m1, struct mutex *m2)
+static int kcmp_lock(struct rw_semaphore *l1, struct rw_semaphore *l2)
{
int err;

- if (m2 > m1)
- swap(m1, m2);
+ if (l2 > l1)
+ swap(l1, l2);

- err = mutex_lock_killable(m1);
- if (!err && likely(m1 != m2)) {
- err = mutex_lock_killable_nested(m2, SINGLE_DEPTH_NESTING);
+ err = down_read_killable(l1);
+ if (!err && likely(l1 != l2)) {
+ err = down_read_killable_nested(l2, SINGLE_DEPTH_NESTING);
if (err)
- mutex_unlock(m1);
+ up_read(l1);
}

return err;
@@ -173,8 +173,8 @@ SYSCALL_DEFINE5(kcmp, pid_t, pid1, pid_t, pid2, int, type,
/*
* One should have enough rights to inspect task details.
*/
- ret = kcmp_lock(&task1->signal->exec_update_mutex,
- &task2->signal->exec_update_mutex);
+ ret = kcmp_lock(&task1->signal->exec_update_lock,
+ &task2->signal->exec_update_lock);
if (ret)
goto err;
if (!ptrace_may_access(task1, PTRACE_MODE_READ_REALCREDS) ||
@@ -229,8 +229,8 @@ SYSCALL_DEFINE5(kcmp, pid_t, pid1, pid_t, pid2, int, type,
}

err_unlock:
- kcmp_unlock(&task1->signal->exec_update_mutex,
- &task2->signal->exec_update_mutex);
+ kcmp_unlock(&task1->signal->exec_update_lock,
+ &task2->signal->exec_update_lock);
err:
put_task_struct(task1);
put_task_struct(task2);
diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c
index a5eb87f2c5816..5d54ff3179b80 100644
--- a/kernel/locking/rwsem.c
+++ b/kernel/locking/rwsem.c
@@ -1516,7 +1516,7 @@ int __sched down_read_interruptible(struct rw_semaphore *sem)
rwsem_acquire_read(&sem->dep_map, 0, 0, _RET_IP_);

if (LOCK_CONTENDED_RETURN(sem, __down_read_trylock, __down_read_interruptible)) {
- rwsem_release(&sem->dep_map, _RET_IP_);
+ rwsem_release(&sem->dep_map, 1, _RET_IP_);
return -EINTR;
}

@@ -1640,7 +1640,7 @@ int down_read_killable_nested(struct rw_semaphore *sem, int subclass)
rwsem_acquire_read(&sem->dep_map, subclass, 0, _RET_IP_);

if (LOCK_CONTENDED_RETURN(sem, __down_read_trylock, __down_read_killable)) {
- rwsem_release(&sem->dep_map, _RET_IP_);
+ rwsem_release(&sem->dep_map, 1, _RET_IP_);
return -EINTR;
}

--
2.27.0



2021-01-07 14:38:11

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 06/13] kdev_t: always inline major/minor helper functions

From: Josh Poimboeuf <[email protected]>

commit aa8c7db494d0a83ecae583aa193f1134ef25d506 upstream.

Silly GCC doesn't always inline these trivial functions.

Fixes the following warning:

arch/x86/kernel/sys_ia32.o: warning: objtool: cp_stat64()+0xd8: call to new_encode_dev() with UACCESS enabled

Link: https://lkml.kernel.org/r/984353b44a4484d86ba9f73884b7306232e25e30.1608737428.git.jpoimboe@redhat.com
Signed-off-by: Josh Poimboeuf <[email protected]>
Reported-by: Randy Dunlap <[email protected]>
Acked-by: Randy Dunlap <[email protected]> [build-tested]
Cc: Peter Zijlstra <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
include/linux/kdev_t.h | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)

--- a/include/linux/kdev_t.h
+++ b/include/linux/kdev_t.h
@@ -21,61 +21,61 @@
})

/* acceptable for old filesystems */
-static inline bool old_valid_dev(dev_t dev)
+static __always_inline bool old_valid_dev(dev_t dev)
{
return MAJOR(dev) < 256 && MINOR(dev) < 256;
}

-static inline u16 old_encode_dev(dev_t dev)
+static __always_inline u16 old_encode_dev(dev_t dev)
{
return (MAJOR(dev) << 8) | MINOR(dev);
}

-static inline dev_t old_decode_dev(u16 val)
+static __always_inline dev_t old_decode_dev(u16 val)
{
return MKDEV((val >> 8) & 255, val & 255);
}

-static inline u32 new_encode_dev(dev_t dev)
+static __always_inline u32 new_encode_dev(dev_t dev)
{
unsigned major = MAJOR(dev);
unsigned minor = MINOR(dev);
return (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12);
}

-static inline dev_t new_decode_dev(u32 dev)
+static __always_inline dev_t new_decode_dev(u32 dev)
{
unsigned major = (dev & 0xfff00) >> 8;
unsigned minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);
return MKDEV(major, minor);
}

-static inline u64 huge_encode_dev(dev_t dev)
+static __always_inline u64 huge_encode_dev(dev_t dev)
{
return new_encode_dev(dev);
}

-static inline dev_t huge_decode_dev(u64 dev)
+static __always_inline dev_t huge_decode_dev(u64 dev)
{
return new_decode_dev(dev);
}

-static inline int sysv_valid_dev(dev_t dev)
+static __always_inline int sysv_valid_dev(dev_t dev)
{
return MAJOR(dev) < (1<<14) && MINOR(dev) < (1<<18);
}

-static inline u32 sysv_encode_dev(dev_t dev)
+static __always_inline u32 sysv_encode_dev(dev_t dev)
{
return MINOR(dev) | (MAJOR(dev) << 18);
}

-static inline unsigned sysv_major(u32 dev)
+static __always_inline unsigned sysv_major(u32 dev)
{
return (dev >> 18) & 0x3fff;
}

-static inline unsigned sysv_minor(u32 dev)
+static __always_inline unsigned sysv_minor(u32 dev)
{
return dev & 0x3ffff;
}


2021-01-07 14:38:14

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 11/13] rwsem: Implement down_read_interruptible

From: Eric W. Biederman <[email protected]>

[ Upstream commit 31784cff7ee073b34d6eddabb95e3be2880a425c ]

In preparation for converting exec_update_mutex to a rwsem so that
multiple readers can execute in parallel and not deadlock, add
down_read_interruptible. This is needed for perf_event_open to be
converted (with no semantic changes) from working on a mutex to
wroking on a rwsem.

Signed-off-by: Eric W. Biederman <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Sasha Levin <[email protected]>
---
include/linux/rwsem.h | 1 +
kernel/locking/rwsem.c | 26 ++++++++++++++++++++++++++
2 files changed, 27 insertions(+)

diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h
index c91ac00d1ff8c..8a3606372abc8 100644
--- a/include/linux/rwsem.h
+++ b/include/linux/rwsem.h
@@ -125,6 +125,7 @@ static inline int rwsem_is_contended(struct rw_semaphore *sem)
* lock for reading
*/
extern void down_read(struct rw_semaphore *sem);
+extern int __must_check down_read_interruptible(struct rw_semaphore *sem);
extern int __must_check down_read_killable(struct rw_semaphore *sem);

/*
diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c
index 2ce13f9585779..a5eb87f2c5816 100644
--- a/kernel/locking/rwsem.c
+++ b/kernel/locking/rwsem.c
@@ -1348,6 +1348,18 @@ inline void __down_read(struct rw_semaphore *sem)
}
}

+static inline int __down_read_interruptible(struct rw_semaphore *sem)
+{
+ if (!rwsem_read_trylock(sem)) {
+ if (IS_ERR(rwsem_down_read_slowpath(sem, TASK_INTERRUPTIBLE)))
+ return -EINTR;
+ DEBUG_RWSEMS_WARN_ON(!is_rwsem_reader_owned(sem), sem);
+ } else {
+ rwsem_set_reader_owned(sem);
+ }
+ return 0;
+}
+
static inline int __down_read_killable(struct rw_semaphore *sem)
{
if (!rwsem_read_trylock(sem)) {
@@ -1498,6 +1510,20 @@ void __sched down_read(struct rw_semaphore *sem)
}
EXPORT_SYMBOL(down_read);

+int __sched down_read_interruptible(struct rw_semaphore *sem)
+{
+ might_sleep();
+ rwsem_acquire_read(&sem->dep_map, 0, 0, _RET_IP_);
+
+ if (LOCK_CONTENDED_RETURN(sem, __down_read_trylock, __down_read_interruptible)) {
+ rwsem_release(&sem->dep_map, _RET_IP_);
+ return -EINTR;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(down_read_interruptible);
+
int __sched down_read_killable(struct rw_semaphore *sem)
{
might_sleep();
--
2.27.0



2021-01-07 14:38:19

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 04/13] dmaengine: at_hdmac: add missing put_device() call in at_dma_xlate()

From: Yu Kuai <[email protected]>

commit 3832b78b3ec2cf51e07102f9b4480e343459b20f upstream.

If of_find_device_by_node() succeed, at_dma_xlate() doesn't have a
corresponding put_device(). Thus add put_device() to fix the exception
handling for this function implementation.

Fixes: bbe89c8e3d59 ("at_hdmac: move to generic DMA binding")
Signed-off-by: Yu Kuai <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Vinod Koul <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/dma/at_hdmac.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)

--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -1674,8 +1674,10 @@ static struct dma_chan *at_dma_xlate(str
dma_cap_set(DMA_SLAVE, mask);

atslave = kmalloc(sizeof(*atslave), GFP_KERNEL);
- if (!atslave)
+ if (!atslave) {
+ put_device(&dmac_pdev->dev);
return NULL;
+ }

atslave->cfg = ATC_DST_H2SEL_HW | ATC_SRC_H2SEL_HW;
/*
@@ -1704,8 +1706,10 @@ static struct dma_chan *at_dma_xlate(str
atslave->dma_dev = &dmac_pdev->dev;

chan = dma_request_channel(mask, at_dma_filter, atslave);
- if (!chan)
+ if (!chan) {
+ put_device(&dmac_pdev->dev);
return NULL;
+ }

atchan = to_at_dma_chan(chan);
atchan->per_if = dma_spec->args[0] & 0xff;


2021-01-07 14:39:46

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.4 10/13] rwsem: Implement down_read_killable_nested

From: Eric W. Biederman <[email protected]>

[ Upstream commit 0f9368b5bf6db0c04afc5454b1be79022a681615 ]

In preparation for converting exec_update_mutex to a rwsem so that
multiple readers can execute in parallel and not deadlock, add
down_read_killable_nested. This is needed so that kcmp_lock
can be converted from working on a mutexes to working on rw_semaphores.

Signed-off-by: Eric W. Biederman <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Sasha Levin <[email protected]>
---
include/linux/rwsem.h | 2 ++
kernel/locking/rwsem.c | 14 ++++++++++++++
2 files changed, 16 insertions(+)

diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h
index 00d6054687dd2..c91ac00d1ff8c 100644
--- a/include/linux/rwsem.h
+++ b/include/linux/rwsem.h
@@ -173,6 +173,7 @@ extern void downgrade_write(struct rw_semaphore *sem);
* See Documentation/locking/lockdep-design.rst for more details.)
*/
extern void down_read_nested(struct rw_semaphore *sem, int subclass);
+extern int __must_check down_read_killable_nested(struct rw_semaphore *sem, int subclass);
extern void down_write_nested(struct rw_semaphore *sem, int subclass);
extern int down_write_killable_nested(struct rw_semaphore *sem, int subclass);
extern void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest_lock);
@@ -193,6 +194,7 @@ extern void down_read_non_owner(struct rw_semaphore *sem);
extern void up_read_non_owner(struct rw_semaphore *sem);
#else
# define down_read_nested(sem, subclass) down_read(sem)
+# define down_read_killable_nested(sem, subclass) down_read_killable(sem)
# define down_write_nest_lock(sem, nest_lock) down_write(sem)
# define down_write_nested(sem, subclass) down_write(sem)
# define down_write_killable_nested(sem, subclass) down_write_killable(sem)
diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c
index baafa1dd9fcc4..2ce13f9585779 100644
--- a/kernel/locking/rwsem.c
+++ b/kernel/locking/rwsem.c
@@ -1608,6 +1608,20 @@ void down_read_nested(struct rw_semaphore *sem, int subclass)
}
EXPORT_SYMBOL(down_read_nested);

+int down_read_killable_nested(struct rw_semaphore *sem, int subclass)
+{
+ might_sleep();
+ rwsem_acquire_read(&sem->dep_map, subclass, 0, _RET_IP_);
+
+ if (LOCK_CONTENDED_RETURN(sem, __down_read_trylock, __down_read_killable)) {
+ rwsem_release(&sem->dep_map, _RET_IP_);
+ return -EINTR;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(down_read_killable_nested);
+
void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest)
{
might_sleep();
--
2.27.0



2021-01-08 01:15:30

by Shuah Khan

[permalink] [raw]
Subject: Re: [PATCH 5.4 00/13] 5.4.88-rc1 review

On 1/7/21 7:33 AM, Greg Kroah-Hartman wrote:
> This is the start of the stable review cycle for the 5.4.88 release.
> There are 13 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Sat, 09 Jan 2021 14:30:35 +0000.
> Anything received after that time might be too late.
>
> The whole patch series can be found in one patch at:
> https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.4.88-rc1.gz
> or in the git tree and branch at:
> git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.4.y
> and the diffstat can be found below.
>
> thanks,
>
> greg k-h
>
Compiled and booted on my test system. No dmesg regressions.

Tested-by: Shuah Khan <[email protected]>

thanks,
-- Shuah

2021-01-08 02:31:56

by Naresh Kamboju

[permalink] [raw]
Subject: Re: [PATCH 5.4 00/13] 5.4.88-rc1 review

On Thu, 7 Jan 2021 at 20:02, Greg Kroah-Hartman
<[email protected]> wrote:
>
> This is the start of the stable review cycle for the 5.4.88 release.
> There are 13 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Sat, 09 Jan 2021 14:30:35 +0000.
> Anything received after that time might be too late.
>
> The whole patch series can be found in one patch at:
> https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.4.88-rc1.gz
> or in the git tree and branch at:
> git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.4.y
> and the diffstat can be found below.
>
> thanks,
>
> greg k-h

Results from Linaro’s test farm.
No regressions on arm64, arm, x86_64, and i386.

Tested-by: Linux Kernel Functional Testing <[email protected]>

Summary
------------------------------------------------------------------------

kernel: 5.4.88-rc1
git repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
git branch: linux-5.4.y
git commit: f52a40401ee9825556cc803c110c67bfec5f6b94
git describe: v5.4.87-14-gf52a40401ee9
Test details: https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-5.4.y/build/v5.4.87-14-gf52a40401ee9

No regressions (compared to build v5.4.87)

No fixes (compared to build v5.4.87)


Ran 47652 total tests in the following environments and test suites.

Environments
--------------
- arc
- arm
- arm64
- dragonboard-410c
- hi6220-hikey
- i386
- juno-r2
- juno-r2-compat
- juno-r2-kasan
- mips
- nxp-ls2088
- parisc
- powerpc
- qemu-arm-clang
- qemu-arm64-clang
- qemu-arm64-kasan
- qemu-x86_64-clang
- qemu-x86_64-kasan
- qemu-x86_64-kcsan
- qemu_arm
- qemu_arm64
- qemu_arm64-compat
- qemu_i386
- qemu_x86_64
- qemu_x86_64-compat
- riscv
- s390
- sh
- sparc
- x15
- x86
- x86-kasan

Test Suites
-----------
* build
* linux-log-parser
* install-android-platform-tools-r2600
* ltp-containers-tests
* ltp-controllers-tests
* ltp-dio-tests
* ltp-fcntl-locktests-tests
* ltp-filecaps-tests
* ltp-fs_bind-tests
* ltp-fs_perms_simple-tests
* ltp-fsx-tests
* ltp-hugetlb-tests
* ltp-io-tests
* ltp-mm-tests
* perf
* fwts
* kselftest
* kvm-unit-tests
* libhugetlbfs
* ltp-cap_bounds-tests
* ltp-commands-tests
* ltp-cpuhotplug-tests
* ltp-crypto-tests
* ltp-cve-tests
* ltp-fs-tests
* ltp-ipc-tests
* ltp-math-tests
* ltp-nptl-tests
* ltp-pty-tests
* ltp-sched-tests
* ltp-securebits-tests
* ltp-syscalls-tests
* ltp-tracing-tests
* network-basic-tests
* v4l2-compliance
* ltp-open-posix-tests
* rcutorture
* kselftest-vsyscall-mode-native
* kselftest-vsyscall-mode-none

--
Linaro LKFT
https://lkft.linaro.org

2021-01-08 17:42:26

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH 5.4 00/13] 5.4.88-rc1 review

On Thu, Jan 07, 2021 at 03:33:19PM +0100, Greg Kroah-Hartman wrote:
> This is the start of the stable review cycle for the 5.4.88 release.
> There are 13 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Sat, 09 Jan 2021 14:30:35 +0000.
> Anything received after that time might be too late.
>

Build results:
total: 157 pass: 157 fail: 0
Qemu test results:
total: 427 pass: 427 fail: 0

Tested-by: Guenter Roeck <[email protected]>

Guenter