# cherry picked from commit: c62a5331a5feef2b09556546d02a2b2fc67f6e67 # which fixed this CVE in upstream master diff -Naur fdupes-1.51.orig/fdupes.1 fdupes-1.51/fdupes.1 --- fdupes-1.51.orig/fdupes.1 2013-04-20 12:00:09.000000000 -0500 +++ fdupes-1.51/fdupes.1 2013-07-16 13:01:16.264491871 -0500 @@ -56,6 +56,9 @@ when used together with --delete, preserve the first file in each set of duplicates and delete the others without prompting the user .TP +.B -p --permissions +don't consider files with different owner/group or permission bits as duplicates +.TP .B -v --version display fdupes version .TP diff -Naur fdupes-1.51.orig/fdupes.c fdupes-1.51/fdupes.c --- fdupes-1.51.orig/fdupes.c 2013-04-20 13:02:18.000000000 -0500 +++ fdupes-1.51/fdupes.c 2013-07-16 13:03:04.529344704 -0500 @@ -51,6 +51,7 @@ #define F_RECURSEAFTER 0x0200 #define F_NOPROMPT 0x0400 #define F_SUMMARIZEMATCHES 0x0800 +#define F_PERMISSIONS 0x1000 char *program_name; @@ -467,6 +468,19 @@ return 1; } +int same_permissions(char* name1, char* name2) +{ + struct stat s1, s2; + + if (stat(name1, &s1) != 0) return -1; + if (stat(name2, &s2) != 0) return -1; + + return (s1.st_mode == s2.st_mode && + s1.st_uid == s2.st_uid && + s1.st_gid == s2.st_gid); +} + + file_t **checkmatch(filetree_t **root, filetree_t *checktree, file_t *file) { int cmpresult; @@ -489,6 +503,10 @@ cmpresult = -1; else if (fsize > checktree->file->size) cmpresult = 1; + else + if (ISFLAG(flags, F_PERMISSIONS) && + !same_permissions(file->d_name, checktree->file->d_name)) + cmpresult = -1; else { if (checktree->file->crcpartial == NULL) { crcsignature = getcrcpartialsignature(checktree->file->d_name); @@ -958,6 +976,7 @@ printf(" -N --noprompt \ttogether with --delete, preserve the first file in\n"); printf(" \teach set of duplicates and delete the rest without\n"); printf(" \tprompting the user\n"); + printf(" -p --permissions \tdon't consider files with different owner/group or permission bits as duplicates\n"); printf(" -v --version \tdisplay fdupes version\n"); printf(" -h --help \tdisplay this help message\n\n"); #ifdef OMIT_GETOPT_LONG @@ -1000,6 +1019,7 @@ { "noprompt", 0, 0, 'N' }, { "summarize", 0, 0, 'm'}, { "summary", 0, 0, 'm' }, + { "permissions", 0, 0, 'p' }, { 0, 0, 0, 0 } }; #define GETOPT getopt_long @@ -1011,7 +1031,7 @@ oldargv = cloneargs(argc, argv); - while ((opt = GETOPT(argc, argv, "frRq1Ss::HlndvhNm" + while ((opt = GETOPT(argc, argv, "frRq1Ss::HlndvhNmp" #ifndef OMIT_GETOPT_LONG , long_options, NULL #endif @@ -1059,6 +1079,9 @@ case 'm': SETFLAG(flags, F_SUMMARIZEMATCHES); break; + case 'p': + SETFLAG(flags, F_PERMISSIONS); + break; default: fprintf(stderr, "Try `fdupes --help' for more information.\n");