8000 MFV r305816: · freebsd/freebsd-src@dfb2179 · GitHub
[go: up one dir, main page]

Skip to content

Commit dfb2179

Browse files
committed
MFV r305816:
Sync libarchive with vendor including important security fixes. Issues fixed (FreeBSD): PR #778: ACL error handling Issue #745: Symlink check prefix optimization is too aggressive Issue #746: Hard links with data can evade sandboxing restrictions This update fixes the vulnerability #3 and vulnerability #4 as reported in "non-cryptanalytic attacks against FreeBSD update components". https://gist.github.com/anonymous/e48209b03f1dd9625a992717e7b89c4f Fix for vulnerability #2 has already been merged in r304989. MFC after: 1 week Security: http://gist.github.com/anonymous/e48209b03f1dd9625a992717e7b89c4f
1 parent 6b0578f commit dfb2179

10 files changed

+469
-152
lines changed

contrib/libarchive/libarchive/archive_platform.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,15 @@
159159
#define CAN_RESTORE_METADATA_FD
160160
#endif
161161

162+
/*
163+
* glibc 2.24 deprecates readdir_r
164+
*/
165+
#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24))
166+
#define USE_READDIR_R 1
167+
#else
168+
#undef USE_READDIR_R
169+
#endif
170+
162171
/* Set up defaults for internal error codes. */
163172
#ifndef ARCHIVE_ERRNO_FILE_FORMAT
164173
#if HAVE_EFTYPE

contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c

