diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-14 21:19:05 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-14 21:19:05 -0400 |
| commit | b26b5ef5ec7eab0e1d84c5b281e87b2f2a5e0586 (patch) | |
| tree | 3fd57787765f05a19b85b384bd2a68cb4f9276d4 /fs | |
| parent | 87dbe42a16b654e33665756c63e96c0fa73eb003 (diff) | |
| parent | 2692a71bbd40160165e89d5505c5c28144ec5a42 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull more misc uaccess and vfs updates from Al Viro:
"The rest of the stuff from -next (more uaccess work) + assorted fixes"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
score: traps: Add missing include file to fix build error
fs/super.c: don't fool lockdep in freeze_super() and thaw_super() paths
fs/super.c: fix race between freeze_super() and thaw_super()
overlayfs: Fix setting IOP_XATTR flag
iov_iter: kernel-doc import_iovec() and rw_copy_check_uvector()
blackfin: no access_ok() for __copy_{to,from}_user()
arm64: don't zero in __copy_from_user{,_inatomic}
arm: don't zero in __copy_from_user_inatomic()/__copy_from_user()
arc: don't leak bits of kernel stack into coredump
alpha: get rid of tail-zeroing in __copy_user()
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/overlayfs/super.c | 11 | ||||
| -rw-r--r-- | fs/read_write.c | 29 | ||||
| -rw-r--r-- | fs/super.c | 43 |
3 files changed, 63 insertions, 20 deletions
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 89182c4e2e30..bcf3965be819 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
| @@ -1303,6 +1303,12 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) | |||
| 1303 | if (!oe) | 1303 | if (!oe) |
| 1304 | goto out_put_cred; | 1304 | goto out_put_cred; |
| 1305 | 1305 | ||
| 1306 | sb->s_magic = OVERLAYFS_SUPER_MAGIC; | ||
| 1307 | sb->s_op = &ovl_super_operations; | ||
| 1308 | sb->s_xattr = ovl_xattr_handlers; | ||
| 1309 | sb->s_fs_info = ufs; | ||
| 1310 | sb->s_flags |= MS_POSIXACL | MS_NOREMOTELOCK; | ||
| 1311 | |||
| 1306 | root_dentry = d_make_root(ovl_new_inode(sb, S_IFDIR)); | 1312 | root_dentry = d_make_root(ovl_new_inode(sb, S_IFDIR)); |
| 1307 | if (!root_dentry) | 1313 | if (!root_dentry) |
| 1308 | goto out_free_oe; | 1314 | goto out_free_oe; |
| @@ -1326,12 +1332,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) | |||
| 1326 | ovl_inode_init(d_inode(root_dentry), realinode, !!upperpath.dentry); | 1332 | ovl_inode_init(d_inode(root_dentry), realinode, !!upperpath.dentry); |
| 1327 | ovl_copyattr(realinode, d_inode(root_dentry)); | 1333 | ovl_copyattr(realinode, d_inode(root_dentry)); |
| 1328 | 1334 | ||
| 1329 | sb->s_magic = OVERLAYFS_SUPER_MAGIC; | ||
| 1330 | sb->s_op = &ovl_super_operations; | ||
| 1331 | sb->s_xattr = ovl_xattr_handlers; | ||
| 1332 | sb->s_root = root_dentry; | 1335 | sb->s_root = root_dentry; |
| 1333 | sb->s_fs_info = ufs; | ||
| 1334 | sb->s_flags |= MS_POSIXACL | MS_NOREMOTELOCK; | ||
| 1335 | 1336 | ||
| 1336 | return 0; | 1337 | return 0; |
| 1337 | 1338 | ||
diff --git a/fs/read_write.c b/fs/read_write.c index 66215a7b17cf..190e0d362581 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
| @@ -730,6 +730,35 @@ static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter, | |||
| 730 | /* A write operation does a read from user space and vice versa */ | 730 | /* A write operation does a read from user space and vice versa */ |
| 731 | #define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ) | 731 | #define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ) |
| 732 | 732 | ||
| 733 | /** | ||
| 734 | * rw_copy_check_uvector() - Copy an array of &struct iovec from userspace | ||
| 735 | * into the kernel and check that it is valid. | ||
| 736 | * | ||
| 737 | * @type: One of %CHECK_IOVEC_ONLY, %READ, or %WRITE. | ||
| 738 | * @uvector: Pointer to the userspace array. | ||
| 739 | * @nr_segs: Number of elements in userspace array. | ||
| 740 | * @fast_segs: Number of elements in @fast_pointer. | ||
| 741 | * @fast_pointer: Pointer to (usually small on-stack) kernel array. | ||
| 742 | * @ret_pointer: (output parameter) Pointer to a variable that will point to | ||
| 743 | * either @fast_pointer, a newly allocated kernel array, or NULL, | ||
| 744 | * depending on which array was used. | ||
| 745 | * | ||
| 746 | * This function copies an array of &struct iovec of @nr_segs from | ||
| 747 | * userspace into the kernel and checks that each element is valid (e.g. | ||
| 748 | * it does not point to a kernel address or cause overflow by being too | ||
| 749 | * large, etc.). | ||
| 750 | * | ||
| 751 | * As an optimization, the caller may provide a pointer to a small | ||
| 752 | * on-stack array in @fast_pointer, typically %UIO_FASTIOV elements long | ||
| 753 | * (the size of this array, or 0 if unused, should be given in @fast_segs). | ||
| 754 | * | ||
| 755 | * @ret_pointer will always point to the array that was used, so the | ||
| 756 | * caller must take care not to call kfree() on it e.g. in case the | ||
| 757 | * @fast_pointer array was used and it was allocated on the stack. | ||
| 758 | * | ||
| 759 | * Return: The total number of bytes covered by the iovec array on success | ||
| 760 | * or a negative error code on error. | ||
| 761 | */ | ||
| 733 | ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, | 762 | ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, |
| 734 | unsigned long nr_segs, unsigned long fast_segs, | 763 | unsigned long nr_segs, unsigned long fast_segs, |
| 735 | struct iovec *fast_pointer, | 764 | struct iovec *fast_pointer, |
diff --git a/fs/super.c b/fs/super.c index c2ff475c1711..c183835566c1 100644 --- a/fs/super.c +++ b/fs/super.c | |||
| @@ -1269,25 +1269,34 @@ EXPORT_SYMBOL(__sb_start_write); | |||
| 1269 | static void sb_wait_write(struct super_block *sb, int level) | 1269 | static void sb_wait_write(struct super_block *sb, int level) |
| 1270 | { | 1270 | { |
| 1271 | percpu_down_write(sb->s_writers.rw_sem + level-1); | 1271 | percpu_down_write(sb->s_writers.rw_sem + level-1); |
| 1272 | /* | ||
| 1273 | * We are going to return to userspace and forget about this lock, the | ||
| 1274 | * ownership goes to the caller of thaw_super() which does unlock. | ||
| 1275 | * | ||
| 1276 | * FIXME: we should do this before return from freeze_super() after we | ||
| 1277 | * called sync_filesystem(sb) and s_op->freeze_fs(sb), and thaw_super() | ||
| 1278 | * should re-acquire these locks before s_op->unfreeze_fs(sb). However | ||
| 1279 | * this leads to lockdep false-positives, so currently we do the early | ||
| 1280 | * release right after acquire. | ||
| 1281 | */ | ||
| 1282 | percpu_rwsem_release(sb->s_writers.rw_sem + level-1, 0, _THIS_IP_); | ||
| 1283 | } | 1272 | } |
| 1284 | 1273 | ||
| 1285 | static void sb_freeze_unlock(struct super_block *sb) | 1274 | /* |
| 1275 | * We are going to return to userspace and forget about these locks, the | ||
| 1276 | * ownership goes to the caller of thaw_super() which does unlock(). | ||
| 1277 | */ | ||
| 1278 | static void lockdep_sb_freeze_release(struct super_block *sb) | ||
| 1279 | { | ||
| 1280 | int level; | ||
| 1281 | |||
| 1282 | for (level = SB_FREEZE_LEVELS - 1; level >= 0; level--) | ||
| 1283 | percpu_rwsem_release(sb->s_writers.rw_sem + level, 0, _THIS_IP_); | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | /* | ||
| 1287 | * Tell lockdep we are holding these locks before we call ->unfreeze_fs(sb). | ||
| 1288 | */ | ||
| 1289 | static void lockdep_sb_freeze_acquire(struct super_block *sb) | ||
| 1286 | { | 1290 | { |
| 1287 | int level; | 1291 | int level; |
| 1288 | 1292 | ||
| 1289 | for (level = 0; level < SB_FREEZE_LEVELS; ++level) | 1293 | for (level = 0; level < SB_FREEZE_LEVELS; ++level) |
| 1290 | percpu_rwsem_acquire(sb->s_writers.rw_sem + level, 0, _THIS_IP_); | 1294 | percpu_rwsem_acquire(sb->s_writers.rw_sem + level, 0, _THIS_IP_); |
| 1295 | } | ||
| 1296 | |||
| 1297 | static void sb_freeze_unlock(struct super_block *sb) | ||
| 1298 | { | ||
| 1299 | int level; | ||
| 1291 | 1300 | ||
| 1292 | for (level = SB_FREEZE_LEVELS - 1; level >= 0; level--) | 1301 | for (level = SB_FREEZE_LEVELS - 1; level >= 0; level--) |
| 1293 | percpu_up_write(sb->s_writers.rw_sem + level); | 1302 | percpu_up_write(sb->s_writers.rw_sem + level); |
| @@ -1379,10 +1388,11 @@ int freeze_super(struct super_block *sb) | |||
| 1379 | } | 1388 | } |
| 1380 | } | 1389 | } |
| 1381 | /* | 1390 | /* |
| 1382 | * This is just for debugging purposes so that fs can warn if it | 1391 | * For debugging purposes so that fs can warn if it sees write activity |
| 1383 | * sees write activity when frozen is set to SB_FREEZE_COMPLETE. | 1392 | * when frozen is set to SB_FREEZE_COMPLETE, and for thaw_super(). |
| 1384 | */ | 1393 | */ |
| 1385 | sb->s_writers.frozen = SB_FREEZE_COMPLETE; | 1394 | sb->s_writers.frozen = SB_FREEZE_COMPLETE; |
| 1395 | lockdep_sb_freeze_release(sb); | ||
| 1386 | up_write(&sb->s_umount); | 1396 | up_write(&sb->s_umount); |
| 1387 | return 0; | 1397 | return 0; |
| 1388 | } | 1398 | } |
| @@ -1399,7 +1409,7 @@ int thaw_super(struct super_block *sb) | |||
| 1399 | int error; | 1409 | int error; |
| 1400 | 1410 | ||
| 1401 | down_write(&sb->s_umount); | 1411 | down_write(&sb->s_umount); |
| 1402 | if (sb->s_writers.frozen == SB_UNFROZEN) { | 1412 | if (sb->s_writers.frozen != SB_FREEZE_COMPLETE) { |
| 1403 | up_write(&sb->s_umount); | 1413 | up_write(&sb->s_umount); |
| 1404 | return -EINVAL; | 1414 | return -EINVAL; |
| 1405 | } | 1415 | } |
| @@ -1409,11 +1419,14 @@ int thaw_super(struct super_block *sb) | |||
| 1409 | goto out; | 1419 | goto out; |
| 1410 | } | 1420 | } |
| 1411 | 1421 | ||
| 1422 | lockdep_sb_freeze_acquire(sb); | ||
| 1423 | |||
| 1412 | if (sb->s_op->unfreeze_fs) { | 1424 | if (sb->s_op->unfreeze_fs) { |
| 1413 | error = sb->s_op->unfreeze_fs(sb); | 1425 | error = sb->s_op->unfreeze_fs(sb); |
| 1414 | if (error) { | 1426 | if (error) { |
| 1415 | printk(KERN_ERR | 1427 | printk(KERN_ERR |
| 1416 | "VFS:Filesystem thaw failed\n"); | 1428 | "VFS:Filesystem thaw failed\n"); |
| 1429 | lockdep_sb_freeze_release(sb); | ||
| 1417 | up_write(&sb->s_umount); | 1430 | up_write(&sb->s_umount); |
| 1418 | return error; | 1431 | return error; |
| 1419 | } | 1432 | } |
