All of lore.kernel.org
 help / color / mirror / Atom feed
From: Riku Voipio <riku.voipio@iki.fi>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH] linux-user: break recursion loop on symlink to . or ..
Date: Mon, 19 Jan 2009 17:30:33 +0200	[thread overview]
Message-ID: <20090119153033.GA21176@kos.to> (raw)

From: Mika Westerberg

This patch corrects bug in qemu where it contructs its
internal paths and ends up in recursion loop when filesystem
contains symlink that points to dot '.'.

(Riku: some whitespace fudging to minize diff - the whole
 file needs reindenting...)

Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
---
 linux-user/path.c |   37 ++++++++++++++++++++++++++++++++++++-
 1 files changed, 36 insertions(+), 1 deletions(-)

diff --git a/linux-user/path.c b/linux-user/path.c
index 06b1f5f..b991af0 100644
--- a/linux-user/path.c
+++ b/linux-user/path.c
@@ -4,6 +4,7 @@
    The assumption is that this area does not change.
 */
 #include <sys/types.h>
+#include <assert.h>
 #include <dirent.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -52,6 +53,38 @@ static struct pathelem *new_entry(const char *root,
 
 #define streq(a,b) (strcmp((a), (b)) == 0)
 
+/*
+ * Checks whether directory entry (dent) is valid.  This
+ * means that symlinks pointing to '.' and '..' should
+ * be skipped by main recursion code.  Returns 1 when
+ * entry is valid.
+ */
+static int
+is_dentry_valid(const char *path, const struct dirent *dent)
+{
+    char fullpath[PATH_MAX];
+    char linkbuf[PATH_MAX];
+    ssize_t len;
+
+    assert(path != NULL);
+    assert(dent != NULL);
+
+    if (dent->d_type != DT_LNK)
+        return (1);
+
+    (void) snprintf(fullpath, sizeof (fullpath), "%s/%s",
+       path, dent->d_name);
+
+    if ((len = readlink(fullpath, linkbuf, sizeof (linkbuf) - 1)) != -1) {
+        linkbuf[len] = '\0';
+        if (streq(linkbuf, ".") || streq(linkbuf, ".."))
+            return (0);
+    }
+
+    return (1);
+}
+
+/* TODO: add recursion count check */
 static struct pathelem *add_dir_maybe(struct pathelem *path)
 {
     DIR *dir;
@@ -61,7 +94,9 @@ static struct pathelem *add_dir_maybe(struct pathelem *path)
 
 	while ((dirent = readdir(dir)) != NULL) {
 	    if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){
-		path = add_entry(path, dirent->d_name);
+	        if (is_dentry_valid(path->pathname, dirent)) {
+	            path = add_entry(path, dirent->d_name);
+	        }
 	    }
 	}
         closedir(dir);
-- 
1.5.6.5


-- 
"rm -rf" only sounds scary if you don't have backups

             reply	other threads:[~2009-01-19 15:30 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-01-19 15:30 Riku Voipio [this message]
2009-01-30 19:50 ` [Qemu-devel] [PATCH] linux-user: break recursion loop on symlink to . or Aurelien Jarno

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090119153033.GA21176@kos.to \
    --to=riku.voipio@iki.fi \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.