Lines changed: 94 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -411,9 +411,7 @@ setup_acls(struct archive_read_disk *a,
411411
{
412412
const char *accpath;
413413
acl_t acl;
414-
#if HAVE_ACL_IS_TRIVIAL_NP
415414
int r;
416-
#endif
417415

418416
accpath = archive_entry_sourcepath(entry);
419417
if (accpath == NULL)
@@ -473,9 +471,13 @@ setup_acls(struct archive_read_disk *a,
473471
}
474472
#endif
475473
if (acl != NULL) {
476-
translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
474+
r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
477475
acl_free(acl);
478-
return (ARCHIVE_OK);
476+
if (r != ARCHIVE_OK) {
477+
archive_set_error(&a->archive, errno,
478+
"Couldn't translate NFSv4 ACLs: %s", accpath);
479+
}
480+
return (r);
479481
}
480482
#endif /* ACL_TYPE_NFS4 */
481483

@@ -506,19 +508,30 @@ setup_acls(struct archive_read_disk *a,
506508
#endif
507509

508510
if (acl != NULL) {
509-
translate_acl(a, entry, acl,
511+
r = translate_acl(a, entry, acl,
510512
ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
511513
acl_free(acl);
512514
acl = NULL;
515+
if (r != ARCHIVE_OK) {
516+
archive_set_error(&a->archive, errno,
517+
"Couldn't translate access ACLs: %s", accpath);
518+
return (r);
519+
}
513520
}
514521

515522
/* Only directories can have default ACLs. */
516523
if (S_ISDIR(archive_entry_mode(entry))) {
517524
acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
518525
if (acl != NULL) {
519-
translate_acl(a, entry, acl,
526+
r = translate_acl(a, entry, acl,
520527
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
521528
acl_free(acl);
529+
if (r != ARCHIVE_OK) {
530+
archive_set_error(&a->archive, errno,
531+
"Couldn't translate default ACLs: %s",
532+
accpath);
533+
return (r);
534+
}
522535
}
523536
}
524537
return (ARCHIVE_OK);
@@ -574,51 +587,67 @@ translate_acl(struct archive_read_disk *a,
574587
#ifdef ACL_TYPE_NFS4
575588
acl_entry_type_t acl_type;
576589
acl_flagset_t acl_flagset;
577-
int brand, r;
590+
int brand;
578591
#endif
579592
acl_entry_t acl_entry;
580593
acl_permset_t acl_permset;
581594
int i, entry_acl_type;
582-
int s, ae_id, ae_tag, ae_perm;
595+
int r, s, ae_id, ae_tag, ae_perm;
583596
const char *ae_name;
584597

585598
#ifdef ACL_TYPE_NFS4
586599
// FreeBSD "brands" ACLs as POSIX.1e or NFSv4
587600
// Make sure the "brand" on this ACL is consistent
588601
// with the default_entry_acl_type bits provided.
589-
acl_get_brand_np(acl, &brand);
602+
if (acl_get_brand_np(acl, &brand) != 0) {
603+
archive_set_error(&a->archive, errno,
604+
"Failed to read ACL brand");
605+
return (ARCHIVE_WARN);
606+
}
590607
switch (brand) {
591608
case ACL_BRAND_POSIX:
592609
switch (default_entry_acl_type) {
593610
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
594611
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
595612
break;
596613
default:
597-
// XXX set warning message?
598-
return ARCHIVE_FAILED;
614+
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
615+
"Invalid ACL entry type for POSIX.1e ACL");
616+
return (ARCHIVE_WARN);
599617
}
600618
break;
601619
case ACL_BRAND_NFS4:
602620
if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
603-
// XXX set warning message?
604-
return ARCHIVE_FAILED;
621+
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
622+
"Invalid ACL entry type for NFSv4 ACL");
623+
return (ARCHIVE_WARN);
605624
}
606625
break;
607626
default:
608-
// XXX set warning message?
609-
return ARCHIVE_FAILED;
627+
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
628+
"Unknown ACL brand");
629+
return (ARCHIVE_WARN);
610630
break;
611631
}
612632
#endif
613633

614634

615635
s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
636+
if (s == -1) {
637+
archive_set_error(&a->archive, errno,
638+
"Failed to get first ACL entry");
639+
return (ARCHIVE_WARN);
640+
}
616641
while (s == 1) {
617642
ae_id = -1;
618643
ae_name = NULL;
619644
ae_perm = 0;
620645

621-
acl_get_tag_type(acl_entry, &acl_tag);
646+
if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
647+
archive_set_error(&a->archive, errno,
648+
"Failed to get ACL tag type");
649+
return (ARCHIVE_WARN);
650+
}
622651
switch (acl_tag) {
623652
case ACL_USER:
624653
ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
@@ -653,13 +682,18 @@ translate_acl(struct archive_read_disk *a,
653682
continue;
654683
}
655684

656-
// XXX acl type maps to allow/deny/audit/YYYY bits
657-
// XXX acl_get_entry_type_np on FreeBSD returns EINVAL for
658-
// non-NFSv4 ACLs
685+
// XXX acl_type maps to allow/deny/audit/YYYY bits
659686
entry_acl_type = default_entry_acl_type;
660687
#ifdef ACL_TYPE_NFS4
661-
r = acl_get_entry_type_np(acl_entry, &acl_type);
662-
if (r == 0) {
688+
if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
689+
/*
690+
* acl_get_entry_type_np() falis with non-NFSv4 ACLs
691+
*/
692+
if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
693+
archive_set_error(&a->archive, errno, "Failed "
694+
"to get ACL type from a NFSv4 ACL entry");
695+
return (ARCHIVE_WARN);
696+
}
663697
switch (acl_type) {
664698
case ACL_ENTRY_TYPE_ALLOW:
665699
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
@@ -673,32 +707,53 @@ translate_acl(struct archive_read_disk *a,
673707
case ACL_ENTRY_TYPE_ALARM:
674708
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
675709
break;
710+
default:
711+
archive_set_error(&a->archive, errno,
712+
"Invalid NFSv4 ACL entry type");
713+
return (ARCHIVE_WARN);
676714
}
677-
}
678715

679-
/*
680-
* Libarchive stores "flag" (NFSv4 inheritance bits)
681-
* in the ae_perm bitmap.
682-
*/
683-
// XXX acl_get_flagset_np on FreeBSD returns EINVAL for
684-
// non-NFSv4 ACLs
685-
r = acl_get_flagset_np(acl_entry, &acl_flagset);
686-
if (r == 0) {
716+
/*
717+
* Libarchive stores "flag" (NFSv4 inheritance bits)
718+
* in the ae_perm bitmap.
719+
*
720+
* acl_get_flagset_np() fails with non-NFSv4 ACLs
721+
*/
722+
if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
723+
archive_set_error(&a->archive, errno,
724+
"Failed to get flagset from a NFSv4 ACL entry");
725+
return (ARCHIVE_WARN);
726+
}
687727
for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
688-
if (acl_get_flag_np(acl_flagset,
689-
acl_inherit_map[i].platform_inherit))
728+
r = acl_get_flag_np(acl_flagset,
729+
acl_inherit_map[i].platform_inherit);
730+
if (r == -1) {
731+
archive_set_error(&a->archive, errno,
732+
"Failed to check flag in a NFSv4 "
733+
"ACL flagset");
734+
return (ARCHIVE_WARN);
735+
} else if (r)
690736
ae_perm |= acl_inherit_map[i].archive_inherit;
691737
}
692738
}
693739
#endif
694740

695-
acl_get_permset(acl_entry, &acl_permset);
741+
if (acl_get_permset(acl_entry, &acl_permset) != 0) {
742+
archive_set_error(&a->archive, errno,
743+
"Failed to get ACL permission set");
744+
return (ARCHIVE_WARN);
745+
}
696746
for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
697747
/*
698748
* acl_get_perm() is spelled differently on different
699749
* platforms; see above.
700750
*/
701-
if (ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm))
751+
r = ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm);
752+
if (r == -1) {
753+
archive_set_error(&a->archive, errno,
754+
"Failed to check permission in an ACL permission set");
755+
return (ARCHIVE_WARN);
756+
} else if (r)
702757
ae_perm |= acl_perm_map[i].archive_perm;
703758
}
704759

