Introduction
Introduction Statistics Contact Development Disclaimer Help
rm: Use basenames to protect against . and .. - sbase - suckless unix tools
git clone git://git.suckless.org/sbase
Log
Files
Refs
README
LICENSE
---
commit b27871013b1debede7a5177f915be3f7b75aaee3
parent d4dfd42d3580ad36bedfdc5b8924ff6683981f53
Author: Roberto E. Vargas Caballero <[email protected]>
Date: Fri, 25 Apr 2025 12:37:10 +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).
Diffstat:
M rm.c | 44 +++++++++++++++++++++++++++++…
1 file changed, 42 insertions(+), 2 deletions(-)
---
diff --git a/rm.c b/rm.c
@@ -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 {
@@ -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;
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.