diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-03 14:57:09 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-03 14:57:09 -0400 |
| commit | 236bfd8ed868edfc42a656682487683ade3fede4 (patch) | |
| tree | e1311ab7ca76f663f837c7adf9aacd27492939bb | |
| parent | 4f302921c1458d790ae21147f7043f4e6b6a1085 (diff) | |
| parent | e7c0b5991dd1be7b6f6dc2b54a15a0f47b64b007 (diff) | |
Merge branch 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs
Pull overlayfs fixes from Miklos Szeredi:
"This contains fixes for a dentry leak, a regression in 4.6 noticed by
Docker users and missing write access checking in truncate"
* 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs:
ovl: warn instead of error if d_type is not supported
ovl: get_write_access() in truncate
ovl: fix dentry leak for default_permissions
| -rw-r--r-- | fs/overlayfs/inode.c | 29 | ||||
| -rw-r--r-- | fs/overlayfs/super.c | 12 |
2 files changed, 33 insertions, 8 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 1dbeab6cf96e..c831c2e5f803 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
| @@ -59,16 +59,37 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 59 | if (err) | 59 | if (err) |
| 60 | goto out; | 60 | goto out; |
| 61 | 61 | ||
| 62 | if (attr->ia_valid & ATTR_SIZE) { | ||
| 63 | struct inode *realinode = d_inode(ovl_dentry_real(dentry)); | ||
| 64 | |||
| 65 | err = -ETXTBSY; | ||
| 66 | if (atomic_read(&realinode->i_writecount) < 0) | ||
| 67 | goto out_drop_write; | ||
| 68 | } | ||
| 69 | |||
| 62 | err = ovl_copy_up(dentry); | 70 | err = ovl_copy_up(dentry); |
| 63 | if (!err) { | 71 | if (!err) { |
| 72 | struct inode *winode = NULL; | ||
| 73 | |||
| 64 | upperdentry = ovl_dentry_upper(dentry); | 74 | upperdentry = ovl_dentry_upper(dentry); |
| 65 | 75 | ||
| 76 | if (attr->ia_valid & ATTR_SIZE) { | ||
| 77 | winode = d_inode(upperdentry); | ||
| 78 | err = get_write_access(winode); | ||
| 79 | if (err) | ||
| 80 | goto out_drop_write; | ||
| 81 | } | ||
| 82 | |||
| 66 | inode_lock(upperdentry->d_inode); | 83 | inode_lock(upperdentry->d_inode); |
| 67 | err = notify_change(upperdentry, attr, NULL); | 84 | err = notify_change(upperdentry, attr, NULL); |
| 68 | if (!err) | 85 | if (!err) |
| 69 | ovl_copyattr(upperdentry->d_inode, dentry->d_inode); | 86 | ovl_copyattr(upperdentry->d_inode, dentry->d_inode); |
| 70 | inode_unlock(upperdentry->d_inode); | 87 | inode_unlock(upperdentry->d_inode); |
| 88 | |||
| 89 | if (winode) | ||
| 90 | put_write_access(winode); | ||
| 71 | } | 91 | } |
| 92 | out_drop_write: | ||
| 72 | ovl_drop_write(dentry); | 93 | ovl_drop_write(dentry); |
| 73 | out: | 94 | out: |
| 74 | return err; | 95 | return err; |
| @@ -121,16 +142,18 @@ int ovl_permission(struct inode *inode, int mask) | |||
| 121 | 142 | ||
| 122 | err = vfs_getattr(&realpath, &stat); | 143 | err = vfs_getattr(&realpath, &stat); |
| 123 | if (err) | 144 | if (err) |
| 124 | return err; | 145 | goto out_dput; |
| 125 | 146 | ||
| 147 | err = -ESTALE; | ||
| 126 | if ((stat.mode ^ inode->i_mode) & S_IFMT) | 148 | if ((stat.mode ^ inode->i_mode) & S_IFMT) |
| 127 | return -ESTALE; | 149 | goto out_dput; |
| 128 | 150 | ||
| 129 | inode->i_mode = stat.mode; | 151 | inode->i_mode = stat.mode; |
| 130 | inode->i_uid = stat.uid; | 152 | inode->i_uid = stat.uid; |
| 131 | inode->i_gid = stat.gid; | 153 | inode->i_gid = stat.gid; |
| 132 | 154 | ||
| 133 | return generic_permission(inode, mask); | 155 | err = generic_permission(inode, mask); |
| 156 | goto out_dput; | ||
| 134 | } | 157 | } |
| 135 | 158 | ||
| 136 | /* Careful in RCU walk mode */ | 159 | /* Careful in RCU walk mode */ |
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index ce02f46029da..9a7693d5f8ff 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
| @@ -1082,11 +1082,13 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) | |||
| 1082 | if (err < 0) | 1082 | if (err < 0) |
| 1083 | goto out_put_workdir; | 1083 | goto out_put_workdir; |
| 1084 | 1084 | ||
| 1085 | if (!err) { | 1085 | /* |
| 1086 | pr_err("overlayfs: upper fs needs to support d_type.\n"); | 1086 | * We allowed this configuration and don't want to |
| 1087 | err = -EINVAL; | 1087 | * break users over kernel upgrade. So warn instead |
| 1088 | goto out_put_workdir; | 1088 | * of erroring out. |
| 1089 | } | 1089 | */ |
| 1090 | if (!err) | ||
| 1091 | pr_warn("overlayfs: upper fs needs to support d_type.\n"); | ||
| 1090 | } | 1092 | } |
| 1091 | } | 1093 | } |
| 1092 | 1094 | ||
