History

vfs: don't allow writes to swap files

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.

Darrick J. Wong committed 7 years ago

Commit dc617f21 parent 16380456 files · +38 −3Browse files

Unified · Split

6 files
  1. fs/block_dev.c +3 −0
  2. include/linux/fs.h +11 −0
  3. mm/filemap.c +3 −0
  4. mm/memory.c +4 −0
  5. mm/mmap.c +6 −2
  6. mm/swapfile.c +11 −1
fs/block_dev.c+3−0
@@ -1978,6 +1978,9 @@ ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) · 1977 unmodified lines
19781978 if (bdev_read_only(I_BDEV(bd_inode)))
19791979 return -EPERM;
19801980
1981+ if (IS_SWAPFILE(bd_inode))
1982+ return -ETXTBSY;
1983+
19811984 if (!iov_iter_count(from))
19821985 return 0;
19831986
include/linux/fs.h+11−0
@@ -3547,4 +3547,15 @@ static inline void simple_fill_fsxattr(struct fsxattr *fa, __u32 xflags) · 3546 unmodified lines
35473547 fa->fsx_xflags = xflags;
35483548 }
35493549
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+
35503561 #endif /* _LINUX_FS_H */
mm/filemap.c+3−0
@@ -2988,6 +2988,9 @@ inline ssize_t generic_write_checks(struct kiocb *iocb, struct iov_iter *from) · 2987 unmodified lines
29882988 loff_t count;
29892989 int ret;
29902990
2991+ if (IS_SWAPFILE(inode))
2992+ return -ETXTBSY;
2993+
29912994 if (!iov_iter_count(from))
29922995 return 0;
29932996
mm/memory.c+4−0
@@ -2196,6 +2196,10 @@ static vm_fault_t do_page_mkwrite(struct vm_fault *vmf) · 2195 unmodified lines
21962196
21972197 vmf->flags = FAULT_FLAG_WRITE|FAULT_FLAG_MKWRITE;
21982198
2199+ if (vmf->vma->vm_file &&
2200+ IS_SWAPFILE(vmf->vma->vm_file->f_mapping->host))
2201+ return VM_FAULT_SIGBUS;
2202+
21992203 ret = vmf->vma->vm_ops->page_mkwrite(vmf);
22002204 /* Restore original flags so that caller is not surprised */
22012205 vmf->flags = old_flags;
mm/mmap.c+6−2
@@ -1483,8 +1483,12 @@ unsigned long do_mmap(struct file *file, unsigned long addr, · 1482 unmodified lines
14831483 case MAP_SHARED_VALIDATE:
14841484 if (flags & ~flags_mask)
14851485 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+ }
14881492
14891493 /*
14901494 * Make sure we don't allow writing to an append-only
mm/swapfile.c+11−1
@@ -3275,6 +3275,17 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) · 3274 unmodified lines
32753275 if (error)
32763276 goto bad_swap;
32773277
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+
32783289 mutex_lock(&swapon_mutex);
32793290 prio = -1;
32803291 if (swap_flags & SWAP_FLAG_PREFER)
@@ -3295,7 +3306,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) · 14 unmodified lines
32953306 atomic_inc(&proc_poll_event);
32963307 wake_up_interruptible(&proc_poll_wait);
32973308
3298− inode->i_flags |= S_SWAPFILE;
32993309 error = 0;
33003310 goto out;
33013311 bad_swap:

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t