aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/namei.c57
1 files changed, 35 insertions, 22 deletions
diff --git a/fs/namei.c b/fs/namei.c
index e0f59031be8..5e4206f4537 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2169,17 +2169,26 @@ exit:
2169 return ERR_PTR(error); 2169 return ERR_PTR(error);
2170} 2170}
2171 2171
2172struct open_flags {
2173 int open_flag;
2174 int mode;
2175 int acc_mode;
2176 int intent;
2177};
2178
2172/* 2179/*
2173 * Handle O_CREAT case for do_filp_open 2180 * Handle O_CREAT case for do_filp_open
2174 */ 2181 */
2175static struct file *do_last(struct nameidata *nd, struct path *path, 2182static struct file *do_last(struct nameidata *nd, struct path *path,
2176 int open_flag, int acc_mode, 2183 const struct open_flags *op, const char *pathname)
2177 int mode, const char *pathname)
2178{ 2184{
2179 struct dentry *dir = nd->path.dentry; 2185 struct dentry *dir = nd->path.dentry;
2180 struct file *filp; 2186 struct file *filp;
2181 int error; 2187 int error;
2182 2188
2189 nd->flags &= ~LOOKUP_PARENT;
2190 nd->flags |= op->intent;
2191
2183 switch (nd->last_type) { 2192 switch (nd->last_type) {
2184 case LAST_DOTDOT: 2193 case LAST_DOTDOT:
2185 follow_dotdot(nd); 2194 follow_dotdot(nd);
@@ -2233,7 +2242,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2233 error = mnt_want_write(nd->path.mnt); 2242 error = mnt_want_write(nd->path.mnt);
2234 if (error) 2243 if (error)
2235 goto exit_mutex_unlock; 2244 goto exit_mutex_unlock;
2236 error = __open_namei_create(nd, path, open_flag, mode); 2245 error = __open_namei_create(nd, path, op->open_flag, op->mode);
2237 if (error) { 2246 if (error) {
2238 mnt_drop_write(nd->path.mnt); 2247 mnt_drop_write(nd->path.mnt);
2239 goto exit; 2248 goto exit;
@@ -2242,7 +2251,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2242 mnt_drop_write(nd->path.mnt); 2251 mnt_drop_write(nd->path.mnt);
2243 path_put(&nd->path); 2252 path_put(&nd->path);
2244 if (!IS_ERR(filp)) { 2253 if (!IS_ERR(filp)) {
2245 error = ima_file_check(filp, acc_mode); 2254 error = ima_file_check(filp, op->acc_mode);
2246 if (error) { 2255 if (error) {
2247 fput(filp); 2256 fput(filp);
2248 filp = ERR_PTR(error); 2257 filp = ERR_PTR(error);
@@ -2258,7 +2267,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2258 audit_inode(pathname, path->dentry); 2267 audit_inode(pathname, path->dentry);
2259 2268
2260 error = -EEXIST; 2269 error = -EEXIST;
2261 if (open_flag & O_EXCL) 2270 if (op->open_flag & O_EXCL)
2262 goto exit_dput; 2271 goto exit_dput;
2263 2272
2264 error = follow_managed(path, nd->flags); 2273 error = follow_managed(path, nd->flags);
@@ -2278,7 +2287,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2278 if (S_ISDIR(nd->inode->i_mode)) 2287 if (S_ISDIR(nd->inode->i_mode))
2279 goto exit; 2288 goto exit;
2280ok: 2289ok:
2281 filp = finish_open(nd, open_flag, acc_mode); 2290 filp = finish_open(nd, op->open_flag, op->acc_mode);
2282 return filp; 2291 return filp;
2283 2292
2284exit_mutex_unlock: 2293exit_mutex_unlock:
@@ -2304,7 +2313,8 @@ struct file *do_filp_open(int dfd, const char *pathname,
2304 struct path path; 2313 struct path path;
2305 int count = 0; 2314 int count = 0;
2306 int flag = open_to_namei_flags(open_flag); 2315 int flag = open_to_namei_flags(open_flag);
2307 int flags; 2316 int flags = 0;
2317 struct open_flags op;
2308 2318
2309 if (!(open_flag & O_CREAT)) 2319 if (!(open_flag & O_CREAT))
2310 mode = 0; 2320 mode = 0;
@@ -2321,6 +2331,8 @@ struct file *do_filp_open(int dfd, const char *pathname,
2321 if (open_flag & __O_SYNC) 2331 if (open_flag & __O_SYNC)
2322 open_flag |= O_DSYNC; 2332 open_flag |= O_DSYNC;
2323 2333
2334 op.open_flag = open_flag;
2335
2324 if (!acc_mode) 2336 if (!acc_mode)
2325 acc_mode = MAY_OPEN | ACC_MODE(open_flag); 2337 acc_mode = MAY_OPEN | ACC_MODE(open_flag);
2326 2338
@@ -2333,12 +2345,15 @@ struct file *do_filp_open(int dfd, const char *pathname,
2333 if (open_flag & O_APPEND) 2345 if (open_flag & O_APPEND)
2334 acc_mode |= MAY_APPEND; 2346 acc_mode |= MAY_APPEND;
2335 2347
2336 flags = LOOKUP_OPEN; 2348 op.acc_mode = acc_mode;
2349
2350 op.intent = LOOKUP_OPEN;
2337 if (open_flag & O_CREAT) { 2351 if (open_flag & O_CREAT) {
2338 flags |= LOOKUP_CREATE; 2352 op.intent |= LOOKUP_CREATE;
2339 if (open_flag & O_EXCL) 2353 if (open_flag & O_EXCL)
2340 flags |= LOOKUP_EXCL; 2354 op.intent |= LOOKUP_EXCL;
2341 } 2355 }
2356
2342 if (open_flag & O_DIRECTORY) 2357 if (open_flag & O_DIRECTORY)
2343 flags |= LOOKUP_DIRECTORY; 2358 flags |= LOOKUP_DIRECTORY;
2344 if (!(open_flag & O_NOFOLLOW)) 2359 if (!(open_flag & O_NOFOLLOW))
@@ -2357,7 +2372,7 @@ struct file *do_filp_open(int dfd, const char *pathname,
2357 goto creat; 2372 goto creat;
2358 2373
2359 /* !O_CREAT, simple open */ 2374 /* !O_CREAT, simple open */
2360 error = do_path_lookup(dfd, pathname, flags, &nd); 2375 error = do_path_lookup(dfd, pathname, flags | op.intent, &nd);
2361 if (unlikely(error)) 2376 if (unlikely(error))
2362 goto out_filp2; 2377 goto out_filp2;
2363 error = -ELOOP; 2378 error = -ELOOP;
@@ -2384,14 +2399,14 @@ out_filp2:
2384 2399
2385creat: 2400creat:
2386 /* OK, have to create the file. Find the parent. */ 2401 /* OK, have to create the file. Find the parent. */
2387 error = path_lookupat(dfd, pathname, LOOKUP_PARENT | LOOKUP_RCU, &nd); 2402 error = path_lookupat(dfd, pathname,
2403 LOOKUP_PARENT | LOOKUP_RCU | flags, &nd);
2388 if (unlikely(error == -ECHILD)) 2404 if (unlikely(error == -ECHILD))
2389 error = path_lookupat(dfd, pathname, LOOKUP_PARENT, &nd); 2405 error = path_lookupat(dfd, pathname, LOOKUP_PARENT | flags, &nd);
2390 if (unlikely(error == -ESTALE)) { 2406 if (unlikely(error == -ESTALE)) {
2391reval: 2407reval:
2392 flags |= LOOKUP_REVAL; 2408 flags |= LOOKUP_REVAL;
2393 error = path_lookupat(dfd, pathname, 2409 error = path_lookupat(dfd, pathname, LOOKUP_PARENT | flags, &nd);
2394 LOOKUP_PARENT | LOOKUP_REVAL, &nd);
2395 } 2410 }
2396 if (unlikely(error)) 2411 if (unlikely(error))
2397 goto out_filp; 2412 goto out_filp;
@@ -2401,8 +2416,7 @@ reval:
2401 /* 2416 /*
2402 * We have the parent and last component. 2417 * We have the parent and last component.
2403 */ 2418 */
2404 nd.flags = (nd.flags & ~LOOKUP_PARENT) | flags; 2419 filp = do_last(&nd, &path, &op, pathname);
2405 filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
2406 while (unlikely(!filp)) { /* trailing symlink */ 2420 while (unlikely(!filp)) { /* trailing symlink */
2407 struct path link = path; 2421 struct path link = path;
2408 struct inode *linki = link.dentry->d_inode; 2422 struct inode *linki = link.dentry->d_inode;
@@ -2424,13 +2438,12 @@ reval:
2424 * just set LAST_BIND. 2438 * just set LAST_BIND.
2425 */ 2439 */
2426 nd.flags |= LOOKUP_PARENT; 2440 nd.flags |= LOOKUP_PARENT;
2441 nd.flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
2427 error = __do_follow_link(&link, &nd, &cookie); 2442 error = __do_follow_link(&link, &nd, &cookie);
2428 if (unlikely(error)) { 2443 if (unlikely(error))
2429 filp = ERR_PTR(error); 2444 filp = ERR_PTR(error);
2430 } else { 2445 else
2431 nd.flags &= ~LOOKUP_PARENT; 2446 filp = do_last(&nd, &path, &op, pathname);
2432 filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
2433 }
2434 if (!IS_ERR(cookie) && linki->i_op->put_link) 2447 if (!IS_ERR(cookie) && linki->i_op->put_link)
2435 linki->i_op->put_link(link.dentry, &nd, cookie); 2448 linki->i_op->put_link(link.dentry, &nd, cookie);
2436 path_put(&link); 2449 path_put(&link);