@@ -707,6 +762,11 @@ translate_acl(struct archive_read_disk *a,
707762
ae_id, ae_name);
708763

709764
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
765+
if (s == -1) {
766+
archive_set_error(&a->archive, errno,
767+
"Failed to get next ACL entry");
768+
return (ARCHIVE_WARN);
769+
}
710770
}
711771
return (ARCHIVE_OK);
712772
}

contrib/libarchive/libarchive/archive_read_disk_posix.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ struct filesystem {
165165
int synthetic;
166166
int remote;
167167
int noatime;
168-
#if defined(HAVE_READDIR_R)
168+
#if defined(USE_READDIR_R)
169169
size_t name_max;
170170
#endif
171171
long incr_xfer_size;
@@ -200,7 +200,7 @@ struct tree {
200200
DIR *d;
201201
#define INVALID_DIR_HANDLE NULL
202202
struct dirent *de;
203-
#if defined(HAVE_READDIR_R)
203+
#if defined(USE_READDIR_R)
204204
struct dirent *dirent;
205205
size_t dirent_allocated;
206206
#endif
@@ -1592,7 +1592,7 @@ setup_current_filesystem(struct archive_read_disk *a)
15921592
#endif
15931593
t->current_filesystem->noatime = 0;
15941594

1595-
#if defined(HAVE_READDIR_R)
1595+
#if defined(USE_READDIR_R)
15961596
/* Set maximum filename length. */
15971597
#if defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
15981598
t->current_filesystem->name_max = sfs.f_namemax;
@@ -1615,7 +1615,7 @@ setup_current_filesystem(struct archive_read_disk *a)
16151615
else
16161616
t->current_filesystem->name_max = nm;
16171617
#endif
1618-
#endif /* HAVE_READDIR_R */
1618+
#endif /* USE_READDIR_R */
16191619
return (ARCHIVE_OK);
16201620
}
16211621

@@ -1817,7 +1817,7 @@ setup_current_filesystem(struct archive_read_disk *a)
18171817
#endif
18181818
t->current_filesystem->noatime = 0;
18191819

1820-
#if defined(HAVE_READDIR_R)
1820+
#if defined(USE_READDIR_R)
18211821
/* Set maximum filename length. */
18221822
t->current_filesystem->name_max = sfs.f_namelen;
18231823
#endif
@@ -1901,7 +1901,7 @@ setup_current_filesystem(struct archive_read_disk *a)
19011901
#endif
19021902
t->current_filesystem->noatime = 0;
19031903

1904-
#if defined(HAVE_READDIR_R)
1904+
#if defined(USE_READDIR_R)
19051905
/* Set maximum filename length. */
19061906
t->current_filesystem->name_max = sfs.f_namemax;
19071907
#endif
@@ -1918,7 +1918,7 @@ static int
19181918
setup_current_filesystem(struct archive_read_disk *a)
19191919
{
19201920
struct tree *t = a->tree;
1921-
#if defined(_PC_NAME_MAX) && defined(HAVE_READDIR_R)
1921+
#if defined(_PC_NAME_MAX) && defined(USE_READDIR_R)
19221922
long nm;
19231923
#endif
19241924
t->current_filesystem->synthetic = -1;/* Not supported */
@@ -1930,7 +1930,7 @@ setup_current_filesystem(struct archive_read_disk *a)
19301930
t->current_filesystem->min_xfer_size = -1;
19311931
t->current_filesystem->incr_xfer_size = -1;
19321932

1933-
#if defined(HAVE_READDIR_R)
1933+
#if defined(USE_READDIR_R)
19341934
/* Set maximum filename length. */
19351935
# if defined(_PC_NAME_MAX)
19361936
if (tree_current_is_symblic_link_target(t)) {
@@ -1958,7 +1958,7 @@ setup_current_filesystem(struct archive_read_disk *a)
19581958
else
19591959
t->current_filesystem->name_max = nm;
19601960
# endif /* _PC_NAME_MAX */
1961-
#endif /* HAVE_READDIR_R */
1961+
#endif /* USE_READDIR_R */
19621962
return (ARCHIVE_OK);
19631963
}
19641964

@@ -2366,7 +2366,7 @@ tree_dir_next_posix(struct tree *t)
23662366
size_t namelen;
23672367

23682368
if (t->d == NULL) {
2369-
#if defined(HAVE_READDIR_R)
2369+
#if defined(USE_READDIR_R)
23702370
size_t dirent_size;
23712371
#endif
23722372

@@ -2387,7 +2387,7 @@ tree_dir_next_posix(struct tree *t)
23872387
t->visit_type = r != 0 ? r : TREE_ERROR_DIR;
23882388
return (t->visit_type);
23892389
}
2390-
#if defined(HAVE_READDIR_R)
2390+
#if defined(USE_READDIR_R)
23912391
dirent_size = offsetof(struct dirent, d_name) +
23922392
t->filesystem_table[t->current->filesystem_id].name_max + 1;
23932393
if (t->dirent == NULL || t->dirent_allocated < dirent_size) {
@@ -2404,11 +2404,11 @@ tree_dir_next_posix(struct tree *t)
24042404
}
24052405
t->dirent_allocated = dirent_size;
24062406
}
2407-
#endif /* HAVE_READDIR_R */
2407+
#endif /* USE_READDIR_R */
24082408
}
24092409
for (;;) {
24102410
errno = 0;
2411-
#if defined(HAVE_READDIR_R)
2411+
#if defined(USE_READDIR_R)
24122412
r = readdir_r(t->d, t->dirent, &t->de);
24132413
#ifdef _AIX
24142414
/* Note: According to the man page, return value 9 indicates
@@ -2660,7 +2660,7 @@ tree_free(struct tree *t)
26602660
if (t == NULL)
26612661
return;
26622662
archive_string_free(&t->path);
2663-
#if defined(HAVE_READDIR_R)
2663+
#if defined(USE_READDIR_R)
26642664
free(t->dirent);
26652665
#endif
26662666
free(t->sparse_list);

0 commit comments

Comments
 (0)
0