aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c90
1 files changed, 38 insertions, 52 deletions
diff --git a/fs/namei.c b/fs/namei.c
index d1a5dfeaf999..1f561dc495a1 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2111,57 +2111,6 @@ static int open_will_truncate(int flag, struct inode *inode)
2111 return (flag & O_TRUNC); 2111 return (flag & O_TRUNC);
2112} 2112}
2113 2113
2114static struct file *finish_open(struct nameidata *nd,
2115 int open_flag, int acc_mode)
2116{
2117 struct file *filp;
2118 int will_truncate;
2119 int error;
2120
2121 will_truncate = open_will_truncate(open_flag, nd->path.dentry->d_inode);
2122 if (will_truncate) {
2123 error = mnt_want_write(nd->path.mnt);
2124 if (error)
2125 goto exit;
2126 }
2127 error = may_open(&nd->path, acc_mode, open_flag);
2128 if (error) {
2129 if (will_truncate)
2130 mnt_drop_write(nd->path.mnt);
2131 goto exit;
2132 }
2133 filp = nameidata_to_filp(nd);
2134 if (!IS_ERR(filp)) {
2135 error = ima_file_check(filp, acc_mode);
2136 if (error) {
2137 fput(filp);
2138 filp = ERR_PTR(error);
2139 }
2140 }
2141 if (!IS_ERR(filp)) {
2142 if (will_truncate) {
2143 error = handle_truncate(filp);
2144 if (error) {
2145 fput(filp);
2146 filp = ERR_PTR(error);
2147 }
2148 }
2149 }
2150 /*
2151 * It is now safe to drop the mnt write
2152 * because the filp has had a write taken
2153 * on its behalf.
2154 */
2155 if (will_truncate)
2156 mnt_drop_write(nd->path.mnt);
2157 path_put(&nd->path);
2158 return filp;
2159
2160exit:
2161 path_put(&nd->path);
2162 return ERR_PTR(error);
2163}
2164
2165/* 2114/*
2166 * Handle the last step of open() 2115 * Handle the last step of open()
2167 */ 2116 */
@@ -2169,6 +2118,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2169 const struct open_flags *op, const char *pathname) 2118 const struct open_flags *op, const char *pathname)
2170{ 2119{
2171 struct dentry *dir = nd->path.dentry; 2120 struct dentry *dir = nd->path.dentry;
2121 int will_truncate;
2172 struct file *filp; 2122 struct file *filp;
2173 struct inode *inode; 2123 struct inode *inode;
2174 int error; 2124 int error;
@@ -2329,7 +2279,43 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2329 if (S_ISDIR(nd->inode->i_mode)) 2279 if (S_ISDIR(nd->inode->i_mode))
2330 goto exit; 2280 goto exit;
2331ok: 2281ok:
2332 filp = finish_open(nd, op->open_flag, op->acc_mode); 2282 will_truncate = open_will_truncate(op->open_flag, nd->path.dentry->d_inode);
2283 if (will_truncate) {
2284 error = mnt_want_write(nd->path.mnt);
2285 if (error)
2286 goto exit;
2287 }
2288 error = may_open(&nd->path, op->acc_mode, op->open_flag);
2289 if (error) {
2290 if (will_truncate)
2291 mnt_drop_write(nd->path.mnt);
2292 goto exit;
2293 }
2294 filp = nameidata_to_filp(nd);
2295 if (!IS_ERR(filp)) {
2296 error = ima_file_check(filp, op->acc_mode);
2297 if (error) {
2298 fput(filp);
2299 filp = ERR_PTR(error);
2300 }
2301 }
2302 if (!IS_ERR(filp)) {
2303 if (will_truncate) {
2304 error = handle_truncate(filp);
2305 if (error) {
2306 fput(filp);
2307 filp = ERR_PTR(error);
2308 }
2309 }
2310 }
2311 /*
2312 * It is now safe to drop the mnt write
2313 * because the filp has had a write taken
2314 * on its behalf.
2315 */
2316 if (will_truncate)
2317 mnt_drop_write(nd->path.mnt);
2318 path_put(&nd->path);
2333 return filp; 2319 return filp;
2334 2320
2335exit_mutex_unlock: 2321exit_mutex_unlock: