Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'vfs-5.4-merge-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull swap access updates from Darrick Wong:
"Prohibit writing to active swap files and swap partitions.

There's no non-malicious use case for allowing userspace to scribble
on storage that the kernel thinks it owns"

* tag 'vfs-5.4-merge-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
vfs: don't allow writes to swap files
mm: set S_SWAPFILE on blockdev swap devices

+52 -18
+3
fs/block_dev.c
··· 1972 1972 if (bdev_read_only(I_BDEV(bd_inode))) 1973 1973 return -EPERM; 1974 1974 1975 + if (IS_SWAPFILE(bd_inode)) 1976 + return -ETXTBSY; 1977 + 1975 1978 if (!iov_iter_count(from)) 1976 1979 return 0; 1977 1980
+11
include/linux/fs.h
··· 3565 3565 fa->fsx_xflags = xflags; 3566 3566 } 3567 3567 3568 + /* 3569 + * Flush file data before changing attributes. Caller must hold any locks 3570 + * required to prevent further writes to this file until we're done setting 3571 + * flags. 3572 + */ 3573 + static inline int inode_drain_writes(struct inode *inode) 3574 + { 3575 + inode_dio_wait(inode); 3576 + return filemap_write_and_wait(inode->i_mapping); 3577 + } 3578 + 3568 3579 #endif /* _LINUX_FS_H */
+3
mm/filemap.c
··· 2988 2988 loff_t count; 2989 2989 int ret; 2990 2990 2991 + if (IS_SWAPFILE(inode)) 2992 + return -ETXTBSY; 2993 + 2991 2994 if (!iov_iter_count(from)) 2992 2995 return 0; 2993 2996
+4
mm/memory.c
··· 2196 2196 2197 2197 vmf->flags = FAULT_FLAG_WRITE|FAULT_FLAG_MKWRITE; 2198 2198 2199 + if (vmf->vma->vm_file && 2200 + IS_SWAPFILE(vmf->vma->vm_file->f_mapping->host)) 2201 + return VM_FAULT_SIGBUS; 2202 + 2199 2203 ret = vmf->vma->vm_ops->page_mkwrite(vmf); 2200 2204 /* Restore original flags so that caller is not surprised */ 2201 2205 vmf->flags = old_flags;
+6 -2
mm/mmap.c
··· 1483 1483 case MAP_SHARED_VALIDATE: 1484 1484 if (flags & ~flags_mask) 1485 1485 return -EOPNOTSUPP; 1486 - if ((prot&PROT_WRITE) && !(file->f_mode&FMODE_WRITE)) 1487 - return -EACCES; 1486 + if (prot & PROT_WRITE) { 1487 + if (!(file->f_mode & FMODE_WRITE)) 1488 + return -EACCES; 1489 + if (IS_SWAPFILE(file->f_mapping->host)) 1490 + return -ETXTBSY; 1491 + } 1488 1492 1489 1493 /* 1490 1494 * Make sure we don't allow writing to an append-only
+25 -16
mm/swapfile.c
··· 2368 2368 * requirements, they are simply tossed out - we will never use those blocks 2369 2369 * for swapping. 2370 2370 * 2371 - * For S_ISREG swapfiles we set S_SWAPFILE across the life of the swapon. This 2372 - * prevents root from shooting her foot off by ftruncating an in-use swapfile, 2373 - * which will scribble on the fs. 2371 + * For all swap devices we set S_SWAPFILE across the life of the swapon. This 2372 + * prevents users from writing to the swap device, which will corrupt memory. 2374 2373 * 2375 2374 * The amount of disk space which a single swap extent represents varies. 2376 2375 * Typically it is in the 1-4 megabyte range. So we can have hundreds of ··· 2660 2661 inode = mapping->host; 2661 2662 if (S_ISBLK(inode->i_mode)) { 2662 2663 struct block_device *bdev = I_BDEV(inode); 2664 + 2663 2665 set_blocksize(bdev, old_block_size); 2664 2666 blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL); 2665 - } else { 2666 - inode_lock(inode); 2667 - inode->i_flags &= ~S_SWAPFILE; 2668 - inode_unlock(inode); 2669 2667 } 2668 + 2669 + inode_lock(inode); 2670 + inode->i_flags &= ~S_SWAPFILE; 2671 + inode_unlock(inode); 2670 2672 filp_close(swap_file, NULL); 2671 2673 2672 2674 /* ··· 2890 2890 p->flags |= SWP_BLKDEV; 2891 2891 } else if (S_ISREG(inode->i_mode)) { 2892 2892 p->bdev = inode->i_sb->s_bdev; 2893 - inode_lock(inode); 2894 - if (IS_SWAPFILE(inode)) 2895 - return -EBUSY; 2896 - } else 2897 - return -EINVAL; 2893 + } 2894 + 2895 + inode_lock(inode); 2896 + if (IS_SWAPFILE(inode)) 2897 + return -EBUSY; 2898 2898 2899 2899 return 0; 2900 2900 } ··· 3275 3275 if (error) 3276 3276 goto bad_swap; 3277 3277 3278 + /* 3279 + * Flush any pending IO and dirty mappings before we start using this 3280 + * swap device. 3281 + */ 3282 + inode->i_flags |= S_SWAPFILE; 3283 + error = inode_drain_writes(inode); 3284 + if (error) { 3285 + inode->i_flags &= ~S_SWAPFILE; 3286 + goto bad_swap; 3287 + } 3288 + 3278 3289 mutex_lock(&swapon_mutex); 3279 3290 prio = -1; 3280 3291 if (swap_flags & SWAP_FLAG_PREFER) ··· 3306 3295 atomic_inc(&proc_poll_event); 3307 3296 wake_up_interruptible(&proc_poll_wait); 3308 3297 3309 - if (S_ISREG(inode->i_mode)) 3310 - inode->i_flags |= S_SWAPFILE; 3311 3298 error = 0; 3312 3299 goto out; 3313 3300 bad_swap: ··· 3327 3318 if (inced_nr_rotate_swap) 3328 3319 atomic_dec(&nr_rotate_swap); 3329 3320 if (swap_file) { 3330 - if (inode && S_ISREG(inode->i_mode)) { 3321 + if (inode) { 3331 3322 inode_unlock(inode); 3332 3323 inode = NULL; 3333 3324 } ··· 3340 3331 } 3341 3332 if (name) 3342 3333 putname(name); 3343 - if (inode && S_ISREG(inode->i_mode)) 3334 + if (inode) 3344 3335 inode_unlock(inode); 3345 3336 if (!error) 3346 3337 enable_swap_slots_cache();