aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/open.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/fs/open.c b/fs/open.c
index e12f17010324..e2df8fd1eb0b 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -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
584out_drop_write:
585 mnt_drop_write(file->f_path.mnt);
584out_putf: 586out_putf:
585 fput(file); 587 fput(file);
586out: 588out:
@@ -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
621out_drop_write:
622 mnt_drop_write(nd.path.mnt);
619dput_and_out: 623dput_and_out:
620 path_put(&nd.path); 624 path_put(&nd.path);
621out: 625out:
@@ -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);
680out_release:
675 path_put(&nd.path); 681 path_put(&nd.path);
676out: 682out:
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);
705out_release:
695 path_put(&nd.path); 706 path_put(&nd.path);
696out: 707out:
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);
724out_release:
709 path_put(&nd.path); 725 path_put(&nd.path);
710out: 726out:
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);
748out_fput:
728 fput(file); 749 fput(file);
729out: 750out:
730 return error; 751 return error;