5.4.19-stable review
Subsystems (3)
Greg Kroah-Hartman
maintainerPATCH 136/309 ASoC: SOF: core: release resources on errors in probe_continue
In reply to Greg Kroah-HartmanFrom: Pierre-Louis Bossart <[email protected]>
[ Upstream commit 410e5e55c9c1c9c0d452ac5b9adb37b933a7747e ]
The initial intent of releasing resources in the .remove does not work well with HDaudio codecs. If the probe_continue() fails in a work queue, e.g. due to missing firmware or authentication issues, we don't release any resources, and as a result the kernel oopses during suspend operations.
The suggested fix is to release all resources during errors in probe_continue(), and use fw_state to track resource allocation state, so that .remove does not attempt to release the same hardware resources twice. PM operations are also modified so that no action is done if DSP resources have been freed due to an error at probe.
Bugzilla: http://bugzilla.suse.com/show_bug.cgi?id=1161246
--- sound/soc/sof/core.c | 32 +++++++++++--------------------- sound/soc/sof/pm.c | 4 ++++ 2 files changed, 15 insertions(+), 21 deletions(-)
sound/soc/sof/core.c +11 -21
@@ -440,7 +440,6 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)return 0 ; -#if !IS_ENABLED (CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE ) fw_trace_err:snd_sof_free_trace (sdev); fw_run_err:
@@ -451,22 +450,10 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)snd_sof_free_debug (sdev); dbg_err:snd_sof_remove (sdev); -#else - -/* -* when the probe_continue is handled in a work queue, the -* probe does not fail so we don't release resources here. -* They will be released with an explicit call to -* snd_sof_device_remove() when the PCI/ACPI device is removed -*/ - -fw_trace_err: -fw_run_err: -fw_load_err: -ipc_err: -dbg_err: -#endif +/* all resources freed, update state to match */ + sdev->fw_state =SOF_FW_BOOT_NOT_STARTED ; + sdev->first_boot = true;return ret; }
@@ -545,10 +532,12 @@ int snd_sof_device_remove(struct device *dev)if (IS_ENABLED (CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE ))cancel_work_sync (&sdev->probe_work); -snd_sof_fw_unload (sdev); -snd_sof_ipc_free (sdev); -snd_sof_free_debug (sdev); -snd_sof_free_trace (sdev); +if (sdev->fw_state >SOF_FW_BOOT_NOT_STARTED ) { +snd_sof_fw_unload (sdev); +snd_sof_ipc_free (sdev); +snd_sof_free_debug (sdev); +snd_sof_free_trace (sdev); + }/* * Unregister machine driver. This will unbind the snd_card which
@@ -564,7 +553,8 @@ int snd_sof_device_remove(struct device *dev)* scheduled on, when they are unloaded. Therefore, the DSP must be * removed only after the topology has been unloaded. */ -snd_sof_remove (sdev); +if (sdev->fw_state >SOF_FW_BOOT_NOT_STARTED ) +snd_sof_remove (sdev);/* release firmware */ release_firmware (pdata->fw);
sound/soc/sof/pm.c +4 -0
@@ -269,6 +269,10 @@ static int sof_resume(struct device *dev, bool runtime_resume)if (!sof_ops (sdev)->resume || !sof_ops (sdev)->runtime_resume)return 0 ; +/* DSP was never successfully started, nothing to resume */ +if (sdev->first_boot) +return 0 ; +/* * if the runtime_resume flag is set, call the runtime_resume routine * or else call the system resume routine
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 137/309 tracing: Annotate ftrace_graph_hash pointer with __rcu
In reply to Greg Kroah-HartmanFrom: Amol Grover <[email protected]>
[ Upstream commit 24a9729f831462b1d9d61dc85ecc91c59037243f ]
Fix following instances of sparse error kernel/trace/ftrace.c:5664:29: error: incompatible types in comparison kernel/trace/ftrace.c:5785:21: error: incompatible types in comparison kernel/trace/ftrace.c:5864:36: error: incompatible types in comparison kernel/trace/ftrace.c:5866:25: error: incompatible types in comparison
Use rcu_dereference_protected to access the __rcu annotated pointer.
--- kernel/trace/ftrace.c | 2 +- kernel/trace/trace.h | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-)
kernel/trace/ftrace.c +1 -1
@@ -5102,7 +5102,7 @@ static const struct file_operations ftrace_notrace_fops = {static DEFINE_MUTEX (graph_lock); -struct ftrace_hash *ftrace_graph_hash =EMPTY_HASH ; +struct ftrace_hash __rcu *ftrace_graph_hash =EMPTY_HASH ;struct ftrace_hash *ftrace_graph_notrace_hash =EMPTY_HASH ;enum graph_filter_type {
kernel/trace/trace.h +6 -3
@@ -932,22 +932,25 @@ extern void __trace_graph_return(struct trace_array *tr, unsigned long flags, int pc);#ifdef CONFIG_DYNAMIC_FTRACE -extern struct ftrace_hash *ftrace_graph_hash; +extern struct ftrace_hash __rcu *ftrace_graph_hash;extern struct ftrace_hash *ftrace_graph_notrace_hash;static inline int ftrace_graph_addr (struct ftrace_graph_ent *trace) {unsigned long addr = trace->func;int ret =0 ; +struct ftrace_hash *hash;preempt_disable_notrace (); -if (ftrace_hash_empty (ftrace_graph_hash)) { + hash =rcu_dereference_protected (ftrace_graph_hash, !preemptible ()); + +if (ftrace_hash_empty (hash)) { ret =1 ; goto out; } -if (ftrace_lookup_ip (ftrace_graph_hash, addr)) { +if (ftrace_lookup_ip (hash, addr)) {/* * This needs to be cleared on the return functions
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 138/309 tracing: Annotate ftrace_graph_notrace_hash pointer with __rcu
In reply to Greg Kroah-HartmanFrom: Amol Grover <[email protected]>
[ Upstream commit fd0e6852c407dd9aefc594f54ddcc21d84803d3b ]
Fix following instances of sparse error kernel/trace/ftrace.c:5667:29: error: incompatible types in comparison kernel/trace/ftrace.c:5813:21: error: incompatible types in comparison kernel/trace/ftrace.c:5868:36: error: incompatible types in comparison kernel/trace/ftrace.c:5870:25: error: incompatible types in comparison
Use rcu_dereference_protected to dereference the newly annotated pointer.
--- kernel/trace/ftrace.c | 2 +- kernel/trace/trace.h | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-)
kernel/trace/ftrace.c +1 -1
@@ -5103,7 +5103,7 @@ static const struct file_operations ftrace_notrace_fops = {static DEFINE_MUTEX (graph_lock);struct ftrace_hash __rcu *ftrace_graph_hash =EMPTY_HASH ; -struct ftrace_hash *ftrace_graph_notrace_hash =EMPTY_HASH ; +struct ftrace_hash __rcu *ftrace_graph_notrace_hash =EMPTY_HASH ;enum graph_filter_type {GRAPH_FILTER_NOTRACE =0 ,
kernel/trace/trace.h +6 -2
@@ -933,7 +933,7 @@ extern void __trace_graph_return(struct trace_array *tr,#ifdef CONFIG_DYNAMIC_FTRACE extern struct ftrace_hash __rcu *ftrace_graph_hash; -extern struct ftrace_hash *ftrace_graph_notrace_hash; +extern struct ftrace_hash __rcu *ftrace_graph_notrace_hash;static inline int ftrace_graph_addr (struct ftrace_graph_ent *trace) {
@@ -986,10 +986,14 @@ static inline void ftrace_graph_addr_finish(struct ftrace_graph_ret *trace)static inline int ftrace_graph_notrace_addr (unsigned long addr) {int ret =0 ; +struct ftrace_hash *notrace_hash;preempt_disable_notrace (); -if (ftrace_lookup_ip (ftrace_graph_notrace_hash, addr)) + notrace_hash =rcu_dereference_protected (ftrace_graph_notrace_hash, + !preemptible ()); + +if (ftrace_lookup_ip (notrace_hash, addr)) ret =1 ;preempt_enable_notrace ();
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 139/309 ftrace: Add comment to why rcu_dereference_sched() is open coded
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (VMware) <[email protected]>
[ Upstream commit 16052dd5bdfa16dbe18d8c1d4cde2ddab9d23177 ]
Because the function graph tracer can execute in sections where RCU is not "watching", the rcu_dereference_sched() for the has needs to be open coded. This is fine because the RCU "flavor" of the ftrace hash is protected by its own RCU handling (it does its own little synchronization on every CPU and does not rely on RCU sched).
--- kernel/trace/trace.h | 10 ++++++++++ 1 file changed, 10 insertions(+)
kernel/trace/trace.h +10 -0
@@ -943,6 +943,11 @@ static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace)preempt_disable_notrace (); +/* +* Have to open code "rcu_dereference_sched()" because the +* function graph tracer can be called when RCU is not +* "watching". +*/ hash =rcu_dereference_protected (ftrace_graph_hash, !preemptible ());if (ftrace_hash_empty (hash)) {
@@ -990,6 +995,11 @@ static inline int ftrace_graph_notrace_addr(unsigned long addr)preempt_disable_notrace (); +/* +* Have to open code "rcu_dereference_sched()" because the +* function graph tracer can be called when RCU is not +* "watching". +*/ notrace_hash =rcu_dereference_protected (ftrace_graph_notrace_hash, !preemptible ());
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 140/309 ftrace: Protect ftrace_graph_hash with ftrace_sync
In reply to Greg Kroah-HartmanFrom: Steven Rostedt (VMware) <[email protected]>
[ Upstream commit 54a16ff6f2e50775145b210bcd94d62c3c2af117 ]
As function_graph tracer can run when RCU is not "watching", it can not be protected by synchronize_rcu() it requires running a task on each CPU before it can be freed. Calling schedule_on_each_cpu(ftrace_sync) needs to be used.
--- kernel/trace/ftrace.c | 11 +++++++++-- kernel/trace/trace.h | 2 ++ 2 files changed, 11 insertions(+), 2 deletions(-)
kernel/trace/ftrace.c +9 -2
@@ -5378,8 +5378,15 @@ ftrace_graph_release(struct inode *inode, struct file *file)mutex_unlock (&graph_lock); -/* Wait till all users are no longer using the old hash */ -synchronize_rcu (); +/* +* We need to do a hard force of sched synchronization. +* This is because we use preempt_disable() to do RCU, but +* the function tracers can be called where RCU is not watching +* (like before user_exit()). We can not rely on the RCU +* infrastructure to do the synchronization, thus we must do it +* ourselves. +*/ +schedule_on_each_cpu (ftrace_sync);free_ftrace_hash (old_hash); }
kernel/trace/trace.h +2 -0
@@ -947,6 +947,7 @@ static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace)* Have to open code "rcu_dereference_sched()" because the * function graph tracer can be called when RCU is not * "watching". +* Protected with schedule_on_each_cpu(ftrace_sync) */ hash =rcu_dereference_protected (ftrace_graph_hash, !preemptible ());
@@ -999,6 +1000,7 @@ static inline int ftrace_graph_notrace_addr(unsigned long addr)* Have to open code "rcu_dereference_sched()" because the * function graph tracer can be called when RCU is not * "watching". +* Protected with schedule_on_each_cpu(ftrace_sync) */ notrace_hash =rcu_dereference_protected (ftrace_graph_notrace_hash, !preemptible ());
Signature · 1 line
2.20.1
Greg Kroah-Hartman
maintainerPATCH 141/309 crypto: pcrypt - Avoid deadlock by using per-instance padata queues
In reply to Greg Kroah-HartmanFrom: Herbert Xu <[email protected]>
commit bbefa1dd6a6d53537c11624752219e39959d04fb upstream.
If the pcrypt template is used multiple times in an algorithm, then a deadlock occurs because all pcrypt instances share the same padata_instance, which completes requests in the order submitted. That is, the inner pcrypt request waits for the outer pcrypt request while the outer request is already waiting for the inner.
This patch fixes this by allocating a set of queues for each pcrypt instance instead of using two global queues. In order to maintain the existing user-space interface, the pinst structure remains global so any sysfs modifications will apply to every pcrypt instance.
Note that when an update occurs we have to allocate memory for every pcrypt instance. Should one of the allocations fail we will abort the update without rolling back changes already made.
The new per-instance data structure is called padata_shell and is essentially a wrapper around parallel_data.
Reproducer:
#include <linux/if_alg.h>
#include <sys/socket.h>
#include <unistd.h>
int main()
{
struct sockaddr_alg addr = {
.salg_type = "aead",
.salg_name = "pcrypt(pcrypt(rfc4106-gcm-aesni))"
};
int algfd, reqfd;
char buf[32] = { 0 };
algfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
bind(algfd, (void *)&addr, sizeof(addr));
setsockopt(algfd, SOL_ALG, ALG_SET_KEY, buf, 20);
reqfd = accept(algfd, 0, 0);
write(reqfd, buf, 32);
read(reqfd, buf, 16);
}--- crypto/pcrypt.c | 36 ++++++- include/linux/padata.h | 34 ++++++- kernel/padata.c | 236 ++++++++++++++++++++++++++++++++++--------------- 3 files changed, 227 insertions(+), 79 deletions(-)
crypto/pcrypt.c +33 -3
@@ -24,6 +24,8 @@ static struct kset *pcrypt_ksestruct pcrypt_instance_ctx {struct crypto_aead_spawn spawn; +struct padata_shell *psenc; +struct padata_shell *psdec;atomic_t tfm_count; };
@@ -32,6 +34,12 @@ struct pcrypt_aead_ctx {unsigned int cb_cpu; }; +static inline struct pcrypt_instance_ctx *pcrypt_tfm_ictx ( +struct crypto_aead *tfm) +{ +return aead_instance_ctx (aead_alg_instance (tfm)); +} +static int pcrypt_aead_setkey (struct crypto_aead *parent,const u8 *key,unsigned int keylen) {
@@ -90,6 +98,9 @@ static int pcrypt_aead_encrypt(struct aestruct crypto_aead *aead =crypto_aead_reqtfm (req);struct pcrypt_aead_ctx *ctx =crypto_aead_ctx (aead);u32 flags =aead_request_flags (req); +struct pcrypt_instance_ctx *ictx; + + ictx =pcrypt_tfm_ictx (aead);memset (padata,0 ,sizeof (struct padata_priv ));
@@ -103,7 +114,7 @@ static int pcrypt_aead_encrypt(struct ae req->cryptlen, req->iv);aead_request_set_ad (creq, req->assoclen); - err =padata_do_parallel (pencrypt, padata, &ctx->cb_cpu); + err =padata_do_parallel (ictx->psenc, padata, &ctx->cb_cpu);if (!err)return -EINPROGRESS ;
@@ -132,6 +143,9 @@ static int pcrypt_aead_decrypt(struct aestruct crypto_aead *aead =crypto_aead_reqtfm (req);struct pcrypt_aead_ctx *ctx =crypto_aead_ctx (aead);u32 flags =aead_request_flags (req); +struct pcrypt_instance_ctx *ictx; + + ictx =pcrypt_tfm_ictx (aead);memset (padata,0 ,sizeof (struct padata_priv ));
@@ -145,7 +159,7 @@ static int pcrypt_aead_decrypt(struct ae req->cryptlen, req->iv);aead_request_set_ad (creq, req->assoclen); - err =padata_do_parallel (pdecrypt, padata, &ctx->cb_cpu); + err =padata_do_parallel (ictx->psdec, padata, &ctx->cb_cpu);if (!err)return -EINPROGRESS ;
@@ -192,6 +206,8 @@ static void pcrypt_free(struct aead_inststruct pcrypt_instance_ctx *ctx =aead_instance_ctx (inst);crypto_drop_aead (&ctx->spawn); +padata_free_shell (ctx->psdec); +padata_free_shell (ctx->psenc);kfree (inst); }
@@ -233,12 +249,22 @@ static int pcrypt_create_aead(struct cryif (!inst)return -ENOMEM ; + err = -ENOMEM ; + ctx =aead_instance_ctx (inst); + ctx->psenc =padata_alloc_shell (pencrypt); +if (!ctx->psenc) + goto out_free_inst; + + ctx->psdec =padata_alloc_shell (pdecrypt); +if (!ctx->psdec) + goto out_free_psenc; +crypto_set_aead_spawn (&ctx->spawn,aead_crypto_instance (inst)); err =crypto_grab_aead (&ctx->spawn, name,0 ,0 );if (err) - goto out_free_inst; + goto out_free_psdec; alg =crypto_spawn_aead_alg (&ctx->spawn); err =pcrypt_init_instance (aead_crypto_instance (inst), &alg->base);
@@ -271,6 +297,10 @@ out: out_drop_aead:crypto_drop_aead (&ctx->spawn); +out_free_psdec: +padata_free_shell (ctx->psdec); +out_free_psenc: +padata_free_shell (ctx->psenc); out_free_inst:kfree (inst); goto out;
include/linux/padata.h +29 -5
@@ -9,6 +9,7 @@#ifndef PADATA_H #define PADATA_H +#include <linux/compiler_types.h> #include <linux/workqueue.h> #include <linux/spinlock.h> #include <linux/list.h>
@@ -98,7 +99,7 @@ struct padata_cpumask {* struct parallel_data - Internal control structure, covers everything * that depends on the cpumask in use. * -* @pinst: padata instance. +* @sh: padata_shell object. * @pqueue: percpu padata queues used for parallelization. * @squeue: percpu padata queues used for serialuzation. * @reorder_objects: Number of objects waiting in the reorder queues.
@@ -111,7 +112,7 @@ struct padata_cpumask {* @lock: Reorder lock. */ struct parallel_data { -struct padata_instance *pinst; +struct padata_shell *ps;struct padata_parallel_queue __percpu *pqueue;struct padata_serial_queue __percpu *squeue;atomic_t reorder_objects;
@@ -125,13 +126,32 @@ struct parallel_data { };/** +* struct padata_shell - Wrapper around struct parallel_data, its +* purpose is to allow the underlying control structure to be replaced +* on the fly using RCU. +* +* @pinst: padat instance. +* @pd: Actual parallel_data structure which may be substituted on the fly. +* @opd: Pointer to old pd to be freed by padata_replace. +* @list: List entry in padata_instance list. +*/ +struct padata_shell { +struct padata_instance *pinst; +struct parallel_data __rcu *pd; +struct parallel_data *opd; +struct list_head list; +}; + +/** * struct padata_instance - The overall control structure. * * @cpu_notifier: cpu hotplug notifier. * @parallel_wq: The workqueue used for parallel work. * @serial_wq: The workqueue used for serial work. -* @pd: The internal control structure. +* @pslist: List of padata_shell objects attached to this instance. * @cpumask: User supplied cpumasks for parallel and serial works. +* @rcpumask: Actual cpumasks based on user cpumask and cpu_online_mask. +* @omask: Temporary storage used to compute the notification mask. * @cpumask_change_notifier: Notifiers chain for user-defined notify * callbacks that will be called when either @pcpu or @cbcpu * or both cpumasks change.
@@ -143,8 +163,10 @@ struct padata_instance {struct hlist_node node;struct workqueue_struct *parallel_wq;struct workqueue_struct *serial_wq; -struct parallel_data *pd; +struct list_head pslist;struct padata_cpumask cpumask; +struct padata_cpumask rcpumask; +cpumask_var_t omask;struct blocking_notifier_head cpumask_change_notifier;struct kobject kobj;struct mutex lock;
@@ -156,7 +178,9 @@ struct padata_instance {extern struct padata_instance *padata_alloc_possible (const char *name);extern void padata_free (struct padata_instance *pinst); -extern int padata_do_parallel (struct padata_instance *pinst, +extern struct padata_shell *padata_alloc_shell (struct padata_instance *pinst); +extern void padata_free_shell (struct padata_shell *ps); +extern int padata_do_parallel (struct padata_shell *ps,struct padata_priv *padata,int *cb_cpu);extern void padata_do_serial (struct padata_priv *padata); extern int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type,
kernel/padata.c +165 -71
399 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 142/309 btrfs: fix improper setting of scanned for range cyclic write cache pages
In reply to Greg Kroah-HartmanFrom: Josef Bacik <[email protected]>
commit 556755a8a99be8ca3cd9fbe36aaf9b3b0339a00d upstream.
We noticed that we were having regular CG OOM kills in cases where there was still enough dirty pages to avoid OOM'ing. It turned out there's this corner case in btrfs's handling of range_cyclic where files that were being redirtied were not getting fully written out because of how we do range_cyclic writeback.
We unconditionally were setting scanned = 1; the first time we found any pages in the inode. This isn't actually what we want, we want it to be set if we've scanned the entire file. For range_cyclic we could be starting in the middle or towards the end of the file, so we could write one page and then not write any of the other dirty pages in the file because we set scanned = 1.
Fix this by not setting scanned = 1 if we find pages. The rules for setting scanned should be
1) !range_cyclic. In this case we have a specified range to write out.
2) range_cyclic && index == 0. In this case we've started at the beginning and there is no need to loop around a second time.
3) range_cyclic && we started at index > 0 and we've reached the end of the file without satisfying our nr_to_write.
This patch fixes both of our writepages implementations to make sure these rules hold true. This fixed our over zealous CG OOMs in production.
--- fs/btrfs/extent_io.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
fs/btrfs/extent_io.c +10 -2
@@ -3938,6 +3938,11 @@ int btree_write_cache_pages(struct addreif (wbc->range_cyclic) { index = mapping->writeback_index;/* Start from prev offset */ end =-1 ; +/* +* Start from the beginning does not need to cycle over the +* range, mark it as scanned. +*/ + scanned = (index ==0 ); }else { index = wbc->range_start >>PAGE_SHIFT ; end = wbc->range_end >>PAGE_SHIFT ;
@@ -3955,7 +3960,6 @@ retry: tag))) {unsigned i; - scanned =1 ;for (i =0 ; i < nr_pages; i++) {struct page *page = pvec.pages[i];
@@ -4084,6 +4088,11 @@ static int extent_write_cache_pages(struif (wbc->range_cyclic) { index = mapping->writeback_index;/* Start from prev offset */ end =-1 ; +/* +* Start from the beginning does not need to cycle over the +* range, mark it as scanned. +*/ + scanned = (index ==0 ); }else { index = wbc->range_start >>PAGE_SHIFT ; end = wbc->range_end >>PAGE_SHIFT ;
@@ -4117,7 +4126,6 @@ retry: &index, end, tag))) {unsigned i; - scanned =1 ;for (i =0 ; i < nr_pages; i++) {struct page *page = pvec.pages[i];
Greg Kroah-Hartman
maintainerPATCH 143/309 btrfs: Handle another split brain scenario with metadata uuid feature
In reply to Greg Kroah-HartmanFrom: Nikolay Borisov <[email protected]>
commit 05840710149c7d1a78ea85a2db5723f706e97d8f upstream.
There is one more cases which isn't handled by the original metadata uuid work. Namely, when a filesystem has METADATA_UUID incompat bit and the user decides to change the FSID to the original one e.g. have metadata_uuid and fsid match. In case of power failure while this operation is in progress we could end up in a situation where some of the disks have the incompat bit removed and the other half have both METADATA_UUID_INCOMPAT and FSID_CHANGING_IN_PROGRESS flags.
This patch handles the case where a disk that has successfully changed its FSID such that it equals METADATA_UUID is scanned first. Subsequently when a disk with both METADATA_UUID_INCOMPAT/FSID_CHANGING_IN_PROGRESS flags is scanned find_fsid_changed won't be able to find an appropriate btrfs_fs_devices. This is done by extending find_fsid_changed to correctly find btrfs_fs_devices whose metadata_uuid/fsid are the same and they match the metadata_uuid of the currently scanned device.
--- fs/btrfs/volumes.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
fs/btrfs/volumes.c +14 -3
@@ -881,17 +881,28 @@ static struct btrfs_fs_devices *find_fsi/* * Handles the case where scanned device is part of an fs that had * multiple successful changes of FSID but curently device didn't -* observe it. Meaning our fsid will be different than theirs. +* observe it. Meaning our fsid will be different than theirs. We need +* to handle two subcases : +* 1 - The fs still continues to have different METADATA/FSID uuids. +* 2 - The fs is switched back to its original FSID (METADATA/FSID +* are equal). */ list_for_each_entry (fs_devices, &fs_uuids, fs_list) { +/* Changed UUIDs */ if (memcmp (fs_devices->metadata_uuid, fs_devices->fsid,BTRFS_FSID_SIZE ) !=0 &&memcmp (fs_devices->metadata_uuid, disk_super->metadata_uuid,BTRFS_FSID_SIZE ) ==0 &&memcmp (fs_devices->fsid, disk_super->fsid, -BTRFS_FSID_SIZE ) !=0 ) { +BTRFS_FSID_SIZE ) !=0 ) +return fs_devices; + +/* Unchanged UUIDs */ +if (memcmp (fs_devices->metadata_uuid, fs_devices->fsid, +BTRFS_FSID_SIZE ) ==0 && +memcmp (fs_devices->fsid, disk_super->metadata_uuid, +BTRFS_FSID_SIZE ) ==0 )return fs_devices; - } }return NULL ;
Greg Kroah-Hartman
maintainerPATCH 144/309 riscv, bpf: Fix broken BPF tail calls
In reply to Greg Kroah-HartmanFrom: Björn Töpel <[email protected]>
commit f1003b787c00fbaa4b11619c6b23a885bfce8f07 upstream.
The BPF JIT incorrectly clobbered the a0 register, and did not flag usage of s5 register when BPF stack was being used.
--- arch/riscv/net/bpf_jit_comp.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
arch/riscv/net/bpf_jit_comp.c +11 -2
@@ -120,6 +120,11 @@ static bool seen_reg(int reg, struct rv_return false; } +static void mark_fp (struct rv_jit_context *ctx) +{ +__set_bit (RV_CTX_F_SEEN_S5 , &ctx->flags); +} +static void mark_call (struct rv_jit_context *ctx) {__set_bit (RV_CTX_F_SEEN_CALL , &ctx->flags);
@@ -596,7 +601,8 @@ static void __build_epilogue(u8 reg, stremit (rv_addi (RV_REG_SP ,RV_REG_SP , stack_adjust), ctx);/* Set return value. */ -emit (rv_addi (RV_REG_A0 ,RV_REG_A5 ,0 ), ctx); +if (reg ==RV_REG_RA ) +emit (rv_addi (RV_REG_A0 ,RV_REG_A5 ,0 ), ctx);emit (rv_jalr (RV_REG_ZERO , reg,0 ), ctx); }
@@ -1426,6 +1432,10 @@ static void build_prologue(struct rv_jit {int stack_adjust =0 , store_offset, bpf_stack_adjust; + bpf_stack_adjust =round_up (ctx->prog->aux->stack_depth,16 ); +if (bpf_stack_adjust) +mark_fp (ctx); +if (seen_reg (RV_REG_RA , ctx)) stack_adjust +=8 ; stack_adjust +=8 ;/* RV_REG_FP */
@@ -1443,7 +1453,6 @@ static void build_prologue(struct rv_jit stack_adjust +=8 ; stack_adjust =round_up (stack_adjust,16 ); - bpf_stack_adjust =round_up (ctx->prog->aux->stack_depth,16 ); stack_adjust += bpf_stack_adjust; store_offset = stack_adjust -8 ;
Greg Kroah-Hartman
maintainerPATCH 145/309 selftests/bpf: Fix perf_buffer test on systems w/ offline CPUs
In reply to Greg Kroah-HartmanFrom: Andrii Nakryiko <[email protected]>
commit 91cbdf740a476cf2c744169bf407de2e3ac1f3cf upstream.
Fix up perf_buffer.c selftest to take into account offline/missing CPUs.
--- tools/testing/selftests/bpf/prog_tests/perf_buffer.c | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-)
tools/testing/selftests/bpf/prog_tests/perf_buffer.c +24 -5
@@ -4,6 +4,7 @@#include <sched.h> #include <sys/socket.h> #include <test_progs.h> +#include "libbpf_internal.h" static void on_sample (void *ctx,int cpu,void *data,__u32 size) {
@@ -19,7 +20,7 @@ static void on_sample(void *ctx, int cpuvoid test_perf_buffer (void ) { -int err, prog_fd, nr_cpus, i, duration =0 ; +int err, prog_fd, on_len, nr_on_cpus =0 , nr_cpus, i, duration =0 ;const char *prog_name ="kprobe/sys_nanosleep" ;const char *file ="./test_perf_buffer.o" ;struct perf_buffer_opts pb_opts = {};
@@ -29,15 +30,27 @@ void test_perf_buffer(void)struct bpf_object *obj;struct perf_buffer *pb;struct bpf_link *link; +bool *online; nr_cpus =libbpf_num_possible_cpus ();if (CHECK (nr_cpus <0 ,"nr_cpus" ,"err %d\n" , nr_cpus))return ; + err =parse_cpu_mask_file ("/sys/devices/system/cpu/online" , + &online, &on_len); +if (CHECK (err,"nr_on_cpus" ,"err %d\n" , err)) +return ; + +for (i =0 ; i < on_len; i++) +if (online[i]) + nr_on_cpus++; +/* load program */ err =bpf_prog_load (file,BPF_PROG_TYPE_KPROBE , &obj, &prog_fd); -if (CHECK (err,"obj_load" ,"err %d errno %d\n" , err, errno)) -return ; +if (CHECK (err,"obj_load" ,"err %d errno %d\n" , err, errno)) { + obj =NULL ; + goto out_close; + } prog =bpf_object__find_program_by_title (obj, prog_name);if (CHECK (!prog,"find_probe" ,"prog '%s' not found\n" , prog_name))
@@ -64,6 +77,11 @@ void test_perf_buffer(void)/* trigger kprobe on every CPU */ CPU_ZERO (&cpu_seen);for (i =0 ; i < nr_cpus; i++) { +if (i >= on_len || !online[i]) { +printf ("skipping offline CPU #%d\n" , i); +continue ; + } +CPU_ZERO (&cpu_set);CPU_SET (i, &cpu_set);
@@ -81,8 +99,8 @@ void test_perf_buffer(void)if (CHECK (err <0 ,"perf_buffer__poll" ,"err %d\n" , err)) goto out_free_pb; -if (CHECK (CPU_COUNT (&cpu_seen) != nr_cpus,"seen_cpu_cnt" , -"expect %d, seen %d\n" , nr_cpus,CPU_COUNT (&cpu_seen))) +if (CHECK (CPU_COUNT (&cpu_seen) != nr_on_cpus,"seen_cpu_cnt" , +"expect %d, seen %d\n" , nr_on_cpus,CPU_COUNT (&cpu_seen))) goto out_free_pb; out_free_pb:
@@ -91,4 +109,5 @@ out_detach:bpf_link__destroy (link); out_close:bpf_object__close (obj); +free (online); }
Greg Kroah-Hartman
maintainerPATCH 146/309 bpf, devmap: Pass lockdep expression to RCU lists
In reply to Greg Kroah-HartmanFrom: Amol Grover <[email protected]>
commit 485ec2ea9cf556e9c120e07961b7b459d776a115 upstream.
head is traversed using hlist_for_each_entry_rcu outside an RCU read-side critical section but under the protection of dtab->index_lock.
Hence, add corresponding lockdep expression to silence false-positive lockdep warnings, and harden RCU lists.
--- kernel/bpf/devmap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/bpf/devmap.c +2 -1
@@ -293,7 +293,8 @@ struct bpf_dtab_netdev *__dev_map_hash_lstruct hlist_head *head =dev_map_index_hash (dtab, key);struct bpf_dtab_netdev *dev; -hlist_for_each_entry_rcu (dev, head, index_hlist) +hlist_for_each_entry_rcu (dev, head, index_hlist, +lockdep_is_held (&dtab->index_lock))if (dev->idx == key)return dev;
Greg Kroah-Hartman
maintainerPATCH 147/309 libbpf: Fix realloc usage in bpf_core_find_cands
In reply to Greg Kroah-HartmanFrom: Andrii Nakryiko <[email protected]>
commit 35b9211c0a2427e8f39e534f442f43804fc8d5ca upstream.
Fix bug requesting invalid size of reallocated array when constructing CO-RE relocation candidate list. This can cause problems if there are many potential candidates and a very fine-grained memory allocator bucket sizes are used.
--- tools/lib/bpf/libbpf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
tools/lib/bpf/libbpf.c +3 -1
@@ -2541,7 +2541,9 @@ static struct ids_vec *bpf_core_find_canif (strncmp (local_name, targ_name, local_essent_len) ==0 ) {pr_debug ("[%d] %s: found candidate [%d] %s\n" , local_type_id, local_name, i, targ_name); - new_ids =realloc (cand_ids->data, cand_ids->len +1 ); + new_ids =reallocarray (cand_ids->data, + cand_ids->len +1 , +sizeof (*cand_ids->data));if (!new_ids) { err = -ENOMEM ; goto err_out;
Greg Kroah-Hartman
maintainerPATCH 148/309 tc-testing: fix eBPF tests failure on linux fresh clones
In reply to Greg Kroah-HartmanFrom: Davide Caratti <[email protected]>
commit 7145fcfffef1fad4266aaf5ca96727696916edb7 upstream.
when the following command is done on a fresh clone of the kernel tree,
[root@f31 tc-testing]# ./tdc.py -c bpf
test cases that need to build the eBPF sample program fail systematically, because 'buildebpfPlugin' is unable to install the kernel headers (i.e, the 'khdr' target fails). Pass the correct environment to 'make', in place of ENVIR, to allow running these tests.
--- tools/testing/selftests/tc-testing/plugin-lib/buildebpfPlugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/tc-testing/plugin-lib/buildebpfPlugin.py +1 -1
@@ -54,7 +54,7 @@ class SubPlugin(TdcPlugin): shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - env=ENVIR) + env=os.environ.copy()) (rawout, serr) = proc.communicate() if proc.returncode != 0 and len(serr) > 0:
Greg Kroah-Hartman
maintainerPATCH 149/309 samples/bpf: Dont try to remove users homedir on clean
In reply to Greg Kroah-HartmanFrom: Toke Høiland-Jørgensen <[email protected]>
commit b2e5e93ae8af6a34bca536cdc4b453ab1e707b8b upstream.
The 'clean' rule in the samples/bpf Makefile tries to remove backup files (ending in ~). However, if no such files exist, it will instead try to remove the user's home directory. While the attempt is mostly harmless, it does lead to a somewhat scary warning like this:
rm: cannot remove '~': Is a directory
Fix this by using find instead of shell expansion to locate any actual backup files that need to be removed.
--- samples/bpf/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
samples/bpf/Makefile +1 -1
@@ -236,7 +236,7 @@ all: clean: $(MAKE) -C ../../ M=$(CURDIR) clean - @rm -f *~ + @find $(CURDIR) -type f -name '*~' -delete $(LIBBPF): FORCE # Fix up variables inherited from Kbuild that tools/ build system won't like
Greg Kroah-Hartman
maintainerPATCH 150/309 samples/bpf: Xdp_redirect_cpu fix missing tracepoint attach
In reply to Greg Kroah-HartmanFrom: Jesper Dangaard Brouer <[email protected]>
commit f9e6bfdbaf0cf304d72c70a05d81acac01a04f48 upstream.
When sample xdp_redirect_cpu was converted to use libbpf, the tracepoints used by this sample were not getting attached automatically like with bpf_load.c. The BPF-maps was still getting loaded, thus nobody notice that the tracepoints were not updating these maps.
This fix doesn't use the new skeleton code, as this bug was introduced in v5.1 and stable might want to backport this. E.g. Red Hat QA uses this sample as part of their testing.
--- samples/bpf/xdp_redirect_cpu_user.c | 59 +++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-)
samples/bpf/xdp_redirect_cpu_user.c +55 -4
@@ -16,6 +16,10 @@ static const char *__doc__ =#include <getopt.h> #include <net/if.h> #include <time.h> +#include <linux/limits.h> + +#define __must_check +#include <linux/err.h> #include <arpa/inet.h> #include <linux/if_link.h>
@@ -46,6 +50,10 @@ static int cpus_count_map_fd;static int cpus_iterator_map_fd;static int exception_cnt_map_fd; +#define NUM_TP 5 +struct bpf_link *tp_links[NUM_TP ] = {0 }; +static int tp_cnt =0 ; +/* Exit return codes */ #define EXIT_OK 0#define EXIT_FAIL 1
@@ -88,6 +96,10 @@ static void int_exit(int sig)printf ("program on interface changed, not removing\n" ); } } +/* Detach tracepoints */ +while (tp_cnt) +bpf_link__destroy (tp_links[--tp_cnt]); +exit (EXIT_OK ); }
@@ -588,23 +600,61 @@ static void stats_poll(int interval, boofree_stats_record (prev); } +static struct bpf_link *attach_tp (struct bpf_object *obj, +const char *tp_category, +const char * tp_name) +{ +struct bpf_program *prog; +struct bpf_link *link; +char sec_name[PATH_MAX ]; +int len; + + len =snprintf (sec_name,PATH_MAX ,"tracepoint/%s/%s" , + tp_category, tp_name); +if (len <0 ) +exit (EXIT_FAIL ); + + prog =bpf_object__find_program_by_title (obj, sec_name); +if (!prog) { +fprintf (stderr,"ERR: finding progsec: %s\n" , sec_name); +exit (EXIT_FAIL_BPF ); + } + + link =bpf_program__attach_tracepoint (prog, tp_category, tp_name); +if (IS_ERR (link)) +exit (EXIT_FAIL_BPF ); + +return link; +} + +static void init_tracepoints (struct bpf_object *obj) { + tp_links[tp_cnt++] =attach_tp (obj,"xdp" ,"xdp_redirect_err" ); + tp_links[tp_cnt++] =attach_tp (obj,"xdp" ,"xdp_redirect_map_err" ); + tp_links[tp_cnt++] =attach_tp (obj,"xdp" ,"xdp_exception" ); + tp_links[tp_cnt++] =attach_tp (obj,"xdp" ,"xdp_cpumap_enqueue" ); + tp_links[tp_cnt++] =attach_tp (obj,"xdp" ,"xdp_cpumap_kthread" ); +} +static int init_map_fds (struct bpf_object *obj) { - cpu_map_fd =bpf_object__find_map_fd_by_name (obj,"cpu_map" ); - rx_cnt_map_fd =bpf_object__find_map_fd_by_name (obj,"rx_cnt" ); +/* Maps updated by tracepoints */ redirect_err_cnt_map_fd =bpf_object__find_map_fd_by_name (obj,"redirect_err_cnt" ); + exception_cnt_map_fd = +bpf_object__find_map_fd_by_name (obj,"exception_cnt" ); cpumap_enqueue_cnt_map_fd =bpf_object__find_map_fd_by_name (obj,"cpumap_enqueue_cnt" ); cpumap_kthread_cnt_map_fd =bpf_object__find_map_fd_by_name (obj,"cpumap_kthread_cnt" ); + +/* Maps used by XDP */ + rx_cnt_map_fd =bpf_object__find_map_fd_by_name (obj,"rx_cnt" ); + cpu_map_fd =bpf_object__find_map_fd_by_name (obj,"cpu_map" ); cpus_available_map_fd =bpf_object__find_map_fd_by_name (obj,"cpus_available" ); cpus_count_map_fd =bpf_object__find_map_fd_by_name (obj,"cpus_count" ); cpus_iterator_map_fd =bpf_object__find_map_fd_by_name (obj,"cpus_iterator" ); - exception_cnt_map_fd = -bpf_object__find_map_fd_by_name (obj,"exception_cnt" ); if (cpu_map_fd < 0 || rx_cnt_map_fd < 0 || redirect_err_cnt_map_fd < 0 || cpumap_enqueue_cnt_map_fd < 0 ||
@@ -662,6 +712,7 @@ int main(int argc, char **argv) strerror(errno));return EXIT_FAIL ; } +init_tracepoints (obj);if (init_map_fds (obj) <0 ) {fprintf (stderr,"bpf_object__find_map_fd_by_name failed\n" );return EXIT_FAIL ;
Greg Kroah-Hartman
maintainerPATCH 151/309 selftests/bpf: Fix test_attach_probe
In reply to Greg Kroah-HartmanFrom: Alexei Starovoitov <[email protected]>
commit 580205dd4fe800b1e95be8b6df9e2991f975a8ad upstream.
Fix two issues in test_attach_probe:
1. it was not able to parse /proc/self/maps beyond the first line, since %s means parse string until white space.
2. offset has to be accounted for otherwise uprobed address is incorrect.
--- tools/testing/selftests/bpf/prog_tests/attach_probe.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
tools/testing/selftests/bpf/prog_tests/attach_probe.c +4 -3
@@ -2,7 +2,7 @@#include <test_progs.h> ssize_t get_base_addr () { -size_t start; +size_t start, offset;char buf[256 ];FILE *f;
@@ -10,10 +10,11 @@ ssize_t get_base_addr() {if (!f)return -errno; -while (fscanf (f,"%zx-%*x %s %*s\n" , &start, buf) ==2 ) { +while (fscanf (f,"%zx-%*x %s %zx %*[^\n]\n" , + &start, buf, &offset) ==3 ) {if (strcmp (buf,"r-xp" ) ==0 ) {fclose (f); -return start; +return start - offset; } }
Greg Kroah-Hartman
maintainerPATCH 152/309 selftests/bpf: Skip perf hw events test if the setup disabled it
In reply to Greg Kroah-HartmanFrom: Hangbin Liu <[email protected]>
commit f1c3656c6d9c147d07d16614455aceb34932bdeb upstream.
The same with commit 4e59afbbed96 ("selftests/bpf: skip nmi test when perf hw events are disabled"), it would make more sense to skip the test_stacktrace_build_id_nmi test if the setup (e.g. virtual machines) has disabled hardware perf events.
--- tools/testing/selftests/bpf/prog_tests/stacktrace_build_id_nmi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
tools/testing/selftests/bpf/prog_tests/stacktrace_build_id_nmi.c +6 -2
@@ -49,8 +49,12 @@ retry: pmu_fd =syscall (__NR_perf_event_open, &attr,-1 /* pid */ ,0 /* cpu 0 */ ,-1 /* group id */ ,0 /* flags */ ); -if (CHECK (pmu_fd <0 ,"perf_event_open" , -"err %d errno %d. Does the test host support PERF_COUNT_HW_CPU_CYCLES?\n" , +if (pmu_fd <0 && errno ==ENOENT ) { +printf ("%s:SKIP:no PERF_COUNT_HW_CPU_CYCLES\n" , __func__); +test__skip (); + goto cleanup; + } +if (CHECK (pmu_fd <0 ,"perf_event_open" ,"err %d errno %d\n" , pmu_fd, errno)) goto close_prog;
Greg Kroah-Hartman
maintainerPATCH 153/309 selftests: bpf: Use a temporary file in test_sockmap
In reply to Greg Kroah-HartmanFrom: Lorenz Bauer <[email protected]>
commit c31dbb1e41d1857b403f9bf58c87f5898519a0bc upstream.
Use a proper temporary file for sendpage tests. This means that running the tests doesn't clutter the working directory, and allows running the test on read-only filesystems.
--- tools/testing/selftests/bpf/test_sockmap.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-)
tools/testing/selftests/bpf/test_sockmap.c +5 -10
@@ -331,7 +331,7 @@ static int msg_loop_sendpage(int fd, intFILE *file;int i, fp; - file =fopen (".sendpage_tst.tmp" ,"w+" ); + file =tmpfile ();if (!file) {perror ("create file for sendpage" );return 1 ;
@@ -340,13 +340,8 @@ static int msg_loop_sendpage(int fd, intfwrite (&k,sizeof (char ),1 , file);fflush (file);fseek (file,0 ,SEEK_SET ); -fclose (file); - fp =open (".sendpage_tst.tmp" ,O_RDONLY ); -if (fp <0 ) { -perror ("reopen file for sendpage" ); -return 1 ; - } + fp =fileno (file);clock_gettime (CLOCK_MONOTONIC , &s->start);for (i =0 ; i < cnt; i++) {
@@ -354,11 +349,11 @@ static int msg_loop_sendpage(int fd, intif (!drop && sent <0 ) {perror ("send loop error" ); -close (fp); +fclose (file);return sent; }else if (drop && sent >=0 ) {printf ("sendpage loop error expected: %i\n" , sent); -close (fp); +fclose (file);return -EIO ; }
@@ -366,7 +361,7 @@ static int msg_loop_sendpage(int fd, int s->bytes_sent += sent; }clock_gettime (CLOCK_MONOTONIC , &s->end); -close (fp); +fclose (file);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 154/309 selftests: bpf: Ignore FIN packets for reuseport tests
In reply to Greg Kroah-HartmanFrom: Lorenz Bauer <[email protected]>
commit 8bec4f665e0baecb5f1b683379fc10b3745eb612 upstream.
The reuseport tests currently suffer from a race condition: FIN packets count towards DROP_ERR_SKB_DATA, since they don't contain a valid struct cmd. Tests will spuriously fail depending on whether check_results is called before or after the FIN is processed.
Exit the BPF program early if FIN is set.
--- tools/testing/selftests/bpf/progs/test_select_reuseport_kern.c | 6 ++++++ 1 file changed, 6 insertions(+)
tools/testing/selftests/bpf/progs/test_select_reuseport_kern.c +6 -0
@@ -113,6 +113,12 @@ int _select_by_skb_data(struct sk_reusep data_check.skb_ports[0 ] = th->source; data_check.skb_ports[1 ] = th->dest; +if (th->fin) +/* The connection is being torn down at the end of a +* test. It can't contain a cmd, so return early. +*/ +return SK_PASS ; +if ((th->doff <<2 ) +sizeof (*cmd) > data_check.len)GOTO_DONE (DROP_ERR_SKB_DATA ); if (bpf_skb_load_bytes(reuse_md, th->doff << 2, &cmd_copy,
Greg Kroah-Hartman
maintainerPATCH 155/309 crypto: api - fix unexpectedly getting generic implementation
In reply to Greg Kroah-HartmanFrom: Herbert Xu <[email protected]>
commit 2bbb3375d967155bccc86a5887d4a6e29c56b683 upstream.
When CONFIG_CRYPTO_MANAGER_EXTRA_TESTS=y, the first lookup of an algorithm that needs to be instantiated using a template will always get the generic implementation, even when an accelerated one is available.
This happens because the extra self-tests for the accelerated implementation allocate the generic implementation for comparison purposes, and then crypto_alg_tested() for the generic implementation "fulfills" the original request (i.e. sets crypto_larval::adult).
This patch fixes this by only fulfilling the original request if we are currently the best outstanding larval as judged by the priority. If we're not the best then we will ask all waiters on that larval request to retry the lookup.
Note that this patch introduces a behaviour change when the module providing the new algorithm is unregistered during the process. Previously we would have failed with ENOENT, after the patch we will instead redo the lookup.
--- crypto/algapi.c | 24 +++++++++++++++++++++--- crypto/api.c | 4 +++- 2 files changed, 24 insertions(+), 4 deletions(-)
crypto/algapi.c +21 -3
@@ -257,6 +257,7 @@ void crypto_alg_tested(const char *name,struct crypto_alg *alg;struct crypto_alg *q;LIST_HEAD (list); +bool best;down_write (&crypto_alg_sem);list_for_each_entry (q, &crypto_alg_list, cra_list) {
@@ -280,6 +281,21 @@ found: alg->cra_flags |=CRYPTO_ALG_TESTED ; +/* Only satisfy larval waiters if we are the best. */ + best = true; +list_for_each_entry (q, &crypto_alg_list, cra_list) { +if (crypto_is_moribund (q) || !crypto_is_larval (q)) +continue ; + +if (strcmp (alg->cra_name, q->cra_name)) +continue ; + +if (q->cra_priority > alg->cra_priority) { + best = false; +break ; + } + } +list_for_each_entry (q, &crypto_alg_list, cra_list) {if (q == alg)continue ;
@@ -303,10 +319,12 @@ found:continue ;if ((q->cra_flags ^ alg->cra_flags) & larval->mask)continue ; -if (!crypto_mod_get (alg)) -continue ; - larval->adult = alg; +if (best &&crypto_mod_get (alg)) + larval->adult = alg; +else + larval->adult =ERR_PTR (-EAGAIN ); +continue ; }
crypto/api.c +3 -1
@@ -97,7 +97,7 @@ static void crypto_larval_destroy(structstruct crypto_larval *larval = (void *)alg;BUG_ON (!crypto_is_larval (alg)); -if (larval->adult) +if (!IS_ERR_OR_NULL (larval->adult))crypto_mod_put (larval->adult);kfree (larval); }
@@ -178,6 +178,8 @@ static struct crypto_alg *crypto_larval_ alg =ERR_PTR (-ETIMEDOUT ); else if (!alg) alg =ERR_PTR (-ENOENT ); + else if (IS_ERR(alg)) + ; else if (crypto_is_test_larval(larval) && !(alg->cra_flags & CRYPTO_ALG_TESTED)) alg =ERR_PTR (-EAGAIN );
Greg Kroah-Hartman
maintainerPATCH 156/309 crypto: hisilicon - Use the offset fields in sqe to avoid need to split scatterlists
In reply to Greg Kroah-HartmanFrom: Jonathan Cameron <[email protected]>
commit 484a897ffa3005f16cd9a31efd747bcf8155826f upstream.
We can configure sgl offset fields in ZIP sqe to let ZIP engine read/write sgl data with skipped data. Hence no need to splite the sgl.
--- drivers/crypto/hisilicon/Kconfig | 1 drivers/crypto/hisilicon/zip/zip.h | 4 + drivers/crypto/hisilicon/zip/zip_crypto.c | 92 +++++++----------------------- 3 files changed, 27 insertions(+), 70 deletions(-)
drivers/crypto/hisilicon/Kconfig +0 -1
@@ -35,6 +35,5 @@ config CRYPTO_DEV_HISI_ZIP depends on ARM64 && PCI && PCI_MSI select CRYPTO_DEV_HISI_QM select CRYPTO_HISI_SGL - select SG_SPLIT help Support for HiSilicon ZIP Driver
drivers/crypto/hisilicon/zip/zip.h +4 -0
@@ -12,6 +12,10 @@/* hisi_zip_sqe dw3 */ #define HZIP_BD_STATUS_M GENMASK(7, 0) +/* hisi_zip_sqe dw7 */ +#define HZIP_IN_SGE_DATA_OFFSET_M GENMASK(23, 0) +/* hisi_zip_sqe dw8 */ +#define HZIP_OUT_SGE_DATA_OFFSET_M GENMASK(23, 0)/* hisi_zip_sqe dw9 */ #define HZIP_REQ_TYPE_M GENMASK(7, 0)#define HZIP_ALG_TYPE_ZLIB 0x02
drivers/crypto/hisilicon/zip/zip_crypto.c +23 -69
178 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 157/309 crypto: ccp - set max RSA modulus size for v3 platform devices as well
In reply to Greg Kroah-HartmanFrom: Ard Biesheuvel <[email protected]>
commit 11548f5a5747813ff84bed6f2ea01100053b0d8d upstream.
AMD Seattle incorporates a non-PCI version of the v3 CCP crypto accelerator, and this version was left behind when the maximum RSA modulus size was parameterized in order to support v5 hardware which supports larger moduli than v3 hardware does. Due to this oversight, RSA acceleration no longer works at all on these systems.
Fix this by setting the .rsamax property to the appropriate value for v3 platform hardware.
--- drivers/crypto/ccp/ccp-dev-v3.c | 1 + 1 file changed, 1 insertion(+)
drivers/crypto/ccp/ccp-dev-v3.c +1 -0
@@ -586,6 +586,7 @@ const struct ccp_vdata ccpv3_platform = .setup = NULL, .perform = &ccp3_actions, .offset = 0, + .rsamax = CCP_RSA_MAX_WIDTH, };const struct ccp_vdata ccpv3 = {
Greg Kroah-Hartman
maintainerPATCH 158/309 crypto: arm64/ghash-neon - bump priority to 150
In reply to Greg Kroah-HartmanFrom: Ard Biesheuvel <[email protected]>
commit 5441c6507bc84166e9227e9370a56c57ba13794a upstream.
The SIMD based GHASH implementation for arm64 is typically much faster than the generic one, and doesn't use any lookup tables, so it is clearly preferred when available. So bump the priority to reflect that.
--- arch/arm64/crypto/ghash-ce-glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/crypto/ghash-ce-glue.c +1 -1
@@ -261,7 +261,7 @@ static int ghash_setkey(struct crypto_shstatic struct shash_alg ghash_alg[] = {{ .base.cra_name ="ghash" , .base.cra_driver_name ="ghash-neon" , - .base.cra_priority =100 , + .base.cra_priority =150 , .base.cra_blocksize =GHASH_BLOCK_SIZE , .base.cra_ctxsize =sizeof (struct ghash_key ), .base.cra_module =THIS_MODULE ,
Greg Kroah-Hartman
maintainerPATCH 159/309 crypto: pcrypt - Do not clear MAY_SLEEP flag in original request
In reply to Greg Kroah-HartmanFrom: Herbert Xu <[email protected]>
commit e8d998264bffade3cfe0536559f712ab9058d654 upstream.
We should not be modifying the original request's MAY_SLEEP flag upon completion. It makes no sense to do so anyway.
--- crypto/pcrypt.c | 1 - 1 file changed, 1 deletion(-)
crypto/pcrypt.c +0 -1
@@ -71,7 +71,6 @@ static void pcrypt_aead_done(struct crypstruct padata_priv *padata =pcrypt_request_padata (preq); padata->info = err; - req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP ;padata_do_serial (padata); }
Greg Kroah-Hartman
maintainerPATCH 160/309 crypto: atmel-aes - Fix counter overflow in CTR mode
In reply to Greg Kroah-HartmanFrom: Tudor Ambarus <[email protected]>
commit 781a08d9740afa73357f1a60d45d7c93d7cca2dd upstream.
32 bit counter is not supported by neither of our AES IPs, all implement a 16 bit block counter. Drop the 32 bit block counter logic.
--- drivers/crypto/atmel-aes.c | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-)
drivers/crypto/atmel-aes.c +12 -25
@@ -88,7 +88,6 @@struct atmel_aes_caps {bool has_dualbuff;bool has_cfb64; -bool has_ctr32;bool has_gcm;bool has_xts;bool has_authenc;
@@ -1013,8 +1012,9 @@ static int atmel_aes_ctr_transfer(structstruct atmel_aes_ctr_ctx *ctx =atmel_aes_ctr_ctx_cast (dd->ctx);struct ablkcipher_request *req =ablkcipher_request_cast (dd->areq);struct scatterlist *src, *dst; -u32 ctr, blocks;size_t datalen; +u32 ctr; +u16 blocks, start, end;bool use_dma, fragmented = false;/* Check for transfer completion. */
@@ -1026,27 +1026,17 @@ static int atmel_aes_ctr_transfer(struct datalen = req->nbytes - ctx->offset; blocks =DIV_ROUND_UP (datalen,AES_BLOCK_SIZE ); ctr =be32_to_cpu (ctx->iv[3 ]); -if (dd->caps.has_ctr32) { -/* Check 32bit counter overflow. */ -u32 start = ctr; -u32 end = start + blocks -1 ; - -if (end < start) { - ctr |=0xffffffff ; - datalen =AES_BLOCK_SIZE * -start; - fragmented = true; - } - }else { -/* Check 16bit counter overflow. */ -u16 start = ctr &0xffff ; -u16 end = start + (u16 )blocks -1 ; - -if (blocks >>16 || end < start) { - ctr |=0xffff ; - datalen =AES_BLOCK_SIZE * (0x10000 -start); - fragmented = true; - } + +/* Check 16bit counter overflow. */ + start = ctr &0xffff ; + end = start + blocks -1 ; + +if (blocks >>16 || end < start) { + ctr |=0xffff ; + datalen =AES_BLOCK_SIZE * (0x10000 - start); + fragmented = true; } + use_dma = (datalen >=ATMEL_AES_DMA_THRESHOLD );/* Jump to offset. */
@@ -2550,7 +2540,6 @@ static void atmel_aes_get_cap(struct atm { dd->caps.has_dualbuff =0 ; dd->caps.has_cfb64 =0 ; - dd->caps.has_ctr32 =0 ; dd->caps.has_gcm =0 ; dd->caps.has_xts =0 ; dd->caps.has_authenc =0 ;
@@ -2561,7 +2550,6 @@ static void atmel_aes_get_cap(struct atmcase 0x500 : dd->caps.has_dualbuff =1 ; dd->caps.has_cfb64 =1 ; - dd->caps.has_ctr32 =1 ; dd->caps.has_gcm =1 ; dd->caps.has_xts =1 ; dd->caps.has_authenc =1 ;
@@ -2570,7 +2558,6 @@ static void atmel_aes_get_cap(struct atmcase 0x200 : dd->caps.has_dualbuff =1 ; dd->caps.has_cfb64 =1 ; - dd->caps.has_ctr32 =1 ; dd->caps.has_gcm =1 ; dd->caps.max_burst_size =4 ;break ;
Greg Kroah-Hartman
maintainerPATCH 161/309 crypto: api - Fix race condition in crypto_spawn_alg
In reply to Greg Kroah-HartmanFrom: Herbert Xu <[email protected]>
commit 73669cc556462f4e50376538d77ee312142e8a8a upstream.
The function crypto_spawn_alg is racy because it drops the lock before shooting the dying algorithm. The algorithm could disappear altogether before we shoot it.
This patch fixes it by moving the shooting into the locked section.
--- crypto/algapi.c | 16 +++++----------- crypto/api.c | 3 +-- crypto/internal.h | 1 - 3 files changed, 6 insertions(+), 14 deletions(-)
crypto/algapi.c +5 -11
@@ -697,22 +697,16 @@ EXPORT_SYMBOL_GPL(crypto_drop_spawn);static struct crypto_alg *crypto_spawn_alg (struct crypto_spawn *spawn) {struct crypto_alg *alg; -struct crypto_alg *alg2;down_read (&crypto_alg_sem); alg = spawn->alg; - alg2 = alg; -if (alg2) - alg2 =crypto_mod_get (alg2); -up_read (&crypto_alg_sem); - -if (!alg2) { -if (alg) -crypto_shoot_alg (alg); -return ERR_PTR (-EAGAIN ); +if (alg && !crypto_mod_get (alg)) { + alg->cra_flags |=CRYPTO_ALG_DYING ; + alg =NULL ; } +up_read (&crypto_alg_sem); -return alg; +return alg ?:ERR_PTR (-EAGAIN ); } struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
crypto/api.c +1 -2
@@ -346,13 +346,12 @@ static unsigned int crypto_ctxsize(strucreturn len; } -void crypto_shoot_alg (struct crypto_alg *alg) +static void crypto_shoot_alg (struct crypto_alg *alg) {down_write (&crypto_alg_sem); alg->cra_flags |=CRYPTO_ALG_DYING ;up_write (&crypto_alg_sem); } -EXPORT_SYMBOL_GPL (crypto_shoot_alg);struct crypto_tfm *__crypto_alloc_tfm (struct crypto_alg *alg,u32 type,u32 mask)
crypto/internal.h +0 -1
@@ -68,7 +68,6 @@ void crypto_alg_tested(const char *name,void crypto_remove_spawns (struct crypto_alg *alg,struct list_head *list,struct crypto_alg *nalg);void crypto_remove_final (struct list_head *list); -void crypto_shoot_alg (struct crypto_alg *alg);struct crypto_tfm *__crypto_alloc_tfm (struct crypto_alg *alg,u32 type,u32 mask); void *crypto_create_tfm(struct crypto_alg *alg,
Greg Kroah-Hartman
maintainerPATCH 162/309 crypto: picoxcell - adjust the position of tasklet_init and fix missed tasklet_kill
In reply to Greg Kroah-HartmanFrom: Chuhong Yuan <[email protected]>
commit 7f8c36fe9be46862c4f3c5302f769378028a34fa upstream.
Since tasklet is needed to be initialized before registering IRQ handler, adjust the position of tasklet_init to fix the wrong order.
Besides, to fix the missed tasklet_kill, this patch adds a helper function and uses devm_add_action to kill the tasklet automatically.
--- drivers/crypto/picoxcell_crypto.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
drivers/crypto/picoxcell_crypto.c +13 -2
@@ -1613,6 +1613,11 @@ static const struct of_device_id spacc_oMODULE_DEVICE_TABLE (of, spacc_of_id_table);#endif /* CONFIG_OF */ +static void spacc_tasklet_kill (void *data) +{ +tasklet_kill (data); +} +static int spacc_probe (struct platform_device *pdev) {int i, err, ret;
@@ -1655,6 +1660,14 @@ static int spacc_probe(struct platform_dreturn -ENXIO ; } +tasklet_init (&engine->complete, spacc_spacc_complete, + (unsigned long )engine); + + ret =devm_add_action (&pdev->dev, spacc_tasklet_kill, + &engine->complete); +if (ret) +return ret; +if (devm_request_irq (&pdev->dev, irq->start, spacc_spacc_irq,0 , engine->name, engine)) {dev_err (engine->dev,"failed to request IRQ\n" );
@@ -1712,8 +1725,6 @@ static int spacc_probe(struct platform_dINIT_LIST_HEAD (&engine->completed);INIT_LIST_HEAD (&engine->in_progress); engine->in_flight =0 ; -tasklet_init (&engine->complete, spacc_spacc_complete, - (unsigned long )engine);platform_set_drvdata (pdev, engine);
Greg Kroah-Hartman
maintainerPATCH 163/309 powerpc/futex: Fix incorrect user access blocking
In reply to Greg Kroah-HartmanFrom: Michael Ellerman <[email protected]>
commit 9dc086f1e9ef39dd823bd27954b884b2062f9e70 upstream.
The early versions of our kernel user access prevention (KUAP) were written by Russell and Christophe, and didn't have separate read/write access.
At some point I picked up the series and added the read/write access, but I failed to update the usages in futex.h to correctly allow read and write.
However we didn't notice because of another bug which was causing the low-level code to always enable read and write. That bug was fixed recently in commit 1d8f739b07bd ("powerpc/kuap: Fix set direction in allow/prevent_user_access()").
futex_atomic_cmpxchg_inatomic() is passed the user address as %3 and does:
1: lwarx %1, 0, %3
cmpw 0, %1, %4
bne- 3f
2: stwcx. %5, 0, %3Which clearly loads and stores from/to %3. The logic in arch_futex_atomic_op_inuser() is similar, so fix both of them to use allow_read_write_user().
Without this fix, and with PPC_KUAP_DEBUG=y, we see eg:
Bug: Read fault blocked by AMR!
WARNING: CPU: 94 PID: 149215 at arch/powerpc/include/asm/book3s/64/kup-radix.h:126 __do_page_fault+0x600/0xf30
CPU: 94 PID: 149215 Comm: futex_requeue_p Tainted: G W 5.5.0-rc7-gcc9x-g4c25df5640ae #1
...
NIP [c000000000070680] __do_page_fault+0x600/0xf30
LR [c00000000007067c] __do_page_fault+0x5fc/0xf30
Call Trace:
[c00020138e5637e0] [c00000000007067c] __do_page_fault+0x5fc/0xf30 (unreliable)
[c00020138e5638c0] [c00000000000ada8] handle_page_fault+0x10/0x30
--- interrupt: 301 at cmpxchg_futex_value_locked+0x68/0xd0
LR = futex_lock_pi_atomic+0xe0/0x1f0
[c00020138e563bc0] [c000000000217b50] futex_lock_pi_atomic+0x80/0x1f0 (unreliable)
[c00020138e563c30] [c00000000021b668] futex_requeue+0x438/0xb60
[c00020138e563d60] [c00000000021c6cc] do_futex+0x1ec/0x2b0
[c00020138e563d90] [c00000000021c8b8] sys_futex+0x128/0x200
[c00020138e563e20] [c00000000000b7ac] system_call+0x5c/0x68--- arch/powerpc/include/asm/futex.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
arch/powerpc/include/asm/futex.h +6 -4
@@ -35,7 +35,7 @@ static inline int arch_futex_atomic_op_i {int oldval =0 , ret; -allow_write_to_user (uaddr,sizeof (*uaddr)); +allow_read_write_user (uaddr, uaddr,sizeof (*uaddr));pagefault_disable ();switch (op) {
@@ -62,7 +62,7 @@ static inline int arch_futex_atomic_op_i *oval = oldval; -prevent_write_to_user (uaddr,sizeof (*uaddr)); +prevent_read_write_user (uaddr, uaddr,sizeof (*uaddr));return ret; }
@@ -76,7 +76,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,if (!access_ok (uaddr,sizeof (u32)))return -EFAULT ; -allow_write_to_user (uaddr,sizeof (*uaddr)); +allow_read_write_user (uaddr, uaddr,sizeof (*uaddr)); + __asm__ __volatile__ ( PPC_ATOMIC_ENTRY_BARRIER "1: lwarx %1,0,%3 # futex_atomic_cmpxchg_inatomic\n\
@@ -97,7 +98,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, : "cc", "memory"); *uval = prev; -prevent_write_to_user (uaddr,sizeof (*uaddr)); +prevent_read_write_user (uaddr, uaddr,sizeof (*uaddr)); +return ret; }
Greg Kroah-Hartman
maintainerPATCH 164/309 scsi: qla2xxx: Fix unbound NVME response length
In reply to Greg Kroah-HartmanFrom: Arun Easi <[email protected]>
commit 00fe717ee1ea3c2979db4f94b1533c57aed8dea9 upstream.
On certain cases when response length is less than 32, NVME response data is supplied inline in IOCB. This is indicated by some combination of state flags. There was an instance when a high, and incorrect, response length was indicated causing driver to overrun buffers. Fix this by checking and limiting the response payload length.
--- drivers/scsi/qla2xxx/qla_dbg.c | 6 ------ drivers/scsi/qla2xxx/qla_dbg.h | 6 ++++++ drivers/scsi/qla2xxx/qla_isr.c | 12 ++++++++++++ 3 files changed, 18 insertions(+), 6 deletions(-)
drivers/scsi/qla2xxx/qla_dbg.c +0 -6
@@ -2519,12 +2519,6 @@ qla83xx_fw_dump_failed:/* Driver Debug Functions. */ /****************************************************************************/ -static inline int -ql_mask_match (uint level) -{ -return (level & ql2xextended_error_logging) == level; -} -/* * This function is for formatting and logging debug information. * It is to be used when vha is available. It formats the message
drivers/scsi/qla2xxx/qla_dbg.h +6 -0
@@ -374,3 +374,9 @@ extern int qla24xx_dump_ram(struct qla_hextern void qla24xx_pause_risc (struct device_reg_24xx __iomem *,struct qla_hw_data *);extern int qla24xx_soft_reset (struct qla_hw_data *); + +static inline int +ql_mask_match (uint level) +{ +return (level & ql2xextended_error_logging) == level; +}
drivers/scsi/qla2xxx/qla_isr.c +12 -0
@@ -1897,6 +1897,18 @@ static void qla24xx_nvme_iocb_entry(scsi inbuf = (uint32_t *)&sts->nvme_ersp_data; outbuf = (uint32_t *)fd->rspaddr; iocb->u.nvme.rsp_pyld_len =le16_to_cpu (sts->nvme_rsp_pyld_len); +if (unlikely (iocb->u.nvme.rsp_pyld_len > +sizeof (struct nvme_fc_ersp_iu ))) { +if (ql_mask_match (ql_dbg_io)) { +WARN_ONCE (1 ,"Unexpected response payload length %u.\n" , + iocb->u.nvme.rsp_pyld_len); +ql_log (ql_log_warn, fcport->vha,0x5100 , +"Unexpected response payload length %u.\n" , + iocb->u.nvme.rsp_pyld_len); + } + iocb->u.nvme.rsp_pyld_len = +sizeof (struct nvme_fc_ersp_iu ); + } iter = iocb->u.nvme.rsp_pyld_len >>2 ;for (; iter; iter--) *outbuf++ =swab32 (*inbuf++);
Greg Kroah-Hartman
maintainerPATCH 165/309 NFS: Fix memory leaks and corruption in readdir
In reply to Greg Kroah-HartmanFrom: Trond Myklebust <[email protected]>
commit 4b310319c6a8ce708f1033d57145e2aa027a883c upstream.
nfs_readdir_xdr_to_array() must not exit without having initialised the array, so that the page cache deletion routines can safely call nfs_readdir_clear_array().
Furthermore, we should ensure that if we exit nfs_readdir_filler() with an error, we free up any page contents to prevent a leak if we try to fill the page again.
--- fs/nfs/dir.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
fs/nfs/dir.c +15 -2
@@ -162,6 +162,17 @@ typedef struct {bool eof; } nfs_readdir_descriptor_t; +static +void nfs_readdir_init_array (struct page *page) +{ +struct nfs_cache_array *array; + + array =kmap_atomic (page); +memset (array,0 ,sizeof (struct nfs_cache_array )); + array->eof_index =-1 ; +kunmap_atomic (array); +} +/* * we are freeing strings created by nfs_add_to_readdir_array() */
@@ -174,6 +185,7 @@ void nfs_readdir_clear_array(struct page array =kmap_atomic (page);for (i =0 ; i < array->size; i++)kfree (array->array[i].string.name); + array->size =0 ;kunmap_atomic (array); }
@@ -610,6 +622,8 @@ int nfs_readdir_xdr_to_array(nfs_readdirint status = -ENOMEM ;unsigned int array_size =ARRAY_SIZE (pages); +nfs_readdir_init_array (page); + entry.prev_cookie =0 ; entry.cookie = desc->last_cookie; entry.eof =0 ;
@@ -626,8 +640,6 @@ int nfs_readdir_xdr_to_array(nfs_readdir } array =kmap (page); -memset (array,0 ,sizeof (struct nfs_cache_array )); - array->eof_index =-1 ; status =nfs_readdir_alloc_pages (pages, array_size);if (status <0 )
@@ -682,6 +694,7 @@ int nfs_readdir_filler(void *data, strucunlock_page (page);return 0 ; error: +nfs_readdir_clear_array (page);unlock_page (page);return ret; }
Greg Kroah-Hartman
maintainerPATCH 166/309 NFS: Directory page cache pages need to be locked when read
In reply to Greg Kroah-HartmanFrom: Trond Myklebust <[email protected]>
commit 114de38225d9b300f027e2aec9afbb6e0def154b upstream.
When a NFS directory page cache page is removed from the page cache, its contents are freed through a call to nfs_readdir_clear_array(). To prevent the removal of the page cache entry until after we've finished reading it, we must take the page lock.
--- fs/nfs/dir.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-)
fs/nfs/dir.c +19 -11
@@ -702,8 +702,6 @@ int nfs_readdir_filler(void *data, strucstatic void cache_page_release (nfs_readdir_descriptor_t *desc) { -if (!desc->page->mapping) -nfs_readdir_clear_array (desc->page);put_page (desc->page); desc->page =NULL ; }
@@ -717,19 +715,28 @@ struct page *get_cache_page(nfs_readdir_/* * Returns 0 if desc->dir_cookie was found on page desc->page_index +* and locks the page to prevent removal from the page cache. */ static -int find_cache_page (nfs_readdir_descriptor_t *desc) +int find_and_lock_cache_page (nfs_readdir_descriptor_t *desc) {int res; desc->page =get_cache_page (desc);if (IS_ERR (desc->page))return PTR_ERR (desc->page); - - res =nfs_readdir_search_array (desc); + res =lock_page_killable (desc->page);if (res !=0 ) -cache_page_release (desc); + goto error; + res = -EAGAIN ; +if (desc->page->mapping !=NULL ) { + res =nfs_readdir_search_array (desc); +if (res ==0 ) +return 0 ; + } +unlock_page (desc->page); +error: +cache_page_release (desc);return res; }
@@ -744,7 +751,7 @@ int readdir_search_pagecache(nfs_readdir desc->last_cookie =0 ; }do { - res =find_cache_page (desc); + res =find_and_lock_cache_page (desc); }while (res == -EAGAIN );return res; }
@@ -783,7 +790,6 @@ int nfs_do_filldir(nfs_readdir_descripto desc->eof = true;kunmap (desc->page); -cache_page_release (desc);dfprintk (DIRCACHE ,"NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n" , (unsigned long long )*desc->dir_cookie, res);return res;
@@ -829,13 +835,13 @@ int uncached_readdir(nfs_readdir_descrip status =nfs_do_filldir (desc); + out_release: +nfs_readdir_clear_array (desc->page); +cache_page_release (desc); out:dfprintk (DIRCACHE ,"NFS: %s: returns %d\n" , __func__, status);return status; - out_release: -cache_page_release (desc); - goto out; }/* The file offset position represents the dirent entry number. A
@@ -900,6 +906,8 @@ static int nfs_readdir(struct file *filebreak ; res =nfs_do_filldir (desc); +unlock_page (desc->page); +cache_page_release (desc);if (res <0 )break ; }while (!desc->eof);
Greg Kroah-Hartman
maintainerPATCH 167/309 nfsd: fix filecache lookup
In reply to Greg Kroah-HartmanFrom: Trond Myklebust <[email protected]>
commit 28c7d86bb6172ffbb1a1237c6388e77f9fe5f181 upstream.
If the lookup keeps finding a nfsd_file with an unhashed open file, then retry once only.
--- fs/nfsd/filecache.c | 6 ++++++ 1 file changed, 6 insertions(+)
fs/nfsd/filecache.c +6 -0
@@ -791,6 +791,7 @@ nfsd_file_acquire(struct svc_rqst *rqstpstruct nfsd_file *nf, *new;struct inode *inode;unsigned int hashval; +bool retry = true;/* FIXME: skip this if fh_dentry is already set? */ status = fh_verify(rqstp, fhp, S_IFREG,
@@ -826,6 +827,11 @@ wait_for_construction:/* Did construction of this file fail? */ if (!test_bit (NFSD_FILE_HASHED , &nf->nf_flags)) { +if (!retry) { + status = nfserr_jukebox; + goto out; + } + retry = false;nfsd_file_put_noref (nf); goto retry; }
Greg Kroah-Hartman
maintainerPATCH 168/309 jbd2_seq_info_next should increase position index
In reply to Greg Kroah-HartmanFrom: Vasily Averin <[email protected]>
commit 1a8e9cf40c9a6a2e40b1e924b13ed303aeea4418 upstream.
if seq_file .next fuction does not change position index, read after some lseek can generate unexpected output.
Script below generates endless output
$ q=;while read -r r;do echo "$((++q)) $r";done </proc/fs/jbd2/DEV/info
https://bugzilla.kernel.org/show_bug.cgi?id=206283
--- fs/jbd2/journal.c | 1 + 1 file changed, 1 insertion(+)
fs/jbd2/journal.c +1 -0
@@ -981,6 +981,7 @@ static void *jbd2_seq_info_start(structstatic void *jbd2_seq_info_next (struct seq_file *seq,void *v,loff_t *pos) { + (*pos)++;return NULL ; }
Greg Kroah-Hartman
maintainerPATCH 169/309 ext4: fix deadlock allocating crypto bounce page from mempool
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit 547c556f4db7c09447ecf5f833ab6aaae0c5ab58 upstream.
ext4_writepages() on an encrypted file has to encrypt the data, but it can't modify the pagecache pages in-place, so it encrypts the data into bounce pages and writes those instead. All bounce pages are allocated from a mempool using GFP_NOFS.
This is not correct use of a mempool, and it can deadlock. This is because GFP_NOFS includes __GFP_DIRECT_RECLAIM, which enables the "never fail" mode for mempool_alloc() where a failed allocation will fall back to waiting for one of the preallocated elements in the pool.
But since this mode is used for all a bio's pages and not just the first, it can deadlock waiting for pages already in the bio to be freed.
This deadlock can be reproduced by patching mempool_alloc() to pretend that pool->alloc() always fails (so that it always falls back to the preallocations), and then creating an encrypted file of size > 128 KiB.
Fix it by only using GFP_NOFS for the first page in the bio. For subsequent pages just use GFP_NOWAIT, and if any of those fail, just submit the bio and start a new one.
This will need to be fixed in f2fs too, but that's less straightforward.
--- fs/ext4/page-io.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-)
fs/ext4/page-io.c +14 -5
@@ -478,17 +478,26 @@ int ext4_bio_write_page(struct ext4_io_sgfp_t gfp_flags =GFP_NOFS ;unsigned int enc_bytes =round_up (len,i_blocksize (inode)); +/* +* Since bounce page allocation uses a mempool, we can only use +* a waiting mask (i.e. request guaranteed allocation) on the +* first page of the bio. Otherwise it can deadlock. +*/ +if (io->io_bio) + gfp_flags =GFP_NOWAIT | __GFP_NOWARN; retry_encrypt: bounce_page =fscrypt_encrypt_pagecache_blocks (page, enc_bytes,0 , gfp_flags);if (IS_ERR (bounce_page)) { ret =PTR_ERR (bounce_page); -if (ret == -ENOMEM && wbc->sync_mode ==WB_SYNC_ALL ) { -if (io->io_bio) { +if (ret == -ENOMEM && + (io->io_bio || wbc->sync_mode ==WB_SYNC_ALL )) { + gfp_flags =GFP_NOFS ; +if (io->io_bio)ext4_io_submit (io); -congestion_wait (BLK_RW_ASYNC ,HZ /50 ); - } - gfp_flags |= __GFP_NOFAIL; +else + gfp_flags |= __GFP_NOFAIL; +congestion_wait (BLK_RW_ASYNC ,HZ /50 ); goto retry_encrypt; } bounce_page =NULL ;
Greg Kroah-Hartman
maintainerPATCH 170/309 ext4: fix race conditions in ->d_compare() and ->d_hash()
In reply to Greg Kroah-HartmanFrom: Eric Biggers <[email protected]>
commit ec772f01307a2c06ebf6cdd221e6b518a71ddae7 upstream.
Since ->d_compare() and ->d_hash() can be called in RCU-walk mode, ->d_parent and ->d_inode can be concurrently modified, and in particular, ->d_inode may be changed to NULL. For ext4_d_hash() this resulted in a reproducible NULL dereference if a lookup is done in a directory being deleted, e.g. with:
int main()
{
if (fork()) {
for (;;) {
mkdir("subdir", 0700);
rmdir("subdir");
}
} else {
for (;;)
access("subdir/file", 0);
}
}... or by running the 't_encrypted_d_revalidate' program from xfstests. Both repros work in any directory on a filesystem with the encoding feature, even if the directory doesn't actually have the casefold flag.
I couldn't reproduce a crash in ext4_d_compare(), but it appears that a similar crash is possible there.
Fix these bugs by reading ->d_parent and ->d_inode using READ_ONCE() and falling back to the case sensitive behavior if the inode is NULL.
--- fs/ext4/dir.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
fs/ext4/dir.c +6 -3
@@ -673,9 +673,11 @@ static int ext4_d_compare(const struct d const char *str, const struct qstr *name) { struct qstr qstr = {.name = str, .len = len }; -struct inode *inode = dentry->d_parent->d_inode; +const struct dentry *parent =READ_ONCE (dentry->d_parent); +const struct inode *inode =READ_ONCE (parent->d_inode); -if (!IS_CASEFOLDED (inode) || !EXT4_SB (inode->i_sb)->s_encoding) { +if (!inode || !IS_CASEFOLDED (inode) || + !EXT4_SB (inode->i_sb)->s_encoding) {if (len != name->len)return -1 ;return memcmp (str, name->name, len);
@@ -688,10 +690,11 @@ static int ext4_d_hash(const struct dent {const struct ext4_sb_info *sbi =EXT4_SB (dentry->d_sb);const struct unicode_map *um = sbi->s_encoding; +const struct inode *inode =READ_ONCE (dentry->d_inode);unsigned char *norm;int len, ret =0 ; -if (!IS_CASEFOLDED (dentry->d_inode) || !um) +if (!inode || !IS_CASEFOLDED (inode) || !um)return 0 ; norm =kmalloc (PATH_MAX ,GFP_ATOMIC );
Greg Kroah-Hartman
maintainerPATCH 171/309 Btrfs: fix missing hole after hole punching and fsync when using NO_HOLES
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit 0e56315ca147b3e60c7bf240233a301d3c7fb508 upstream.
When using the NO_HOLES feature, if we punch a hole into a file and then fsync it, there are cases where a subsequent fsync will miss the fact that a hole was punched, resulting in the holes not existing after replaying the log tree.
Essentially these cases all imply that, tree-log.c:copy_items(), is not invoked for the leafs that delimit holes, because nothing changed those leafs in the current transaction. And it's precisely copy_items() where we currenly detect and log holes, which works as long as the holes are between file extent items in the input leaf or between the beginning of input leaf and the previous leaf or between the last item in the leaf and the next leaf.
First example where we miss a hole:
*) The extent items of the inode span multiple leafs;
*) The punched hole covers a range that affects only the extent items of
the first leaf;
*) The fsync operation is done in full mode (BTRFS_INODE_NEEDS_FULL_SYNC
is set in the inode's runtime flags).
That results in the hole not existing after replaying the log tree.
For example, if the fs/subvolume tree has the following layout for a particular inode:
Leaf N, generation 10:
[ ... INODE_ITEM INODE_REF EXTENT_ITEM (0 64K) EXTENT_ITEM (64K 128K) ]
Leaf N + 1, generation 10:
[ EXTENT_ITEM (128K 64K) ... ]
If at transaction 11 we punch a hole coverting the range [0, 128K[, we end up dropping the two extent items from leaf N, but we don't touch the other leaf, so we end up in the following state:
Leaf N, generation 11:
[ ... INODE_ITEM INODE_REF ]
Leaf N + 1, generation 10:
[ EXTENT_ITEM (128K 64K) ... ]
A full fsync after punching the hole will only process leaf N because it was modified in the current transaction, but not leaf N + 1, since it was not modified in the current transaction (generation 10 and not 11). As a result the fsync will not log any holes, because it didn't process any leaf with extent items.
Second example where we will miss a hole:
*) An inode as its items spanning 5 (or more) leafs;
*) A hole is punched and it covers only the extents items of the 3rd
leaf. This resulsts in deleting the entire leaf and not touching any of the other leafs.
So the only leaf that is modified in the current transaction, when punching the hole, is the first leaf, which contains the inode item. During the full fsync, the only leaf that is passed to copy_items() is that first leaf, and that's not enough for the hole detection code in copy_items() to determine there's a hole between the last file extent item in the 2nd leaf and the first file extent item in the 3rd leaf (which was the 4th leaf before punching the hole).
Fix this by scanning all leafs and punch holes as necessary when doing a full fsync (less common than a non-full fsync) when the NO_HOLES feature is enabled. The lack of explicit file extent items to mark holes makes it necessary to scan existing extents to determine if holes exist.
A test case for fstests follows soon.
--- fs/btrfs/tree-log.c | 388 +++++++++++++--------------------------------------- 1 file changed, 100 insertions(+), 288 deletions(-)
fs/btrfs/tree-log.c +100 -288
@@ -3953,7 +3953,7 @@ static int log_csums(struct btrfs_trans_ static noinline int copy_items(struct btrfs_trans_handle *trans,struct btrfs_inode *inode,struct btrfs_path *dst_path, -struct btrfs_path *src_path,u64 *last_extent, +struct btrfs_path *src_path,int start_slot,int nr,int inode_only,u64 logged_isize) {
@@ -3964,7 +3964,6 @@ static noinline int copy_items(struct btstruct btrfs_file_extent_item *extent;struct btrfs_inode_item *inode_item;struct extent_buffer *src = src_path->nodes[0 ]; -struct btrfs_key first_key, last_key, key;int ret;struct btrfs_key *ins_keys;u32 *ins_sizes;
@@ -3972,9 +3971,6 @@ static noinline int copy_items(struct btint i;struct list_head ordered_sums;int skip_csum = inode->flags &BTRFS_INODE_NODATASUM ; -bool has_extents = false; -bool need_find_last_extent = true; -bool done = false;INIT_LIST_HEAD (&ordered_sums);
@@ -3983,8 +3979,6 @@ static noinline int copy_items(struct btif (!ins_data)return -ENOMEM ; - first_key.objectid = (u64)-1 ; - ins_sizes = (u32 *)ins_data; ins_keys = (struct btrfs_key *)(ins_data + nr *sizeof (u32));
@@ -4005,9 +3999,6 @@ static noinline int copy_items(struct bt src_offset =btrfs_item_ptr_offset (src, start_slot + i); -if (i == nr -1 ) - last_key = ins_keys[i]; -if (ins_keys[i].type ==BTRFS_INODE_ITEM_KEY ) { inode_item = btrfs_item_ptr(dst_path->nodes[0], dst_path->slots[0],
@@ -4021,20 +4012,6 @@ static noinline int copy_items(struct bt src_offset, ins_sizes[i]); } -/* -* We set need_find_last_extent here in case we know we were -* processing other items and then walk into the first extent in -* the inode. If we don't hit an extent then nothing changes, -* we'll do the last search the next time around. -*/ -if (ins_keys[i].type ==BTRFS_EXTENT_DATA_KEY ) { - has_extents = true; -if (first_key.objectid == (u64)-1 ) - first_key = ins_keys[i]; - }else { - need_find_last_extent = false; - } -/* take a reference on file data extents so that truncates * or deletes of this inode don't have to relog the inode * again
@@ -4100,167 +4077,6 @@ static noinline int copy_items(struct btkfree (sums); } -if (!has_extents) -return ret; - -if (need_find_last_extent && *last_extent == first_key.offset) { -/* -* We don't have any leafs between our current one and the one -* we processed before that can have file extent items for our -* inode (and have a generation number smaller than our current -* transaction id). -*/ - need_find_last_extent = false; - } - -/* -* Because we use btrfs_search_forward we could skip leaves that were -* not modified and then assume *last_extent is valid when it really -* isn't. So back up to the previous leaf and read the end of the last -* extent before we go and fill in holes. -*/ -if (need_find_last_extent) { -u64 len; - - ret =btrfs_prev_leaf (inode->root, src_path); -if (ret <0 ) -return ret; -if (ret) - goto fill_holes; -if (src_path->slots[0 ]) - src_path->slots[0 ]--; - src = src_path->nodes[0 ]; -btrfs_item_key_to_cpu (src, &key, src_path->slots[0 ]); -if (key.objectid !=btrfs_ino (inode) || - key.type !=BTRFS_EXTENT_DATA_KEY ) - goto fill_holes; - extent =btrfs_item_ptr (src, src_path->slots[0 ], - struct btrfs_file_extent_item); -if (btrfs_file_extent_type (src, extent) == -BTRFS_FILE_EXTENT_INLINE ) { - len =btrfs_file_extent_ram_bytes (src, extent); - *last_extent =ALIGN (key.offset + len, - fs_info->sectorsize); - }else { - len =btrfs_file_extent_num_bytes (src, extent); - *last_extent = key.offset + len; - } - } -fill_holes: -/* So we did prev_leaf, now we need to move to the next leaf, but a few -* things could have happened -* -* 1) A merge could have happened, so we could currently be on a leaf -* that holds what we were copying in the first place. -* 2) A split could have happened, and now not all of the items we want -* are on the same leaf. -* -* So we need to adjust how we search for holes, we need to drop the -* path and re-search for the first extent key we found, and then walk -* forward until we hit the last one we copied. -*/ -if (need_find_last_extent) { -/* btrfs_prev_leaf could return 1 without releasing the path */ -btrfs_release_path (src_path); - ret =btrfs_search_slot (NULL , inode->root, &first_key, - src_path,0 ,0 ); -if (ret <0 ) -return ret; -ASSERT (ret ==0 ); - src = src_path->nodes[0 ]; - i = src_path->slots[0 ]; - }else { - i = start_slot; - } - -/* -* Ok so here we need to go through and fill in any holes we may have -* to make sure that holes are punched for those areas in case they had -* extents previously. -*/ -while (!done) { -u64 offset, len; -u64 extent_end; - -if (i >=btrfs_header_nritems (src_path->nodes[0 ])) { - ret =btrfs_next_leaf (inode->root, src_path); -if (ret <0 ) -return ret; -ASSERT (ret ==0 ); - src = src_path->nodes[0 ]; - i =0 ; - need_find_last_extent = true; - } - -btrfs_item_key_to_cpu (src, &key, i); -if (!btrfs_comp_cpu_keys (&key, &last_key)) - done = true; -if (key.objectid !=btrfs_ino (inode) || - key.type !=BTRFS_EXTENT_DATA_KEY ) { - i++; -continue ; - } - extent = btrfs_item_ptr(src, i, struct btrfs_file_extent_item); -if (btrfs_file_extent_type (src, extent) == -BTRFS_FILE_EXTENT_INLINE ) { - len =btrfs_file_extent_ram_bytes (src, extent); - extent_end =ALIGN (key.offset + len, - fs_info->sectorsize); - }else { - len =btrfs_file_extent_num_bytes (src, extent); - extent_end = key.offset + len; - } - i++; - -if (*last_extent == key.offset) { - *last_extent = extent_end; -continue ; - } - offset = *last_extent; - len = key.offset - *last_extent; - ret =btrfs_insert_file_extent (trans, log,btrfs_ino (inode), - offset,0 ,0 , len,0 , len,0 ,0 ,0 ); -if (ret) -break ; - *last_extent = extent_end; - } - -/* -* Check if there is a hole between the last extent found in our leaf -* and the first extent in the next leaf. If there is one, we need to -* log an explicit hole so that at replay time we can punch the hole. -*/ -if (ret ==0 && - key.objectid ==btrfs_ino (inode) && - key.type ==BTRFS_EXTENT_DATA_KEY && - i ==btrfs_header_nritems (src_path->nodes[0 ])) { - ret =btrfs_next_leaf (inode->root, src_path); - need_find_last_extent = true; -if (ret >0 ) { - ret =0 ; - }else if (ret ==0 ) { -btrfs_item_key_to_cpu (src_path->nodes[0 ], &key, - src_path->slots[0 ]); -if (key.objectid ==btrfs_ino (inode) && - key.type ==BTRFS_EXTENT_DATA_KEY && - *last_extent < key.offset) { -const u64 len = key.offset - *last_extent; - - ret =btrfs_insert_file_extent (trans, log, -btrfs_ino (inode), - *last_extent,0 , -0 , len,0 , len, -0 ,0 ,0 ); - *last_extent += len; - } - } - } -/* -* Need to let the callers know we dropped the path so they should -* re-search. -*/ -if (!ret && need_find_last_extent) - ret =1 ;return ret; }
@@ -4425,7 +4241,7 @@ static int btrfs_log_prealloc_extents(stconst u64 i_size =i_size_read (&inode->vfs_inode);const u64 ino =btrfs_ino (inode);struct btrfs_path *dst_path =NULL ; -u64 last_extent = (u64)-1 ; +bool dropped_extents = false;int ins_nr =0 ;int start_slot;int ret;
@@ -4447,8 +4263,7 @@ static int btrfs_log_prealloc_extents(stif (slot >=btrfs_header_nritems (leaf)) {if (ins_nr >0 ) { ret =copy_items (trans, inode, dst_path, path, - &last_extent, start_slot, - ins_nr,1 ,0 ); + start_slot, ins_nr,1 ,0 );if (ret <0 ) goto out; ins_nr =0 ;
@@ -4472,8 +4287,7 @@ static int btrfs_log_prealloc_extents(st path->slots[0 ]++;continue ; } -if (last_extent == (u64)-1 ) { - last_extent = key.offset; +if (!dropped_extents) {/* * Avoid logging extent items logged in past fsync calls * and leading to duplicate keys in the log tree.
@@ -4487,6 +4301,7 @@ static int btrfs_log_prealloc_extents(st }while (ret == -EAGAIN );if (ret) goto out; + dropped_extents = true; }if (ins_nr ==0 ) start_slot = slot;
@@ -4501,7 +4316,7 @@ static int btrfs_log_prealloc_extents(st } }if (ins_nr >0 ) { - ret =copy_items (trans, inode, dst_path, path, &last_extent, + ret =copy_items (trans, inode, dst_path, path, start_slot, ins_nr,1 ,0 );if (ret >0 ) ret =0 ;
@@ -4688,13 +4503,8 @@ static int btrfs_log_all_xattrs(struct bif (slot >= nritems) {if (ins_nr >0 ) { -u64 last_extent =0 ; - ret =copy_items (trans, inode, dst_path, path, - &last_extent, start_slot, - ins_nr,1 ,0 ); -/* can't be 1, extent items aren't processed */ -ASSERT (ret <=0 ); + start_slot, ins_nr,1 ,0 );if (ret <0 )return ret; ins_nr =0 ;
@@ -4718,13 +4528,8 @@ static int btrfs_log_all_xattrs(struct bcond_resched (); }if (ins_nr >0 ) { -u64 last_extent =0 ; - ret =copy_items (trans, inode, dst_path, path, - &last_extent, start_slot, - ins_nr,1 ,0 ); -/* can't be 1, extent items aren't processed */ -ASSERT (ret <=0 ); + start_slot, ins_nr,1 ,0 );if (ret <0 )return ret; }
@@ -4733,100 +4538,119 @@ static int btrfs_log_all_xattrs(struct b }/* -* If the no holes feature is enabled we need to make sure any hole between the -* last extent and the i_size of our inode is explicitly marked in the log. This -* is to make sure that doing something like: -* -* 1) create file with 128Kb of data -* 2) truncate file to 64Kb -* 3) truncate file to 256Kb -* 4) fsync file -* 5) <crash/power failure> -* 6) mount fs and trigger log replay -* -* Will give us a file with a size of 256Kb, the first 64Kb of data match what -* the file had in its first 64Kb of data at step 1 and the last 192Kb of the -* file correspond to a hole. The presence of explicit holes in a log tree is -* what guarantees that log replay will remove/adjust file extent items in the -* fs/subvol tree. -* -* Here we do not need to care about holes between extents, that is already done -* by copy_items(). We also only need to do this in the full sync path, where we -* lookup for extents from the fs/subvol tree only. In the fast path case, we -* lookup the list of modified extent maps and if any represents a hole, we -* insert a corresponding extent representing a hole in the log tree. +* When using the NO_HOLES feature if we punched a hole that causes the +* deletion of entire leafs or all the extent items of the first leaf (the one +* that contains the inode item and references) we may end up not processing +* any extents, because there are no leafs with a generation matching the +* current transaction that have extent items for our inode. So we need to find +* if any holes exist and then log them. We also need to log holes after any +* truncate operation that changes the inode's size. */ -static int btrfs_log_trailing_hole (struct btrfs_trans_handle *trans, -struct btrfs_root *root, -struct btrfs_inode *inode, -struct btrfs_path *path) +static int btrfs_log_holes (struct btrfs_trans_handle *trans, +struct btrfs_root *root, +struct btrfs_inode *inode, +struct btrfs_path *path) {struct btrfs_fs_info *fs_info = root->fs_info; -int ret;struct btrfs_key key; -u64 hole_start; -u64 hole_size; -struct extent_buffer *leaf; -struct btrfs_root *log = root->log_root;const u64 ino =btrfs_ino (inode);const u64 i_size =i_size_read (&inode->vfs_inode); +u64 prev_extent_end =0 ; +int ret; -if (!btrfs_fs_incompat (fs_info,NO_HOLES )) +if (!btrfs_fs_incompat (fs_info,NO_HOLES ) || i_size ==0 )return 0 ; key.objectid = ino; key.type =BTRFS_EXTENT_DATA_KEY ; - key.offset = (u64)-1 ; + key.offset =0 ; ret =btrfs_search_slot (NULL , root, &key, path,0 ,0 ); -ASSERT (ret !=0 );if (ret <0 )return ret; -ASSERT (path->slots[0 ] >0 ); - path->slots[0 ]--; - leaf = path->nodes[0 ]; -btrfs_item_key_to_cpu (leaf, &key, path->slots[0 ]); - -if (key.objectid != ino || key.type !=BTRFS_EXTENT_DATA_KEY ) { -/* inode does not have any extents */ - hole_start =0 ; - hole_size = i_size; - }else { +while (true) {struct btrfs_file_extent_item *extent; +struct extent_buffer *leaf = path->nodes[0 ];u64 len; -/* -* If there's an extent beyond i_size, an explicit hole was -* already inserted by copy_items(). -*/ -if (key.offset >= i_size) -return 0 ; +if (path->slots[0 ] >=btrfs_header_nritems (path->nodes[0 ])) { + ret =btrfs_next_leaf (root, path); +if (ret <0 ) +return ret; +if (ret >0 ) { + ret =0 ; +break ; + } + leaf = path->nodes[0 ]; + } + +btrfs_item_key_to_cpu (leaf, &key, path->slots[0 ]); +if (key.objectid != ino || key.type !=BTRFS_EXTENT_DATA_KEY ) +break ; + +/* We have a hole, log it. */ +if (prev_extent_end < key.offset) { +const u64 hole_len = key.offset - prev_extent_end; + +/* +* Release the path to avoid deadlocks with other code +* paths that search the root while holding locks on +* leafs from the log root. +*/ +btrfs_release_path (path); + ret =btrfs_insert_file_extent (trans, root->log_root, + ino, prev_extent_end,0 , +0 , hole_len,0 , hole_len, +0 ,0 ,0 ); +if (ret <0 ) +return ret; + +/* +* Search for the same key again in the root. Since it's +* an extent item and we are holding the inode lock, the +* key must still exist. If it doesn't just emit warning +* and return an error to fall back to a transaction +* commit. +*/ + ret =btrfs_search_slot (NULL , root, &key, path,0 ,0 ); +if (ret <0 ) +return ret; +if (WARN_ON (ret >0 )) +return -ENOENT ; + leaf = path->nodes[0 ]; + } extent =btrfs_item_ptr (leaf, path->slots[0 ], struct btrfs_file_extent_item); -if (btrfs_file_extent_type (leaf, extent) == -BTRFS_FILE_EXTENT_INLINE ) -return 0 ; +BTRFS_FILE_EXTENT_INLINE ) { + len =btrfs_file_extent_ram_bytes (leaf, extent); + prev_extent_end =ALIGN (key.offset + len, + fs_info->sectorsize); + }else { + len =btrfs_file_extent_num_bytes (leaf, extent); + prev_extent_end = key.offset + len; + } - len =btrfs_file_extent_num_bytes (leaf, extent); -/* Last extent goes beyond i_size, no need to log a hole. */ -if (key.offset + len > i_size) -return 0 ; - hole_start = key.offset + len; - hole_size = i_size - hole_start; + path->slots[0 ]++; +cond_resched (); } -btrfs_release_path (path); -/* Last extent ends at i_size. */ -if (hole_size ==0 ) -return 0 ; +if (prev_extent_end < i_size) { +u64 hole_len; - hole_size =ALIGN (hole_size, fs_info->sectorsize); - ret =btrfs_insert_file_extent (trans, log, ino, hole_start,0 ,0 , - hole_size,0 , hole_size,0 ,0 ,0 ); -return ret; +btrfs_release_path (path); + hole_len =ALIGN (i_size - prev_extent_end, fs_info->sectorsize); + ret =btrfs_insert_file_extent (trans, root->log_root, + ino, prev_extent_end,0 ,0 , + hole_len,0 , hole_len, +0 ,0 ,0 ); +if (ret <0 ) +return ret; + } + +return 0 ; }/*
@@ -5129,7 +4953,6 @@ static int btrfs_log_inode(struct btrfs_struct btrfs_key min_key;struct btrfs_key max_key;struct btrfs_root *log = root->log_root; -u64 last_extent =0 ;int err =0 ;int ret;int nritems;
@@ -5307,7 +5130,7 @@ again: ins_start_slot = path->slots[0 ]; } ret =copy_items (trans, inode, dst_path, path, - &last_extent, ins_start_slot, + ins_start_slot, ins_nr, inode_only, logged_isize);if (ret <0 ) {
@@ -5330,17 +5153,13 @@ again:if (ins_nr ==0 ) goto next_slot; ret =copy_items (trans, inode, dst_path, path, - &last_extent, ins_start_slot, + ins_start_slot, ins_nr, inode_only, logged_isize);if (ret <0 ) { err = ret; goto out_unlock; } ins_nr =0 ; -if (ret) { -btrfs_release_path (path); -continue ; - } goto next_slot; }
@@ -5353,18 +5172,13 @@ again: goto next_slot; } - ret =copy_items (trans, inode, dst_path, path, &last_extent, + ret =copy_items (trans, inode, dst_path, path, ins_start_slot, ins_nr, inode_only, logged_isize);if (ret <0 ) { err = ret; goto out_unlock; } -if (ret) { - ins_nr =0 ; -btrfs_release_path (path); -continue ; - } ins_nr =1 ; ins_start_slot = path->slots[0 ]; next_slot:
@@ -5378,13 +5192,12 @@ next_slot: }if (ins_nr) { ret =copy_items (trans, inode, dst_path, path, - &last_extent, ins_start_slot, + ins_start_slot, ins_nr, inode_only, logged_isize);if (ret <0 ) { err = ret; goto out_unlock; } - ret =0 ; ins_nr =0 ; }btrfs_release_path (path);
@@ -5399,14 +5212,13 @@ next_key: } }if (ins_nr) { - ret =copy_items (trans, inode, dst_path, path, &last_extent, + ret =copy_items (trans, inode, dst_path, path, ins_start_slot, ins_nr, inode_only, logged_isize);if (ret <0 ) { err = ret; goto out_unlock; } - ret =0 ; ins_nr =0 ; }
@@ -5419,7 +5231,7 @@ next_key:if (max_key.type >=BTRFS_EXTENT_DATA_KEY && !fast_search) {btrfs_release_path (path);btrfs_release_path (dst_path); - err =btrfs_log_trailing_hole (trans, root, inode, path); + err =btrfs_log_holes (trans, root, inode, path);if (err) goto out_unlock; }
Greg Kroah-Hartman
maintainerPATCH 172/309 Btrfs: make deduplication with range including the last block work
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit 831d2fa25ab8e27592b1b0268dae6f2dfaf7cc43 upstream.
Since btrfs was migrated to use the generic VFS helpers for clone and deduplication, it stopped allowing for the last block of a file to be deduplicated when the source file size is not sector size aligned (when eof is somewhere in the middle of the last block). There are two reasons for that:
1) The generic code always rounds down, to a multiple of the block size, the range's length for deduplications. This means we end up never deduplicating the last block when the eof is not block size aligned, even for the safe case where the destination range's end offset matches the destination file's size. That rounding down operation is done at generic_remap_check_len();
2) Because of that, the btrfs specific code does not expect anymore any non-aligned range length's for deduplication and therefore does not work if such nona-aligned length is given.
This patch addresses that second part, and it depends on a patch that fixes generic_remap_check_len(), in the VFS, which was submitted ealier and has the following subject:
"fs: allow deduplication of eof block into the end of the destination file"
These two patches address reports from users that started seeing lower deduplication rates due to the last block never being deduplicated when the file size is not aligned to the filesystem's block size.
--- fs/btrfs/ioctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/btrfs/ioctl.c +2 -1
@@ -3244,6 +3244,7 @@ static void btrfs_double_extent_lock(strstatic int btrfs_extent_same_range (struct inode *src,u64 loff,u64 len,struct inode *dst,u64 dst_loff) { +const u64 bs =BTRFS_I (src)->root->fs_info->sb->s_blocksize;int ret;/*
@@ -3251,7 +3252,7 @@ static int btrfs_extent_same_range(struc* source range to serialize with relocation. */ btrfs_double_extent_lock (src, loff, dst, dst_loff, len); - ret =btrfs_clone (src, dst, loff, len, len, dst_loff,1 ); + ret =btrfs_clone (src, dst, loff, len,ALIGN (len, bs), dst_loff,1 );btrfs_double_extent_unlock (src, loff, dst, dst_loff, len);return ret;
Greg Kroah-Hartman
maintainerPATCH 173/309 Btrfs: fix infinite loop during fsync after rename operations
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit b5e4ff9d465da1233a2d9a47ebce487c70d8f4ab upstream.
Recently fsstress (from fstests) sporadically started to trigger an infinite loop during fsync operations. This turned out to be because support for the rename exchange and whiteout operations was added to fsstress in fstests. These operations, unlike any others in fsstress, cause file names to be reused, whence triggering this issue. However it's not necessary to use rename exchange and rename whiteout operations trigger this issue, simple rename operations and file creations are enough to trigger the issue.
The issue boils down to when we are logging inodes that conflict (that had the name of any inode we need to log during the fsync operation), we keep logging them even if they were already logged before, and after that we check if there's any other inode that conflicts with them and then add it again to the list of inodes to log. Skipping already logged inodes fixes the issue.
Consider the following example:
$ mkfs.btrfs -f /dev/sdb $ mount /dev/sdb /mnt
$ mkdir /mnt/testdir # inode 257
$ touch /mnt/testdir/zz # inode 258 $ ln /mnt/testdir/zz /mnt/testdir/zz_link
$ touch /mnt/testdir/a # inode 259
$ sync
# The following 3 renames achieve the same result as a rename exchange
# operation (<rename_exchange> /mnt/testdir/zz_link to /mnt/testdir/a).
$ mv /mnt/testdir/a /mnt/testdir/a/tmp $ mv /mnt/testdir/zz_link /mnt/testdir/a $ mv /mnt/testdir/a/tmp /mnt/testdir/zz_link
# The following rename and file creation give the same result as a
# rename whiteout operation (<rename_whiteout> zz to a2).
$ mv /mnt/testdir/zz /mnt/testdir/a2 $ touch /mnt/testdir/zz # inode 260
$ xfs_io -c fsync /mnt/testdir/zz
--> results in the infinite loopThe following steps happen:
1) When logging inode 260, we find that its reference named "zz" was used by inode 258 in the previous transaction (through the commit root), so inode 258 is added to the list of conflicting indoes that need to be logged;
2) After logging inode 258, we find that its reference named "a" was used by inode 259 in the previous transaction, and therefore we add inode 259 to the list of conflicting inodes to be logged;
3) After logging inode 259, we find that its reference named "zz_link" was used by inode 258 in the previous transaction - we add inode 258 to the list of conflicting inodes to log, again - we had already logged it before at step 3. After logging it again, we find again that inode 259 conflicts with him, and we add again 259 to the list, etc - we end up repeating all the previous steps.
So fix this by skipping logging of conflicting inodes that were already logged.
--- fs/btrfs/tree-log.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
fs/btrfs/tree-log.c +44 -0
@@ -4855,6 +4855,50 @@ static int log_conflicting_inodes(structcontinue ; }/* +* If the inode was already logged skip it - otherwise we can +* hit an infinite loop. Example: +* +* From the commit root (previous transaction) we have the +* following inodes: +* +* inode 257 a directory +* inode 258 with references "zz" and "zz_link" on inode 257 +* inode 259 with reference "a" on inode 257 +* +* And in the current (uncommitted) transaction we have: +* +* inode 257 a directory, unchanged +* inode 258 with references "a" and "a2" on inode 257 +* inode 259 with reference "zz_link" on inode 257 +* inode 261 with reference "zz" on inode 257 +* +* When logging inode 261 the following infinite loop could +* happen if we don't skip already logged inodes: +* +* - we detect inode 258 as a conflicting inode, with inode 261 +* on reference "zz", and log it; +* +* - we detect inode 259 as a conflicting inode, with inode 258 +* on reference "a", and log it; +* +* - we detect inode 258 as a conflicting inode, with inode 259 +* on reference "zz_link", and log it - again! After this we +* repeat the above steps forever. +*/ +spin_lock (&BTRFS_I (inode)->lock); +/* +* Check the inode's logged_trans only instead of +* btrfs_inode_in_log(). This is because the last_log_commit of +* the inode is not updated when we only log that it exists and +* and it has the full sync bit set (see btrfs_log_inode()). +*/ +if (BTRFS_I (inode)->logged_trans == trans->transid) { +spin_unlock (&BTRFS_I (inode)->lock); +btrfs_add_delayed_iput (inode); +continue ; + } +spin_unlock (&BTRFS_I (inode)->lock); +/* * We are safe logging the other inode without acquiring its * lock as long as we log with the LOG_INODE_EXISTS mode. We * are safe against concurrent renames of the other inode as
Greg Kroah-Hartman
maintainerPATCH 174/309 btrfs: set trans->drity in btrfs_commit_transaction
In reply to Greg Kroah-HartmanFrom: Josef Bacik <[email protected]>
commit d62b23c94952e78211a383b7d90ef0afbd9a3717 upstream.
If we abort a transaction we have the following sequence
if (!trans->dirty && list_empty(&trans->new_bgs))
return;
WRITE_ONCE(trans->transaction->aborted, err);
The idea being if we didn't modify anything with our trans handle then we don't really need to abort the whole transaction, maybe the other trans handles are fine and we can carry on.
However in the case of create_snapshot we add a pending_snapshot object to our transaction and then commit the transaction. We don't actually modify anything. sync() behaves the same way, attach to an existing transaction and commit it. This means that if we have an IO error in the right places we could abort the committing transaction with our trans->dirty being not set and thus not set transaction->aborted.
This is a problem because in the create_snapshot() case we depend on pending->error being set to something, or btrfs_commit_transaction returning an error.
If we are not the trans handle that gets to commit the transaction, and we're waiting on the commit to happen we get our return value from cur_trans->aborted. If this was not set to anything because sync() hit an error in the transaction commit before it could modify anything then cur_trans->aborted would be 0. Thus we'd return 0 from btrfs_commit_transaction() in create_snapshot.
This is a problem because we then try to do things with pending_snapshot->snap, which will be NULL because we didn't create the snapshot, and then we'll get a NULL pointer dereference like the following
"BUG: kernel NULL pointer dereference, address: 00000000000001f0"
RIP: 0010:btrfs_orphan_cleanup+0x2d/0x330 Call Trace: ? btrfs_mksubvol.isra.31+0x3f2/0x510 btrfs_mksubvol.isra.31+0x4bc/0x510 ? __sb_start_write+0xfa/0x200 ? mnt_want_write_file+0x24/0x50 btrfs_ioctl_snap_create_transid+0x16c/0x1a0 btrfs_ioctl_snap_create_v2+0x11e/0x1a0 btrfs_ioctl+0x1534/0x2c10 ? free_debug_processing+0x262/0x2a3 do_vfs_ioctl+0xa6/0x6b0 ? do_sys_open+0x188/0x220 ? syscall_trace_enter+0x1f8/0x330 ksys_ioctl+0x60/0x90 __x64_sys_ioctl+0x16/0x20 do_syscall_64+0x4a/0x1b0
In order to fix this we need to make sure anybody who calls commit_transaction has trans->dirty set so that they properly set the trans->transaction->aborted value properly so any waiters know bad things happened.
This was found while I was running generic/475 with my modified fsstress, it reproduced within a few runs. I ran with this patch all night and didn't see the problem again.
--- fs/btrfs/transaction.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/btrfs/transaction.c +8 -0
@@ -1949,6 +1949,14 @@ int btrfs_commit_transaction(struct btrfstruct btrfs_transaction *prev_trans =NULL ;int ret; +/* +* Some places just start a transaction to commit it. We need to make +* sure that if this commit fails that the abort code actually marks the +* transaction as failed, so set trans->dirty to make the abort code do +* the right thing. +*/ + trans->dirty = true; +/* Stop the commit early if ->aborted is set */ if (unlikely (READ_ONCE (cur_trans->aborted))) { ret = cur_trans->aborted;
Greg Kroah-Hartman
maintainerPATCH 175/309 btrfs: drop log root for dropped roots
In reply to Greg Kroah-HartmanFrom: Josef Bacik <[email protected]>
commit 889bfa39086e86b52fcfaa04d72c95eaeb12f9a5 upstream.
If we fsync on a subvolume and create a log root for that volume, and then later delete that subvolume we'll never clean up its log root. Fix this by making switch_commit_roots free the log for any dropped roots we encounter. The extra churn is because we need a btrfs_trans_handle, not the btrfs_transaction.
--- fs/btrfs/transaction.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-)
fs/btrfs/transaction.c +12 -10
@@ -77,13 +77,14 @@ void btrfs_put_transaction(struct btrfs_ } } -static noinline void switch_commit_roots(struct btrfs_transaction *trans) +static noinline void switch_commit_roots(struct btrfs_trans_handle *trans) { +struct btrfs_transaction *cur_trans = trans->transaction;struct btrfs_fs_info *fs_info = trans->fs_info;struct btrfs_root *root, *tmp;down_write (&fs_info->commit_root_sem); -list_for_each_entry_safe (root, tmp, &trans->switch_commits, +list_for_each_entry_safe (root, tmp, &cur_trans->switch_commits, dirty_list) {list_del_init (&root->dirty_list);free_extent_buffer (root->commit_root);
@@ -95,16 +96,17 @@ static noinline void switch_commit_roots }/* We can free old roots now. */ -spin_lock (&trans->dropped_roots_lock); -while (!list_empty (&trans->dropped_roots)) { - root =list_first_entry (&trans->dropped_roots, +spin_lock (&cur_trans->dropped_roots_lock); +while (!list_empty (&cur_trans->dropped_roots)) { + root =list_first_entry (&cur_trans->dropped_roots, struct btrfs_root, root_list);list_del_init (&root->root_list); -spin_unlock (&trans->dropped_roots_lock); +spin_unlock (&cur_trans->dropped_roots_lock); +btrfs_free_log (trans, root);btrfs_drop_and_free_fs_root (fs_info, root); -spin_lock (&trans->dropped_roots_lock); +spin_lock (&cur_trans->dropped_roots_lock); } -spin_unlock (&trans->dropped_roots_lock); +spin_unlock (&cur_trans->dropped_roots_lock);up_write (&fs_info->commit_root_sem); }
@@ -1359,7 +1361,7 @@ static int qgroup_account_snapshot(struc ret =commit_cowonly_roots (trans);if (ret) goto out; -switch_commit_roots (trans->transaction); +switch_commit_roots (trans); ret =btrfs_write_and_wait_transaction (trans);if (ret) btrfs_handle_fs_error(fs_info, ret,
@@ -2245,7 +2247,7 @@ int btrfs_commit_transaction(struct btrflist_add_tail (&fs_info->chunk_root->dirty_list, &cur_trans->switch_commits); -switch_commit_roots (cur_trans); +switch_commit_roots (trans);ASSERT (list_empty (&cur_trans->dirty_bgs));ASSERT (list_empty (&cur_trans->io_bgs));
Greg Kroah-Hartman
maintainerPATCH 176/309 Btrfs: fix race between adding and putting tree mod seq elements and nodes
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit 7227ff4de55d931bbdc156c8ef0ce4f100c78a5b upstream.
There is a race between adding and removing elements to the tree mod log list and rbtree that can lead to use-after-free problems.
Consider the following example that explains how/why the problems happens:
1) Task A has mod log element with sequence number 200. It currently is the only element in the mod log list;
2) Task A calls btrfs_put_tree_mod_seq() because it no longer needs to access the tree mod log. When it enters the function, it initializes 'min_seq' to (u64)-1. Then it acquires the lock 'tree_mod_seq_lock' before checking if there are other elements in the mod seq list. Since the list it empty, 'min_seq' remains set to (u64)-1. Then it unlocks the lock 'tree_mod_seq_lock';
3) Before task A acquires the lock 'tree_mod_log_lock', task B adds itself to the mod seq list through btrfs_get_tree_mod_seq() and gets a sequence number of 201;
4) Some other task, name it task C, modifies a btree and because there elements in the mod seq list, it adds a tree mod elem to the tree mod log rbtree. That node added to the mod log rbtree is assigned a sequence number of 202;
5) Task B, which is doing fiemap and resolving indirect back references, calls btrfs get_old_root(), with 'time_seq' == 201, which in turn calls tree_mod_log_search() - the search returns the mod log node from the rbtree with sequence number 202, created by task C;
6) Task A now acquires the lock 'tree_mod_log_lock', starts iterating the mod log rbtree and finds the node with sequence number 202. Since 202 is less than the previously computed 'min_seq', (u64)-1, it removes the node and frees it;
7) Task B still has a pointer to the node with sequence number 202, and it dereferences the pointer itself and through the call to __tree_mod_log_rewind(), resulting in a use-after-free problem.
This issue can be triggered sporadically with the test case generic/561 from fstests, and it happens more frequently with a higher number of duperemove processes. When it happens to me, it either freezes the VM or it produces a trace like the following before crashing:
[ 1245.321140] general protection fault: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC PTI [ 1245.321200] CPU: 1 PID: 26997 Comm: pool Not tainted 5.5.0-rc6-btrfs-next-52 #1 [ 1245.321235] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-0-ga698c8995f-prebuilt.qemu.org 04/01/2014 [ 1245.321287] RIP: 0010:rb_next+0x16/0x50 [ 1245.321307] Code: .... [ 1245.321372] RSP: 0018:ffffa151c4d039b0 EFLAGS: 00010202 [ 1245.321388] RAX: 6b6b6b6b6b6b6b6b RBX: ffff8ae221363c80 RCX: 6b6b6b6b6b6b6b6b [ 1245.321409] RDX: 0000000000000001 RSI: 0000000000000000 RDI: ffff8ae221363c80 [ 1245.321439] RBP: ffff8ae20fcc4688 R08: 0000000000000002 R09: 0000000000000000 [ 1245.321475] R10: ffff8ae20b120910 R11: 00000000243f8bb1 R12: 0000000000000038 [ 1245.321506] R13: ffff8ae221363c80 R14: 000000000000075f R15: ffff8ae223f762b8 [ 1245.321539] FS: 00007fdee1ec7700(0000) GS:ffff8ae236c80000(0000) knlGS:0000000000000000 [ 1245.321591] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1245.321614] CR2: 00007fded4030c48 CR3: 000000021da16003 CR4: 00000000003606e0 [ 1245.321642] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 1245.321668] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 1245.321706] Call Trace: [ 1245.321798] __tree_mod_log_rewind+0xbf/0x280 [btrfs] [ 1245.321841] btrfs_search_old_slot+0x105/0xd00 [btrfs] [ 1245.321877] resolve_indirect_refs+0x1eb/0xc60 [btrfs] [ 1245.321912] find_parent_nodes+0x3dc/0x11b0 [btrfs] [ 1245.321947] btrfs_check_shared+0x115/0x1c0 [btrfs] [ 1245.321980] ? extent_fiemap+0x59d/0x6d0 [btrfs] [ 1245.322029] extent_fiemap+0x59d/0x6d0 [btrfs] [ 1245.322066] do_vfs_ioctl+0x45a/0x750 [ 1245.322081] ksys_ioctl+0x70/0x80 [ 1245.322092] ? trace_hardirqs_off_thunk+0x1a/0x1c [ 1245.322113] __x64_sys_ioctl+0x16/0x20 [ 1245.322126] do_syscall_64+0x5c/0x280 [ 1245.322139] entry_SYSCALL_64_after_hwframe+0x49/0xbe [ 1245.322155] RIP: 0033:0x7fdee3942dd7 [ 1245.322177] Code: .... [ 1245.322258] RSP: 002b:00007fdee1ec6c88 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 [ 1245.322294] RAX: ffffffffffffffda RBX: 00007fded40210d8 RCX: 00007fdee3942dd7 [ 1245.322314] RDX: 00007fded40210d8 RSI: 00000000c020660b RDI: 0000000000000004 [ 1245.322337] RBP: 0000562aa89e7510 R08: 0000000000000000 R09: 00007fdee1ec6d44 [ 1245.322369] R10: 0000000000000073 R11: 0000000000000246 R12: 00007fdee1ec6d48 [ 1245.322390] R13: 00007fdee1ec6d40 R14: 00007fded40210d0 R15: 00007fdee1ec6d50 [ 1245.322423] Modules linked in: .... [ 1245.323443] ---[ end trace 01de1e9ec5dff3cd ]---
Fix this by ensuring that btrfs_put_tree_mod_seq() computes the minimum sequence number and iterates the rbtree while holding the lock 'tree_mod_log_lock' in write mode. Also get rid of the 'tree_mod_seq_lock' lock, since it is now redundant.
--- fs/btrfs/ctree.c | 8 ++------ fs/btrfs/ctree.h | 6 ++---- fs/btrfs/delayed-ref.c | 8 ++++---- fs/btrfs/disk-io.c | 1 - fs/btrfs/tests/btrfs-tests.c | 1 - 5 files changed, 8 insertions(+), 16 deletions(-)
fs/btrfs/ctree.c +2 -6
@@ -330,12 +330,10 @@ u64 btrfs_get_tree_mod_seq(struct btrfs_ struct seq_list *elem) {write_lock (&fs_info->tree_mod_log_lock); -spin_lock (&fs_info->tree_mod_seq_lock);if (!elem->seq) { elem->seq =btrfs_inc_tree_mod_seq (fs_info);list_add_tail (&elem->list, &fs_info->tree_mod_seq_list); } -spin_unlock (&fs_info->tree_mod_seq_lock);write_unlock (&fs_info->tree_mod_log_lock);return elem->seq;
@@ -355,7 +353,7 @@ void btrfs_put_tree_mod_seq(struct btrfsif (!seq_putting)return ; -spin_lock (&fs_info->tree_mod_seq_lock); +write_lock (&fs_info->tree_mod_log_lock);list_del (&elem->list); elem->seq =0 ;
@@ -366,19 +364,17 @@ void btrfs_put_tree_mod_seq(struct btrfs* blocker with lower sequence number exists, we * cannot remove anything from the log */ -spin_unlock (&fs_info->tree_mod_seq_lock); +write_unlock (&fs_info->tree_mod_log_lock);return ; } min_seq = cur_elem->seq; } } -spin_unlock (&fs_info->tree_mod_seq_lock);/* * anything that's lower than the lowest existing (read: blocked) * sequence number can be removed from the tree. */ -write_lock (&fs_info->tree_mod_log_lock); tm_root = &fs_info->tree_mod_log;for (node =rb_first (tm_root); node; node = next) { next =rb_next (node);
fs/btrfs/ctree.h +2 -4
@@ -671,14 +671,12 @@ struct btrfs_fs_info {atomic_t nr_delayed_iputs;wait_queue_head_t delayed_iputs_wait; -/* this protects tree_mod_seq_list */ -spinlock_t tree_mod_seq_lock;atomic64_t tree_mod_seq; -struct list_head tree_mod_seq_list; -/* this protects tree_mod_log */ +/* this protects tree_mod_log and tree_mod_seq_list */ rwlock_t tree_mod_log_lock;struct rb_root tree_mod_log; +struct list_head tree_mod_seq_list;atomic_t async_delalloc_pages;
fs/btrfs/delayed-ref.c +4 -4
@@ -492,7 +492,7 @@ void btrfs_merge_delayed_refs(struct btrif (head->is_data)return ; -spin_lock (&fs_info->tree_mod_seq_lock); +read_lock (&fs_info->tree_mod_log_lock);if (!list_empty (&fs_info->tree_mod_seq_list)) {struct seq_list *elem;
@@ -500,7 +500,7 @@ void btrfs_merge_delayed_refs(struct btr struct seq_list, list); seq = elem->seq; } -spin_unlock (&fs_info->tree_mod_seq_lock); +read_unlock (&fs_info->tree_mod_log_lock); again: for (node = rb_first_cached(&head->ref_tree); node;
@@ -518,7 +518,7 @@ int btrfs_check_delayed_seq(struct btrfsstruct seq_list *elem;int ret =0 ; -spin_lock (&fs_info->tree_mod_seq_lock); +read_lock (&fs_info->tree_mod_log_lock);if (!list_empty (&fs_info->tree_mod_seq_list)) { elem =list_first_entry (&fs_info->tree_mod_seq_list, struct seq_list, list);
@@ -531,7 +531,7 @@ int btrfs_check_delayed_seq(struct btrfs } } -spin_unlock (&fs_info->tree_mod_seq_lock); +read_unlock (&fs_info->tree_mod_log_lock);return ret; }
fs/btrfs/disk-io.c +0 -1
@@ -2652,7 +2652,6 @@ int open_ctree(struct super_block *sb,spin_lock_init (&fs_info->fs_roots_radix_lock);spin_lock_init (&fs_info->delayed_iput_lock);spin_lock_init (&fs_info->defrag_inodes_lock); -spin_lock_init (&fs_info->tree_mod_seq_lock);spin_lock_init (&fs_info->super_lock);spin_lock_init (&fs_info->buffer_lock);spin_lock_init (&fs_info->unused_bgs_lock);
fs/btrfs/tests/btrfs-tests.c +0 -1
@@ -121,7 +121,6 @@ struct btrfs_fs_info *btrfs_alloc_dummy_spin_lock_init (&fs_info->qgroup_lock);spin_lock_init (&fs_info->super_lock);spin_lock_init (&fs_info->fs_roots_radix_lock); -spin_lock_init (&fs_info->tree_mod_seq_lock);mutex_init (&fs_info->qgroup_ioctl_lock);mutex_init (&fs_info->qgroup_rescan_lock);rwlock_init (&fs_info->tree_mod_log_lock);
Greg Kroah-Hartman
maintainerPATCH 177/309 btrfs: flush write bio if we loop in extent_write_cache_pages
In reply to Greg Kroah-HartmanFrom: Josef Bacik <[email protected]>
commit 42ffb0bf584ae5b6b38f72259af1e0ee417ac77f upstream.
There exists a deadlock with range_cyclic that has existed forever. If we loop around with a bio already built we could deadlock with a writer who has the page locked that we're attempting to write but is waiting on a page in our bio to be written out. The task traces are as follows
PID: 1329874 TASK: ffff889ebcdf3800 CPU: 33 COMMAND: "kworker/u113:5"
#0 [ffffc900297bb658] __schedule at ffffffff81a4c33f
#1 [ffffc900297bb6e0] schedule at ffffffff81a4c6e3
#2 [ffffc900297bb6f8] io_schedule at ffffffff81a4ca42
#3 [ffffc900297bb708] __lock_page at ffffffff811f145b
#4 [ffffc900297bb798] __process_pages_contig at ffffffff814bc502 #5 [ffffc900297bb8c8] lock_delalloc_pages at ffffffff814bc684 #6 [ffffc900297bb900] find_lock_delalloc_range at ffffffff814be9ff #7 [ffffc900297bb9a0] writepage_delalloc at ffffffff814bebd0 #8 [ffffc900297bba18] __extent_writepage at ffffffff814bfbf2 #9 [ffffc900297bba98] extent_write_cache_pages at ffffffff814bffbd
PID: 2167901 TASK: ffff889dc6a59c00 CPU: 14 COMMAND:
"aio-dio-invalid"
#0 [ffffc9003b50bb18] __schedule at ffffffff81a4c33f #1 [ffffc9003b50bba0] schedule at ffffffff81a4c6e3 #2 [ffffc9003b50bbb8] io_schedule at ffffffff81a4ca42 #3 [ffffc9003b50bbc8] wait_on_page_bit at ffffffff811f24d6 #4 [ffffc9003b50bc60] prepare_pages at ffffffff814b05a7 #5 [ffffc9003b50bcd8] btrfs_buffered_write at ffffffff814b1359 #6 [ffffc9003b50bdb0] btrfs_file_write_iter at ffffffff814b5933 #7 [ffffc9003b50be38] new_sync_write at ffffffff8128f6a8 #8 [ffffc9003b50bec8] vfs_write at ffffffff81292b9d #9 [ffffc9003b50bf00] ksys_pwrite64 at ffffffff81293032
I used drgn to find the respective pages we were stuck on
page_entry.page 0xffffea00fbfc7500 index 8148 bit 15 pid 2167901 page_entry.page 0xffffea00f9bb7400 index 7680 bit 0 pid 1329874
As you can see the kworker is waiting for bit 0 (PG_locked) on index 7680, and aio-dio-invalid is waiting for bit 15 (PG_writeback) on index 8148. aio-dio-invalid has 7680, and the kworker epd looks like the following
crash> struct extent_page_data ffffc900297bbbb0
struct extent_page_data {
bio = 0xffff889f747ed830,
tree = 0xffff889eed6ba448,
extent_locked = 0,
sync_io = 0
}Probably worth mentioning as well that it waits for writeback of the page to complete while holding a lock on it (at prepare_pages()).
Using drgn I walked the bio pages looking for page 0xffffea00fbfc7500 which is the one we're waiting for writeback on
bio = Object(prog, 'struct bio', address=0xffff889f747ed830) for i in range(0, bio.bi_vcnt.value_()):
bv = bio.bi_io_vec[i]
if bv.bv_page.value_() == 0xffffea00fbfc7500:
print("FOUND IT")which validated what I suspected.
The fix for this is simple, flush the epd before we loop back around to the beginning of the file during writeout.
--- fs/btrfs/extent_io.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
fs/btrfs/extent_io.c +10 -1
@@ -4185,7 +4185,16 @@ retry:*/ scanned =1 ; index =0 ; - goto retry; + +/* +* If we're looping we could run into a page that is locked by a +* writer and that writer could be waiting on writeback for a +* page in our current bio, and thus deadlock, so flush the +* write bio here. +*/ + ret =flush_write_bio (epd); +if (!ret) + goto retry; }if (wbc->range_cyclic || (wbc->nr_to_write >0 && range_whole))
Greg Kroah-Hartman
maintainerPATCH 178/309 btrfs: Correctly handle empty trees in find_first_clear_extent_bit
In reply to Greg Kroah-HartmanFrom: Nikolay Borisov <[email protected]>
commit 5750c37523a2c8cbb450b9ef31e21c2ba876b05e upstream.
Raviu reported that running his regular fs_trim segfaulted with the following backtrace:
[ 237.525947] assertion failed: prev, in ../fs/btrfs/extent_io.c:1595 [ 237.525984] ------------[ cut here ]------------ [ 237.525985] kernel BUG at ../fs/btrfs/ctree.h:3117! [ 237.525992] invalid opcode: 0000 [#1] SMP PTI [ 237.525998] CPU: 4 PID: 4423 Comm: fstrim Tainted: G U OE 5.4.14-8-vanilla #1 [ 237.526001] Hardware name: ASUSTeK COMPUTER INC. [ 237.526044] RIP: 0010:assfail.constprop.58+0x18/0x1a [btrfs] [ 237.526079] Call Trace: [ 237.526120] find_first_clear_extent_bit+0x13d/0x150 [btrfs] [ 237.526148] btrfs_trim_fs+0x211/0x3f0 [btrfs] [ 237.526184] btrfs_ioctl_fitrim+0x103/0x170 [btrfs] [ 237.526219] btrfs_ioctl+0x129a/0x2ed0 [btrfs] [ 237.526227] ? filemap_map_pages+0x190/0x3d0 [ 237.526232] ? do_filp_open+0xaf/0x110 [ 237.526238] ? _copy_to_user+0x22/0x30 [ 237.526242] ? cp_new_stat+0x150/0x180 [ 237.526247] ? do_vfs_ioctl+0xa4/0x640 [ 237.526278] ? btrfs_ioctl_get_supported_features+0x30/0x30 [btrfs] [ 237.526283] do_vfs_ioctl+0xa4/0x640 [ 237.526288] ? __do_sys_newfstat+0x3c/0x60 [ 237.526292] ksys_ioctl+0x70/0x80 [ 237.526297] __x64_sys_ioctl+0x16/0x20 [ 237.526303] do_syscall_64+0x5a/0x1c0 [ 237.526310] entry_SYSCALL_64_after_hwframe+0x49/0xbe
That was due to btrfs_fs_device::aloc_tree being empty. Initially I thought this wasn't possible and as a percaution have put the assert in find_first_clear_extent_bit. Turns out this is indeed possible and could happen when a file system with SINGLE data/metadata profile has a 2nd device added. Until balance is run or a new chunk is allocated on this device it will be completely empty.
In this case find_first_clear_extent_bit should return the full range [0, -1ULL] and let the caller handle this i.e for trim the end will be capped at the size of actual device.
--- fs/btrfs/extent_io.c | 32 ++++++++++++++++++-------------- fs/btrfs/tests/extent-io-tests.c | 9 +++++++++ 2 files changed, 27 insertions(+), 14 deletions(-)
fs/btrfs/extent_io.c +18 -14
@@ -1583,21 +1583,25 @@ void find_first_clear_extent_bit(struct/* Find first extent with bits cleared */ while (1 ) { node =__etree_search (tree, start, &next, &prev,NULL ,NULL ); -if (!node) { +if (!node && !next && !prev) { +/* +* Tree is completely empty, send full range and let +* caller deal with it +*/ + *start_ret =0 ; + *end_ret =-1 ; + goto out; + }else if (!node && !next) { +/* +* We are past the last allocated chunk, set start at +* the end of the last extent. +*/ + state = rb_entry(prev, struct extent_state, rb_node); + *start_ret = state->end +1 ; + *end_ret =-1 ; + goto out; + }else if (!node) { node = next; -if (!node) { -/* -* We are past the last allocated chunk, -* set start at the end of the last extent. The -* device alloc tree should never be empty so -* prev is always set. -*/ -ASSERT (prev); - state = rb_entry(prev, struct extent_state, rb_node); - *start_ret = state->end +1 ; - *end_ret =-1 ; - goto out; - } }/* * At this point 'node' either contains 'start' or start is
fs/btrfs/tests/extent-io-tests.c +9 -0
@@ -441,8 +441,17 @@ static int test_find_first_clear_extent_int ret = -EINVAL ;test_msg ("running find_first_clear_extent_bit test" ); +extent_io_tree_init (NULL , &tree,IO_TREE_SELFTEST ,NULL ); +/* Test correct handling of empty tree */ +find_first_clear_extent_bit (&tree,0 , &start, &end,CHUNK_TRIMMED ); +if (start !=0 || end !=-1 ) { +test_err ( +"error getting a range from completely empty tree: start %llu end %llu" , + start, end); + goto out; + }/* * Set 1M-4M alloc/discard and 32M-64M thus leaving a hole between * 4M-32M
Greg Kroah-Hartman
maintainerPATCH 179/309 ARM: tegra: Enable PLLP bypass during Tegra124 LP1
In reply to Greg Kroah-HartmanFrom: Stephen Warren <[email protected]>
commit 1a3388d506bf5b45bb283e6a4c4706cfb4897333 upstream.
For a little over a year, U-Boot has configured the flow controller to perform automatic RAM re-repair on off->on power transitions of the CPU rail[1]. This is mandatory for correct operation of Tegra124. However, RAM re-repair relies on certain clocks, which the kernel must enable and leave running. PLLP is one of those clocks. This clock is shut down during LP1 in order to save power. Enable bypass (which I believe routes osc_div_clk, essentially the crystal clock, to the PLL output) so that this clock signal toggles even though the PLL is not active. This is required so that LP1 power mode (system suspend) operates correctly.
The bypass configuration must then be undone when resuming from LP1, so that all peripheral clocks run at the expected rate. Without this, many peripherals won't work correctly; for example, the UART baud rate would be incorrect.
NVIDIA's downstream kernel code only does this if not compiled for Tegra30, so the added code is made conditional upon the chip ID. NVIDIA's downstream code makes this change conditional upon the active CPU cluster. The upstream kernel currently doesn't support cluster switching, so this patch doesn't test the active CPU cluster ID.
[1] 3cc7942a4ae5 ARM: tegra: implement RAM repair
--- arch/arm/mach-tegra/sleep-tegra30.S | 11 +++++++++++ 1 file changed, 11 insertions(+)
arch/arm/mach-tegra/sleep-tegra30.S +11 -0
@@ -370,6 +370,14 @@ _pll_m_c_x_done: pll_locked r1, r0, CLK_RESET_PLLC_BASE pll_locked r1, r0, CLK_RESET_PLLX_BASE + tegra_get_soc_id TEGRA_APB_MISC_BASE, r1 + cmp r1, #TEGRA30 + beq 1f + ldr r1, [r0, #CLK_RESET_PLLP_BASE] + bic r1, r1, #(1<<31) @ disable PllP bypass + str r1, [r0, #CLK_RESET_PLLP_BASE] +1: + mov32 r7, TEGRA_TMRUS_BASE ldr r1, [r7] add r1, r1, #LOCK_DELAY
@@ -630,7 +638,10 @@ tegra30_switch_cpu_to_clk32k: str r0, [r4, #PMC_PLLP_WB0_OVERRIDE] /* disable PLLP, PLLA, PLLC and PLLX */ + tegra_get_soc_id TEGRA_APB_MISC_BASE, r1 + cmp r1, #TEGRA30 ldr r0, [r5, #CLK_RESET_PLLP_BASE] + orrne r0, r0, #(1 << 31) @ enable PllP bypass on fast cluster bic r0, r0, #(1 << 30) str r0, [r5, #CLK_RESET_PLLP_BASE] ldr r0, [r5, #CLK_RESET_PLLA_BASE]
Greg Kroah-Hartman
maintainerPATCH 180/309 iwlwifi: dont throw error when trying to remove IGTK
In reply to Greg Kroah-HartmanFrom: Luca Coelho <[email protected]>
commit 197288d5ba8a5289f22d3aeb4fca3824bfd9b4af upstream.
The IGTK keys are only removed by mac80211 after it has already removed the AP station. This causes the driver to throw an error because mac80211 is trying to remove the IGTK when the station doesn't exist anymore.
The firmware is aware that the station has been removed and can deal with it the next time we try to add an IGTK for a station, so we shouldn't try to remove the key if the station ID is IWL_MVM_INVALID_STA. Do this by removing the check for mvm_sta before calling iwl_mvm_send_sta_igtk() and check return from that function gracefully if the station ID is invalid.
--- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/net/wireless/intel/iwlwifi/mvm/sta.c +7 -3
@@ -3321,6 +3321,10 @@ static int iwl_mvm_send_sta_igtk(struct igtk_cmd.sta_id =cpu_to_le32 (sta_id);if (remove_key) { +/* This is a valid situation for IGTK */ +if (sta_id ==IWL_MVM_INVALID_STA ) +return 0 ; + igtk_cmd.ctrl_flags |=cpu_to_le32 (STA_KEY_NOT_VALID ); }else {struct ieee80211_key_seq seq;
@@ -3575,9 +3579,9 @@ int iwl_mvm_remove_sta_key(struct iwl_mvIWL_DEBUG_WEP (mvm,"mvm remove dynamic key: idx=%d sta=%d\n" , keyconf->keyidx, sta_id); -if (mvm_sta && (keyconf->cipher ==WLAN_CIPHER_SUITE_AES_CMAC || - keyconf->cipher ==WLAN_CIPHER_SUITE_BIP_GMAC_128 || - keyconf->cipher ==WLAN_CIPHER_SUITE_BIP_GMAC_256 )) +if (keyconf->cipher ==WLAN_CIPHER_SUITE_AES_CMAC || + keyconf->cipher ==WLAN_CIPHER_SUITE_BIP_GMAC_128 || + keyconf->cipher ==WLAN_CIPHER_SUITE_BIP_GMAC_256 )return iwl_mvm_send_sta_igtk (mvm, keyconf, sta_id, true);if (!__test_and_clear_bit (keyconf->hw_key_idx, mvm->fw_key_table)) {
Greg Kroah-Hartman
maintainerPATCH 181/309 mwifiex: fix unbalanced locking in mwifiex_process_country_ie()
In reply to Greg Kroah-HartmanFrom: Brian Norris <[email protected]>
commit 65b1aae0d9d5962faccc06bdb8e91a2a0b09451c upstream.
We called rcu_read_lock(), so we need to call rcu_read_unlock() before we return.
--- drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +1 -0
@@ -232,6 +232,7 @@ static int mwifiex_process_country_ie(stif (country_ie_len > (IEEE80211_COUNTRY_STRING_LEN +MWIFIEX_MAX_TRIPLET_802_11D )) { +rcu_read_unlock ();mwifiex_dbg (priv->adapter,ERROR ,"11D: country_ie_len overflow!, deauth AP\n" );return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 182/309 sunrpc: expiry_time should be seconds not timeval
In reply to Greg Kroah-HartmanFrom: Roberto Bergantinos Corpas <[email protected]>
commit 3d96208c30f84d6edf9ab4fac813306ac0d20c10 upstream.
When upcalling gssproxy, cache_head.expiry_time is set as a timeval, not seconds since boot. As such, RPC cache expiry logic will not clean expired objects created under auth.rpcsec.context cache.
This has proven to cause kernel memory leaks on field. Using 64 bit variants of getboottime/timespec
Expiration times have worked this way since 2010's c5b29f885afe "sunrpc:
use seconds since boot in expiry cache". The gssproxy code introduced in 2012 added gss_proxy_save_rsc and introduced the bug. That's a while for this to lurk, but it required a bit of an extreme case to make it obvious.
--- net/sunrpc/auth_gss/svcauth_gss.c | 4 ++++ 1 file changed, 4 insertions(+)
net/sunrpc/auth_gss/svcauth_gss.c +4 -0
@@ -1245,6 +1245,7 @@ static int gss_proxy_save_rsc(struct cacdprintk ("RPC: No creds found!\n" ); goto out; }else { +struct timespec64 boot;/* steal creds */ rsci.cred = ud->creds;
@@ -1265,6 +1266,9 @@ static int gss_proxy_save_rsc(struct cac &expiry, GFP_KERNEL);if (status) goto out; + +getboottime64 (&boot); + expiry -= boot.tv_sec; } rsci.h.expiry_time = expiry;
Greg Kroah-Hartman
maintainerPATCH 183/309 gfs2: fix gfs2_find_jhead that returns uninitialized jhead with seq 0
In reply to Greg Kroah-HartmanFrom: Abhi Das <[email protected]>
commit 7582026f6f3588ecebd281965c8a71aff6fb6158 upstream.
When the first log header in a journal happens to have a sequence number of 0, a bug in gfs2_find_jhead() causes it to prematurely exit, and return an uninitialized jhead with seq 0. This can cause failures in the caller. For instance, a mount fails in one test case.
The correct behavior is for it to continue searching through the journal to find the correct journal head with the highest sequence number.
--- fs/gfs2/lops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/gfs2/lops.c +1 -1
@@ -421,7 +421,7 @@ static bool gfs2_jhead_pg_srch(struct gffor (offset =0 ; offset <PAGE_SIZE ; offset += sdp->sd_sb.sb_bsize) {if (!__get_log_header (sdp, kaddr + offset,0 , &lh)) { -if (lh.lh_sequence > head->lh_sequence) +if (lh.lh_sequence >= head->lh_sequence) *head = lh;else { ret = true;
Greg Kroah-Hartman
maintainerPATCH 184/309 gfs2: move setting current->backing_dev_info
In reply to Greg Kroah-HartmanFrom: Christoph Hellwig <[email protected]>
commit 4c0e8dda608a51855225c611b5c6b442f95fbc56 upstream.
Set current->backing_dev_info just around the buffered write calls to prepare for the next fix.
--- fs/gfs2/file.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-)
fs/gfs2/file.c +10 -11
@@ -853,18 +853,15 @@ static ssize_t gfs2_file_write_iter(struinode_lock (inode); ret =generic_write_checks (iocb, from);if (ret <=0 ) - goto out; - -/* We can write back this queue in page reclaim */ - current->backing_dev_info =inode_to_bdi (inode); + goto out_unlock; ret =file_remove_privs (file);if (ret) - goto out2; + goto out_unlock; ret =file_update_time (file);if (ret) - goto out2; + goto out_unlock;if (iocb->ki_flags &IOCB_DIRECT ) {struct address_space *mapping = file->f_mapping;
@@ -873,11 +870,13 @@ static ssize_t gfs2_file_write_iter(stru written =gfs2_file_direct_write (iocb, from);if (written <0 || !iov_iter_count (from)) - goto out2; + goto out_unlock; + current->backing_dev_info =inode_to_bdi (inode); ret =iomap_file_buffered_write (iocb, from, &gfs2_iomap_ops); + current->backing_dev_info =NULL ;if (unlikely (ret <0 )) - goto out2; + goto out_unlock; buffered = ret;/*
@@ -901,14 +900,14 @@ static ssize_t gfs2_file_write_iter(stru*/ } }else { + current->backing_dev_info =inode_to_bdi (inode); ret =iomap_file_buffered_write (iocb, from, &gfs2_iomap_ops); + current->backing_dev_info =NULL ;if (likely (ret >0 )) iocb->ki_pos += ret; } -out2: - current->backing_dev_info =NULL ; -out: +out_unlock:inode_unlock (inode);if (likely (ret >0 )) {/* Handle various SYNC-type writes */
Greg Kroah-Hartman
maintainerPATCH 185/309 gfs2: fix O_SYNC write handling
In reply to Greg Kroah-HartmanFrom: Andreas Gruenbacher <[email protected]>
commit 6e5e41e2dc4e4413296d5a4af54ac92d7cd52317 upstream.
In gfs2_file_write_iter, for direct writes, the error checking in the buffered write fallback case is incomplete. This can cause inode write errors to go undetected. Fix and clean up gfs2_file_write_iter along the way.
Based on a proposed fix by Christoph Hellwig <[email protected]>.
--- fs/gfs2/file.c | 51 +++++++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 30 deletions(-)
fs/gfs2/file.c +21 -30
@@ -833,7 +833,7 @@ static ssize_t gfs2_file_write_iter(strustruct file *file = iocb->ki_filp;struct inode *inode =file_inode (file);struct gfs2_inode *ip =GFS2_I (inode); -ssize_t written =0 , ret; +ssize_t ret; ret =gfs2_rsqa_alloc (ip);if (ret)
@@ -865,55 +865,46 @@ static ssize_t gfs2_file_write_iter(struif (iocb->ki_flags &IOCB_DIRECT ) {struct address_space *mapping = file->f_mapping; -loff_t pos, endbyte; -ssize_t buffered; +ssize_t buffered, ret2; - written =gfs2_file_direct_write (iocb, from); -if (written <0 || !iov_iter_count (from)) + ret =gfs2_file_direct_write (iocb, from); +if (ret <0 || !iov_iter_count (from)) goto out_unlock; + iocb->ki_flags |=IOCB_DSYNC ; current->backing_dev_info =inode_to_bdi (inode); - ret =iomap_file_buffered_write (iocb, from, &gfs2_iomap_ops); + buffered =iomap_file_buffered_write (iocb, from, &gfs2_iomap_ops); current->backing_dev_info =NULL ; -if (unlikely (ret <0 )) +if (unlikely (buffered <=0 )) goto out_unlock; - buffered = ret;/* * We need to ensure that the page cache pages are written to * disk and invalidated to preserve the expected O_DIRECT -* semantics. +* semantics. If the writeback or invalidate fails, only report +* the direct I/O range as we don't know if the buffered pages +* made it to disk. */ - pos = iocb->ki_pos; - endbyte = pos + buffered -1 ; - ret =filemap_write_and_wait_range (mapping, pos, endbyte); -if (!ret) { - iocb->ki_pos += buffered; - written += buffered; -invalidate_mapping_pages (mapping, - pos >>PAGE_SHIFT , - endbyte >>PAGE_SHIFT ); - }else { -/* -* We don't know how much we wrote, so just return -* the number of bytes which were direct-written -*/ - } + iocb->ki_pos += buffered; + ret2 =generic_write_sync (iocb, buffered); +invalidate_mapping_pages (mapping, + (iocb->ki_pos - buffered) >>PAGE_SHIFT , + (iocb->ki_pos -1 ) >>PAGE_SHIFT ); +if (!ret || ret2 >0 ) + ret += ret2; }else { current->backing_dev_info =inode_to_bdi (inode); ret =iomap_file_buffered_write (iocb, from, &gfs2_iomap_ops); current->backing_dev_info =NULL ; -if (likely (ret >0 )) +if (likely (ret >0 )) { iocb->ki_pos += ret; + ret =generic_write_sync (iocb, ret); + } } out_unlock:inode_unlock (inode); -if (likely (ret >0 )) { -/* Handle various SYNC-type writes */ - ret =generic_write_sync (iocb, ret); - } -return written ? written : ret; +return ret; } static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
Greg Kroah-Hartman
maintainerPATCH 186/309 drm: atmel-hlcdc: use double rate for pixel clock only if supported
In reply to Greg Kroah-HartmanFrom: Claudiu Beznea <[email protected]>
commit 07acf4bafe81dd37eff3fbcfbbdbc48084bc202b upstream.
Doubled system clock should be used as pixel cock source only if this is supported. This is emphasized by the value of atmel_hlcdc_crtc::dc::desc::fixed_clksrc.
--- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +3 -3
@@ -95,14 +95,14 @@ static void atmel_hlcdc_crtc_mode_set_no (adj->crtc_hdisplay -1 ) | ((adj->crtc_vdisplay - 1) << 16)); + prate =clk_get_rate (crtc->dc->hlcdc->sys_clk); + mode_rate = adj->crtc_clock *1000 ;if (!crtc->dc->desc->fixed_clksrc) { + prate *=2 ; cfg |=ATMEL_HLCDC_CLKSEL ; mask |=ATMEL_HLCDC_CLKSEL ; } - prate =2 *clk_get_rate (crtc->dc->hlcdc->sys_clk); - mode_rate = adj->crtc_clock *1000 ; - div =DIV_ROUND_UP (prate, mode_rate);if (div <2 ) { div =2 ;
Greg Kroah-Hartman
maintainerPATCH 187/309 drm: atmel-hlcdc: enable clock before configuring timing engine
In reply to Greg Kroah-HartmanFrom: Claudiu Beznea <[email protected]>
commit 2c1fb9d86f6820abbfaa38a6836157c76ccb4e7b upstream.
Changing pixel clock source without having this clock source enabled will block the timing engine and the next operations after (in this case setting ATMEL_HLCDC_CFG(5) settings in atmel_hlcdc_crtc_mode_set_nofb() will fail). It is recomended (although in datasheet this is not present) to actually enabled pixel clock source before doing any changes on timing enginge (only SAM9X60 datasheet specifies that the peripheral clock and pixel clock must be enabled before using LCD controller).
--- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +7 -1
@@ -73,7 +73,11 @@ static void atmel_hlcdc_crtc_mode_set_nounsigned long prate;unsigned int mask =ATMEL_HLCDC_CLKDIV_MASK |ATMEL_HLCDC_CLKPOL ;unsigned int cfg =0 ; -int div; +int div, ret; + + ret =clk_prepare_enable (crtc->dc->hlcdc->sys_clk); +if (ret) +return ; vm.vfront_porch = adj->crtc_vsync_start - adj->crtc_vdisplay; vm.vback_porch = adj->crtc_vtotal - adj->crtc_vsync_end;
@@ -147,6 +151,8 @@ static void atmel_hlcdc_crtc_mode_set_noATMEL_HLCDC_VSPSU |ATMEL_HLCDC_VSPHO |ATMEL_HLCDC_GUARDTIME_MASK |ATMEL_HLCDC_MODE_MASK , cfg); + +clk_disable_unprepare (crtc->dc->hlcdc->sys_clk); } static enum drm_mode_status
Greg Kroah-Hartman
maintainerPATCH 188/309 drm: atmel-hlcdc: prefer a lower pixel-clock than requested
In reply to Greg Kroah-HartmanFrom: Peter Rosin <[email protected]>
commit 51a19d150b520f6cb42143f3bdffacd3c33d7ac5 upstream.
The intention was to only select a higher pixel-clock rate than the requested, if a slight overclocking would result in a rate significantly closer to the requested rate than if the conservative lower pixel-clock rate is selected. The fixed patch has the logic the other way around and actually prefers the higher frequency. Fix that.
--- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +2 -2
@@ -121,8 +121,8 @@ static void atmel_hlcdc_crtc_mode_set_noint div_low = prate / mode_rate;if (div_low >=2 && - ((prate / div_low - mode_rate) < -10 * (mode_rate - prate / div))) + (10 * (prate / div_low - mode_rate) < + (mode_rate - prate / div)))/* * At least 10 times better when using a higher * frequency than requested, instead of a lower.
Greg Kroah-Hartman
maintainerPATCH 189/309 drm/rect: Avoid division by zero
In reply to Greg Kroah-HartmanFrom: Ville Syrjälä <[email protected]>
commit 433480c1afd44f3e1e664b85063d98cefeefa0ed upstream.
Check for zero width/height destination rectangle in drm_rect_clip_scaled() to avoid a division by zero.
Testcase: igt/kms_selftest/drm_rect_clip_scaled_div_by_zero
--- drivers/gpu/drm/drm_rect.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/gpu/drm/drm_rect.c +6 -1
@@ -54,7 +54,12 @@ EXPORT_SYMBOL(drm_rect_intersect);static u32 clip_scaled (u32 src,u32 dst,u32 clip) { -u64 tmp =mul_u32_u32 (src, dst - clip); +u64 tmp; + +if (dst ==0 ) +return 0 ; + + tmp =mul_u32_u32 (src, dst - clip);/* * Round toward 1.0 when clipping so that we don't accidentally
Greg Kroah-Hartman
maintainerPATCH 190/309 media: iguanair: fix endpoint sanity check
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit 1b257870a78b0a9ce98fdfb052c58542022ffb5b upstream.
Make sure to use the current alternate setting, which need not be the first one by index, when verifying the endpoint descriptors and initialising the URBs.
Failing to do so could cause the driver to misbehave or trigger a WARN() in usb_submit_urb() that kernels with panic_on_warn set would choke on.
--- drivers/media/rc/iguanair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/rc/iguanair.c +1 -1
@@ -413,7 +413,7 @@ static int iguanair_probe(struct usb_intint ret, pipein, pipeout;struct usb_host_interface *idesc; - idesc = intf->altsetting; + idesc = intf->cur_altsetting;if (idesc->desc.bNumEndpoints <2 )return -ENODEV ;
Greg Kroah-Hartman
maintainerPATCH 191/309 media: rc: ensure lirc is initialized before registering input device
In reply to Greg Kroah-HartmanFrom: Sean Young <[email protected]>
commit 080d89f522e2baddb4fbbd1af4b67b5f92537ef8 upstream.
Once rc_open is called on the input device, lirc events can be delivered. Ensure lirc is ready to do so else we might get this:
Registered IR keymap rc-hauppauge
rc rc0: Hauppauge WinTV PVR-350 as /devices/pci0000:00/0000:00:1e.0/0000:04:00.0/i2c-0/0-0018/rc/rc0
input: Hauppauge WinTV PVR-350 as /devices/pci0000:00/0000:00:1e.0/0000:04:00.0/i2c-0/0-0018/rc/rc0/input9
BUG: kernel NULL pointer dereference, address: 0000000000000038 PGD 0 P4D 0 Oops: 0000 [#1] SMP PTI CPU: 1 PID: 17 Comm: kworker/1:0 Not tainted 5.3.11-300.fc31.x86_64 #1 Hardware name: /DG43NB, BIOS NBG4310H.86A.0096.2009.0903.1845 09/03/2009 Workqueue: events ir_work [ir_kbd_i2c] RIP: 0010:ir_lirc_scancode_event+0x3d/0xb0 Code: a6 b4 07 00 00 49 81 c6 b8 07 00 00 55 53 e8 ba a7 9d ff 4c 89 e7 49 89 45 00 e8 5e 7a 25 00 49 8b 1e 48 89 c5 4c 39 f3 74 58 <8b> 43 38 8b 53 40 89 c1 2b 4b 3c 39 ca 72 41 21 d0 49 8b 7d 00 49 RSP: 0018:ffffaae2000b3d88 EFLAGS: 00010017 RAX: 0000000000000002 RBX: 0000000000000000 RCX: 0000000000000019 RDX: 0000000000000001 RSI: 006e801b1f26ce6a RDI: ffff9e39797c37b4 RBP: 0000000000000002 R08: 0000000000000001 R09: 0000000000000001 R10: 0000000000000001 R11: 0000000000000001 R12: ffff9e39797c37b4 R13: ffffaae2000b3db8 R14: ffff9e39797c37b8 R15: ffff9e39797c33d8 FS: 0000000000000000(0000) GS:ffff9e397b680000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000038 CR3: 0000000035844000 CR4: 00000000000006e0 Call Trace: ir_do_keydown+0x8e/0x2b0 rc_keydown+0x52/0xc0 ir_work+0xb8/0x130 [ir_kbd_i2c] process_one_work+0x19d/0x340 worker_thread+0x50/0x3b0 kthread+0xfb/0x130 ? process_one_work+0x340/0x340 ? kthread_park+0x80/0x80 ret_from_fork+0x35/0x40 Modules linked in: rc_hauppauge tuner msp3400 saa7127 saa7115 ivtv(+)
tveeprom cx2341x v4l2_common videodev mc i2c_algo_bit ir_kbd_i2c ip_tables firewire_ohci e1000e serio_raw firewire_core ata_generic crc_itu_t pata_acpi pata_jmicron fuse
CR2: 0000000000000038
---[ end trace c67c2697a99fa74b ]--- RIP: 0010:ir_lirc_scancode_event+0x3d/0xb0 Code: a6 b4 07 00 00 49 81 c6 b8 07 00 00 55 53 e8 ba a7 9d ff 4c 89 e7 49 89 45 00 e8 5e 7a 25 00 49 8b 1e 48 89 c5 4c 39 f3 74 58 <8b> 43 38 8b 53 40 89 c1 2b 4b 3c 39 ca 72 41 21 d0 49 8b 7d 00 49 RSP: 0018:ffffaae2000b3d88 EFLAGS: 00010017 RAX: 0000000000000002 RBX: 0000000000000000 RCX: 0000000000000019 RDX: 0000000000000001 RSI: 006e801b1f26ce6a RDI: ffff9e39797c37b4 RBP: 0000000000000002 R08: 0000000000000001 R09: 0000000000000001 R10: 0000000000000001 R11: 0000000000000001 R12: ffff9e39797c37b4 R13: ffffaae2000b3db8 R14: ffff9e39797c37b8 R15: ffff9e39797c33d8 FS: 0000000000000000(0000) GS:ffff9e397b680000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000038 CR3: 0000000035844000 CR4: 00000000000006e0 rc rc0: lirc_dev: driver ir_kbd_i2c registered at minor = 0, scancode
receiver, no transmitter
tuner-simple 0-0061: creating new instance
tuner-simple 0-0061: type set to 2 (Philips NTSC (FI1236,FM1236 and compatibles))
ivtv0: Registered device video0 for encoder MPG (4096 kB)
ivtv0: Registered device video32 for encoder YUV (2048 kB)
ivtv0: Registered device vbi0 for encoder VBI (1024 kB)
ivtv0: Registered device video24 for encoder PCM (320 kB)
ivtv0: Registered device radio0 for encoder radio
ivtv0: Registered device video16 for decoder MPG (1024 kB)
ivtv0: Registered device vbi8 for decoder VBI (64 kB)
ivtv0: Registered device vbi16 for decoder VOUT
ivtv0: Registered device video48 for decoder YUV (1024 kB)
--- drivers/media/rc/rc-main.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-)
drivers/media/rc/rc-main.c +16 -11
@@ -1891,23 +1891,28 @@ int rc_register_device(struct rc_dev *de dev->registered = true; -if (dev->driver_type !=RC_DRIVER_IR_RAW_TX ) { - rc =rc_setup_rx_device (dev); -if (rc) - goto out_dev; - } - -/* Ensure that the lirc kfifo is setup before we start the thread */ +/* +* once the the input device is registered in rc_setup_rx_device, +* userspace can open the input device and rc_open() will be called +* as a result. This results in driver code being allowed to submit +* keycodes with rc_keydown, so lirc must be registered first. +*/ if (dev->allowed_protocols !=RC_PROTO_BIT_CEC ) { rc =ir_lirc_register (dev);if (rc <0 ) - goto out_rx; + goto out_dev; + } + +if (dev->driver_type !=RC_DRIVER_IR_RAW_TX ) { + rc =rc_setup_rx_device (dev); +if (rc) + goto out_lirc; }if (dev->driver_type ==RC_DRIVER_IR_RAW ) { rc =ir_raw_event_register (dev);if (rc <0 ) - goto out_lirc; + goto out_rx; } dev_dbg(&dev->dev, "Registered rc%u (driver: %s)\n", dev->minor,
@@ -1915,11 +1920,11 @@ int rc_register_device(struct rc_dev *dereturn 0 ; +out_rx: +rc_free_rx_device (dev); out_lirc:if (dev->allowed_protocols !=RC_PROTO_BIT_CEC )ir_lirc_unregister (dev); -out_rx: -rc_free_rx_device (dev); out_dev:device_del (&dev->dev); out_rx_free:
Greg Kroah-Hartman
maintainerPATCH 192/309 tools/kvm_stat: Fix kvm_exit filter name
In reply to Greg Kroah-HartmanFrom: Gavin Shan <[email protected]>
commit 5fcf3a55a62afb0760ccb6f391d62f20bce4a42f upstream.
The filter name is fixed to "exit_reason" for some kvm_exit events, no matter what architect we have. Actually, the filter name ("exit_reason") is only applicable to x86, meaning it's broken on other architects including aarch64.
This fixes the issue by providing various kvm_exit filter names, depending on architect we're on. Afterwards, the variable filter name is picked and applied through ioctl(fd, SET_FILTER).
--- tools/kvm/kvm_stat/kvm_stat | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
tools/kvm/kvm_stat/kvm_stat +6 -2
@@ -270,6 +270,7 @@ class ArchX86(Arch): def __init__(self, exit_reasons): self.sc_perf_evt_open = 298 self.ioctl_numbers = IOCTL_NUMBERS + self.exit_reason_field = 'exit_reason' self.exit_reasons = exit_reasons def debugfs_is_child(self, field):
@@ -289,6 +290,7 @@ class ArchPPC(Arch): # numbers depend on the wordsize. char_ptr_size = ctypes.sizeof(ctypes.c_char_p) self.ioctl_numbers['SET_FILTER'] = 0x80002406 | char_ptr_size << 16 + self.exit_reason_field = 'exit_nr' self.exit_reasons = {} def debugfs_is_child(self, field):
@@ -300,6 +302,7 @@ class ArchA64(Arch): def __init__(self): self.sc_perf_evt_open = 241 self.ioctl_numbers = IOCTL_NUMBERS + self.exit_reason_field = 'esr_ec' self.exit_reasons = AARCH64_EXIT_REASONS def debugfs_is_child(self, field):
@@ -311,6 +314,7 @@ class ArchS390(Arch): def __init__(self): self.sc_perf_evt_open = 331 self.ioctl_numbers = IOCTL_NUMBERS + self.exit_reason_field = None self.exit_reasons = None def debugfs_is_child(self, field):
@@ -541,8 +545,8 @@ class TracepointProvider(Provider): """ filters = {} filters['kvm_userspace_exit'] = ('reason', USERSPACE_EXIT_REASONS) - if ARCH.exit_reasons: - filters['kvm_exit'] = ('exit_reason', ARCH.exit_reasons) + if ARCH.exit_reason_field and ARCH.exit_reasons: + filters['kvm_exit'] = (ARCH.exit_reason_field, ARCH.exit_reasons) return filters def _get_available_fields(self):
Greg Kroah-Hartman
maintainerPATCH 193/309 xen/balloon: Support xend-based toolstack take two
In reply to Greg Kroah-HartmanFrom: Juergen Gross <[email protected]>
commit eda4eabf86fd6806eaabc23fb90dd056fdac037b upstream.
Commit 3aa6c19d2f38be ("xen/balloon: Support xend-based toolstack") tried to fix a regression with running on rather ancient Xen versions. Unfortunately the fix was based on the assumption that xend would just use another Xenstore node, but in reality only some downstream versions of xend are doing that. The upstream xend does not write that Xenstore node at all, so the problem must be fixed in another way.
The easiest way to achieve that is to fall back to the behavior before commit 96edd61dcf4436 ("xen/balloon: don't online new memory initially") in case the static memory maximum can't be read.
This is achieved by setting static_max to the current number of memory pages known by the system resulting in target_diff becoming zero.
--- drivers/xen/xen-balloon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/xen/xen-balloon.c +1 -1
@@ -94,7 +94,7 @@ static void watch_target(struct xenbus_w "%llu", &static_max) == 1)) static_max >>=PAGE_SHIFT -10 ; else - static_max = new_target; + static_max = balloon_stats.current_pages; target_diff = (xen_pv_domain () ||xen_initial_domain ()) ?0 : static_max - balloon_stats.target_pages;
Greg Kroah-Hartman
maintainerPATCH 194/309 watchdog: fix UAF in reboot notifier handling in watchdog core code
In reply to Greg Kroah-HartmanFrom: Vladis Dronov <[email protected]>
commit 69503e585192fdd84b240f18a0873d20e18a2e0a upstream.
After the commit 44ea39420fc9 ("drivers/watchdog: make use of devm_register_reboot_notifier()") the struct notifier_block reboot_nb in the struct watchdog_device is removed from the reboot notifiers chain at the time watchdog's chardev is closed. But at least in i6300esb.c case reboot_nb is embedded in the struct esb_dev which can be freed on its device removal and before the chardev is closed, thus UAF at reboot:
[ 7.728581] esb_probe: esb_dev.watchdog_device ffff91316f91ab28
ts# uname -r note the address ^^^
5.5.0-rc5-ae6088-wdog
ts# ./openwdog0 &
[1] 696
ts# opened /dev/watchdog0, sleeping 10s...
ts# echo 1 > /sys/devices/pci0000\:00/0000\:00\:09.0/remove
[ 178.086079] devres:rel_nodes: dev ffff91317668a0b0 data ffff91316f91ab28
esb_dev.watchdog_device.reboot_nb memory is freed here ^^^
ts# ...woken up
[ 181.459010] devres:rel_nodes: dev ffff913171781000 data ffff913174a1dae8
[ 181.460195] devm_unreg_reboot_notifier: res ffff913174a1dae8 nb ffff91316f91ab78
attempt to use memory already freed ^^^
[ 181.461063] devm_unreg_reboot_notifier: nb->call 6b6b6b6b6b6b6b6b
[ 181.461243] devm_unreg_reboot_notifier: nb->next 6b6b6b6b6b6b6b6b
freed memory is filled with a slub poison ^^^
[1]+ Done ./openwdog0
ts# reboot
[ 229.921862] systemd-shutdown[1]: Rebooting.
[ 229.939265] notifier_call_chain: nb ffffffff9c6c2f20 nb->next ffffffff9c6d50c0
[ 229.943080] notifier_call_chain: nb ffffffff9c6d50c0 nb->next 6b6b6b6b6b6b6b6b
[ 229.946054] notifier_call_chain: nb 6b6b6b6b6b6b6b6b INVAL
[ 229.957584] general protection fault: 0000 [#1] SMP
[ 229.958770] CPU: 0 PID: 1 Comm: systemd-shutdow Not tainted 5.5.0-rc5-ae6088-wdog
[ 229.960224] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), ...
[ 229.963288] RIP: 0010:notifier_call_chain+0x66/0xd0
[ 229.969082] RSP: 0018:ffffb20dc0013d88 EFLAGS: 00010246
[ 229.970812] RAX: 000000000000002e RBX: 6b6b6b6b6b6b6b6b RCX: 00000000000008b3
[ 229.972929] RDX: 0000000000000000 RSI: 0000000000000096 RDI: ffffffff9ccc46ac
[ 229.975028] RBP: 0000000000000001 R08: 0000000000000000 R09: 00000000000008b3
[ 229.977039] R10: 0000000000000001 R11: ffffffff9c26c740 R12: 0000000000000000
[ 229.979155] R13: 6b6b6b6b6b6b6b6b R14: 0000000000000000 R15: 00000000fffffffa
... slub_debug=FZP poison ^^^
[ 229.989089] Call Trace:
[ 229.990157] blocking_notifier_call_chain+0x43/0x59
[ 229.991401] kernel_restart_prepare+0x14/0x30
[ 229.992607] kernel_restart+0x9/0x30
[ 229.993800] __do_sys_reboot+0x1d2/0x210
[ 230.000149] do_syscall_64+0x3d/0x130
[ 230.001277] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 230.002639] RIP: 0033:0x7f5461bdd177
[ 230.016402] Modules linked in: i6300esb
[ 230.050261] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000bFix the crash by reverting 44ea39420fc9 so unregister_reboot_notifier() is called when watchdog device is removed. This also makes handling of the reboot notifier unified with the handling of the restart handler, which is freed with unregister_restart_handler() in the same place.
--- drivers/watchdog/watchdog_core.c | 35 +++++++++++++++++++++++++++++++++++ drivers/watchdog/watchdog_dev.c | 36 +----------------------------------- 2 files changed, 36 insertions(+), 35 deletions(-)
drivers/watchdog/watchdog_core.c +35 -0
@@ -147,6 +147,25 @@ int watchdog_init_timeout(struct watchdo }EXPORT_SYMBOL_GPL (watchdog_init_timeout); +static int watchdog_reboot_notifier (struct notifier_block *nb, +unsigned long code,void *data) +{ +struct watchdog_device *wdd; + + wdd = container_of(nb, struct watchdog_device, reboot_nb); +if (code ==SYS_DOWN || code ==SYS_HALT ) { +if (watchdog_active (wdd)) { +int ret; + + ret = wdd->ops->stop (wdd); +if (ret) +return NOTIFY_BAD ; + } + } + +return NOTIFY_DONE ; +} +static int watchdog_restart_notifier (struct notifier_block *nb,unsigned long action,void *data) {
@@ -235,6 +254,19 @@ static int __watchdog_register_device(st } } +if (test_bit (WDOG_STOP_ON_REBOOT , &wdd->status)) { + wdd->reboot_nb.notifier_call = watchdog_reboot_notifier; + + ret =register_reboot_notifier (&wdd->reboot_nb); +if (ret) { +pr_err ("watchdog%d: Cannot register reboot notifier (%d)\n" , + wdd->id, ret); +watchdog_dev_unregister (wdd); +ida_simple_remove (&watchdog_ida, id); +return ret; + } + } +if (wdd->ops->restart) { wdd->restart_nb.notifier_call = watchdog_restart_notifier;
@@ -289,6 +321,9 @@ static void __watchdog_unregister_deviceif (wdd->ops->restart)unregister_restart_handler (&wdd->restart_nb); +if (test_bit (WDOG_STOP_ON_REBOOT , &wdd->status)) +unregister_reboot_notifier (&wdd->reboot_nb); +watchdog_dev_unregister (wdd);ida_simple_remove (&watchdog_ida, wdd->id); }
drivers/watchdog/watchdog_dev.c +1 -35
@@ -38,7 +38,6 @@#include <linux/miscdevice.h> /* For handling misc devices */ #include <linux/module.h> /* For module stuff/... */ #include <linux/mutex.h> /* For mutexes */ -#include <linux/reboot.h> /* For reboot notifier */ #include <linux/slab.h> /* For memory functions */ #include <linux/types.h> /* For standard types (like size_t) */ #include <linux/watchdog.h> /* For watchdog specific items */
@@ -1077,25 +1076,6 @@ static void watchdog_cdev_unregister(strput_device (&wd_data->dev); } -static int watchdog_reboot_notifier (struct notifier_block *nb, -unsigned long code,void *data) -{ -struct watchdog_device *wdd; - - wdd = container_of(nb, struct watchdog_device, reboot_nb); -if (code ==SYS_DOWN || code ==SYS_HALT ) { -if (watchdog_active (wdd)) { -int ret; - - ret = wdd->ops->stop (wdd); -if (ret) -return NOTIFY_BAD ; - } - } - -return NOTIFY_DONE ; -} -/* * watchdog_dev_register: register a watchdog device * @wdd: watchdog device
@@ -1114,22 +1094,8 @@ int watchdog_dev_register(struct watchdoreturn ret; ret =watchdog_register_pretimeout (wdd); -if (ret) { +if (ret)watchdog_cdev_unregister (wdd); -return ret; - } - -if (test_bit (WDOG_STOP_ON_REBOOT , &wdd->status)) { - wdd->reboot_nb.notifier_call = watchdog_reboot_notifier; - - ret =devm_register_reboot_notifier (&wdd->wd_data->dev, - &wdd->reboot_nb); -if (ret) { -pr_err ("watchdog%d: Cannot register reboot notifier (%d)\n" , - wdd->id, ret); -watchdog_dev_unregister (wdd); - } - }return ret; }
Greg Kroah-Hartman
maintainerPATCH 195/309 bcache: add readahead cache policy options via sysfs interface
In reply to Greg Kroah-HartmanFrom: Coly Li <[email protected]>
commit 038ba8cc1bffc51250add4a9b9249d4331576d8f upstream.
In year 2007 high performance SSD was still expensive, in order to save more space for real workload or meta data, the readahead I/Os for non-meta data was bypassed and not cached on SSD.
In now days, SSD price drops a lot and people can find larger size SSD with more comfortable price. It is unncessary to alway bypass normal readahead I/Os to save SSD space for now.
This patch adds options for readahead data cache policies via sysfs file /sys/block/bcache<N>/readahead_cache_policy, the options are,
- "all": cache all readahead data I/Os.
- "meta-only": only cache meta data, and bypass other regular I/Os.
If users want to make bcache continue to only cache readahead request for metadata and bypass regular data readahead, please set "meta-only" to this sysfs file. By default, bcache will back to cache all read- ahead requests now.
--- drivers/md/bcache/bcache.h | 3 +++ drivers/md/bcache/request.c | 17 ++++++++++++----- drivers/md/bcache/sysfs.c | 22 ++++++++++++++++++++++ 3 files changed, 37 insertions(+), 5 deletions(-)
drivers/md/bcache/bcache.h +3 -0
@@ -329,6 +329,9 @@ struct cached_dev {*/ atomic_t has_dirty; +#define BCH_CACHE_READA_ALL 0 +#define BCH_CACHE_READA_META_ONLY 1 +unsigned int cache_readahead_policy;struct bch_ratelimit writeback_rate;struct delayed_work writeback_rate_update;
drivers/md/bcache/request.c +12 -5
@@ -391,13 +391,20 @@ static bool check_should_bypass(struct c goto skip;/* -* Flag for bypass if the IO is for read-ahead or background, -* unless the read-ahead request is for metadata +* If the bio is for read-ahead or background IO, bypass it or +* not depends on the following situations, +* - If the IO is for meta data, always cache it and no bypass +* - If the IO is not meta data, check dc->cache_reada_policy, +* BCH_CACHE_READA_ALL: cache it and not bypass +* BCH_CACHE_READA_META_ONLY: not cache it and bypass +* That is, read-ahead request for metadata always get cached * (eg, for gfs2 or xfs). */ -if (bio->bi_opf & (REQ_RAHEAD |REQ_BACKGROUND ) && - !(bio->bi_opf & (REQ_META |REQ_PRIO ))) - goto skip; +if ((bio->bi_opf & (REQ_RAHEAD |REQ_BACKGROUND ))) { +if (!(bio->bi_opf & (REQ_META |REQ_PRIO )) && + (dc->cache_readahead_policy !=BCH_CACHE_READA_ALL )) + goto skip; + }if (bio->bi_iter.bi_sector & (c->sb.block_size -1 ) ||bio_sectors (bio) & (c->sb.block_size -1 )) {
drivers/md/bcache/sysfs.c +22 -0
@@ -27,6 +27,12 @@ static const char * const bch_cache_modeNULL }; +static const char *const bch_reada_cache_policies[] = { +"all" , +"meta-only" , +NULL +}; +/* Default is 0 ("auto") */ static const char *const bch_stop_on_failure_modes[] = {"auto" ,
@@ -100,6 +106,7 @@ rw_attribute(congested_write_threshold_urw_attribute (sequential_cutoff);rw_attribute (data_csum);rw_attribute (cache_mode); +rw_attribute (readahead_cache_policy);rw_attribute (stop_when_cache_set_failed);rw_attribute (writeback_metadata);rw_attribute (writeback_running);
@@ -167,6 +174,11 @@ SHOW(__bch_cached_dev) bch_cache_modes, BDEV_CACHE_MODE(&dc->sb)); +if (attr == &sysfs_readahead_cache_policy) +return bch_snprint_string_list (buf,PAGE_SIZE , + bch_reada_cache_policies, + dc->cache_readahead_policy); +if (attr == &sysfs_stop_when_cache_set_failed) return bch_snprint_string_list(buf, PAGE_SIZE, bch_stop_on_failure_modes,
@@ -352,6 +364,15 @@ STORE(__cached_dev) } } +if (attr == &sysfs_readahead_cache_policy) { + v =__sysfs_match_string (bch_reada_cache_policies,-1 , buf); +if (v <0 ) +return v; + +if ((unsigned int ) v != dc->cache_readahead_policy) + dc->cache_readahead_policy = v; + } +if (attr == &sysfs_stop_when_cache_set_failed) { v =__sysfs_match_string (bch_stop_on_failure_modes,-1 , buf);if (v <0 )
@@ -466,6 +487,7 @@ static struct attribute *bch_cached_dev_ &sysfs_data_csum, #endif &sysfs_cache_mode, + &sysfs_readahead_cache_policy, &sysfs_stop_when_cache_set_failed, &sysfs_writeback_metadata, &sysfs_writeback_running,
Greg Kroah-Hartman
maintainerPATCH 196/309 eventfd: track eventfd_signal() recursion depth
In reply to Greg Kroah-HartmanFrom: Jens Axboe <[email protected]>
commit b5e683d5cab8cd433b06ae178621f083cabd4f63 upstream.
eventfd use cases from aio and io_uring can deadlock due to circular or resursive calling, when eventfd_signal() tries to grab the waitqueue lock. On top of that, it's also possible to construct notification chains that are deep enough that we could blow the stack.
Add a percpu counter that tracks the percpu recursion depth, warn if we exceed it. The counter is also exposed so that users of eventfd_signal() can do the right thing if it's non-zero in the context where it is called.
--- fs/eventfd.c | 15 +++++++++++++++ include/linux/eventfd.h | 14 ++++++++++++++ 2 files changed, 29 insertions(+)
fs/eventfd.c +15 -0
@@ -24,6 +24,8 @@#include <linux/seq_file.h> #include <linux/idr.h> +DEFINE_PER_CPU (int, eventfd_wake_count); +static DEFINE_IDA (eventfd_ida);struct eventfd_ctx {
@@ -60,12 +62,25 @@ __u64 eventfd_signal(struct eventfd_ctx {unsigned long flags; +/* +* Deadlock or stack overflow issues can happen if we recurse here +* through waitqueue wakeup handlers. If the caller users potentially +* nested waitqueues with custom wakeup handlers, then it should +* check eventfd_signal_count() before calling this function. If +* it returns true, the eventfd_signal() call should be deferred to a +* safe context. +*/ +if (WARN_ON_ONCE (this_cpu_read (eventfd_wake_count))) +return 0 ; +spin_lock_irqsave (&ctx->wqh.lock, flags); +this_cpu_inc (eventfd_wake_count);if (ULLONG_MAX - ctx->count < n) n =ULLONG_MAX - ctx->count; ctx->count += n;if (waitqueue_active (&ctx->wqh))wake_up_locked_poll (&ctx->wqh,EPOLLIN ); +this_cpu_dec (eventfd_wake_count);spin_unlock_irqrestore (&ctx->wqh.lock, flags);return n;
include/linux/eventfd.h +14 -0
@@ -12,6 +12,8 @@#include <linux/fcntl.h> #include <linux/wait.h> #include <linux/err.h> +#include <linux/percpu-defs.h> +#include <linux/percpu.h> /* * CAREFUL: Check include/uapi/asm-generic/fcntl.h when defining
@@ -40,6 +42,13 @@ __u64 eventfd_signal(struct eventfd_ctxint eventfd_ctx_remove_wait_queue (struct eventfd_ctx *ctx,wait_queue_entry_t *wait,__u64 *cnt); +DECLARE_PER_CPU (int, eventfd_wake_count); + +static inline bool eventfd_signal_count (void ) +{ +return this_cpu_read (eventfd_wake_count); +} +#else /* CONFIG_EVENTFD */ /*
@@ -68,6 +77,11 @@ static inline int eventfd_ctx_remove_waireturn -ENOSYS ; } +static inline bool eventfd_signal_count (void ) +{ +return false; +} +#endif #endif /* _LINUX_EVENTFD_H */
Greg Kroah-Hartman
maintainerPATCH 197/309 aio: prevent potential eventfd recursion on poll
In reply to Greg Kroah-HartmanFrom: Jens Axboe <[email protected]>
commit 01d7a356872eec22ef34a33a5f9cfa917d145468 upstream.
If we have nested or circular eventfd wakeups, then we can deadlock if we run them inline from our poll waitqueue wakeup handler. It's also possible to have very long chains of notifications, to the extent where we could risk blowing the stack.
Check the eventfd recursion count before calling eventfd_signal(). If it's non-zero, then punt the signaling to async context. This is always safe, as it takes us out-of-line in terms of stack and locking context.
--- fs/aio.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
fs/aio.c +18 -2
@@ -1610,6 +1610,14 @@ static int aio_fsync(struct fsync_iocb *return 0 ; } +static void aio_poll_put_work (struct work_struct *work) +{ + struct poll_iocb *req = container_of(work, struct poll_iocb, work); + struct aio_kiocb *iocb = container_of(req, struct aio_kiocb, poll); + +iocb_put (iocb); +} +static void aio_poll_complete_work (struct work_struct *work) { struct poll_iocb *req = container_of(work, struct poll_iocb, work);
@@ -1674,6 +1682,8 @@ static int aio_poll_wake(struct wait_quelist_del_init (&req->wait.entry);if (mask &&spin_trylock_irqsave (&iocb->ki_ctx->ctx_lock, flags)) { +struct kioctx *ctx = iocb->ki_ctx; +/* * Try to complete the iocb inline if we can. Use * irqsave/irqrestore because not all filesystems (e.g. fuse)
@@ -1683,8 +1693,14 @@ static int aio_poll_wake(struct wait_quelist_del (&iocb->ki_list); iocb->ki_res.res =mangle_poll (mask); req->done = true; -spin_unlock_irqrestore (&iocb->ki_ctx->ctx_lock, flags); -iocb_put (iocb); +if (iocb->ki_eventfd &&eventfd_signal_count ()) { + iocb =NULL ; +INIT_WORK (&req->work, aio_poll_put_work); +schedule_work (&req->work); + } +spin_unlock_irqrestore (&ctx->ctx_lock, flags); +if (iocb) +iocb_put (iocb); }else {schedule_work (&req->work); }
Greg Kroah-Hartman
maintainerPATCH 198/309 KVM: x86: Refactor picdev_write() to prevent Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 14e32321f3606e4b0970200b6e5e47ee6f1e6410 upstream.
This fixes a Spectre-v1/L1TF vulnerability in picdev_write(). It replaces index computations based on the (attacked-controlled) port number with constants through a minor refactoring.
--- arch/x86/kvm/i8259.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
arch/x86/kvm/i8259.c +5 -1
@@ -460,10 +460,14 @@ static int picdev_write(struct kvm_pic *switch (addr) {case 0x20 :case 0x21 : +pic_lock (s); +pic_ioport_write (&s->pics[0 ], addr, data); +pic_unlock (s); +break ;case 0xa0 :case 0xa1 :pic_lock (s); -pic_ioport_write (&s->pics[addr >>7 ], addr, data); +pic_ioport_write (&s->pics[1 ], addr, data);pic_unlock (s);break ;case 0x4d0 :
Greg Kroah-Hartman
maintainerPATCH 199/309 KVM: x86: Refactor prefix decoding to prevent Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 125ffc5e0a56a3eded608dc51e09d5ebf72cf652 upstream.
This fixes Spectre-v1/L1TF vulnerabilities in vmx_read_guest_seg_selector(), vmx_read_guest_seg_base(), vmx_read_guest_seg_limit() and vmx_read_guest_seg_ar(). When invoked from emulation, these functions contain index computations based on the (attacker-influenced) segment value. Using constants prevents the attack.
--- arch/x86/kvm/emulate.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
arch/x86/kvm/emulate.c +14 -2
@@ -5212,16 +5212,28 @@ int x86_decode_insn(struct x86_emulate_c ctxt->ad_bytes = def_ad_bytes ^6 ;break ;case 0x26 :/* ES override */ + has_seg_override = true; + ctxt->seg_override =VCPU_SREG_ES ; +break ;case 0x2e :/* CS override */ + has_seg_override = true; + ctxt->seg_override =VCPU_SREG_CS ; +break ;case 0x36 :/* SS override */ + has_seg_override = true; + ctxt->seg_override =VCPU_SREG_SS ; +break ;case 0x3e :/* DS override */ has_seg_override = true; - ctxt->seg_override = (ctxt->b >>3 ) &3 ; + ctxt->seg_override =VCPU_SREG_DS ;break ;case 0x64 :/* FS override */ + has_seg_override = true; + ctxt->seg_override =VCPU_SREG_FS ; +break ;case 0x65 :/* GS override */ has_seg_override = true; - ctxt->seg_override = ctxt->b &7 ; + ctxt->seg_override =VCPU_SREG_GS ;break ; case 0x40 ... 0x4f: /* REX */if (mode !=X86EMUL_MODE_PROT64 )
Greg Kroah-Hartman
maintainerPATCH 200/309 KVM: x86: Protect pmu_intel.c from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 66061740f1a487f4ed54fde75e724709f805da53 upstream.
This fixes Spectre-v1/L1TF vulnerabilities in intel_find_fixed_event() and intel_rdpmc_ecx_to_pmc().kvm_rdpmc() (ancestor of intel_find_fixed_event()) and reprogram_fixed_counter() (ancestor of intel_rdpmc_ecx_to_pmc()) are exported symbols so KVM should treat them conservatively from a security perspective.
--- arch/x86/kvm/vmx/pmu_intel.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-)
arch/x86/kvm/vmx/pmu_intel.c +16 -8
@@ -84,10 +84,14 @@ static unsigned intel_find_arch_event(ststatic unsigned intel_find_fixed_event (int idx) { -if (idx >=ARRAY_SIZE (fixed_pmc_events)) +u32 event; +size_t size =ARRAY_SIZE (fixed_pmc_events); + +if (idx >= size)return PERF_COUNT_HW_MAX ; -return intel_arch_events[fixed_pmc_events[idx]].event_type; + event = fixed_pmc_events[array_index_nospec (idx, size)]; +return intel_arch_events[event].event_type; }/* check if a PMC is enabled by comparing it with globl_ctrl bits. */
@@ -128,16 +132,20 @@ static struct kvm_pmc *intel_msr_idx_to_struct kvm_pmu *pmu =vcpu_to_pmu (vcpu);bool fixed = idx & (1u <<30 );struct kvm_pmc *counters; +unsigned int num_counters; idx &= ~(3u <<30 ); -if (!fixed && idx >= pmu->nr_arch_gp_counters) -return NULL ; -if (fixed && idx >= pmu->nr_arch_fixed_counters) +if (fixed) { + counters = pmu->fixed_counters; + num_counters = pmu->nr_arch_fixed_counters; + }else { + counters = pmu->gp_counters; + num_counters = pmu->nr_arch_gp_counters; + } +if (idx >= num_counters)return NULL ; - counters = fixed ? pmu->fixed_counters : pmu->gp_counters; *mask &= pmu->counter_bitmask[fixed ?KVM_PMC_FIXED :KVM_PMC_GP ]; - -return &counters[idx]; +return &counters[array_index_nospec (idx, num_counters)]; }static bool intel_is_valid_msr (struct kvm_vcpu *vcpu,u32 msr)
Greg Kroah-Hartman
maintainerPATCH 201/309 KVM: x86: Protect DR-based index computations from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit ea740059ecb37807ba47b84b33d1447435a8d868 upstream.
This fixes a Spectre-v1/L1TF vulnerability in __kvm_set_dr() and kvm_get_dr().
Both kvm_get_dr() and kvm_set_dr() (a wrapper of __kvm_set_dr()) are exported symbols so KVM should tream them conservatively from a security perspective.
--- arch/x86/kvm/x86.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
arch/x86/kvm/x86.c +6 -2
@@ -1054,9 +1054,11 @@ static u64 kvm_dr6_fixed(struct kvm_vcpustatic int __kvm_set_dr (struct kvm_vcpu *vcpu,int dr,unsigned long val) { +size_t size =ARRAY_SIZE (vcpu->arch.db); +switch (dr) { case 0 ... 3: - vcpu->arch.db[dr] = val; + vcpu->arch.db[array_index_nospec (dr, size)] = val;if (!(vcpu->guest_debug &KVM_GUESTDBG_USE_HW_BP )) vcpu->arch.eff_db[dr] = val;break ;
@@ -1093,9 +1095,11 @@ EXPORT_SYMBOL_GPL(kvm_set_dr);int kvm_get_dr (struct kvm_vcpu *vcpu,int dr,unsigned long *val) { +size_t size =ARRAY_SIZE (vcpu->arch.db); +switch (dr) { case 0 ... 3: - *val = vcpu->arch.db[dr]; + *val = vcpu->arch.db[array_index_nospec (dr, size)];break ;case 4 :/* fall through */
Greg Kroah-Hartman
maintainerPATCH 202/309 KVM: x86: Protect kvm_lapic_reg_write() from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 4bf79cb089f6b1c6c632492c0271054ce52ad766 upstream.
This fixes a Spectre-v1/L1TF vulnerability in kvm_lapic_reg_write(). This function contains index computations based on the (attacker-controlled) MSR number.
--- arch/x86/kvm/lapic.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
arch/x86/kvm/lapic.c +9 -4
@@ -1926,15 +1926,20 @@ int kvm_lapic_reg_write(struct kvm_lapiccase APIC_LVTTHMR :case APIC_LVTPC :case APIC_LVT1 : -case APIC_LVTERR : +case APIC_LVTERR : {/* TODO: Check vector */ +size_t size; +u32 index; +if (!kvm_apic_sw_enabled (apic)) val |=APIC_LVT_MASKED ; - - val &= apic_lvt_mask[(reg -APIC_LVTT ) >>4 ]; + size =ARRAY_SIZE (apic_lvt_mask); + index =array_index_nospec ( + (reg -APIC_LVTT ) >>4 , size); + val &= apic_lvt_mask[index];kvm_lapic_set_reg (apic, reg, val); -break ; + }case APIC_LVTT :if (!kvm_apic_sw_enabled (apic))
Greg Kroah-Hartman
maintainerPATCH 203/309 KVM: x86: Protect kvm_hv_msr_[get|set]_crash_data() from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 8618793750071d66028584a83ed0b4fa7eb4f607 upstream.
This fixes Spectre-v1/L1TF vulnerabilities in kvm_hv_msr_get_crash_data() and kvm_hv_msr_set_crash_data().
These functions contain index computations that use the (attacker-controlled) MSR number.
--- arch/x86/kvm/hyperv.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
arch/x86/kvm/hyperv.c +6 -4
@@ -809,11 +809,12 @@ static int kvm_hv_msr_get_crash_data(str u32 index, u64 *pdata) { struct kvm_hv *hv = &vcpu->kvm->arch.hyperv; +size_t size =ARRAY_SIZE (hv->hv_crash_param); -if (WARN_ON_ONCE (index >=ARRAY_SIZE (hv->hv_crash_param))) +if (WARN_ON_ONCE (index >= size))return -EINVAL ; - *pdata = hv->hv_crash_param[index]; + *pdata = hv->hv_crash_param[array_index_nospec (index, size)];return 0 ; }
@@ -852,11 +853,12 @@ static int kvm_hv_msr_set_crash_data(str u32 index, u64 data) {struct kvm_hv *hv = &vcpu->kvm->arch.hyperv; +size_t size =ARRAY_SIZE (hv->hv_crash_param); -if (WARN_ON_ONCE (index >=ARRAY_SIZE (hv->hv_crash_param))) +if (WARN_ON_ONCE (index >= size))return -EINVAL ; - hv->hv_crash_param[index] = data; + hv->hv_crash_param[array_index_nospec (index, size)] = data;return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 204/309 KVM: x86: Protect ioapic_write_indirect() from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 670564559ca35b439c8d8861fc399451ddf95137 upstream.
This fixes a Spectre-v1/L1TF vulnerability in ioapic_write_indirect(). This function contains index computations based on the (attacker-controlled) IOREGSEL register.
This patch depends on patch
"KVM: x86: Protect ioapic_read_indirect() from Spectre-v1/L1TF attacks".
--- arch/x86/kvm/ioapic.c | 1 + 1 file changed, 1 insertion(+)
arch/x86/kvm/ioapic.c +1 -0
@@ -291,6 +291,7 @@ static void ioapic_write_indirect(structif (index >=IOAPIC_NUM_PINS )return ; + index =array_index_nospec (index,IOAPIC_NUM_PINS ); e = &ioapic->redirtbl[index]; mask_before = e->fields.mask;/* Preserve read-only fields */
Greg Kroah-Hartman
maintainerPATCH 205/309 KVM: x86: Protect MSR-based index computations in pmu.h from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 13c5183a4e643cc2b03a22d0e582c8e17bb7457d upstream.
This fixes a Spectre-v1/L1TF vulnerability in the get_gp_pmc() and get_fixed_pmc() functions.
They both contain index computations based on the (attacker-controlled) MSR number.
--- arch/x86/kvm/pmu.h | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-)
arch/x86/kvm/pmu.h +14 -4
@@ -2,6 +2,8 @@#ifndef __KVM_X86_PMU_H#define __KVM_X86_PMU_H +#include <linux/nospec.h> +#define vcpu_to_pmu (vcpu) (&(vcpu)->arch.pmu)#define pmu_to_vcpu (pmu) (container_of((pmu), struct kvm_vcpu, arch.pmu))#define pmc_to_pmu (pmc) (&(pmc)->vcpu->arch.pmu)
@@ -86,8 +88,12 @@ static inline bool pmc_is_enabled(structstatic inline struct kvm_pmc *get_gp_pmc (struct kvm_pmu *pmu,u32 msr,u32 base) { -if (msr >= base && msr < base + pmu->nr_arch_gp_counters) -return &pmu->gp_counters[msr - base]; +if (msr >= base && msr < base + pmu->nr_arch_gp_counters) { +u32 index =array_index_nospec (msr - base, + pmu->nr_arch_gp_counters); + +return &pmu->gp_counters[index]; + }return NULL ; }
@@ -97,8 +103,12 @@ static inline struct kvm_pmc *get_fixed_ {int base =MSR_CORE_PERF_FIXED_CTR0 ; -if (msr >= base && msr < base + pmu->nr_arch_fixed_counters) -return &pmu->fixed_counters[msr - base]; +if (msr >= base && msr < base + pmu->nr_arch_fixed_counters) { +u32 index =array_index_nospec (msr - base, + pmu->nr_arch_fixed_counters); + +return &pmu->fixed_counters[index]; + }return NULL ; }
Greg Kroah-Hartman
maintainerPATCH 206/309 KVM: x86: Protect ioapic_read_indirect() from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 8c86405f606ca8508b8d9280680166ca26723695 upstream.
This fixes a Spectre-v1/L1TF vulnerability in ioapic_read_indirect(). This function contains index computations based on the (attacker-controlled) IOREGSEL register.
--- arch/x86/kvm/ioapic.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
arch/x86/kvm/ioapic.c +8 -6
@@ -36,6 +36,7 @@#include <linux/io.h> #include <linux/slab.h> #include <linux/export.h> +#include <linux/nospec.h> #include <asm/processor.h> #include <asm/page.h> #include <asm/current.h>
@@ -68,13 +69,14 @@ static unsigned long ioapic_read_indirecdefault : {u32 redir_index = (ioapic->ioregsel -0x10 ) >>1 ; -u64 redir_content; +u64 redir_content = ~0ULL ; -if (redir_index <IOAPIC_NUM_PINS ) - redir_content = - ioapic->redirtbl[redir_index].bits; -else - redir_content = ~0ULL ; +if (redir_index <IOAPIC_NUM_PINS ) { +u32 index =array_index_nospec ( + redir_index,IOAPIC_NUM_PINS ); + + redir_content = ioapic->redirtbl[index].bits; + } result = (ioapic->ioregsel &0x1 ) ? (redir_content >> 32) & 0xffffffff :
Greg Kroah-Hartman
maintainerPATCH 207/309 KVM: x86: Protect MSR-based index computations from Spectre-v1/L1TF attacks in x86.c
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 6ec4c5eee1750d5d17951c4e1960d953376a0dda upstream.
This fixes a Spectre-v1/L1TF vulnerability in set_msr_mce() and get_msr_mce().
Both functions contain index computations based on the (attacker-controlled) MSR number.
--- arch/x86/kvm/x86.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
arch/x86/kvm/x86.c +8 -2
@@ -2494,7 +2494,10 @@ static int set_msr_mce(struct kvm_vcpu *default :if (msr >=MSR_IA32_MC0_CTL && msr <MSR_IA32_MCx_CTL (bank_num)) { -u32 offset = msr -MSR_IA32_MC0_CTL ; +u32 offset =array_index_nospec ( + msr -MSR_IA32_MC0_CTL , +MSR_IA32_MCx_CTL (bank_num) -MSR_IA32_MC0_CTL ); +/* only 0 or all 1s can be written to IA32_MCi_CTL * some Linux kernels though clear bit 10 in bank 4 to * workaround a BIOS/GART TBL issue on AMD K8s, ignore
@@ -2921,7 +2924,10 @@ static int get_msr_mce(struct kvm_vcpu *default :if (msr >=MSR_IA32_MC0_CTL && msr <MSR_IA32_MCx_CTL (bank_num)) { -u32 offset = msr -MSR_IA32_MC0_CTL ; +u32 offset =array_index_nospec ( + msr -MSR_IA32_MC0_CTL , +MSR_IA32_MCx_CTL (bank_num) -MSR_IA32_MC0_CTL ); + data = vcpu->arch.mce_banks[offset];break ; }
Greg Kroah-Hartman
maintainerPATCH 208/309 KVM: x86: Protect x86_decode_insn from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 3c9053a2cae7ba2ba73766a34cea41baa70f57f7 upstream.
This fixes a Spectre-v1/L1TF vulnerability in x86_decode_insn(). kvm_emulate_instruction() (an ancestor of x86_decode_insn()) is an exported symbol, so KVM should treat it conservatively from a security perspective.
--- arch/x86/kvm/emulate.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
arch/x86/kvm/emulate.c +8 -3
@@ -5317,10 +5317,15 @@ done_prefixes: }break ;case Escape: -if (ctxt->modrm >0xbf ) - opcode = opcode.u.esc->high[ctxt->modrm -0xc0 ]; -else +if (ctxt->modrm >0xbf ) { +size_t size =ARRAY_SIZE (opcode.u.esc->high); +u32 index =array_index_nospec ( + ctxt->modrm -0xc0 , size); + + opcode = opcode.u.esc->high[index]; + }else { opcode = opcode.u.esc->op[(ctxt->modrm >>3 ) &7 ]; + }break ;case InstrDual:if ((ctxt->modrm >>6 ) ==3 )
Greg Kroah-Hartman
maintainerPATCH 209/309 KVM: x86: Protect MSR-based index computations in fixed_msr_to_seg_unit() from Spectre-v1/L1TF attacks
In reply to Greg Kroah-HartmanFrom: Marios Pomonis <[email protected]>
commit 25a5edea71b7c154b6a0b8cec14c711cafa31d26 upstream.
This fixes a Spectre-v1/L1TF vulnerability in fixed_msr_to_seg_unit(). This function contains index computations based on the (attacker-controlled) MSR number.
--- arch/x86/kvm/mtrr.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
arch/x86/kvm/mtrr.c +6 -2
@@ -192,11 +192,15 @@ static bool fixed_msr_to_seg_unit(u32 msbreak ; case MSR_MTRRfix16K_80000 ... MSR_MTRRfix16K_A0000: *seg =1 ; - *unit = msr - MSR_MTRRfix16K_80000; + *unit =array_index_nospec ( + msr - MSR_MTRRfix16K_80000, + MSR_MTRRfix16K_A0000 - MSR_MTRRfix16K_80000 +1 );break ; case MSR_MTRRfix4K_C0000 ... MSR_MTRRfix4K_F8000: *seg =2 ; - *unit = msr - MSR_MTRRfix4K_C0000; + *unit =array_index_nospec ( + msr - MSR_MTRRfix4K_C0000, + MSR_MTRRfix4K_F8000 - MSR_MTRRfix4K_C0000 +1 );break ;default :return false;
Greg Kroah-Hartman
maintainerPATCH 210/309 KVM: x86: Fix potential put_fpu() w/o load_fpu() on MPX platform
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit f958bd2314d117f8c29f4821401bc1925bc2e5ef upstream.
Unlike most state managed by XSAVE, MPX is initialized to zero on INIT. Because INITs are usually recognized in the context of a VCPU_RUN call, kvm_vcpu_reset() puts the guest's FPU so that the FPU state is resident in memory, zeros the MPX state, and reloads FPU state to hardware. But, in the unlikely event that an INIT is recognized during kvm_arch_vcpu_ioctl_get_mpstate() via kvm_apic_accept_events(), kvm_vcpu_reset() will call kvm_put_guest_fpu() without a preceding kvm_load_guest_fpu() and corrupt the guest's FPU state (and possibly userspace's FPU state as well).
Given that MPX is being removed from the kernel[*], fix the bug with the simple-but-ugly approach of loading the guest's FPU during KVM_GET_MP_STATE.
[*] See commit f240652b6032b ("x86/mpx: Remove MPX APIs").
--- arch/x86/kvm/x86.c | 4 ++++ 1 file changed, 4 insertions(+)
arch/x86/kvm/x86.c +4 -0
@@ -8698,6 +8698,8 @@ int kvm_arch_vcpu_ioctl_get_mpstate(stru struct kvm_mp_state *mp_state) {vcpu_load (vcpu); +if (kvm_mpx_supported ()) +kvm_load_guest_fpu (vcpu);kvm_apic_accept_events (vcpu); if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED &&
@@ -8706,6 +8708,8 @@ int kvm_arch_vcpu_ioctl_get_mpstate(struelse mp_state->mp_state = vcpu->arch.mp_state; +if (kvm_mpx_supported ()) +kvm_put_guest_fpu (vcpu);vcpu_put (vcpu);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 211/309 KVM: PPC: Book3S HV: Uninit vCPU if vcore creation fails
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit 1a978d9d3e72ddfa40ac60d26301b154247ee0bc upstream.
Call kvm_vcpu_uninit() if vcore creation fails to avoid leaking any resources allocated by kvm_vcpu_init(), i.e. the vcpu->run page.
--- arch/powerpc/kvm/book3s_hv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/powerpc/kvm/book3s_hv.c +3 -1
@@ -2354,7 +2354,7 @@ static struct kvm_vcpu *kvmppc_core_vcpumutex_unlock (&kvm->lock);if (!vcore) - goto free_vcpu; + goto uninit_vcpu;spin_lock (&vcore->lock); ++vcore->num_threads;
@@ -2371,6 +2371,8 @@ static struct kvm_vcpu *kvmppc_core_vcpureturn vcpu; +uninit_vcpu: +kvm_vcpu_uninit (vcpu); free_vcpu:kmem_cache_free (kvm_vcpu_cache, vcpu); out:
Greg Kroah-Hartman
maintainerPATCH 212/309 KVM: PPC: Book3S PR: Free shared page if mmu initialization fails
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit cb10bf9194f4d2c5d830eddca861f7ca0fecdbb4 upstream.
Explicitly free the shared page if kvmppc_mmu_init() fails during kvmppc_core_vcpu_create(), as the page is freed only in kvmppc_core_vcpu_free(), which is not reached via kvm_vcpu_uninit().
--- arch/powerpc/kvm/book3s_pr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/powerpc/kvm/book3s_pr.c +3 -1
@@ -1769,10 +1769,12 @@ static struct kvm_vcpu *kvmppc_core_vcpu err =kvmppc_mmu_init (vcpu);if (err <0 ) - goto uninit_vcpu; + goto free_shared_page;return vcpu; +free_shared_page: +free_page ((unsigned long )vcpu->arch.shared); uninit_vcpu:kvm_vcpu_uninit (vcpu); free_shadow_vcpu:
Greg Kroah-Hartman
maintainerPATCH 213/309 kvm/svm: PKU not currently supported
In reply to Greg Kroah-HartmanFrom: John Allen <[email protected]>
commit a47970ed74a535b1accb4bc73643fd5a93993c3e upstream.
Current SVM implementation does not have support for handling PKU. Guests running on a host with future AMD cpus that support the feature will read garbage from the PKRU register and will hit segmentation faults on boot as memory is getting marked as protected that should not be. Ensure that cpuid from SVM does not advertise the feature.
--- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/cpuid.c | 4 +++- arch/x86/kvm/svm.c | 6 ++++++ arch/x86/kvm/vmx/capabilities.h | 5 +++++ arch/x86/kvm/vmx/vmx.c | 1 + 5 files changed, 16 insertions(+), 1 deletion(-)
arch/x86/include/asm/kvm_host.h +1 -0
@@ -1128,6 +1128,7 @@ struct kvm_x86_ops {bool (*xsaves_supported)(void );bool (*umip_emulated)(void );bool (*pt_supported)(void ); +bool (*pku_supported)(void );int (*check_nested_events)(struct kvm_vcpu *vcpu,bool external_intr);void (*request_immediate_exit)(struct kvm_vcpu *vcpu);
arch/x86/kvm/cpuid.c +3 -1
@@ -352,6 +352,7 @@ static inline void do_cpuid_7_mask(strucunsigned f_umip = kvm_x86_ops->umip_emulated () ?F (UMIP ) :0 ;unsigned f_intel_pt = kvm_x86_ops->pt_supported () ?F (INTEL_PT ) :0 ;unsigned f_la57; +unsigned f_pku = kvm_x86_ops->pku_supported () ?F (PKU ) :0 ;/* cpuid 7.0.ebx */ const u32 kvm_cpuid_7_0_ebx_x86_features =
@@ -363,7 +364,7 @@ static inline void do_cpuid_7_mask(struc/* cpuid 7.0.ecx*/ const u32 kvm_cpuid_7_0_ecx_x86_features = -F (AVX512VBMI ) |F (LA57 ) |F (PKU ) |0 /*OSPKE*/ |F (RDPID ) | +F (AVX512VBMI ) |F (LA57 ) |0 /*PKU*/ |0 /*OSPKE*/ |F (RDPID ) |F (AVX512_VPOPCNTDQ ) |F (UMIP ) |F (AVX512_VBMI2 ) |F (GFNI ) |F (VAES ) |F (VPCLMULQDQ ) |F (AVX512_VNNI ) |F (AVX512_BITALG ) |F (CLDEMOTE ) |F (MOVDIRI ) |F (MOVDIR64B ) |0 /*WAITPKG*/ ;
@@ -392,6 +393,7 @@ static inline void do_cpuid_7_mask(struc/* Set LA57 based on hardware capability. */ entry->ecx |= f_la57; entry->ecx |= f_umip; + entry->ecx |= f_pku;/* PKU is not yet implemented for shadow paging. */ if (!tdp_enabled || !boot_cpu_has (X86_FEATURE_OSPKE )) entry->ecx &= ~F (PKU );
arch/x86/kvm/svm.c +6 -0
@@ -5986,6 +5986,11 @@ static bool svm_has_wbinvd_exit(void)return true; } +static bool svm_pku_supported (void ) +{ +return false; +} +#define PRE_EX (exit) { .exit_code = (exit), \ .stage = X86_ICPT_PRE_EXCEPT, }#define POST_EX (exit) { .exit_code = (exit), \
@@ -7278,6 +7283,7 @@ static struct kvm_x86_ops svm_x86_ops __ .xsaves_supported = svm_xsaves_supported, .umip_emulated = svm_umip_emulated, .pt_supported = svm_pt_supported, + .pku_supported = svm_pku_supported, .set_supported_cpuid = svm_set_supported_cpuid,
arch/x86/kvm/vmx/capabilities.h +5 -0
@@ -145,6 +145,11 @@ static inline bool vmx_umip_emulated(voiSECONDARY_EXEC_DESC ; } +static inline bool vmx_pku_supported (void ) +{ +return boot_cpu_has (X86_FEATURE_PKU ); +} +static inline bool cpu_has_vmx_rdtscp (void ) { return vmcs_config.cpu_based_2nd_exec_ctrl &
arch/x86/kvm/vmx/vmx.c +1 -0
@@ -7865,6 +7865,7 @@ static struct kvm_x86_ops vmx_x86_ops __ .xsaves_supported = vmx_xsaves_supported, .umip_emulated = vmx_umip_emulated, .pt_supported = vmx_pt_supported, + .pku_supported = vmx_pku_supported, .request_immediate_exit = vmx_request_immediate_exit,
Greg Kroah-Hartman
maintainerPATCH 214/309 x86/kvm: Be careful not to clear KVM_VCPU_FLUSH_TLB bit
In reply to Greg Kroah-HartmanFrom: Boris Ostrovsky <[email protected]>
commit 8c6de56a42e0c657955e12b882a81ef07d1d073e upstream.
kvm_steal_time_set_preempted() may accidentally clear KVM_VCPU_FLUSH_TLB bit if it is called more than once while VCPU is preempted.
This is part of CVE-2019-3016.
(This bug was also independently discovered by Jim Mattson <[email protected]>)
--- arch/x86/kvm/x86.c | 3 +++ 1 file changed, 3 insertions(+)
arch/x86/kvm/x86.c +3 -0
@@ -3499,6 +3499,9 @@ static void kvm_steal_time_set_preemptedif (!(vcpu->arch.st.msr_val &KVM_MSR_ENABLED ))return ; +if (vcpu->arch.st.steal.preempted) +return ; + vcpu->arch.st.steal.preempted =KVM_VCPU_PREEMPTED ; kvm_write_guest_offset_cached(vcpu->kvm, &vcpu->arch.st.stime,
Greg Kroah-Hartman
maintainerPATCH 215/309 x86/kvm: Introduce kvm_(un)map_gfn()
In reply to Greg Kroah-HartmanFrom: Boris Ostrovsky <[email protected]>
commit 1eff70a9abd46f175defafd29bc17ad456f398a7 upstream.
kvm_vcpu_(un)map operates on gfns from any current address space. In certain cases we want to make sure we are not mapping SMRAM and for that we can use kvm_(un)map_gfn() that we are introducing in this patch.
This is part of CVE-2019-3016.
--- include/linux/kvm_host.h | 2 ++ virt/kvm/kvm_main.c | 29 ++++++++++++++++++++++++----- 2 files changed, 26 insertions(+), 5 deletions(-)
include/linux/kvm_host.h +2 -0
@@ -758,8 +758,10 @@ struct kvm_memory_slot *kvm_vcpu_gfn_to_kvm_pfn_t kvm_vcpu_gfn_to_pfn_atomic (struct kvm_vcpu *vcpu,gfn_t gfn);kvm_pfn_t kvm_vcpu_gfn_to_pfn (struct kvm_vcpu *vcpu,gfn_t gfn);int kvm_vcpu_map (struct kvm_vcpu *vcpu,gpa_t gpa,struct kvm_host_map *map); +int kvm_map_gfn (struct kvm_vcpu *vcpu,gfn_t gfn,struct kvm_host_map *map);struct page *kvm_vcpu_gfn_to_page (struct kvm_vcpu *vcpu,gfn_t gfn);void kvm_vcpu_unmap (struct kvm_vcpu *vcpu,struct kvm_host_map *map,bool dirty); +int kvm_unmap_gfn (struct kvm_vcpu *vcpu,struct kvm_host_map *map,bool dirty);unsigned long kvm_vcpu_gfn_to_hva (struct kvm_vcpu *vcpu,gfn_t gfn);unsigned long kvm_vcpu_gfn_to_hva_prot (struct kvm_vcpu *vcpu,gfn_t gfn,bool *writable); int kvm_vcpu_read_guest_page(struct kvm_vcpu *vcpu, gfn_t gfn, void *data, int offset,
virt/kvm/kvm_main.c +24 -5
@@ -1809,12 +1809,13 @@ struct page *gfn_to_page(struct kvm *kvm }EXPORT_SYMBOL_GPL (gfn_to_page); -static int __kvm_map_gfn (struct kvm_memory_slot *slot,gfn_t gfn, +static int __kvm_map_gfn (struct kvm_memslots *slots,gfn_t gfn,struct kvm_host_map *map) {kvm_pfn_t pfn;void *hva =NULL ;struct page *page =KVM_UNMAPPED_PAGE ; +struct kvm_memory_slot *slot =__gfn_to_memslot (slots, gfn);if (!map)return -EINVAL ;
@@ -1843,14 +1844,20 @@ static int __kvm_map_gfn(struct kvm_memoreturn 0 ; } +int kvm_map_gfn (struct kvm_vcpu *vcpu,gfn_t gfn,struct kvm_host_map *map) +{ +return __kvm_map_gfn (kvm_memslots (vcpu->kvm), gfn, map); +} +EXPORT_SYMBOL_GPL (kvm_map_gfn); +int kvm_vcpu_map (struct kvm_vcpu *vcpu,gfn_t gfn,struct kvm_host_map *map) { -return __kvm_map_gfn (kvm_vcpu_gfn_to_memslot (vcpu, gfn), gfn, map); +return __kvm_map_gfn (kvm_vcpu_memslots (vcpu), gfn, map); }EXPORT_SYMBOL_GPL (kvm_vcpu_map); -void kvm_vcpu_unmap (struct kvm_vcpu *vcpu,struct kvm_host_map *map, -bool dirty) +static void __kvm_unmap_gfn (struct kvm_memory_slot *memslot, +struct kvm_host_map *map,bool dirty) {if (!map)return ;
@@ -1866,7 +1873,7 @@ void kvm_vcpu_unmap(struct kvm_vcpu *vcp#endif if (dirty) { -kvm_vcpu_mark_page_dirty (vcpu, map->gfn); +mark_page_dirty_in_slot (memslot, map->gfn);kvm_release_pfn_dirty (map->pfn); }else {kvm_release_pfn_clean (map->pfn);
@@ -1875,6 +1882,18 @@ void kvm_vcpu_unmap(struct kvm_vcpu *vcp map->hva =NULL ; map->page =NULL ; } + +int kvm_unmap_gfn (struct kvm_vcpu *vcpu,struct kvm_host_map *map,bool dirty) +{ +__kvm_unmap_gfn (gfn_to_memslot (vcpu->kvm, map->gfn), map, dirty); +return 0 ; +} +EXPORT_SYMBOL_GPL (kvm_unmap_gfn); + +void kvm_vcpu_unmap (struct kvm_vcpu *vcpu,struct kvm_host_map *map,bool dirty) +{ +__kvm_unmap_gfn (kvm_vcpu_gfn_to_memslot (vcpu, map->gfn), map, dirty); +}EXPORT_SYMBOL_GPL (kvm_vcpu_unmap);struct page *kvm_vcpu_gfn_to_page (struct kvm_vcpu *vcpu,gfn_t gfn)
Greg Kroah-Hartman
maintainerPATCH 216/309 x86/KVM: Make sure KVM_VCPU_FLUSH_TLB flag is not missed
In reply to Greg Kroah-HartmanFrom: Boris Ostrovsky <[email protected]>
commit b043138246a41064527cf019a3d51d9f015e9796 upstream.
There is a potential race in record_steal_time() between setting host-local vcpu->arch.st.steal.preempted to zero (i.e. clearing KVM_VCPU_PREEMPTED) and propagating this value to the guest with kvm_write_guest_cached(). Between those two events the guest may still see KVM_VCPU_PREEMPTED in its copy of kvm_steal_time, set KVM_VCPU_FLUSH_TLB and assume that hypervisor will do the right thing. Which it won't.
Instad of copying, we should map kvm_steal_time and that will guarantee atomicity of accesses to @preempted.
This is part of CVE-2019-3016.
--- arch/x86/kvm/x86.c | 51 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 21 deletions(-)
arch/x86/kvm/x86.c +30 -21
@@ -2593,45 +2593,47 @@ static void kvm_vcpu_flush_tlb(struct kvstatic void record_steal_time (struct kvm_vcpu *vcpu) { +struct kvm_host_map map; +struct kvm_steal_time *st; +if (!(vcpu->arch.st.msr_val &KVM_MSR_ENABLED ))return ; -if (unlikely (kvm_read_guest_cached (vcpu->kvm, &vcpu->arch.st.stime, - &vcpu->arch.st.steal,sizeof (struct kvm_steal_time )))) +/* -EAGAIN is returned in atomic context so we can just return. */ +if (kvm_map_gfn (vcpu, vcpu->arch.st.msr_val >>PAGE_SHIFT , + &map, &vcpu->arch.st.cache, false))return ; + st = map.hva + +offset_in_page (vcpu->arch.st.msr_val &KVM_STEAL_VALID_BITS ); +/* * Doing a TLB flush here, on the guest's behalf, can avoid * expensive IPIs. */ trace_kvm_pv_tlb_flush (vcpu->vcpu_id, - vcpu->arch.st.steal.preempted &KVM_VCPU_FLUSH_TLB ); -if (xchg (&vcpu->arch.st.steal.preempted,0 ) &KVM_VCPU_FLUSH_TLB ) + st->preempted &KVM_VCPU_FLUSH_TLB ); +if (xchg (&st->preempted,0 ) &KVM_VCPU_FLUSH_TLB )kvm_vcpu_flush_tlb (vcpu, false); -if (vcpu->arch.st.steal.version &1 ) - vcpu->arch.st.steal.version +=1 ;/* first time write, random junk */ + vcpu->arch.st.steal.preempted =0 ; - vcpu->arch.st.steal.version +=1 ; +if (st->version &1 ) + st->version +=1 ;/* first time write, random junk */ -kvm_write_guest_cached (vcpu->kvm, &vcpu->arch.st.stime, - &vcpu->arch.st.steal,sizeof (struct kvm_steal_time )); + st->version +=1 ;smp_wmb (); - vcpu->arch.st.steal.steal += current->sched_info.run_delay - + st->steal += current->sched_info.run_delay - vcpu->arch.st.last_steal; vcpu->arch.st.last_steal = current->sched_info.run_delay; -kvm_write_guest_cached (vcpu->kvm, &vcpu->arch.st.stime, - &vcpu->arch.st.steal,sizeof (struct kvm_steal_time )); -smp_wmb (); - vcpu->arch.st.steal.version +=1 ; + st->version +=1 ; -kvm_write_guest_cached (vcpu->kvm, &vcpu->arch.st.stime, - &vcpu->arch.st.steal,sizeof (struct kvm_steal_time )); +kvm_unmap_gfn (vcpu, &map, &vcpu->arch.st.cache, true, false); }int kvm_set_msr_common (struct kvm_vcpu *vcpu,struct msr_data *msr_info)
@@ -3496,18 +3498,25 @@ void kvm_arch_vcpu_load(struct kvm_vcpustatic void kvm_steal_time_set_preempted (struct kvm_vcpu *vcpu) { +struct kvm_host_map map; +struct kvm_steal_time *st; +if (!(vcpu->arch.st.msr_val &KVM_MSR_ENABLED ))return ;if (vcpu->arch.st.steal.preempted)return ; - vcpu->arch.st.steal.preempted =KVM_VCPU_PREEMPTED ; +if (kvm_map_gfn (vcpu, vcpu->arch.st.msr_val >>PAGE_SHIFT , &map, + &vcpu->arch.st.cache, true)) +return ; + + st = map.hva + +offset_in_page (vcpu->arch.st.msr_val &KVM_STEAL_VALID_BITS ); + + st->preempted = vcpu->arch.st.steal.preempted =KVM_VCPU_PREEMPTED ; -kvm_write_guest_offset_cached (vcpu->kvm, &vcpu->arch.st.stime, - &vcpu->arch.st.steal.preempted, - offsetof(struct kvm_steal_time , preempted), -sizeof (vcpu->arch.st.steal.preempted)); +kvm_unmap_gfn (vcpu, &map, &vcpu->arch.st.cache, true, true); }void kvm_arch_vcpu_put (struct kvm_vcpu *vcpu)
Greg Kroah-Hartman
maintainerPATCH 217/309 x86/kvm: Cache gfn to pfn translation
In reply to Greg Kroah-HartmanFrom: Boris Ostrovsky <[email protected]>
commit 917248144db5d7320655dbb41d3af0b8a0f3d589 upstream.
__kvm_map_gfn()'s call to gfn_to_pfn_memslot() is
* relatively expensive
* in certain cases (such as when done from atomic context) cannot be called
Stashing gfn-to-pfn mapping should help with both cases.
This is part of CVE-2019-3016.
--- arch/x86/include/asm/kvm_host.h | 1 arch/x86/kvm/x86.c | 10 ++++ include/linux/kvm_host.h | 7 ++ include/linux/kvm_types.h | 9 +++ virt/kvm/kvm_main.c | 98 ++++++++++++++++++++++++++++++++-------- 5 files changed, 103 insertions(+), 22 deletions(-)
arch/x86/include/asm/kvm_host.h +1 -0
@@ -671,6 +671,7 @@ struct kvm_vcpu_arch {u64 last_steal;struct gfn_to_hva_cache stime;struct kvm_steal_time steal; +struct gfn_to_pfn_cache cache; } st;u64 tsc_offset;
arch/x86/kvm/x86.c +10 -0
@@ -9081,6 +9081,9 @@ static void fx_init(struct kvm_vcpu *vcpvoid kvm_arch_vcpu_free (struct kvm_vcpu *vcpu) {void *wbinvd_dirty_mask = vcpu->arch.wbinvd_dirty_mask; +struct gfn_to_pfn_cache *cache = &vcpu->arch.st.cache; + +kvm_release_pfn (cache->pfn, cache->dirty, cache);kvmclock_reset (vcpu);
@@ -9745,11 +9748,18 @@ out_free:void kvm_arch_memslots_updated (struct kvm *kvm,u64 gen) { +struct kvm_vcpu *vcpu; +int i; +/* * memslots->generation has been incremented. * mmio generation may have reached its maximum value. */ kvm_mmu_invalidate_mmio_sptes (kvm, gen); + +/* Force re-initialization of steal_time cache */ +kvm_for_each_vcpu (i, vcpu, kvm) +kvm_vcpu_kick (vcpu); } int kvm_arch_prepare_memory_region(struct kvm *kvm,
include/linux/kvm_host.h +5 -2
@@ -728,6 +728,7 @@ void kvm_set_pfn_dirty(kvm_pfn_t pfn);void kvm_set_pfn_accessed (kvm_pfn_t pfn);void kvm_get_pfn (kvm_pfn_t pfn); +void kvm_release_pfn (kvm_pfn_t pfn,bool dirty,struct gfn_to_pfn_cache *cache);int kvm_read_guest_page (struct kvm *kvm,gfn_t gfn,void *data,int offset,int len); int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data,
@@ -758,10 +759,12 @@ struct kvm_memory_slot *kvm_vcpu_gfn_to_kvm_pfn_t kvm_vcpu_gfn_to_pfn_atomic (struct kvm_vcpu *vcpu,gfn_t gfn);kvm_pfn_t kvm_vcpu_gfn_to_pfn (struct kvm_vcpu *vcpu,gfn_t gfn);int kvm_vcpu_map (struct kvm_vcpu *vcpu,gpa_t gpa,struct kvm_host_map *map); -int kvm_map_gfn (struct kvm_vcpu *vcpu,gfn_t gfn,struct kvm_host_map *map); +int kvm_map_gfn (struct kvm_vcpu *vcpu,gfn_t gfn,struct kvm_host_map *map, +struct gfn_to_pfn_cache *cache,bool atomic);struct page *kvm_vcpu_gfn_to_page (struct kvm_vcpu *vcpu,gfn_t gfn);void kvm_vcpu_unmap (struct kvm_vcpu *vcpu,struct kvm_host_map *map,bool dirty); -int kvm_unmap_gfn (struct kvm_vcpu *vcpu,struct kvm_host_map *map,bool dirty); +int kvm_unmap_gfn (struct kvm_vcpu *vcpu,struct kvm_host_map *map, +struct gfn_to_pfn_cache *cache,bool dirty,bool atomic);unsigned long kvm_vcpu_gfn_to_hva (struct kvm_vcpu *vcpu,gfn_t gfn);unsigned long kvm_vcpu_gfn_to_hva_prot (struct kvm_vcpu *vcpu,gfn_t gfn,bool *writable); int kvm_vcpu_read_guest_page(struct kvm_vcpu *vcpu, gfn_t gfn, void *data, int offset,
include/linux/kvm_types.h +8 -1
@@ -18,7 +18,7 @@ struct kvm_memslots;enum kvm_mr_change ; -#include <asm/types.h> +#include <linux/types.h> /* * Address types:
@@ -49,4 +49,11 @@ struct gfn_to_hva_cache { struct kvm_memory_slot *memslot; }; +struct gfn_to_pfn_cache { +u64 generation; +gfn_t gfn; +kvm_pfn_t pfn; +bool dirty; +}; +#endif /* __KVM_TYPES_H__ */
virt/kvm/kvm_main.c +79 -19
160 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 218/309 x86/KVM: Clean up hosts steal time structure
In reply to Greg Kroah-HartmanFrom: Boris Ostrovsky <[email protected]>
commit a6bd811f1209fe1c64c9f6fd578101d6436c6b6e upstream.
Now that we are mapping kvm_steal_time from the guest directly we don't need keep a copy of it in kvm_vcpu_arch.st. The same is true for the stime field.
This is part of CVE-2019-3016.
--- arch/x86/include/asm/kvm_host.h | 3 +-- arch/x86/kvm/x86.c | 11 +++-------- 2 files changed, 4 insertions(+), 10 deletions(-)
arch/x86/include/asm/kvm_host.h +1 -2
@@ -667,10 +667,9 @@ struct kvm_vcpu_arch {bool pvclock_set_guest_stopped_request;struct { +u8 preempted;u64 msr_val;u64 last_steal; -struct gfn_to_hva_cache stime; -struct kvm_steal_time steal;struct gfn_to_pfn_cache cache; } st;
arch/x86/kvm/x86.c +3 -8
@@ -2616,7 +2616,7 @@ static void record_steal_time(struct kvmif (xchg (&st->preempted,0 ) &KVM_VCPU_FLUSH_TLB )kvm_vcpu_flush_tlb (vcpu, false); - vcpu->arch.st.steal.preempted =0 ; + vcpu->arch.st.preempted =0 ;if (st->version &1 ) st->version +=1 ;/* first time write, random junk */
@@ -2786,11 +2786,6 @@ int kvm_set_msr_common(struct kvm_vcpu *if (data &KVM_STEAL_RESERVED_MASK )return 1 ; -if (kvm_gfn_to_hva_cache_init (vcpu->kvm, &vcpu->arch.st.stime, - data &KVM_STEAL_VALID_BITS , -sizeof (struct kvm_steal_time ))) -return 1 ; - vcpu->arch.st.msr_val = data;if (!(data &KVM_MSR_ENABLED ))
@@ -3504,7 +3499,7 @@ static void kvm_steal_time_set_preemptedif (!(vcpu->arch.st.msr_val &KVM_MSR_ENABLED ))return ; -if (vcpu->arch.st.steal.preempted) +if (vcpu->arch.st.preempted)return ; if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT, &map,
@@ -3514,7 +3509,7 @@ static void kvm_steal_time_set_preempted st = map.hva +offset_in_page (vcpu->arch.st.msr_val &KVM_STEAL_VALID_BITS ); - st->preempted = vcpu->arch.st.steal.preempted =KVM_VCPU_PREEMPTED ; + st->preempted = vcpu->arch.st.preempted =KVM_VCPU_PREEMPTED ;kvm_unmap_gfn (vcpu, &map, &vcpu->arch.st.cache, true, true); }
Greg Kroah-Hartman
maintainerPATCH 219/309 KVM: VMX: Add non-canonical check on writes to RTIT address MSRs
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit fe6ed369fca98e99df55c932b85782a5687526b5 upstream.
Reject writes to RTIT address MSRs if the data being written is a non-canonical address as the MSRs are subject to canonical checks, e.g. KVM will trigger an unchecked #GP when loading the values to hardware during pt_guest_enter().
--- arch/x86/kvm/vmx/vmx.c | 2 ++ 1 file changed, 2 insertions(+)
arch/x86/kvm/vmx/vmx.c +2 -0
@@ -2140,6 +2140,8 @@ static int vmx_set_msr(struct kvm_vcpu * (index >= 2 * intel_pt_validate_cap(vmx->pt_desc.caps, PT_CAP_num_address_ranges)))return 1 ; +if (is_noncanonical_address (data, vcpu)) +return 1 ;if (index %2 ) vmx->pt_desc.guest.addr_b[index /2 ] = data;else
Greg Kroah-Hartman
maintainerPATCH 220/309 KVM: x86: Dont let userspace set host-reserved cr4 bits
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit b11306b53b2540c6ba068c4deddb6a17d9f8d95b upstream.
Calculate the host-reserved cr4 bits at runtime based on the system's capabilities (using logic similar to __do_cpuid_func()), and use the dynamically generated mask for the reserved bit check in kvm_set_cr4() instead using of the static CR4_RESERVED_BITS define. This prevents userspace from "enabling" features in cr4 that are not supported by the system, e.g. by ignoring KVM_GET_SUPPORTED_CPUID and specifying a bogus CPUID for the vCPU.
Allowing userspace to set unsupported bits in cr4 can lead to a variety of undesirable behavior, e.g. failed VM-Enter, and in general increases KVM's attack surface. A crafty userspace can even abuse CR4.LA57 to induce an unchecked #GP on a WRMSR.
On a platform without LA57 support:
KVM_SET_CPUID2 // CPUID_7_0_ECX.LA57 = 1
KVM_SET_SREGS // CR4.LA57 = 1
KVM_SET_MSRS // KERNEL_GS_BASE = 0x0004000000000000
KVM_RUN
leads to a #GP when writing KERNEL_GS_BASE into hardware:
unchecked MSR access error: WRMSR to 0xc0000102 (tried to write 0x0004000000000000) at rIP: 0xffffffffa00f239a (vmx_prepare_switch_to_guest+0x10a/0x1d0 [kvm_intel])
Call Trace: kvm_arch_vcpu_ioctl_run+0x671/0x1c70 [kvm] kvm_vcpu_ioctl+0x36b/0x5d0 [kvm] do_vfs_ioctl+0xa1/0x620 ksys_ioctl+0x66/0x70 __x64_sys_ioctl+0x16/0x20 do_syscall_64+0x4c/0x170 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x7fc08133bf47
Note, the above sequence fails VM-Enter due to invalid guest state. Userspace can allow VM-Enter to succeed (after the WRMSR #GP) by adding a KVM_SET_SREGS w/ CR4.LA57=0 after KVM_SET_MSRS, in which case KVM will technically leak the host's KERNEL_GS_BASE into the guest. But, as KERNEL_GS_BASE is a userspace-defined value/address, the leak is largely benign as a malicious userspace would simply be exposing its own data to the guest, and attacking a benevolent userspace would require multiple bugs in the userspace VMM.
--- arch/x86/kvm/x86.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-)
arch/x86/kvm/x86.c +34 -1
@@ -92,6 +92,8 @@ u64 __read_mostly efer_reserved_bits = ~static u64 __read_mostly efer_reserved_bits = ~((u64 )EFER_SCE );#endif +static u64 __read_mostly cr4_reserved_bits =CR4_RESERVED_BITS ; +#define VM_STAT (x, ...) offsetof(struct kvm, stat.x), KVM_STAT_VM, ## __VA_ARGS__#define VCPU_STAT (x, ...) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU, ## __VA_ARGS__
@@ -886,9 +888,38 @@ int kvm_set_xcr(struct kvm_vcpu *vcpu, u }EXPORT_SYMBOL_GPL (kvm_set_xcr); +static u64 kvm_host_cr4_reserved_bits (struct cpuinfo_x86 *c) +{ +u64 reserved_bits =CR4_RESERVED_BITS ; + +if (!cpu_has (c,X86_FEATURE_XSAVE )) + reserved_bits |=X86_CR4_OSXSAVE ; + +if (!cpu_has (c,X86_FEATURE_SMEP )) + reserved_bits |=X86_CR4_SMEP ; + +if (!cpu_has (c,X86_FEATURE_SMAP )) + reserved_bits |=X86_CR4_SMAP ; + +if (!cpu_has (c,X86_FEATURE_FSGSBASE )) + reserved_bits |=X86_CR4_FSGSBASE ; + +if (!cpu_has (c,X86_FEATURE_PKU )) + reserved_bits |=X86_CR4_PKE ; + +if (!cpu_has (c,X86_FEATURE_LA57 ) && + !(cpuid_ecx (0x7 ) &bit (X86_FEATURE_LA57 ))) + reserved_bits |=X86_CR4_LA57 ; + +if (!cpu_has (c,X86_FEATURE_UMIP ) && !kvm_x86_ops->umip_emulated ()) + reserved_bits |=X86_CR4_UMIP ; + +return reserved_bits; +} +static int kvm_valid_cr4 (struct kvm_vcpu *vcpu,unsigned long cr4) { -if (cr4 &CR4_RESERVED_BITS ) +if (cr4 & cr4_reserved_bits)return -EINVAL ;if (!guest_cpuid_has (vcpu,X86_FEATURE_XSAVE ) && (cr4 &X86_CR4_OSXSAVE ))
@@ -9341,6 +9372,8 @@ int kvm_arch_hardware_setup(void)if (r !=0 )return r; + cr4_reserved_bits =kvm_host_cr4_reserved_bits (&boot_cpu_data); +if (kvm_has_tsc_control) {/* * Make sure the user can only configure tsc_khz values that
Greg Kroah-Hartman
maintainerPATCH 221/309 KVM: x86: Free wbinvd_dirty_mask if vCPU creation fails
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit 16be9ddea268ad841457a59109963fff8c9de38d upstream.
Free the vCPU's wbinvd_dirty_mask if vCPU creation fails after kvm_arch_vcpu_init(), e.g. when installing the vCPU's file descriptor. Do the freeing by calling kvm_arch_vcpu_free() instead of open coding the freeing. This adds a likely superfluous, but ultimately harmless, call to kvmclock_reset(), which only clears vcpu->arch.pv_time_enabled. Using kvm_arch_vcpu_free() allows for additional cleanup in the future.
--- arch/x86/kvm/x86.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kvm/x86.c +1 -1
@@ -9180,7 +9180,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vckvm_mmu_unload (vcpu);vcpu_put (vcpu); - kvm_x86_ops->vcpu_free (vcpu); +kvm_arch_vcpu_free (vcpu); }void kvm_vcpu_reset (struct kvm_vcpu *vcpu,bool init_event)
Greg Kroah-Hartman
maintainerPATCH 222/309 KVM: x86: Handle TIF_NEED_FPU_LOAD in kvm_{load,put}_guest_fpu()
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit c9aef3b85f425d1f6635382ec210ee5a7ef55d7d upstream.
Handle TIF_NEED_FPU_LOAD similar to how fpu__copy() handles the flag when duplicating FPU state to a new task struct. TIF_NEED_FPU_LOAD can be set any time control is transferred out of KVM, be it voluntarily, e.g. if I/O is triggered during a KVM call to get_user_pages, or involuntarily, e.g. if softirq runs after an IRQ occurs. Therefore, KVM must account for TIF_NEED_FPU_LOAD whenever it is (potentially) accessing CPU FPU state.
--- arch/x86/kvm/x86.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
arch/x86/kvm/x86.c +17 -2
@@ -8493,12 +8493,26 @@ static int complete_emulated_mmio(structreturn 0 ; } +static void kvm_save_current_fpu (struct fpu *fpu) +{ +/* +* If the target FPU state is not resident in the CPU registers, just +* memcpy() from current, else save CPU state directly to the target. +*/ +if (test_thread_flag (TIF_NEED_FPU_LOAD )) +memcpy (&fpu->state, ¤t->thread.fpu.state, + fpu_kernel_xstate_size); +else +copy_fpregs_to_fpstate (fpu); +} +/* Swap (qemu) user FPU context for the guest FPU context. */ static void kvm_load_guest_fpu (struct kvm_vcpu *vcpu) {fpregs_lock (); -copy_fpregs_to_fpstate (vcpu->arch.user_fpu); +kvm_save_current_fpu (vcpu->arch.user_fpu); +/* PKRU is separately restored in kvm_x86_ops->run. */ __copy_kernel_to_fpregs (&vcpu->arch.guest_fpu->state, ~XFEATURE_MASK_PKRU );
@@ -8514,7 +8528,8 @@ static void kvm_put_guest_fpu(struct kvm {fpregs_lock (); -copy_fpregs_to_fpstate (vcpu->arch.guest_fpu); +kvm_save_current_fpu (vcpu->arch.guest_fpu); +copy_kernel_to_fpregs (&vcpu->arch.user_fpu->state);fpregs_mark_activate ();
Greg Kroah-Hartman
maintainerPATCH 223/309 KVM: x86: Ensure guests FPU state is loaded when accessing for emulation
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit a7baead7e312f5a05381d68585fb6dc68e19e90f upstream.
Lock the FPU regs and reload the current thread's FPU state, which holds the guest's FPU state, to the CPU registers if necessary prior to accessing guest FPU state as part of emulation. kernel_fpu_begin() can be called from softirq context, therefore KVM must ensure softirqs are disabled (locking the FPU regs disables softirqs) when touching CPU FPU state.
Note, for all intents and purposes this reverts commit 6ab0b9feb82a7 ("x86,kvm: remove KVM emulator get_fpu / put_fpu"), but at the time it was applied, removing get/put_fpu() was correct. The re-introduction of {get,put}_fpu() is necessitated by the deferring of FPU state load.
--- arch/x86/kvm/emulate.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
arch/x86/kvm/emulate.c +39 -0
@@ -22,6 +22,7 @@#include "kvm_cache_regs.h" #include <asm/kvm_emulate.h> #include <linux/stringify.h> +#include <asm/fpu/api.h> #include <asm/debugreg.h> #include <asm/nospec-branch.h>
@@ -1075,8 +1076,23 @@ static void fetch_register_operand(struc } } +static void emulator_get_fpu (void ) +{ +fpregs_lock (); + +fpregs_assert_state_consistent (); +if (test_thread_flag (TIF_NEED_FPU_LOAD )) +switch_fpu_return (); +} + +static void emulator_put_fpu (void ) +{ +fpregs_unlock (); +} +static void read_sse_reg (struct x86_emulate_ctxt *ctxt,sse128_t *data,int reg) { +emulator_get_fpu ();switch (reg) {case 0 : asm("movdqa %%xmm0, %0" :"=m" (*data));break ;case 1 : asm("movdqa %%xmm1, %0" :"=m" (*data));break ;
@@ -1098,11 +1114,13 @@ static void read_sse_reg(struct x86_emul#endif default :BUG (); } +emulator_put_fpu (); }static void write_sse_reg (struct x86_emulate_ctxt *ctxt,sse128_t *data,int reg) { +emulator_get_fpu ();switch (reg) {case 0 : asm("movdqa %0, %%xmm0" : :"m" (*data));break ;case 1 : asm("movdqa %0, %%xmm1" : :"m" (*data));break ;
@@ -1124,10 +1142,12 @@ static void write_sse_reg(struct x86_emu#endif default :BUG (); } +emulator_put_fpu (); }static void read_mmx_reg (struct x86_emulate_ctxt *ctxt,u64 *data,int reg) { +emulator_get_fpu ();switch (reg) {case 0 : asm("movq %%mm0, %0" :"=m" (*data));break ;case 1 : asm("movq %%mm1, %0" :"=m" (*data));break ;
@@ -1139,10 +1159,12 @@ static void read_mmx_reg(struct x86_emulcase 7 : asm("movq %%mm7, %0" :"=m" (*data));break ;default :BUG (); } +emulator_put_fpu (); }static void write_mmx_reg (struct x86_emulate_ctxt *ctxt,u64 *data,int reg) { +emulator_get_fpu ();switch (reg) {case 0 : asm("movq %0, %%mm0" : :"m" (*data));break ;case 1 : asm("movq %0, %%mm1" : :"m" (*data));break ;
@@ -1154,6 +1176,7 @@ static void write_mmx_reg(struct x86_emucase 7 : asm("movq %0, %%mm7" : :"m" (*data));break ;default :BUG (); } +emulator_put_fpu (); }static int em_fninit (struct x86_emulate_ctxt *ctxt)
@@ -1161,7 +1184,9 @@ static int em_fninit(struct x86_emulate_if (ctxt->ops->get_cr (ctxt,0 ) & (X86_CR0_TS |X86_CR0_EM ))return emulate_nm (ctxt); +emulator_get_fpu (); asmvolatile ("fninit" ); +emulator_put_fpu ();return X86EMUL_CONTINUE ; }
@@ -1172,7 +1197,9 @@ static int em_fnstcw(struct x86_emulate_if (ctxt->ops->get_cr (ctxt,0 ) & (X86_CR0_TS |X86_CR0_EM ))return emulate_nm (ctxt); +emulator_get_fpu (); asmvolatile ("fnstcw %0" :"+m" (fcw)); +emulator_put_fpu (); ctxt->dst.val = fcw;
@@ -1186,7 +1213,9 @@ static int em_fnstsw(struct x86_emulate_if (ctxt->ops->get_cr (ctxt,0 ) & (X86_CR0_TS |X86_CR0_EM ))return emulate_nm (ctxt); +emulator_get_fpu (); asmvolatile ("fnstsw %0" :"+m" (fsw)); +emulator_put_fpu (); ctxt->dst.val = fsw;
@@ -4094,8 +4123,12 @@ static int em_fxsave(struct x86_emulate_if (rc !=X86EMUL_CONTINUE )return rc; +emulator_get_fpu (); + rc = asm_safe("fxsave %[fx]", , [fx] "+m"(fx_state)); +emulator_put_fpu (); +if (rc !=X86EMUL_CONTINUE )return rc;
@@ -4138,6 +4171,8 @@ static int em_fxrstor(struct x86_emulateif (rc !=X86EMUL_CONTINUE )return rc; +emulator_get_fpu (); +if (size <__fxstate_size (16 )) { rc =fxregs_fixup (&fx_state, size);if (rc !=X86EMUL_CONTINUE )
@@ -4153,6 +4188,8 @@ static int em_fxrstor(struct x86_emulate rc = asm_safe("fxrstor %[fx]", : [fx] "m"(fx_state)); out: +emulator_put_fpu (); +return rc; }
@@ -5467,7 +5504,9 @@ static int flush_pending_x87_faults(stru {int rc; +emulator_get_fpu (); rc =asm_safe ("fwait" ); +emulator_put_fpu ();if (unlikely (rc !=X86EMUL_CONTINUE ))return emulate_exception (ctxt,MF_VECTOR ,0 , false);
Greg Kroah-Hartman
maintainerPATCH 224/309 KVM: x86: Revert "KVM: X86: Fix fpu state crash in kvm guest"
In reply to Greg Kroah-HartmanFrom: Sean Christopherson <[email protected]>
commit 2620fe268e80d667a94553cd37a94ccaa2cb8c83 upstream.
Reload the current thread's FPU state, which contains the guest's FPU state, to the CPU registers if necessary during vcpu_enter_guest(). TIF_NEED_FPU_LOAD can be set any time control is transferred out of KVM, e.g. if I/O is triggered during a KVM call to get_user_pages() or if a softirq occurs while KVM is scheduled in.
Moving the handling of TIF_NEED_FPU_LOAD from vcpu_enter_guest() to kvm_arch_vcpu_load(), effectively kvm_sched_in(), papered over a bug where kvm_put_guest_fpu() failed to account for TIF_NEED_FPU_LOAD. The easiest way to the kvm_put_guest_fpu() bug was to run with involuntary preemption enable, thus handling TIF_NEED_FPU_LOAD during kvm_sched_in() made the bug go away. But, removing the handling in vcpu_enter_guest() exposed KVM to the rare case of a softirq triggering kernel_fpu_begin() between vcpu_load() and vcpu_enter_guest().
Now that kvm_{load,put}_guest_fpu() correctly handle TIF_NEED_FPU_LOAD, revert the commit to both restore the vcpu_enter_guest() behavior and eliminate the superfluous switch_fpu_return() in kvm_arch_vcpu_load().
Note, leaving the handling in kvm_arch_vcpu_load() isn't wrong per se, but it is unnecessary, and most critically, makes it extremely difficult to find bugs such as the kvm_put_guest_fpu() issue due to shrinking the window where a softirq can corrupt state.
A sample trace triggered by warning if TIF_NEED_FPU_LOAD is set while vcpu state is loaded:
<IRQ> gcmaes_crypt_by_sg.constprop.12+0x26e/0x660 ? 0xffffffffc024547d ? __qdisc_run+0x83/0x510 ? __dev_queue_xmit+0x45e/0x990 ? ip_finish_output2+0x1a8/0x570 ? fib4_rule_action+0x61/0x70 ? fib4_rule_action+0x70/0x70 ? fib_rules_lookup+0x13f/0x1c0 ? helper_rfc4106_decrypt+0x82/0xa0 ? crypto_aead_decrypt+0x40/0x70 ? crypto_aead_decrypt+0x40/0x70 ? crypto_aead_decrypt+0x40/0x70 ? esp_output_tail+0x8f4/0xa5a [esp4] ? skb_ext_add+0xd3/0x170 ? xfrm_input+0x7a6/0x12c0 ? xfrm4_rcv_encap+0xae/0xd0 ? xfrm4_transport_finish+0x200/0x200 ? udp_queue_rcv_one_skb+0x1ba/0x460 ? udp_unicast_rcv_skb.isra.63+0x72/0x90 ? __udp4_lib_rcv+0x51b/0xb00 ? ip_protocol_deliver_rcu+0xd2/0x1c0 ? ip_local_deliver_finish+0x44/0x50 ? ip_local_deliver+0xe0/0xf0 ? ip_protocol_deliver_rcu+0x1c0/0x1c0 ? ip_rcv+0xbc/0xd0 ? ip_rcv_finish_core.isra.19+0x380/0x380 ? __netif_receive_skb_one_core+0x7e/0x90 ? netif_receive_skb_internal+0x3d/0xb0 ? napi_gro_receive+0xed/0x150 ? 0xffffffffc0243c77 ? net_rx_action+0x149/0x3b0 ? __do_softirq+0xe4/0x2f8 ? handle_irq_event_percpu+0x6a/0x80 ? irq_exit+0xe6/0xf0 ? do_IRQ+0x7f/0xd0 ? common_interrupt+0xf/0xf </IRQ> ? irq_entries_start+0x20/0x660 ? vmx_get_interrupt_shadow+0x2f0/0x710 [kvm_intel] ? kvm_set_msr_common+0xfc7/0x2380 [kvm] ? recalibrate_cpu_khz+0x10/0x10 ? ktime_get+0x3a/0xa0 ? kvm_arch_vcpu_ioctl_run+0x107/0x560 [kvm] ? kvm_init+0x6bf/0xd00 [kvm] ? __seccomp_filter+0x7a/0x680 ? do_vfs_ioctl+0xa4/0x630 ? security_file_ioctl+0x32/0x50 ? ksys_ioctl+0x60/0x90 ? __x64_sys_ioctl+0x16/0x20 ? do_syscall_64+0x5f/0x1a0 ? entry_SYSCALL_64_after_hwframe+0x44/0xa9 ---[ end trace 9564a1ccad733a90 ]---
This reverts commit e751732486eb3f159089a64d1901992b1357e7cc.
--- arch/x86/kvm/x86.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
arch/x86/kvm/x86.c +3 -6
@@ -3481,10 +3481,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu kvm_x86_ops->vcpu_load (vcpu, cpu); -fpregs_assert_state_consistent (); -if (test_thread_flag (TIF_NEED_FPU_LOAD )) -switch_fpu_return (); -/* Apply any externally detected TSC adjustments (due to suspend) */ if (unlikely (vcpu->arch.tsc_offset_adjustment)) {adjust_tsc_offset_host (vcpu, vcpu->arch.tsc_offset_adjustment);
@@ -8220,8 +8216,9 @@ static int vcpu_enter_guest(struct kvm_vtrace_kvm_entry (vcpu->vcpu_id);guest_enter_irqoff (); -/* The preempt notifier should have taken care of the FPU already. */ -WARN_ON_ONCE (test_thread_flag (TIF_NEED_FPU_LOAD )); +fpregs_assert_state_consistent (); +if (test_thread_flag (TIF_NEED_FPU_LOAD )) +switch_fpu_return ();if (unlikely (vcpu->arch.switch_db_regs)) {set_debugreg (0 ,7 );
Greg Kroah-Hartman
maintainerPATCH 225/309 KVM: s390: do not clobber registers during guest reset/store status
In reply to Greg Kroah-HartmanFrom: Christian Borntraeger <[email protected]>
commit 55680890ea78be0df5e1384989f1be835043c084 upstream.
The initial CPU reset clobbers the userspace fpc and the store status ioctl clobbers the guest acrs + fpr. As these calls are only done via ioctl (and not via vcpu_run), no CPU context is loaded, so we can (and must) act directly on the sync regs, not on the thread context.
--- arch/s390/kvm/kvm-s390.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
arch/s390/kvm/kvm-s390.c +2 -4
@@ -2863,9 +2863,7 @@ static void kvm_s390_vcpu_initial_reset( vcpu->arch.sie_block->gcr[14 ] =CR14_UNUSED_32 |CR14_UNUSED_33 |CR14_EXTERNAL_DAMAGE_SUBMASK ; -/* make sure the new fpc will be lazily loaded */ -save_fpu_regs (); - current->thread.fpu.fpc =0 ; + vcpu->run->s.regs.fpc =0 ; vcpu->arch.sie_block->gbea =1 ; vcpu->arch.sie_block->pp =0 ; vcpu->arch.sie_block->fpf &= ~FPF_BPBC ;
@@ -4354,7 +4352,7 @@ long kvm_arch_vcpu_ioctl(struct file *fiswitch (ioctl) {case KVM_S390_STORE_STATUS : idx =srcu_read_lock (&vcpu->kvm->srcu); - r =kvm_s390_vcpu_store_status (vcpu, arg); + r =kvm_s390_store_status_unloaded (vcpu, arg);srcu_read_unlock (&vcpu->kvm->srcu, idx);break ;case KVM_S390_SET_INITIAL_PSW : {
Greg Kroah-Hartman
maintainerPATCH 226/309 ocfs2: fix oops when writing cloned file
In reply to Greg Kroah-HartmanFrom: Gang He <[email protected]>
commit 2d797e9ff95ecbcf0a83d657928ed20579444857 upstream.
Writing a cloned file triggers a kernel oops and the user-space command process is also killed by the system. The bug can be reproduced stably via:
1) create a file under ocfs2 file system directory.
journalctl -b > aa.txt
2) create a cloned file for this file.
reflink aa.txt bb.txt
3) write the cloned file with dd command.
dd if=/dev/zero of=bb.txt bs=512 count=1 conv=notrunc
The dd command is killed by the kernel, then you can see the oops message via dmesg command.
[ 463.875404] BUG: kernel NULL pointer dereference, address: 0000000000000028 [ 463.875413] #PF: supervisor read access in kernel mode [ 463.875416] #PF: error_code(0x0000) - not-present page [ 463.875418] PGD 0 P4D 0 [ 463.875425] Oops: 0000 [#1] SMP PTI [ 463.875431] CPU: 1 PID: 2291 Comm: dd Tainted: G OE 5.3.16-2-default [ 463.875433] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 [ 463.875500] RIP: 0010:ocfs2_refcount_cow+0xa4/0x5d0 [ocfs2] [ 463.875505] Code: 06 89 6c 24 38 89 eb f6 44 24 3c 02 74 be 49 8b 47 28 [ 463.875508] RSP: 0018:ffffa2cb409dfce8 EFLAGS: 00010202 [ 463.875512] RAX: ffff8b1ebdca8000 RBX: 0000000000000001 RCX: ffff8b1eb73a9df0 [ 463.875515] RDX: 0000000000056a01 RSI: 0000000000000000 RDI: 0000000000000000 [ 463.875517] RBP: 0000000000000001 R08: ffff8b1eb73a9de0 R09: 0000000000000000 [ 463.875520] R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000000 [ 463.875522] R13: ffff8b1eb922f048 R14: 0000000000000000 R15: ffff8b1eb922f048 [ 463.875526] FS: 00007f8f44d15540(0000) GS:ffff8b1ebeb00000(0000) knlGS:0000000000000000 [ 463.875529] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 463.875532] CR2: 0000000000000028 CR3: 000000003c17a000 CR4: 00000000000006e0 [ 463.875546] Call Trace: [ 463.875596] ? ocfs2_inode_lock_full_nested+0x18b/0x960 [ocfs2] [ 463.875648] ocfs2_file_write_iter+0xaf8/0xc70 [ocfs2] [ 463.875672] new_sync_write+0x12d/0x1d0 [ 463.875688] vfs_write+0xad/0x1a0 [ 463.875697] ksys_write+0xa1/0xe0 [ 463.875710] do_syscall_64+0x60/0x1f0 [ 463.875743] entry_SYSCALL_64_after_hwframe+0x49/0xbe [ 463.875758] RIP: 0033:0x7f8f4482ed44 [ 463.875762] Code: 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 80 00 00 00 [ 463.875765] RSP: 002b:00007fff300a79d8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 [ 463.875769] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f8f4482ed44 [ 463.875771] RDX: 0000000000000200 RSI: 000055f771b5c000 RDI: 0000000000000001 [ 463.875774] RBP: 0000000000000200 R08: 00007f8f44af9c78 R09: 0000000000000003 [ 463.875776] R10: 000000000000089f R11: 0000000000000246 R12: 000055f771b5c000 [ 463.875779] R13: 0000000000000200 R14: 0000000000000000 R15: 000055f771b5c000
This regression problem was introduced by commit e74540b28556 ("ocfs2:
protect extent tree in ocfs2_prepare_inode_for_write()").
--- fs/ocfs2/file.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
fs/ocfs2/file.c +6 -8
@@ -2101,17 +2101,15 @@ static int ocfs2_is_io_unaligned(structstatic int ocfs2_inode_lock_for_extent_tree (struct inode *inode,struct buffer_head **di_bh,int meta_level, -int overwrite_io,int write_sem,int wait) {int ret =0 ;if (wait) - ret =ocfs2_inode_lock (inode,NULL , meta_level); + ret =ocfs2_inode_lock (inode, di_bh, meta_level);else - ret =ocfs2_try_inode_lock (inode, - overwrite_io ?NULL : di_bh, meta_level); + ret =ocfs2_try_inode_lock (inode, di_bh, meta_level);if (ret <0 ) goto out;
@@ -2136,6 +2134,7 @@ static int ocfs2_inode_lock_for_extent_t out_unlock:brelse (*di_bh); + *di_bh =NULL ;ocfs2_inode_unlock (inode, meta_level); out:return ret;
@@ -2177,7 +2176,6 @@ static int ocfs2_prepare_inode_for_write ret =ocfs2_inode_lock_for_extent_tree (inode, &di_bh, meta_level, - overwrite_io, write_sem, wait);if (ret <0 ) {
@@ -2233,13 +2231,13 @@ static int ocfs2_prepare_inode_for_write &di_bh, meta_level, write_sem); + meta_level =1 ; + write_sem =1 ; ret =ocfs2_inode_lock_for_extent_tree (inode, &di_bh, meta_level, - overwrite_io, -1 , + write_sem, wait); - write_sem =1 ;if (ret <0 ) {if (ret != -EAGAIN )mlog_errno (ret);
Greg Kroah-Hartman
maintainerPATCH 227/309 mm/page_alloc.c: fix uninitialized memmaps on a partially populated last section
In reply to Greg Kroah-HartmanFrom: David Hildenbrand <[email protected]>
commit e822969cab48b786b64246aad1a3ba2a774f5d23 upstream.
Patch series "mm: fix max_pfn not falling on section boundary", v2.
Playing with different memory sizes for a x86-64 guest, I discovered that some memmaps (highest section if max_mem does not fall on the section boundary) are marked as being valid and online, but contain garbage. We have to properly initialize these memmaps.
Looking at /proc/kpageflags and friends, I found some more issues, partially related to this.
This patch (of 3):
If max_pfn is not aligned to a section boundary, we can easily run into BUGs. This can e.g., be triggered on x86-64 under QEMU by specifying a memory size that is not a multiple of 128MB (e.g., 4097MB, but also 4160MB). I was told that on real HW, we can easily have this scenario (esp., one of the main reasons sub-section hotadd of devmem was added).
The issue is, that we have a valid memmap (pfn_valid()) for the whole section, and the whole section will be marked "online". pfn_to_online_page() will succeed, but the memmap contains garbage.
E.g., doing a "./page-types -r -a 0x144001" when QEMU was started with "-m 4160M" - (see tools/vm/page-types.c):
[ 200.476376] BUG: unable to handle page fault for address: fffffffffffffffe [ 200.477500] #PF: supervisor read access in kernel mode [ 200.478334] #PF: error_code(0x0000) - not-present page [ 200.479076] PGD 59614067 P4D 59614067 PUD 59616067 PMD 0 [ 200.479557] Oops: 0000 [#4] SMP NOPTI [ 200.479875] CPU: 0 PID: 603 Comm: page-types Tainted: G D W 5.5.0-rc1-next-20191209 #93 [ 200.480646] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu4 [ 200.481648] RIP: 0010:stable_page_flags+0x4d/0x410 [ 200.482061] Code: f3 ff 41 89 c0 48 b8 00 00 00 00 01 00 00 00 45 84 c0 0f 85 cd 02 00 00 48 8b 53 08 48 8b 2b 48f [ 200.483644] RSP: 0018:ffffb139401cbe60 EFLAGS: 00010202 [ 200.484091] RAX: fffffffffffffffe RBX: fffffbeec5100040 RCX: 0000000000000000 [ 200.484697] RDX: 0000000000000001 RSI: ffffffff9535c7cd RDI: 0000000000000246 [ 200.485313] RBP: ffffffffffffffff R08: 0000000000000000 R09: 0000000000000000 [ 200.485917] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000144001 [ 200.486523] R13: 00007ffd6ba55f48 R14: 00007ffd6ba55f40 R15: ffffb139401cbf08 [ 200.487130] FS: 00007f68df717580(0000) GS:ffff9ec77fa00000(0000) knlGS:0000000000000000 [ 200.487804] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 200.488295] CR2: fffffffffffffffe CR3: 0000000135d48000 CR4: 00000000000006f0 [ 200.488897] Call Trace: [ 200.489115] kpageflags_read+0xe9/0x140 [ 200.489447] proc_reg_read+0x3c/0x60 [ 200.489755] vfs_read+0xc2/0x170 [ 200.490037] ksys_pread64+0x65/0xa0 [ 200.490352] do_syscall_64+0x5c/0xa0 [ 200.490665] entry_SYSCALL_64_after_hwframe+0x49/0xbe
But it can be triggered much easier via "cat /proc/kpageflags > /dev/null" after cold/hot plugging a DIMM to such a system:
[root@localhost ~]# cat /proc/kpageflags > /dev/null
[ 111.517275] BUG: unable to handle page fault for address: fffffffffffffffe [ 111.517907] #PF: supervisor read access in kernel mode [ 111.518333] #PF: error_code(0x0000) - not-present page [ 111.518771] PGD a240e067 P4D a240e067 PUD a2410067 PMD 0
This patch fixes that by at least zero-ing out that memmap (so e.g., page_to_pfn() will not crash). Commit 907ec5fca3dc ("mm: zero remaining unavailable struct pages") tried to fix a similar issue, but forgot to consider this special case.
After this patch, there are still problems to solve. E.g., not all of these pages falling into a memory hole will actually get initialized later and set PageReserved - they are only zeroed out - but at least the immediate crashes are gone. A follow-up patch will take care of this.
--- mm/page_alloc.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
mm/page_alloc.c +12 -2
@@ -6933,7 +6933,8 @@ static u64 zero_pfn_range(unsigned long* This function also addresses a similar issue where struct pages are left * uninitialized because the physical address range is not covered by * memblock.memory or memblock.reserved. That could happen when memblock -* layout is manually configured via memmap=. +* layout is manually configured via memmap=, or when the highest physical +* address (max_pfn) does not end on a section boundary. */ void __init zero_resv_unavail (void ) {
@@ -6951,7 +6952,16 @@ void __init zero_resv_unavail(void) pgcnt +=zero_pfn_range (PFN_DOWN (next),PFN_UP (start)); next = end; } - pgcnt +=zero_pfn_range (PFN_DOWN (next), max_pfn); + +/* +* Early sections always have a fully populated memmap for the whole +* section - see pfn_valid(). If the last section has holes at the +* end and that section is marked "online", the memmap will be +* considered initialized. Make sure that memmap has a well defined +* state. +*/ + pgcnt +=zero_pfn_range (PFN_DOWN (next), +round_up (max_pfn,PAGES_PER_SECTION ));/* * Struct pages that do not have backing memory. This could be because
Greg Kroah-Hartman
maintainerPATCH 228/309 arm64: dts: qcom: qcs404-evb: Set vdd_apc regulator in high power mode
In reply to Greg Kroah-HartmanFrom: Niklas Cassel <[email protected]>
commit eac8ce86cb90ba96cb4bcbf2549d7a8b6938aa30 upstream.
vdd_apc is the regulator that supplies the main CPU cluster.
At sudden CPU load changes, we have noticed invalid page faults on addresses with all bits shifted, as well as on addresses with individual bits flipped.
By putting the vdd_apc regulator in high power mode, the voltage drops during sudden load changes will be less severe, and we have not been able to reproduce the invalid page faults with the regulator in this mode.
--- arch/arm64/boot/dts/qcom/qcs404-evb.dtsi | 1 + 1 file changed, 1 insertion(+)
arch/arm64/boot/dts/qcom/qcs404-evb.dtsi +1 -0
@@ -73,6 +73,7 @@ regulator-always-on; regulator-boot-on; regulator-name = "vdd_apc"; + regulator-initial-mode = <1>; regulator-min-microvolt = <1048000>; regulator-max-microvolt = <1384000>; };
Greg Kroah-Hartman
maintainerPATCH 229/309 mm/mmu_gather: invalidate TLB correctly on batch allocation failure and flush
In reply to Greg Kroah-HartmanFrom: Peter Zijlstra <[email protected]>
commit 0ed1325967ab5f7a4549a2641c6ebe115f76e228 upstream.
Architectures for which we have hardware walkers of Linux page table should flush TLB on mmu gather batch allocation failures and batch flush. Some architectures like POWER supports multiple translation modes (hash and radix) and in the case of POWER only radix translation mode needs the above TLBI. This is because for hash translation mode kernel wants to avoid this extra flush since there are no hardware walkers of linux page table. With radix translation, the hardware also walks linux page table and with that, kernel needs to make sure to TLB invalidate page walk cache before page table pages are freed.
More details in commit d86564a2f085 ("mm/tlb, x86/mm: Support invalidating TLB caches for RCU_TABLE_FREE")
The changes to sparc are to make sure we keep the old behavior since we are now removing HAVE_RCU_TABLE_NO_INVALIDATE. The default value for tlb_needs_table_invalidate is to always force an invalidate and sparc can avoid the table invalidate. Hence we define tlb_needs_table_invalidate to false for sparc architecture.
--- arch/Kconfig | 3 --- arch/powerpc/Kconfig | 1 - arch/powerpc/include/asm/tlb.h | 11 +++++++++++ arch/sparc/Kconfig | 1 - arch/sparc/include/asm/tlb_64.h | 9 +++++++++ include/asm-generic/tlb.h | 22 +++++++++++++++------- mm/mmu_gather.c | 16 ++++++++-------- 7 files changed, 43 insertions(+), 20 deletions(-)
arch/Kconfig +0 -3
@@ -396,9 +396,6 @@ config HAVE_ARCH_JUMP_LABEL_RELATIVE config HAVE_RCU_TABLE_FREE bool -config HAVE_RCU_TABLE_NO_INVALIDATE - bool - config HAVE_MMU_GATHER_PAGE_SIZE bool
arch/powerpc/Kconfig +0 -1
@@ -222,7 +222,6 @@ config PPC select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP select HAVE_RCU_TABLE_FREE - select HAVE_RCU_TABLE_NO_INVALIDATE if HAVE_RCU_TABLE_FREE select HAVE_MMU_GATHER_PAGE_SIZE select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_RELIABLE_STACKTRACE if PPC_BOOK3S_64 && CPU_LITTLE_ENDIAN
arch/powerpc/include/asm/tlb.h +11 -0
@@ -26,6 +26,17 @@#define tlb_flush tlb_flushextern void tlb_flush (struct mmu_gather *tlb); +/* +* book3s: +* Hash does not use the linux page-tables, so we can avoid +* the TLB invalidate for page-table freeing, Radix otoh does use the +* page-tables and needs the TLBI. +* +* nohash: +* We still do TLB invalidate in the __pte_free_tlb routine before we +* add the page table pages to mmu gather table batch. +*/ +#define tlb_needs_table_invalidate () radix_enabled()/* Get the generic bits... */ #include <asm-generic/tlb.h>
arch/sparc/Kconfig +0 -1
@@ -65,7 +65,6 @@ config SPARC64 select HAVE_KRETPROBES select HAVE_KPROBES select HAVE_RCU_TABLE_FREE if SMP - select HAVE_RCU_TABLE_NO_INVALIDATE if HAVE_RCU_TABLE_FREE select HAVE_MEMBLOCK_NODE_MAP select HAVE_ARCH_TRANSPARENT_HUGEPAGE select HAVE_DYNAMIC_FTRACE
arch/sparc/include/asm/tlb_64.h +9 -0
@@ -28,6 +28,15 @@ void flush_tlb_pending(void);#define __tlb_remove_tlb_entry (tlb, ptep, address) do { } while (0)#define tlb_flush (tlb) flush_tlb_pending() +/* +* SPARC64's hardware TLB fill does not use the Linux page-tables +* and therefore we don't need a TLBI when freeing page-table pages. +*/ + +#ifdef CONFIG_HAVE_RCU_TABLE_FREE +#define tlb_needs_table_invalidate () (false) +#endif +#include <asm-generic/tlb.h> #endif /* _SPARC64_TLB_H */
include/asm-generic/tlb.h +15 -7
@@ -137,13 +137,6 @@* When used, an architecture is expected to provide __tlb_remove_table() * which does the actual freeing of these pages. * -* HAVE_RCU_TABLE_NO_INVALIDATE -* -* This makes HAVE_RCU_TABLE_FREE avoid calling tlb_flush_mmu_tlbonly() before -* freeing the page-table pages. This can be avoided if you use -* HAVE_RCU_TABLE_FREE and your architecture does _NOT_ use the Linux -* page-tables natively. -* * MMU_GATHER_NO_RANGE * * Use this if your architecture lacks an efficient flush_tlb_range().
@@ -189,8 +182,23 @@ struct mmu_table_batch {extern void tlb_remove_table (struct mmu_gather *tlb,void *table); +/* +* This allows an architecture that does not use the linux page-tables for +* hardware to skip the TLBI when freeing page tables. +*/ +#ifndef tlb_needs_table_invalidate +#define tlb_needs_table_invalidate () (true)#endif +#else + +#ifdef tlb_needs_table_invalidate +#error tlb_needs_table_invalidate() requires HAVE_RCU_TABLE_FREE +#endif + +#endif /* CONFIG_HAVE_RCU_TABLE_FREE */ + +#ifndef CONFIG_HAVE_MMU_GATHER_NO_GATHER /* * If we can't allocate a page to make a big batch of page pointers
mm/mmu_gather.c +8 -8
@@ -102,14 +102,14 @@ bool __tlb_remove_page_size(struct mmu_g*/ static inline void tlb_table_invalidate (struct mmu_gather *tlb) { -#ifndef CONFIG_HAVE_RCU_TABLE_NO_INVALIDATE -/* -* Invalidate page-table caches used by hardware walkers. Then we still -* need to RCU-sched wait while freeing the pages because software -* walkers can still be in-flight. -*/ -tlb_flush_mmu_tlbonly (tlb); -#endif +if (tlb_needs_table_invalidate ()) { +/* +* Invalidate page-table caches used by hardware walkers. Then +* we still need to RCU-sched wait while freeing the pages +* because software walkers can still be in-flight. +*/ +tlb_flush_mmu_tlbonly (tlb); + } }static void tlb_remove_table_smp_sync (void *arg)
Greg Kroah-Hartman
maintainerPATCH 230/309 clk: tegra: Mark fuse clock as critical
In reply to Greg Kroah-HartmanFrom: Stephen Warren <[email protected]>
commit bf83b96f87ae2abb1e535306ea53608e8de5dfbb upstream.
For a little over a year, U-Boot on Tegra124 has configured the flow controller to perform automatic RAM re-repair on off->on power transitions of the CPU rail[1]. This is mandatory for correct operation of Tegra124. However, RAM re-repair relies on certain clocks, which the kernel must enable and leave running. The fuse clock is one of those clocks. Mark this clock as critical so that LP1 power mode (system suspend) operates correctly.
[1] 3cc7942a4ae5 ARM: tegra: implement RAM repair
--- drivers/clk/tegra/clk-tegra-periph.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/clk/tegra/clk-tegra-periph.c +5 -1
@@ -785,7 +785,11 @@ static struct tegra_periph_init_data gatGATE ("ahbdma" ,"hclk" ,33 ,0 , tegra_clk_ahbdma,0 ),GATE ("apbdma" ,"pclk" ,34 ,0 , tegra_clk_apbdma,0 ),GATE ("kbc" ,"clk_32k" ,36 ,TEGRA_PERIPH_ON_APB |TEGRA_PERIPH_NO_RESET , tegra_clk_kbc,0 ), -GATE ("fuse" ,"clk_m" ,39 ,TEGRA_PERIPH_ON_APB , tegra_clk_fuse,0 ), +/* +* Critical for RAM re-repair operation, which must occur on resume +* from LP1 system suspend and as part of CCPLEX cluster switching. +*/ +GATE ("fuse" ,"clk_m" ,39 ,TEGRA_PERIPH_ON_APB , tegra_clk_fuse,CLK_IS_CRITICAL ),GATE ("fuse_burn" ,"clk_m" ,39 ,TEGRA_PERIPH_ON_APB , tegra_clk_fuse_burn,0 ),GATE ("kfuse" ,"clk_m" ,40 ,TEGRA_PERIPH_ON_APB , tegra_clk_kfuse,0 ), GATE("apbif", "clk_m", 107, TEGRA_PERIPH_ON_APB, tegra_clk_apbif, 0),
Greg Kroah-Hartman
maintainerPATCH 231/309 drm/amd/dm/mst: Ignore payload update failures
In reply to Greg Kroah-HartmanFrom: Lyude Paul <[email protected]>
commit 58fe03d6dec908a1bec07eea7e94907af5c07eec upstream.
Disabling a display on MST can potentially happen after the entire MST topology has been removed, which means that we can't communicate with the topology at all in this scenario. Likewise, this also means that we can't properly update payloads on the topology and as such, it's a good idea to ignore payload update failures when disabling displays. Currently, amdgpu makes the mistake of halting the payload update process when any payload update failures occur, resulting in leaving DC's local copies of the payload tables out of date.
This ends up causing problems with hotplugging MST topologies, and causes modesets on the second hotplug to fail like so:
[drm] Failed to updateMST allocation table forpipe idx:1
------------[ cut here ]------------ WARNING: CPU: 5 PID: 1511 at drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_link.c:2677 update_mst_stream_alloc_table+0x11e/0x130 [amdgpu] Modules linked in: cdc_ether usbnet fuse xt_conntrack nf_conntrack
nf_defrag_ipv6 libcrc32c nf_defrag_ipv4 ipt_REJECT nf_reject_ipv4 nft_counter nft_compat nf_tables nfnetlink tun bridge stp llc sunrpc vfat fat wmi_bmof uvcvideo snd_hda_codec_realtek snd_hda_codec_generic snd_hda_codec_hdmi videobuf2_vmalloc snd_hda_intel videobuf2_memops videobuf2_v4l2 snd_intel_dspcfg videobuf2_common crct10dif_pclmul snd_hda_codec videodev crc32_pclmul snd_hwdep snd_hda_core ghash_clmulni_intel snd_seq mc joydev pcspkr snd_seq_device snd_pcm sp5100_tco k10temp i2c_piix4 snd_timer thinkpad_acpi ledtrig_audio snd wmi soundcore video i2c_scmi acpi_cpufreq ip_tables amdgpu(O) rtsx_pci_sdmmc amd_iommu_v2 gpu_sched mmc_core i2c_algo_bit ttm drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops cec drm crc32c_intel serio_raw hid_multitouch r8152 mii nvme r8169 nvme_core rtsx_pci pinctrl_amd
CPU: 5 PID: 1511 Comm: gnome-shell Tainted: G O 5.5.0-rc7Lyude-Test+ #4 Hardware name: LENOVO FA495SIT26/FA495SIT26, BIOS R12ET22W(0.22 ) 01/31/2019 RIP: 0010:update_mst_stream_alloc_table+0x11e/0x130 [amdgpu] Code: 28 00 00 00 75 2b 48 8d 65 e0 5b 41 5c 41 5d 41 5e 5d c3 0f b6 06 49 89 1c 24 41 88 44 24 08 0f b6 46 01 41 88 44 24 09 eb 93 <0f> 0b e9 2f ff ff ff e8 a6 82 a3 c2 66 0f 1f 44 00 00 0f 1f 44 00 RSP: 0018:ffffac428127f5b0 EFLAGS: 00010202 RAX: 0000000000000002 RBX: ffff8d1e166eee80 RCX: 0000000000000000 RDX: ffffac428127f668 RSI: ffff8d1e166eee80 RDI: ffffac428127f610 RBP: ffffac428127f640 R08: ffffffffc03d94a8 R09: 0000000000000000 R10: ffff8d1e24b02000 R11: ffffac428127f5b0 R12: ffff8d1e1b83d000 R13: ffff8d1e1bea0b08 R14: 0000000000000002 R15: 0000000000000002 FS: 00007fab23ffcd80(0000) GS:ffff8d1e28b40000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f151f1711e8 CR3: 00000005997c0000 CR4: 00000000003406e0 Call Trace: ? mutex_lock+0xe/0x30 dc_link_allocate_mst_payload+0x9a/0x210 [amdgpu] ? dm_read_reg_func+0x39/0xb0 [amdgpu] ? core_link_enable_stream+0x656/0x730 [amdgpu] core_link_enable_stream+0x656/0x730 [amdgpu] dce110_apply_ctx_to_hw+0x58e/0x5d0 [amdgpu] ? dcn10_verify_allow_pstate_change_high+0x1d/0x280 [amdgpu] ? dcn10_wait_for_mpcc_disconnect+0x3c/0x130 [amdgpu] dc_commit_state+0x292/0x770 [amdgpu] ? add_timer+0x101/0x1f0 ? ttm_bo_put+0x1a1/0x2f0 [ttm] amdgpu_dm_atomic_commit_tail+0xb59/0x1ff0 [amdgpu] ? amdgpu_move_blit.constprop.0+0xb8/0x1f0 [amdgpu] ? amdgpu_bo_move+0x16d/0x2b0 [amdgpu] ? ttm_bo_handle_move_mem+0x118/0x570 [ttm] ? ttm_bo_validate+0x134/0x150 [ttm] ? dm_plane_helper_prepare_fb+0x1b9/0x2a0 [amdgpu] ? _cond_resched+0x15/0x30 ? wait_for_completion_timeout+0x38/0x160 ? _cond_resched+0x15/0x30 ? wait_for_completion_interruptible+0x33/0x190 commit_tail+0x94/0x130 [drm_kms_helper] drm_atomic_helper_commit+0x113/0x140 [drm_kms_helper] drm_atomic_helper_set_config+0x70/0xb0 [drm_kms_helper] drm_mode_setcrtc+0x194/0x6a0 [drm] ? _cond_resched+0x15/0x30 ? mutex_lock+0xe/0x30 ? drm_mode_getcrtc+0x180/0x180 [drm] drm_ioctl_kernel+0xaa/0xf0 [drm] drm_ioctl+0x208/0x390 [drm] ? drm_mode_getcrtc+0x180/0x180 [drm] amdgpu_drm_ioctl+0x49/0x80 [amdgpu] do_vfs_ioctl+0x458/0x6d0 ksys_ioctl+0x5e/0x90 __x64_sys_ioctl+0x16/0x20 do_syscall_64+0x55/0x1b0 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x7fab2121f87b Code: 0f 1e fa 48 8b 05 0d 96 2c 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff
ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d dd 95 2c 00 f7 d8 64 89 01 48
RSP: 002b:00007ffd045f9068 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007ffd045f90a0 RCX: 00007fab2121f87b
RDX: 00007ffd045f90a0 RSI: 00000000c06864a2 RDI: 000000000000000b
RBP: 00007ffd045f90a0 R08: 0000000000000000 R09: 000055dbd2985d10
R10: 000055dbd2196280 R11: 0000000000000246 R12: 00000000c06864a2
R13: 000000000000000b R14: 0000000000000000 R15: 000055dbd2196280
---[ end trace 6ea888c24d2059cd ]---
Note as well, I have only been able to reproduce this on setups with 2 MST displays.
Changes since v1:
* Don't return false when part 1 or part 2 of updating the payloads fails, we don't want to abort at any step of the process even if things fail
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +4 -9
@@ -247,7 +247,8 @@ bool dm_helpers_dp_mst_write_payload_alldrm_dp_mst_reset_vcpi_slots (mst_mgr, mst_port); } - ret =drm_dp_update_payload_part1 (mst_mgr); +/* It's OK for this to fail */ +drm_dp_update_payload_part1 (mst_mgr);/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or * AUX message. The sequence is slot 1-63 allocated sequence for each
@@ -256,9 +257,6 @@ bool dm_helpers_dp_mst_write_payload_allget_payload_table (aconnector, proposed_table); -if (ret) -return false; -return true; }
@@ -316,7 +314,6 @@ bool dm_helpers_dp_mst_send_payload_allostruct amdgpu_dm_connector *aconnector;struct drm_dp_mst_topology_mgr *mst_mgr;struct drm_dp_mst_port *mst_port; -int ret; aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
@@ -330,10 +327,8 @@ bool dm_helpers_dp_mst_send_payload_alloif (!mst_mgr->mst_state)return false; - ret =drm_dp_update_payload_part2 (mst_mgr); - -if (ret) -return false; +/* It's OK for this to fail */ +drm_dp_update_payload_part2 (mst_mgr);if (!enable)drm_dp_mst_deallocate_vcpi (mst_mgr, mst_port);
Greg Kroah-Hartman
maintainerPATCH 232/309 virtio-balloon: initialize all vq callbacks
In reply to Greg Kroah-HartmanFrom: Daniel Verkamp <[email protected]>
commit 5790b53390e18fdd21e70776e46d058c05eda2f2 upstream.
Ensure that elements of the callbacks array that correspond to unavailable features are set to NULL; previously, they would be left uninitialized.
Since the corresponding names array elements were explicitly set to NULL, the uninitialized callback pointers would not actually be dereferenced; however, the uninitialized callbacks elements would still be read in vp_find_vqs_msix() and used to calculate the number of MSI-X vectors required.
--- drivers/virtio/virtio_balloon.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/virtio/virtio_balloon.c +2 -0
@@ -474,7 +474,9 @@ static int init_vqs(struct virtio_balloo names[VIRTIO_BALLOON_VQ_INFLATE ] ="inflate" ; callbacks[VIRTIO_BALLOON_VQ_DEFLATE ] = balloon_ack; names[VIRTIO_BALLOON_VQ_DEFLATE ] ="deflate" ; + callbacks[VIRTIO_BALLOON_VQ_STATS ] =NULL ; names[VIRTIO_BALLOON_VQ_STATS ] =NULL ; + callbacks[VIRTIO_BALLOON_VQ_FREE_PAGE ] =NULL ; names[VIRTIO_BALLOON_VQ_FREE_PAGE ] =NULL ;if (virtio_has_feature (vb->vdev,VIRTIO_BALLOON_F_STATS_VQ )) {
Greg Kroah-Hartman
maintainerPATCH 233/309 virtio-pci: check name when counting MSI-X vectors
In reply to Greg Kroah-HartmanFrom: Daniel Verkamp <[email protected]>
commit 303090b513fd1ee45aa1536b71a3838dc054bc05 upstream.
VQs without a name specified are not valid; they are skipped in the later loop that assigns MSI-X vectors to queues, but the per_vq_vectors loop above that counts the required number of vectors previously still counted any queue with a non-NULL callback as needing a vector.
Add a check to the per_vq_vectors loop so that vectors with no name are not counted to make the two loops consistent. This prevents over-counting unnecessary vectors (e.g. for features which were not negotiated with the device).
--- drivers/virtio/virtio_pci_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/virtio/virtio_pci_common.c +1 -1
@@ -294,7 +294,7 @@ static int vp_find_vqs_msix(struct virti/* Best option: one for change interrupt, one per vq. */ nvectors =1 ;for (i =0 ; i < nvqs; ++i) -if (callbacks[i]) +if (names[i] && callbacks[i]) ++nvectors; }else {/* Second best: one for change, shared for all vqs. */
Greg Kroah-Hartman
maintainerPATCH 234/309 fix up iter on short count in fuse_direct_io()
In reply to Greg Kroah-HartmanFrom: Miklos Szeredi <[email protected]>
commit f658adeea45e430a24c7a157c3d5448925ac2038 upstream.
fuse_direct_io() can end up advancing the iterator by more than the amount of data read or written. This case is handled by the generic code if going through ->direct_IO(), but not in the FOPEN_DIRECT_IO case.
Fix by reverting the extra bytes from the iterator in case of error or a short count.
To test: install lxcfs, then the following testcase
int fd = open("/var/lib/lxcfs/proc/uptime", O_RDONLY); sendfile(1, fd, NULL, 16777216);
sendfile(1, fd, NULL, 16777216);
will spew WARN_ON() in iov_iter_pipe().
--- fs/fuse/file.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
fs/fuse/file.c +4 -1
@@ -1465,6 +1465,7 @@ ssize_t fuse_direct_io(struct fuse_io_pr } ia =NULL ;if (nres <0 ) { +iov_iter_revert (iter, nbytes); err = nres;break ; }
@@ -1473,8 +1474,10 @@ ssize_t fuse_direct_io(struct fuse_io_pr count -= nres; res += nres; pos += nres; -if (nres != nbytes) +if (nres != nbytes) { +iov_iter_revert (iter, nbytes - nres);break ; + }if (count) { max_pages =iov_iter_npages (iter, fc->max_pages); ia =fuse_io_alloc (io, max_pages);
Greg Kroah-Hartman
maintainerPATCH 235/309 broken ping to ipv6 linklocal addresses on debian buster
In reply to Greg Kroah-HartmanFrom: Casey Schaufler <[email protected]>
commit 87fbfffcc89b92a4281b0aa53bd06af714087889 upstream.
I am seeing ping failures to IPv6 linklocal addresses with Debian buster. Easiest example to reproduce is:
$ ping -c1 -w1 ff02::1%eth1 connect: Invalid argument
$ ping -c1 -w1 ff02::1%eth1 PING ff02::01%eth1(ff02::1%eth1) 56 data bytes 64 bytes from fe80::e0:f9ff:fe0c:37%eth1: icmp_seq=1 ttl=64 time=0.059 ms
git bisect traced the failure to
commit b9ef5513c99b ("smack: Check address length before reading address family")
Arguably ping is being stupid since the buster version is not setting the address family properly (ping on stretch for example does):
$ strace -e connect ping6 -c1 -w1 ff02::1%eth1
connect(5, {sa_family=AF_UNSPEC,
sa_data="\4\1\0\0\0\0\377\2\0\0\0\0\0\0\0\0\0\0\0\0\0\1\3\0\0\0"}, 28)
= -1 EINVAL (Invalid argument)but the command works fine on kernels prior to this commit, so this is breakage which goes against the Linux paradigm of "don't break userspace"
security/smack/smack_lsm.c | 41 +++++++++++++++++++----------------------
security/smack/smack_lsm.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-)
security/smack/smack_lsm.c +19 -22
@@ -2832,42 +2832,39 @@ static int smack_socket_connect(struct s int addrlen) {int rc =0 ; -#if IS_ENABLED (CONFIG_IPV6 ) -struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap; -#endif -#ifdef SMACK_IPV6_SECMARK_LABELING -struct smack_known *rsp; -struct socket_smack *ssp; -#endif if (sock->sk ==NULL )return 0 ; - +if (sock->sk->sk_family !=PF_INET && + (!IS_ENABLED (CONFIG_IPV6 ) || sock->sk->sk_family !=PF_INET6 )) +return 0 ; + if (addrlen < offsetofend(struct sockaddr, sa_family)) +return 0 ; +if (IS_ENABLED (CONFIG_IPV6 ) && sap->sa_family ==AF_INET6 ) { +struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap;#ifdef SMACK_IPV6_SECMARK_LABELING - ssp = sock->sk->sk_security; +struct smack_known *rsp;#endif -switch (sock->sk->sk_family) { -case PF_INET : -if (addrlen <sizeof (struct sockaddr_in ) || - sap->sa_family !=AF_INET ) -return -EINVAL ; - rc =smack_netlabel_send (sock->sk, (struct sockaddr_in *)sap); -break ; -case PF_INET6 : -if (addrlen <SIN6_LEN_RFC2133 || sap->sa_family !=AF_INET6 ) -return -EINVAL ; +if (addrlen <SIN6_LEN_RFC2133 ) +return 0 ;#ifdef SMACK_IPV6_SECMARK_LABELING rsp =smack_ipv6host_label (sip); -if (rsp !=NULL ) +if (rsp !=NULL ) { +struct socket_smack *ssp = sock->sk->sk_security; + rc =smk_ipv6_check (ssp->smk_out, rsp, sip, -SMK_CONNECTING ); +SMK_CONNECTING ); + }#endif #ifdef SMACK_IPV6_PORT_LABELING rc =smk_ipv6_port_check (sock->sk, sip,SMK_CONNECTING );#endif -break ; +return rc; } +if (sap->sa_family !=AF_INET || addrlen <sizeof (struct sockaddr_in )) +return 0 ; + rc =smack_netlabel_send (sock->sk, (struct sockaddr_in *)sap);return rc; }
Greg Kroah-Hartman
maintainerPATCH 236/309 percpu: Separate decrypted varaibles anytime encryption can be enabled
In reply to Greg Kroah-HartmanFrom: Erdem Aktas <[email protected]>
commit 264b0d2bee148073c117e7bbbde5be7125a53be1 upstream.
CONFIG_VIRTUALIZATION may not be enabled for memory encrypted guests. If disabled, decrypted per-CPU variables may end up sharing the same page with variables that should be left encrypted.
Always separate per-CPU variables that should be decrypted into their own page anytime memory encryption can be enabled in the guest rather than rely on any other config option that may not be enabled.
--- include/linux/percpu-defs.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
include/linux/percpu-defs.h +1 -2
@@ -175,8 +175,7 @@* Declaration/definition used for per-CPU variables that should be accessed * as decrypted when memory encryption is enabled in the guest. */ -#if defined(CONFIG_VIRTUALIZATION ) && defined(CONFIG_AMD_MEM_ENCRYPT ) - +#ifdef CONFIG_AMD_MEM_ENCRYPT #define DECLARE_PER_CPU_DECRYPTED (type, name) \ DECLARE_PER_CPU_SECTION(type, name, "..decrypted")
Greg Kroah-Hartman
maintainerPATCH 237/309 ASoC: meson: axg-fifo: fix fifo threshold setup
In reply to Greg Kroah-HartmanFrom: Jerome Brunet <[email protected]>
commit 864cee90d4bd870e5d5e5a0b1a6f055f4f951350 upstream.
On TODDR sm1, the fifo threshold register field is slightly different compared to the other SoCs. This leads to the fifo A being flushed to memory every 8kB. If the period is smaller than that, several periods are pushed to memory and notified at once. This is not ideal.
Fix the register field update. With this, the fifos are flushed every 128B. We could still do better, like adapt the threshold depending on the period size, but at least it consistent across the different SoC/fifos
--- sound/soc/meson/axg-fifo.c | 27 +++++++++++++++++++++++++-- sound/soc/meson/axg-fifo.h | 6 ++++-- sound/soc/meson/axg-frddr.c | 24 ++++++++++++------------ sound/soc/meson/axg-toddr.c | 21 +++++++++------------ 4 files changed, 50 insertions(+), 28 deletions(-)
sound/soc/meson/axg-fifo.c +25 -2
@@ -108,10 +108,12 @@ static int axg_fifo_pcm_hw_params(struct {struct snd_pcm_runtime *runtime = ss->runtime;struct axg_fifo *fifo =axg_fifo_data (ss); +unsigned int burst_num, period, threshold;dma_addr_t end_ptr; -unsigned int burst_num;int ret; + period =params_period_bytes (params); + ret =snd_pcm_lib_malloc_pages (ss,params_buffer_bytes (params));if (ret <0 )return ret;
@@ -122,9 +124,25 @@ static int axg_fifo_pcm_hw_params(structregmap_write (fifo->map,FIFO_FINISH_ADDR , end_ptr);/* Setup interrupt periodicity */ - burst_num =params_period_bytes (params) /AXG_FIFO_BURST ; + burst_num = period /AXG_FIFO_BURST ;regmap_write (fifo->map,FIFO_INT_ADDR , burst_num); +/* +* Start the fifo request on the smallest of the following: +* - Half the fifo size +* - Half the period size +*/ + threshold =min (period /2 , + (unsigned int )AXG_FIFO_MIN_DEPTH /2 ); + +/* +* With the threshold in bytes, register value is: +* V = (threshold / burst) - 1 +*/ + threshold /=AXG_FIFO_BURST ; +regmap_field_write (fifo->field_threshold, + threshold ? threshold -1 :0 ); +/* Enable block count irq */ regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT),
@@ -360,6 +378,11 @@ int axg_fifo_probe(struct platform_devicreturn fifo->irq; } + fifo->field_threshold = +devm_regmap_field_alloc (dev, fifo->map, data->field_threshold); +if (IS_ERR (fifo->field_threshold)) +return PTR_ERR (fifo->field_threshold); +return devm_snd_soc_register_component (dev, data->component_drv, data->dai_drv,1 ); }
sound/soc/meson/axg-fifo.h +4 -2
@@ -9,7 +9,9 @@struct clk ;struct platform_device ; +struct reg_field ;struct regmap ; +struct regmap_field ;struct reset_control ;struct snd_soc_component_driver ;
@@ -50,8 +52,6 @@ struct snd_soc_pcm_runtime;#define CTRL1_STATUS2_SEL_MASK GENMASK(11, 8)#define CTRL1_STATUS2_SEL (x) ((x) << 8)#define STATUS2_SEL_DDR_READ 0 -#define CTRL1_THRESHOLD_MASK GENMASK(23, 16) -#define CTRL1_THRESHOLD (x) ((x) << 16)#define CTRL1_FRDDR_DEPTH_MASK GENMASK(31, 24)#define CTRL1_FRDDR_DEPTH (x) ((x) << 24)#define FIFO_START_ADDR 0x08
@@ -67,12 +67,14 @@ struct axg_fifo {struct regmap *map;struct clk *pclk;struct reset_control *arb; +struct regmap_field *field_threshold;int irq; };struct axg_fifo_match_data {const struct snd_soc_component_driver *component_drv;struct snd_soc_dai_driver *dai_drv; +struct reg_field field_threshold; };extern const struct snd_pcm_ops axg_fifo_pcm_ops;
sound/soc/meson/axg-frddr.c +12 -12
@@ -50,7 +50,7 @@ static int axg_frddr_dai_startup(struct struct snd_soc_dai *dai) {struct axg_fifo *fifo =snd_soc_dai_get_drvdata (dai); -unsigned int fifo_depth, fifo_threshold; +unsigned int fifo_depth;int ret;/* Enable pclk to access registers and clock the fifo ip */
@@ -68,11 +68,8 @@ static int axg_frddr_dai_startup(struct* Depth and threshold are zero based. */ fifo_depth =AXG_FIFO_MIN_CNT -1 ; - fifo_threshold = (AXG_FIFO_MIN_CNT /2 ) -1 ; -regmap_update_bits (fifo->map,FIFO_CTRL1 , -CTRL1_FRDDR_DEPTH_MASK |CTRL1_THRESHOLD_MASK , -CTRL1_FRDDR_DEPTH (fifo_depth) | -CTRL1_THRESHOLD (fifo_threshold)); +regmap_update_bits (fifo->map,FIFO_CTRL1 ,CTRL1_FRDDR_DEPTH_MASK , +CTRL1_FRDDR_DEPTH (fifo_depth));return 0 ; }
@@ -153,8 +150,9 @@ static const struct snd_soc_component_dr };static const struct axg_fifo_match_data axg_frddr_match_data = { - .component_drv = &axg_frddr_component_drv, - .dai_drv = &axg_frddr_dai_drv + .field_threshold =REG_FIELD (FIFO_CTRL1 ,16 ,23 ), + .component_drv = &axg_frddr_component_drv, + .dai_drv = &axg_frddr_dai_drv };static const struct snd_soc_dai_ops g12a_frddr_ops = {
@@ -271,8 +269,9 @@ static const struct snd_soc_component_dr };static const struct axg_fifo_match_data g12a_frddr_match_data = { - .component_drv = &g12a_frddr_component_drv, - .dai_drv = &g12a_frddr_dai_drv + .field_threshold =REG_FIELD (FIFO_CTRL1 ,16 ,23 ), + .component_drv = &g12a_frddr_component_drv, + .dai_drv = &g12a_frddr_dai_drv };/* On SM1, the output selection in on CTRL2 */
@@ -335,8 +334,9 @@ static const struct snd_soc_component_dr };static const struct axg_fifo_match_data sm1_frddr_match_data = { - .component_drv = &sm1_frddr_component_drv, - .dai_drv = &g12a_frddr_dai_drv + .field_threshold =REG_FIELD (FIFO_CTRL1 ,16 ,23 ), + .component_drv = &sm1_frddr_component_drv, + .dai_drv = &g12a_frddr_dai_drv };static const struct of_device_id axg_frddr_of_match[] = {
sound/soc/meson/axg-toddr.c +9 -12
@@ -89,7 +89,6 @@ static int axg_toddr_dai_startup(struct struct snd_soc_dai *dai) {struct axg_fifo *fifo =snd_soc_dai_get_drvdata (dai); -unsigned int fifo_threshold;int ret;/* Enable pclk to access registers and clock the fifo ip */
@@ -107,11 +106,6 @@ static int axg_toddr_dai_startup(struct/* Apply single buffer mode to the interface */ regmap_update_bits (fifo->map,FIFO_CTRL0 ,CTRL0_TODDR_PP_MODE ,0 ); -/* TODDR does not have a configurable fifo depth */ - fifo_threshold =AXG_FIFO_MIN_CNT -1 ; -regmap_update_bits (fifo->map,FIFO_CTRL1 ,CTRL1_THRESHOLD_MASK , -CTRL1_THRESHOLD (fifo_threshold)); -return 0 ; }
@@ -185,8 +179,9 @@ static const struct snd_soc_component_dr };static const struct axg_fifo_match_data axg_toddr_match_data = { - .component_drv = &axg_toddr_component_drv, - .dai_drv = &axg_toddr_dai_drv + .field_threshold =REG_FIELD (FIFO_CTRL1 ,16 ,23 ), + .component_drv = &axg_toddr_component_drv, + .dai_drv = &axg_toddr_dai_drv };static const struct snd_soc_dai_ops g12a_toddr_ops = {
@@ -218,8 +213,9 @@ static const struct snd_soc_component_dr };static const struct axg_fifo_match_data g12a_toddr_match_data = { - .component_drv = &g12a_toddr_component_drv, - .dai_drv = &g12a_toddr_dai_drv + .field_threshold =REG_FIELD (FIFO_CTRL1 ,16 ,23 ), + .component_drv = &g12a_toddr_component_drv, + .dai_drv = &g12a_toddr_dai_drv };static const char *const sm1_toddr_sel_texts[] = {
@@ -282,8 +278,9 @@ static const struct snd_soc_component_dr };static const struct axg_fifo_match_data sm1_toddr_match_data = { - .component_drv = &sm1_toddr_component_drv, - .dai_drv = &g12a_toddr_dai_drv + .field_threshold =REG_FIELD (FIFO_CTRL1 ,12 ,23 ), + .component_drv = &sm1_toddr_component_drv, + .dai_drv = &g12a_toddr_dai_drv };static const struct of_device_id axg_toddr_of_match[] = {
Greg Kroah-Hartman
maintainerPATCH 238/309 scsi: qla2xxx: Fix the endianness of the qla82xx_get_fw_size() return type
In reply to Greg Kroah-HartmanFrom: Bart Van Assche <[email protected]>
commit 3f5f7335e5e234e340b48ecb24c2aba98a61f934 upstream.
Since qla82xx_get_fw_size() returns a number in CPU-endian format, change its return type from __le32 into u32. This patch does not change any functionality.
--- drivers/scsi/qla2xxx/qla_nx.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/scsi/qla2xxx/qla_nx.c +3 -4
@@ -1612,8 +1612,7 @@ qla82xx_get_bootld_offset(struct qla_hw_return (u8 *)&ha->hablob->fw->data[offset]; } -static __le32 -qla82xx_get_fw_size (struct qla_hw_data *ha) +static u32 qla82xx_get_fw_size (struct qla_hw_data *ha) {struct qla82xx_uri_data_desc *uri_desc =NULL ;
@@ -1624,7 +1623,7 @@ qla82xx_get_fw_size(struct qla_hw_data *return cpu_to_le32 (uri_desc->size); } -return cpu_to_le32 (*(u32 *)&ha->hablob->fw->data[FW_SIZE_OFFSET ]); +return get_unaligned_le32 (&ha->hablob->fw->data[FW_SIZE_OFFSET ]); } static u8 *
@@ -1816,7 +1815,7 @@ qla82xx_fw_load_from_blob(struct qla_hw_ } flashaddr =FLASH_ADDR_START ; - size = (__force u32 )qla82xx_get_fw_size (ha) /8 ; + size =qla82xx_get_fw_size (ha) /8 ; ptr64 = (u64 *)qla82xx_get_fw_offs (ha);for (i =0 ; i < size; i++) {
Greg Kroah-Hartman
maintainerPATCH 239/309 scsi: csiostor: Adjust indentation in csio_device_reset
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
commit a808a04c861782e31fc30e342a619c144aaee14a upstream.
Clang warns:
../drivers/scsi/csiostor/csio_scsi.c:1386:3: warning: misleading indentation; statement is not part of the previous 'if' [-Wmisleading-indentation]
csio_lnodes_exit(hw, 1);
^
../drivers/scsi/csiostor/csio_scsi.c:1382:2: note: previous statement is
here
if (*buf != '1')
^1 warning generated.
This warning occurs because there is a space after the tab on this line. Remove it so that the indentation is consistent with the Linux kernel coding style and clang no longer warns.
--- drivers/scsi/csiostor/csio_scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/csiostor/csio_scsi.c +1 -1
@@ -1383,7 +1383,7 @@ csio_device_reset(struct device *dev,return -EINVAL ;/* Delete NPIV lnodes */ -csio_lnodes_exit (hw,1 ); +csio_lnodes_exit (hw,1 );/* Block upper IOs */ csio_lnodes_block_request (hw);
Greg Kroah-Hartman
maintainerPATCH 240/309 scsi: qla4xxx: Adjust indentation in qla4xxx_mem_free
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
commit aa8679736a82386551eb9f3ea0e6ebe2c0e99104 upstream.
Clang warns:
../drivers/scsi/qla4xxx/ql4_os.c:4148:3: warning: misleading indentation; statement is not part of the previous 'if' [-Wmisleading-indentation]
if (ha->fw_dump)
^
../drivers/scsi/qla4xxx/ql4_os.c:4144:2: note: previous statement is
here
if (ha->queues)
^1 warning generated.
This warning occurs because there is a space after the tab on this line. Remove it so that the indentation is consistent with the Linux kernel coding style and clang no longer warns.
--- drivers/scsi/qla4xxx/ql4_os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/qla4xxx/ql4_os.c +1 -1
@@ -4145,7 +4145,7 @@ static void qla4xxx_mem_free(struct scsidma_free_coherent (&ha->pdev->dev, ha->queues_len, ha->queues, ha->queues_dma); -if (ha->fw_dump) +if (ha->fw_dump)vfree (ha->fw_dump); ha->queues_len =0 ;
Greg Kroah-Hartman
maintainerPATCH 241/309 scsi: ufs: Recheck bkops level if bkops is disabled
In reply to Greg Kroah-HartmanFrom: Asutosh Das <[email protected]>
commit 24366c2afbb0539fb14eff330d4e3a5db5c0a3ef upstream.
bkops level should be rechecked upon receiving an exception. Currently the level is being cached and never updated.
Update bkops each time the level is checked. Also do not use the cached bkops level value if it is disabled and then enabled.
--- drivers/scsi/ufs/ufshcd.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/scsi/ufs/ufshcd.c +3 -0
@@ -5023,6 +5023,7 @@ static int ufshcd_disable_auto_bkops(str hba->auto_bkops_enabled = false;trace_ufshcd_auto_bkops_state (dev_name (hba->dev),"Disabled" ); + hba->is_urgent_bkops_lvl_checked = false; out:return err; }
@@ -5047,6 +5048,7 @@ static void ufshcd_force_reset_auto_bkop hba->ee_ctrl_mask &= ~MASK_EE_URGENT_BKOPS ;ufshcd_disable_auto_bkops (hba); } + hba->is_urgent_bkops_lvl_checked = false; }static inline int ufshcd_get_bkops_status (struct ufs_hba *hba,u32 *status)
@@ -5093,6 +5095,7 @@ static int ufshcd_bkops_ctrl(struct ufs_ err =ufshcd_enable_auto_bkops (hba); else err =ufshcd_disable_auto_bkops (hba); + hba->urgent_bkops_lvl = curr_status; out:return err; }
Greg Kroah-Hartman
maintainerPATCH 242/309 mtd: spi-nor: Split mt25qu512a (n25q512a) entry into two
In reply to Greg Kroah-HartmanFrom: Vignesh Raghavendra <[email protected]>
commit bd8a6e31b87b39a03ab11820776363640440dbe0 upstream.
mt25q family is different from n25q family of devices, even though manf ID and device IDs are same. mt25q flash has bit 6 set in 5th byte of READ ID response which can be used to distinguish it from n25q variant. mt25q flashes support stateless 4 Byte addressing opcodes where as n25q flashes don't. Therefore, have two separate entries for mt25qu512a and n25q512a.
--- drivers/mtd/spi-nor/spi-nor.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/mtd/spi-nor/spi-nor.c +5 -4
@@ -2310,15 +2310,16 @@ static const struct flash_info spi_nor_i { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "n25q256ax1", INFO(0x20bb19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) }, { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, + { "mt25qu512a", INFO6(0x20bb20, 0x104400, 64 * 1024, 1024, +SECT_4K |USE_FSR |SPI_NOR_DUAL_READ | + SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | + SPI_NOR_QUAD_READ) }, { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, { "mt25ql02g", INFO(0x20ba22, 0, 64 * 1024, 4096,SECT_4K |USE_FSR |SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, - { "mt25qu512a (n25q512a)", INFO(0x20bb20, 0, 64 * 1024, 1024, -SECT_4K |USE_FSR |SPI_NOR_DUAL_READ | -SPI_NOR_QUAD_READ | - SPI_NOR_4B_OPCODES) }, { "mt25qu02g", INFO(0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, /* Micron */
Greg Kroah-Hartman
maintainerPATCH 243/309 phy: qualcomm: Adjust indentation in read_poll_timeout
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
commit a89806c998ee123bb9c0f18526e55afd12c0c0ab upstream.
Clang warns:
../drivers/phy/qualcomm/phy-qcom-apq8064-sata.c:83:4: warning:
misleading indentation; statement is not part of the previous 'if' [-Wmisleading-indentation]
usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50);
^../drivers/phy/qualcomm/phy-qcom-apq8064-sata.c:80:3: note: previous statement is here
if (readl_relaxed(addr) & mask)
^
1 warning generated.
This warning occurs because there is a space after the tab on this line. Remove it so that the indentation is consistent with the Linux kernel coding style and clang no longer warns.
--- drivers/phy/qualcomm/phy-qcom-apq8064-sata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/phy/qualcomm/phy-qcom-apq8064-sata.c +1 -1
@@ -80,7 +80,7 @@ static int read_poll_timeout(void __iomeif (readl_relaxed (addr) & mask)return 0 ; -usleep_range (DELAY_INTERVAL_US ,DELAY_INTERVAL_US +50 ); +usleep_range (DELAY_INTERVAL_US ,DELAY_INTERVAL_US +50 ); }while (!time_after (jiffies, timeout));return (readl_relaxed (addr) & mask) ?0 : -ETIMEDOUT ;
Greg Kroah-Hartman
maintainerPATCH 244/309 ext2: Adjust indentation in ext2_fill_super
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
commit d9e9866803f7b6c3fdd35d345e97fb0b2908bbbc upstream.
Clang warns:
../fs/ext2/super.c:1076:3: warning: misleading indentation; statement is not part of the previous 'if' [-Wmisleading-indentation]
sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) -
^
../fs/ext2/super.c:1074:2: note: previous statement is here
if (EXT2_BLOCKS_PER_GROUP(sb) == 0)
^1 warning generated.
This warning occurs because there is a space before the tab on this line. Remove it so that the indentation is consistent with the Linux kernel coding style and clang no longer warns.
--- fs/ext2/super.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/ext2/super.c +3 -3
@@ -1082,9 +1082,9 @@ static int ext2_fill_super(struct super_if (EXT2_BLOCKS_PER_GROUP (sb) ==0 ) goto cantfind_ext2; - sbi->s_groups_count = ((le32_to_cpu (es->s_blocks_count) - -le32_to_cpu (es->s_first_data_block) -1 ) - /EXT2_BLOCKS_PER_GROUP (sb)) +1 ; + sbi->s_groups_count = ((le32_to_cpu (es->s_blocks_count) - +le32_to_cpu (es->s_first_data_block) -1 ) + /EXT2_BLOCKS_PER_GROUP (sb)) +1 ; db_count = (sbi->s_groups_count +EXT2_DESC_PER_BLOCK (sb) -1 ) /EXT2_DESC_PER_BLOCK (sb); sbi->s_group_desc = kmalloc_array (db_count,
Greg Kroah-Hartman
maintainerPATCH 245/309 powerpc/44x: Adjust indentation in ibm4xx_denali_fixup_memsize
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
commit c3aae14e5d468d18dbb5d7c0c8c7e2968cc14aad upstream.
Clang warns:
../arch/powerpc/boot/4xx.c:231:3: warning: misleading indentation; statement is not part of the previous 'else' [-Wmisleading-indentation]
val = SDRAM0_READ(DDR0_42);
^
../arch/powerpc/boot/4xx.c:227:2: note: previous statement is here
else
^This is because there is a space at the beginning of this line; remove it so that the indentation is consistent according to the Linux kernel coding style and clang no longer warns.
--- arch/powerpc/boot/4xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/boot/4xx.c +1 -1
@@ -228,7 +228,7 @@ void ibm4xx_denali_fixup_memsize(void) dpath =8 ;/* 64 bits */ /* get address pins (rows) */ - val =SDRAM0_READ (DDR0_42 ); + val =SDRAM0_READ (DDR0_42 ); row =DDR_GET_VAL (val,DDR_APIN ,DDR_APIN_SHIFT );if (row > max_row)
Greg Kroah-Hartman
maintainerPATCH 246/309 drm: msm: mdp4: Adjust indentation in mdp4_dsi_encoder_enable
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
commit 251e3cb1418ff3f5061ee31335e346e852b16573 upstream.
Clang warns:
../drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c:124:3: warning:
misleading indentation; statement is not part of the previous 'if' [-Wmisleading-indentation]
mdp4_crtc_set_config(encoder->crtc,
^
../drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c:121:2: note:
previous statement is here
if (mdp4_dsi_encoder->enabled)
^This warning occurs because there is a space after the tab on this line. Remove it so that the indentation is consistent with the Linux kernel coding style and clang no longer warns.
--- drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c +1 -1
@@ -121,7 +121,7 @@ static void mdp4_dsi_encoder_enable(struif (mdp4_dsi_encoder->enabled)return ; - mdp4_crtc_set_config(encoder->crtc, + mdp4_crtc_set_config(encoder->crtc, MDP4_DMA_CONFIG_PACK_ALIGN_MSB | MDP4_DMA_CONFIG_DEFLKR_EN | MDP4_DMA_CONFIG_DITHER_EN |
Greg Kroah-Hartman
maintainerPATCH 247/309 NFC: pn544: Adjust indentation in pn544_hci_check_presence
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
commit 5080832627b65e3772a35d1dced68c64e2b24442 upstream.
Clang warns
../drivers/nfc/pn544/pn544.c:696:4: warning: misleading indentation; statement is not part of the previous 'if' [-Wmisleading-indentation]
return nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE, ^../drivers/nfc/pn544/pn544.c:692:3: note: previous statement is here
if (target->nfcid1_len != 4 && target->nfcid1_len != 7 &&
^1 warning generated.
This warning occurs because there is a space after the tab on this line. Remove it so that the indentation is consistent with the Linux kernel coding style and clang no longer warns.
--- drivers/nfc/pn544/pn544.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/nfc/pn544/pn544.c +1 -1
@@ -693,7 +693,7 @@ static int pn544_hci_check_presence(stru target->nfcid1_len != 10)return -EOPNOTSUPP ; -return nfc_hci_send_cmd (hdev,NFC_HCI_RF_READER_A_GATE , +return nfc_hci_send_cmd (hdev,NFC_HCI_RF_READER_A_GATE ,PN544_RF_READER_CMD_ACTIVATE_NEXT , target->nfcid1, target->nfcid1_len,NULL ); } else if (target->supported_protocols & (NFC_PROTO_JEWEL_MASK |
Greg Kroah-Hartman
maintainerPATCH 248/309 ppp: Adjust indentation into ppp_async_input
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
commit 08cbc75f96029d3092664213a844a5e25523aa35 upstream.
Clang warns:
../drivers/net/ppp/ppp_async.c:877:6: warning: misleading indentation; statement is not part of the previous 'if' [-Wmisleading-indentation]
ap->rpkt = skb;
^
../drivers/net/ppp/ppp_async.c:875:5: note: previous statement is here
if (!skb)
^1 warning generated.
This warning occurs because there is a space before the tab on this line. Clean up this entire block's indentation so that it is consistent with the Linux kernel coding style and clang no longer warns.
--- drivers/net/ppp/ppp_async.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
drivers/net/ppp/ppp_async.c +9 -9
@@ -874,15 +874,15 @@ ppp_async_input(struct asyncppp *ap, con skb =dev_alloc_skb (ap->mru +PPP_HDRLEN +2 );if (!skb) goto nomem; - ap->rpkt = skb; - } -if (skb->len ==0 ) { -/* Try to get the payload 4-byte aligned. -* This should match the -* PPP_ALLSTATIONS/PPP_UI/compressed tests in -* process_input_packet, but we do not have -* enough chars here to test buf[1] and buf[2]. -*/ + ap->rpkt = skb; + } +if (skb->len ==0 ) { +/* Try to get the payload 4-byte aligned. +* This should match the +* PPP_ALLSTATIONS/PPP_UI/compressed tests in +* process_input_packet, but we do not have +* enough chars here to test buf[1] and buf[2]. +*/ if (buf[0 ] !=PPP_ALLSTATIONS )skb_reserve (skb,2 + (buf[0 ] &1 )); }
Greg Kroah-Hartman
maintainerPATCH 249/309 net: smc911x: Adjust indentation in smc911x_phy_configure
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
commit 5c61e223004b3b5c3f1dd25718e979bc17a3b12d upstream.
Clang warns:
../drivers/net/ethernet/smsc/smc911x.c:939:3: warning: misleading indentation; statement is not part of the previous 'if' [-Wmisleading-indentation]
if (!lp->ctl_rfduplx)
^
../drivers/net/ethernet/smsc/smc911x.c:936:2: note: previous statement
is here
if (lp->ctl_rspeed != 100)
^1 warning generated.
This warning occurs because there is a space after the tab on this line. Remove it so that the indentation is consistent with the Linux kernel coding style and clang no longer warns.
--- drivers/net/ethernet/smsc/smc911x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/smsc/smc911x.c +1 -1
@@ -936,7 +936,7 @@ static void smc911x_phy_configure(structif (lp->ctl_rspeed !=100 ) my_ad_caps &= ~(ADVERTISE_100BASE4 |ADVERTISE_100FULL |ADVERTISE_100HALF ); -if (!lp->ctl_rfduplx) +if (!lp->ctl_rfduplx) my_ad_caps &= ~(ADVERTISE_100FULL |ADVERTISE_10FULL );/* Update our Auto-Neg Advertisement Register */
Greg Kroah-Hartman
maintainerPATCH 250/309 net: tulip: Adjust indentation in {dmfe, uli526x}_init_module
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
commit fe06bf3d83ef0d92f35a24e03297172e92ce9ce3 upstream.
Clang warns:
../drivers/net/ethernet/dec/tulip/uli526x.c:1812:3: warning: misleading indentation; statement is not part of the previous 'if' [-Wmisleading-indentation]
switch (mode) {
^
../drivers/net/ethernet/dec/tulip/uli526x.c:1809:2: note: previous
statement is here
if (cr6set)
^1 warning generated.
../drivers/net/ethernet/dec/tulip/dmfe.c:2217:3: warning: misleading indentation; statement is not part of the previous 'if' [-Wmisleading-indentation]
switch(mode) {
^
../drivers/net/ethernet/dec/tulip/dmfe.c:2214:2: note: previous
statement is here
if (cr6set)
^1 warning generated.
This warning occurs because there is a space before the tab on these lines. Remove them so that the indentation is consistent with the Linux kernel coding style and clang no longer warns.
While we are here, adjust the default block in dmfe_init_module to have a proper break between the label and assignment and add a space between the switch and opening parentheses to avoid a checkpatch warning.
--- drivers/net/ethernet/dec/tulip/dmfe.c | 7 ++++--- drivers/net/ethernet/dec/tulip/uli526x.c | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-)
drivers/net/ethernet/dec/tulip/dmfe.c +4 -3
@@ -2214,15 +2214,16 @@ static int __init dmfe_init_module(void)if (cr6set) dmfe_cr6_user_set = cr6set; -switch (mode) { -case DMFE_10MHF : +switch (mode) { +case DMFE_10MHF :case DMFE_100MHF :case DMFE_10MFD :case DMFE_100MFD :case DMFE_1M_HPNA : dmfe_media_mode = mode;break ; -default :dmfe_media_mode =DMFE_AUTO ; +default : + dmfe_media_mode =DMFE_AUTO ;break ; }
drivers/net/ethernet/dec/tulip/uli526x.c +2 -2
@@ -1809,8 +1809,8 @@ static int __init uli526x_init_module(voif (cr6set) uli526x_cr6_user_set = cr6set; -switch (mode) { -case ULI526X_10MHF : +switch (mode) { +case ULI526X_10MHF :case ULI526X_100MHF :case ULI526X_10MFD :case ULI526X_100MFD :
Greg Kroah-Hartman
maintainerPATCH 251/309 IB/mlx5: Fix outstanding_pi index for GSI qps
In reply to Greg Kroah-HartmanFrom: Prabhath Sajeepa <[email protected]>
commit b5671afe5e39ed71e94eae788bacdcceec69db09 upstream.
Commit b0ffeb537f3a ("IB/mlx5: Fix iteration overrun in GSI qps") changed the way outstanding WRs are tracked for the GSI QP. But the fix did not cover the case when a call to ib_post_send() fails and updates index to track outstanding.
Since the prior commmit outstanding_pi should not be bounded otherwise the loop generate_completions() will fail.
--- drivers/infiniband/hw/mlx5/gsi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/infiniband/hw/mlx5/gsi.c +1 -2
@@ -507,8 +507,7 @@ int mlx5_ib_gsi_post_send(struct ib_qp * ret =ib_post_send (tx_qp, &cur_wr.wr, bad_wr);if (ret) {/* Undo the effect of adding the outstanding wr */ - gsi->outstanding_pi = (gsi->outstanding_pi -1 ) % - gsi->cap.max_send_wr; + gsi->outstanding_pi--; goto err; }spin_unlock_irqrestore (&gsi->lock, flags);
Greg Kroah-Hartman
maintainerPATCH 252/309 IB/core: Fix ODP get user pages flow
In reply to Greg Kroah-HartmanFrom: Yishai Hadas <[email protected]>
commit d07de8bd1709a80a282963ad7b2535148678a9e4 upstream.
The nr_pages argument of get_user_pages_remote() should always be in terms of the system page size, not the MR page size. Use PAGE_SIZE instead of umem_odp->page_shift.
--- drivers/infiniband/core/umem_odp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/core/umem_odp.c +1 -1
@@ -632,7 +632,7 @@ int ib_umem_odp_map_dma_pages(struct ib_while (bcnt >0 ) {const size_t gup_num_pages =min_t (size_t, - (bcnt +BIT (page_shift) -1 ) >> page_shift, +ALIGN (bcnt,PAGE_SIZE ) /PAGE_SIZE ,PAGE_SIZE /sizeof (struct page *));down_read (&owning_mm->mmap_sem);
Greg Kroah-Hartman
maintainerPATCH 253/309 nfsd: fix delay timer on 32-bit architectures
In reply to Greg Kroah-HartmanFrom: Arnd Bergmann <[email protected]>
commit 2561c92b12f4f4e386d453556685f75775c0938b upstream.
The nfsd4_cb_layout_done() function takes a 'time_t' value, multiplied by NSEC_PER_SEC*2 to get a nanosecond value.
This works fine on 64-bit architectures, but on 32-bit, any value over 1 second results in a signed integer overflow with unexpected results.
Cast one input to a 64-bit type in order to produce the same result that we have on 64-bit architectures, regarless of the type of nfsd4_lease.
--- fs/nfsd/nfs4layouts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/nfs4layouts.c +1 -1
@@ -675,7 +675,7 @@ nfsd4_cb_layout_done(struct nfsd4_callba/* Client gets 2 lease periods to return it */ cutoff =ktime_add_ns (task->tk_start, - nn->nfsd4_lease *NSEC_PER_SEC *2 ); + (u64 )nn->nfsd4_lease *NSEC_PER_SEC *2 );if (ktime_before (now, cutoff)) {rpc_delay (task,HZ /100 );/* 10 mili-seconds */
Greg Kroah-Hartman
maintainerPATCH 254/309 nfsd: fix jiffies/time_t mixup in LRU list
In reply to Greg Kroah-HartmanFrom: Arnd Bergmann <[email protected]>
commit 9594497f2c78993cb66b696122f7c65528ace985 upstream.
The nfsd4_blocked_lock->nbl_time timestamp is recorded in jiffies, but then compared to a CLOCK_REALTIME timestamp later on, which makes no sense.
For consistency with the other timestamps, change this to use a time_t.
This is a change in behavior, which may cause regressions, but the current code is not sensible. On a system with CONFIG_HZ=1000, the 'time_after((unsigned long)nbl->nbl_time, (unsigned long)cutoff))' check is false for roughly the first 18 days of uptime and then true for the next 49 days.
--- fs/nfsd/nfs4state.c | 2 +- fs/nfsd/state.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
fs/nfsd/nfs4state.c +1 -1
@@ -6550,7 +6550,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struc }if (fl_flags &FL_SLEEP ) { - nbl->nbl_time = jiffies; + nbl->nbl_time =get_seconds ();spin_lock (&nn->blocked_locks_lock);list_add_tail (&nbl->nbl_list, &lock_sop->lo_blocked);list_add_tail (&nbl->nbl_lru, &nn->blocked_locks_lru);
fs/nfsd/state.h +1 -1
@@ -605,7 +605,7 @@ static inline bool nfsd4_stateid_generatstruct nfsd4_blocked_lock {struct list_head nbl_list;struct list_head nbl_lru; -unsigned long nbl_time; +time_t nbl_time;struct file_lock nbl_lock;struct knfsd_fh nbl_fh;struct nfsd4_callback nbl_cb;
Greg Kroah-Hartman
maintainerPATCH 255/309 nfsd: Return the correct number of bytes written to the file
In reply to Greg Kroah-HartmanFrom: Trond Myklebust <[email protected]>
commit 09a80f2aef06b7c86143f5c14efd3485e0d2c139 upstream.
We must allow for the fact that iov_iter_write() could have returned a short write (e.g. if there was an ENOSPC issue).
--- fs/nfsd/vfs.c | 1 + 1 file changed, 1 insertion(+)
fs/nfsd/vfs.c +1 -0
@@ -975,6 +975,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s host_err =vfs_iter_write (file, &iter, &pos, flags);if (host_err <0 ) goto out_nfserr; + *cnt = host_err; nfsdstats.io_write += *cnt;fsnotify_modify (file);
Greg Kroah-Hartman
maintainerPATCH 256/309 virtio-balloon: Fix memory leak when unloading while hinting is in progress
In reply to Greg Kroah-HartmanFrom: David Hildenbrand <[email protected]>
commit 6c22dc61c76b7e7d355f1697ba0ecf26d1334ba6 upstream.
When unloading the driver while hinting is in progress, we will not release the free page blocks back to MM, resulting in a memory leak.
--- drivers/virtio/virtio_balloon.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/virtio/virtio_balloon.c +4 -0
@@ -967,6 +967,10 @@ static void remove_common(struct virtio_leak_balloon (vb, vb->num_pages);update_balloon_size (vb); +/* There might be free pages that are being reported: release them. */ +if (virtio_has_feature (vb->vdev,VIRTIO_BALLOON_F_FREE_PAGE_HINT )) +return_free_pages_to_mm (vb,ULONG_MAX ); +/* Now we reset the device so we can clean up the queues. */ vb->vdev->config->reset (vb->vdev);
Greg Kroah-Hartman
maintainerPATCH 257/309 virtio_balloon: Fix memory leaks on errors in virtballoon_probe()
In reply to Greg Kroah-HartmanFrom: David Hildenbrand <[email protected]>
commit 1ad6f58ea9364b0a5d8ae06249653ac9304a8578 upstream.
We forget to put the inode and unmount the kernfs used for compaction.
--- drivers/virtio/virtio_balloon.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/virtio/virtio_balloon.c +9 -4
@@ -900,8 +900,7 @@ static int virtballoon_probe(struct virt vb->vb_dev_info.inode =alloc_anon_inode (balloon_mnt->mnt_sb);if (IS_ERR (vb->vb_dev_info.inode)) { err =PTR_ERR (vb->vb_dev_info.inode); -kern_unmount (balloon_mnt); - goto out_del_vqs; + goto out_kern_unmount; } vb->vb_dev_info.inode->i_mapping->a_ops = &balloon_aops;#endif
@@ -912,13 +911,13 @@ static int virtballoon_probe(struct virt*/ if (virtqueue_get_vring_size (vb->free_page_vq) <2 ) { err = -ENOSPC ; - goto out_del_vqs; + goto out_iput; } vb->balloon_wq =alloc_workqueue ("balloon-wq" ,WQ_FREEZABLE |WQ_CPU_INTENSIVE ,0 );if (!vb->balloon_wq) { err = -ENOMEM ; - goto out_del_vqs; + goto out_iput; }INIT_WORK (&vb->report_free_page_work, report_free_page_func); vb->cmd_id_received_cache =VIRTIO_BALLOON_CMD_ID_STOP ;
@@ -952,6 +951,12 @@ static int virtballoon_probe(struct virt out_del_balloon_wq:if (virtio_has_feature (vdev,VIRTIO_BALLOON_F_FREE_PAGE_HINT ))destroy_workqueue (vb->balloon_wq); +out_iput: +#ifdef CONFIG_BALLOON_COMPACTION +iput (vb->vb_dev_info.inode); +out_kern_unmount: +kern_unmount (balloon_mnt); +#endif out_del_vqs: vdev->config->del_vqs (vdev); out_free_vb:
Greg Kroah-Hartman
maintainerPATCH 258/309 ubi: fastmap: Fix inverted logic in seen selfcheck
In reply to Greg Kroah-HartmanFrom: Sascha Hauer <[email protected]>
commit ef5aafb6e4e9942a28cd300bdcda21ce6cbaf045 upstream.
set_seen() sets the bit corresponding to the PEB number in the bitmap, so when self_check_seen() wants to find PEBs that haven't been seen we have to print the PEBs that have their bit cleared, not the ones which have it set.
--- drivers/mtd/ubi/fastmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mtd/ubi/fastmap.c +1 -1
@@ -64,7 +64,7 @@ static int self_check_seen(struct ubi_dereturn 0 ;for (pnum =0 ; pnum < ubi->peb_count; pnum++) { -if (test_bit (pnum, seen) && ubi->lookuptbl[pnum]) { +if (!test_bit (pnum, seen) && ubi->lookuptbl[pnum]) {ubi_err (ubi,"self-check failed for PEB %d, fastmap didn't see it" , pnum); ret = -EINVAL ; }
Greg Kroah-Hartman
maintainerPATCH 259/309 ubi: Fix an error pointer dereference in error handling code
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
commit 5d3805af279c93ef49a64701f35254676d709622 upstream.
If "seen_pebs = init_seen(ubi);" fails then "seen_pebs" is an error pointer and we try to kfree() it which results in an Oops.
This patch re-arranges the error handling so now it only frees things which have been allocated successfully.
--- drivers/mtd/ubi/fastmap.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-)
drivers/mtd/ubi/fastmap.c +12 -9
@@ -1137,7 +1137,7 @@ static int ubi_write_fastmap(struct ubi_struct rb_node *tmp_rb;int ret, i, j, free_peb_count, used_peb_count, vol_count;int scrub_peb_count, erase_peb_count; -unsigned long *seen_pebs =NULL ; +unsigned long *seen_pebs; fm_raw = ubi->fm_buf;memset (ubi->fm_buf,0 , ubi->fm_size);
@@ -1151,7 +1151,7 @@ static int ubi_write_fastmap(struct ubi_ dvbuf =new_fm_vbuf (ubi,UBI_FM_DATA_VOLUME_ID );if (!dvbuf) { ret = -ENOMEM ; - goto out_kfree; + goto out_free_avbuf; } avhdr =ubi_get_vid_hdr (avbuf);
@@ -1160,7 +1160,7 @@ static int ubi_write_fastmap(struct ubi_ seen_pebs =init_seen (ubi);if (IS_ERR (seen_pebs)) { ret =PTR_ERR (seen_pebs); - goto out_kfree; + goto out_free_dvbuf; }spin_lock (&ubi->volumes_lock);
@@ -1328,7 +1328,7 @@ static int ubi_write_fastmap(struct ubi_ ret =ubi_io_write_vid_hdr (ubi, new_fm->e[0 ]->pnum, avbuf);if (ret) {ubi_err (ubi,"unable to write vid_hdr to fastmap SB!" ); - goto out_kfree; + goto out_free_seen; }for (i =0 ; i < new_fm->used_blocks; i++) {
@@ -1350,7 +1350,7 @@ static int ubi_write_fastmap(struct ubi_if (ret) {ubi_err (ubi,"unable to write vid_hdr to PEB %i!" , new_fm->e[i]->pnum); - goto out_kfree; + goto out_free_seen; } }
@@ -1360,7 +1360,7 @@ static int ubi_write_fastmap(struct ubi_if (ret) {ubi_err (ubi,"unable to write fastmap to PEB %i!" , new_fm->e[i]->pnum); - goto out_kfree; + goto out_free_seen; } }
@@ -1370,10 +1370,13 @@ static int ubi_write_fastmap(struct ubi_ ret =self_check_seen (ubi, seen_pebs);dbg_bld ("fastmap written!" ); -out_kfree: -ubi_free_vid_buf (avbuf); -ubi_free_vid_buf (dvbuf); +out_free_seen:free_seen (seen_pebs); +out_free_dvbuf: +ubi_free_vid_buf (dvbuf); +out_free_avbuf: +ubi_free_vid_buf (avbuf); + out:return ret; }
Greg Kroah-Hartman
maintainerPATCH 260/309 ubifs: Fix memory leak from c->sup_node
In reply to Greg Kroah-HartmanFrom: Quanyang Wang <[email protected]>
commit ff90bdfb206e49c8b418811efbdd0c77380fa8c2 upstream.
The c->sup_node is allocated in function ubifs_read_sb_node but is not freed. This will cause memory leak as below:
unreferenced object 0xbc9ce000 (size 4096):
comm "mount", pid 500, jiffies 4294952946 (age 315.820s) hex dump (first 32 bytes):
31 18 10 06 06 7b f1 11 02 00 00 00 00 00 00 00 1....{..........
00 10 00 00 06 00 00 00 00 00 00 00 08 00 00 00 ................
backtrace:
[<d1c503cd>] ubifs_read_superblock+0x48/0xebc
[<a20e14bd>] ubifs_mount+0x974/0x1420
[<8589ecc3>] legacy_get_tree+0x2c/0x50
[<5f1fb889>] vfs_get_tree+0x28/0xfc
[<bbfc7939>] do_mount+0x4f8/0x748
[<4151f538>] ksys_mount+0x78/0xa0
[<d59910a9>] ret_fast_syscall+0x0/0x54
[<1cc40005>] 0x7ea02790Free it in ubifs_umount and in the error path of mount_ubifs.
--- fs/ubifs/super.c | 2 ++ 1 file changed, 2 insertions(+)
fs/ubifs/super.c +2 -0
@@ -1599,6 +1599,7 @@ out_free:vfree (c->ileb_buf);vfree (c->sbuf);kfree (c->bottom_up_buf); +kfree (c->sup_node);ubifs_debugging_exit (c);return err; }
@@ -1641,6 +1642,7 @@ static void ubifs_umount(struct ubifs_invfree (c->ileb_buf);vfree (c->sbuf);kfree (c->bottom_up_buf); +kfree (c->sup_node);ubifs_debugging_exit (c); }
Greg Kroah-Hartman
maintainerPATCH 261/309 regulator: core: Add regulator_is_equal() helper
In reply to Greg Kroah-HartmanFrom: Marek Vasut <[email protected]>
commit b059b7e0ec3208ff1e17cff6387d75a9fbab4e02 upstream.
Add regulator_is_equal() helper to compare whether two regulators are the same. This is useful for checking whether two separate regulators in a driver are actually the same supply.
--- drivers/regulator/helpers.c | 14 ++++++++++++++ include/linux/regulator/consumer.h | 7 +++++++ 2 files changed, 21 insertions(+)
drivers/regulator/helpers.c +14 -0
@@ -13,6 +13,8 @@#include <linux/regulator/driver.h> #include <linux/module.h> +#include "internal.h" +/** * regulator_is_enabled_regmap - standard is_enabled() for regmap users *
@@ -881,3 +883,15 @@ void regulator_bulk_set_supply_names(str consumers[i].supply = supply_names[i]; }EXPORT_SYMBOL_GPL (regulator_bulk_set_supply_names); + +/** +* regulator_is_equal - test whether two regulators are the same +* +* @reg1: first regulator to operate on +* @reg2: second regulator to operate on +*/ +bool regulator_is_equal (struct regulator *reg1,struct regulator *reg2) +{ +return reg1->rdev == reg2->rdev; +} +EXPORT_SYMBOL_GPL (regulator_is_equal);
include/linux/regulator/consumer.h +7 -0
@@ -287,6 +287,8 @@ void regulator_bulk_set_supply_names(strconst char *const *supply_names, unsigned int num_supplies); +bool regulator_is_equal (struct regulator *reg1,struct regulator *reg2); +#else /*
@@ -593,6 +595,11 @@ regulator_bulk_set_supply_names(struct r { } +static inline bool +regulator_is_equal (struct regulator *reg1,struct regulator *reg2); +{ +return false; +}#endif static inline int regulator_set_voltage_triplet(struct regulator *regulator,
Re: [PATCH 5.4 261/309] regulator: core: Add regulator_is_equal() helper
include/linux/regulator/consumer.h regulator_bulk_set_supply_names(struct r · line 599
Quoted 2 lines · Greg Kroah-Hartman
include/linux/regulator/consumer.h +2
-0+static inline bool +regulator_is_equal (struct regulator *reg1,struct regulator *reg2);
This causes build error. There is a fix for this in:
commit 0468e667a5bead9c1b7ded92861b5a98d8d78745
Author: Stephen Rothwell <[email protected]> Date: Wed Jan 15 12:02:58 2020 +1100
regulator fix for "regulator: core: Add regulator_is_equal() helper"
Greg Kroah-Hartman
maintainerRe: [PATCH 5.4 261/309] regulator: core: Add regulator_is_equal() helper
Quoted 12 lines · Fabio Estevam
include/linux/regulator/consumer.h regulator_bulk_set_supply_names(struct r · line 599
Quoted 2 lines · Greg Kroah-Hartman
include/linux/regulator/consumer.h +2
-0+static inline bool +regulator_is_equal (struct regulator *reg1,struct regulator *reg2);This causes build error. There is a fix for this in:
commit
0468e667a5bead9c1b7ded92861b5a98d8d78745Author: Stephen Rothwell <[email protected]> Date: Wed Jan 15 12:02:58 2020 +1100
Quoted 6 lines
regulator fix for "regulator: core: Add
regulator_is_equal()helper"Signed-off-by Stephen Rothwell <[email protected]>Acked-by Marek Vasut <[email protected]>Signed-off-by Mark Brown <[email protected]>
That commit is also queued up already, thanks!
greg k-h
Greg Kroah-Hartman
maintainerPATCH 262/309 ASoC: sgtl5000: Fix VDDA and VDDIO comparison
In reply to Greg Kroah-HartmanFrom: Marek Vasut <[email protected]>
commit e19ecbf105b236a6334fab64d8fd5437b12ee019 upstream.
Comparing the voltage of VDDA and VDDIO to determine whether or not to enable VDDC manual override is insufficient. This is a problem in case the VDDA is supplied from different regulator than VDDIO, while both report the same voltage to the regulator framework. In that case where VDDA and VDDIO is supplied by different regulators, the VDDC manual override must not be applied.
--- sound/soc/codecs/sgtl5000.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
sound/soc/codecs/sgtl5000.c +2 -1
@@ -1344,7 +1344,8 @@ static int sgtl5000_set_power_regs(struc* if vddio == vdda the source of charge pump should be * assigned manually to VDDIO */ -if (vddio == vdda) { +if (regulator_is_equal (sgtl5000->supplies[VDDA ].consumer, + sgtl5000->supplies[VDDIO ].consumer)) { lreg_ctrl |=SGTL5000_VDDC_ASSN_OVRD ; lreg_ctrl |=SGTL5000_VDDC_MAN_ASSN_VDDIO <<SGTL5000_VDDC_MAN_ASSN_SHIFT ;
Greg Kroah-Hartman
maintainerPATCH 263/309 bonding/alb: properly access headers in bond_alb_xmit()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit 38f88c45404293bbc027b956def6c10cbd45c616 ]
syzbot managed to send an IPX packet through bond_alb_xmit() and af_packet and triggered a use-after-free.
First, bond_alb_xmit() was using ipx_hdr() helper to reach the IPX header, but ipx_hdr() was using the transport offset instead of the network offset. In the particular syzbot report transport offset was 0xFFFF
This patch removes ipx_hdr() since it was only (mis)used from bonding.
Then we need to make sure IPv4/IPv6/IPX headers are pulled in skb->head before dereferencing anything.
BUG: KASAN: use-after-free in bond_alb_xmit+0x153a/0x1590 drivers/net/bonding/bond_alb.c:1452 Read of size 2 at addr ffff8801ce56dfff by task syz-executor.2/18108 (if (ipx_hdr(skb)->ipx_checksum != IPX_NO_CHECKSUM) ...) Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: [<ffffffff8441fc42>] __dump_stack lib/dump_stack.c:17 [inline] [<ffffffff8441fc42>] dump_stack+0x14d/0x20b lib/dump_stack.c:53 [<ffffffff81a7dec4>] print_address_description+0x6f/0x20b mm/kasan/report.c:282 [<ffffffff81a7e0ec>] kasan_report_error mm/kasan/report.c:380 [inline] [<ffffffff81a7e0ec>] kasan_report mm/kasan/report.c:438 [inline] [<ffffffff81a7e0ec>] kasan_report.cold+0x8c/0x2a0 mm/kasan/report.c:422 [<ffffffff81a7dc4f>] __asan_report_load_n_noabort+0xf/0x20 mm/kasan/report.c:469 [<ffffffff82c8c00a>] bond_alb_xmit+0x153a/0x1590 drivers/net/bonding/bond_alb.c:1452 [<ffffffff82c60c74>] __bond_start_xmit drivers/net/bonding/bond_main.c:4199 [inline] [<ffffffff82c60c74>] bond_start_xmit+0x4f4/0x1570 drivers/net/bonding/bond_main.c:4224 [<ffffffff83baa558>] __netdev_start_xmit include/linux/netdevice.h:4525 [inline] [<ffffffff83baa558>] netdev_start_xmit include/linux/netdevice.h:4539 [inline] [<ffffffff83baa558>] xmit_one net/core/dev.c:3611 [inline] [<ffffffff83baa558>] dev_hard_start_xmit+0x168/0x910 net/core/dev.c:3627 [<ffffffff83bacf35>] __dev_queue_xmit+0x1f55/0x33b0 net/core/dev.c:4238 [<ffffffff83bae3a8>] dev_queue_xmit+0x18/0x20 net/core/dev.c:4278 [<ffffffff84339189>] packet_snd net/packet/af_packet.c:3226 [inline] [<ffffffff84339189>] packet_sendmsg+0x4919/0x70b0 net/packet/af_packet.c:3252 [<ffffffff83b1ac0c>] sock_sendmsg_nosec net/socket.c:673 [inline] [<ffffffff83b1ac0c>] sock_sendmsg+0x12c/0x160 net/socket.c:684 [<ffffffff83b1f5a2>] __sys_sendto+0x262/0x380 net/socket.c:1996 [<ffffffff83b1f700>] SYSC_sendto net/socket.c:2008 [inline] [<ffffffff83b1f700>] SyS_sendto+0x40/0x60 net/socket.c:2004
--- drivers/net/bonding/bond_alb.c | 44 +++++++++++++++++++++++++++++------------ include/net/ipx.h | 5 ---- 2 files changed, 32 insertions(+), 17 deletions(-)
drivers/net/bonding/bond_alb.c +32 -12
@@ -1383,26 +1383,31 @@ netdev_tx_t bond_alb_xmit(struct sk_buffbool do_tx_balance = true;u32 hash_index =0 ;const u8 *hash_start =NULL ; -struct ipv6hdr *ip6hdr;skb_reset_mac_header (skb); eth_data =eth_hdr (skb);switch (ntohs (skb->protocol)) {case ETH_P_IP : { -const struct iphdr *iph =ip_hdr (skb); +const struct iphdr *iph;if (is_broadcast_ether_addr (eth_data->h_dest) || - iph->daddr == ip_bcast || - iph->protocol ==IPPROTO_IGMP ) { + !pskb_network_may_pull (skb,sizeof (*iph))) { + do_tx_balance = false; +break ; + } + iph =ip_hdr (skb); +if (iph->daddr == ip_bcast || iph->protocol ==IPPROTO_IGMP ) { do_tx_balance = false;break ; } hash_start = (char *)&(iph->daddr); hash_size =sizeof (iph->daddr); - }break ; -case ETH_P_IPV6 : + } +case ETH_P_IPV6 : { +const struct ipv6hdr *ip6hdr; +/* IPv6 doesn't really use broadcast mac address, but leave * that here just in case. */
@@ -1419,7 +1424,11 @@ netdev_tx_t bond_alb_xmit(struct sk_buffbreak ; } -/* Additianally, DAD probes should not be tx-balanced as that +if (!pskb_network_may_pull (skb,sizeof (*ip6hdr))) { + do_tx_balance = false; +break ; + } +/* Additionally, DAD probes should not be tx-balanced as that * will lead to false positives for duplicate addresses and * prevent address configuration from working. */
@@ -1429,17 +1438,26 @@ netdev_tx_t bond_alb_xmit(struct sk_buffbreak ; } - hash_start = (char *)&(ipv6_hdr (skb)->daddr); - hash_size =sizeof (ipv6_hdr (skb)->daddr); + hash_start = (char *)&ip6hdr->daddr; + hash_size =sizeof (ip6hdr->daddr);break ; -case ETH_P_IPX : -if (ipx_hdr (skb)->ipx_checksum !=IPX_NO_CHECKSUM ) { + } +case ETH_P_IPX : { +const struct ipxhdr *ipxhdr; + +if (pskb_network_may_pull (skb,sizeof (*ipxhdr))) { + do_tx_balance = false; +break ; + } + ipxhdr = (struct ipxhdr *)skb_network_header (skb); + +if (ipxhdr->ipx_checksum !=IPX_NO_CHECKSUM ) {/* something is wrong with this packet */ do_tx_balance = false;break ; } -if (ipx_hdr (skb)->ipx_type !=IPX_TYPE_NCP ) { +if (ipxhdr->ipx_type !=IPX_TYPE_NCP ) {/* The only protocol worth balancing in * this family since it has an "ARP" like * mechanism
@@ -1448,9 +1466,11 @@ netdev_tx_t bond_alb_xmit(struct sk_buffbreak ; } + eth_data =eth_hdr (skb); hash_start = (char *)eth_data->h_dest; hash_size =ETH_ALEN ;break ; + }case ETH_P_ARP : do_tx_balance = false;if (bond_info->rlb_enabled)
include/net/ipx.h +0 -5
@@ -47,11 +47,6 @@ struct ipxhdr {/* From af_ipx.c */ extern int sysctl_ipx_pprop_broadcasting; -static __inline__struct ipxhdr *ipx_hdr (struct sk_buff *skb) -{ -return (struct ipxhdr *)skb_transport_header (skb); -} -struct ipx_interface {/* IPX address */ __be32 if_netnum;
Greg Kroah-Hartman
maintainerPATCH 264/309 devlink: report 0 after hitting end in region read
In reply to Greg Kroah-HartmanFrom: Jacob Keller <[email protected]>
[ Upstream commit d5b90e99e1d51b7b5d2b74fbc4c2db236a510913 ]
commit fdd41ec21e15 ("devlink: Return right error code in case of errors for region read") modified the region read code to report errors properly in unexpected cases.
In the case where the start_offset and ret_offset match, it unilaterally converted this into an error. This causes an issue for the "dump" version of the command. In this case, the devlink region dump will always report an invalid argument:
000000000000ffd0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 000000000000ffe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff devlink answers: Invalid argument000000000000fff0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
This occurs because the expected flow for the dump is to return 0 after there is no further data.
The simplest fix would be to stop converting the error code to -EINVAL if start_offset == ret_offset. However, avoid unnecessary work by checking for when start_offset is larger than the region size and returning 0 upfront.
--- net/core/devlink.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/core/devlink.c +6 -0
@@ -3863,6 +3863,12 @@ static int devlink_nl_cmd_region_read_du goto out_unlock; } +/* return 0 if there is no further data to read */ +if (start_offset >= region->size) { + err =0 ; + goto out_unlock; + } + hdr =genlmsg_put (skb,NETLINK_CB (cb->skb).portid, cb->nlh->nlmsg_seq, &devlink_nl_family,NLM_F_ACK |NLM_F_MULTI ,DEVLINK_CMD_REGION_READ );
Greg Kroah-Hartman
maintainerPATCH 265/309 dpaa_eth: support all modes with rate adapting PHYs
In reply to Greg Kroah-HartmanFrom: Madalin Bucur <[email protected]>
[ Upstream commit 73a21fa817f0cc8022dc6226250a86bca727a56d ]
Stop removing modes that are not supported on the system interface when the connected PHY is capable of rate adaptation. This addresses an issue with the LS1046ARDB board 10G interface no longer working with an 1G link partner after autonegotiation support was added for the Aquantia PHY on board in
commit 09c4c57f7bc4 ("net: phy: aquantia: add support for auto-negotiation configuration")
Before this commit the values advertised by the PHY were not influenced by the dpaa_eth driver removal of system-side unsupported modes as the aqr_config_aneg() was basically a no-op. After this commit, the modes removed by the dpaa_eth driver were no longer advertised thus autonegotiation with 1G link partners failed.
--- drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +11 -3
@@ -2483,6 +2483,9 @@ static void dpaa_adjust_link(struct net_ mac_dev->adjust_link (mac_dev); } +/* The Aquantia PHYs are capable of performing rate adaptation */ +#define PHY_VEND_AQUANTIA 0x03a1b400 +static int dpaa_phy_init (struct net_device *net_dev) {__ETHTOOL_DECLARE_LINK_MODE_MASK (mask) = {0 , };
@@ -2501,9 +2504,14 @@ static int dpaa_phy_init(struct net_devireturn -ENODEV ; } -/* Remove any features not supported by the controller */ -ethtool_convert_legacy_u32_to_link_mode (mask, mac_dev->if_support); -linkmode_and (phy_dev->supported, phy_dev->supported, mask); +/* Unless the PHY is capable of rate adaptation */ +if (mac_dev->phy_if !=PHY_INTERFACE_MODE_XGMII || + ((phy_dev->drv->phy_id &GENMASK (31 ,10 )) !=PHY_VEND_AQUANTIA )) { +/* remove any features not supported by the controller */ +ethtool_convert_legacy_u32_to_link_mode (mask, + mac_dev->if_support); +linkmode_and (phy_dev->supported, phy_dev->supported, mask); + }phy_support_asym_pause (phy_dev);
Greg Kroah-Hartman
maintainerPATCH 266/309 net: dsa: b53: Always use dev->vlan_enabled in b53_configure_vlan()
In reply to Greg Kroah-HartmanFrom: Florian Fainelli <[email protected]>
[ Upstream commit df373702bc0f8f2d83980ea441e71639fc1efcf8 ]
b53_configure_vlan() is called by the bcm_sf2 driver upon setup and indirectly through resume as well. During the initial setup, we are guaranteed that dev->vlan_enabled is false, so there is no change in behavior, however during suspend, we may have enabled VLANs before, so we do want to restore that setting.
--- drivers/net/dsa/b53/b53_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/dsa/b53/b53_common.c +1 -1
@@ -680,7 +680,7 @@ int b53_configure_vlan(struct dsa_switchb53_do_vlan_op (dev,VTA_CMD_CLEAR ); } -b53_enable_vlan (dev, false, ds->vlan_filtering); +b53_enable_vlan (dev, dev->vlan_enabled, ds->vlan_filtering);b53_for_each_port (dev, i) b53_write16(dev, B53_VLAN_PAGE,
Greg Kroah-Hartman
maintainerPATCH 267/309 net: dsa: bcm_sf2: Only 7278 supports 2Gb/sec IMP port
In reply to Greg Kroah-HartmanFrom: Florian Fainelli <[email protected]>
[ Upstream commit de34d7084edd069dac5aa010cfe32bd8c4619fa6 ]
The 7445 switch clocking profiles do not allow us to run the IMP port at 2Gb/sec in a way that it is reliable and consistent. Make sure that the setting is only applied to the 7278 family.
--- drivers/net/dsa/bcm_sf2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/dsa/bcm_sf2.c +3 -1
@@ -68,7 +68,9 @@ static void bcm_sf2_imp_setup(struct dsa/* Force link status for IMP port */ reg =core_readl (priv, offset); - reg |= (MII_SW_OR |LINK_STS |GMII_SPEED_UP_2G ); + reg |= (MII_SW_OR |LINK_STS ); +if (priv->type ==BCM7278_DEVICE_ID ) + reg |=GMII_SPEED_UP_2G ;core_writel (priv, reg, offset);/* Enable Broadcast, Multicast, Unicast forwarding to IMP port */
Greg Kroah-Hartman
maintainerPATCH 268/309 net: dsa: microchip: enable module autoprobe
In reply to Greg Kroah-HartmanFrom: Razvan Stefanescu <[email protected]>
[ Upstream commit f8c2afa66d5397b0b9293c4347dac6dabb327685 ]
This matches /sys/devices/.../spi1.0/modalias content.
--- drivers/net/dsa/microchip/ksz9477_spi.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/net/dsa/microchip/ksz9477_spi.c +6 -0
@@ -101,6 +101,12 @@ static struct spi_driver ksz9477_spi_drimodule_spi_driver (ksz9477_spi_driver); +MODULE_ALIAS ("spi:ksz9477" ); +MODULE_ALIAS ("spi:ksz9897" ); +MODULE_ALIAS ("spi:ksz9893" ); +MODULE_ALIAS ("spi:ksz9563" ); +MODULE_ALIAS ("spi:ksz8563" ); +MODULE_ALIAS ("spi:ksz9567" );MODULE_AUTHOR ("Woojung Huh <[email protected]>" );MODULE_DESCRIPTION ("Microchip KSZ9477 Series Switch SPI access Driver" );MODULE_LICENSE ("GPL" );
Greg Kroah-Hartman
maintainerPATCH 269/309 net: mvneta: move rx_dropped and rx_errors in per-cpu stats
In reply to Greg Kroah-HartmanFrom: Lorenzo Bianconi <[email protected]>
[ Upstream commit c35947b8ff8acca33134ee39c31708233765c31a ]
Move rx_dropped and rx_errors counters in mvneta_pcpu_stats in order to avoid possible races updating statistics
--- drivers/net/ethernet/marvell/mvneta.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-)
drivers/net/ethernet/marvell/mvneta.c +21 -6
@@ -388,6 +388,8 @@ struct mvneta_pcpu_stats {struct u64_stats_sync syncp;u64 rx_packets;u64 rx_bytes; +u64 rx_dropped; +u64 rx_errors;u64 tx_packets;u64 tx_bytes; };
@@ -706,6 +708,8 @@ mvneta_get_stats64(struct net_device *destruct mvneta_pcpu_stats *cpu_stats;u64 rx_packets;u64 rx_bytes; +u64 rx_dropped; +u64 rx_errors;u64 tx_packets;u64 tx_bytes;
@@ -714,19 +718,20 @@ mvneta_get_stats64(struct net_device *de start =u64_stats_fetch_begin_irq (&cpu_stats->syncp); rx_packets = cpu_stats->rx_packets; rx_bytes = cpu_stats->rx_bytes; + rx_dropped = cpu_stats->rx_dropped; + rx_errors = cpu_stats->rx_errors; tx_packets = cpu_stats->tx_packets; tx_bytes = cpu_stats->tx_bytes; }while (u64_stats_fetch_retry_irq (&cpu_stats->syncp, start)); stats->rx_packets += rx_packets; stats->rx_bytes += rx_bytes; + stats->rx_dropped += rx_dropped; + stats->rx_errors += rx_errors; stats->tx_packets += tx_packets; stats->tx_bytes += tx_bytes; } - stats->rx_errors = dev->stats.rx_errors; - stats->rx_dropped = dev->stats.rx_dropped; - stats->tx_dropped = dev->stats.tx_dropped; }
@@ -1703,8 +1708,14 @@ static u32 mvneta_txq_desc_csum(int l3_ostatic void mvneta_rx_error (struct mvneta_port *pp,struct mvneta_rx_desc *rx_desc) { +struct mvneta_pcpu_stats *stats =this_cpu_ptr (pp->stats);u32 status = rx_desc->status; +/* update per-cpu counter */ +u64_stats_update_begin (&stats->syncp); + stats->rx_errors++; +u64_stats_update_end (&stats->syncp); +switch (status &MVNETA_RXD_ERR_CODE_MASK ) {case MVNETA_RXD_ERR_CRC : netdev_err(pp->dev, "bad rx status %08x (crc error), size=%d\n",
@@ -1965,7 +1976,6 @@ static int mvneta_rx_swbm(struct napi_st/* Check errors only for FIRST descriptor */ if (rx_status &MVNETA_RXD_ERR_SUMMARY ) {mvneta_rx_error (pp, rx_desc); - dev->stats.rx_errors++;/* leave the descriptor untouched */ continue ; }
@@ -1976,11 +1986,17 @@ static int mvneta_rx_swbm(struct napi_st skb_size =max (rx_copybreak, rx_header_size); rxq->skb =netdev_alloc_skb_ip_align (dev, skb_size);if (unlikely (!rxq->skb)) { +struct mvneta_pcpu_stats *stats =this_cpu_ptr (pp->stats); +netdev_err (dev,"Can't allocate skb on queue %d\n" , rxq->id); - dev->stats.rx_dropped++; + rxq->skb_alloc_err++; + +u64_stats_update_begin (&stats->syncp); + stats->rx_dropped++; +u64_stats_update_end (&stats->syncp);continue ; } copy_size =min (skb_size, rx_bytes);
@@ -2137,7 +2153,6 @@ err_drop_frame_ret_pool:mvneta_bm_pool_put_bp (pp->bm_priv, bm_pool, rx_desc->buf_phys_addr); err_drop_frame: - dev->stats.rx_errors++;mvneta_rx_error (pp, rx_desc);/* leave the descriptor untouched */ continue ;
Greg Kroah-Hartman
maintainerPATCH 270/309 net_sched: fix a resource leak in tcindex_set_parms()
In reply to Greg Kroah-HartmanFrom: Cong Wang <[email protected]>
[ Upstream commit 52b5ae501c045010aeeb1d5ac0373ff161a88291 ]
Jakub noticed there is a potential resource leak in tcindex_set_parms(): when tcindex_filter_result_init() fails and it jumps to 'errout1' which doesn't release the memory and resources allocated by tcindex_alloc_perfect_hash().
We should just jump to 'errout_alloc' which callstcindex_free_perfect_hash().
--- net/sched/cls_tcindex.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
net/sched/cls_tcindex.c +1 -2
@@ -365,7 +365,7 @@ tcindex_set_parms(struct net *net, struc err =tcindex_filter_result_init (&new_filter_result, net);if (err <0 ) - goto errout1; + goto errout_alloc;if (old_r) cr = r->res;
@@ -484,7 +484,6 @@ errout_alloc:tcindex_free_perfect_hash (cp); else if (balloc == 2) kfree(cp->h); -errout1:tcf_exts_destroy (&new_filter_result.exts); errout:kfree (cp);
Greg Kroah-Hartman
maintainerPATCH 271/309 net: stmmac: fix a possible endless loop
In reply to Greg Kroah-HartmanFrom: Dejin Zheng <[email protected]>
[ Upstream commit 7d10f0774f9e32aa2f2e012f7fcb312a2ce422b9 ]
It forgot to reduce the value of the variable retry in a while loop in the ethqos_configure() function. It may cause an endless loop and without timeout.
--- drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +1 -0
@@ -413,6 +413,7 @@ static int ethqos_configure(struct qcom_ dll_lock =rgmii_readl (ethqos,SDC4_STATUS );if (dll_lock &SDC4_STATUS_DLL_LOCK )break ; + retry--; }while (retry >0 );if (!retry) dev_err(ðqos->pdev->dev,
Greg Kroah-Hartman
maintainerPATCH 272/309 net: systemport: Avoid RBUF stuck in Wake-on-LAN mode
In reply to Greg Kroah-HartmanFrom: Florian Fainelli <[email protected]>
[ Upstream commit 263a425a482fc495d6d3f9a29b9103a664c38b69 ]
After a number of suspend and resume cycles, it is possible for the RBUF to be stuck in Wake-on-LAN mode, despite the MPD enable bit being cleared which instructed the RBUF to exit that mode.
Avoid creating that problematic condition by clearing the RX_EN and TX_EN bits in the UniMAC prior to disable the Magic Packet Detector logic which is guaranteed to make the RBUF exit Wake-on-LAN mode.
--- drivers/net/ethernet/broadcom/bcmsysport.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/ethernet/broadcom/bcmsysport.c +3 -0
@@ -2728,6 +2728,9 @@ static int __maybe_unused bcm_sysport_reumac_reset (priv); +/* Disable the UniMAC RX/TX */ +umac_enable_set (priv,CMD_RX_EN |CMD_TX_EN ,0 ); +/* We may have been suspended and never received a WOL event that * would turn off MPD detection, take care of that now */
Greg Kroah-Hartman
maintainerPATCH 273/309 net/mlx5: IPsec, Fix esp modify function attribute
In reply to Greg Kroah-HartmanFrom: Raed Salem <[email protected]>
[ Upstream commit 0dc2c534f17c05bed0622b37a744bc38b48ca88a ]
The function mlx5_fpga_esp_validate_xfrm_attrs is wrongly used with negative negation as zero value indicates success but it used as failure return value instead.
Fix by remove the unary not negation operator.
--- drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c +1 -1
@@ -1478,7 +1478,7 @@ int mlx5_fpga_esp_modify_xfrm(struct mlxif (!memcmp (&xfrm->attrs, attrs,sizeof (xfrm->attrs)))return 0 ; -if (!mlx5_fpga_esp_validate_xfrm_attrs (mdev, attrs)) { +if (mlx5_fpga_esp_validate_xfrm_attrs (mdev, attrs)) {mlx5_core_warn (mdev,"Tried to create an esp with unsupported attrs\n" );return -EOPNOTSUPP ; }
Greg Kroah-Hartman
maintainerPATCH 274/309 net/mlx5: IPsec, fix memory leak at mlx5_fpga_ipsec_delete_sa_ctx
In reply to Greg Kroah-HartmanFrom: Raed Salem <[email protected]>
[ Upstream commit 08db2cf577487f5123aebcc2f913e0b8a2c14b43 ]
SA context is allocated at mlx5_fpga_ipsec_create_sa_ctx, however the counterpart mlx5_fpga_ipsec_delete_sa_ctx function nullifies sa_ctx pointer without freeing the memory allocated, hence the memory leak.
Fix by free SA context when the SA is released.
--- drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c +1 -0
@@ -850,6 +850,7 @@ void mlx5_fpga_ipsec_delete_sa_ctx(voidmutex_lock (&fpga_xfrm->lock);if (!--fpga_xfrm->num_rules) {mlx5_fpga_ipsec_release_sa_ctx (fpga_xfrm->sa_ctx); +kfree (fpga_xfrm->sa_ctx); fpga_xfrm->sa_ctx =NULL ; }mutex_unlock (&fpga_xfrm->lock);
Greg Kroah-Hartman
maintainerPATCH 275/309 net: macb: Remove unnecessary alignment check for TSO
In reply to Greg Kroah-HartmanFrom: Harini Katakam <[email protected]>
[ Upstream commit 41c1ef978c8d0259c6636e6d2d854777e92650eb ]
The IP TSO implementation does NOT require the length to be a multiple of 8. That is only a requirement for UFO as per IP documentation. Hence, exit macb_features_check function in the beginning if the protocol is not UDP. Only when it is UDP, proceed further to the alignment checks. Update comments to reflect the same. Also remove dead code checking for protocol TCP when calculating header length.
--- drivers/net/ethernet/cadence/macb_main.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
drivers/net/ethernet/cadence/macb_main.c +3 -5
@@ -1664,16 +1664,14 @@ static netdev_features_t macb_features_c/* Validate LSO compatibility */ -/* there is only one buffer */ -if (!skb_is_nonlinear (skb)) +/* there is only one buffer or protocol is not UDP */ +if (!skb_is_nonlinear (skb) || (ip_hdr (skb)->protocol !=IPPROTO_UDP ))return features;/* length of header */ hdrlen =skb_transport_offset (skb); -if (ip_hdr (skb)->protocol ==IPPROTO_TCP ) - hdrlen +=tcp_hdrlen (skb); -/* For LSO: +/* For UFO only: * When software supplies two or more payload buffers all payload buffers * apart from the last must be a multiple of 8 bytes in size. */
Greg Kroah-Hartman
maintainerPATCH 276/309 net: macb: Limit maximum GEM TX length in TSO
In reply to Greg Kroah-HartmanFrom: Harini Katakam <[email protected]>
[ Upstream commit f822e9c4ffa511a5c681cf866287d9383a3b6f1b ]
GEM_MAX_TX_LEN currently resolves to 0x3FF8 for any IP version supporting TSO with full 14bits of length field in payload descriptor. But an IP errata causes false amba_error (bit 6 of ISR) when length in payload descriptors is specified above 16387. The error occurs because the DMA falsely concludes that there is not enough space in SRAM for incoming payload. These errors were observed continuously under stress of large packets using iperf on a version where SRAM was 16K for each queue. This errata will be documented shortly and affects all versions since TSO functionality was added. Hence limit the max length to 0x3FC0 (rounded).
--- drivers/net/ethernet/cadence/macb_main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/net/ethernet/cadence/macb_main.c +5 -1
@@ -73,7 +73,11 @@ struct sifive_fu540_macb_mgmt {/* Max length of transmit frame must be a multiple of 8 bytes */ #define MACB_TX_LEN_ALIGN 8#define MACB_MAX_TX_LEN ((unsigned int)((1 << MACB_TX_FRMLEN_SIZE) - 1) & ~((unsigned int)(MACB_TX_LEN_ALIGN - 1))) -#define GEM_MAX_TX_LEN ((unsigned int)((1 << GEM_TX_FRMLEN_SIZE) - 1) & ~((unsigned int)(MACB_TX_LEN_ALIGN - 1))) +/* Limit maximum TX length as per Cadence TSO errata. This is to avoid a +* false amba_error in TX path from the DMA assuming there is not enough +* space in the SRAM (16KB) even when there is. +*/ +#define GEM_MAX_TX_LEN (unsigned int)(0x3FC0)#define GEM_MTU_MIN_SIZE ETH_MIN_MTU#define MACB_NETIF_LSO NETIF_F_TSO
Greg Kroah-Hartman
maintainerPATCH 277/309 taprio: Fix enabling offload with wrong number of traffic classes
In reply to Greg Kroah-HartmanFrom: Vinicius Costa Gomes <[email protected]>
[ Upstream commit 5652e63df3303c2a702bac25fbf710b9cb64dfba ]
If the driver implementing taprio offloading depends on the value of the network device number of traffic classes (dev->num_tc) for whatever reason, it was going to receive the value zero. The value was only set after the offloading function is called.
So, moving setting the number of traffic classes to before the offloading function is called fixes this issue. This is safe because this only happens when taprio is instantiated (we don't allow this configuration to be changed without first removing taprio).
--- net/sched/sch_taprio.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
net/sched/sch_taprio.c +13 -13
@@ -1444,6 +1444,19 @@ static int taprio_change(struct Qdisc *staprio_set_picos_per_byte (dev, q); +if (mqprio) { +netdev_set_num_tc (dev, mqprio->num_tc); +for (i =0 ; i < mqprio->num_tc; i++) +netdev_set_tc_queue (dev, i, + mqprio->count[i], + mqprio->offset[i]); + +/* Always use supplied priority mappings */ +for (i =0 ; i <=TC_BITMASK ; i++) +netdev_set_prio_tc_map (dev, i, + mqprio->prio_tc_map[i]); + } +if (FULL_OFFLOAD_IS_ENABLED (taprio_flags)) err =taprio_enable_offload (dev, mqprio, q, new_admin, extack);else
@@ -1471,19 +1484,6 @@ static int taprio_change(struct Qdisc *s q->advance_timer.function = advance_sched; } -if (mqprio) { -netdev_set_num_tc (dev, mqprio->num_tc); -for (i =0 ; i < mqprio->num_tc; i++) -netdev_set_tc_queue (dev, i, - mqprio->count[i], - mqprio->offset[i]); - -/* Always use supplied priority mappings */ -for (i =0 ; i <=TC_BITMASK ; i++) -netdev_set_prio_tc_map (dev, i, - mqprio->prio_tc_map[i]); - } -if (FULL_OFFLOAD_IS_ENABLED (taprio_flags)) { q->dequeue = taprio_dequeue_offload; q->peek = taprio_peek_offload;
Greg Kroah-Hartman
maintainerPATCH 278/309 taprio: Fix still allowing changing the flags during runtime
In reply to Greg Kroah-HartmanFrom: Vinicius Costa Gomes <[email protected]>
[ Upstream commit a9d6227436f32142209f4428f2dc616761485112 ]
Because 'q->flags' starts as zero, and zero is a valid value, we aren't able to detect the transition from zero to something else during "runtime".
The solution is to initialize 'q->flags' with an invalid value, so we can detect if 'q->flags' was set by the user or not.
To better solidify the behavior, 'flags' handling is moved to a separate function. The behavior is:
- 'flags' if unspecified by the user, is assumed to be zero;
- 'flags' cannot change during "runtime" (i.e. a change() request cannot modify it);
With this new function we can remove taprio_flags, which should reduce the risk of future accidents.
Allowing flags to be changed was causing the following RCU stall:
[ 1730.558249] rcu: INFO: rcu_preempt detected stalls on CPUs/tasks: [ 1730.558258] rcu: 6-...0: (190 ticks this GP) idle=922/0/0x1 softirq=25580/25582 fqs=16250 [ 1730.558264] (detected by 2, t=65002 jiffies, g=33017, q=81) [ 1730.558269] Sending NMI from CPU 2 to CPUs 6: [ 1730.559277] NMI backtrace for cpu 6 [ 1730.559277] CPU: 6 PID: 0 Comm: swapper/6 Tainted: G E 5.5.0-rc6+ #35 [ 1730.559278] Hardware name: Gigabyte Technology Co., Ltd. Z390 AORUS ULTRA/Z390 AORUS ULTRA-CF, BIOS F7 03/14/2019 [ 1730.559278] RIP: 0010:__hrtimer_run_queues+0xe2/0x440 [ 1730.559278] Code: 48 8b 43 28 4c 89 ff 48 8b 75 c0 48 89 45 c8 e8 f4 bb 7c 00 0f 1f 44 00 00 65 8b 05 40 31 f0 68 89 c0 48 0f a3 05 3e 5c 25 01 <0f> 82 fc 01 00 00 48 8b 45 c8 48 89 df ff d0 89 45 c8 0f 1f 44 00 [ 1730.559279] RSP: 0018:ffff9970802d8f10 EFLAGS: 00000083 [ 1730.559279] RAX: 0000000000000006 RBX: ffff8b31645bff38 RCX: 0000000000000000 [ 1730.559280] RDX: 0000000000000000 RSI: ffffffff9710f2ec RDI: ffffffff978daf0e [ 1730.559280] RBP: ffff9970802d8f68 R08: 0000000000000000 R09: 0000000000000000 [ 1730.559280] R10: 0000018336d7944e R11: 0000000000000001 R12: ffff8b316e39f9c0 [ 1730.559281] R13: ffff8b316e39f940 R14: ffff8b316e39f998 R15: ffff8b316e39f7c0 [ 1730.559281] FS: 0000000000000000(0000) GS:ffff8b316e380000(0000) knlGS:0000000000000000 [ 1730.559281] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1730.559281] CR2: 00007f1105303760 CR3: 0000000227210005 CR4: 00000000003606e0 [ 1730.559282] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 1730.559282] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 1730.559282] Call Trace: [ 1730.559282] <IRQ> [ 1730.559283] ? taprio_dequeue_soft+0x2d0/0x2d0 [sch_taprio] [ 1730.559283] hrtimer_interrupt+0x104/0x220 [ 1730.559283] ? irqtime_account_irq+0x34/0xa0 [ 1730.559283] smp_apic_timer_interrupt+0x6d/0x230 [ 1730.559284] apic_timer_interrupt+0xf/0x20 [ 1730.559284] </IRQ> [ 1730.559284] RIP: 0010:cpu_idle_poll+0x35/0x1a0 [ 1730.559285] Code: 88 82 ff 65 44 8b 25 12 7d 73 68 0f 1f 44 00 00 e8 90 c3 89 ff fb 65 48 8b 1c 25 c0 7e 01 00 48 8b 03 a8 08 74 0b eb 1c f3 90 <48> 8b 03 a8 08 75 13 8b 05 be a8 a8 00 85 c0 75 ed e8 75 48 84 ff [ 1730.559285] RSP: 0018:ffff997080137ea8 EFLAGS: 00000202 ORIG_RAX: ffffffffffffff13 [ 1730.559285] RAX: 0000000000000001 RBX: ffff8b316bc3c580 RCX: 0000000000000000 [ 1730.559286] RDX: 0000000000000001 RSI: 000000002819aad9 RDI: ffffffff978da730 [ 1730.559286] RBP: ffff997080137ec0 R08: 0000018324a6d387 R09: 0000000000000000 [ 1730.559286] R10: 0000000000000400 R11: 0000000000000001 R12: 0000000000000006 [ 1730.559286] R13: ffff8b316bc3c580 R14: 0000000000000000 R15: 0000000000000000 [ 1730.559287] ? cpu_idle_poll+0x20/0x1a0 [ 1730.559287] ? cpu_idle_poll+0x20/0x1a0 [ 1730.559287] do_idle+0x4d/0x1f0 [ 1730.559287] ? complete+0x44/0x50 [ 1730.559288] cpu_startup_entry+0x1b/0x20 [ 1730.559288] start_secondary+0x142/0x180 [ 1730.559288] secondary_startup_64+0xb6/0xc0 [ 1776.686313] nvme nvme0: I/O 96 QID 1 timeout, completion polled
--- net/sched/sch_taprio.c | 61 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 20 deletions(-)
net/sched/sch_taprio.c +41 -20
@@ -31,6 +31,7 @@ static DEFINE_SPINLOCK(taprio_list_lock)#define TXTIME_ASSIST_IS_ENABLED (flags) ((flags) & TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST)#define FULL_OFFLOAD_IS_ENABLED (flags) ((flags) & TCA_TAPRIO_ATTR_FLAG_FULL_OFFLOAD) +#define TAPRIO_FLAGS_INVALID U32_MAXstruct sched_entry {struct list_head list;
@@ -1367,6 +1368,33 @@ static int taprio_mqprio_cmp(const strucreturn 0 ; } +/* The semantics of the 'flags' argument in relation to 'change()' +* requests, are interpreted following two rules (which are applied in +* this order): (1) an omitted 'flags' argument is interpreted as +* zero; (2) the 'flags' of a "running" taprio instance cannot be +* changed. +*/ +static int taprio_new_flags (const struct nlattr *attr,u32 old, +struct netlink_ext_ack *extack) +{ +u32 new =0 ; + +if (attr) + new =nla_get_u32 (attr); + +if (old !=TAPRIO_FLAGS_INVALID && old != new) { +NL_SET_ERR_MSG_MOD (extack,"Changing 'flags' of a running schedule is not supported" ); +return -EOPNOTSUPP ; + } + +if (!taprio_flags_valid (new)) { +NL_SET_ERR_MSG_MOD (extack,"Specified 'flags' are not valid" ); +return -EINVAL ; + } + +return new; +} +static int taprio_change (struct Qdisc *sch,struct nlattr *opt,struct netlink_ext_ack *extack) {
@@ -1375,7 +1403,6 @@ static int taprio_change(struct Qdisc *sstruct taprio_sched *q =qdisc_priv (sch);struct net_device *dev =qdisc_dev (sch);struct tc_mqprio_qopt *mqprio =NULL ; -u32 taprio_flags =0 ;unsigned long flags;ktime_t start;int i, err;
@@ -1388,21 +1415,14 @@ static int taprio_change(struct Qdisc *sif (tb[TCA_TAPRIO_ATTR_PRIOMAP ]) mqprio =nla_data (tb[TCA_TAPRIO_ATTR_PRIOMAP ]); -if (tb[TCA_TAPRIO_ATTR_FLAGS ]) { - taprio_flags =nla_get_u32 (tb[TCA_TAPRIO_ATTR_FLAGS ]); - -if (q->flags !=0 && q->flags != taprio_flags) { -NL_SET_ERR_MSG_MOD (extack,"Changing 'flags' of a running schedule is not supported" ); -return -EOPNOTSUPP ; - }else if (!taprio_flags_valid (taprio_flags)) { -NL_SET_ERR_MSG_MOD (extack,"Specified 'flags' are not valid" ); -return -EINVAL ; - } + err =taprio_new_flags (tb[TCA_TAPRIO_ATTR_FLAGS ], + q->flags, extack); +if (err <0 ) +return err; - q->flags = taprio_flags; - } + q->flags = err; - err =taprio_parse_mqprio_opt (dev, mqprio, extack, taprio_flags); + err =taprio_parse_mqprio_opt (dev, mqprio, extack, q->flags);if (err <0 )return err;
@@ -1457,7 +1477,7 @@ static int taprio_change(struct Qdisc *s mqprio->prio_tc_map[i]); } -if (FULL_OFFLOAD_IS_ENABLED (taprio_flags)) +if (FULL_OFFLOAD_IS_ENABLED (q->flags)) err =taprio_enable_offload (dev, mqprio, q, new_admin, extack);else err =taprio_disable_offload (dev, q, extack);
@@ -1477,14 +1497,14 @@ static int taprio_change(struct Qdisc *s q->txtime_delay =nla_get_u32 (tb[TCA_TAPRIO_ATTR_TXTIME_DELAY ]); } -if (!TXTIME_ASSIST_IS_ENABLED (taprio_flags) && - !FULL_OFFLOAD_IS_ENABLED (taprio_flags) && +if (!TXTIME_ASSIST_IS_ENABLED (q->flags) && + !FULL_OFFLOAD_IS_ENABLED (q->flags) && !hrtimer_active (&q->advance_timer)) {hrtimer_init (&q->advance_timer, q->clockid,HRTIMER_MODE_ABS ); q->advance_timer.function = advance_sched; } -if (FULL_OFFLOAD_IS_ENABLED (taprio_flags)) { +if (FULL_OFFLOAD_IS_ENABLED (q->flags)) { q->dequeue = taprio_dequeue_offload; q->peek = taprio_peek_offload; }else {
@@ -1501,7 +1521,7 @@ static int taprio_change(struct Qdisc *s goto unlock; } -if (TXTIME_ASSIST_IS_ENABLED (taprio_flags)) { +if (TXTIME_ASSIST_IS_ENABLED (q->flags)) {setup_txtime (q, new_admin, start);if (!oper) {
@@ -1528,7 +1548,7 @@ static int taprio_change(struct Qdisc *sspin_unlock_irqrestore (&q->current_entry_lock, flags); -if (FULL_OFFLOAD_IS_ENABLED (taprio_flags)) +if (FULL_OFFLOAD_IS_ENABLED (q->flags))taprio_offload_config_changed (q); }
@@ -1597,6 +1617,7 @@ static int taprio_init(struct Qdisc *sch* and get the valid one on taprio_change(). */ q->clockid =-1 ; + q->flags =TAPRIO_FLAGS_INVALID ;spin_lock (&taprio_list_lock);list_add (&q->taprio_list, &taprio_list);
Greg Kroah-Hartman
maintainerPATCH 279/309 taprio: Add missing policy validation for flags
In reply to Greg Kroah-HartmanFrom: Vinicius Costa Gomes <[email protected]>
[ Upstream commit 49c684d79cfdc3032344bf6f3deeea81c4efedbf ]
netlink policy validation for the 'flags' argument was missing.
--- net/sched/sch_taprio.c | 1 + 1 file changed, 1 insertion(+)
net/sched/sch_taprio.c +1 -0
@@ -767,6 +767,7 @@ static const struct nla_policy taprio_po [TCA_TAPRIO_ATTR_SCHED_CLOCKID] = { .type = NLA_S32 }, [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME] = { .type = NLA_S64 }, [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION] = { .type = NLA_S64 }, + [TCA_TAPRIO_ATTR_FLAGS] = { .type = NLA_U32 }, }; static int fill_sched_entry(struct nlattr **tb, struct sched_entry *entry,
Greg Kroah-Hartman
maintainerPATCH 280/309 taprio: Use taprio_reset_tc() to reset Traffic Classes configuration
In reply to Greg Kroah-HartmanFrom: Vinicius Costa Gomes <[email protected]>
[ Upstream commit 7c16680a08ee1e444a67d232c679ccf5b30fad16 ]
When destroying the current taprio instance, which can happen when the creation of one fails, we should reset the traffic class configuration back to the default state.
netdev_reset_tc() is a better way because in addition to setting the number of traffic classes to zero, it also resets the priority to traffic classes mapping to the default value.
--- net/sched/sch_taprio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/sch_taprio.c +1 -1
@@ -1588,7 +1588,7 @@ static void taprio_destroy(struct Qdisc } q->qdiscs =NULL ; -netdev_set_num_tc (dev,0 ); +netdev_reset_tc (dev);if (q->oper_sched)call_rcu (&q->oper_sched->rcu, taprio_free_sched_cb);
Greg Kroah-Hartman
maintainerPATCH 281/309 taprio: Fix dropping packets when using taprio + ETF offloading
In reply to Greg Kroah-HartmanFrom: Vinicius Costa Gomes <[email protected]>
[ Upstream commit bfabd41da34180d05382312533a3adc2e012dee0 ]
When using taprio offloading together with ETF offloading, configured like this, for example:
$ tc qdisc replace dev $IFACE parent root handle 100 taprio \
num_tc 4 \
map 2 2 1 0 3 2 2 2 2 2 2 2 2 2 2 2 \
queues 1@0 1@1 1@2 1@3 \
base-time $BASE_TIME \
sched-entry S 01 1000000 \
sched-entry S 0e 1000000 \
flags 0x2$ tc qdisc replace dev $IFACE parent 100:1 etf \
offload delta 300000 clockid CLOCK_TAIDuring enqueue, it works out that the verification added for the "txtime" assisted mode is run when using taprio + ETF offloading, the only thing missing is initializing the 'next_txtime' of all the cycle entries. (if we don't set 'next_txtime' all packets from SO_TXTIME sockets are dropped)
--- net/sched/sch_taprio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/sched/sch_taprio.c +2 -2
@@ -1522,9 +1522,9 @@ static int taprio_change(struct Qdisc *s goto unlock; } -if (TXTIME_ASSIST_IS_ENABLED (q->flags)) { -setup_txtime (q, new_admin, start); +setup_txtime (q, new_admin, start); +if (TXTIME_ASSIST_IS_ENABLED (q->flags)) {if (!oper) {rcu_assign_pointer (q->oper_sched, new_admin); err =0 ;
Greg Kroah-Hartman
maintainerPATCH 282/309 ipv6/addrconf: fix potential NULL deref in inet6_set_link_af()
In reply to Greg Kroah-HartmanFrom: Eric Dumazet <[email protected]>
[ Upstream commit db3fa271022dacb9f741b96ea4714461a8911bb9 ]
__in6_dev_get(dev) called from inet6_set_link_af() can return NULL.
The needed check has been recently removed, let's add it back.
While do_setlink() does call validate_linkmsg() :
...
err = validate_linkmsg(dev, tb); /* OK at this point */
...
It is possible that the following call happening before the ->set_link_af() removes IPv6 if MTU is less than 1280 :
if (tb[IFLA_MTU]) {
err = dev_set_mtu_ext(dev, nla_get_u32(tb[IFLA_MTU]), extack);
if (err < 0)
goto errout;
status |= DO_SETLINK_MODIFIED;
}...
if (tb[IFLA_AF_SPEC]) {
...
err = af_ops->set_link_af(dev, af);
->inet6_set_link_af() // CRASH because idev is NULLPlease note that IPv4 is immune to the bug since inet_set_link_af() does :
struct in_device *in_dev = __in_dev_get_rcu(dev);
if (!in_dev)
return -EAFNOSUPPORT;
This problem has been mentioned in commit cf7afbfeb8ce ("rtnl: make link af-specific updates atomic") changelog :
This method is not fail proof, while it is currently sufficient to make set_link_af() inerrable and thus 100% atomic, the validation function method will not be able to detect all error scenarios in the future, there will likely always be errors depending on states which are f.e. not protected by rtnl_mutex and thus may change between validation and setting.
IPv6: ADDRCONF(NETDEV_CHANGE): lo: link becomes ready
general protection fault, probably for non-canonical address 0xdffffc0000000056: 0000 [#1] PREEMPT SMP KASAN KASAN: null-ptr-deref in range [0x00000000000002b0-0x00000000000002b7] CPU: 0 PID: 9698 Comm: syz-executor712 Not tainted 5.5.0-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:inet6_set_link_af+0x66e/0xae0 net/ipv6/addrconf.c:5733 Code: 38 d0 7f 08 84 c0 0f 85 20 03 00 00 48 8d bb b0 02 00 00 45 0f b6 64 24 04 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <0f> b6 04 02 84 c0 74 08 3c 03 0f 8e 1a 03 00 00 44 89 a3 b0 02 00 RSP: 0018:ffffc90005b06d40 EFLAGS: 00010206 RAX: dffffc0000000000 RBX: 0000000000000000 RCX: ffffffff86df39a6 RDX: 0000000000000056 RSI: ffffffff86df3e74 RDI: 00000000000002b0 RBP: ffffc90005b06e70 R08: ffff8880a2ac0380 R09: ffffc90005b06db0 R10: fffff52000b60dbe R11: ffffc90005b06df7 R12: 0000000000000000 R13: 0000000000000000 R14: ffff8880a1fcc424 R15: dffffc0000000000 FS: 0000000000c46880(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055f0494ca0d0 CR3: 000000009e4ac000 CR4: 00000000001406f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: do_setlink+0x2a9f/0x3720 net/core/rtnetlink.c:2754 rtnl_group_changelink net/core/rtnetlink.c:3103 [inline] __rtnl_newlink+0xdd1/0x1790 net/core/rtnetlink.c:3257 rtnl_newlink+0x69/0xa0 net/core/rtnetlink.c:3377 rtnetlink_rcv_msg+0x45e/0xaf0 net/core/rtnetlink.c:5438 netlink_rcv_skb+0x177/0x450 net/netlink/af_netlink.c:2477 rtnetlink_rcv+0x1d/0x30 net/core/rtnetlink.c:5456 netlink_unicast_kernel net/netlink/af_netlink.c:1302 [inline] netlink_unicast+0x59e/0x7e0 net/netlink/af_netlink.c:1328 netlink_sendmsg+0x91c/0xea0 net/netlink/af_netlink.c:1917 sock_sendmsg_nosec net/socket.c:652 [inline] sock_sendmsg+0xd7/0x130 net/socket.c:672 ____sys_sendmsg+0x753/0x880 net/socket.c:2343 ___sys_sendmsg+0x100/0x170 net/socket.c:2397 __sys_sendmsg+0x105/0x1d0 net/socket.c:2430 __do_sys_sendmsg net/socket.c:2439 [inline] __se_sys_sendmsg net/socket.c:2437 [inline] __x64_sys_sendmsg+0x78/0xb0 net/socket.c:2437 do_syscall_64+0xfa/0x790 arch/x86/entry/common.c:294 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x4402e9 Code: 18 89 d0 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 fb 13 fc ff c3 66 2e 0f 1f 84 00 00 00 00 RSP: 002b:00007fffd62fbcf8 EFLAGS: 00000246 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 00000000004002c8 RCX: 00000000004402e9 RDX: 0000000000000000 RSI: 0000000020000080 RDI: 0000000000000003 RBP: 00000000006ca018 R08: 0000000000000008 R09: 00000000004002c8 R10: 0000000000000005 R11: 0000000000000246 R12: 0000000000401b70 R13: 0000000000401c00 R14: 0000000000000000 R15: 0000000000000000 Modules linked in: ---[ end trace cfa7664b8fdcdff3 ]--- RIP: 0010:inet6_set_link_af+0x66e/0xae0 net/ipv6/addrconf.c:5733 Code: 38 d0 7f 08 84 c0 0f 85 20 03 00 00 48 8d bb b0 02 00 00 45 0f b6 64 24 04 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <0f> b6 04 02 84 c0 74 08 3c 03 0f 8e 1a 03 00 00 44 89 a3 b0 02 00 RSP: 0018:ffffc90005b06d40 EFLAGS: 00010206 RAX: dffffc0000000000 RBX: 0000000000000000 RCX: ffffffff86df39a6 RDX: 0000000000000056 RSI: ffffffff86df3e74 RDI: 00000000000002b0 RBP: ffffc90005b06e70 R08: ffff8880a2ac0380 R09: ffffc90005b06db0 R10: fffff52000b60dbe R11: ffffc90005b06df7 R12: 0000000000000000 R13: 0000000000000000 R14: ffff8880a1fcc424 R15: dffffc0000000000 FS: 0000000000c46880(0000) GS:ffff8880ae900000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000020000004 CR3: 000000009e4ac000 CR4: 00000000001406e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
--- net/ipv6/addrconf.c | 3 +++ 1 file changed, 3 insertions(+)
net/ipv6/addrconf.c +3 -0
@@ -5719,6 +5719,9 @@ static int inet6_set_link_af(struct net_struct nlattr *tb[IFLA_INET6_MAX +1 ];int err; +if (!idev) +return -EAFNOSUPPORT ; +if (nla_parse_nested_deprecated (tb,IFLA_INET6_MAX , nla,NULL ,NULL ) <0 )BUG ();
Greg Kroah-Hartman
maintainerPATCH 283/309 qed: Fix timestamping issue for L2 unicast ptp packets.
In reply to Greg Kroah-HartmanFrom: Sudarsana Reddy Kalluru <[email protected]>
[ Upstream commit 0202d293c2faecba791ba4afc5aec086249c393d ]
commit cedeac9df4b8 ("qed: Add support for Timestamping the unicast PTP packets.") handles the timestamping of L4 ptp packets only. This patch adds driver changes to detect/timestamp both L2/L4 unicast PTP packets.
--- drivers/net/ethernet/qlogic/qed/qed_ptp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/qlogic/qed/qed_ptp.c +2 -2
@@ -44,8 +44,8 @@/* Add/subtract the Adjustment_Value when making a Drift adjustment */ #define QED_DRIFT_CNTR_DIRECTION_SHIFT 31#define QED_TIMESTAMP_MASK BIT(16) -/* Param mask for Hardware to detect/timestamp the unicast PTP packets */ -#define QED_PTP_UCAST_PARAM_MASK 0xF +/* Param mask for Hardware to detect/timestamp the L2/L4 unicast PTP packets */ +#define QED_PTP_UCAST_PARAM_MASK 0x70Fstatic enum qed_resc_lock qed_ptcdev_to_resc (struct qed_hwfn *p_hwfn) {
Greg Kroah-Hartman
maintainerPATCH 284/309 drop_monitor: Do not cancel uninitialized work item
In reply to Greg Kroah-HartmanFrom: Ido Schimmel <[email protected]>
[ Upstream commit dfa7f709596be5ca46c070d4f8acbb344322056a ]
Drop monitor uses a work item that takes care of constructing and sending netlink notifications to user space. In case drop monitor never started to monitor, then the work item is uninitialized and not associated with a function.
Therefore, a stop command from user space results in canceling an uninitialized work item which leads to the following warning [1].
Fix this by not processing a stop command if drop monitor is not currently monitoring.
[1]
[ 31.735402] ------------[ cut here ]------------ [ 31.736470] WARNING: CPU: 0 PID: 143 at kernel/workqueue.c:3032 __flush_work+0x89f/0x9f0 ... [ 31.738120] CPU: 0 PID: 143 Comm: dwdump Not tainted 5.5.0-custom-09491-g16d4077796b8 #727 [ 31.741968] RIP: 0010:__flush_work+0x89f/0x9f0 ... [ 31.760526] Call Trace: [ 31.771689] __cancel_work_timer+0x2a6/0x3b0 [ 31.776809] net_dm_cmd_trace+0x300/0xef0 [ 31.777549] genl_rcv_msg+0x5c6/0xd50 [ 31.781005] netlink_rcv_skb+0x13b/0x3a0 [ 31.784114] genl_rcv+0x29/0x40 [ 31.784720] netlink_unicast+0x49f/0x6a0 [ 31.787148] netlink_sendmsg+0x7cf/0xc80 [ 31.790426] ____sys_sendmsg+0x620/0x770 [ 31.793458] ___sys_sendmsg+0xfd/0x170 [ 31.802216] __sys_sendmsg+0xdf/0x1a0 [ 31.806195] do_syscall_64+0xa0/0x540 [ 31.806885] entry_SYSCALL_64_after_hwframe+0x49/0xbe
--- net/core/drop_monitor.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/core/drop_monitor.c +3 -1
@@ -1004,8 +1004,10 @@ static void net_dm_hw_monitor_stop(struc {int cpu; -if (!monitor_hw) +if (!monitor_hw) {NL_SET_ERR_MSG_MOD (extack,"Hardware monitoring already disabled" ); +return ; + } monitor_hw = false;