From d27f5391d5654e13bfaab2a0f090fb78f4be0afa Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 26 Aug 2015 17:07:31 +0300 Subject: [PATCH] mount: Handle deleted bindmounts for regular files 1) Deleted bindmount for files should be restored by creating temp file. The kernel doesn't permit to mix bindmount in terms of file/dir relationship: either both source and target should be files or directories. Thus we can call stat on the target and figure out what kind of source we had. 2) Even for deleted entries better to use permissions from the target's stat call, this makes result close to how would it look if program hadn't been checkpointed. Reported-by: Andrey Wagin Signed-off-by: Cyrill Gorcunov Acked-by: Tycho Andersen Signed-off-by: Pavel Emelyanov --- mount.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/mount.c b/mount.c index 04b99d990b..6d44eae442 100644 --- a/mount.c +++ b/mount.c @@ -1970,6 +1970,7 @@ static int do_bind_mount(struct mount_info *mi) { bool shared = 0; bool force_private_remount = false; + struct stat st; if (!mi->need_plugin) { char *root, *cut_root, rpath[PATH_MAX]; @@ -1996,8 +1997,24 @@ static int do_bind_mount(struct mount_info *mi) pr_info("\tBind %s to %s\n", root, mi->mountpoint); if (unlikely(mi->deleted)) { - if (mkdir(root, 0700)) { - pr_perror("Can't re-create deleted %s\n", root); + if (stat(mi->mountpoint, &st)) { + pr_perror("Can't fetch stat on %s", mi->mountpoint); + return -1; + } + + if (S_ISDIR(st.st_mode)) { + if (mkdir(root, (st.st_mode & ~S_IFMT))) { + pr_perror("Can't re-create deleted directory %s\n", root); + return -1; + } + } else if (S_ISREG(st.st_mode)) { + if (open(root, O_WRONLY | O_CREAT | O_TRUNC, (st.st_mode & ~S_IFMT)) < 0) { + pr_perror("Can't re-create deleted file %s\n", root); + return -1; + } + } else { + pr_err("Unsupported st_mode 0%o deleted root %s\n", + (int)st.st_mode, root); return -1; } } @@ -2008,9 +2025,16 @@ static int do_bind_mount(struct mount_info *mi) } if (unlikely(mi->deleted)) { - if (rmdir(root)) { - pr_perror("Can't remove deleted %s\n", root); - return -1; + if (S_ISDIR(st.st_mode)) { + if (rmdir(root)) { + pr_perror("Can't remove deleted directory %s\n", root); + return -1; + } + } else if (S_ISREG(st.st_mode)) { + if (unlink(root)) { + pr_perror("Can't unlink deleted file %s\n", root); + return -1; + } } } } else {