diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fuse/dev.c | 19 | ||||
-rw-r--r-- | fs/overlayfs/super.c | 33 | ||||
-rw-r--r-- | fs/proc/task_mmu.c | 3 |
3 files changed, 47 insertions, 8 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index ed19a7d622fa..39706c57ad3c 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -890,8 +890,8 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) | |||
890 | 890 | ||
891 | newpage = buf->page; | 891 | newpage = buf->page; |
892 | 892 | ||
893 | if (WARN_ON(!PageUptodate(newpage))) | 893 | if (!PageUptodate(newpage)) |
894 | return -EIO; | 894 | SetPageUptodate(newpage); |
895 | 895 | ||
896 | ClearPageMappedToDisk(newpage); | 896 | ClearPageMappedToDisk(newpage); |
897 | 897 | ||
@@ -1353,6 +1353,17 @@ static ssize_t fuse_dev_do_read(struct fuse_conn *fc, struct file *file, | |||
1353 | return err; | 1353 | return err; |
1354 | } | 1354 | } |
1355 | 1355 | ||
1356 | static int fuse_dev_open(struct inode *inode, struct file *file) | ||
1357 | { | ||
1358 | /* | ||
1359 | * The fuse device's file's private_data is used to hold | ||
1360 | * the fuse_conn(ection) when it is mounted, and is used to | ||
1361 | * keep track of whether the file has been mounted already. | ||
1362 | */ | ||
1363 | file->private_data = NULL; | ||
1364 | return 0; | ||
1365 | } | ||
1366 | |||
1356 | static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov, | 1367 | static ssize_t fuse_dev_read(struct kiocb *iocb, const struct iovec *iov, |
1357 | unsigned long nr_segs, loff_t pos) | 1368 | unsigned long nr_segs, loff_t pos) |
1358 | { | 1369 | { |
@@ -1797,6 +1808,9 @@ copy_finish: | |||
1797 | static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, | 1808 | static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, |
1798 | unsigned int size, struct fuse_copy_state *cs) | 1809 | unsigned int size, struct fuse_copy_state *cs) |
1799 | { | 1810 | { |
1811 | /* Don't try to move pages (yet) */ | ||
1812 | cs->move_pages = 0; | ||
1813 | |||
1800 | switch (code) { | 1814 | switch (code) { |
1801 | case FUSE_NOTIFY_POLL: | 1815 | case FUSE_NOTIFY_POLL: |
1802 | return fuse_notify_poll(fc, size, cs); | 1816 | return fuse_notify_poll(fc, size, cs); |
@@ -2217,6 +2231,7 @@ static int fuse_dev_fasync(int fd, struct file *file, int on) | |||
2217 | 2231 | ||
2218 | const struct file_operations fuse_dev_operations = { | 2232 | const struct file_operations fuse_dev_operations = { |
2219 | .owner = THIS_MODULE, | 2233 | .owner = THIS_MODULE, |
2234 | .open = fuse_dev_open, | ||
2220 | .llseek = no_llseek, | 2235 | .llseek = no_llseek, |
2221 | .read = do_sync_read, | 2236 | .read = do_sync_read, |
2222 | .aio_read = fuse_dev_read, | 2237 | .aio_read = fuse_dev_read, |
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index b90952f528b1..5f0d1993e6e3 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
@@ -529,8 +529,7 @@ static int ovl_remount(struct super_block *sb, int *flags, char *data) | |||
529 | { | 529 | { |
530 | struct ovl_fs *ufs = sb->s_fs_info; | 530 | struct ovl_fs *ufs = sb->s_fs_info; |
531 | 531 | ||
532 | if (!(*flags & MS_RDONLY) && | 532 | if (!(*flags & MS_RDONLY) && !ufs->upper_mnt) |
533 | (!ufs->upper_mnt || (ufs->upper_mnt->mnt_sb->s_flags & MS_RDONLY))) | ||
534 | return -EROFS; | 533 | return -EROFS; |
535 | 534 | ||
536 | return 0; | 535 | return 0; |
@@ -615,9 +614,19 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config) | |||
615 | break; | 614 | break; |
616 | 615 | ||
617 | default: | 616 | default: |
617 | pr_err("overlayfs: unrecognized mount option \"%s\" or missing value\n", p); | ||
618 | return -EINVAL; | 618 | return -EINVAL; |
619 | } | 619 | } |
620 | } | 620 | } |
621 | |||
622 | /* Workdir is useless in non-upper mount */ | ||
623 | if (!config->upperdir && config->workdir) { | ||
624 | pr_info("overlayfs: option \"workdir=%s\" is useless in a non-upper mount, ignore\n", | ||
625 | config->workdir); | ||
626 | kfree(config->workdir); | ||
627 | config->workdir = NULL; | ||
628 | } | ||
629 | |||
621 | return 0; | 630 | return 0; |
622 | } | 631 | } |
623 | 632 | ||
@@ -837,7 +846,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) | |||
837 | 846 | ||
838 | sb->s_stack_depth = 0; | 847 | sb->s_stack_depth = 0; |
839 | if (ufs->config.upperdir) { | 848 | if (ufs->config.upperdir) { |
840 | /* FIXME: workdir is not needed for a R/O mount */ | ||
841 | if (!ufs->config.workdir) { | 849 | if (!ufs->config.workdir) { |
842 | pr_err("overlayfs: missing 'workdir'\n"); | 850 | pr_err("overlayfs: missing 'workdir'\n"); |
843 | goto out_free_config; | 851 | goto out_free_config; |
@@ -847,6 +855,13 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) | |||
847 | if (err) | 855 | if (err) |
848 | goto out_free_config; | 856 | goto out_free_config; |
849 | 857 | ||
858 | /* Upper fs should not be r/o */ | ||
859 | if (upperpath.mnt->mnt_sb->s_flags & MS_RDONLY) { | ||
860 | pr_err("overlayfs: upper fs is r/o, try multi-lower layers mount\n"); | ||
861 | err = -EINVAL; | ||
862 | goto out_put_upperpath; | ||
863 | } | ||
864 | |||
850 | err = ovl_mount_dir(ufs->config.workdir, &workpath); | 865 | err = ovl_mount_dir(ufs->config.workdir, &workpath); |
851 | if (err) | 866 | if (err) |
852 | goto out_put_upperpath; | 867 | goto out_put_upperpath; |
@@ -869,8 +884,14 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) | |||
869 | 884 | ||
870 | err = -EINVAL; | 885 | err = -EINVAL; |
871 | stacklen = ovl_split_lowerdirs(lowertmp); | 886 | stacklen = ovl_split_lowerdirs(lowertmp); |
872 | if (stacklen > OVL_MAX_STACK) | 887 | if (stacklen > OVL_MAX_STACK) { |
888 | pr_err("overlayfs: too many lower directries, limit is %d\n", | ||
889 | OVL_MAX_STACK); | ||
873 | goto out_free_lowertmp; | 890 | goto out_free_lowertmp; |
891 | } else if (!ufs->config.upperdir && stacklen == 1) { | ||
892 | pr_err("overlayfs: at least 2 lowerdir are needed while upperdir nonexistent\n"); | ||
893 | goto out_free_lowertmp; | ||
894 | } | ||
874 | 895 | ||
875 | stack = kcalloc(stacklen, sizeof(struct path), GFP_KERNEL); | 896 | stack = kcalloc(stacklen, sizeof(struct path), GFP_KERNEL); |
876 | if (!stack) | 897 | if (!stack) |
@@ -932,8 +953,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) | |||
932 | ufs->numlower++; | 953 | ufs->numlower++; |
933 | } | 954 | } |
934 | 955 | ||
935 | /* If the upper fs is r/o or nonexistent, we mark overlayfs r/o too */ | 956 | /* If the upper fs is nonexistent, we mark overlayfs r/o too */ |
936 | if (!ufs->upper_mnt || (ufs->upper_mnt->mnt_sb->s_flags & MS_RDONLY)) | 957 | if (!ufs->upper_mnt) |
937 | sb->s_flags |= MS_RDONLY; | 958 | sb->s_flags |= MS_RDONLY; |
938 | 959 | ||
939 | sb->s_d_op = &ovl_dentry_operations; | 960 | sb->s_d_op = &ovl_dentry_operations; |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 956b75d61809..6dee68d013ff 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -1325,6 +1325,9 @@ out: | |||
1325 | 1325 | ||
1326 | static int pagemap_open(struct inode *inode, struct file *file) | 1326 | static int pagemap_open(struct inode *inode, struct file *file) |
1327 | { | 1327 | { |
1328 | /* do not disclose physical addresses: attack vector */ | ||
1329 | if (!capable(CAP_SYS_ADMIN)) | ||
1330 | return -EPERM; | ||
1328 | pr_warn_once("Bits 55-60 of /proc/PID/pagemap entries are about " | 1331 | pr_warn_once("Bits 55-60 of /proc/PID/pagemap entries are about " |
1329 | "to stop being page-shift some time soon. See the " | 1332 | "to stop being page-shift some time soon. See the " |
1330 | "linux/Documentation/vm/pagemap.txt for details.\n"); | 1333 | "linux/Documentation/vm/pagemap.txt for details.\n"); |