Don't let userspace write to an active swap file because the kernel effectively has a long term lease on the storage and things could get seriously corrupted if we let this happen.
Unified · Split
| @@ -1978,6 +1978,9 @@ ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) · 1977 unmodified lines | ||
| 1978 | 1978 | if (bdev_read_only(I_BDEV(bd_inode))) |
| 1979 | 1979 | return -EPERM; |
| 1980 | 1980 | |
| 1981 | + if (IS_SWAPFILE(bd_inode)) | |
| 1982 | + return -ETXTBSY; | |
| 1983 | + | |
| 1981 | 1984 | if (!iov_iter_count(from)) |
| 1982 | 1985 | return 0; |
| 1983 | 1986 | |
| @@ -3547,4 +3547,15 @@ static inline void simple_fill_fsxattr(struct fsxattr *fa, __u32 xflags) · 3546 unmodified lines | ||
| 3547 | 3547 | fa->fsx_xflags = xflags; |
| 3548 | 3548 | } |
| 3549 | 3549 | |
| 3550 | +/* | |
| 3551 | + * Flush file data before changing attributes. Caller must hold any locks | |
| 3552 | + * required to prevent further writes to this file until we're done setting | |
| 3553 | + * flags. | |
| 3554 | + */ | |
| 3555 | +static inline int inode_drain_writes(struct inode *inode) | |
| 3556 | +{ | |
| 3557 | + inode_dio_wait(inode); | |
| 3558 | + return filemap_write_and_wait(inode->i_mapping); | |
| 3559 | +} | |
| 3560 | + | |
| 3550 | 3561 | #endif /* _LINUX_FS_H */ |
| @@ -2988,6 +2988,9 @@ inline ssize_t generic_write_checks(struct kiocb *iocb, struct iov_iter *from) · 2987 unmodified lines | ||
| 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 | |
| @@ -2196,6 +2196,10 @@ static vm_fault_t do_page_mkwrite(struct vm_fault *vmf) · 2195 unmodified lines | ||
| 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; |
| @@ -1483,8 +1483,12 @@ unsigned long do_mmap(struct file *file, unsigned long addr, · 1482 unmodified lines | ||
| 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 |
| @@ -3275,6 +3275,17 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) · 3274 unmodified lines | ||
| 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) |
| @@ -3295,7 +3306,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) · 14 unmodified lines | ||
| 3295 | 3306 | atomic_inc(&proc_poll_event); |
| 3296 | 3307 | wake_up_interruptible(&proc_poll_wait); |
| 3297 | 3308 | |
| 3298 | − inode->i_flags |= S_SWAPFILE; | |
| 3299 | 3309 | error = 0; |
| 3300 | 3310 | goto out; |
| 3301 | 3311 | bad_swap: |