Re: [PATCH RFC v2 22/25] kmsan: unpoisoning buffers from devices etc.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Nov 7, 2019 at 2:00 PM Alexander Potapenko <glider@xxxxxxxxxx> wrote:
>
> On Tue, Nov 5, 2019 at 4:02 PM Alexander Potapenko <glider@xxxxxxxxxx> wrote:
> >
> > On Wed, Oct 30, 2019 at 3:38 PM Christoph Hellwig <hch@xxxxxx> wrote:
> > >
> > > On Wed, Oct 30, 2019 at 03:22:34PM +0100, glider@xxxxxxxxxx wrote:
> > > > When data is copied to memory from a device KMSAN should treat it as
> > > > initialized. In most cases it's enough to just unpoison the buffer that
> > > > is known to come from a device.
> > > > In the case with __do_page_cache_readahead() and bio_copy_user_iov() we
> > > > have to mark the whole pages as ignored by KMSAN, as it's not obvious
> > > > where these pages are read again.
> > >
> > > A lot of this looks pretty strange.  Why don't you instrument
> > > the dma_map / dma_sync infrastucture?  That should avoid most of the
> > > driver hooks.
> >
> > That's the exact reason I'm sending these patches: I simply don't know
> > the kernel code good enough.
> > May I ask you for some pointers?
> > My goal is to mark data copied from the device as initialized (by
> > calling kmsan_unpoison_shadow(ptr, size)), and, if possible, check
> > data that's about to be copied to device (by calling
> > kmsan_check_memory(ptr, size)).
> > My understanding is that:
> >  1. calls to dma_map_* and dma_sync_* with direction=DMA_FROM_DEVICE
> > denote that the corresponding kernel buffer can be marked as
> > initialized
> >  2. calls to dma_unmap_* and dma_sync_* with direction=DMA_TO_DEVICE
> > denote that the buffer will be copied to device (and must be checked
> > for being initialized)
> >  3. I need some translation table to find out the virtual address for
> > a given dma_addr_t
> > Does this sound reasonable?
> Initializing memory in dma_map_ still leaves out the reports as the one below.
> There seems to be a DMA access somewhere in blk_execute_rq(), but I
> fail to see why it's not covered.
>
> =============================================
> BUG: KMSAN: uninit-value in[<      none      >]
> sr_check_events+0x1091/0x1190 drivers/scsi/sr.c:246
>  CPU: 0 PID: 5 Comm: kworker/0:0 Not tainted 5.4.0-rc5+ #3266
>  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014
>  Workqueue: events_freezable_power_ disk_events_workfn
>  Call Trace:
>  [<     inline     >] __dump_stack lib/dump_stack.c:77
>  [<      none      >] dump_stack+0x196/0x1f0 lib/dump_stack.c:113
>  [<      none      >] kmsan_report+0x127/0x220 mm/kmsan/kmsan_report.c:108
>  [<      none      >] __msan_warning+0x73/0xe0 mm/kmsan/kmsan_instr.c:245
>  [<     inline     >] sr_get_events drivers/scsi/sr.c:213
>  [<      none      >] sr_check_events+0x1091/0x1190 drivers/scsi/sr.c:246
>  [<     inline     >] cdrom_update_events drivers/cdrom/cdrom.c:1476
>  [<      none      >] cdrom_check_events+0xc3/0x260 drivers/cdrom/cdrom.c:1486
>  [<      none      >] sr_block_check_events+0x3c4/0x670 drivers/scsi/sr.c:614
>  [<      none      >] disk_check_events+0x154/0x8b0 block/genhd.c:1855
>  [<      none      >] disk_events_workfn+0x47/0x50 block/genhd.c:1841
>  [<      none      >] process_one_work+0x1556/0x1ef0 kernel/workqueue.c:2269
> ...
>  Uninit was stored to memory at:
>  [<     inline     >] kmsan_save_stack_with_flags mm/kmsan/kmsan.c:151
>  [<      none      >] kmsan_internal_chain_origin+0xa3/0x160
> mm/kmsan/kmsan.c:319
>  [<      none      >] kmsan_memcpy_memmove_metadata+0x271/0x2e0
> mm/kmsan/kmsan.c:254
>  [<      none      >] kmsan_memcpy_metadata+0xb/0x10 mm/kmsan/kmsan.c:274
>  [<      none      >] __msan_memcpy+0x55/0x70 mm/kmsan/kmsan_instr.c:129
>  [<      none      >] bio_copy_kern_endio_read+0x467/0x990 block/bio.c:1543
>  [<      none      >] bio_endio+0xa36/0xbb0 block/bio.c:1850
>  [<     inline     >] req_bio_endio block/blk-core.c:242
>  [<      none      >] blk_update_request+0xd3c/0x20a0 block/blk-core.c:1462
>  [<      none      >] scsi_end_request+0x10b/0xeb0 drivers/scsi/scsi_lib.c:579
>  [<      none      >] scsi_io_completion+0x279/0x2660
> drivers/scsi/scsi_lib.c:963
>  [<      none      >] scsi_finish_command+0x6f9/0x720 drivers/scsi/scsi.c:228
>  [<      none      >] scsi_softirq_done+0x772/0x980 drivers/scsi/scsi_lib.c:1477
>  [<      none      >] blk_done_softirq+0x300/0x4f0 block/blk-softirq.c:37
>  [<      none      >] __do_softirq+0x311/0x83d kernel/softirq.c:293
> ...
>  Uninit was created at:
>  [<      none      >] kmsan_save_stack_with_flags+0x3f/0x90 mm/kmsan/kmsan.c:151
>  [<     inline     >] kmsan_internal_alloc_meta_for_pages
> mm/kmsan/kmsan_shadow.c:362
>  [<      none      >] kmsan_alloc_page+0x14e/0x360 mm/kmsan/kmsan_shadow.c:391
>  [<      none      >] __alloc_pages_nodemask+0x594e/0x6050 mm/page_alloc.c:4796
>  [<      none      >] alloc_pages_current+0x682/0x990 mm/mempolicy.c:2188
>  [<     inline     >] alloc_pages ./include/linux/gfp.h:511
>  [<      none      >] bio_copy_kern+0x4c5/0xed0 block/bio.c:1590
>  [<      none      >] blk_rq_map_kern+0x458/0x7e0 block/blk-map.c:237
>  [<      none      >] __scsi_execute+0x2cf/0xaf0 drivers/scsi/scsi_lib.c:265
>  [<     inline     >] scsi_execute_req ./include/scsi/scsi_device.h:451
>  [<     inline     >] sr_get_events drivers/scsi/sr.c:207
>  [<      none      >] sr_check_events+0x2ff/0x1190 drivers/scsi/sr.c:246
>  [<     inline     >] cdrom_update_events drivers/cdrom/cdrom.c:1476
>  [<      none      >] cdrom_check_events+0xc3/0x260 drivers/cdrom/cdrom.c:1486
>  [<      none      >] sr_block_check_events+0x3c4/0x670 drivers/scsi/sr.c:614
>  [<      none      >] disk_check_events+0x154/0x8b0 block/genhd.c:1855
>  [<      none      >] disk_events_workfn+0x47/0x50 block/genhd.c:1841
> =============================================

