140-overlayfs_readdir_locking_fix.patch 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. Patch by: Miklos Szeredi <[email protected]>
  2. Some filesystems (e.g. jffs2) lock the same resources for both readdir
  3. and lookup, leading to a deadlock in ovl_cache_entry_new, which is called
  4. from the filldir, and calls lookup itself.
  5. --- a/fs/overlayfs/readdir.c
  6. +++ b/fs/overlayfs/readdir.c
  7. @@ -23,6 +23,7 @@ struct ovl_cache_entry {
  8. u64 ino;
  9. struct list_head l_node;
  10. struct rb_node node;
  11. + struct ovl_cache_entry *next_maybe_whiteout;
  12. bool is_whiteout;
  13. char name[];
  14. };
  15. @@ -39,7 +40,7 @@ struct ovl_readdir_data {
  16. struct rb_root root;
  17. struct list_head *list;
  18. struct list_head middle;
  19. - struct dentry *dir;
  20. + struct ovl_cache_entry *first_maybe_whiteout;
  21. int count;
  22. int err;
  23. };
  24. @@ -79,7 +80,7 @@ static struct ovl_cache_entry *ovl_cache
  25. return NULL;
  26. }
  27. -static struct ovl_cache_entry *ovl_cache_entry_new(struct dentry *dir,
  28. +static struct ovl_cache_entry *ovl_cache_entry_new(struct ovl_readdir_data *rdd,
  29. const char *name, int len,
  30. u64 ino, unsigned int d_type)
  31. {
  32. @@ -98,29 +99,8 @@ static struct ovl_cache_entry *ovl_cache
  33. p->is_whiteout = false;
  34. if (d_type == DT_CHR) {
  35. - struct dentry *dentry;
  36. - const struct cred *old_cred;
  37. - struct cred *override_cred;
  38. -
  39. - override_cred = prepare_creds();
  40. - if (!override_cred) {
  41. - kfree(p);
  42. - return NULL;
  43. - }
  44. -
  45. - /*
  46. - * CAP_DAC_OVERRIDE for lookup
  47. - */
  48. - cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
  49. - old_cred = override_creds(override_cred);
  50. -
  51. - dentry = lookup_one_len(name, dir, len);
  52. - if (!IS_ERR(dentry)) {
  53. - p->is_whiteout = ovl_is_whiteout(dentry);
  54. - dput(dentry);
  55. - }
  56. - revert_creds(old_cred);
  57. - put_cred(override_cred);
  58. + p->next_maybe_whiteout = rdd->first_maybe_whiteout;
  59. + rdd->first_maybe_whiteout = p;
  60. }
  61. return p;
  62. }
  63. @@ -148,7 +128,7 @@ static int ovl_cache_entry_add_rb(struct
  64. return 0;
  65. }
  66. - p = ovl_cache_entry_new(rdd->dir, name, len, ino, d_type);
  67. + p = ovl_cache_entry_new(rdd, name, len, ino, d_type);
  68. if (p == NULL)
  69. return -ENOMEM;
  70. @@ -169,7 +149,7 @@ static int ovl_fill_lower(struct ovl_rea
  71. if (p) {
  72. list_move_tail(&p->l_node, &rdd->middle);
  73. } else {
  74. - p = ovl_cache_entry_new(rdd->dir, name, namelen, ino, d_type);
  75. + p = ovl_cache_entry_new(rdd, name, namelen, ino, d_type);
  76. if (p == NULL)
  77. rdd->err = -ENOMEM;
  78. else
  79. @@ -219,6 +199,43 @@ static int ovl_fill_merge(struct dir_con
  80. return ovl_fill_lower(rdd, name, namelen, offset, ino, d_type);
  81. }
  82. +static int ovl_check_whiteouts(struct dentry *dir, struct ovl_readdir_data *rdd)
  83. +{
  84. + int err = 0;
  85. +
  86. + mutex_lock(&dir->d_inode->i_mutex);
  87. + while (rdd->first_maybe_whiteout) {
  88. + struct dentry *dentry;
  89. + const struct cred *old_cred;
  90. + struct cred *override_cred;
  91. + struct ovl_cache_entry *p = rdd->first_maybe_whiteout;
  92. +
  93. + rdd->first_maybe_whiteout = p->next_maybe_whiteout;
  94. +
  95. + override_cred = prepare_creds();
  96. + if (!override_cred) {
  97. + err = -ENOMEM;
  98. + break;
  99. + }
  100. + /*
  101. + * CAP_DAC_OVERRIDE for lookup
  102. + */
  103. + cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
  104. + old_cred = override_creds(override_cred);
  105. +
  106. + dentry = lookup_one_len(p->name, dir, p->len);
  107. + if (!IS_ERR(dentry)) {
  108. + p->is_whiteout = ovl_is_whiteout(dentry);
  109. + dput(dentry);
  110. + }
  111. + revert_creds(old_cred);
  112. + put_cred(override_cred);
  113. + }
  114. + mutex_unlock(&dir->d_inode->i_mutex);
  115. +
  116. + return err;
  117. +}
  118. +
  119. static inline int ovl_dir_read(struct path *realpath,
  120. struct ovl_readdir_data *rdd)
  121. {
  122. @@ -229,7 +246,7 @@ static inline int ovl_dir_read(struct pa
  123. if (IS_ERR(realfile))
  124. return PTR_ERR(realfile);
  125. - rdd->dir = realpath->dentry;
  126. + rdd->first_maybe_whiteout = NULL;
  127. rdd->ctx.pos = 0;
  128. do {
  129. rdd->count = 0;
  130. @@ -238,6 +255,10 @@ static inline int ovl_dir_read(struct pa
  131. if (err >= 0)
  132. err = rdd->err;
  133. } while (!err && rdd->count);
  134. +
  135. + if (!err && rdd->first_maybe_whiteout)
  136. + err = ovl_check_whiteouts(realpath->dentry, rdd);
  137. +
  138. fput(realfile);
  139. return err;