mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 00:32:25 -04:00
Notice when mkdir() fails.
Don't change permissions on an existing dir unless _EXTRACT_PERM is requested. In particular, bsdtar -x should not edit mode of existing dirs now; bsdtar -xp will.
This commit is contained in:
parent
ac6b4cf110
commit
e2d97e54d0
3 changed files with 73 additions and 11 deletions
|
|
@ -9,7 +9,7 @@ LDADD= -lbz2 -lz
|
|||
# Major: Bumped ONLY when API/ABI breakage happens (see SHLIB_MAJOR)
|
||||
# Minor: Bumped when significant new features are added
|
||||
# Revision: Bumped on any notable change
|
||||
VERSION= 2.0.24
|
||||
VERSION= 2.0.25
|
||||
|
||||
ARCHIVE_API_MAJOR!= echo ${VERSION} | sed -e 's/[^0-9]/./g' -e 's/\..*//'
|
||||
ARCHIVE_API_MINOR!= echo ${VERSION} | sed -e 's/[^0-9]/./g' -e 's/[0-9]*\.//' -e 's/\..*//'
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ struct fixup_entry {
|
|||
* that verification can occur explicitly through a stat() call or
|
||||
* implicitly because of a successful chown() call.
|
||||
*/
|
||||
#define TODO_MODE_FORCE 0x40000000
|
||||
#define TODO_MODE_BASE 0x20000000
|
||||
#define TODO_SUID 0x10000000
|
||||
#define TODO_SUID_CHECK 0x08000000
|
||||
|
|
@ -320,6 +321,7 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
|
|||
/* Figure out what we need to do for this entry. */
|
||||
a->todo = TODO_MODE_BASE;
|
||||
if (a->flags & ARCHIVE_EXTRACT_PERM) {
|
||||
a->todo |= TODO_MODE_FORCE; /* Be pushy about permissions. */
|
||||
/*
|
||||
* SGID requires an extra "check" step because we
|
||||
* cannot easily predict the GID that the system will
|
||||
|
|
@ -732,9 +734,12 @@ restore_entry(struct archive_write_disk *a)
|
|||
* There's a dir in the way of a dir. Don't
|
||||
* waste time with rmdir()/mkdir(), just fix
|
||||
* up the permissions on the existing dir.
|
||||
* Note that we don't change perms on existing
|
||||
* dirs unless _EXTRACT_PERM is specified.
|
||||
*/
|
||||
if (a->mode != a->st.st_mode)
|
||||
a->deferred |= TODO_MODE;
|
||||
if ((a->mode != a->st.st_mode)
|
||||
&& (a->todo & TODO_MODE_FORCE))
|
||||
a->deferred |= (a->todo & TODO_MODE);
|
||||
/* Ownership doesn't need deferred fixup. */
|
||||
en = 0; /* Forget the EEXIST. */
|
||||
}
|
||||
|
|
@ -806,13 +811,15 @@ create_filesystem_object(struct archive_write_disk *a)
|
|||
case S_IFDIR:
|
||||
mode = (mode | MINIMUM_DIR_MODE) & MAXIMUM_DIR_MODE;
|
||||
r = mkdir(a->name, mode);
|
||||
/* Defer setting dir times. */
|
||||
a->deferred |= (a->todo & TODO_TIMES);
|
||||
a->todo &= ~TODO_TIMES;
|
||||
/* Never use an immediate chmod(). */
|
||||
if (mode != final_mode)
|
||||
a->deferred |= (a->todo & TODO_MODE);
|
||||
a->todo &= ~TODO_MODE;
|
||||
if (r == 0) {
|
||||
/* Defer setting dir times. */
|
||||
a->deferred |= (a->todo & TODO_TIMES);
|
||||
a->todo &= ~TODO_TIMES;
|
||||
/* Never use an immediate chmod(). */
|
||||
if (mode != final_mode)
|
||||
a->deferred |= (a->todo & TODO_MODE);
|
||||
a->todo &= ~TODO_MODE;
|
||||
}
|
||||
break;
|
||||
case S_IFIFO:
|
||||
r = mkfifo(a->name, mode);
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ searchgid(void)
|
|||
return;
|
||||
_searched = 1;
|
||||
|
||||
/* Create a file on disk. */
|
||||
/* Create a file on disk in the current default dir. */
|
||||
fd = open("test_gid", O_CREAT, 0664);
|
||||
failure("Couldn't create a file for gid testing.");
|
||||
assert(fd > 0);
|
||||
|
|
@ -136,6 +136,49 @@ DEFINE_TEST(test_write_disk_perms)
|
|||
assert(0 == archive_write_header(a, ae));
|
||||
assert(0 == archive_write_finish_entry(a));
|
||||
|
||||
/* Write a regular file, then write over it. */
|
||||
/* For files, the perms should get updated. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file_overwrite_0144");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0777);
|
||||
assert(0 == archive_write_header(a, ae));
|
||||
assert(0 == archive_write_finish_entry(a));
|
||||
/* Check that file was created with different perms. */
|
||||
assert(0 == stat("file_overwrite_0144", &st));
|
||||
failure("file_overwrite_0144: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) != 0144);
|
||||
/* Overwrite, this should change the perms. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file_overwrite_0144");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0144);
|
||||
assert(0 == archive_write_header(a, ae));
|
||||
assert(0 == archive_write_finish_entry(a));
|
||||
|
||||
/* Write a regular dir. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "dir_0514");
|
||||
archive_entry_set_mode(ae, S_IFDIR | 0514);
|
||||
assert(0 == archive_write_header(a, ae));
|
||||
assert(0 == archive_write_finish_entry(a));
|
||||
|
||||
/* Overwrite an existing dir. */
|
||||
/* For dir, the first perms should get left. */
|
||||
assert(mkdir("dir_overwrite_0744", 0744) == 0);
|
||||
/* Check original perms. */
|
||||
assert(0 == stat("dir_overwrite_0744", &st));
|
||||
failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == 0744);
|
||||
/* Overwrite shouldn't edit perms. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "dir_overwrite_0744");
|
||||
archive_entry_set_mode(ae, S_IFDIR | 0777);
|
||||
assert(0 == archive_write_header(a, ae));
|
||||
assert(0 == archive_write_finish_entry(a));
|
||||
/* Make sure they're unchanged. */
|
||||
assert(0 == stat("dir_overwrite_0744", &st));
|
||||
failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == 0744);
|
||||
|
||||
/* Write a regular file with SUID bit, but don't use _EXTRACT_PERM. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "file_no_suid");
|
||||
|
|
@ -268,6 +311,18 @@ DEFINE_TEST(test_write_disk_perms)
|
|||
failure("file_0755: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == 0755);
|
||||
|
||||
assert(0 == stat("file_overwrite_0144", &st));
|
||||
failure("file_overwrite_0144: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == 0144);
|
||||
|
||||
assert(0 == stat("dir_0514", &st));
|
||||
failure("dir_0514: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == 0514);
|
||||
|
||||
assert(0 == stat("dir_overwrite_0744", &st));
|
||||
failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == 0744);
|
||||
|
||||
assert(0 == stat("file_no_suid", &st));
|
||||
failure("file_0755: st.st_mode=%o", st.st_mode);
|
||||
assert((st.st_mode & 07777) == 0755);
|
||||
|
|
|
|||
Loading…
Reference in a new issue