From 2844a7d7e1ae32cc002d5dcf1e1181dc6934cb14 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: May 14 2015 12:20:07 +0000 Subject: Fix non-empty dir removal in overlayfs (rhbz 1220915) --- diff --git a/kernel.spec b/kernel.spec index 7806b69..3262eac 100644 --- a/kernel.spec +++ b/kernel.spec @@ -613,6 +613,9 @@ Patch26192: blk-loop-avoid-too-many-pending-per-work-IO.patch #rhbz 1219343 Patch26200: 0001-HID-usbhid-Add-HID_QUIRK_NOGET-for-Aten-DVI-KVM-swit.patch +#rhbz 1220915 +Patch26201: ovl-don-t-remove-non-empty-opaque-directory.patch + # END OF PATCH DEFINITIONS %endif @@ -1346,6 +1349,9 @@ ApplyPatch blk-loop-avoid-too-many-pending-per-work-IO.patch #rhbz 1219343 ApplyPatch 0001-HID-usbhid-Add-HID_QUIRK_NOGET-for-Aten-DVI-KVM-swit.patch +#rhbz 1220915 +ApplyPatch ovl-don-t-remove-non-empty-opaque-directory.patch + # END OF PATCH APPLICATIONS %endif @@ -2206,6 +2212,9 @@ fi # # %changelog +* Thu May 14 2015 Josh Boyer +- Fix non-empty dir removal in overlayfs (rhbz 1220915) + * Wed May 13 2015 Laura Abbott - Fix spew from KVM switch (rhbz 1219343) diff --git a/ovl-don-t-remove-non-empty-opaque-directory.patch b/ovl-don-t-remove-non-empty-opaque-directory.patch new file mode 100644 index 0000000..1f29e1e --- /dev/null +++ b/ovl-don-t-remove-non-empty-opaque-directory.patch @@ -0,0 +1,57 @@ +From: Miklos Szeredi +Date: Thu, 14 May 2015 10:04:44 +0200 +Subject: [PATCH] ovl: don't remove non-empty opaque directory + +When removing an opaque directory we can't just call rmdir() to check for +emptiness, because the directory will need to be replaced with a whiteout. +The replacement is done with RENAME_EXCHANGE, which doesn't check +emptiness. + +Solution is just to check emptiness by reading the directory. In the +future we could add a new rename flag to check for emptiness even for +RENAME_EXCHANGE to optimize this case. + +Reported-by: Vincent Batts +Signed-off-by: Miklos Szeredi +Tested-by: Jordi Pujol Palomer +Fixes: 263b4a0fee43 ("ovl: dont replace opaque dir") +Cc: # v4.0+ +--- + fs/overlayfs/dir.c | 24 +++++++++++++++++++----- + 1 file changed, 19 insertions(+), 5 deletions(-) + +diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c +index d139405d2bfa..2578a0c0677d 100644 +--- a/fs/overlayfs/dir.c ++++ b/fs/overlayfs/dir.c +@@ -506,11 +506,25 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir) + struct dentry *opaquedir = NULL; + int err; + +- if (is_dir && OVL_TYPE_MERGE_OR_LOWER(ovl_path_type(dentry))) { +- opaquedir = ovl_check_empty_and_clear(dentry); +- err = PTR_ERR(opaquedir); +- if (IS_ERR(opaquedir)) +- goto out; ++ if (is_dir) { ++ if (OVL_TYPE_MERGE_OR_LOWER(ovl_path_type(dentry))) { ++ opaquedir = ovl_check_empty_and_clear(dentry); ++ err = PTR_ERR(opaquedir); ++ if (IS_ERR(opaquedir)) ++ goto out; ++ } else { ++ LIST_HEAD(list); ++ ++ /* ++ * When removing an empty opaque directory, then it ++ * makes no sense to replace it with an exact replica of ++ * itself. But emptiness still needs to be checked. ++ */ ++ err = ovl_check_empty_dir(dentry, &list); ++ ovl_cache_free(&list); ++ if (err) ++ goto out; ++ } + } + + err = ovl_lock_rename_workdir(workdir, upperdir);