aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2019-06-11 11:09:28 -0400
committerMiklos Szeredi <mszeredi@redhat.com>2019-06-11 11:17:41 -0400
commit941d935ac7636911a3fd8fa80e758e52b0b11e20 (patch)
tree54fdae5004d26421871f47ef8980bb334dd25bdf
parentd1fdb6d8f6a4109a4263176c84b899076a5f8008 (diff)
ovl: fix wrong flags check in FS_IOC_FS[SG]ETXATTR ioctls
The ioctl argument was parsed as the wrong type. Fixes: b21d9c435f93 ("ovl: support the FS_IOC_FS[SG]ETXATTR ioctls") Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r--fs/overlayfs/file.c91
1 files changed, 65 insertions, 26 deletions
diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
index 340a6ad45914..75d8d00fa087 100644
--- a/fs/overlayfs/file.c
+++ b/fs/overlayfs/file.c
@@ -409,37 +409,16 @@ static long ovl_real_ioctl(struct file *file, unsigned int cmd,
409 return ret; 409 return ret;
410} 410}
411 411
412static unsigned int ovl_get_inode_flags(struct inode *inode)
413{
414 unsigned int flags = READ_ONCE(inode->i_flags);
415 unsigned int ovl_iflags = 0;
416
417 if (flags & S_SYNC)
418 ovl_iflags |= FS_SYNC_FL;
419 if (flags & S_APPEND)
420 ovl_iflags |= FS_APPEND_FL;
421 if (flags & S_IMMUTABLE)
422 ovl_iflags |= FS_IMMUTABLE_FL;
423 if (flags & S_NOATIME)
424 ovl_iflags |= FS_NOATIME_FL;
425
426 return ovl_iflags;
427}
428
429static long ovl_ioctl_set_flags(struct file *file, unsigned int cmd, 412static long ovl_ioctl_set_flags(struct file *file, unsigned int cmd,
430 unsigned long arg) 413 unsigned long arg, unsigned int iflags)
431{ 414{
432 long ret; 415 long ret;
433 struct inode *inode = file_inode(file); 416 struct inode *inode = file_inode(file);
434 unsigned int flags; 417 unsigned int old_iflags;
435 unsigned int old_flags;
436 418
437 if (!inode_owner_or_capable(inode)) 419 if (!inode_owner_or_capable(inode))
438 return -EACCES; 420 return -EACCES;
439 421
440 if (get_user(flags, (int __user *) arg))
441 return -EFAULT;
442
443 ret = mnt_want_write_file(file); 422 ret = mnt_want_write_file(file);
444 if (ret) 423 if (ret)
445 return ret; 424 return ret;
@@ -448,8 +427,8 @@ static long ovl_ioctl_set_flags(struct file *file, unsigned int cmd,
448 427
449 /* Check the capability before cred override */ 428 /* Check the capability before cred override */
450 ret = -EPERM; 429 ret = -EPERM;
451 old_flags = ovl_get_inode_flags(inode); 430 old_iflags = READ_ONCE(inode->i_flags);
452 if (((flags ^ old_flags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) && 431 if (((iflags ^ old_iflags) & (S_APPEND | S_IMMUTABLE)) &&
453 !capable(CAP_LINUX_IMMUTABLE)) 432 !capable(CAP_LINUX_IMMUTABLE))
454 goto unlock; 433 goto unlock;
455 434
@@ -469,6 +448,63 @@ unlock:
469 448
470} 449}
471 450
451static unsigned int ovl_fsflags_to_iflags(unsigned int flags)
452{
453 unsigned int iflags = 0;
454
455 if (flags & FS_SYNC_FL)
456 iflags |= S_SYNC;
457 if (flags & FS_APPEND_FL)
458 iflags |= S_APPEND;
459 if (flags & FS_IMMUTABLE_FL)
460 iflags |= S_IMMUTABLE;
461 if (flags & FS_NOATIME_FL)
462 iflags |= S_NOATIME;
463
464 return iflags;
465}
466
467static long ovl_ioctl_set_fsflags(struct file *file, unsigned int cmd,
468 unsigned long arg)
469{
470 unsigned int flags;
471
472 if (get_user(flags, (int __user *) arg))
473 return -EFAULT;
474
475 return ovl_ioctl_set_flags(file, cmd, arg,
476 ovl_fsflags_to_iflags(flags));
477}
478
479static unsigned int ovl_fsxflags_to_iflags(unsigned int xflags)
480{
481 unsigned int iflags = 0;
482
483 if (xflags & FS_XFLAG_SYNC)
484 iflags |= S_SYNC;
485 if (xflags & FS_XFLAG_APPEND)
486 iflags |= S_APPEND;
487 if (xflags & FS_XFLAG_IMMUTABLE)
488 iflags |= S_IMMUTABLE;
489 if (xflags & FS_XFLAG_NOATIME)
490 iflags |= S_NOATIME;
491
492 return iflags;
493}
494
495static long ovl_ioctl_set_fsxflags(struct file *file, unsigned int cmd,
496 unsigned long arg)
497{
498 struct fsxattr fa;
499
500 memset(&fa, 0, sizeof(fa));
501 if (copy_from_user(&fa, (void __user *) arg, sizeof(fa)))
502 return -EFAULT;
503
504 return ovl_ioctl_set_flags(file, cmd, arg,
505 ovl_fsxflags_to_iflags(fa.fsx_xflags));
506}
507
472static long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 508static long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
473{ 509{
474 long ret; 510 long ret;
@@ -480,8 +516,11 @@ static long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
480 break; 516 break;
481 517
482 case FS_IOC_SETFLAGS: 518 case FS_IOC_SETFLAGS:
519 ret = ovl_ioctl_set_fsflags(file, cmd, arg);
520 break;
521
483 case FS_IOC_FSSETXATTR: 522 case FS_IOC_FSSETXATTR:
484 ret = ovl_ioctl_set_flags(file, cmd, arg); 523 ret = ovl_ioctl_set_fsxflags(file, cmd, arg);
485 break; 524 break;
486 525
487 default: 526 default: