[dev] [PATCH] rm: Use basenames to protect against . and ..

From: Roberto E. Vargas Caballero <k0ga_AT_shike2.net>
Date: Fri, 25 Apr 2025 12:39:20 +0200

POSIX mandates that the protection should care about the basename,
and we cannot use basename because it can modify the input string
and it would make harder later operations. Also, it would put a limit
in the length of the name of the paths and POSIX forbids limitations
about that regard in rm(1).
---
 rm.c | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/rm.c b/rm.c
index 1f23c09..c1ae4fd 100644
--- a/rm.c
+++ b/rm.c
_AT_@ -11,9 +11,29 @@ usage(void)
 	eprintf("usage: %s [-f] [-iRr] file ...\n", argv0);
 }
 
+static int
+dotdot(char *path)
+{
+	char *s, *t;
+	size_t len;
+
+	len = strlen(path);
+	for (t = path + len; t > path && t[-1] == '/'; --t)
+		;
+	for (s = t; s > path && s[-1] != '/'; --s)
+		;
+
+	if (t - s == 1 && *s == '.')
+		return 1;
+	if (t - s == 2 && s[0] == '.' && s[1] == '.')
+		return 1;
+	return 0;
+}
+
 int
 main(int argc, char *argv[])
 {
+	char *s;
 	struct recursor r = { .fn = rm, .maxdepth = 1, .follow = 'P' };
 
 	ARGBEGIN {
_AT_@ -39,8 +59,12 @@ main(int argc, char *argv[])
 	}
 
 	for (; *argv; argc--, argv++) {
-		if (strcmp(*argv, ".") && strcmp(*argv, ".."))
-			recurse(AT_FDCWD, *argv, NULL, &r);
+		if (dotdot(*argv)) {
+			weprintf("\".\" and \"..\" may not be removed");
+			rm_status = 1;
+			continue;
+		}
+		recurse(AT_FDCWD, *argv, NULL, &r);
 	}
 
 	return rm_status || recurse_status;
-- 
2.46.1
Received on Fri Apr 25 2025 - 12:39:20 CEST

This archive was generated by hypermail 2.3.0 : Fri Apr 25 2025 - 12:48:09 CEST