mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-16 21:35:07 +00:00
457f730825
It's possible the migration file is accessed after reset when it has been cleaned up, especially when it's initiated by the device. This is because the driver doesn't rip out the filep when cleaning up it only frees the related page structures and sets its local struct pds_vfio_lm_file pointer to NULL. This can cause a NULL pointer dereference, which is shown in the example below during a restore after a device initiated reset: BUG: kernel NULL pointer dereference, address: 000000000000000c PF: supervisor read access in kernel mode PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: 0000 [#1] PREEMPT SMP NOPTI RIP: 0010:pds_vfio_get_file_page+0x5d/0xf0 [pds_vfio_pci] [...] Call Trace: <TASK> pds_vfio_restore_write+0xf6/0x160 [pds_vfio_pci] vfs_write+0xc9/0x3f0 ? __fget_light+0xc9/0x110 ksys_write+0xb5/0xf0 __x64_sys_write+0x1a/0x20 do_syscall_64+0x38/0x90 entry_SYSCALL_64_after_hwframe+0x63/0xcd [...] Add a disabled flag to the driver's struct pds_vfio_lm_file that gets set during cleanup. Then make sure to check the flag when the migration file is accessed via its file_operations. By default this flag will be false as the memory for struct pds_vfio_lm_file is kzalloc'd, which means the struct pds_vfio_lm_file is enabled and accessible. Also, since the file_operations and driver's migration file cleanup happen under the protection of the same pds_vfio_lm_file.lock, using this flag is thread safe. Fixes: 8512ed256334 ("vfio/pds: Always clear the save/restore FDs on reset") Reviewed-by: Shannon Nelson <shannon.nelson@amd.com> Signed-off-by: Brett Creeley <brett.creeley@amd.com> Link: https://lore.kernel.org/r/20240308182149.22036-2-brett.creeley@amd.com Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
43 lines
1.2 KiB
C
43 lines
1.2 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/* Copyright(c) 2023 Advanced Micro Devices, Inc. */
|
|
|
|
#ifndef _LM_H_
|
|
#define _LM_H_
|
|
|
|
#include <linux/fs.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/scatterlist.h>
|
|
#include <linux/types.h>
|
|
|
|
#include <linux/pds/pds_common.h>
|
|
#include <linux/pds/pds_adminq.h>
|
|
|
|
struct pds_vfio_lm_file {
|
|
struct file *filep;
|
|
struct mutex lock; /* protect live migration data file */
|
|
u64 size; /* Size with valid data */
|
|
u64 alloc_size; /* Total allocated size. Always >= len */
|
|
void *page_mem; /* memory allocated for pages */
|
|
struct page **pages; /* Backing pages for file */
|
|
unsigned long long npages;
|
|
struct sg_table sg_table; /* SG table for backing pages */
|
|
struct pds_lm_sg_elem *sgl; /* DMA mapping */
|
|
dma_addr_t sgl_addr;
|
|
u16 num_sge;
|
|
struct scatterlist *last_offset_sg; /* Iterator */
|
|
unsigned int sg_last_entry;
|
|
unsigned long last_offset;
|
|
bool disabled;
|
|
};
|
|
|
|
struct pds_vfio_pci_device;
|
|
|
|
struct file *
|
|
pds_vfio_step_device_state_locked(struct pds_vfio_pci_device *pds_vfio,
|
|
enum vfio_device_mig_state next);
|
|
|
|
void pds_vfio_put_save_file(struct pds_vfio_pci_device *pds_vfio);
|
|
void pds_vfio_put_restore_file(struct pds_vfio_pci_device *pds_vfio);
|
|
|
|
#endif /* _LM_H_ */
|