diff options
-rw-r--r-- | fs/open.c | 39 |
1 files changed, 30 insertions, 9 deletions
@@ -567,12 +567,12 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) | |||
567 | 567 | ||
568 | audit_inode(NULL, dentry); | 568 | audit_inode(NULL, dentry); |
569 | 569 | ||
570 | err = -EROFS; | 570 | err = mnt_want_write(file->f_path.mnt); |
571 | if (IS_RDONLY(inode)) | 571 | if (err) |
572 | goto out_putf; | 572 | goto out_putf; |
573 | err = -EPERM; | 573 | err = -EPERM; |
574 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 574 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
575 | goto out_putf; | 575 | goto out_drop_write; |
576 | mutex_lock(&inode->i_mutex); | 576 | mutex_lock(&inode->i_mutex); |
577 | if (mode == (mode_t) -1) | 577 | if (mode == (mode_t) -1) |
578 | mode = inode->i_mode; | 578 | mode = inode->i_mode; |
@@ -581,6 +581,8 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) | |||
581 | err = notify_change(dentry, &newattrs); | 581 | err = notify_change(dentry, &newattrs); |
582 | mutex_unlock(&inode->i_mutex); | 582 | mutex_unlock(&inode->i_mutex); |
583 | 583 | ||
584 | out_drop_write: | ||
585 | mnt_drop_write(file->f_path.mnt); | ||
584 | out_putf: | 586 | out_putf: |
585 | fput(file); | 587 | fput(file); |
586 | out: | 588 | out: |
@@ -600,13 +602,13 @@ asmlinkage long sys_fchmodat(int dfd, const char __user *filename, | |||
600 | goto out; | 602 | goto out; |
601 | inode = nd.path.dentry->d_inode; | 603 | inode = nd.path.dentry->d_inode; |
602 | 604 | ||
603 | error = -EROFS; | 605 | error = mnt_want_write(nd.path.mnt); |
604 | if (IS_RDONLY(inode)) | 606 | if (error) |
605 | goto dput_and_out; | 607 | goto dput_and_out; |
606 | 608 | ||
607 | error = -EPERM; | 609 | error = -EPERM; |
608 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 610 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
609 | goto dput_and_out; | 611 | goto out_drop_write; |
610 | 612 | ||
611 | mutex_lock(&inode->i_mutex); | 613 | mutex_lock(&inode->i_mutex); |
612 | if (mode == (mode_t) -1) | 614 | if (mode == (mode_t) -1) |
@@ -616,6 +618,8 @@ asmlinkage long sys_fchmodat(int dfd, const char __user *filename, | |||
616 | error = notify_change(nd.path.dentry, &newattrs); | 618 | error = notify_change(nd.path.dentry, &newattrs); |
617 | mutex_unlock(&inode->i_mutex); | 619 | mutex_unlock(&inode->i_mutex); |
618 | 620 | ||
621 | out_drop_write: | ||
622 | mnt_drop_write(nd.path.mnt); | ||
619 | dput_and_out: | 623 | dput_and_out: |
620 | path_put(&nd.path); | 624 | path_put(&nd.path); |
621 | out: | 625 | out: |
@@ -638,9 +642,6 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group) | |||
638 | printk(KERN_ERR "chown_common: NULL inode\n"); | 642 | printk(KERN_ERR "chown_common: NULL inode\n"); |
639 | goto out; | 643 | goto out; |
640 | } | 644 | } |
641 | error = -EROFS; | ||
642 | if (IS_RDONLY(inode)) | ||
643 | goto out; | ||
644 | error = -EPERM; | 645 | error = -EPERM; |
645 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 646 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
646 | goto out; | 647 | goto out; |
@@ -671,7 +672,12 @@ asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group) | |||
671 | error = user_path_walk(filename, &nd); | 672 | error = user_path_walk(filename, &nd); |
672 | if (error) | 673 | if (error) |
673 | goto out; | 674 | goto out; |
675 | error = mnt_want_write(nd.path.mnt); | ||
676 | if (error) | ||
677 | goto out_release; | ||
674 | error = chown_common(nd.path.dentry, user, group); | 678 | error = chown_common(nd.path.dentry, user, group); |
679 | mnt_drop_write(nd.path.mnt); | ||
680 | out_release: | ||
675 | path_put(&nd.path); | 681 | path_put(&nd.path); |
676 | out: | 682 | out: |
677 | return error; | 683 | return error; |
@@ -691,7 +697,12 @@ asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, | |||
691 | error = __user_walk_fd(dfd, filename, follow, &nd); | 697 | error = __user_walk_fd(dfd, filename, follow, &nd); |
692 | if (error) | 698 | if (error) |
693 | goto out; | 699 | goto out; |
700 | error = mnt_want_write(nd.path.mnt); | ||
701 | if (error) | ||
702 | goto out_release; | ||
694 | error = chown_common(nd.path.dentry, user, group); | 703 | error = chown_common(nd.path.dentry, user, group); |
704 | mnt_drop_write(nd.path.mnt); | ||
705 | out_release: | ||
695 | path_put(&nd.path); | 706 | path_put(&nd.path); |
696 | out: | 707 | out: |
697 | return error; | 708 | return error; |
@@ -705,7 +716,12 @@ asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group | |||
705 | error = user_path_walk_link(filename, &nd); | 716 | error = user_path_walk_link(filename, &nd); |
706 | if (error) | 717 | if (error) |
707 | goto out; | 718 | goto out; |
719 | error = mnt_want_write(nd.path.mnt); | ||
720 | if (error) | ||
721 | goto out_release; | ||
708 | error = chown_common(nd.path.dentry, user, group); | 722 | error = chown_common(nd.path.dentry, user, group); |
723 | mnt_drop_write(nd.path.mnt); | ||
724 | out_release: | ||
709 | path_put(&nd.path); | 725 | path_put(&nd.path); |
710 | out: | 726 | out: |
711 | return error; | 727 | return error; |
@@ -722,9 +738,14 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group) | |||
722 | if (!file) | 738 | if (!file) |
723 | goto out; | 739 | goto out; |
724 | 740 | ||
741 | error = mnt_want_write(file->f_path.mnt); | ||
742 | if (error) | ||
743 | goto out_fput; | ||
725 | dentry = file->f_path.dentry; | 744 | dentry = file->f_path.dentry; |
726 | audit_inode(NULL, dentry); | 745 | audit_inode(NULL, dentry); |
727 | error = chown_common(dentry, user, group); | 746 | error = chown_common(dentry, user, group); |
747 | mnt_drop_write(file->f_path.mnt); | ||
748 | out_fput: | ||
728 | fput(file); | 749 | fput(file); |
729 | out: | 750 | out: |
730 | return error; | 751 | return error; |