Turned out these reports were coming from reads from iomapped memory.
Unpoisoning those (in lib/iomap.c) in addition to DMA reads will
probably eliminate the need of ad-hoc annotations in device drivers.

> > I still don't understand how to handle DMA_BIDIRECTIONAL. Will it be
> > sane to assume that at each dma_{map,sync,unmap}_* call must always
> > check the memory range and then unpoison it?
> >
> > Thanks in advance
> >
> > --
> > Alexander Potapenko
> > Software Engineer
> >
> > Google Germany GmbH
> > Erika-Mann-Straße, 33
> > 80636 München
> >
> > Geschäftsführer: Paul Manicle, Halimah DeLaine Prado
> > Registergericht und -nummer: Hamburg, HRB 86891
> > Sitz der Gesellschaft: Hamburg
>
>
>
> --
> Alexander Potapenko
> Software Engineer
>
> Google Germany GmbH
> Erika-Mann-Straße, 33
> 80636 München
>
> Geschäftsführer: Paul Manicle, Halimah DeLaine Prado
> Registergericht und -nummer: Hamburg, HRB 86891
> Sitz der Gesellschaft: Hamburg



-- 
Alexander Potapenko
Software Engineer

Google Germany GmbH
Erika-Mann-Straße, 33
80636 München

Geschäftsführer: Paul Manicle, Halimah DeLaine Prado
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg





[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux