Skip to content

Commit 37bff00

Browse files
committed
debugfs: expose a preserve command line switch in rdump command
rdump assumed the user wanted to preserve permissions and ownership when dumping a filesystem directory recursively with 'rdump'. This is in opposition with the way the 'dump' or 'dump_inode' command has been designed, since it expose a '-p' command line switch to allow the end users to explicitly opt-in for permission and ownership preservation. The inability to explicitly ask for permission and ownership preservation would get rdump to default to preservation, which is a problem when faced with filesystems having directories with the read flag but not the execute flag, since it would only allow to enumerate the directory content, but not see the inode details. Therefore getting debugfs in all kinds of issues trying to set ownership and permissions of files it can't see. This fix introduce a 'preserve' ('-p') flag in rdump command so that users can explicitly opt-in for it, and debugfs will default to a safer way of operation (no preserve).
1 parent df13395 commit 37bff00

File tree

1 file changed

+46
-15
lines changed

1 file changed

+46
-15
lines changed

debugfs/dump.c

+46-15
Original file line numberDiff line numberDiff line change
@@ -262,10 +262,15 @@ static void rdump_symlink(ext2_ino_t ino, struct ext2_inode *inode,
262262
free(buf);
263263
}
264264

265+
typedef struct {
266+
char* fullname;
267+
int preserve;
268+
} rdump_dirent_private;
269+
265270
static int rdump_dirent(struct ext2_dir_entry *, int, int, char *, void *);
266271

267272
static int rdump_inode(ext2_ino_t ino, struct ext2_inode *inode,
268-
const char *name, const char *dumproot)
273+
const char *name, const char *dumproot, int preserve)
269274
{
270275
char *fullname;
271276
int result = 0;
@@ -290,7 +295,7 @@ static int rdump_inode(ext2_ino_t ino, struct ext2_inode *inode,
290295
goto errout;
291296
}
292297

293-
if (dump_file("rdump", ino, fd, 1, fullname) != 0) {
298+
if (dump_file("rdump", ino, fd, preserve, fullname) != 0) {
294299
result = 1;
295300
com_err("rdump", errno, "while dumping %s", fullname);
296301
}
@@ -315,14 +320,23 @@ static int rdump_inode(ext2_ino_t ino, struct ext2_inode *inode,
315320
goto errout;
316321
}
317322

323+
rdump_dirent_private* entry = malloc(sizeof(rdump_dirent_private));
324+
if (entry == NULL) {
325+
com_err("rdump", errno, "while allocating entry for %s", fullname);
326+
goto errout;
327+
}
328+
entry->fullname = fullname;
329+
entry->preserve = preserve;
330+
318331
retval = ext2fs_dir_iterate(current_fs, ino, 0, 0,
319-
rdump_dirent, (void *) fullname);
332+
rdump_dirent, (void *) entry);
333+
free(entry);
320334
if (retval) {
321335
com_err("rdump", retval, "while dumping %s", fullname);
322336
result = 1;
323337
}
324-
325-
fix_perms("rdump", inode, -1, fullname);
338+
if (preserve)
339+
fix_perms("rdump", inode, -1, fullname);
326340
}
327341
/* else do nothing (don't dump device files, sockets, fifos, etc.) */
328342

@@ -338,29 +352,42 @@ static int rdump_dirent(struct ext2_dir_entry *dirent,
338352
{
339353
char name[EXT2_NAME_LEN + 1];
340354
int thislen;
341-
const char *dumproot = private;
342355
struct ext2_inode inode;
343356

357+
rdump_dirent_private *dirent_private = (rdump_dirent_private *) private;
344358
thislen = ext2fs_dirent_name_len(dirent);
345359
strncpy(name, dirent->name, thislen);
346360
name[thislen] = 0;
347361

348362
if (debugfs_read_inode(dirent->inode, &inode, name))
349363
return 0;
350364

351-
return rdump_inode(dirent->inode, &inode, name, dumproot);
365+
return rdump_inode(dirent->inode, &inode, name, dirent_private->fullname, dirent_private->preserve);
352366
}
353367

354368
void do_rdump(int argc, char **argv, int sci_idx,
355369
void *infop EXT2FS_ATTR((unused)))
356370
{
357371
struct stat st;
358372
char *dest_dir;
359-
int i;
373+
int i, c;
374+
int preserve = 0;
375+
ext2_ino_t ino;
376+
struct ext2_inode inode;
360377

361-
if (common_args_process(argc, argv, 3, INT_MAX, "rdump",
362-
"<directory>... <native directory>", 0))
363-
return;
378+
reset_getopt();
379+
while ((c = getopt(argc, argv, "p")) != EOF) {
380+
switch (c) {
381+
case 'p':
382+
preserve++;
383+
break;
384+
default:
385+
goto print_usage;
386+
}
387+
}
388+
389+
if (optind > argc - 2)
390+
goto print_usage;
364391

365392
/* Pull out last argument */
366393
dest_dir = argv[argc - 1];
@@ -376,10 +403,9 @@ void do_rdump(int argc, char **argv, int sci_idx,
376403
return;
377404
}
378405

379-
for (i = 1; i < argc; i++) {
406+
for (i = optind; i < argc; i++) {
380407
char *arg = argv[i], *basename;
381-
struct ext2_inode inode;
382-
ext2_ino_t ino = string_to_inode(arg);
408+
ino = string_to_inode(arg);
383409
if (!ino)
384410
continue;
385411

@@ -392,9 +418,14 @@ void do_rdump(int argc, char **argv, int sci_idx,
392418
else
393419
basename = arg;
394420

395-
if (rdump_inode(ino, &inode, basename, dest_dir) != 0)
421+
if (rdump_inode(ino, &inode, basename, dest_dir, preserve) != 0)
396422
ss_set_exit_status(sci_idx, 1);
397423
}
424+
print_usage:
425+
com_err(argv[0], 0,
426+
"Usage: rdump [-p] "
427+
"<fs_directory>... <output_file>");
428+
ss_set_exit_status(sci_idx, 1);
398429
}
399430

400431
void do_cat(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)),

0 commit comments

Comments
 (0)