Loading fs/namei.c +56 −50 Original line number Diff line number Diff line Loading @@ -1590,6 +1590,61 @@ static int open_will_truncate(int flag, struct inode *inode) return (flag & O_TRUNC); } static struct file *finish_open(struct nameidata *nd, int open_flag, int flag, int acc_mode) { struct file *filp; int will_truncate; int error; will_truncate = open_will_truncate(flag, nd->path.dentry->d_inode); if (will_truncate) { error = mnt_want_write(nd->path.mnt); if (error) goto exit; } error = may_open(&nd->path, acc_mode, open_flag); if (error) { if (will_truncate) mnt_drop_write(nd->path.mnt); goto exit; } filp = nameidata_to_filp(nd); if (!IS_ERR(filp)) { error = ima_file_check(filp, acc_mode); if (error) { fput(filp); filp = ERR_PTR(error); } } if (!IS_ERR(filp)) { if (acc_mode & MAY_WRITE) vfs_dq_init(nd->path.dentry->d_inode); if (will_truncate) { error = handle_truncate(&nd->path); if (error) { fput(filp); filp = ERR_PTR(error); } } } /* * It is now safe to drop the mnt write * because the filp has had a write taken * on its behalf. */ if (will_truncate) mnt_drop_write(nd->path.mnt); return filp; exit: if (!IS_ERR(nd->intent.open.file)) release_open_intent(nd); path_put(&nd->path); return ERR_PTR(error); } /* * Note that the low bits of the passed in "open_flag" * are not the same as in the local variable "flag". See Loading @@ -1604,7 +1659,6 @@ struct file *do_filp_open(int dfd, const char *pathname, struct path path; struct dentry *dir; int count = 0; int will_truncate; int flag = open_to_namei_flags(open_flag); int force_reval = 0; Loading Loading @@ -1769,55 +1823,7 @@ struct file *do_filp_open(int dfd, const char *pathname, if (S_ISDIR(path.dentry->d_inode->i_mode)) goto exit; ok: /* * Consider: * 1. may_open() truncates a file * 2. a rw->ro mount transition occurs * 3. nameidata_to_filp() fails due to * the ro mount. * That would be inconsistent, and should * be avoided. Taking this mnt write here * ensures that (2) can not occur. */ will_truncate = open_will_truncate(flag, nd.path.dentry->d_inode); if (will_truncate) { error = mnt_want_write(nd.path.mnt); if (error) goto exit; } error = may_open(&nd.path, acc_mode, open_flag); if (error) { if (will_truncate) mnt_drop_write(nd.path.mnt); goto exit; } filp = nameidata_to_filp(&nd); if (!IS_ERR(filp)) { error = ima_file_check(filp, acc_mode); if (error) { fput(filp); filp = ERR_PTR(error); } } if (!IS_ERR(filp)) { if (acc_mode & MAY_WRITE) vfs_dq_init(nd.path.dentry->d_inode); if (will_truncate) { error = handle_truncate(&nd.path); if (error) { fput(filp); filp = ERR_PTR(error); } } } /* * It is now safe to drop the mnt write * because the filp has had a write taken * on its behalf. */ if (will_truncate) mnt_drop_write(nd.path.mnt); filp = finish_open(&nd, open_flag, flag, acc_mode); if (nd.root.mnt) path_put(&nd.root); return filp; Loading Loading
fs/namei.c +56 −50 Original line number Diff line number Diff line Loading @@ -1590,6 +1590,61 @@ static int open_will_truncate(int flag, struct inode *inode) return (flag & O_TRUNC); } static struct file *finish_open(struct nameidata *nd, int open_flag, int flag, int acc_mode) { struct file *filp; int will_truncate; int error; will_truncate = open_will_truncate(flag, nd->path.dentry->d_inode); if (will_truncate) { error = mnt_want_write(nd->path.mnt); if (error) goto exit; } error = may_open(&nd->path, acc_mode, open_flag); if (error) { if (will_truncate) mnt_drop_write(nd->path.mnt); goto exit; } filp = nameidata_to_filp(nd); if (!IS_ERR(filp)) { error = ima_file_check(filp, acc_mode); if (error) { fput(filp); filp = ERR_PTR(error); } } if (!IS_ERR(filp)) { if (acc_mode & MAY_WRITE) vfs_dq_init(nd->path.dentry->d_inode); if (will_truncate) { error = handle_truncate(&nd->path); if (error) { fput(filp); filp = ERR_PTR(error); } } } /* * It is now safe to drop the mnt write * because the filp has had a write taken * on its behalf. */ if (will_truncate) mnt_drop_write(nd->path.mnt); return filp; exit: if (!IS_ERR(nd->intent.open.file)) release_open_intent(nd); path_put(&nd->path); return ERR_PTR(error); } /* * Note that the low bits of the passed in "open_flag" * are not the same as in the local variable "flag". See Loading @@ -1604,7 +1659,6 @@ struct file *do_filp_open(int dfd, const char *pathname, struct path path; struct dentry *dir; int count = 0; int will_truncate; int flag = open_to_namei_flags(open_flag); int force_reval = 0; Loading Loading @@ -1769,55 +1823,7 @@ struct file *do_filp_open(int dfd, const char *pathname, if (S_ISDIR(path.dentry->d_inode->i_mode)) goto exit; ok: /* * Consider: * 1. may_open() truncates a file * 2. a rw->ro mount transition occurs * 3. nameidata_to_filp() fails due to * the ro mount. * That would be inconsistent, and should * be avoided. Taking this mnt write here * ensures that (2) can not occur. */ will_truncate = open_will_truncate(flag, nd.path.dentry->d_inode); if (will_truncate) { error = mnt_want_write(nd.path.mnt); if (error) goto exit; } error = may_open(&nd.path, acc_mode, open_flag); if (error) { if (will_truncate) mnt_drop_write(nd.path.mnt); goto exit; } filp = nameidata_to_filp(&nd); if (!IS_ERR(filp)) { error = ima_file_check(filp, acc_mode); if (error) { fput(filp); filp = ERR_PTR(error); } } if (!IS_ERR(filp)) { if (acc_mode & MAY_WRITE) vfs_dq_init(nd.path.dentry->d_inode); if (will_truncate) { error = handle_truncate(&nd.path); if (error) { fput(filp); filp = ERR_PTR(error); } } } /* * It is now safe to drop the mnt write * because the filp has had a write taken * on its behalf. */ if (will_truncate) mnt_drop_write(nd.path.mnt); filp = finish_open(&nd, open_flag, flag, acc_mode); if (nd.root.mnt) path_put(&nd.root); return filp; Loading