Pull overlayfs fixes from Miklos Szeredi: "Fix two bugs in copy-up code. One introduced in 4.11 and one in 4.12-rc" * 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs: ovl: don't set origin on broken lower hardlink ovl: copy-up: don't unlock between lookup and link
Unified · Split
| @@ -330,15 +330,9 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, · 329 unmodified lines | ||
| 330 | 330 | .link = link |
| 331 | 331 | }; |
| 332 | 332 | |
| 333 | − upper = lookup_one_len(dentry->d_name.name, upperdir, | |
| 334 | − dentry->d_name.len); | |
| 335 | − err = PTR_ERR(upper); | |
| 336 | − if (IS_ERR(upper)) | |
| 337 | − goto out; | |
| 338 | − | |
| 339 | 333 | err = security_inode_copy_up(dentry, &new_creds); |
| 340 | 334 | if (err < 0) |
| 341 | − goto out1; | |
| 335 | + goto out; | |
| 342 | 336 | |
| 343 | 337 | if (new_creds) |
| 344 | 338 | old_creds = override_creds(new_creds); |
| @@ -362,7 +356,7 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, · 17 unmodified lines | ||
| 362 | 356 | } |
| 363 | 357 | |
| 364 | 358 | if (err) |
| 365 | − goto out2; | |
| 359 | + goto out; | |
| 366 | 360 | |
| 367 | 361 | if (S_ISREG(stat->mode)) { |
| 368 | 362 | struct path upperpath; |
| @@ -398,10 +392,23 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, · 29 unmodified lines | ||
| 398 | 392 | /* |
| 399 | 393 | * Store identifier of lower inode in upper inode xattr to |
| 400 | 394 | * allow lookup of the copy up origin inode. |
| 395 | + * | |
| 396 | + * Don't set origin when we are breaking the association with a lower | |
| 397 | + * hard link. | |
| 401 | 398 | */ |
| 402 | − err = ovl_set_origin(dentry, lowerpath->dentry, temp); | |
| 403 | − if (err) | |
| 399 | + if (S_ISDIR(stat->mode) || stat->nlink == 1) { | |
| 400 | + err = ovl_set_origin(dentry, lowerpath->dentry, temp); | |
| 401 | + if (err) | |
| 402 | + goto out_cleanup; | |
| 403 | + } | |
| 404 | + | |
| 405 | + upper = lookup_one_len(dentry->d_name.name, upperdir, | |
| 406 | + dentry->d_name.len); | |
| 407 | + if (IS_ERR(upper)) { | |
| 408 | + err = PTR_ERR(upper); | |
| 409 | + upper = NULL; | |
| 404 | 410 | goto out_cleanup; |
| 411 | + } | |
| 405 | 412 | |
| 406 | 413 | if (tmpfile) |
| 407 | 414 | err = ovl_do_link(temp, udir, upper, true); |
| @@ -416,17 +423,15 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, · 8 unmodified lines | ||
| 416 | 423 | |
| 417 | 424 | /* Restore timestamps on parent (best effort) */ |
| 418 | 425 | ovl_set_timestamps(upperdir, pstat); |
| 419 | −out2: | |
| 426 | +out: | |
| 420 | 427 | dput(temp); |
| 421 | −out1: | |
| 422 | 428 | dput(upper); |
| 423 | −out: | |
| 424 | 429 | return err; |
| 425 | 430 | |
| 426 | 431 | out_cleanup: |
| 427 | 432 | if (!tmpfile) |
| 428 | 433 | ovl_cleanup(wdir, temp); |
| 429 | − goto out2; | |
| 434 | + goto out; | |
| 430 | 435 | } |
| 431 | 436 | |
| 432 | 437 | /* |