[hackers] [sbase] rm: Use basenames to protect against . and .. || Roberto E. Vargas Caballero

From: <git_AT_suckless.org>
Date: Fri, 25 Apr 2025 18:45:57 +0200 (CEST)

commit b27871013b1debede7a5177f915be3f7b75aaee3
Author: Roberto E. Vargas Caballero <k0ga_AT_shike2.net>
AuthorDate: Fri Apr 25 12:37:10 2025 +0200
Commit: Roberto E. Vargas Caballero <k0ga_AT_shike2.net>
CommitDate: Fri Apr 25 17:16:36 2025 +0200

    rm: Use basenames to protect against . and ..
    
    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).

diff --git a/rm.c b/rm.c
index 1f23c09..fd13b22 100644
--- a/rm.c
+++ b/rm.c
_AT_@ -11,9 +11,44 @@ usage(void)
         eprintf("usage: %s [-f] [-iRr] file ...\n", argv0);
 }
 
+static int
+forbidden(char *path, struct stat *root)
+{
+ char *s, *t;
+ size_t n;
+ struct stat st;
+ static int w1, w2;
+
+ n = strlen(path);
+ for (t = path + n; t > path && t[-1] == '/'; --t)
+ ;
+ for (s = t; s > path && s[-1] != '/'; --s)
+ ;
+ n = t - s;
+ if (n == 1 && *s == '.' || n == 2 && s[0] == '.' && s[1] == '.') {
+ if (!w1)
+ weprintf("\".\" and \"..\" may not be removed\n");
+ w1 = 1;
+ return 1;
+ }
+
+ if (stat(path, &st) < 0)
+ eprintf("stat argument '%s':", path);
+ if (st.st_dev == root->st_dev && st.st_ino == root->st_ino) {
+ if (!w2)
+ weprintf("\"/\" may not be removed\n");
+ w2 = 1;
+ return 1;
+ }
+
+ return 0;
+}
+
 int
 main(int argc, char *argv[])
 {
+ char *s;
+ struct stat st;
         struct recursor r = { .fn = rm, .maxdepth = 1, .follow = 'P' };
 
         ARGBEGIN {
_AT_@ -38,9 +73,14 @@ main(int argc, char *argv[])
                         return 0;
         }
 
+ if (stat("/", &st) < 0)
+ eprintf("stat root:");
         for (; *argv; argc--, argv++) {
- if (strcmp(*argv, ".") && strcmp(*argv, ".."))
- recurse(AT_FDCWD, *argv, NULL, &r);
+ if (forbidden(*argv, &st)) {
+ rm_status = 1;
+ continue;
+ }
+ recurse(AT_FDCWD, *argv, NULL, &r);
         }
 
         return rm_status || recurse_status;
Received on Fri Apr 25 2025 - 18:45:57 CEST

This archive was generated by hypermail 2.3.0 : Fri Apr 25 2025 - 18:48:41 CEST