commit: 19c387aa62dc66647da6b3ded8f9c255cab086e8
parent 50861bc1e07d70ad37a4a9d6c7d3e769c98a2a83
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Mon, 29 Dec 2025 23:24:47 +0100
cmd/chown: Add depth counter against recursion
Diffstat:
1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/cmd/chown.c b/cmd/chown.c
@@ -28,6 +28,8 @@
#include <getopt.h>
#endif
+#define DEPTH_MAX 100
+
const char *argv0 = NULL;
static uid_t user = (uid_t)-1;
@@ -44,7 +46,8 @@ enum chown_follow_symlinks
};
static int
-do_fchownat(int fd, char *name, char *acc_path, enum chown_follow_symlinks follow_symlinks)
+do_fchownat(
+ int fd, char *name, char *acc_path, enum chown_follow_symlinks follow_symlinks, unsigned depth)
{
struct stat stats;
int err = 0;
@@ -52,6 +55,16 @@ do_fchownat(int fd, char *name, char *acc_path, enum chown_follow_symlinks follo
int stat_opts = (follow_symlinks == CHOWN_FOLLOW_NO_SYMLINK) ? AT_SYMLINK_NOFOLLOW : 0;
int chown_opts = (follow_symlinks == CHOWN_FOLLOW_NO_SYMLINK) ? AT_SYMLINK_NOFOLLOW : 0;
+ if(depth == DEPTH_MAX)
+ {
+ fprintf(stderr,
+ "%s: error: Maximum levels of recursion (%d) reached at file '%s'\n",
+ argv0,
+ depth,
+ acc_path);
+ return 1;
+ }
+
if(fstatat(fd, name, &stats, stat_opts) != 0)
{
fprintf(stderr,
@@ -165,7 +178,7 @@ do_fchownat(int fd, char *name, char *acc_path, enum chown_follow_symlinks follo
(follow_symlinks == CHOWN_FOLLOW_ONE_SYMLINK) ? CHOWN_FOLLOW_NO_SYMLINK : follow_symlinks;
// No depth counter for now, unlikely to be a problem as symlinks aren't followed
- int ret = do_fchownat(dir, dp->d_name, new_path, child_follow_symlinks);
+ int ret = do_fchownat(dir, dp->d_name, new_path, child_follow_symlinks, depth + 1);
if(ret != 0) return ret;
}
@@ -310,7 +323,7 @@ main(int argc, char *argv[])
for(int i = 0; i < argc; i++)
{
- int ret = do_fchownat(AT_FDCWD, argv[i], argv[i], follow_symlinks);
+ int ret = do_fchownat(AT_FDCWD, argv[i], argv[i], follow_symlinks, 0);
if(ret != 0) return ret;
}
@@ -349,7 +362,7 @@ main(int argc, char *argv[])
for(int i = 1; i < argc; i++)
{
- int ret = do_fchownat(AT_FDCWD, argv[i], argv[i], follow_symlinks);
+ int ret = do_fchownat(AT_FDCWD, argv[i], argv[i], follow_symlinks, 0);
if(ret != 0) return ret;
}