Skip to content

Commit

Permalink
debugfs: expose a preserve command line switch in rdump command
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
qkaiser committed Feb 14, 2024
1 parent df13395 commit 06f383f
Showing 1 changed file with 48 additions and 15 deletions.
63 changes: 48 additions & 15 deletions debugfs/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,15 @@ static void rdump_symlink(ext2_ino_t ino, struct ext2_inode *inode,
free(buf);
}

typedef struct {
char* fullname;
int preserve;
} rdump_dirent_private;

static int rdump_dirent(struct ext2_dir_entry *, int, int, char *, void *);

static int rdump_inode(ext2_ino_t ino, struct ext2_inode *inode,
const char *name, const char *dumproot)
const char *name, const char *dumproot, int preserve)
{
char *fullname;
int result = 0;
Expand All @@ -290,7 +295,7 @@ static int rdump_inode(ext2_ino_t ino, struct ext2_inode *inode,
goto errout;
}

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

rdump_dirent_private* entry = malloc(sizeof(rdump_dirent_private));
if (entry == NULL) {
com_err("rdump", errno, "while allocating entry for %s", fullname);
goto errout;
}
entry->fullname = fullname;
entry->preserve = preserve;

retval = ext2fs_dir_iterate(current_fs, ino, 0, 0,
rdump_dirent, (void *) fullname);
rdump_dirent, (void *) entry);
free(entry);
if (retval) {
com_err("rdump", retval, "while dumping %s", fullname);
result = 1;
}

fix_perms("rdump", inode, -1, fullname);
if (preserve)
fix_perms("rdump", inode, -1, fullname);
}
/* else do nothing (don't dump device files, sockets, fifos, etc.) */

Expand All @@ -338,29 +352,42 @@ static int rdump_dirent(struct ext2_dir_entry *dirent,
{
char name[EXT2_NAME_LEN + 1];
int thislen;
const char *dumproot = private;
struct ext2_inode inode;

rdump_dirent_private *dirent_private = (rdump_dirent_private *) private;
thislen = ext2fs_dirent_name_len(dirent);
strncpy(name, dirent->name, thislen);
name[thislen] = 0;

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

return rdump_inode(dirent->inode, &inode, name, dumproot);
return rdump_inode(dirent->inode, &inode, name, dirent_private->fullname, dirent_private->preserve);
}

void do_rdump(int argc, char **argv, int sci_idx,
void *infop EXT2FS_ATTR((unused)))
{
struct stat st;
char *dest_dir;
int i;
int i, c;
int preserve = 0;
ext2_ino_t ino;
struct ext2_inode inode;

if (common_args_process(argc, argv, 3, INT_MAX, "rdump",
"<directory>... <native directory>", 0))
return;
reset_getopt();
while ((c = getopt(argc, argv, "p")) != EOF) {
switch (c) {
case 'p':
preserve++;
break;
default:
goto print_usage;
}
}

if (optind > argc - 2)
goto print_usage;

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

for (i = 1; i < argc; i++) {
for (i = optind; i < argc; i++) {
char *arg = argv[i], *basename;
struct ext2_inode inode;
ext2_ino_t ino = string_to_inode(arg);
ino = string_to_inode(arg);
if (!ino)
continue;

Expand All @@ -392,9 +418,16 @@ void do_rdump(int argc, char **argv, int sci_idx,
else
basename = arg;

if (rdump_inode(ino, &inode, basename, dest_dir) != 0)
if (rdump_inode(ino, &inode, basename, dest_dir, preserve) != 0)
ss_set_exit_status(sci_idx, 1);
}
return;

print_usage:
com_err(argv[0], 0,
"Usage: rdump [-p] "
"<fs_directory>... <output_directory>");
ss_set_exit_status(sci_idx, 1);
}

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

0 comments on commit 06f383f

Please sign in to comment.