diff options
163 files changed, 1887 insertions, 768 deletions
diff --git a/contrib/blocklist/libexec/blacklistd-helper b/contrib/blocklist/libexec/blacklistd-helper index f92eab8b29bd..fa53c8c84932 100644 --- a/contrib/blocklist/libexec/blacklistd-helper +++ b/contrib/blocklist/libexec/blacklistd-helper @@ -17,24 +17,41 @@ if [ -f "/etc/ipfw-blacklist.rc" ]; then fi if [ -z "$pf" ]; then - for f in npf pf ipf; do - if [ -f "/etc/$f.conf" ]; then + for f in npf pf ipfilter ipfw; do + if [ -x /etc/rc.d/$f ]; then + if /etc/rc.d/$f status >/dev/null 2>&1; then + pf="$f" + break + fi + elif [ -f "/etc/$f.conf" ]; then + # xxx assume a config file means it can be enabled -- + # and the first one wins! pf="$f" break fi done fi +if [ -z "$pf" -a -x "/sbin/iptables" ]; then + pf="iptables" +fi + if [ -z "$pf" ]; then echo "$0: Unsupported packet filter" 1>&2 exit 1 fi +flags= if [ -n "$3" ]; then + raw_proto="$3" proto="proto $3" + if [ $3 = "tcp" ]; then + flags="flags S/SAFR" + fi fi if [ -n "$6" ]; then + raw_port="$6" port="port $6" fi @@ -51,12 +68,65 @@ esac case "$1" in add) case "$pf" in - ipf) - /sbin/ipfstat -io | /sbin/ipf -I -f - >/dev/null 2>&1 - echo block in quick $proto from $addr/$mask to \ - any port=$6 head port$6 | \ - /sbin/ipf -I -f - -s >/dev/null 2>&1 && echo OK + ipfilter) + # N.B.: If you reload /etc/ipf.conf then you need to stop and + # restart blacklistd (and make sure blacklistd_flags="-r"). + # This should normally already be implemented in + # /etc/rc.d/ipfilter, but if then not add the following lines to + # the end of the ipfilter_reload() function: + # + # if checkyesnox blacklistd; then + # /etc/rc.d/blacklistd restart + # fi + # + # XXX we assume the following rule is present in /etc/ipf.conf: + # (should we check? -- it probably cannot be added dynamically) + # + # block in proto tcp/udp from any to any head blacklistd + # + # where "blacklistd" is the default rulename (i.e. "$2") + # + # This rule can come before any rule that logs connections, + # etc., and should be followed by final rules such as: + # + # # log all as-yet unblocked incoming TCP connection + # # attempts + # log in proto tcp from any to any flags S/SAFR + # # last "pass" match wins for all non-blocked packets + # pass in all + # pass out all + # + # I.e. a "pass" rule which will be the final match and override + # the "block". This way the rules added by blacklistd will + # actually block packets, and prevent logging of them as + # connections, because they include the "quick" flag. + # + # N.b.: $port is not included/used in rules -- abusers are cut + # off completely from all services! + # + # Note RST packets are not returned for blocked SYN packets of + # active attacks, so the port will not appear to be closed. + # This will probably give away the fact that a firewall has been + # triggered to block connections, but it prevents generating + # extra outbound traffic, and it may also slow down the attacker + # somewhat. + # + # Note also that we don't block all packets, just new attempts + # to open connections (see $flags above). This allows us to do + # counterespionage against the attacker (or continue to make use + # of any other services that might be on the same subnet as the + # supposed attacker). However it does not kill any active + # connections -- we rely on the reporting daemon to do its own + # protection and cleanup. + # + # N.B.: The rule generated here must exactly match the + # corresponding rule generated for the "rem" command below! + # + echo block in log quick $proto \ + from $addr/$mask to any $flags group $2 | \ + /sbin/ipf -A -f - >/dev/null 2>&1 && echo OK ;; + ipfw) # use $ipfw_offset+$port for rule number rule=$(($ipfw_offset + $6)) @@ -69,10 +139,23 @@ add) table"("$tname")" to any dst-port $6 >/dev/null && \ echo OK ;; + + iptables) + if ! /sbin/iptables --list "$2" >/dev/null 2>&1; then + /sbin/iptables --new-chain "$2" + fi + /sbin/iptables --append INPUT --proto "$raw_proto" \ + --dport "$raw_port" --jump "$2" + /sbin/iptables --append "$2" --proto "$raw_proto" \ + --source "$addr/$mask" --dport "$raw_port" --jump DROP + echo OK + ;; + npf) /sbin/npfctl rule "$2" add block in final $proto from \ "$addr/$mask" to any $port ;; + pf) # if the filtering rule does not exist, create it /sbin/pfctl -a "$2/$6" -sr 2>/dev/null | \ @@ -83,45 +166,100 @@ add) /sbin/pfctl -qa "$2/$6" -t "port$6" -T add "$addr/$mask" && \ /sbin/pfctl -qk "$addr" && echo OK ;; + esac ;; rem) case "$pf" in - ipf) - /sbin/ipfstat -io | /sbin/ipf -I -f - >/dev/null 2>&1 - echo block in quick $proto from $addr/$mask to \ - any port=$6 head port$6 | \ - /sbin/ipf -I -r -f - -s >/dev/null 2>&1 && echo OK + ipfilter) + # N.B.: The rule generated here must exactly match the + # corresponding rule generated for the "add" command above! + # + echo block in log quick $proto \ + from $addr/$mask to any $flags group $2 | \ + /sbin/ipf -A -r -f - >/dev/null 2>&1 && echo OK ;; + ipfw) /sbin/ipfw table "port$6" delete "$addr/$mask" 2>/dev/null && \ echo OK ;; + + iptables) + if /sbin/iptables --list "$2" >/dev/null 2>&1; then + /sbin/iptables --delete "$2" --proto "$raw_proto" \ + --source "$addr/$mask" --dport "$raw_port" \ + --jump DROP + fi + echo OK + ;; + npf) /sbin/npfctl rule "$2" rem-id "$7" ;; + pf) /sbin/pfctl -qa "$2/$6" -t "port$6" -T delete "$addr/$mask" && \ echo OK ;; + esac ;; flush) case "$pf" in - ipf) - /sbin/ipf -Z -I -Fi -s > /dev/null && echo OK + ipfilter) + # + # N.B. WARNING: This is obviously not reentrant! + # + # First we flush all the rules from the inactive set, then we + # reload the ones that do not belong to the group "$2", and + # finally we swap the active and inactive rule sets. + # + /sbin/ipf -I -F a + # + # "ipf -I -F a" also flushes active accounting rules! + # + # Note that accounting rule groups are unique to accounting + # rules and have nothing to do with filter rules, though of + # course theoretically one could use the same group name for + # them too. + # + # In theory anyone using any such accounting rules should have a + # wrapper /etc/rc.conf.d/blacklistd script (and corresponding + # /etc/rc.conf.d/ipfilter script) that will record and + # consolidate the values accumulated by such accounting rules + # before they are flushed, since otherwise their counts will be + # lost forever. + # + /usr/sbin/ipfstat -io | fgrep -v "group $2" | \ + /sbin/ipf -I -f - >/dev/null 2>&1 + # + # This MUST be done last and separately as "-s" is executed + # _while_ the command arguments are being processed! + # + /sbin/ipf -s && echo OK ;; + ipfw) /sbin/ipfw table "port$6" flush 2>/dev/null && echo OK ;; + + iptables) + if /sbin/iptables --list "$2" >/dev/null 2>&1; then + /sbin/iptables --flush "$2" + fi + echo OK + ;; + npf) /sbin/npfctl rule "$2" flush ;; + pf) # dynamically determine which anchors exist - for anchor in $(/sbin/pfctl -a "$2" -s Anchors); do - /sbin/pfctl -a $anchor -t "port${anchor##*/}" -T flush - /sbin/pfctl -a $anchor -F rules + for anchor in $(/sbin/pfctl -a "$2" -s Anchors 2> /dev/null); do + /sbin/pfctl -a "$anchor" -t "port${anchor##*/}" -T flush + /sbin/pfctl -a "$anchor" -F rules done echo OK ;; diff --git a/contrib/libarchive/NEWS b/contrib/libarchive/NEWS index caca7d5cbdb9..f2dd4102fa04 100644 --- a/contrib/libarchive/NEWS +++ b/contrib/libarchive/NEWS @@ -1,3 +1,5 @@ +Oct 15, 2026: libarchive 3.8.2 released + Jun 01, 2026: libarchive 3.8.1 released May 20, 2025: libarchive 3.8.0 released diff --git a/contrib/libarchive/SECURITY.md b/contrib/libarchive/SECURITY.md index 6ca188b603fe..f2f60e792a57 100644 --- a/contrib/libarchive/SECURITY.md +++ b/contrib/libarchive/SECURITY.md @@ -16,4 +16,4 @@ Please provide the following information in your report: - How to reproduce the issue This project is maintained by volunteers on a reasonable-effort basis. As such, we ask -that you give me 90 days to work on a fix before public exposure. +that you give us 90 days to work on a fix before public exposure. diff --git a/contrib/libarchive/build/ci/github_actions/install-macos-dependencies.sh b/contrib/libarchive/build/ci/github_actions/install-macos-dependencies.sh index 2aa4823fc3d0..b33aed5e5562 100755 --- a/contrib/libarchive/build/ci/github_actions/install-macos-dependencies.sh +++ b/contrib/libarchive/build/ci/github_actions/install-macos-dependencies.sh @@ -5,6 +5,9 @@ set -eux #brew update > /dev/null #brew upgrade > /dev/null +# Workaround for cmake in local/pinned tap issue +brew uninstall cmake + # This does an upgrade if the package is already installed brew install \ autoconf \ diff --git a/contrib/libarchive/cat/bsdcat.c b/contrib/libarchive/cat/bsdcat.c index 731621fa9b75..2e78870ae50e 100644 --- a/contrib/libarchive/cat/bsdcat.c +++ b/contrib/libarchive/cat/bsdcat.c @@ -7,6 +7,9 @@ #include "bsdcat_platform.h" +#ifdef HAVE_SIGNAL_H +#include <signal.h> +#endif #include <stdio.h> #ifdef HAVE_STDLIB_H #include <stdlib.h> @@ -22,7 +25,7 @@ #include <archive_entry.h> #include "bsdcat.h" -#include "err.h" +#include "lafe_err.h" #define BYTES_PER_BLOCK (20*512) @@ -105,6 +108,16 @@ main(int argc, char **argv) bsdcat = &bsdcat_storage; memset(bsdcat, 0, sizeof(*bsdcat)); +#if defined(HAVE_SIGACTION) && defined(SIGCHLD) + { /* Do not ignore SIGCHLD. */ + struct sigaction sa; + sa.sa_handler = SIG_DFL; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGCHLD, &sa, NULL); + } +#endif + lafe_setprogname(*argv, "bsdcat"); bsdcat->argv = argv; diff --git a/contrib/libarchive/cat/cmdline.c b/contrib/libarchive/cat/cmdline.c index 8ecd74aa95e4..5a5fcaf0263f 100644 --- a/contrib/libarchive/cat/cmdline.c +++ b/contrib/libarchive/cat/cmdline.c @@ -22,7 +22,7 @@ #endif #include "bsdcat.h" -#include "err.h" +#include "lafe_err.h" /* * Short options for bsdcat. Please keep this sorted. diff --git a/contrib/libarchive/cpio/cmdline.c b/contrib/libarchive/cpio/cmdline.c index c67519947dbc..db06c03c011d 100644 --- a/contrib/libarchive/cpio/cmdline.c +++ b/contrib/libarchive/cpio/cmdline.c @@ -26,7 +26,7 @@ #endif #include "cpio.h" -#include "err.h" +#include "lafe_err.h" /* * Short options for cpio. Please keep this sorted. diff --git a/contrib/libarchive/cpio/cpio.c b/contrib/libarchive/cpio/cpio.c index 2bf1bfa2985a..262db510568b 100644 --- a/contrib/libarchive/cpio/cpio.c +++ b/contrib/libarchive/cpio/cpio.c @@ -60,7 +60,7 @@ #endif #include "cpio.h" -#include "err.h" +#include "lafe_err.h" #include "line_reader.h" #include "passphrase.h" @@ -124,13 +124,21 @@ main(int argc, char *argv[]) cpio->buff_size = sizeof(buff); -#if defined(HAVE_SIGACTION) && defined(SIGPIPE) - { /* Ignore SIGPIPE signals. */ +#if defined(HAVE_SIGACTION) + { struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; +#ifdef SIGPIPE + /* Ignore SIGPIPE signals. */ sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, NULL); +#endif +#ifdef SIGCHLD + /* Do not ignore SIGCHLD. */ + sa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &sa, NULL); +#endif } #endif diff --git a/contrib/libarchive/cpio/test/test_owner_parse.c b/contrib/libarchive/cpio/test/test_owner_parse.c index dfc78ca77aec..bd68f21cec9b 100644 --- a/contrib/libarchive/cpio/test/test_owner_parse.c +++ b/contrib/libarchive/cpio/test/test_owner_parse.c @@ -7,7 +7,7 @@ #include "test.h" #include "../cpio.h" -#include "err.h" +#include "lafe_err.h" #if !defined(_WIN32) #define ROOT "root" diff --git a/contrib/libarchive/libarchive/archive.h b/contrib/libarchive/libarchive/archive.h index 002190a24663..98d7674e18f1 100644 --- a/contrib/libarchive/libarchive/archive.h +++ b/contrib/libarchive/libarchive/archive.h @@ -34,7 +34,7 @@ * assert that ARCHIVE_VERSION_NUMBER >= 2012108. */ /* Note: Compiler will complain if this does not match archive_entry.h! */ -#define ARCHIVE_VERSION_NUMBER 3008001 +#define ARCHIVE_VERSION_NUMBER 3008002 #include <sys/stat.h> #include <stddef.h> /* for wchar_t */ @@ -177,7 +177,7 @@ __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_ONLY_STRING "3.8.1" +#define ARCHIVE_VERSION_ONLY_STRING "3.8.2" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); diff --git a/contrib/libarchive/libarchive/archive_acl.c b/contrib/libarchive/libarchive/archive_acl.c index 9e71f5ee5610..362e3308f43f 100644 --- a/contrib/libarchive/libarchive/archive_acl.c +++ b/contrib/libarchive/libarchive/archive_acl.c @@ -270,6 +270,19 @@ acl_new_entry(struct archive_acl *acl, { struct archive_acl_entry *ap, *aq; + /* Reject an invalid type */ + switch (type) { + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: + case ARCHIVE_ENTRY_ACL_TYPE_ALARM: + break; + default: + return (NULL); + } + /* Type argument must be a valid NFS4 or POSIX.1e type. * The type must agree with anything already set and * the permset must be compatible. */ @@ -822,6 +835,9 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int type, wname = NULL; id = -1; break; + default: + **wp = '\0'; + break; } *wp += wcslen(*wp); *(*wp)++ = L':'; @@ -878,6 +894,7 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int type, wcscpy(*wp, L"alarm"); break; default: + *(*wp) = L'\0'; break; } *wp += wcslen(*wp); @@ -1057,6 +1074,9 @@ append_entry(char **p, const char *prefix, int type, name = NULL; id = -1; break; + default: + **p = '\0'; + break; } *p += strlen(*p); *(*p)++ = ':'; @@ -1112,6 +1132,9 @@ append_entry(char **p, const char *prefix, int type, case ARCHIVE_ENTRY_ACL_TYPE_ALARM: strcpy(*p, "alarm"); break; + default: + *(*p) = '\0'; + break; } *p += strlen(*p); } diff --git a/contrib/libarchive/libarchive/archive_check_magic.c b/contrib/libarchive/libarchive/archive_check_magic.c index d12f0c496e27..6b8e0c5595f4 100644 --- a/contrib/libarchive/libarchive/archive_check_magic.c +++ b/contrib/libarchive/libarchive/archive_check_magic.c @@ -30,6 +30,7 @@ #endif #include <stdio.h> +#include <errno.h> #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif @@ -54,8 +55,14 @@ errmsg(const char *m) while (s > 0) { written = write(2, m, s); - if (written <= 0) + if (written == 0) return; + if (written < 0) + { + if (errno == EINTR) + continue; + return; + } m += written; s -= written; } diff --git a/contrib/libarchive/libarchive/archive_cryptor.c b/contrib/libarchive/libarchive/archive_cryptor.c index 1825af4dc510..9f03f9ca6dd0 100644 --- a/contrib/libarchive/libarchive/archive_cryptor.c +++ b/contrib/libarchive/libarchive/archive_cryptor.c @@ -151,7 +151,7 @@ pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt, (void)rounds; /* UNUSED */ (void)derived_key; /* UNUSED */ (void)derived_key_len; /* UNUSED */ - return -1; /* UNSUPPORTED */ + return CRYPTOR_STUB_FUNCTION; /* UNSUPPORTED */ } #endif @@ -439,14 +439,14 @@ aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len) (void)ctx; /* UNUSED */ (void)key; /* UNUSED */ (void)key_len; /* UNUSED */ - return -1; + return CRYPTOR_STUB_FUNCTION; } static int aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) { (void)ctx; /* UNUSED */ - return -1; + return CRYPTOR_STUB_FUNCTION; } static int @@ -469,7 +469,7 @@ aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in, (void)out; /* UNUSED */ (void)out_len; /* UNUSED */ aes_ctr_encrypt_counter(ctx); /* UNUSED */ /* Fix unused function warning */ - return -1; + return CRYPTOR_STUB_FUNCTION; } #else diff --git a/contrib/libarchive/libarchive/archive_cryptor_private.h b/contrib/libarchive/libarchive/archive_cryptor_private.h index 4b3c6c161433..1dbc5c17a01a 100644 --- a/contrib/libarchive/libarchive/archive_cryptor_private.h +++ b/contrib/libarchive/libarchive/archive_cryptor_private.h @@ -43,7 +43,7 @@ int __libarchive_cryptor_build_hack(void); #ifdef __APPLE__ # include <AvailabilityMacros.h> # if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 -# define ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto +# define ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto 1 # endif #endif @@ -144,9 +144,15 @@ typedef struct { #else +#if defined(ARCHIVE_CRYPTO_MD5_WIN) ||\ + defined(ARCHIVE_CRYPTO_SHA1_WIN) ||\ + defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\ + defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\ + defined(ARCHIVE_CRYPTO_SHA512_WIN) #if defined(_WIN32) && !defined(__CYGWIN__) && !(defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA) #define ARCHIVE_CRYPTOR_USE_WINCRYPT 1 #endif +#endif #define AES_BLOCK_SIZE 16 #define AES_MAX_KEY_SIZE 32 @@ -172,6 +178,9 @@ typedef int archive_crypto_ctx; #define archive_encrypto_aes_ctr_release(ctx) \ __archive_cryptor.encrypto_aes_ctr_release(ctx) +/* Stub return value if no encryption support exists. */ +#define CRYPTOR_STUB_FUNCTION -2 + /* Minimal interface to cryptographic functionality for internal use in * libarchive */ struct archive_cryptor diff --git a/contrib/libarchive/libarchive/archive_entry.h b/contrib/libarchive/libarchive/archive_entry.h index 2b917b3fde8e..344f33bffac2 100644 --- a/contrib/libarchive/libarchive/archive_entry.h +++ b/contrib/libarchive/libarchive/archive_entry.h @@ -28,7 +28,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3008001 +#define ARCHIVE_VERSION_NUMBER 3008002 /* * Note: archive_entry.h is for use outside of libarchive; the diff --git a/contrib/libarchive/libarchive/archive_entry_paths.3 b/contrib/libarchive/libarchive/archive_entry_paths.3 index 0f849c9ebb35..f739b172308d 100644 --- a/contrib/libarchive/libarchive/archive_entry_paths.3 +++ b/contrib/libarchive/libarchive/archive_entry_paths.3 @@ -64,7 +64,7 @@ Streaming Archive Library (libarchive, -larchive) .Ft void .Fn archive_entry_copy_hardlink "struct archive_entry *a" "const char *path" .Ft void -.Fn archive_entry_copy_hardlink_w "struct archive_entry *a "const wchar_t *path" +.Fn archive_entry_copy_hardlink_w "struct archive_entry *a" "const wchar_t *path" .Ft int .Fn archive_entry_update_hardlink_utf8 "struct archive_entry *a" "const char *path" .Ft void diff --git a/contrib/libarchive/libarchive/archive_entry_stat.c b/contrib/libarchive/libarchive/archive_entry_stat.c index c4906838ed0f..345d3d29b2f2 100644 --- a/contrib/libarchive/libarchive/archive_entry_stat.c +++ b/contrib/libarchive/libarchive/archive_entry_stat.c @@ -38,6 +38,7 @@ const struct stat * archive_entry_stat(struct archive_entry *entry) { + int64_t size; struct stat *st; if (entry->stat == NULL) { entry->stat = calloc(1, sizeof(*st)); @@ -74,7 +75,10 @@ archive_entry_stat(struct archive_entry *entry) st->st_ino = (ino_t)archive_entry_ino64(entry); st->st_nlink = archive_entry_nlink(entry); st->st_rdev = archive_entry_rdev(entry); - st->st_size = (off_t)archive_entry_size(entry); + size = archive_entry_size(entry); + st->st_size = (off_t)size; + if (st->st_size < 0 || (int64_t)st->st_size != size) + st->st_size = 0; st->st_mode = archive_entry_mode(entry); /* diff --git a/contrib/libarchive/libarchive/archive_parse_date.c b/contrib/libarchive/libarchive/archive_parse_date.c index cda0b11a555f..d9e968387d34 100644 --- a/contrib/libarchive/libarchive/archive_parse_date.c +++ b/contrib/libarchive/libarchive/archive_parse_date.c @@ -703,9 +703,7 @@ Convert(time_t Month, time_t Day, time_t Year, Year += 1900; DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 29 : 28; - /* Checking for 2038 bogusly assumes that time_t is 32 bits. But - I'm too lazy to try to check for time_t overflow in another way. */ - if (Year < EPOCH || Year >= 2038 + if (Year < EPOCH || (sizeof(time_t) <= 4 && Year >= 2038) || Month < 1 || Month > 12 /* Lint fluff: "conversion from long may lose accuracy" */ || Day < 1 || Day > DaysInMonth[(int)--Month] diff --git a/contrib/libarchive/libarchive/archive_platform.h b/contrib/libarchive/libarchive/archive_platform.h index f30df1104c83..33dc5582b7ed 100644 --- a/contrib/libarchive/libarchive/archive_platform.h +++ b/contrib/libarchive/libarchive/archive_platform.h @@ -183,16 +183,6 @@ #define CAN_RESTORE_METADATA_FD #endif -/* - * glibc 2.24 deprecates readdir_r - * bionic c deprecates readdir_r too - */ -#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24)) && (!defined(__ANDROID__)) -#define USE_READDIR_R 1 -#else -#undef USE_READDIR_R -#endif - /* Set up defaults for internal error codes. */ #ifndef ARCHIVE_ERRNO_FILE_FORMAT #if HAVE_EFTYPE diff --git a/contrib/libarchive/libarchive/archive_platform_stat.h b/contrib/libarchive/libarchive/archive_platform_stat.h new file mode 100644 index 000000000000..5432b2f6433a --- /dev/null +++ b/contrib/libarchive/libarchive/archive_platform_stat.h @@ -0,0 +1,45 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Tobias Stoeckmann + * All rights reserved. + */ + +/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */ + +#ifndef ARCHIVE_PLATFORM_STAT_H_INCLUDED +#define ARCHIVE_PLATFORM_STAT_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +#if defined(_WIN32) && !defined(__CYGWIN__) +/* We use _lseeki64() on Windows. */ +typedef int64_t la_seek_t; + +struct la_seek_stat { + int64_t st_mtime; + ino_t st_ino; + unsigned short st_mode; + uint32_t st_nlink; + gid_t st_gid; + la_seek_t st_size; + uid_t st_uid; + dev_t st_dev; + dev_t st_rdev; +}; +typedef struct la_seek_stat la_seek_stat_t; + +#define la_seek_fstat(fd, st) __la_seek_fstat((fd), (st)) +#define la_seek_stat(fd, st) __la_seek_stat((fd), (st)) + +#else +typedef off_t la_seek_t; +typedef struct stat la_seek_stat_t; + +#define la_seek_fstat(fd, st) fstat((fd), (st)) +#define la_seek_stat(fd, st) stat((fd), (st)) +#endif + +#endif /* !ARCHIVE_PLATFORM_STAT_H_INCLUDED */ diff --git a/contrib/libarchive/libarchive/archive_private.h b/contrib/libarchive/libarchive/archive_private.h index 050fc63c0b2e..3a926c6886ad 100644 --- a/contrib/libarchive/libarchive/archive_private.h +++ b/contrib/libarchive/libarchive/archive_private.h @@ -158,6 +158,7 @@ int __archive_check_magic(struct archive *, unsigned int magic, __LA_NORETURN void __archive_errx(int retvalue, const char *msg); void __archive_ensure_cloexec_flag(int fd); +int __archive_get_tempdir(struct archive_string *); int __archive_mktemp(const char *tmpdir); #if defined(_WIN32) && !defined(__CYGWIN__) int __archive_mkstemp(wchar_t *templates); diff --git a/contrib/libarchive/libarchive/archive_read.c b/contrib/libarchive/libarchive/archive_read.c index 50db87017706..c9b9d5981516 100644 --- a/contrib/libarchive/libarchive/archive_read.c +++ b/contrib/libarchive/libarchive/archive_read.c @@ -575,8 +575,7 @@ choose_filters(struct archive_read *a) return (ARCHIVE_OK); } - filter - = calloc(1, sizeof(*filter)); + filter = calloc(1, sizeof(*filter)); if (filter == NULL) return (ARCHIVE_FATAL); filter->bidder = best_bidder; @@ -834,7 +833,9 @@ archive_read_data(struct archive *_a, void *buff, size_t s) r = archive_read_data_block(a, &read_buf, &a->read_data_remaining, &a->read_data_offset); a->read_data_block = read_buf; - if (r == ARCHIVE_EOF) + if (r == ARCHIVE_EOF && + a->read_data_offset == a->read_data_output_offset && + a->read_data_remaining == 0) return (bytes_read); /* * Error codes are all negative, so the status diff --git a/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c b/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c index 19d049770b78..42af4034b07e 100644 --- a/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c +++ b/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c @@ -338,7 +338,7 @@ setup_mac_metadata(struct archive_read_disk *a, int ret = ARCHIVE_OK; void *buff = NULL; int have_attrs; - const char *name, *tempdir; + const char *name; struct archive_string tempfile; (void)fd; /* UNUSED */ @@ -357,13 +357,11 @@ setup_mac_metadata(struct archive_read_disk *a, if (have_attrs == 0) return (ARCHIVE_OK); - tempdir = NULL; - if (issetugid() == 0) - tempdir = getenv("TMPDIR"); - if (tempdir == NULL) - tempdir = _PATH_TMP; archive_string_init(&tempfile); - archive_strcpy(&tempfile, tempdir); + if (__archive_get_tempdir(&tempfile) != ARCHIVE_OK) { + ret = ARCHIVE_WARN; + goto cleanup; + } archive_strcat(&tempfile, "tar.md.XXXXXX"); tempfd = mkstemp(tempfile.s); if (tempfd < 0) { diff --git a/contrib/libarchive/libarchive/archive_read_disk_posix.c b/contrib/libarchive/libarchive/archive_read_disk_posix.c index a7a98e9cb1cd..54a8e66188f8 100644 --- a/contrib/libarchive/libarchive/archive_read_disk_posix.c +++ b/contrib/libarchive/libarchive/archive_read_disk_posix.c @@ -168,9 +168,6 @@ struct filesystem { int synthetic; int remote; int noatime; -#if defined(USE_READDIR_R) - size_t name_max; -#endif long incr_xfer_size; long max_xfer_size; long min_xfer_size; @@ -203,10 +200,6 @@ struct tree { DIR *d; #define INVALID_DIR_HANDLE NULL struct dirent *de; -#if defined(USE_READDIR_R) - struct dirent *dirent; - size_t dirent_allocated; -#endif int flags; int visit_type; /* Error code from last failed operation. */ @@ -869,7 +862,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, tree_enter_initial_dir(t); return (ARCHIVE_FATAL); case TREE_ERROR_DIR: - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + archive_set_error(&a->archive, t->tree_errno, "%s: Couldn't visit directory", tree_current_path(t)); tree_enter_initial_dir(t); @@ -1578,9 +1571,6 @@ setup_current_filesystem(struct archive_read_disk *a) # endif #endif int r, xr = 0; -#if !defined(HAVE_STRUCT_STATFS_F_NAMEMAX) - long nm; -#endif t->current_filesystem->synthetic = -1; t->current_filesystem->remote = -1; @@ -1647,35 +1637,6 @@ setup_current_filesystem(struct archive_read_disk *a) #endif t->current_filesystem->noatime = 0; -#if defined(USE_READDIR_R) - /* Set maximum filename length. */ -#if defined(HAVE_STRUCT_STATFS_F_NAMEMAX) - t->current_filesystem->name_max = sfs.f_namemax; -#else -# if defined(_PC_NAME_MAX) - /* Mac OS X does not have f_namemax in struct statfs. */ - if (tree_current_is_symblic_link_target(t)) { - if (tree_enter_working_dir(t) != 0) { - archive_set_error(&a->archive, errno, "fchdir failed"); - return (ARCHIVE_FAILED); - } - nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX); - } else - nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX); -# else - nm = -1; -# endif - if (nm == -1) - t->current_filesystem->name_max = NAME_MAX; - else - t->current_filesystem->name_max = nm; -#endif - if (t->current_filesystem->name_max == 0) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Cannot determine name_max"); - return (ARCHIVE_FAILED); - } -#endif /* USE_READDIR_R */ return (ARCHIVE_OK); } @@ -1863,19 +1824,6 @@ setup_current_filesystem(struct archive_read_disk *a) #endif t->current_filesystem->noatime = 0; -#if defined(USE_READDIR_R) - /* Set maximum filename length. */ -#if defined(HAVE_STATVFS) - t->current_filesystem->name_max = svfs.f_namemax; -#else - t->current_filesystem->name_max = sfs.f_namelen; -#endif - if (t->current_filesystem->name_max == 0) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Cannot determine name_max"); - return (ARCHIVE_FAILED); - } -#endif return (ARCHIVE_OK); } @@ -1953,15 +1901,6 @@ setup_current_filesystem(struct archive_read_disk *a) #endif t->current_filesystem->noatime = 0; -#if defined(USE_READDIR_R) - /* Set maximum filename length. */ - t->current_filesystem->name_max = svfs.f_namemax; - if (t->current_filesystem->name_max == 0) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Cannot determine name_max"); - return (ARCHIVE_FAILED); - } -#endif return (ARCHIVE_OK); } @@ -1975,9 +1914,6 @@ static int setup_current_filesystem(struct archive_read_disk *a) { struct tree *t = a->tree; -#if defined(_PC_NAME_MAX) && defined(USE_READDIR_R) - long nm; -#endif t->current_filesystem->synthetic = -1;/* Not supported */ t->current_filesystem->remote = -1;/* Not supported */ t->current_filesystem->noatime = 0; @@ -1987,40 +1923,6 @@ setup_current_filesystem(struct archive_read_disk *a) t->current_filesystem->min_xfer_size = -1; t->current_filesystem->incr_xfer_size = -1; -#if defined(USE_READDIR_R) - /* Set maximum filename length. */ -# if defined(_PC_NAME_MAX) - if (tree_current_is_symblic_link_target(t)) { - if (tree_enter_working_dir(t) != 0) { - archive_set_error(&a->archive, errno, "fchdir failed"); - return (ARCHIVE_FAILED); - } - nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX); - } else - nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX); - if (nm == -1) -# endif /* _PC_NAME_MAX */ - /* - * Some systems (HP-UX or others?) incorrectly defined - * NAME_MAX macro to be a smaller value. - */ -# if defined(NAME_MAX) && NAME_MAX >= 255 - t->current_filesystem->name_max = NAME_MAX; -# else - /* No way to get a trusted value of maximum filename - * length. */ - t->current_filesystem->name_max = PATH_MAX; -# endif /* NAME_MAX */ -# if defined(_PC_NAME_MAX) - else - t->current_filesystem->name_max = nm; -# endif /* _PC_NAME_MAX */ - if (t->current_filesystem->name_max == 0) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Cannot determine name_max"); - return (ARCHIVE_FAILED); - } -#endif /* USE_READDIR_R */ return (ARCHIVE_OK); } @@ -2112,8 +2014,11 @@ tree_dup(int fd) } #endif /* F_DUPFD_CLOEXEC */ new_fd = dup(fd); - __archive_ensure_cloexec_flag(new_fd); - return (new_fd); + if (new_fd != -1) { + __archive_ensure_cloexec_flag(new_fd); + return (new_fd); + } + return (-1); } /* @@ -2235,11 +2140,16 @@ tree_reopen(struct tree *t, const char *path, int restore_time) * so try again for execute. The consequences of not opening this are * unhelpful and unnecessary errors later. */ - if (t->initial_dir_fd < 0) + if (t->initial_dir_fd < 0) { t->initial_dir_fd = open(".", o_flag | O_CLOEXEC); + if (t->initial_dir_fd < 0) + return NULL; + } #endif __archive_ensure_cloexec_flag(t->initial_dir_fd); t->working_dir_fd = tree_dup(t->initial_dir_fd); + if (t->working_dir_fd < 0) + return NULL; return (t); } @@ -2449,12 +2359,11 @@ tree_dir_next_posix(struct tree *t) size_t namelen; if (t->d == NULL) { -#if defined(USE_READDIR_R) - size_t dirent_size; -#endif #if defined(HAVE_FDOPENDIR) - t->d = fdopendir(tree_dup(t->working_dir_fd)); + int fd = tree_dup(t->working_dir_fd); + if (fd != -1) + t->d = fdopendir(fd); #else /* HAVE_FDOPENDIR */ if (tree_enter_working_dir(t) == 0) { t->d = opendir("."); @@ -2470,45 +2379,12 @@ tree_dir_next_posix(struct tree *t) t->visit_type = r != 0 ? r : TREE_ERROR_DIR; return (t->visit_type); } -#if defined(USE_READDIR_R) - dirent_size = offsetof(struct dirent, d_name) + - t->filesystem_table[t->current->filesystem_id].name_max + 1; - if (t->dirent == NULL || t->dirent_allocated < dirent_size) { - free(t->dirent); - t->dirent = malloc(dirent_size); - if (t->dirent == NULL) { - closedir(t->d); - t->d = INVALID_DIR_HANDLE; - (void)tree_ascend(t); - tree_pop(t); - t->tree_errno = ENOMEM; - t->visit_type = TREE_ERROR_DIR; - return (t->visit_type); - } - t->dirent_allocated = dirent_size; - } -#endif /* USE_READDIR_R */ } for (;;) { errno = 0; -#if defined(USE_READDIR_R) - r = readdir_r(t->d, t->dirent, &t->de); -#ifdef _AIX - /* Note: According to the man page, return value 9 indicates - * that the readdir_r was not successful and the error code - * is set to the global errno variable. And then if the end - * of directory entries was reached, the return value is 9 - * and the third parameter is set to NULL and errno is - * unchanged. */ - if (r == 9) - r = errno; -#endif /* _AIX */ - if (r != 0 || t->de == NULL) { -#else t->de = readdir(t->d); if (t->de == NULL) { r = errno; -#endif closedir(t->d); t->d = INVALID_DIR_HANDLE; if (r != 0) { @@ -2747,9 +2623,6 @@ tree_free(struct tree *t) if (t == NULL) return; archive_string_free(&t->path); -#if defined(USE_READDIR_R) - free(t->dirent); -#endif free(t->sparse_list); for (i = 0; i < t->max_filesystem_id; i++) free(t->filesystem_table[i].allocation_ptr); diff --git a/contrib/libarchive/libarchive/archive_read_open_fd.c b/contrib/libarchive/libarchive/archive_read_open_fd.c index dc7c9e52c6f6..c85a62a3e2d7 100644 --- a/contrib/libarchive/libarchive/archive_read_open_fd.c +++ b/contrib/libarchive/libarchive/archive_read_open_fd.c @@ -48,6 +48,7 @@ #endif #include "archive.h" +#include "archive_platform_stat.h" struct read_fd_data { int fd; @@ -65,12 +66,12 @@ static int64_t file_skip(struct archive *, void *, int64_t request); int archive_read_open_fd(struct archive *a, int fd, size_t block_size) { - struct stat st; + la_seek_stat_t st; struct read_fd_data *mine; void *b; archive_clear_error(a); - if (fstat(fd, &st) != 0) { + if (la_seek_fstat(fd, &st) != 0) { archive_set_error(a, errno, "Can't stat fd %d", fd); return (ARCHIVE_FATAL); } @@ -133,7 +134,7 @@ static int64_t file_skip(struct archive *a, void *client_data, int64_t request) { struct read_fd_data *mine = (struct read_fd_data *)client_data; - off_t skip = (off_t)request; + la_seek_t skip = (la_seek_t)request; int64_t old_offset, new_offset; int skip_bits = sizeof(skip) * 8 - 1; /* off_t is a signed type. */ @@ -149,7 +150,8 @@ file_skip(struct archive *a, void *client_data, int64_t request) } /* Reduce 'skip' to the next smallest multiple of block_size */ - skip = (off_t)(((int64_t)skip / mine->block_size) * mine->block_size); + skip = (la_seek_t)(((int64_t)skip / mine->block_size) * mine->block_size); + if (skip == 0) return (0); @@ -185,27 +187,28 @@ static int64_t file_seek(struct archive *a, void *client_data, int64_t request, int whence) { struct read_fd_data *mine = (struct read_fd_data *)client_data; - off_t seek = (off_t)request; + la_seek_t seek = (la_seek_t)request; int64_t r; int seek_bits = sizeof(seek) * 8 - 1; /* off_t is a signed type. */ /* We use off_t here because lseek() is declared that way. */ - /* Reduce a request that would overflow the 'seek' variable. */ + /* Do not perform a seek which cannot be fulfilled. */ if (sizeof(request) > sizeof(seek)) { const int64_t max_seek = (((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1; const int64_t min_seek = ~max_seek; - if (request > max_seek) - seek = (off_t)max_seek; - else if (request < min_seek) - seek = (off_t)min_seek; + if (request < min_seek || request > max_seek) { + errno = EOVERFLOW; + goto err; + } } r = lseek(mine->fd, seek, whence); if (r >= 0) return r; +err: if (errno == ESPIPE) { archive_set_error(a, errno, "A file descriptor(%d) is not seekable(PIPE)", mine->fd); diff --git a/contrib/libarchive/libarchive/archive_read_open_file.c b/contrib/libarchive/libarchive/archive_read_open_file.c index 742923abbee9..6ca2ff191aa8 100644 --- a/contrib/libarchive/libarchive/archive_read_open_file.c +++ b/contrib/libarchive/libarchive/archive_read_open_file.c @@ -48,6 +48,7 @@ #endif #include "archive.h" +#include "archive_platform_stat.h" struct read_FILE_data { FILE *f; @@ -65,7 +66,7 @@ static int64_t FILE_skip(struct archive *, void *, int64_t); int archive_read_open_FILE(struct archive *a, FILE *f) { - struct stat st; + la_seek_stat_t st; struct read_FILE_data *mine; size_t block_size = 128 * 1024; void *b; @@ -88,7 +89,7 @@ archive_read_open_FILE(struct archive *a, FILE *f) * streams that don't support fileno()). As a result, fileno() * should be used cautiously.) */ - if (fstat(fileno(mine->f), &st) == 0 && S_ISREG(st.st_mode)) { + if (la_seek_fstat(fileno(mine->f), &st) == 0 && S_ISREG(st.st_mode)) { archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino); /* Enable the seek optimization only for regular files. */ mine->can_skip = 1; @@ -205,15 +206,15 @@ FILE_seek(struct archive *a, void *client_data, int64_t request, int whence) int seek_bits = sizeof(seek) * 8 - 1; (void)a; /* UNUSED */ - /* Reduce a request that would overflow the 'seek' variable. */ + /* Do not perform a seek which cannot be fulfilled. */ if (sizeof(request) > sizeof(seek)) { const int64_t max_seek = (((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1; const int64_t min_seek = ~max_seek; - if (request > max_seek) - seek = max_seek; - else if (request < min_seek) - seek = min_seek; + if (request < min_seek || request > max_seek) { + errno = EOVERFLOW; + goto err; + } } #ifdef __ANDROID__ @@ -236,6 +237,7 @@ FILE_seek(struct archive *a, void *client_data, int64_t request, int whence) } #endif /* If we arrive here, the input is corrupted or truncated so fail. */ +err: archive_set_error(a, errno, "Error seeking in FILE* pointer"); return (ARCHIVE_FATAL); } diff --git a/contrib/libarchive/libarchive/archive_read_open_filename.c b/contrib/libarchive/libarchive/archive_read_open_filename.c index 5f5b3f1f7259..a910eefcbfd2 100644 --- a/contrib/libarchive/libarchive/archive_read_open_filename.c +++ b/contrib/libarchive/libarchive/archive_read_open_filename.c @@ -59,6 +59,7 @@ #endif #include "archive.h" +#include "archive_platform_stat.h" #include "archive_private.h" #include "archive_string.h" @@ -136,8 +137,10 @@ archive_read_open_filenames(struct archive *a, const char **filenames, mine->filename_type = FNT_STDIN; } else mine->filename_type = FNT_MBS; - if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK)) + if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK)) { + free(mine); return (ARCHIVE_FATAL); + } if (filenames == NULL) break; filename = *(filenames++); @@ -216,8 +219,10 @@ archive_read_open_filenames_w(struct archive *a, const wchar_t **wfilenames, archive_string_free(&fn); #endif } - if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK)) + if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK)) { + free(mine); return (ARCHIVE_FATAL); + } if (wfilenames == NULL) break; wfilename = *(wfilenames++); @@ -248,7 +253,7 @@ archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename, static int file_open(struct archive *a, void *client_data) { - struct stat st; + la_seek_stat_t st; struct read_file_data *mine = (struct read_file_data *)client_data; void *buffer; const char *filename = NULL; @@ -313,7 +318,7 @@ file_open(struct archive *a, void *client_data) goto fail; #endif } - if (fstat(fd, &st) != 0) { + if (la_seek_fstat(fd, &st) != 0) { #if defined(_WIN32) && !defined(__CYGWIN__) if (mine->filename_type == FNT_WCS) archive_set_error(a, errno, "Can't stat '%ls'", @@ -482,10 +487,11 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request) struct read_file_data *mine = (struct read_file_data *)client_data; #if defined(_WIN32) && !defined(__CYGWIN__) /* We use _lseeki64() on Windows. */ - int64_t old_offset, new_offset, skip = request; + int64_t old_offset, new_offset; #else - off_t old_offset, new_offset, skip = (off_t)request; + off_t old_offset, new_offset; #endif + la_seek_t skip = (la_seek_t)request; int skip_bits = sizeof(skip) * 8 - 1; /* We use off_t here because lseek() is declared that way. */ @@ -552,21 +558,21 @@ static int64_t file_seek(struct archive *a, void *client_data, int64_t request, int whence) { struct read_file_data *mine = (struct read_file_data *)client_data; - off_t seek = (off_t)request; + la_seek_t seek = (la_seek_t)request; int64_t r; int seek_bits = sizeof(seek) * 8 - 1; /* We use off_t here because lseek() is declared that way. */ - /* Reduce a request that would overflow the 'seek' variable. */ + /* Do not perform a seek which cannot be fulfilled. */ if (sizeof(request) > sizeof(seek)) { const int64_t max_seek = (((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1; const int64_t min_seek = ~max_seek; - if (request > max_seek) - seek = (off_t)max_seek; - else if (request < min_seek) - seek = (off_t)min_seek; + if (request < min_seek || request > max_seek) { + errno = EOVERFLOW; + goto err; + } } r = lseek(mine->fd, seek, whence); @@ -574,6 +580,7 @@ file_seek(struct archive *a, void *client_data, int64_t request, int whence) return r; /* If the input is corrupted or truncated, fail. */ +err: if (mine->filename_type == FNT_STDIN) archive_set_error(a, errno, "Error seeking in stdin"); else if (mine->filename_type == FNT_MBS) diff --git a/contrib/libarchive/libarchive/archive_read_set_format.c b/contrib/libarchive/libarchive/archive_read_set_format.c index c74361b20c13..552ab12d2f92 100644 --- a/contrib/libarchive/libarchive/archive_read_set_format.c +++ b/contrib/libarchive/libarchive/archive_read_set_format.c @@ -37,7 +37,7 @@ int archive_read_set_format(struct archive *_a, int code) { int r1, r2, slots, i; - char str[10]; + const char *str; struct archive_read *a = (struct archive_read *)_a; if ((r1 = archive_read_support_format_by_code(_a, code)) < (ARCHIVE_OK)) @@ -49,49 +49,49 @@ archive_read_set_format(struct archive *_a, int code) switch (code & ARCHIVE_FORMAT_BASE_MASK) { case ARCHIVE_FORMAT_7ZIP: - strcpy(str, "7zip"); + str = "7zip"; break; case ARCHIVE_FORMAT_AR: - strcpy(str, "ar"); + str = "ar"; break; case ARCHIVE_FORMAT_CAB: - strcpy(str, "cab"); + str = "cab"; break; case ARCHIVE_FORMAT_CPIO: - strcpy(str, "cpio"); + str = "cpio"; break; case ARCHIVE_FORMAT_EMPTY: - strcpy(str, "empty"); + str = "empty"; break; case ARCHIVE_FORMAT_ISO9660: - strcpy(str, "iso9660"); + str = "iso9660"; break; case ARCHIVE_FORMAT_LHA: - strcpy(str, "lha"); + str = "lha"; break; case ARCHIVE_FORMAT_MTREE: - strcpy(str, "mtree"); + str = "mtree"; break; case ARCHIVE_FORMAT_RAR: - strcpy(str, "rar"); + str = "rar"; break; case ARCHIVE_FORMAT_RAR_V5: - strcpy(str, "rar5"); + str = "rar5"; break; case ARCHIVE_FORMAT_RAW: - strcpy(str, "raw"); + str = "raw"; break; case ARCHIVE_FORMAT_TAR: - strcpy(str, "tar"); + str = "tar"; break; case ARCHIVE_FORMAT_WARC: - strcpy(str, "warc"); + str = "warc"; break; case ARCHIVE_FORMAT_XAR: - strcpy(str, "xar"); + str = "xar"; break; case ARCHIVE_FORMAT_ZIP: - strcpy(str, "zip"); + str = "zip"; break; default: archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_program.c b/contrib/libarchive/libarchive/archive_read_support_filter_program.c index 9e825223b26c..2c8e45302d8e 100644 --- a/contrib/libarchive/libarchive/archive_read_support_filter_program.c +++ b/contrib/libarchive/libarchive/archive_read_support_filter_program.c @@ -110,7 +110,7 @@ struct program_filter { pid_t child; #endif int exit_status; - int waitpid_return; + pid_t waitpid_return; int child_stdin, child_stdout; char *out_buf; @@ -242,16 +242,13 @@ child_stop(struct archive_read_filter *self, struct program_filter *state) state->waitpid_return = waitpid(state->child, &state->exit_status, 0); } while (state->waitpid_return == -1 && errno == EINTR); -#if defined(_WIN32) && !defined(__CYGWIN__) - CloseHandle(state->child); -#endif state->child = 0; } if (state->waitpid_return < 0) { /* waitpid() failed? This is ugly. */ archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, - "Child process exited badly"); + "Error closing child process"); return (ARCHIVE_WARN); } diff --git a/contrib/libarchive/libarchive/archive_read_support_format_7zip.c b/contrib/libarchive/libarchive/archive_read_support_format_7zip.c index f273f84be521..595462733104 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_7zip.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_7zip.c @@ -80,7 +80,7 @@ /* * ELF format */ -#define ELF_HDR_MIN_LEN 0x34 +#define ELF_HDR_MIN_LEN 0x3f #define ELF_HDR_EI_CLASS_OFFSET 0x04 #define ELF_HDR_EI_DATA_OFFSET 0x05 @@ -811,6 +811,8 @@ find_elf_data_sec(struct archive_read *a) strtab_size = (*dec32)( h + e_shstrndx * e_shentsize + 0x14); } + if (strtab_size < 6 || strtab_size > SIZE_MAX) + break; /* * Read the STRTAB section to find the .data offset @@ -1391,7 +1393,8 @@ init_decompression(struct archive_read *a, struct _7zip *zip, * size to liblzma when using lzma_raw_decoder() liblzma * could correctly deal with BCJ+LZMA. But unfortunately * there is no way to do that. - * Discussion about this can be found at XZ Utils forum. + * + * Reference: https://web.archive.org/web/20240405171610/https://www.mail-archive.com/xz-devel@tukaani.org/msg00373.html */ if (coder2 != NULL) { zip->codec2 = coder2->codec; diff --git a/contrib/libarchive/libarchive/archive_read_support_format_mtree.c b/contrib/libarchive/libarchive/archive_read_support_format_mtree.c index ba0e49de2408..ded13bee79a3 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_mtree.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_mtree.c @@ -51,6 +51,7 @@ #include "archive.h" #include "archive_entry.h" #include "archive_entry_private.h" +#include "archive_platform_stat.h" #include "archive_private.h" #include "archive_rb.h" #include "archive_read_private.h" @@ -1073,6 +1074,8 @@ read_mtree(struct archive_read *a, struct mtree *mtree) /* Non-printable characters are not allowed */ for (s = p;s < p + len - 1; s++) { if (!isprint((unsigned char)*s) && *s != '\t') { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Non-printable character 0x%02X", (unsigned char)(*s)); r = ARCHIVE_FATAL; break; } @@ -1175,7 +1178,7 @@ parse_file(struct archive_read *a, struct archive_entry *entry, struct mtree *mtree, struct mtree_entry *mentry, int *use_next) { const char *path; - struct stat st_storage, *st; + la_seek_stat_t st_storage, *st; struct mtree_entry *mp; struct archive_entry *sparse_entry; int r = ARCHIVE_OK, r1, parsed_kws; @@ -1251,7 +1254,7 @@ parse_file(struct archive_read *a, struct archive_entry *entry, archive_entry_filetype(entry) == AE_IFDIR) { mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC); __archive_ensure_cloexec_flag(mtree->fd); - if (mtree->fd == -1 && ( + if (mtree->fd < 0 && ( #if defined(_WIN32) && !defined(__CYGWIN__) /* * On Windows, attempting to open a file with an @@ -1270,7 +1273,7 @@ parse_file(struct archive_read *a, struct archive_entry *entry, st = &st_storage; if (mtree->fd >= 0) { - if (fstat(mtree->fd, st) == -1) { + if (la_seek_fstat(mtree->fd, st) == -1) { archive_set_error(&a->archive, errno, "Could not fstat %s", path); r = ARCHIVE_WARN; @@ -1283,7 +1286,7 @@ parse_file(struct archive_read *a, struct archive_entry *entry, #ifdef HAVE_LSTAT else if (lstat(path, st) == -1) #else - else if (la_stat(path, st) == -1) + else if (la_seek_stat(path, st) == -1) #endif { st = NULL; @@ -2130,6 +2133,13 @@ readline(struct archive_read *a, struct mtree *mtree, char **start, for (u = mtree->line.s + find_off; *u; ++u) { if (u[0] == '\n') { /* Ends with unescaped newline. */ + /* Check if preceded by '\r' for CRLF handling */ + if (u > mtree->line.s && u[-1] == '\r') { + /* CRLF ending - remove the '\r' */ + u[-1] = '\n'; + u[0] = '\0'; + total_size--; + } *start = mtree->line.s; return total_size; } else if (u[0] == '#') { @@ -2144,6 +2154,11 @@ readline(struct archive_read *a, struct mtree *mtree, char **start, total_size -= 2; mtree->line.s[total_size] = '\0'; break; + } else if (u[1] == '\r' && u[2] == '\n') { + /* Trim escaped CRLF. */ + total_size -= 3; + mtree->line.s[total_size] = '\0'; + break; } else if (u[1] != '\0') { /* Skip the two-char escape sequence */ ++u; diff --git a/contrib/libarchive/libarchive/archive_read_support_format_rar.c b/contrib/libarchive/libarchive/archive_read_support_format_rar.c index 923ae5c65e17..9b401c00ba34 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_rar.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_rar.c @@ -1117,8 +1117,6 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff, if (rar->entry_eof || rar->offset_seek >= rar->unp_size) { *size = 0; *offset = rar->offset; - if (*offset < rar->unp_size) - *offset = rar->unp_size; return (ARCHIVE_EOF); } @@ -1455,7 +1453,7 @@ read_header(struct archive_read *a, struct archive_entry *entry, return (ARCHIVE_FATAL); #endif } - /* If no CRC error, Go on parsing File Header. */ + /* If no CRC error, go on parsing File Header. */ p = h; endp = p + header_size - 7; memcpy(&file_header, p, sizeof(file_header)); @@ -2368,8 +2366,8 @@ parse_codes(struct archive_read *a) return (ARCHIVE_FATAL); } - /* Make sure ppmd7_contest is freed before Ppmd7_Construct - * because reading a broken file cause this abnormal sequence. */ + /* Make sure ppmd7_context is freed before Ppmd7_Construct + * because reading a broken file causes this abnormal sequence. */ __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context); rar->bytein.a = a; diff --git a/contrib/libarchive/libarchive/archive_read_support_format_rar5.c b/contrib/libarchive/libarchive/archive_read_support_format_rar5.c index 48dde0c2e814..17e501e02e9f 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_rar5.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_rar5.c @@ -1619,10 +1619,13 @@ static int process_head_file_extra(struct archive_read* a, { uint64_t extra_field_size; uint64_t extra_field_id = 0; - int ret = ARCHIVE_FATAL; uint64_t var_size; while(extra_data_size > 0) { + /* Make sure we won't fail if the file declares only unsupported + attributes. */ + int ret = ARCHIVE_OK; + if(!read_var(a, &extra_field_size, &var_size)) return ARCHIVE_EOF; @@ -1675,12 +1678,53 @@ static int process_head_file_extra(struct archive_read* a, if (ARCHIVE_OK != consume(a, extra_field_size)) { return ARCHIVE_EOF; } + + /* Don't fail on unsupported attribute -- we've handled it + by skipping over it. */ + ret = ARCHIVE_OK; + } + + if (ret != ARCHIVE_OK) { + /* Forward any errors signalled by the attribute parsing + functions. */ + return ret; } } - if(ret != ARCHIVE_OK) { - /* Attribute not implemented. */ - return ret; + if (extra_data_size != 0) { + /* We didn't skip everything, or we skipped too much; either way, + there's an error in this parsing function. */ + + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "unsupported structure of file header extra data"); + return ARCHIVE_FATAL; + } + + return ARCHIVE_OK; +} + +static int file_entry_sanity_checks(struct archive_read* a, + size_t block_flags, uint8_t is_dir, uint64_t unpacked_size, + size_t packed_size) +{ + if (is_dir) { + const int declares_data_size = + (int) (unpacked_size != 0 || packed_size != 0); + + /* FILE entries for directories still declare HFL_DATA in block flags, + even though attaching data to such blocks doesn't make much sense. */ + if (declares_data_size) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "directory entries cannot have any data"); + return ARCHIVE_FATAL; + } + } else { + const int declares_hfl_data = (int) ((block_flags & HFL_DATA) != 0); + if (!declares_hfl_data) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "no data found in file/service block"); + return ARCHIVE_FATAL; + } } return ARCHIVE_OK; @@ -1701,6 +1745,7 @@ static int process_head_file(struct archive_read* a, struct rar5* rar, int c_method = 0, c_version = 0; char name_utf8_buf[MAX_NAME_IN_BYTES]; const uint8_t* p; + int sanity_ret; enum FILE_FLAGS { DIRECTORY = 0x0001, UTIME = 0x0002, CRC32 = 0x0004, @@ -1744,10 +1789,6 @@ static int process_head_file(struct archive_read* a, struct rar5* rar, rar->file.bytes_remaining = data_size; } else { rar->file.bytes_remaining = 0; - - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "no data found in file/service block"); - return ARCHIVE_FATAL; } if(!read_var_sized(a, &file_flags, NULL)) @@ -1764,6 +1805,13 @@ static int process_head_file(struct archive_read* a, struct rar5* rar, rar->file.dir = (uint8_t) ((file_flags & DIRECTORY) > 0); + sanity_ret = file_entry_sanity_checks(a, block_flags, rar->file.dir, + unpacked_size, data_size); + + if (sanity_ret != ARCHIVE_OK) { + return sanity_ret; + } + if(!read_var_sized(a, &file_attr, NULL)) return ARCHIVE_EOF; @@ -4163,7 +4211,7 @@ static int rar5_read_data(struct archive_read *a, const void **buff, * it's impossible to perform any decompression. */ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Can't decompress an entry marked as a directory"); - return ARCHIVE_FAILED; + return ARCHIVE_FATAL; } if(!rar->skip_mode && (rar->cstate.last_write_ptr > rar->file.unpacked_size)) { diff --git a/contrib/libarchive/libarchive/archive_read_support_format_tar.c b/contrib/libarchive/libarchive/archive_read_support_format_tar.c index 0c87bc6d732f..eeb2c725f6eb 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_tar.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_tar.c @@ -233,7 +233,7 @@ static int tar_read_header(struct archive_read *, struct tar *, struct archive_entry *, int64_t *); static int tohex(int c); static char *url_decode(const char *, size_t); -static void tar_flush_unconsumed(struct archive_read *, int64_t *); +static int tar_flush_unconsumed(struct archive_read *, int64_t *); /* Sanity limits: These numbers should be low enough to * prevent a maliciously-crafted archive from forcing us to @@ -477,7 +477,7 @@ archive_read_format_tar_options(struct archive_read *a, * how much unconsumed data we have floating around, and to consume * anything outstanding since we're going to do read_aheads */ -static void +static int tar_flush_unconsumed(struct archive_read *a, int64_t *unconsumed) { if (*unconsumed) { @@ -490,9 +490,13 @@ tar_flush_unconsumed(struct archive_read *a, int64_t *unconsumed) memset(data, 0xff, *unconsumed); } */ - __archive_read_consume(a, *unconsumed); + int64_t consumed = __archive_read_consume(a, *unconsumed); + if (consumed != *unconsumed) { + return (ARCHIVE_FATAL); + } *unconsumed = 0; } + return (ARCHIVE_OK); } /* @@ -750,7 +754,9 @@ tar_read_header(struct archive_read *a, struct tar *tar, /* Find the next valid header record. */ while (1) { - tar_flush_unconsumed(a, unconsumed); + if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) { + return (ARCHIVE_FATAL); + } /* Read 512-byte header record */ h = __archive_read_ahead(a, 512, &bytes); @@ -796,7 +802,9 @@ tar_read_header(struct archive_read *a, struct tar *tar, /* This is NOT a null block, so it must be a valid header. */ if (!checksum(a, h)) { - tar_flush_unconsumed(a, unconsumed); + if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) { + return (ARCHIVE_FATAL); + } archive_set_error(&a->archive, EINVAL, "Damaged tar archive (bad header checksum)"); /* If we've read some critical information (pax headers, etc) @@ -1236,7 +1244,7 @@ header_volume(struct archive_read *a, struct tar *tar, header = (const struct archive_entry_header_ustar *)h; size = tar_atol(header->size, sizeof(header->size)); - if (size > (int64_t)pathname_limit) { + if (size < 0 || size > (int64_t)pathname_limit) { return (ARCHIVE_FATAL); } to_consume = ((size + 511) & ~511); @@ -1255,13 +1263,15 @@ read_bytes_to_string(struct archive_read *a, const void *src; /* Fail if we can't make our buffer big enough. */ - if (archive_string_ensure(as, (size_t)size+1) == NULL) { + if (archive_string_ensure(as, size + 1) == NULL) { archive_set_error(&a->archive, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } - tar_flush_unconsumed(a, unconsumed); + if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) { + return (ARCHIVE_FATAL); + } /* Read the body into the string. */ src = __archive_read_ahead(a, size, NULL); @@ -1272,9 +1282,9 @@ read_bytes_to_string(struct archive_read *a, *unconsumed = 0; return (ARCHIVE_FATAL); } - memcpy(as->s, src, (size_t)size); + memcpy(as->s, src, size); as->s[size] = '\0'; - as->length = (size_t)size; + as->length = size; *unconsumed += size; return (ARCHIVE_OK); } @@ -1715,7 +1725,9 @@ read_mac_metadata_blob(struct archive_read *a, * Q: Is the above idea really possible? Even * when there are GNU or pax extension entries? */ - tar_flush_unconsumed(a, unconsumed); + if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) { + return (ARCHIVE_FATAL); + } data = __archive_read_ahead(a, msize, NULL); if (data == NULL) { archive_set_error(&a->archive, EINVAL, @@ -1900,7 +1912,9 @@ header_pax_extension(struct archive_read *a, struct tar *tar, (long long)ext_size, (long long)ext_size_limit); return (ARCHIVE_WARN); } - tar_flush_unconsumed(a, unconsumed); + if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) { + return (ARCHIVE_FATAL); + } /* Parse the size/name of each pax attribute in the body */ archive_string_init(&attr_name); @@ -1994,7 +2008,9 @@ header_pax_extension(struct archive_read *a, struct tar *tar, /* Consume size, name, and `=` */ *unconsumed += p - attr_start; - tar_flush_unconsumed(a, unconsumed); + if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) { + return (ARCHIVE_FATAL); + } if (value_length == 0) { archive_set_error(&a->archive, EINVAL, @@ -2017,7 +2033,9 @@ header_pax_extension(struct archive_read *a, struct tar *tar, err = err_combine(err, r); /* Consume the `\n` that follows the pax attribute value. */ - tar_flush_unconsumed(a, unconsumed); + if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) { + return (ARCHIVE_FATAL); + } p = __archive_read_ahead(a, 1, &did_read); if (p == NULL) { archive_set_error(&a->archive, EINVAL, @@ -2033,7 +2051,9 @@ header_pax_extension(struct archive_read *a, struct tar *tar, } ext_size -= 1; *unconsumed += 1; - tar_flush_unconsumed(a, unconsumed); + if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) { + return (ARCHIVE_FATAL); + } } *unconsumed += ext_size + ext_padding; @@ -2290,7 +2310,9 @@ pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t * archive_string_init(&as); r = read_bytes_to_string(a, &as, value_length, &unconsumed); - tar_flush_unconsumed(a, &unconsumed); + if (tar_flush_unconsumed(a, &unconsumed) != ARCHIVE_OK) { + return (ARCHIVE_FATAL); + } if (r < ARCHIVE_OK) { archive_string_free(&as); *result = 0; @@ -2940,7 +2962,9 @@ header_gnutar(struct archive_read *a, struct tar *tar, /* Copy filename over (to ensure null termination). */ header = (const struct archive_entry_header_gnutar *)h; const char *existing_pathname = archive_entry_pathname(entry); - if (existing_pathname == NULL || existing_pathname[0] == '\0') { + const wchar_t *existing_wcs_pathname = archive_entry_pathname_w(entry); + if ((existing_pathname == NULL || existing_pathname[0] == '\0') + && (existing_wcs_pathname == NULL || existing_wcs_pathname[0] == L'\0')) { if (archive_entry_copy_pathname_l(entry, header->name, sizeof(header->name), tar->sconv) != 0) { err = set_conversion_failed_error(a, tar->sconv, "Pathname"); @@ -3093,7 +3117,9 @@ gnu_sparse_old_read(struct archive_read *a, struct tar *tar, return (ARCHIVE_OK); do { - tar_flush_unconsumed(a, unconsumed); + if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) { + return (ARCHIVE_FATAL); + } data = __archive_read_ahead(a, 512, &bytes_read); if (data == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -3283,7 +3309,9 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, int64_t *unconsumed) return (ARCHIVE_FATAL); } /* Skip rest of block... */ - tar_flush_unconsumed(a, unconsumed); + if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) { + return (ARCHIVE_FATAL); + } bytes_read = tar->entry_bytes_remaining - remaining; to_skip = 0x1ff & -bytes_read; /* Fail if tar->entry_bytes_remaing would get negative */ @@ -3509,7 +3537,9 @@ readline(struct archive_read *a, struct tar *tar, const char **start, const char *s; void *p; - tar_flush_unconsumed(a, unconsumed); + if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) { + return (ARCHIVE_FATAL); + } t = __archive_read_ahead(a, 1, &bytes_read); if (bytes_read <= 0 || t == NULL) diff --git a/contrib/libarchive/libarchive/archive_read_support_format_warc.c b/contrib/libarchive/libarchive/archive_read_support_format_warc.c index 696f959c341d..d8f188cf0b44 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_warc.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_warc.c @@ -405,7 +405,7 @@ _warc_read(struct archive_read *a, const void **buf, size_t *bsz, int64_t *off) /* it's our lucky day, no work, we can leave early */ *buf = NULL; *bsz = 0U; - *off = w->cntoff + 4U/*for \r\n\r\n separator*/; + *off = w->cntoff; w->unconsumed = 0U; return (ARCHIVE_EOF); } diff --git a/contrib/libarchive/libarchive/archive_read_support_format_xar.c b/contrib/libarchive/libarchive/archive_read_support_format_xar.c index b4e1192ef771..36b5ab3ae04c 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_xar.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_xar.c @@ -930,7 +930,7 @@ xar_read_data(struct archive_read *a, abort_read_data: *buff = NULL; *size = 0; - *offset = xar->total; + *offset = (int64_t)xar->entry_total; return (r); } diff --git a/contrib/libarchive/libarchive/archive_read_support_format_zip.c b/contrib/libarchive/libarchive/archive_read_support_format_zip.c index daf51933d687..9abd55709e3f 100644 --- a/contrib/libarchive/libarchive/archive_read_support_format_zip.c +++ b/contrib/libarchive/libarchive/archive_read_support_format_zip.c @@ -3015,8 +3015,8 @@ init_WinZip_AES_decryption(struct archive_read *a) p, salt_len, 1000, derived_key, key_len * 2 + 2); if (r != 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Decryption is unsupported due to lack of " - "crypto library"); + r == CRYPTOR_STUB_FUNCTION ? "Decryption is unsupported due " + "to lack of crypto library" : "Failed to process passphrase"); return (ARCHIVE_FAILED); } diff --git a/contrib/libarchive/libarchive/archive_string.c b/contrib/libarchive/libarchive/archive_string.c index 7437715f9122..3bb978335eb8 100644 --- a/contrib/libarchive/libarchive/archive_string.c +++ b/contrib/libarchive/libarchive/archive_string.c @@ -2015,7 +2015,7 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n, /* We must allocate memory even if there is no data for conversion * or copy. This simulates archive_string_append behavior. */ if (length == 0) { - int tn = 1; + size_t tn = 1; if (sc != NULL && (sc->flag & SCONV_TO_UTF16)) tn = 2; if (archive_string_ensure(as, as->length + tn) == NULL) @@ -2752,7 +2752,8 @@ archive_string_append_unicode(struct archive_string *as, const void *_p, char *p, *endp; uint32_t uc; size_t w; - int n, ret = 0, ts, tm; + size_t ts, tm; + int n, ret = 0; int (*parse)(uint32_t *, const char *, size_t); size_t (*unparse)(char *, size_t, uint32_t); diff --git a/contrib/libarchive/libarchive/archive_string_sprintf.c b/contrib/libarchive/libarchive/archive_string_sprintf.c index 1c5910e0b2d3..69b0cdcd83d5 100644 --- a/contrib/libarchive/libarchive/archive_string_sprintf.c +++ b/contrib/libarchive/libarchive/archive_string_sprintf.c @@ -146,7 +146,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt, case 'z': s = va_arg(ap, ssize_t); break; default: s = va_arg(ap, int); break; } - append_int(as, s, 10); + append_int(as, s, 10); break; case 's': switch(long_flag) { diff --git a/contrib/libarchive/libarchive/archive_util.c b/contrib/libarchive/libarchive/archive_util.c index 900abd0c3c62..d048bbc94650 100644 --- a/contrib/libarchive/libarchive/archive_util.c +++ b/contrib/libarchive/libarchive/archive_util.c @@ -445,11 +445,39 @@ __archive_mkstemp(wchar_t *template) #else static int -get_tempdir(struct archive_string *temppath) +__archive_issetugid(void) { - const char *tmp; +#ifdef HAVE_ISSETUGID + return (issetugid()); +#elif HAVE_GETRESUID + uid_t ruid, euid, suid; + gid_t rgid, egid, sgid; + if (getresuid(&ruid, &euid, &suid) != 0) + return (-1); + if (ruid != euid || ruid != suid) + return (1); + if (getresgid(&ruid, &egid, &sgid) != 0) + return (-1); + if (rgid != egid || rgid != sgid) + return (1); +#elif HAVE_GETEUID + if (geteuid() != getuid()) + return (1); +#if HAVE_GETEGID + if (getegid() != getgid()) + return (1); +#endif +#endif + return (0); +} + +int +__archive_get_tempdir(struct archive_string *temppath) +{ + const char *tmp = NULL; - tmp = getenv("TMPDIR"); + if (__archive_issetugid() == 0) + tmp = getenv("TMPDIR"); if (tmp == NULL) #ifdef _PATH_TMP tmp = _PATH_TMP; @@ -476,7 +504,7 @@ __archive_mktemp(const char *tmpdir) archive_string_init(&temp_name); if (tmpdir == NULL) { - if (get_tempdir(&temp_name) != ARCHIVE_OK) + if (__archive_get_tempdir(&temp_name) != ARCHIVE_OK) goto exit_tmpfile; } else { archive_strcpy(&temp_name, tmpdir); @@ -538,7 +566,7 @@ __archive_mktempx(const char *tmpdir, char *template) if (template == NULL) { archive_string_init(&temp_name); if (tmpdir == NULL) { - if (get_tempdir(&temp_name) != ARCHIVE_OK) + if (__archive_get_tempdir(&temp_name) != ARCHIVE_OK) goto exit_tmpfile; } else archive_strcpy(&temp_name, tmpdir); diff --git a/contrib/libarchive/libarchive/archive_write.c b/contrib/libarchive/libarchive/archive_write.c index a8e7b63b5bfe..9b9cb196f0f9 100644 --- a/contrib/libarchive/libarchive/archive_write.c +++ b/contrib/libarchive/libarchive/archive_write.c @@ -360,7 +360,6 @@ archive_write_client_open(struct archive_write_filter *f) struct archive_none *state; void *buffer; size_t buffer_size; - int ret; f->bytes_per_block = archive_write_get_bytes_per_block(f->archive); f->bytes_in_last_block = @@ -385,13 +384,7 @@ archive_write_client_open(struct archive_write_filter *f) if (a->client_opener == NULL) return (ARCHIVE_OK); - ret = a->client_opener(f->archive, a->client_data); - if (ret != ARCHIVE_OK) { - free(state->buffer); - free(state); - f->data = NULL; - } - return (ret); + return (a->client_opener(f->archive, a->client_data)); } static int @@ -480,6 +473,7 @@ static int archive_write_client_free(struct archive_write_filter *f) { struct archive_write *a = (struct archive_write *)f->archive; + struct archive_none *state = (struct archive_none *)f->data; if (a->client_freer) (*a->client_freer)(&a->archive, a->client_data); @@ -492,6 +486,13 @@ archive_write_client_free(struct archive_write_filter *f) a->passphrase = NULL; } + /* Free state. */ + if (state != NULL) { + free(state->buffer); + free(state); + f->data = NULL; + } + return (ARCHIVE_OK); } @@ -548,8 +549,6 @@ archive_write_client_close(struct archive_write_filter *f) } if (a->client_closer) (*a->client_closer)(&a->archive, a->client_data); - free(state->buffer); - free(state); /* Clear the close handler myself not to be called again. */ f->state = ARCHIVE_WRITE_FILTER_STATE_CLOSED; @@ -807,7 +806,10 @@ _archive_write_finish_entry(struct archive *_a) if (a->archive.state & ARCHIVE_STATE_DATA && a->format_finish_entry != NULL) ret = (a->format_finish_entry)(a); - a->archive.state = ARCHIVE_STATE_HEADER; + if (ret == ARCHIVE_FATAL) + a->archive.state = ARCHIVE_STATE_FATAL; + else + a->archive.state = ARCHIVE_STATE_HEADER; return (ret); } @@ -819,6 +821,7 @@ _archive_write_data(struct archive *_a, const void *buff, size_t s) { struct archive_write *a = (struct archive_write *)_a; const size_t max_write = INT_MAX; + int ret; archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_DATA, "archive_write_data"); @@ -826,7 +829,10 @@ _archive_write_data(struct archive *_a, const void *buff, size_t s) if (s > max_write) s = max_write; archive_clear_error(&a->archive); - return ((a->format_write_data)(a, buff, s)); + ret = (a->format_write_data)(a, buff, s); + if (ret == ARCHIVE_FATAL) + a->archive.state = ARCHIVE_STATE_FATAL; + return (ret); } static struct archive_write_filter * diff --git a/contrib/libarchive/libarchive/archive_write_add_filter_bzip2.c b/contrib/libarchive/libarchive/archive_write_add_filter_bzip2.c index 0726f08936ec..2434528d5133 100644 --- a/contrib/libarchive/libarchive/archive_write_add_filter_bzip2.c +++ b/contrib/libarchive/libarchive/archive_write_add_filter_bzip2.c @@ -281,6 +281,10 @@ static int archive_compressor_bzip2_free(struct archive_write_filter *f) { struct private_data *data = (struct private_data *)f->data; + + /* May already have been called, but not necessarily. */ + (void)BZ2_bzCompressEnd(&(data->stream)); + free(data->compressed); free(data); f->data = NULL; diff --git a/contrib/libarchive/libarchive/archive_write_add_filter_gzip.c b/contrib/libarchive/libarchive/archive_write_add_filter_gzip.c index 5ef43c1936ed..b09e669b753d 100644 --- a/contrib/libarchive/libarchive/archive_write_add_filter_gzip.c +++ b/contrib/libarchive/libarchive/archive_write_add_filter_gzip.c @@ -191,7 +191,8 @@ static int archive_compressor_gzip_open(struct archive_write_filter *f) { struct private_data *data = (struct private_data *)f->data; - int ret; + int ret = ARCHIVE_OK; + int init_success; if (data->compressed == NULL) { size_t bs = 65536, bpb; @@ -221,44 +222,66 @@ archive_compressor_gzip_open(struct archive_write_filter *f) data->compressed[0] = 0x1f; /* GZip signature bytes */ data->compressed[1] = 0x8b; data->compressed[2] = 0x08; /* "Deflate" compression */ - data->compressed[3] = data->original_filename == NULL ? 0 : 0x8; + data->compressed[3] = 0x00; /* Flags */ if (data->timestamp >= 0) { time_t t = time(NULL); data->compressed[4] = (uint8_t)(t)&0xff; /* Timestamp */ data->compressed[5] = (uint8_t)(t>>8)&0xff; data->compressed[6] = (uint8_t)(t>>16)&0xff; data->compressed[7] = (uint8_t)(t>>24)&0xff; - } else + } else { memset(&data->compressed[4], 0, 4); - if (data->compression_level == 9) - data->compressed[8] = 2; - else if(data->compression_level == 1) - data->compressed[8] = 4; - else - data->compressed[8] = 0; + } + if (data->compression_level == 9) { + data->compressed[8] = 2; + } else if(data->compression_level == 1) { + data->compressed[8] = 4; + } else { + data->compressed[8] = 0; + } data->compressed[9] = 3; /* OS=Unix */ data->stream.next_out += 10; data->stream.avail_out -= 10; if (data->original_filename != NULL) { - strcpy((char*)data->compressed + 10, data->original_filename); - data->stream.next_out += strlen(data->original_filename) + 1; - data->stream.avail_out -= strlen(data->original_filename) + 1; + /* Limit "original filename" to 32k or the + * remaining space in the buffer, whichever is smaller. + */ + int ofn_length = strlen(data->original_filename); + int ofn_max_length = 32768; + int ofn_space_available = data->compressed + + data->compressed_buffer_size + - data->stream.next_out + - 1; + if (ofn_max_length > ofn_space_available) { + ofn_max_length = ofn_space_available; + } + if (ofn_length < ofn_max_length) { + data->compressed[3] |= 0x8; + strcpy((char*)data->compressed + 10, + data->original_filename); + data->stream.next_out += ofn_length + 1; + data->stream.avail_out -= ofn_length + 1; + } else { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "Gzip 'Original Filename' ignored because it is too long"); + ret = ARCHIVE_WARN; + } } f->write = archive_compressor_gzip_write; /* Initialize compression library. */ - ret = deflateInit2(&(data->stream), + init_success = deflateInit2(&(data->stream), data->compression_level, Z_DEFLATED, -15 /* < 0 to suppress zlib header */, 8, Z_DEFAULT_STRATEGY); - if (ret == Z_OK) { + if (init_success == Z_OK) { f->data = data; - return (ARCHIVE_OK); + return (ret); } /* Library setup failed: clean up. */ @@ -266,7 +289,7 @@ archive_compressor_gzip_open(struct archive_write_filter *f) "initializing compression library"); /* Override the error message if we know what really went wrong. */ - switch (ret) { + switch (init_success) { case Z_STREAM_ERROR: archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, "Internal error initializing " diff --git a/contrib/libarchive/libarchive/archive_write_add_filter_program.c b/contrib/libarchive/libarchive/archive_write_add_filter_program.c index c661cc7f412f..f12db3373883 100644 --- a/contrib/libarchive/libarchive/archive_write_add_filter_program.c +++ b/contrib/libarchive/libarchive/archive_write_add_filter_program.c @@ -330,6 +330,7 @@ __archive_write_program_close(struct archive_write_filter *f, struct archive_write_program_data *data) { int ret, status; + pid_t pid; ssize_t bytes_read; if (data->child == 0) @@ -373,14 +374,12 @@ cleanup: close(data->child_stdin); if (data->child_stdout != -1) close(data->child_stdout); - while (waitpid(data->child, &status, 0) == -1 && errno == EINTR) - continue; -#if defined(_WIN32) && !defined(__CYGWIN__) - CloseHandle(data->child); -#endif + do { + pid = waitpid(data->child, &status, 0); + } while (pid == -1 && errno == EINTR); data->child = 0; - if (status != 0) { + if (pid < 0 || status != 0) { archive_set_error(f->archive, EIO, "Error closing program: %s", data->program_name); ret = ARCHIVE_FATAL; diff --git a/contrib/libarchive/libarchive/archive_write_add_filter_zstd.c b/contrib/libarchive/libarchive/archive_write_add_filter_zstd.c index c0a6e5a37a66..d4752c247157 100644 --- a/contrib/libarchive/libarchive/archive_write_add_filter_zstd.c +++ b/contrib/libarchive/libarchive/archive_write_add_filter_zstd.c @@ -391,6 +391,8 @@ archive_compressor_zstd_open(struct archive_write_filter *f) ZSTD_CCtx_setParameter(data->cstream, ZSTD_c_nbWorkers, data->threads); + ZSTD_CCtx_setParameter(data->cstream, ZSTD_c_checksumFlag, 1); + #if ZSTD_VERSION_NUMBER >= MINVER_LONG ZSTD_CCtx_setParameter(data->cstream, ZSTD_c_windowLog, data->long_distance); #endif diff --git a/contrib/libarchive/libarchive/archive_write_disk_posix.c b/contrib/libarchive/libarchive/archive_write_disk_posix.c index 1bbfd7a3d779..aeb27e1270ad 100644 --- a/contrib/libarchive/libarchive/archive_write_disk_posix.c +++ b/contrib/libarchive/libarchive/archive_write_disk_posix.c @@ -2204,7 +2204,7 @@ restore_entry(struct archive_write_disk *a) (void)clear_nochange_fflags(a); if ((a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) && - S_ISREG(a->st.st_mode)) { + S_ISREG(a->mode)) { /* Use a temporary file to extract */ if ((a->fd = la_mktemp(a)) == -1) { archive_set_error(&a->archive, errno, @@ -2559,9 +2559,9 @@ _archive_write_disk_close(struct archive *_a) * for directories. For other file types * we need to verify via fstat() or lstat() */ - if (fd == -1 || p->filetype != AE_IFDIR) { + if (fd < 0 || p->filetype != AE_IFDIR) { #if HAVE_FSTAT - if (fd > 0 && ( + if (fd >= 0 && ( fstat(fd, &st) != 0 || la_verify_filetype(st.st_mode, p->filetype) == 0)) { @@ -3930,10 +3930,14 @@ clear_nochange_fflags(struct archive_write_disk *a) #ifdef UF_APPEND | UF_APPEND #endif -#ifdef EXT2_APPEND_FL +#if defined(FS_APPEND_FL) + | FS_APPEND_FL +#elif defined(EXT2_APPEND_FL) | EXT2_APPEND_FL #endif -#ifdef EXT2_IMMUTABLE_FL +#if defined(FS_IMMUTABLE_FL) + | FS_IMMUTABLE_FL +#elif defined(EXT2_IMMUTABLE_FL) | EXT2_IMMUTABLE_FL #endif ; @@ -4437,7 +4441,7 @@ fixup_appledouble(struct archive_write_disk *a, const char *pathname) */ fd = open(pathname, O_RDONLY | O_BINARY | O_CLOEXEC); __archive_ensure_cloexec_flag(fd); - if (fd == -1) { + if (fd < 0) { archive_set_error(&a->archive, errno, "Failed to open a restoring file"); ret = ARCHIVE_WARN; diff --git a/contrib/libarchive/libarchive/archive_write_open_fd.c b/contrib/libarchive/libarchive/archive_write_open_fd.c index 8a3f68d0699d..ba034ed92f8a 100644 --- a/contrib/libarchive/libarchive/archive_write_open_fd.c +++ b/contrib/libarchive/libarchive/archive_write_open_fd.c @@ -122,7 +122,7 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length mine = (struct write_fd_data *)client_data; for (;;) { bytesWritten = write(mine->fd, buff, length); - if (bytesWritten <= 0) { + if (bytesWritten < 0) { if (errno == EINTR) continue; archive_set_error(a, errno, "Write error"); diff --git a/contrib/libarchive/libarchive/archive_write_open_file.c b/contrib/libarchive/libarchive/archive_write_open_file.c index 4c6ebfb2269d..0b310f3da83b 100644 --- a/contrib/libarchive/libarchive/archive_write_open_file.c +++ b/contrib/libarchive/libarchive/archive_write_open_file.c @@ -85,16 +85,12 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length size_t bytesWritten; mine = client_data; - for (;;) { - bytesWritten = fwrite(buff, 1, length, mine->f); - if (bytesWritten <= 0) { - if (errno == EINTR) - continue; - archive_set_error(a, errno, "Write error"); - return (-1); - } - return (bytesWritten); + bytesWritten = fwrite(buff, 1, length, mine->f); + if (bytesWritten != length) { + archive_set_error(a, errno, "Write error"); + return (-1); } + return (bytesWritten); } static int diff --git a/contrib/libarchive/libarchive/archive_write_open_filename.c b/contrib/libarchive/libarchive/archive_write_open_filename.c index 34209426558c..7d0f9bde1dbb 100644 --- a/contrib/libarchive/libarchive/archive_write_open_filename.c +++ b/contrib/libarchive/libarchive/archive_write_open_filename.c @@ -108,6 +108,7 @@ open_filename(struct archive *a, int mbs_fn, const void *filename) else r = archive_mstring_copy_wcs(&mine->filename, filename); if (r < 0) { + free(mine); if (errno == ENOMEM) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); @@ -227,7 +228,7 @@ file_write(struct archive *a, void *client_data, const void *buff, mine = (struct write_file_data *)client_data; for (;;) { bytesWritten = write(mine->fd, buff, length); - if (bytesWritten <= 0) { + if (bytesWritten < 0) { if (errno == EINTR) continue; archive_set_error(a, errno, "Write error"); diff --git a/contrib/libarchive/libarchive/archive_write_set_format_7zip.c b/contrib/libarchive/libarchive/archive_write_set_format_7zip.c index c2bce5975a46..175285da13be 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_7zip.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_7zip.c @@ -686,7 +686,7 @@ write_to_temp(struct archive_write *a, const void *buff, size_t s) ws = write(zip->temp_fd, p, s); if (ws < 0) { archive_set_error(&(a->archive), errno, - "fwrite function failed"); + "write function failed"); return (ARCHIVE_FATAL); } s -= ws; diff --git a/contrib/libarchive/libarchive/archive_write_set_format_mtree.c b/contrib/libarchive/libarchive/archive_write_set_format_mtree.c index 02fbb2d2f555..8131574c8da2 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_mtree.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_mtree.c @@ -1927,7 +1927,7 @@ mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file, } /* - * Find out the position which points the last position of + * Find out the position which points to the last position of * path separator('/'). */ slash = NULL; @@ -2024,7 +2024,7 @@ mtree_entry_add_child_tail(struct mtree_entry *parent, } /* - * Find a entry from a parent entry with the name. + * Find an entry from a parent entry with given name. */ static struct mtree_entry * mtree_entry_find_child(struct mtree_entry *parent, const char *child_name) @@ -2148,10 +2148,10 @@ mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep) /* Find next sub directory. */ if (!np->dir_info) { - /* NOT Directory! */ + /* NOT a directory! */ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "`%s' is not directory, we cannot insert `%s' ", + "`%s' is not a directory, we cannot insert `%s' ", np->pathname.s, file->pathname.s); return (ARCHIVE_FAILED); } @@ -2243,10 +2243,7 @@ mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep) } same_entry: - /* - * We have already has the entry the filename of which is - * the same. - */ + /* We already have an entry with same filename. */ r = mtree_entry_exchange_same_entry(a, np, file); if (r < ARCHIVE_WARN) return (r); @@ -2264,13 +2261,13 @@ mtree_entry_exchange_same_entry(struct archive_write *a, struct mtree_entry *np, if ((np->mode & AE_IFMT) != (file->mode & AE_IFMT)) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Found duplicate entries `%s' and its file type is " - "different", + "Found duplicate entries for `%s' with " + "differing file types.", np->pathname.s); return (ARCHIVE_FAILED); } - /* Update the existent mtree entry's attributes by the new one's. */ + /* Update the existing mtree entry's attributes by the new one's. */ archive_string_empty(&np->symlink); archive_string_concat(&np->symlink, &file->symlink); archive_string_empty(&np->uname); diff --git a/contrib/libarchive/libarchive/archive_write_set_format_xar.c b/contrib/libarchive/libarchive/archive_write_set_format_xar.c index 3775e9f5819a..9921f1032be5 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_xar.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_xar.c @@ -689,7 +689,7 @@ write_to_temp(struct archive_write *a, const void *buff, size_t s) ws = write(xar->temp_fd, p, s); if (ws < 0) { archive_set_error(&(a->archive), errno, - "fwrite function failed"); + "write function failed"); return (ARCHIVE_FATAL); } s -= ws; @@ -3418,8 +3418,8 @@ static int xml_writer_get_final_content_and_length(struct xml_writer *ctx, const char **out, size_t *size) { - *out = (const char*)ctx->bp->content; - *size = (size_t)ctx->bp->use; + *out = (const char*)xmlBufferContent(ctx->bp); + *size = (size_t)xmlBufferLength(ctx->bp); return (0); } diff --git a/contrib/libarchive/libarchive/archive_write_set_format_zip.c b/contrib/libarchive/libarchive/archive_write_set_format_zip.c index 3630b9f2b3a3..19121b519148 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_zip.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_zip.c @@ -1856,7 +1856,10 @@ archive_write_zip_finish_entry(struct archive_write *a) } ret = __archive_write_output(a, zip->buf, remainder); if (ret != ARCHIVE_OK) + { + deflateEnd(&zip->stream.deflate); return (ret); + } zip->entry_compressed_written += remainder; zip->written_bytes += remainder; zip->stream.deflate.next_out = zip->buf; @@ -1898,7 +1901,10 @@ archive_write_zip_finish_entry(struct archive_write *a) } ret = __archive_write_output(a, zip->buf, remainder); if (ret != ARCHIVE_OK) + { + BZ2_bzCompressEnd(&zip->stream.bzip2); return (ret); + } zip->entry_compressed_written += remainder; zip->written_bytes += remainder; zip->stream.bzip2.next_out = (char*)zip->buf; @@ -1940,13 +1946,17 @@ archive_write_zip_finish_entry(struct archive_write *a) } ret = __archive_write_output(a, zip->buf, remainder); if (ret != ARCHIVE_OK) + { + ZSTD_freeCStream(zip->stream.zstd.context); return (ret); + } zip->entry_compressed_written += remainder; zip->written_bytes += remainder; - zip->stream.zstd.out.dst = zip->buf; if (zip->stream.zstd.out.pos != zip->stream.zstd.out.size) finishing = 0; + zip->stream.zstd.out.dst = zip->buf; zip->stream.zstd.out.size = zip->len_buf; + zip->stream.zstd.out.pos = 0; } while (finishing); ZSTD_freeCStream(zip->stream.zstd.context); break; @@ -1984,7 +1994,10 @@ archive_write_zip_finish_entry(struct archive_write *a) } ret = __archive_write_output(a, zip->buf, remainder); if (ret != ARCHIVE_OK) + { + lzma_end(&zip->stream.lzma.context); return (ret); + } zip->entry_compressed_written += remainder; zip->written_bytes += remainder; zip->stream.lzma.context.next_out = zip->buf; @@ -2434,13 +2447,19 @@ init_winzip_aes_encryption(struct archive_write *a) "Can't generate random number for encryption"); return (ARCHIVE_FATAL); } - archive_pbkdf2_sha1(passphrase, strlen(passphrase), + ret = archive_pbkdf2_sha1(passphrase, strlen(passphrase), salt, salt_len, 1000, derived_key, key_len * 2 + 2); + if (ret != 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + ret == CRYPTOR_STUB_FUNCTION ? "Encryption is unsupported due to " + "lack of crypto library" : "Failed to process passphrase"); + return (ARCHIVE_FAILED); + } ret = archive_encrypto_aes_ctr_init(&zip->cctx, derived_key, key_len); if (ret != 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Decryption is unsupported due to lack of crypto library"); + "Failed to initialize AES CTR mode"); return (ARCHIVE_FAILED); } ret = archive_hmac_sha1_init(&zip->hctx, derived_key + key_len, diff --git a/contrib/libarchive/libarchive/filter_fork_posix.c b/contrib/libarchive/libarchive/filter_fork_posix.c index c895c08e59b3..7c48519336ff 100644 --- a/contrib/libarchive/libarchive/filter_fork_posix.c +++ b/contrib/libarchive/libarchive/filter_fork_posix.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2007 Joerg Sonnenberger - * Copyright (c) 2012 Michihiro NAKAJIMA + * Copyright (c) 2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -76,7 +76,15 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout, { pid_t child = -1; int stdin_pipe[2], stdout_pipe[2], tmp; + +#if !defined(POSIX_SPAWN_CLOEXEC_DEFAULT) && \ + (HAVE_FORK || HAVE_VFORK) && \ + (HAVE_CLOSEFROM || HAVE_CLOSE_RANGE || defined(_SC_OPEN_MAX)) +#undef HAVE_POSIX_SPAWNP +#endif + #if HAVE_POSIX_SPAWNP + posix_spawnattr_t attr; posix_spawn_file_actions_t actions; int r; #endif @@ -107,11 +115,21 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout, #if HAVE_POSIX_SPAWNP - r = posix_spawn_file_actions_init(&actions); + r = posix_spawnattr_init(&attr); if (r != 0) { errno = r; goto stdout_opened; } + r = posix_spawn_file_actions_init(&actions); + if (r != 0) { + errno = r; + goto attr_inited; + } +#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT + r = posix_spawnattr_setflags(&attr, POSIX_SPAWN_CLOEXEC_DEFAULT); + if (r != 0) + goto actions_inited; +#endif r = posix_spawn_file_actions_addclose(&actions, stdin_pipe[1]); if (r != 0) goto actions_inited; @@ -136,11 +154,12 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout, if (r != 0) goto actions_inited; } - r = posix_spawnp(&child, cmdline->path, &actions, NULL, + r = posix_spawnp(&child, cmdline->path, &actions, &attr, cmdline->argv, NULL); if (r != 0) goto actions_inited; posix_spawn_file_actions_destroy(&actions); + posix_spawnattr_destroy(&attr); #else /* HAVE_POSIX_SPAWNP */ @@ -162,6 +181,16 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout, _exit(254); if (stdout_pipe[1] != 1 /* stdout */) close(stdout_pipe[1]); + +#if HAVE_CLOSEFROM + closefrom(3); +#elif HAVE_CLOSE_RANGE + close_range(3, ~0U, 0); +#elif defined(_SC_OPEN_MAX) + for (int i = sysconf(_SC_OPEN_MAX); i > 3;) + close(--i); +#endif + execvp(cmdline->path, cmdline->argv); _exit(254); } @@ -183,6 +212,8 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout, actions_inited: errno = r; posix_spawn_file_actions_destroy(&actions); +attr_inited: + posix_spawnattr_destroy(&attr); #endif stdout_opened: close(stdout_pipe[0]); diff --git a/contrib/libarchive/libarchive/test/test_acl_nfs4.c b/contrib/libarchive/libarchive/test/test_acl_nfs4.c index 98d39689df69..050c0a063654 100644 --- a/contrib/libarchive/libarchive/test/test_acl_nfs4.c +++ b/contrib/libarchive/libarchive/test/test_acl_nfs4.c @@ -145,6 +145,13 @@ static struct archive_test_acl_t acls_bad[] = { ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }, { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE, ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }, + + /* Multiple types */ + { ARCHIVE_ENTRY_ACL_TYPE_ALLOW | ARCHIVE_ENTRY_ACL_TYPE_AUDIT, + ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }, + { ARCHIVE_ENTRY_ACL_TYPE_NFS4, ARCHIVE_ENTRY_ACL_EXECUTE, + ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }, }; DEFINE_TEST(test_acl_nfs4) diff --git a/contrib/libarchive/libarchive/test/test_acl_posix1e.c b/contrib/libarchive/libarchive/test/test_acl_posix1e.c index 025ef6afd102..f9b6ffeb6ab7 100644 --- a/contrib/libarchive/libarchive/test/test_acl_posix1e.c +++ b/contrib/libarchive/libarchive/test/test_acl_posix1e.c @@ -94,6 +94,11 @@ static struct archive_test_acl_t acls_nfs4[] = { { ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" }, + + /* Invalid type codes */ + { ARCHIVE_ENTRY_ACL_TYPE_ACCESS | ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, + ARCHIVE_ENTRY_ACL_READ, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" }, }; DEFINE_TEST(test_acl_posix1e) diff --git a/contrib/libarchive/libarchive/test/test_archive_parse_date.c b/contrib/libarchive/libarchive/test/test_archive_parse_date.c index 0a70971b1da6..5251b3393999 100644 --- a/contrib/libarchive/libarchive/test/test_archive_parse_date.c +++ b/contrib/libarchive/libarchive/test/test_archive_parse_date.c @@ -39,6 +39,8 @@ DEFINE_TEST(test_archive_parse_date) assertEqualInt(get_date(now, "Jan 1, 1970 UTC"), 0); assertEqualInt(get_date(now, "7:12:18-0530 4 May 1983"), 420900138); assertEqualInt(get_date(now, "2004/01/29 513 mest"), 1075345980); + assertEqualInt(get_date(now, "2038-06-01 00:01:02 UTC"), + sizeof(time_t) <= 4 ? -1 : 2158963262); assertEqualInt(get_date(now, "99/02/17 7pm utc"), 919278000); assertEqualInt(get_date(now, "02/17/99 7:11am est"), 919253460); assertEqualInt(get_date(now, "now - 2 hours"), diff --git a/contrib/libarchive/libarchive/test/test_archive_string_conversion.c b/contrib/libarchive/libarchive/test/test_archive_string_conversion.c index 12976f3e70ec..055bddc75068 100644 --- a/contrib/libarchive/libarchive/test/test_archive_string_conversion.c +++ b/contrib/libarchive/libarchive/test/test_archive_string_conversion.c @@ -991,6 +991,7 @@ DEFINE_TEST(test_archive_string_update_utf8_koi8) static const char koi8_string[] = "\xD0\xD2\xC9"; static const wchar_t wcs_string[] = L"\U0000043f\U00000440\U00000438"; struct archive_mstring mstr; + struct archive *a; int r; memset(&mstr, 0, sizeof(mstr)); @@ -999,6 +1000,15 @@ DEFINE_TEST(test_archive_string_update_utf8_koi8) skipping("KOI8-R locale not available on this system."); return; } + a = archive_write_new(); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_pax(a)); + if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) { + skipping("This system cannot convert character-set" + " from KOI8-R to UTF-8."); + archive_write_free(a); + return; + } + archive_write_free(a); r = archive_mstring_update_utf8(NULL, &mstr, utf8_string); diff --git a/contrib/libarchive/libarchive/test/test_entry.c b/contrib/libarchive/libarchive/test/test_entry.c index 9b21b83ecdfb..cff9c5c86efc 100644 --- a/contrib/libarchive/libarchive/test/test_entry.c +++ b/contrib/libarchive/libarchive/test/test_entry.c @@ -880,6 +880,17 @@ DEFINE_TEST(test_entry) if (pst == NULL) return; assertEqualInt(pst->st_uid, 22); + + /* Check behavior with large sizes. */ + archive_entry_set_size(e, INT64_MAX - 1); + assert((pst = archive_entry_stat(e)) != NULL); + if (pst == NULL) + return; + if (sizeof(pst->st_size) < sizeof(int64_t)) + assertEqualInt(pst->st_size, 0); + else + assertEqualInt(pst->st_size, INT64_MAX - 1); + /* We don't need to check high-res fields here. */ /* diff --git a/contrib/libarchive/libarchive/test/test_read_filter_gzip_recursive.c b/contrib/libarchive/libarchive/test/test_read_filter_gzip_recursive.c index 0042a0511d5a..51b614b6c023 100644 --- a/contrib/libarchive/libarchive/test/test_read_filter_gzip_recursive.c +++ b/contrib/libarchive/libarchive/test/test_read_filter_gzip_recursive.c @@ -29,8 +29,8 @@ DEFINE_TEST(test_read_filter_gzip_recursive) const char *name = "test_read_filter_gzip_recursive.gz"; struct archive *a; - if (!canGzip()) { - skipping("gzip not available"); + if (archive_zlib_version() == NULL) { + skipping("zlib not available"); return; } diff --git a/contrib/libarchive/libarchive/test/test_read_format_7zip.c b/contrib/libarchive/libarchive/test/test_read_format_7zip.c index ad10ef06bbc5..3236fee2c9d3 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_7zip.c +++ b/contrib/libarchive/libarchive/test/test_read_format_7zip.c @@ -1285,19 +1285,26 @@ DEFINE_TEST(test_read_format_7zip_sfx_pe) const char test_txt[] = "123"; int size = sizeof(test_txt) - 1; - extract_reference_file(reffile); assert((a = archive_read_new()) != NULL); - assertA(0 == archive_read_support_filter_all(a)); - assertA(0 == archive_read_support_format_all(a)); - assertA(0 == archive_read_open_filename(a, reffile, bs)); - assertA(0 == archive_read_next_header(a, &ae)); - assertEqualString("test.txt.txt", archive_entry_pathname(ae)); + if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) { + skipping( + "7zip:lzma decoding is not supported on this platform"); + } else { + extract_reference_file(reffile); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filename(a, reffile, bs)); - assertA(size == archive_read_data(a, buff, size)); - assertEqualMem(buff, test_txt, size); + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.txt.txt", archive_entry_pathname(ae)); + + assertA(size == archive_read_data(a, buff, size)); + assertEqualMem(buff, test_txt, size); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -1316,19 +1323,26 @@ DEFINE_TEST(test_read_format_7zip_sfx_modified_pe) const char test_txt[] = "123"; int size = sizeof(test_txt) - 1; - extract_reference_file(reffile); assert((a = archive_read_new()) != NULL); - assertA(0 == archive_read_support_filter_all(a)); - assertA(0 == archive_read_support_format_all(a)); - assertA(0 == archive_read_open_filename(a, reffile, bs)); - assertA(0 == archive_read_next_header(a, &ae)); - assertEqualString("test.txt.txt", archive_entry_pathname(ae)); + if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) { + skipping( + "7zip:lzma decoding is not supported on this platform"); + } else { + extract_reference_file(reffile); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filename(a, reffile, bs)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.txt.txt", archive_entry_pathname(ae)); + + assertA(size == archive_read_data(a, buff, size)); + assertEqualMem(buff, test_txt, size); - assertA(size == archive_read_data(a, buff, size)); - assertEqualMem(buff, test_txt, size); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -1346,20 +1360,27 @@ DEFINE_TEST(test_read_format_7zip_sfx_elf) const char test_txt[] = "123"; int size = sizeof(test_txt) - 1; - extract_reference_file(reffile); assert((a = archive_read_new()) != NULL); - assertA(0 == archive_read_support_filter_all(a)); - assertA(0 == archive_read_support_format_all(a)); - assertA(0 == archive_read_open_filename(a, reffile, bs)); - assertA(0 == archive_read_next_header(a, &ae)); - assertEqualString("test.txt.txt", archive_entry_pathname(ae)); + if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) { + skipping( + "7zip:lzma decoding is not supported on this platform"); + } else { + extract_reference_file(reffile); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filename(a, reffile, bs)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("test.txt.txt", archive_entry_pathname(ae)); - assertA(size == archive_read_data(a, buff, size)); - assertEqualMem(buff, test_txt, size); + assertA(size == archive_read_data(a, buff, size)); + assertEqualMem(buff, test_txt, size); - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_7zip_extract_second) @@ -1597,9 +1618,9 @@ DEFINE_TEST(test_read_format_7zip_lzma2_powerpc) assert((a = archive_read_new()) != NULL); - if (ARCHIVE_OK != archive_read_support_filter_gzip(a)) { + if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) { skipping( - "7zip:deflate decoding is not supported on this platform"); + "7zip:lzma decoding is not supported on this platform"); } else { test_powerpc_filter("test_read_format_7zip_lzma2_powerpc.7z"); } diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar5.c b/contrib/libarchive/libarchive/test/test_read_format_rar5.c index fd233277bc1b..6ab0d236a1ed 100644 --- a/contrib/libarchive/libarchive/test/test_read_format_rar5.c +++ b/contrib/libarchive/libarchive/test/test_read_format_rar5.c @@ -1111,6 +1111,18 @@ DEFINE_TEST(test_read_format_rar5_nonempty_dir_stream) EPILOGUE(); } +DEFINE_TEST(test_read_format_rar5_nonempty_dir_data) +{ + PROLOGUE("test_read_format_rar5_dirdata.rar"); + + /* This archive is invalid. It declares a directory entry with nonzero + data size. */ + + assertA(archive_read_next_header(a, &ae) == ARCHIVE_FATAL); + + EPILOGUE(); +} + DEFINE_TEST(test_read_format_rar5_fileattr) { unsigned long set, clear, flag; @@ -1428,3 +1440,57 @@ DEFINE_TEST(test_read_format_rar5_data_ready_pointer_leak) EPILOGUE(); } + +DEFINE_TEST(test_read_format_rar5_only_crypt_exfld) +{ + /* GH #2711 */ + + char buf[4096]; + PROLOGUE("test_read_format_rar5_only_crypt_exfld.rar"); + + /* The reader should allow iteration through files, but should fail + during data extraction. */ + + assertA(archive_read_next_header(a, &ae) == ARCHIVE_OK); + assertA(archive_read_data(a, buf, sizeof(buf)) == ARCHIVE_FATAL); + + /* The reader should also provide a valid error message. */ + assertA(archive_error_string(a) != NULL); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_only_unsupported_exfld) +{ + /* GH #2711 */ + + char buf[4096]; + PROLOGUE("test_read_format_rar5_unsupported_exfld.rar"); + + /* The reader should allow iteration through files, and it should + succeed with data extraction. */ + + assertA(archive_read_next_header(a, &ae) == ARCHIVE_OK); + + /* 48 is the expected number of bytes that should be extracted */ + assertA(archive_read_data(a, buf, sizeof(buf)) == 48); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_invalidhash_and_validhtime_exfld) +{ + /* GH #2711 */ + + char buf[4096]; + PROLOGUE("test_read_format_rar5_invalid_hash_valid_htime_exfld.rar"); + + /* The reader should report an error when trying to process this data. + Returning EOF here means that the reader has failed to identify + malformed structure. */ + + assertA(archive_read_next_header(a, &ae) < 0); + assertA(archive_read_data(a, buf, sizeof(buf)) < 0); + + EPILOGUE(); +} diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar5_dirdata.rar.uu b/contrib/libarchive/libarchive/test/test_read_format_rar5_dirdata.rar.uu new file mode 100644 index 000000000000..c7928f344a80 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_rar5_dirdata.rar.uu @@ -0,0 +1,6 @@ +begin 644 - +M4F%R(1H'`0`BD'[;,`$%,#8P`0&`@("``B?GD;$U`@(+@X``"_C5%:2#``(` +M`#"``S`P,#`P,#`P,#!);S#6KA',@]:N$?*IN;YV[8"1S>?4^`,#`R,#`P,# +-`P,#1)'C@XX*4`O.^P`` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar5_invalid_hash_valid_htime_exfld.rar.uu b/contrib/libarchive/libarchive/test/test_read_format_rar5_invalid_hash_valid_htime_exfld.rar.uu new file mode 100644 index 000000000000..399acd814ae4 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_rar5_invalid_hash_valid_htime_exfld.rar.uu @@ -0,0 +1,6 @@ +begin 644 - +M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`#^T/5L)`(###$$,>V#`D840I@``0AF +M:6QE+G1X=`@"OX0]``$"`P(#`&EN=F%L:60@2$%32"!E>'1R82P@86YD(&QA +>=&5R(&$@=F%L:60@2%1)344@97AT<F$@/=^&`@4$ +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar5_only_crypt_exfld.rar.uu b/contrib/libarchive/libarchive/test/test_read_format_rar5_only_crypt_exfld.rar.uu new file mode 100644 index 000000000000..4f9faf350c11 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_rar5_only_crypt_exfld.rar.uu @@ -0,0 +1,7 @@ +begin 644 - +M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`"!0_"Y/0(#)2X$+NV#`IB>)!,``0AF +M:6QE+G1X="0!```&``````````````````````````````````````````!R +M87(U('-T;W)E9"!F:6QE('=I=&@@;VYL>2!A($-265!4(&5X=')A(&9I96QD +'(#W?A@(%!``` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar5_unsupported_exfld.rar.uu b/contrib/libarchive/libarchive/test/test_read_format_rar5_unsupported_exfld.rar.uu new file mode 100644 index 000000000000..16b456bf4873 --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_rar5_unsupported_exfld.rar.uu @@ -0,0 +1,6 @@ +begin 644 - +M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`#>[JDS)@(##C`$,.V#`BX6Z[0``0AF +M:6QE+G1X=`W_____#WA6-!(`````<F%R-2!S=&]R960@9FEL92!W:71H(&%N +?('5N<W5P<&]R=&5D(&5X=')A(&9I96QD(#W?A@(%!``` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_format_tar_V_negative_size.c b/contrib/libarchive/libarchive/test/test_read_format_tar_V_negative_size.c new file mode 100644 index 000000000000..d110553acfaf --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_tar_V_negative_size.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2025 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_read_format_tar_V_negative_size) +{ + /* + * An archive that contains a `V` volume header with a negative body size + * + * This used to lead to an infinite loop: the tar reader would "advance" + * by the size of the body to skip it, which would in this case end up + * reversing back to the beginning of the same header. + */ + struct archive_entry *ae; + struct archive *a; + const char *refname = "test_read_format_tar_V_negative_size.tar"; + + extract_reference_file(refname); + assert((a = archive_read_new()) != NULL); + assertEqualInt(ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualInt(ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/contrib/libarchive/libarchive/test/test_read_format_tar_V_negative_size.tar.uu b/contrib/libarchive/libarchive/test/test_read_format_tar_V_negative_size.tar.uu new file mode 100644 index 000000000000..230d710c8f8f --- /dev/null +++ b/contrib/libarchive/libarchive/test/test_read_format_tar_V_negative_size.tar.uu @@ -0,0 +1,20 @@ +Tar archive with a single `V` header that has a negative size. +This used to result in an infinite loop -- the tar reader would +"advance" by the size of the header, which in this case just backed +up to re-read the same header again. + +begin 644 test_read_format_tar_V_negative_size.tar +M`#(VXP```````````````````-Z;@"E&LOX^\@````````````!7````'``` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````#___\````````@```` +M````````````````````````````5H%ZL#X]SH\-``":SN#[C4;Z5OOW-&'] +M?HHQ%WRG?Z$Q>^E#_1.OY96VEI*Z<U[)$TR502_;F$;9FU"/F'!`V:0````` +M`````````````````````````````````````````````````````0`````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````0`````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +1```````````````````````` +` +end diff --git a/contrib/libarchive/libarchive/test/test_read_set_format.c b/contrib/libarchive/libarchive/test/test_read_set_format.c index c760de0056d3..615dd8ae8022 100644 --- a/contrib/libarchive/libarchive/test/test_read_set_format.c +++ b/contrib/libarchive/libarchive/test/test_read_set_format.c @@ -138,7 +138,10 @@ DEFINE_TEST(test_read_append_filter) assertEqualInt(ARCHIVE_OK, archive_read_free(a)); return; } - assertEqualIntA(a, ARCHIVE_OK, r); + if (r == ARCHIVE_WARN && canGzip()) + assertEqualString(archive_error_string(a), "Using external gzip program"); + else + assertEqualIntA(a, ARCHIVE_OK, r); assertEqualInt(ARCHIVE_OK, archive_read_open_memory(a, archive, sizeof(archive))); assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &ae)); @@ -210,7 +213,7 @@ DEFINE_TEST(test_read_append_filter_wrong_program) /* * If we have "bunzip2 -q", try using that. */ - if (!canRunCommand("bunzip2 -h")) { + if (!canRunCommand("bunzip2 -h", NULL)) { skipping("Can't run bunzip2 program on this platform"); return; } diff --git a/contrib/libarchive/libarchive/test/test_write_filter_bzip2.c b/contrib/libarchive/libarchive/test/test_write_filter_bzip2.c index 20ca0d9a7b22..7b2e4f857a75 100644 --- a/contrib/libarchive/libarchive/test/test_write_filter_bzip2.c +++ b/contrib/libarchive/libarchive/test/test_write_filter_bzip2.c @@ -268,6 +268,35 @@ DEFINE_TEST(test_write_filter_bzip2) assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* + * Test behavior after a fatal error (triggered by giving + * archive_write_open_memory() a very small buffer). + */ + if (!use_prog) { + used1 = 0; + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_format_ustar(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_add_filter_bzip2(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, 100, &used1)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_size(ae, 4000000); + archive_entry_copy_pathname(ae, "file"); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_header(a, ae)); + for (i = 0; i < 1000000; i++) { + r = archive_write_data(a, &i, 4); + if (r == ARCHIVE_FATAL) + break; + } + assertEqualIntA(a, ARCHIVE_FATAL, r); + archive_entry_free(ae); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + } + + /* * Clean up. */ free(data); diff --git a/contrib/libarchive/libarchive/test/test_write_filter_gzip.c b/contrib/libarchive/libarchive/test/test_write_filter_gzip.c index 8fbdbed09744..a6681d7618b1 100644 --- a/contrib/libarchive/libarchive/test/test_write_filter_gzip.c +++ b/contrib/libarchive/libarchive/test/test_write_filter_gzip.c @@ -166,9 +166,15 @@ DEFINE_TEST(test_write_filter_gzip) assertEqualInt(rbuff[0], 0x1f); assertEqualInt(rbuff[1], 0x8b); assertEqualInt(rbuff[2], 0x08); - assertEqualInt(rbuff[3], 0x08); - assertEqualInt(rbuff[8], 2); /* RFC 1952 flag for compression level 9 */ - assertEqualString((const char*)rbuff+10, "testorgfilename"); + /* RFC 1952 flag for compression level 9 */ + assertEqualInt(rbuff[8], 2); + /* External gzip program might not save filename */ + if (!use_prog || rbuff[3] == 0x08) { + assertEqualInt(rbuff[3], 0x08); + assertEqualString((const char*)rbuff+10, "testorgfilename"); + } else { + assertEqualInt(rbuff[3], 0x00); + } /* Curiously, this test fails; the test data above compresses * better at default compression than at level 9. */ diff --git a/contrib/libarchive/libarchive/test/test_write_filter_gzip_timestamp.c b/contrib/libarchive/libarchive/test/test_write_filter_gzip_timestamp.c index a148f818dcec..d0496b025b64 100644 --- a/contrib/libarchive/libarchive/test/test_write_filter_gzip_timestamp.c +++ b/contrib/libarchive/libarchive/test/test_write_filter_gzip_timestamp.c @@ -81,8 +81,11 @@ DEFINE_TEST(test_write_filter_gzip_timestamp) archive_entry_free(ae); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); - failure("Timestamp should be recorded"); - assert(memcmp(buff + 4, "\x00\x00\x00\x00", 4) != 0); + /* External gzip program might not save timestamp */ + if (!use_prog) { + failure("Timestamp should be recorded"); + assert(memcmp(buff + 4, "\x00\x00\x00\x00", 4) != 0); + } /* Test2: set "gzip:!timestamp" option. */ assert((a = archive_write_new()) != NULL); diff --git a/contrib/libarchive/libarchive_fe/err.c b/contrib/libarchive/libarchive_fe/lafe_err.c index f6dcf44af347..b108b9b1fea7 100644 --- a/contrib/libarchive/libarchive_fe/err.c +++ b/contrib/libarchive/libarchive_fe/lafe_err.c @@ -36,7 +36,7 @@ #include <string.h> #endif -#include "err.h" +#include "lafe_err.h" static void lafe_vwarnc(int, const char *, va_list) __LA_PRINTFLIKE(2, 0); diff --git a/contrib/libarchive/libarchive_fe/err.h b/contrib/libarchive/libarchive_fe/lafe_err.h index f4a66350a669..f4a66350a669 100644 --- a/contrib/libarchive/libarchive_fe/err.h +++ b/contrib/libarchive/libarchive_fe/lafe_err.h diff --git a/contrib/libarchive/libarchive_fe/line_reader.c b/contrib/libarchive/libarchive_fe/line_reader.c index 7f0429ece3cf..0af9db53c0a2 100644 --- a/contrib/libarchive/libarchive_fe/line_reader.c +++ b/contrib/libarchive/libarchive_fe/line_reader.c @@ -31,7 +31,7 @@ #include <stdlib.h> #include <string.h> -#include "err.h" +#include "lafe_err.h" #include "line_reader.h" #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__) diff --git a/contrib/libarchive/libarchive_fe/passphrase.c b/contrib/libarchive/libarchive_fe/passphrase.c index 527ad2d63654..1b7a50453664 100644 --- a/contrib/libarchive/libarchive_fe/passphrase.c +++ b/contrib/libarchive/libarchive_fe/passphrase.c @@ -61,7 +61,7 @@ #include <readpassphrase.h> #endif -#include "err.h" +#include "lafe_err.h" #include "passphrase.h" #ifndef HAVE_READPASSPHRASE diff --git a/contrib/libarchive/tar/bsdtar.c b/contrib/libarchive/tar/bsdtar.c index 53ac135f0129..92e86fd6bd94 100644 --- a/contrib/libarchive/tar/bsdtar.c +++ b/contrib/libarchive/tar/bsdtar.c @@ -55,7 +55,7 @@ #endif #include "bsdtar.h" -#include "err.h" +#include "lafe_err.h" #if ARCHIVE_VERSION_NUMBER < 4000000 && !defined(_PATH_DEFTAPE) // Libarchive 4.0 and later will NOT define _PATH_DEFTAPE @@ -183,6 +183,11 @@ main(int argc, char **argv) sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, NULL); #endif +#ifdef SIGCHLD + /* Do not ignore SIGCHLD. */ + sa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &sa, NULL); +#endif } #endif diff --git a/contrib/libarchive/tar/bsdtar.h b/contrib/libarchive/tar/bsdtar.h index 45dfeed7dce3..782d36d6f756 100644 --- a/contrib/libarchive/tar/bsdtar.h +++ b/contrib/libarchive/tar/bsdtar.h @@ -16,6 +16,12 @@ #define ENV_WRITER_OPTIONS "TAR_WRITER_OPTIONS" #define IGNORE_WRONG_MODULE_NAME "__ignore_wrong_module_name__," +#if defined(_MSC_VER ) && (_MSC_VER < 1927 ) /* Check if compiler pre-dated Visual Studio 2019 Release 16.8 */ +#define ARCHIVE_RESTRICT +#else +#define ARCHIVE_RESTRICT restrict +#endif + struct creation_set; /* * The internal state for the "bsdtar" program. @@ -188,7 +194,7 @@ int edit_pathname(struct bsdtar *, struct archive_entry *); void edit_mtime(struct bsdtar *, struct archive_entry *); int need_report(void); int pathcmp(const char *a, const char *b); -void safe_fprintf(FILE * restrict, const char * restrict fmt, ...) __LA_PRINTF(2, 3); +void safe_fprintf(FILE * ARCHIVE_RESTRICT, const char * ARCHIVE_RESTRICT fmt, ...) __LA_PRINTF(2, 3); void set_chdir(struct bsdtar *, const char *newdir); const char *tar_i64toa(int64_t); void tar_mode_c(struct bsdtar *bsdtar); diff --git a/contrib/libarchive/tar/cmdline.c b/contrib/libarchive/tar/cmdline.c index c766c1a52dbb..309be312c948 100644 --- a/contrib/libarchive/tar/cmdline.c +++ b/contrib/libarchive/tar/cmdline.c @@ -22,7 +22,7 @@ #endif #include "bsdtar.h" -#include "err.h" +#include "lafe_err.h" /* * Short options for tar. Please keep this sorted. diff --git a/contrib/libarchive/tar/creation_set.c b/contrib/libarchive/tar/creation_set.c index 6883090418b0..51f803354a5d 100644 --- a/contrib/libarchive/tar/creation_set.c +++ b/contrib/libarchive/tar/creation_set.c @@ -15,7 +15,7 @@ #endif #include "bsdtar.h" -#include "err.h" +#include "lafe_err.h" struct creation_set { char *create_format; diff --git a/contrib/libarchive/tar/read.c b/contrib/libarchive/tar/read.c index 8563fe714f9a..7cbcfb19ff0a 100644 --- a/contrib/libarchive/tar/read.c +++ b/contrib/libarchive/tar/read.c @@ -57,7 +57,7 @@ #endif #include "bsdtar.h" -#include "err.h" +#include "lafe_err.h" struct progress_data { struct bsdtar *bsdtar; diff --git a/contrib/libarchive/tar/subst.c b/contrib/libarchive/tar/subst.c index 5546b5f93b12..a5d644dc5a70 100644 --- a/contrib/libarchive/tar/subst.c +++ b/contrib/libarchive/tar/subst.c @@ -25,7 +25,7 @@ #define REG_BASIC 0 #endif -#include "err.h" +#include "lafe_err.h" struct subst_rule { struct subst_rule *next; diff --git a/contrib/libarchive/tar/test/test_crlf_mtree.c b/contrib/libarchive/tar/test/test_crlf_mtree.c new file mode 100644 index 000000000000..5ef8811369c1 --- /dev/null +++ b/contrib/libarchive/tar/test/test_crlf_mtree.c @@ -0,0 +1,74 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2018 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Arshan Khanifar <arshankhanifar@gmail.com> + * under sponsorship from the FreeBSD Foundation. + */ +#include "test.h" + +DEFINE_TEST(test_crlf_mtree) +{ + char *p0; + size_t s; + int r; + p0 = NULL; + char *content = "#mtree\r\n" + "f type=file uname=\\\r\n" + "root gname=root mode=0755 content=bar/foo\r\n" + "g type=file uname=root gname=root mode=0755 content=bar/goo\r\n"; + char *filename = "output.tar"; +#if defined(_WIN32) && !defined(__CYGWIN__) + char *p; +#endif + + /* an absolute path to mtree file */ + char *mtree_file = "/METALOG.mtree"; + char *absolute_path = malloc(strlen(testworkdir) + strlen(mtree_file) + 1); + strcpy(absolute_path, testworkdir); + strcat(absolute_path, mtree_file ); + + /* Create an archive using an mtree file. */ + assertMakeFile(absolute_path, 0777, content); + assertMakeDir("bar", 0775); + assertMakeFile("bar/foo", 0777, "abc"); + assertMakeFile("bar/goo", 0777, "abc"); + +#if defined(_WIN32) && !defined(__CYGWIN__) + p = absolute_path; + while(*p != '\0') { + if (*p == '/') + *p = '\\'; + p++; + } + + r = systemf("%s -cf %s @%s >step1.out 2>step1.err", testprog, filename, absolute_path); + failure("Error invoking %s -cf %s -C bar @%s", testprog, filename, absolute_path); +#else + r = systemf("%s -cf %s \"@%s\" >step1.out 2>step1.err", testprog, filename, absolute_path); + failure("Error invoking %s -cf %s -C bar \"@%s\"", testprog, filename, absolute_path); +#endif + + assertEqualInt(r, 0); + assertEmptyFile("step1.out"); + assertEmptyFile("step1.err"); + + /* Do validation of the constructed archive. */ + + p0 = slurpfile(&s, "output.tar"); + if (!assert(p0 != NULL)) + goto done; + if (!assert(s >= 2048)) + goto done; + assertEqualMem(p0 + 0, "f", 2); + assertEqualMem(p0 + 512, "abc", 4); + assertEqualMem(p0 + 1024, "g", 2); + assertEqualMem(p0 + 1536, "abc", 4); +done: + free(p0); + free(absolute_path); +} + + diff --git a/contrib/libarchive/tar/test/test_option_safe_writes.c b/contrib/libarchive/tar/test/test_option_safe_writes.c index b88479bc5f35..d30b9a745927 100644 --- a/contrib/libarchive/tar/test/test_option_safe_writes.c +++ b/contrib/libarchive/tar/test/test_option_safe_writes.c @@ -16,11 +16,12 @@ DEFINE_TEST(test_option_safe_writes) assertMakeFile("d", 0644, "c"); assertMakeFile("fs", 0644, "d"); assertMakeFile("ds", 0644, "e"); + assertMakeDir("fd", 0755); assertEqualInt(0, chdir("..")); /* Tar files up */ assertEqualInt(0, - systemf("%s -c -C in -f t.tar f fh d fs ds " + systemf("%s -c -C in -f t.tar f fh d fs ds fd " ">pack.out 2>pack.err", testprog)); /* Verify that nothing went to stdout or stderr. */ @@ -32,6 +33,7 @@ DEFINE_TEST(test_option_safe_writes) assertEqualInt(0, chdir("out")); assertMakeFile("f", 0644, "a"); assertMakeHardlink("fh", "f"); + assertMakeFile("fd", 0644, "b"); assertMakeDir("d", 0755); if (canSymlink()) { assertMakeSymlink("fs", "f", 0); @@ -55,4 +57,5 @@ DEFINE_TEST(test_option_safe_writes) assertTextFileContents("c","d"); assertTextFileContents("d","fs"); assertTextFileContents("e","ds"); + assertIsDir("fd", 0755); } diff --git a/contrib/libarchive/tar/util.c b/contrib/libarchive/tar/util.c index c99f67797562..fc5e15cb039f 100644 --- a/contrib/libarchive/tar/util.c +++ b/contrib/libarchive/tar/util.c @@ -41,7 +41,7 @@ #endif #include "bsdtar.h" -#include "err.h" +#include "lafe_err.h" #include "passphrase.h" static size_t bsdtar_expand_char(char *, size_t, size_t, char); @@ -682,6 +682,7 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry) { char tmp[100]; size_t w; + size_t sw; const char *p; const char *fmt; time_t tim; @@ -769,8 +770,8 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry) ltime = localtime(&tim); #endif if (ltime) - strftime(tmp, sizeof(tmp), fmt, ltime); - else + sw = strftime(tmp, sizeof(tmp), fmt, ltime); + if (!ltime || !sw) sprintf(tmp, "-- -- ----"); fprintf(out, " %s ", tmp); safe_fprintf(out, "%s", archive_entry_pathname(entry)); diff --git a/contrib/libarchive/tar/write.c b/contrib/libarchive/tar/write.c index 21984e980ebd..9e6c97b580b7 100644 --- a/contrib/libarchive/tar/write.c +++ b/contrib/libarchive/tar/write.c @@ -58,7 +58,7 @@ #endif #include "bsdtar.h" -#include "err.h" +#include "lafe_err.h" #include "line_reader.h" #ifndef O_BINARY @@ -111,7 +111,32 @@ seek_file(int fd, int64_t offset, int whence) return (SetFilePointerEx((HANDLE)_get_osfhandle(fd), distance, NULL, FILE_BEGIN) ? 1 : -1); } -#define open _open + +static int +_open_wrap_sopen(char const *const path, int const oflag, ...) +{ + va_list ap; + int r, pmode; + + pmode = 0; + if (oflag & _O_CREAT) + { + va_start(ap, oflag); + pmode = va_arg(ap, int); + va_end(ap); + } + + _sopen_s(&r, path, oflag, _SH_DENYNO, pmode & 0600); + if (r < 0) + { + /* _sopen_s populates errno */ + return -1; + } + + return r; +} + +#define open _open_wrap_sopen #define close _close #define read _read #ifdef lseek diff --git a/contrib/libarchive/test_utils/test_common.h b/contrib/libarchive/test_utils/test_common.h index 064f0a6ec241..a9df300e3be8 100644 --- a/contrib/libarchive/test_utils/test_common.h +++ b/contrib/libarchive/test_utils/test_common.h @@ -340,8 +340,14 @@ int canGrzip(void); /* Return true if this platform can run the "gzip" program. */ int canGzip(void); -/* Return true if this platform can run the specified command. */ -int canRunCommand(const char *); +/* Return true if this platform can run the specified command. + * + * Result can be optionally cached with `*tested`: + * - 0 if not tested yet + * - <0 if already tested negative + * - >0 if already tested positive + */ +int canRunCommand(const char *cmd, int *tested); /* Return true if this platform can run the "lrzip" program. */ int canLrzip(void); diff --git a/contrib/libarchive/test_utils/test_main.c b/contrib/libarchive/test_utils/test_main.c index fe330e5a052e..f4d443060d88 100644 --- a/contrib/libarchive/test_utils/test_main.c +++ b/contrib/libarchive/test_utils/test_main.c @@ -2523,167 +2523,77 @@ static const char *redirectArgs = ">NUL 2>NUL"; /* Win32 cmd.exe */ #else static const char *redirectArgs = ">/dev/null 2>/dev/null"; /* POSIX 'sh' */ #endif + /* - * Can this platform run the bzip2 program? + * Can this platform run the specified command? */ int -canBzip2(void) +canRunCommand(const char *cmd, int *tested) { - static int tested = 0, value = 0; - if (!tested) { - tested = 1; - if (systemf("bzip2 --help %s", redirectArgs) == 0) - value = 1; - } - return (value); + int value = tested ? *tested : 0; + if (!value) { + value = systemf("%s %s", cmd, redirectArgs) ? -1 : +1; + if (tested) + *tested = value; + } + return (value > 0); } +#define CAN_RUN_FUNC(Program, Command) \ + int can##Program(void) { \ + static int tested = 0; \ + return canRunCommand((Command), &tested); \ + } + +/* + * Can this platform run the bzip2 program? + */ +CAN_RUN_FUNC(Bzip2, "bzip2 --help") + /* * Can this platform run the grzip program? */ -int -canGrzip(void) -{ - static int tested = 0, value = 0; - if (!tested) { - tested = 1; - if (systemf("grzip -V %s", redirectArgs) == 0) - value = 1; - } - return (value); -} +CAN_RUN_FUNC(Grzip, "grzip -V") /* * Can this platform run the gzip program? */ -int -canGzip(void) -{ - static int tested = 0, value = 0; - if (!tested) { - tested = 1; - if (systemf("gzip --help %s", redirectArgs) == 0) - value = 1; - } - return (value); -} +CAN_RUN_FUNC(Gzip, "gzip --help") /* * Can this platform run the lrzip program? */ -int -canRunCommand(const char *cmd) -{ - static int tested = 0, value = 0; - if (!tested) { - tested = 1; - if (systemf("%s %s", cmd, redirectArgs) == 0) - value = 1; - } - return (value); -} - -int -canLrzip(void) -{ - static int tested = 0, value = 0; - if (!tested) { - tested = 1; - if (systemf("lrzip -V %s", redirectArgs) == 0) - value = 1; - } - return (value); -} +CAN_RUN_FUNC(Lrzip, "lrzip -V") /* * Can this platform run the lz4 program? */ -int -canLz4(void) -{ - static int tested = 0, value = 0; - if (!tested) { - tested = 1; - if (systemf("lz4 --help %s", redirectArgs) == 0) - value = 1; - } - return (value); -} +CAN_RUN_FUNC(Lz4, "lz4 --help") /* * Can this platform run the zstd program? */ -int -canZstd(void) -{ - static int tested = 0, value = 0; - if (!tested) { - tested = 1; - if (systemf("zstd --help %s", redirectArgs) == 0) - value = 1; - } - return (value); -} +CAN_RUN_FUNC(Zstd, "zstd --help") /* * Can this platform run the lzip program? */ -int -canLzip(void) -{ - static int tested = 0, value = 0; - if (!tested) { - tested = 1; - if (systemf("lzip --help %s", redirectArgs) == 0) - value = 1; - } - return (value); -} +CAN_RUN_FUNC(Lzip, "lzip --help") /* * Can this platform run the lzma program? */ -int -canLzma(void) -{ - static int tested = 0, value = 0; - if (!tested) { - tested = 1; - if (systemf("lzma --help %s", redirectArgs) == 0) - value = 1; - } - return (value); -} +CAN_RUN_FUNC(Lzma, "lzma --help") /* * Can this platform run the lzop program? */ -int -canLzop(void) -{ - static int tested = 0, value = 0; - if (!tested) { - tested = 1; - if (systemf("lzop --help %s", redirectArgs) == 0) - value = 1; - } - return (value); -} +CAN_RUN_FUNC(Lzop, "lzop --help") /* * Can this platform run the xz program? */ -int -canXz(void) -{ - static int tested = 0, value = 0; - if (!tested) { - tested = 1; - if (systemf("xz --help %s", redirectArgs) == 0) - value = 1; - } - return (value); -} +CAN_RUN_FUNC(Xz, "xz --help") /* * Can this filesystem handle nodump flags. @@ -4184,6 +4094,9 @@ main(int argc, char **argv) if (testprogfile == NULL) { tmp2_len = strlen(testprogdir) + 1 + strlen(PROGRAM) + 1; +#if defined(_WIN32) && !defined(__CYGWIN__) + tmp2_len += 4; +#endif if ((tmp2 = malloc(tmp2_len)) == NULL) { fprintf(stderr, "ERROR: Out of memory."); @@ -4192,6 +4105,9 @@ main(int argc, char **argv) strncpy(tmp2, testprogdir, tmp2_len); strncat(tmp2, "/", tmp2_len); strncat(tmp2, PROGRAM, tmp2_len); +#if defined(_WIN32) && !defined(__CYGWIN__) + strncat(tmp2, ".exe", tmp2_len); +#endif testprogfile = tmp2; } diff --git a/contrib/libarchive/unzip/bsdunzip.c b/contrib/libarchive/unzip/bsdunzip.c index 621afbeb9d6a..1b520e841690 100644 --- a/contrib/libarchive/unzip/bsdunzip.c +++ b/contrib/libarchive/unzip/bsdunzip.c @@ -29,6 +29,9 @@ #ifdef HAVE_LOCALE_H #include <locale.h> #endif +#ifdef HAVE_SIGNAL_H +#include <signal.h> +#endif #ifdef HAVE_STDARG_H #include <stdarg.h> #endif @@ -54,7 +57,7 @@ #include "bsdunzip.h" #include "passphrase.h" -#include "err.h" +#include "lafe_err.h" /* command-line options */ static int a_opt; /* convert EOL */ @@ -1187,6 +1190,16 @@ main(int argc, char *argv[]) const char *zipfile; int nopts; +#if defined(HAVE_SIGACTION) && defined(SIGCHLD) + { /* Do not ignore SIGCHLD. */ + struct sigaction sa; + sa.sa_handler = SIG_DFL; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGCHLD, &sa, NULL); + } +#endif + lafe_setprogname(*argv, "bsdunzip"); #if HAVE_SETLOCALE diff --git a/contrib/libarchive/unzip/cmdline.c b/contrib/libarchive/unzip/cmdline.c index 8afddedd5ead..8e6eedd2321c 100644 --- a/contrib/libarchive/unzip/cmdline.c +++ b/contrib/libarchive/unzip/cmdline.c @@ -21,7 +21,7 @@ #endif #include "bsdunzip.h" -#include "err.h" +#include "lafe_err.h" /* * Short options for bsdunzip. Please keep this sorted. diff --git a/contrib/libarchive/unzip/test/test_C.c b/contrib/libarchive/unzip/test/test_C.c index 66835c8406f3..d386bd61e85d 100644 --- a/contrib/libarchive/unzip/test/test_C.c +++ b/contrib/libarchive/unzip/test/test_C.c @@ -9,6 +9,7 @@ /* Test C arg - match case-insensitive */ DEFINE_TEST(test_C) { +#ifdef HAVE_LIBZ const char *reffile = "test_basic.zip"; int r; @@ -19,4 +20,7 @@ DEFINE_TEST(test_C) assertEmptyFile("test.err"); assertTextFileContents("contents CAPS\n", "test_basic/CAPS"); +#else + skipping("zlib not available"); +#endif } diff --git a/contrib/libarchive/unzip/test/test_L.c b/contrib/libarchive/unzip/test/test_L.c index 5b004d5d5707..85b43f592542 100644 --- a/contrib/libarchive/unzip/test/test_L.c +++ b/contrib/libarchive/unzip/test/test_L.c @@ -9,6 +9,7 @@ /* Test L arg - make names lowercase */ DEFINE_TEST(test_L) { +#ifdef HAVE_LIBZ const char *reffile = "test_basic.zip"; int r; @@ -22,4 +23,7 @@ DEFINE_TEST(test_L) assertTextFileContents("contents b\n", "test_basic/b"); assertTextFileContents("contents c\n", "test_basic/c"); assertTextFileContents("contents CAPS\n", "test_basic/caps"); +#else + skipping("zlib not available"); +#endif } diff --git a/contrib/libarchive/unzip/test/test_P_encryption.c b/contrib/libarchive/unzip/test/test_P_encryption.c index e2cf3cda0ebd..ed08a068811b 100644 --- a/contrib/libarchive/unzip/test/test_P_encryption.c +++ b/contrib/libarchive/unzip/test/test_P_encryption.c @@ -14,9 +14,13 @@ DEFINE_TEST(test_P_encryption) extract_reference_file(reffile); r = systemf("%s -P password %s >test.out 2>test.err", testprog, reffile); - assertEqualInt(0, r); - assertNonEmptyFile("test.out"); - assertEmptyFile("test.err"); + if (r == 256) { + assertTextFileContents("unzip: Decryption is unsupported due to lack of crypto library\n", "test.err"); + } else { + assertEqualInt(0, r); + assertNonEmptyFile("test.out"); + assertEmptyFile("test.err"); - assertTextFileContents("plaintext\n", "encrypted/file.txt"); + assertTextFileContents("plaintext\n", "encrypted/file.txt"); + } } diff --git a/contrib/libarchive/unzip/test/test_basic.c b/contrib/libarchive/unzip/test/test_basic.c index 1f37dcd416a3..3a884aa30e5d 100644 --- a/contrib/libarchive/unzip/test/test_basic.c +++ b/contrib/libarchive/unzip/test/test_basic.c @@ -9,6 +9,7 @@ /* This test just does a basic zip decompression */ DEFINE_TEST(test_basic) { +#ifdef HAVE_LIBZ const char *reffile = "test_basic.zip"; int r; @@ -22,4 +23,7 @@ DEFINE_TEST(test_basic) assertTextFileContents("contents b\n", "test_basic/b"); assertTextFileContents("contents c\n", "test_basic/c"); assertTextFileContents("contents CAPS\n", "test_basic/CAPS"); +#else + skipping("zlib not available"); +#endif } diff --git a/contrib/libarchive/unzip/test/test_d.c b/contrib/libarchive/unzip/test/test_d.c index ea67246207f2..cd7c3dfd97ad 100644 --- a/contrib/libarchive/unzip/test/test_d.c +++ b/contrib/libarchive/unzip/test/test_d.c @@ -9,6 +9,7 @@ /* Test d arg - extract to target dir - before zipfile argument */ DEFINE_TEST(test_d_before_zipfile) { +#ifdef HAVE_LIBZ const char *reffile = "test_basic.zip"; int r; @@ -22,11 +23,15 @@ DEFINE_TEST(test_d_before_zipfile) assertTextFileContents("contents b\n", "foobar/test_basic/b"); assertTextFileContents("contents c\n", "foobar/test_basic/c"); assertTextFileContents("contents CAPS\n", "foobar/test_basic/CAPS"); +#else + skipping("zlib not available"); +#endif } /* Test d arg - extract to target dir - after zipfile argument */ DEFINE_TEST(test_d_after_zipfile) { +#ifdef HAVE_LIBZ const char *reffile = "test_basic.zip"; int r; @@ -40,4 +45,7 @@ DEFINE_TEST(test_d_after_zipfile) assertTextFileContents("contents b\n", "foobar/test_basic/b"); assertTextFileContents("contents c\n", "foobar/test_basic/c"); assertTextFileContents("contents CAPS\n", "foobar/test_basic/CAPS"); +#else + skipping("zlib not available"); +#endif } diff --git a/contrib/libarchive/unzip/test/test_doubledash.c b/contrib/libarchive/unzip/test/test_doubledash.c index 4467213dbb89..db0445ec3c24 100644 --- a/contrib/libarchive/unzip/test/test_doubledash.c +++ b/contrib/libarchive/unzip/test/test_doubledash.c @@ -9,6 +9,7 @@ /* Test double dash arg - swallow "--" and use next argument as file name */ DEFINE_TEST(test_doubledash) { +#ifdef HAVE_LIBZ const char *reffile = "test_basic.zip"; int r; @@ -22,4 +23,7 @@ DEFINE_TEST(test_doubledash) assertTextFileContents("contents b\n", "test_basic/b"); assertTextFileContents("contents c\n", "test_basic/c"); assertTextFileContents("contents CAPS\n", "test_basic/CAPS"); +#else + skipping("zlib not available"); +#endif } diff --git a/contrib/libarchive/unzip/test/test_glob.c b/contrib/libarchive/unzip/test/test_glob.c index b53aa16fd85c..589ff1c55ef3 100644 --- a/contrib/libarchive/unzip/test/test_glob.c +++ b/contrib/libarchive/unzip/test/test_glob.c @@ -9,6 +9,7 @@ /* Test that the glob works */ DEFINE_TEST(test_glob) { +#ifdef HAVE_LIBZ const char *reffile = "test_basic.zip"; int r; @@ -22,4 +23,7 @@ DEFINE_TEST(test_glob) assertTextFileContents("contents b\n", "test_basic/b"); assertFileNotExists("test_basic/c"); assertFileNotExists("test_basic/CAPS"); +#else + skipping("zlib not available"); +#endif } diff --git a/contrib/libarchive/unzip/test/test_j.c b/contrib/libarchive/unzip/test/test_j.c index b87229f42e25..1fba8ca207ec 100644 --- a/contrib/libarchive/unzip/test/test_j.c +++ b/contrib/libarchive/unzip/test/test_j.c @@ -9,6 +9,7 @@ /* Test j arg - don't make directories */ DEFINE_TEST(test_j) { +#ifdef HAVE_LIBZ const char *reffile = "test_basic.zip"; int r; @@ -22,4 +23,7 @@ DEFINE_TEST(test_j) assertTextFileContents("contents b\n", "b"); assertTextFileContents("contents c\n", "c"); assertTextFileContents("contents CAPS\n", "CAPS"); +#else + skipping("zlib not available"); +#endif } diff --git a/contrib/libarchive/unzip/test/test_n.c b/contrib/libarchive/unzip/test/test_n.c index bb75c5d7696d..a13623ce23df 100644 --- a/contrib/libarchive/unzip/test/test_n.c +++ b/contrib/libarchive/unzip/test/test_n.c @@ -9,6 +9,7 @@ /* Test n arg - don't overwrite existing files */ DEFINE_TEST(test_n) { +#ifdef HAVE_LIBZ const char *reffile = "test_basic.zip"; int r; @@ -26,4 +27,7 @@ DEFINE_TEST(test_n) assertTextFileContents("orig b\n", "test_basic/b"); assertTextFileContents("contents c\n", "test_basic/c"); assertTextFileContents("contents CAPS\n", "test_basic/CAPS"); +#else + skipping("zlib not available"); +#endif } diff --git a/contrib/libarchive/unzip/test/test_o.c b/contrib/libarchive/unzip/test/test_o.c index 64f946774440..8c48348c41a4 100644 --- a/contrib/libarchive/unzip/test/test_o.c +++ b/contrib/libarchive/unzip/test/test_o.c @@ -9,6 +9,7 @@ /* Test o arg - overwrite existing files */ DEFINE_TEST(test_o) { +#ifdef HAVE_LIBZ const char *reffile = "test_basic.zip"; int r; @@ -25,4 +26,7 @@ DEFINE_TEST(test_o) assertTextFileContents("contents b\n", "test_basic/b"); assertTextFileContents("contents c\n", "test_basic/c"); assertTextFileContents("contents CAPS\n", "test_basic/CAPS"); +#else + skipping("zlib not available"); +#endif } diff --git a/contrib/libarchive/unzip/test/test_p.c b/contrib/libarchive/unzip/test/test_p.c index 8bfffbe5dc39..13a7765463ec 100644 --- a/contrib/libarchive/unzip/test/test_p.c +++ b/contrib/libarchive/unzip/test/test_p.c @@ -9,6 +9,7 @@ /* Test p arg - Print to stdout */ DEFINE_TEST(test_p) { +#ifdef HAVE_LIBZ const char *reffile = "test_basic.zip"; int r; @@ -17,4 +18,7 @@ DEFINE_TEST(test_p) assertEqualInt(0, r); assertTextFileContents("contents a\ncontents b\ncontents c\ncontents CAPS\n", "test.out"); assertEmptyFile("test.err"); +#else + skipping("zlib not available"); +#endif } diff --git a/contrib/libarchive/unzip/test/test_q.c b/contrib/libarchive/unzip/test/test_q.c index 13222a483992..0579e8028d76 100644 --- a/contrib/libarchive/unzip/test/test_q.c +++ b/contrib/libarchive/unzip/test/test_q.c @@ -9,6 +9,7 @@ /* Test q arg - Quiet */ DEFINE_TEST(test_q) { +#ifdef HAVE_LIBZ const char *reffile = "test_basic.zip"; int r; @@ -22,4 +23,7 @@ DEFINE_TEST(test_q) assertTextFileContents("contents b\n", "test_basic/b"); assertTextFileContents("contents c\n", "test_basic/c"); assertTextFileContents("contents CAPS\n", "test_basic/CAPS"); +#else + skipping("zlib not available"); +#endif } diff --git a/contrib/libarchive/unzip/test/test_singlefile.c b/contrib/libarchive/unzip/test/test_singlefile.c index a72811f046d9..a5a35ecacc4d 100644 --- a/contrib/libarchive/unzip/test/test_singlefile.c +++ b/contrib/libarchive/unzip/test/test_singlefile.c @@ -9,6 +9,7 @@ /* Ensure single-file zips work */ DEFINE_TEST(test_singlefile) { +#ifdef HAVE_LIBZ const char *reffile = "test_singlefile.zip"; int r; @@ -19,4 +20,7 @@ DEFINE_TEST(test_singlefile) assertEmptyFile("test.err"); assertTextFileContents("hello\n", "file.txt"); +#else + skipping("zlib not available"); +#endif } diff --git a/contrib/libarchive/unzip/test/test_t.c b/contrib/libarchive/unzip/test/test_t.c index 55a516fc636f..7565830915c3 100644 --- a/contrib/libarchive/unzip/test/test_t.c +++ b/contrib/libarchive/unzip/test/test_t.c @@ -9,6 +9,7 @@ /* Test t arg - Test zip contents */ DEFINE_TEST(test_t) { +#ifdef HAVE_LIBZ const char *reffile = "test_basic.zip"; int r; @@ -17,4 +18,7 @@ DEFINE_TEST(test_t) assertEqualInt(0, r); assertNonEmptyFile("test.out"); assertEmptyFile("test.err"); +#else + skipping("zlib not available"); +#endif } diff --git a/contrib/libarchive/unzip/test/test_x.c b/contrib/libarchive/unzip/test/test_x.c index 959beb1950df..43a2085dc5b2 100644 --- a/contrib/libarchive/unzip/test/test_x.c +++ b/contrib/libarchive/unzip/test/test_x.c @@ -9,6 +9,7 @@ /* Test x arg with single exclude path */ DEFINE_TEST(test_x_single) { +#ifdef HAVE_LIBZ const char *reffile = "test_basic.zip"; int r; @@ -22,11 +23,15 @@ DEFINE_TEST(test_x_single) assertTextFileContents("contents b\n", "test_basic/b"); assertFileNotExists("test_basic/c"); assertTextFileContents("contents CAPS\n", "test_basic/CAPS"); +#else + skipping("zlib not available"); +#endif } /* Test x arg with multiple exclude paths */ DEFINE_TEST(test_x_multiple) { +#ifdef HAVE_LIBZ const char *reffile = "test_basic.zip"; int r; @@ -40,11 +45,15 @@ DEFINE_TEST(test_x_multiple) assertFileNotExists("test_basic/b"); assertFileNotExists("test_basic/c"); assertTextFileContents("contents CAPS\n", "test_basic/CAPS"); +#else + skipping("zlib not available"); +#endif } /* Test x arg with multiple exclude paths and a d arg afterwards */ DEFINE_TEST(test_x_multiple_with_d) { +#ifdef HAVE_LIBZ const char *reffile = "test_basic.zip"; int r; @@ -58,4 +67,7 @@ DEFINE_TEST(test_x_multiple_with_d) assertFileNotExists("foobar/test_basic/b"); assertFileNotExists("foobar/test_basic/c"); assertTextFileContents("contents CAPS\n", "foobar/test_basic/CAPS"); +#else + skipping("zlib not available"); +#endif } diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.h index 7d090ba682b3..7ab63905ed4f 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.h +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.h @@ -78,11 +78,6 @@ public: void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; - bool IsAArch64OutlineAtomicsDefault( - const llvm::opt::ArgList &Args) const override { - return true; - } - UnwindTableLevel getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override; bool isPIEDefault(const llvm::opt::ArgList &Args) const override; diff --git a/crypto/openssh/misc.c b/crypto/openssh/misc.c index 1b4b55c5034d..e129218cdd5c 100644 --- a/crypto/openssh/misc.c +++ b/crypto/openssh/misc.c @@ -2534,8 +2534,10 @@ format_absolute_time(uint64_t t, char *buf, size_t len) time_t tt = t > SSH_TIME_T_MAX ? SSH_TIME_T_MAX : t; struct tm tm; - localtime_r(&tt, &tm); - strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm); + if (localtime_r(&tt, &tm) == NULL) + strlcpy(buf, "UNKNOWN-TIME", len); + else + strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm); } /* diff --git a/lib/libarchive/tests/Makefile b/lib/libarchive/tests/Makefile index 07c5fe24dd30..930250d974c5 100644 --- a/lib/libarchive/tests/Makefile +++ b/lib/libarchive/tests/Makefile @@ -185,6 +185,7 @@ TESTS_SRCS= \ test_read_format_rar_overflow.c \ test_read_format_raw.c \ test_read_format_tar.c \ + test_read_format_tar_V_negative_size.c \ test_read_format_tar_concatenated.c \ test_read_format_tar_empty_filename.c \ test_read_format_tar_empty_pax.c \ @@ -607,6 +608,7 @@ ${PACKAGE}FILES+= test_read_format_rar5_decode_number_out_of_bounds_read.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_different_solid_window_size.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_different_window_size.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_different_winsize_on_merge.rar.uu +${PACKAGE}FILES+= test_read_format_rar5_dirdata.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_distance_overflow.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_encrypted.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_encrypted_filenames.rar.uu @@ -616,6 +618,7 @@ ${PACKAGE}FILES+= test_read_format_rar5_extra_field_version.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_fileattr.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_hardlink.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_invalid_dict_reference.rar.uu +${PACKAGE}FILES+= test_read_format_rar5_invalid_hash_valid_htime_exfld.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_leftshift1.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_leftshift2.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_multiarchive.part01.rar.uu @@ -633,6 +636,7 @@ ${PACKAGE}FILES+= test_read_format_rar5_multiarchive_solid.part04.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_multiple_files.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_multiple_files_solid.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_nonempty_dir_stream.rar.uu +${PACKAGE}FILES+= test_read_format_rar5_only_crypt_exfld.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_owner.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_readtables_overflow.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_sfx.exe.uu @@ -642,12 +646,14 @@ ${PACKAGE}FILES+= test_read_format_rar5_stored_manyfiles.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_symlink.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_truncated_huff.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_unicode.rar.uu +${PACKAGE}FILES+= test_read_format_rar5_unsupported_exfld.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_win32.rar.uu ${PACKAGE}FILES+= test_read_format_rar5_window_buf_and_size_desync.rar.uu ${PACKAGE}FILES+= test_read_format_raw.bufr.uu ${PACKAGE}FILES+= test_read_format_raw.data.Z.uu ${PACKAGE}FILES+= test_read_format_raw.data.gz.uu ${PACKAGE}FILES+= test_read_format_raw.data.uu +${PACKAGE}FILES+= test_read_format_tar_V_negative_size.tar.uu ${PACKAGE}FILES+= test_read_format_tar_concatenated.tar.uu ${PACKAGE}FILES+= test_read_format_tar_empty_filename.tar.uu ${PACKAGE}FILES+= test_read_format_tar_empty_with_gnulabel.tar.uu diff --git a/lib/libc/gen/getvfsbyname.3 b/lib/libc/gen/getvfsbyname.3 index 9365d043a1fc..19fa12419353 100644 --- a/lib/libc/gen/getvfsbyname.3 +++ b/lib/libc/gen/getvfsbyname.3 @@ -27,7 +27,7 @@ .\" .\" @(#)kvm_getvfsbyname.3 8.3 (Berkeley) 5/4/95 .\" -.Dd August 16, 2018 +.Dd October 28, 2025 .Dt GETVFSBYNAME 3 .Os .Sh NAME @@ -104,6 +104,7 @@ argument specifies a file system that is unknown or not configured in the kernel. .El .Sh SEE ALSO +.Xr lsvfs 1 , .Xr jail 2 , .Xr mount 2 , .Xr sysctl 3 , diff --git a/lib/libc/sys/revoke.2 b/lib/libc/sys/revoke.2 index dc92512d3129..db0c8a85558b 100644 --- a/lib/libc/sys/revoke.2 +++ b/lib/libc/sys/revoke.2 @@ -30,7 +30,7 @@ .\" .\" @(#)revoke.2 8.1 (Berkeley) 6/4/93 .\" -.Dd January 25, 2016 +.Dd October 24, 2025 .Dt REVOKE 2 .Os .Sh NAME @@ -64,7 +64,7 @@ using a special close method which does not block. Access to a file may be revoked only by its owner or the super user. The .Fn revoke -system call is currently supported only for block and character special +system call is currently supported only for character special device files. It is normally used to prepare a terminal device for a new login session, preventing any access by a previous user of the terminal. diff --git a/lib/libc/sys/write.2 b/lib/libc/sys/write.2 index adf60aa91d7a..2f0a9d034038 100644 --- a/lib/libc/sys/write.2 +++ b/lib/libc/sys/write.2 @@ -134,6 +134,26 @@ and may write fewer bytes than requested; the return value must be noted, and the remainder of the operation should be retried when possible. +.Sh ATOMICITY OF WRITES +When operating on regular files on local file systems, the effects of +.Fn write +are atomic. +As required by the POSIX standard, +the +.Fn read , +.Fn write , +and +.Fn ftruncate +functions and their variations are atomic with respect to +each other on the file data and metadata for regular files. +See for instance +.St -p1003.1-2024 +Volume 2, Section 2.9.7 for more information. +.Pp +.Fx +implements the requirement by taking +a read/write range lock on the file byte range +affected by the corresponding function. .Sh RETURN VALUES Upon successful completion the number of bytes which were written is returned. diff --git a/sbin/mksnap_ffs/mksnap_ffs.c b/sbin/mksnap_ffs/mksnap_ffs.c index 0d8e32a15ab3..58939cc69029 100644 --- a/sbin/mksnap_ffs/mksnap_ffs.c +++ b/sbin/mksnap_ffs/mksnap_ffs.c @@ -150,7 +150,7 @@ main(int argc, char **argv) errx(1, "%s: Not a mount point", stfsbuf.f_mntonname); } if (cp != stfsbuf.f_mntonname) - strlcpy(stfsbuf.f_mntonname, cp, sizeof(stfsbuf.f_mntonname)); + memmove(stfsbuf.f_mntonname, cp, strlen(cp) + 1); /* * Having verified access to the directory in which the diff --git a/sbin/mount/mount.8 b/sbin/mount/mount.8 index 0adc5ffc228b..1e5440fbc846 100644 --- a/sbin/mount/mount.8 +++ b/sbin/mount/mount.8 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd November 19, 2024 +.Dd October 28, 2025 .Dt MOUNT 8 .Os .Sh NAME @@ -563,6 +563,7 @@ support for a particular file system might be provided either on a static .Xr kldload 8 ) . .Sh SEE ALSO .Xr getfacl 1 , +.Xr lsvfs 1 , .Xr setfacl 1 , .Xr nmount 2 , .Xr acl 3 , diff --git a/share/man/man4/acpi_battery.4 b/share/man/man4/acpi_battery.4 index 3707cd125678..49fed625ea31 100644 --- a/share/man/man4/acpi_battery.4 +++ b/share/man/man4/acpi_battery.4 @@ -158,8 +158,8 @@ Typically this will decrease every charging cycle. .It btech Battery technology: .Bl -tag -width indent -.It 0x00000000 Primary cell Pq non-rechargable -.It 0x00000001 Secondary cell Pq rechargable +.It 0x00000000 Primary cell Pq non-rechargeable +.It 0x00000001 Secondary cell Pq rechargeable .El .It Va dvol Design voltage in mV, diff --git a/share/man/man4/rights.4 b/share/man/man4/rights.4 index 2d44a1060006..6669f75e1674 100644 --- a/share/man/man4/rights.4 +++ b/share/man/man4/rights.4 @@ -276,7 +276,8 @@ Permit and .Xr openat 2 with -.Dv O_FSYNC +.Dv O_DSYNC , +.Dv O_FSYNC , or .Dv O_SYNC flag. diff --git a/share/man/man7/stats.7 b/share/man/man7/stats.7 index 715db70e118b..0b57d525522c 100644 --- a/share/man/man7/stats.7 +++ b/share/man/man7/stats.7 @@ -24,7 +24,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 22, 2021 +.Dd October 28, 2025 .Dt STATS 7 .Os .Sh NAME @@ -100,6 +100,7 @@ Report ZFS I/O statistics .Xr stat 1 , .Xr systat 1 , .Xr intro 7 , +.Xr tuning 7 , .Xr ctlstat 8 , .Xr gstat 8 , .Xr ibstat 8 , diff --git a/share/man/man7/tuning.7 b/share/man/man7/tuning.7 index f04500d0f0dc..8da4b55b9d4f 100644 --- a/share/man/man7/tuning.7 +++ b/share/man/man7/tuning.7 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd November 17, 2023 +.Dd October 28, 2025 .Dt TUNING 7 .Os .Sh NAME @@ -702,6 +702,7 @@ over services you export from your box (web services, email). .Xr firewall 7 , .Xr hier 7 , .Xr ports 7 , +.Xr stats 7 , .Xr boot 8 , .Xr bsdinstall 8 , .Xr ccdconfig 8 , diff --git a/share/man/man9/insmntque.9 b/share/man/man9/insmntque.9 index 869d8767632b..33ba697b10b9 100644 --- a/share/man/man9/insmntque.9 +++ b/share/man/man9/insmntque.9 @@ -24,7 +24,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH .\" DAMAGE. .\" -.Dd January 29, 2022 +.Dd October 24, 2025 .Dt INSMNTQUE 9 .Os .Sh NAME @@ -56,7 +56,7 @@ The vnode must be exclusively locked. .Pp On failure, .Fn insmntque -resets vnode' operation vector to the vector of +resets vnode's operations vector to the vector of .Xr deadfs 9 , clears .Va v_data , @@ -71,7 +71,7 @@ failure is needed, the function may be used instead. It does not do any cleanup following a failure, leaving all the work to the caller. -In particular, the operation vector +In particular, the operations vector .Va v_op and .Va v_data diff --git a/share/misc/bsd-family-tree b/share/misc/bsd-family-tree index 94455bbde628..d36c64259569 100644 --- a/share/misc/bsd-family-tree +++ b/share/misc/bsd-family-tree @@ -479,9 +479,9 @@ FreeBSD 5.2 | | | | | | | | | DragonFly 6.4.1 | | | | | DragonFly 6.4.2 | FreeBSD | | | | - | 14.3 | | | | + | 14.3 | | OpenBSD 7.8 | | | | | | -FreeBSD 15 -current | NetBSD -current OpenBSD -current DragonFly -current +FreeBSD 16 -current | NetBSD -current OpenBSD -current DragonFly -current | | | | | v v v v v @@ -926,6 +926,7 @@ OpenBSD 7.7 2025-04-28 [OBD] DragonFly 6.4.1 2025-04-30 [DFB] DragonFly 6.4.2 2025-05-09 [DFB] FreeBSD 14.3 2025-06-10 [FBD] +OpenBSD 7.8 2025-10-22 [OBD] Bibliography ------------------------ @@ -981,6 +982,15 @@ URL: https://web.archive.org/web/20090427195917/http://ezine.daemonnews.org/2001 ("what are the differences between FreeBSD, NetBSD, and OpenBSD?") +End-of-Life (EOL) +----------------- +The FreeBSD family tree shows when a release was published. +If you would like to know when the support ends, just look at +https://www.freebsd.org/security/#sup and +https://www.freebsd.org/security/unsupported +For other operating systems, see https://endoflife.date + + Acknowledgments --------------- @@ -990,5 +1000,5 @@ original BSD announcements from Usenet or tapes. Steven M. Schultz for providing 2.8BSD, 2.10BSD, 2.11BSD manual pages. -- -Copyright (c) 1997-2024 Wolfram Schneider <wosch@FreeBSD.org> +Copyright (c) 1997-2025 Wolfram Schneider <wosch@FreeBSD.org> URL: https://cgit.freebsd.org/src/tree/share/misc/bsd-family-tree diff --git a/share/mk/bsd.prog.mk b/share/mk/bsd.prog.mk index fa15370a82c6..1c32a442aac9 100644 --- a/share/mk/bsd.prog.mk +++ b/share/mk/bsd.prog.mk @@ -49,9 +49,11 @@ CXXFLAGS+= -mretpoline LDFLAGS+= -Wl,-zretpolineplt .endif .else +.if !defined(_NO_INCLUDE_COMPILERMK) .warning Retpoline requested but not supported by compiler or linker .endif .endif +.endif # LLD sensibly defaults to -znoexecstack, so do the same for BFD LDFLAGS.bfd+= -Wl,-znoexecstack @@ -65,16 +67,20 @@ CFLAGS+= -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clan CXXFLAGS+= -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang .endif .else +.if !defined(_NO_INCLUDE_COMPILERMK) .warning InitAll (zeros) requested but not supported by compiler .endif +.endif .elif ${MK_INIT_ALL_PATTERN} == "yes" .if ${COMPILER_FEATURES:Minit-all} CFLAGS+= -ftrivial-auto-var-init=pattern CXXFLAGS+= -ftrivial-auto-var-init=pattern .else +.if !defined(_NO_INCLUDE_COMPILERMK) .warning InitAll (pattern) requested but not supported by compiler .endif .endif +.endif # bsd.sanitizer.mk is not installed, so don't require it (e.g. for ports). .sinclude "bsd.sanitizer.mk" diff --git a/sys/cddl/dev/fbt/aarch64/fbt_isa.c b/sys/cddl/dev/fbt/aarch64/fbt_isa.c index fd666770d3a2..b265f6a1e23e 100644 --- a/sys/cddl/dev/fbt/aarch64/fbt_isa.c +++ b/sys/cddl/dev/fbt/aarch64/fbt_isa.c @@ -105,7 +105,7 @@ fbt_provide_module_function(linker_file_t lf, int symindx, */ if (strcmp(name, "handle_el1h_sync") == 0 || strcmp(name, "do_el1h_sync") == 0) - return (1); + return (0); instr = (uint32_t *)(symval->value); limit = (uint32_t *)(symval->value + symval->size); diff --git a/sys/dev/e1000/e1000_osdep.h b/sys/dev/e1000/e1000_osdep.h index 893979025f01..ba1c8a16fad1 100644 --- a/sys/dev/e1000/e1000_osdep.h +++ b/sys/dev/e1000/e1000_osdep.h @@ -152,6 +152,9 @@ struct e1000_osdep { bus_space_tag_t mem_bus_space_tag; bus_space_handle_t mem_bus_space_handle; +#ifdef INVARIANTS + bus_size_t mem_bus_space_size; +#endif bus_space_tag_t io_bus_space_tag; bus_space_handle_t io_bus_space_handle; bus_space_tag_t flash_bus_space_tag; @@ -175,27 +178,44 @@ struct e1000_osdep bus_space_write_4(((struct e1000_osdep *)(hw)->back)->mem_bus_space_tag, \ ((struct e1000_osdep *)(hw)->back)->mem_bus_space_handle, offset, value) +static __inline uint32_t +e1000_rd32(struct e1000_osdep *osdep, uint32_t reg) +{ + + KASSERT(reg < osdep->mem_bus_space_size, + ("e1000: register offset %#jx too large (max is %#jx)", + (uintmax_t)reg, (uintmax_t)osdep->mem_bus_space_size)); + + return (bus_space_read_4(osdep->mem_bus_space_tag, + osdep->mem_bus_space_handle, reg)); +} + + +static __inline void +e1000_wr32(struct e1000_osdep *osdep, uint32_t reg, uint32_t value) +{ + + KASSERT(reg < osdep->mem_bus_space_size, + ("e1000: register offset %#jx too large (max is %#jx)", + (uintmax_t)reg, (uintmax_t)osdep->mem_bus_space_size)); + + bus_space_write_4(osdep->mem_bus_space_tag, + osdep->mem_bus_space_handle, reg, value); +} + /* Register READ/WRITE macros */ -#define E1000_READ_REG(hw, reg) \ - bus_space_read_4(((struct e1000_osdep *)(hw)->back)->mem_bus_space_tag, \ - ((struct e1000_osdep *)(hw)->back)->mem_bus_space_handle, \ - E1000_REGISTER(hw, reg)) +#define E1000_READ_REG(hw, reg) \ + e1000_rd32((hw)->back, E1000_REGISTER(hw, reg)) #define E1000_WRITE_REG(hw, reg, value) \ - bus_space_write_4(((struct e1000_osdep *)(hw)->back)->mem_bus_space_tag, \ - ((struct e1000_osdep *)(hw)->back)->mem_bus_space_handle, \ - E1000_REGISTER(hw, reg), value) + e1000_wr32((hw)->back, E1000_REGISTER(hw, reg), value) #define E1000_READ_REG_ARRAY(hw, reg, index) \ - bus_space_read_4(((struct e1000_osdep *)(hw)->back)->mem_bus_space_tag, \ - ((struct e1000_osdep *)(hw)->back)->mem_bus_space_handle, \ - E1000_REGISTER(hw, reg) + ((index)<< 2)) + e1000_rd32((hw)->back, E1000_REGISTER(hw, reg) + ((index) << 2)) #define E1000_WRITE_REG_ARRAY(hw, reg, index, value) \ - bus_space_write_4(((struct e1000_osdep *)(hw)->back)->mem_bus_space_tag, \ - ((struct e1000_osdep *)(hw)->back)->mem_bus_space_handle, \ - E1000_REGISTER(hw, reg) + ((index)<< 2), value) + e1000_wr32((hw)->back, E1000_REGISTER(hw, reg) + ((index) << 2), value) #define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY #define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index f0ef6051fab1..9040949b36c7 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -1575,7 +1575,7 @@ em_if_init(if_ctx_t ctx) E1000_WRITE_REG(&sc->hw, E1000_VET, ETHERTYPE_VLAN); /* Clear bad data from Rx FIFOs */ - if (sc->hw.mac.type >= igb_mac_min) + if (sc->hw.mac.type >= igb_mac_min && !sc->vf_ifp) e1000_rx_fifo_flush_base(&sc->hw); /* Configure for OS presence */ @@ -1595,7 +1595,9 @@ em_if_init(if_ctx_t ctx) /* Don't lose promiscuous settings */ em_if_set_promisc(ctx, if_getflags(ifp)); - e1000_clear_hw_cntrs_base_generic(&sc->hw); + + if (sc->hw.mac.ops.clear_hw_cntrs != NULL) + sc->hw.mac.ops.clear_hw_cntrs(&sc->hw); /* MSI-X configuration for 82574 */ if (sc->hw.mac.type == e1000_82574) { @@ -2374,7 +2376,7 @@ em_if_stop(if_ctx_t ctx) em_flush_desc_rings(sc); e1000_reset_hw(&sc->hw); - if (sc->hw.mac.type >= e1000_82544) + if (sc->hw.mac.type >= e1000_82544 && !sc->vf_ifp) E1000_WRITE_REG(&sc->hw, E1000_WUFC, 0); e1000_led_off(&sc->hw); @@ -2433,6 +2435,9 @@ em_allocate_pci_resources(if_ctx_t ctx) } sc->osdep.mem_bus_space_tag = rman_get_bustag(sc->memory); sc->osdep.mem_bus_space_handle = rman_get_bushandle(sc->memory); +#ifdef INVARIANTS + sc->osdep.mem_bus_space_size = rman_get_size(sc->memory); +#endif sc->hw.hw_addr = (u8 *)&sc->osdep.mem_bus_space_handle; /* Only older adapters use IO mapping */ @@ -3284,11 +3289,13 @@ em_reset(if_ctx_t ctx) /* Issue a global reset */ e1000_reset_hw(hw); - if (hw->mac.type >= igb_mac_min) { - E1000_WRITE_REG(hw, E1000_WUC, 0); - } else { - E1000_WRITE_REG(hw, E1000_WUFC, 0); - em_disable_aspm(sc); + if (!sc->vf_ifp) { + if (hw->mac.type >= igb_mac_min) { + E1000_WRITE_REG(hw, E1000_WUC, 0); + } else { + E1000_WRITE_REG(hw, E1000_WUFC, 0); + em_disable_aspm(sc); + } } if (sc->flags & IGB_MEDIA_RESET) { e1000_setup_init_funcs(hw, true); @@ -3838,7 +3845,7 @@ em_initialize_receive_unit(if_ctx_t ctx) sc->rx_int_delay.value); } - if (hw->mac.type >= em_mac_min) { + if (hw->mac.type >= em_mac_min && !sc->vf_ifp) { uint32_t rfctl; /* Use extended rx descriptor formats */ rfctl = E1000_READ_REG(hw, E1000_RFCTL); @@ -3858,33 +3865,38 @@ em_initialize_receive_unit(if_ctx_t ctx) E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); } - /* Set up L3 and L4 csum Rx descriptor offloads */ - rxcsum = E1000_READ_REG(hw, E1000_RXCSUM); - if (if_getcapenable(ifp) & IFCAP_RXCSUM) { - rxcsum |= E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPOFL; - if (hw->mac.type > e1000_82575) - rxcsum |= E1000_RXCSUM_CRCOFL; - else if (hw->mac.type < em_mac_min && - if_getcapenable(ifp) & IFCAP_HWCSUM_IPV6) - rxcsum |= E1000_RXCSUM_IPV6OFL; - } else { - rxcsum &= ~(E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL); - if (hw->mac.type > e1000_82575) - rxcsum &= ~E1000_RXCSUM_CRCOFL; - else if (hw->mac.type < em_mac_min) - rxcsum &= ~E1000_RXCSUM_IPV6OFL; - } + /* + * Set up L3 and L4 csum Rx descriptor offloads only on Physical + * Functions. Virtual Functions have no access to this register. + */ + if (!sc->vf_ifp) { + rxcsum = E1000_READ_REG(hw, E1000_RXCSUM); + if (if_getcapenable(ifp) & IFCAP_RXCSUM) { + rxcsum |= E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPOFL; + if (hw->mac.type > e1000_82575) + rxcsum |= E1000_RXCSUM_CRCOFL; + else if (hw->mac.type < em_mac_min && + if_getcapenable(ifp) & IFCAP_HWCSUM_IPV6) + rxcsum |= E1000_RXCSUM_IPV6OFL; + } else { + rxcsum &= ~(E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL); + if (hw->mac.type > e1000_82575) + rxcsum &= ~E1000_RXCSUM_CRCOFL; + else if (hw->mac.type < em_mac_min) + rxcsum &= ~E1000_RXCSUM_IPV6OFL; + } - if (sc->rx_num_queues > 1) { - /* RSS hash needed in the Rx descriptor */ - rxcsum |= E1000_RXCSUM_PCSD; + if (sc->rx_num_queues > 1) { + /* RSS hash needed in the Rx descriptor */ + rxcsum |= E1000_RXCSUM_PCSD; - if (hw->mac.type >= igb_mac_min) - igb_initialize_rss_mapping(sc); - else - em_initialize_rss_mapping(sc); + if (hw->mac.type >= igb_mac_min) + igb_initialize_rss_mapping(sc); + else + em_initialize_rss_mapping(sc); + } + E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum); } - E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum); for (i = 0, que = sc->rx_queues; i < sc->rx_num_queues; i++, que++) { struct rx_ring *rxr = &que->rxr; @@ -4392,6 +4404,8 @@ em_get_wakeup(if_ctx_t ctx) switch (sc->hw.mac.type) { case e1000_82542: case e1000_82543: + case e1000_vfadapt: + case e1000_vfadapt_i350: break; case e1000_82544: e1000_read_nvm(&sc->hw, @@ -4437,8 +4451,6 @@ em_get_wakeup(if_ctx_t ctx) case e1000_i354: case e1000_i210: case e1000_i211: - case e1000_vfadapt: - case e1000_vfadapt_i350: apme_mask = E1000_WUC_APME; sc->has_amt = true; eeprom_data = E1000_READ_REG(&sc->hw, E1000_WUC); @@ -4494,7 +4506,6 @@ em_get_wakeup(if_ctx_t ctx) global_quad_port_a = 0; break; } - return; } diff --git a/sys/dev/ice/ice_drv_info.h b/sys/dev/ice/ice_drv_info.h index 46965f4124bc..abb11bdb5fd9 100644 --- a/sys/dev/ice/ice_drv_info.h +++ b/sys/dev/ice/ice_drv_info.h @@ -238,6 +238,9 @@ static const pci_vendor_info_t ice_vendor_info_array[] = { ICE_INTEL_VENDOR_ID, 0x0001, 0, "Intel(R) Ethernet Network Adapter E835-XXV-2 for OCP 3.0"), PVIDV_OEM(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E835CC_SFP, + ICE_INTEL_VENDOR_ID, 0x0002, 0, + "Intel(R) Ethernet Network Adapter E835-XXV-4"), + PVIDV_OEM(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E835CC_SFP, ICE_INTEL_VENDOR_ID, 0x0003, 0, "Intel(R) Ethernet Network Adapter E835-XXV-2"), PVIDV_OEM(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E835CC_SFP, diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c index 43c3af056b67..aa2e69ea0b5a 100644 --- a/sys/dev/ixl/if_ixl.c +++ b/sys/dev/ixl/if_ixl.c @@ -1480,17 +1480,33 @@ ixl_if_multi_set(if_ctx_t ctx) struct ixl_pf *pf = iflib_get_softc(ctx); struct ixl_vsi *vsi = &pf->vsi; struct i40e_hw *hw = vsi->hw; + enum i40e_status_code status; int mcnt; + if_t ifp = iflib_get_ifp(ctx); IOCTL_DEBUGOUT("ixl_if_multi_set: begin"); /* Delete filters for removed multicast addresses */ ixl_del_multi(vsi, false); - mcnt = min(if_llmaddr_count(iflib_get_ifp(ctx)), MAX_MULTICAST_ADDR); + mcnt = min(if_llmaddr_count(ifp), MAX_MULTICAST_ADDR); if (__predict_false(mcnt == MAX_MULTICAST_ADDR)) { - i40e_aq_set_vsi_multicast_promiscuous(hw, + /* Check if promisc mode is already enabled, if yes return */ + if (vsi->flags & IXL_FLAGS_MC_PROMISC) + return; + + status = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid, TRUE, NULL); + if (status != I40E_SUCCESS) + if_printf(ifp, "Failed to enable multicast promiscuous " + "mode, status: %s\n", i40e_stat_str(hw, status)); + else { + if_printf(ifp, "Enabled multicast promiscuous mode\n"); + + /* Set the flag to track promiscuous mode */ + vsi->flags |= IXL_FLAGS_MC_PROMISC; + } + /* Delete all existing MC filters */ ixl_del_multi(vsi, true); return; } @@ -1693,6 +1709,13 @@ ixl_if_promisc_set(if_ctx_t ctx, int flags) return (err); err = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid, multi, NULL); + + /* Update the multicast promiscuous flag based on the new state */ + if (multi) + vsi->flags |= IXL_FLAGS_MC_PROMISC; + else + vsi->flags &= ~IXL_FLAGS_MC_PROMISC; + return (err); } diff --git a/sys/dev/ixl/ixl.h b/sys/dev/ixl/ixl.h index f45354d29300..69925a131b35 100644 --- a/sys/dev/ixl/ixl.h +++ b/sys/dev/ixl/ixl.h @@ -202,6 +202,7 @@ #define IXL_FLAGS_KEEP_TSO6 (1 << 1) #define IXL_FLAGS_USES_MSIX (1 << 2) #define IXL_FLAGS_IS_VF (1 << 3) +#define IXL_FLAGS_MC_PROMISC (1 << 4) #define IXL_VSI_IS_PF(v) ((v->flags & IXL_FLAGS_IS_VF) == 0) #define IXL_VSI_IS_VF(v) ((v->flags & IXL_FLAGS_IS_VF) != 0) diff --git a/sys/dev/ixl/ixl_pf_main.c b/sys/dev/ixl/ixl_pf_main.c index 4f384e7191af..99851af61cfe 100644 --- a/sys/dev/ixl/ixl_pf_main.c +++ b/sys/dev/ixl/ixl_pf_main.c @@ -592,24 +592,29 @@ ixl_add_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) * Routines for multicast and vlan filter management. * *********************************************************************/ + +/** + * ixl_add_multi - Add multicast filters to the hardware + * @vsi: The VSI structure + * + * In case number of multicast filters in the IFP exceeds 127 entries, + * multicast promiscuous mode will be enabled and the filters will be removed + * from the hardware + */ void ixl_add_multi(struct ixl_vsi *vsi) { if_t ifp = vsi->ifp; - struct i40e_hw *hw = vsi->hw; int mcnt = 0; struct ixl_add_maddr_arg cb_arg; IOCTL_DEBUGOUT("ixl_add_multi: begin"); - mcnt = if_llmaddr_count(ifp); - if (__predict_false(mcnt >= MAX_MULTICAST_ADDR)) { - i40e_aq_set_vsi_multicast_promiscuous(hw, - vsi->seid, TRUE, NULL); - /* delete all existing MC filters */ - ixl_del_multi(vsi, true); - return; - } + /* + * There is no need to check if the number of multicast addresses + * exceeds the MAX_MULTICAST_ADDR threshold and set promiscuous mode + * here, as all callers already handle this case. + */ cb_arg.vsi = vsi; LIST_INIT(&cb_arg.to_add); @@ -632,30 +637,103 @@ ixl_match_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) return (0); } +/** + * ixl_dis_multi_promisc - Disable multicast promiscuous mode + * @vsi: The VSI structure + * @vsi_mcnt: Number of multicast filters in the VSI + * + * Disable multicast promiscuous mode based on number of entries in the IFP + * and the VSI, then re-add multicast filters. + * + */ +static void +ixl_dis_multi_promisc(struct ixl_vsi *vsi, int vsi_mcnt) +{ + struct ifnet *ifp = vsi->ifp; + struct i40e_hw *hw = vsi->hw; + int ifp_mcnt = 0; + enum i40e_status_code status; + + /* + * Check if multicast promiscuous mode was actually enabled. + * If promiscuous mode was not enabled, don't attempt to disable it. + * Also, don't disable if IFF_PROMISC or IFF_ALLMULTI is set. + */ + if (!(vsi->flags & IXL_FLAGS_MC_PROMISC) || + (if_getflags(ifp) & (IFF_PROMISC | IFF_ALLMULTI))) + return; + + ifp_mcnt = if_llmaddr_count(ifp); + /* + * Equal lists or empty ifp list mean the list has not been changed + * and in such case avoid disabling multicast promiscuous mode as it + * was not previously enabled. Case where multicast promiscuous mode has + * been enabled is when vsi_mcnt == 0 && ifp_mcnt > 0. + */ + if (ifp_mcnt == vsi_mcnt || ifp_mcnt == 0 || + ifp_mcnt >= MAX_MULTICAST_ADDR) + return; + + status = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid, + FALSE, NULL); + if (status != I40E_SUCCESS) { + if_printf(ifp, "Failed to disable multicast promiscuous " + "mode, status: %s\n", i40e_stat_str(hw, status)); + + return; + } + + /* Clear the flag since promiscuous mode is now disabled */ + vsi->flags &= ~IXL_FLAGS_MC_PROMISC; + if_printf(ifp, "Disabled multicast promiscuous mode\n"); + + ixl_add_multi(vsi); +} + +/** + * ixl_del_multi - Delete multicast filters from the hardware + * @vsi: The VSI structure + * @all: Bool to determine if all the multicast filters should be removed + * + * In case number of multicast filters in the IFP drops to 127 entries, + * multicast promiscuous mode will be disabled and the filters will be reapplied + * to the hardware. + */ void ixl_del_multi(struct ixl_vsi *vsi, bool all) { - struct ixl_ftl_head to_del; + int to_del_cnt = 0, vsi_mcnt = 0; if_t ifp = vsi->ifp; struct ixl_mac_filter *f, *fn; - int mcnt = 0; + struct ixl_ftl_head to_del; IOCTL_DEBUGOUT("ixl_del_multi: begin"); LIST_INIT(&to_del); /* Search for removed multicast addresses */ LIST_FOREACH_SAFE(f, &vsi->ftl, ftle, fn) { - if ((f->flags & IXL_FILTER_MC) == 0 || - (!all && (if_foreach_llmaddr(ifp, ixl_match_maddr, f) == 0))) + if ((f->flags & IXL_FILTER_MC) == 0) + continue; + + /* Count all the multicast filters in the VSI for comparison */ + vsi_mcnt++; + + if (!all && if_foreach_llmaddr(ifp, ixl_match_maddr, f) != 0) continue; LIST_REMOVE(f, ftle); LIST_INSERT_HEAD(&to_del, f, ftle); - mcnt++; + to_del_cnt++; } - if (mcnt > 0) - ixl_del_hw_filters(vsi, &to_del, mcnt); + if (to_del_cnt > 0) { + ixl_del_hw_filters(vsi, &to_del, to_del_cnt); + return; + } + + ixl_dis_multi_promisc(vsi, vsi_mcnt); + + IOCTL_DEBUGOUT("ixl_del_multi: end"); } void diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c index 6f5d6ae74add..ce203e2869fd 100644 --- a/sys/dev/nvme/nvme_ctrlr.c +++ b/sys/dev/nvme/nvme_ctrlr.c @@ -1584,9 +1584,14 @@ noadminq: bus_release_resource(ctrlr->dev, SYS_RES_IRQ, rman_get_rid(ctrlr->res), ctrlr->res); - if (ctrlr->bar4_resource != NULL) { + if (ctrlr->msix_table_resource != NULL) { bus_release_resource(dev, SYS_RES_MEMORY, - ctrlr->bar4_resource_id, ctrlr->bar4_resource); + ctrlr->msix_table_resource_id, ctrlr->msix_table_resource); + } + + if (ctrlr->msix_pba_resource != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, + ctrlr->msix_pba_resource_id, ctrlr->msix_pba_resource); } bus_release_resource(dev, SYS_RES_MEMORY, diff --git a/sys/dev/nvme/nvme_pci.c b/sys/dev/nvme/nvme_pci.c index a78327ba0e8b..9c40c3d9f5c7 100644 --- a/sys/dev/nvme/nvme_pci.c +++ b/sys/dev/nvme/nvme_pci.c @@ -154,11 +154,15 @@ nvme_ctrlr_allocate_bar(struct nvme_controller *ctrlr) { ctrlr->resource_id = PCIR_BAR(0); + ctrlr->msix_table_resource_id = -1; + ctrlr->msix_table_resource = NULL; + ctrlr->msix_pba_resource_id = -1; + ctrlr->msix_pba_resource = NULL; ctrlr->resource = bus_alloc_resource_any(ctrlr->dev, SYS_RES_MEMORY, &ctrlr->resource_id, RF_ACTIVE); - if(ctrlr->resource == NULL) { + if (ctrlr->resource == NULL) { nvme_printf(ctrlr, "unable to allocate pci resource\n"); return (ENOMEM); } @@ -168,15 +172,32 @@ nvme_ctrlr_allocate_bar(struct nvme_controller *ctrlr) ctrlr->regs = (struct nvme_registers *)ctrlr->bus_handle; /* - * The NVMe spec allows for the MSI-X table to be placed behind - * BAR 4/5, separate from the control/doorbell registers. Always - * try to map this bar, because it must be mapped prior to calling - * pci_alloc_msix(). If the table isn't behind BAR 4/5, - * bus_alloc_resource() will just return NULL which is OK. + * The NVMe spec allows for the MSI-X tables to be placed behind + * BAR 4 and/or 5, separate from the control/doorbell registers. */ - ctrlr->bar4_resource_id = PCIR_BAR(4); - ctrlr->bar4_resource = bus_alloc_resource_any(ctrlr->dev, SYS_RES_MEMORY, - &ctrlr->bar4_resource_id, RF_ACTIVE); + + ctrlr->msix_table_resource_id = pci_msix_table_bar(ctrlr->dev); + ctrlr->msix_pba_resource_id = pci_msix_pba_bar(ctrlr->dev); + + if (ctrlr->msix_table_resource_id >= 0 && + ctrlr->msix_table_resource_id != ctrlr->resource_id) { + ctrlr->msix_table_resource = bus_alloc_resource_any(ctrlr->dev, + SYS_RES_MEMORY, &ctrlr->msix_table_resource_id, RF_ACTIVE); + if (ctrlr->msix_table_resource == NULL) { + nvme_printf(ctrlr, "unable to allocate msi-x table resource\n"); + return (ENOMEM); + } + } + if (ctrlr->msix_pba_resource_id >= 0 && + ctrlr->msix_pba_resource_id != ctrlr->resource_id && + ctrlr->msix_pba_resource_id != ctrlr->msix_table_resource_id) { + ctrlr->msix_pba_resource = bus_alloc_resource_any(ctrlr->dev, + SYS_RES_MEMORY, &ctrlr->msix_pba_resource_id, RF_ACTIVE); + if (ctrlr->msix_pba_resource == NULL) { + nvme_printf(ctrlr, "unable to allocate msi-x pba resource\n"); + return (ENOMEM); + } + } return (0); } @@ -202,9 +223,14 @@ bad: ctrlr->resource_id, ctrlr->resource); } - if (ctrlr->bar4_resource != NULL) { + if (ctrlr->msix_table_resource != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, + ctrlr->msix_table_resource_id, ctrlr->msix_table_resource); + } + + if (ctrlr->msix_pba_resource != NULL) { bus_release_resource(dev, SYS_RES_MEMORY, - ctrlr->bar4_resource_id, ctrlr->bar4_resource); + ctrlr->msix_pba_resource_id, ctrlr->msix_pba_resource); } if (ctrlr->tag) diff --git a/sys/dev/nvme/nvme_private.h b/sys/dev/nvme/nvme_private.h index 36e04ceb7f31..93833672674a 100644 --- a/sys/dev/nvme/nvme_private.h +++ b/sys/dev/nvme/nvme_private.h @@ -233,8 +233,10 @@ struct nvme_controller { * separate from the control registers which are in BAR 0/1. These * members track the mapping of BAR 4/5 for that reason. */ - int bar4_resource_id; - struct resource *bar4_resource; + int msix_table_resource_id; + struct resource *msix_table_resource; + int msix_pba_resource_id; + struct resource *msix_pba_resource; int msi_count; uint32_t enable_aborts; diff --git a/sys/geom/zero/g_zero.c b/sys/geom/zero/g_zero.c index 66cc884fab56..be31cc794cb5 100644 --- a/sys/geom/zero/g_zero.c +++ b/sys/geom/zero/g_zero.c @@ -47,11 +47,11 @@ static SYSCTL_NODE(_kern_geom, OID_AUTO, zero, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, "GEOM_ZERO stuff"); static int g_zero_clear = 1; SYSCTL_PROC(_kern_geom_zero, OID_AUTO, clear, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, &g_zero_clear, 0, + CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, &g_zero_clear, 0, g_zero_clear_sysctl, "I", "Clear read data buffer"); static int g_zero_byte = 0; -SYSCTL_INT(_kern_geom_zero, OID_AUTO, byte, CTLFLAG_RW, &g_zero_byte, 0, +SYSCTL_INT(_kern_geom_zero, OID_AUTO, byte, CTLFLAG_RWTUN, &g_zero_byte, 0, "Byte (octet) value to clear the buffers with"); static struct g_provider *gpp; diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 9c5c5b9dfa80..99f9e129f4cd 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1074,7 +1074,7 @@ flags_to_rights(int flags, cap_rights_t *rightsp) if (flags & O_TRUNC) cap_rights_set_one(rightsp, CAP_FTRUNCATE); - if (flags & (O_SYNC | O_FSYNC)) + if (flags & (O_SYNC | O_FSYNC | O_DSYNC)) cap_rights_set_one(rightsp, CAP_FSYNC); if (flags & (O_EXLOCK | O_SHLOCK)) diff --git a/sys/net/altq/altq_cbq.c b/sys/net/altq/altq_cbq.c index fdf39690160b..2333b9ea8678 100644 --- a/sys/net/altq/altq_cbq.c +++ b/sys/net/altq/altq_cbq.c @@ -173,6 +173,8 @@ cbq_request(struct ifaltq *ifq, int req, void *arg) static void get_class_stats(class_stats_t *statsp, struct rm_class *cl) { + memset(statsp, 0, sizeof(*statsp)); + statsp->xmit_cnt = cl->stats_.xmit_cnt; statsp->drop_cnt = cl->stats_.drop_cnt; statsp->over = cl->stats_.over; diff --git a/sys/net/altq/altq_fairq.c b/sys/net/altq/altq_fairq.c index 6069865101a0..0a00168e547e 100644 --- a/sys/net/altq/altq_fairq.c +++ b/sys/net/altq/altq_fairq.c @@ -857,6 +857,8 @@ get_class_stats(struct fairq_classstats *sp, struct fairq_class *cl) { fairq_bucket_t *b; + memset(sp, 0, sizeof(*sp)); + sp->class_handle = cl->cl_handle; sp->qlimit = cl->cl_qlimit; sp->xmit_cnt = cl->cl_xmitcnt; diff --git a/sys/net/altq/altq_priq.c b/sys/net/altq/altq_priq.c index 026346639b2e..fec488418546 100644 --- a/sys/net/altq/altq_priq.c +++ b/sys/net/altq/altq_priq.c @@ -597,6 +597,8 @@ priq_purgeq(struct priq_class *cl) static void get_class_stats(struct priq_classstats *sp, struct priq_class *cl) { + memset(sp, 0, sizeof(*sp)); + sp->class_handle = cl->cl_handle; sp->qlength = qlen(cl->cl_q); sp->qlimit = qlimit(cl->cl_q); diff --git a/sys/net/if.c b/sys/net/if.c index 607bcdd2aa80..0c7e32e858bc 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -2850,15 +2850,20 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) break; case SIOCAIFGROUP: + { + const char *groupname; + error = priv_check(td, PRIV_NET_ADDIFGROUP); if (error) return (error); - error = if_addgroup(ifp, - ((struct ifgroupreq *)data)->ifgr_group); + groupname = ((struct ifgroupreq *)data)->ifgr_group; + if (strnlen(groupname, IFNAMSIZ) == IFNAMSIZ) + return (EINVAL); + error = if_addgroup(ifp, groupname); if (error != 0) return (error); break; - + } case SIOCGIFGROUP: { struct epoch_tracker et; @@ -2870,15 +2875,20 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) } case SIOCDIFGROUP: + { + const char *groupname; + error = priv_check(td, PRIV_NET_DELIFGROUP); if (error) return (error); - error = if_delgroup(ifp, - ((struct ifgroupreq *)data)->ifgr_group); + groupname = ((struct ifgroupreq *)data)->ifgr_group; + if (strnlen(groupname, IFNAMSIZ) == IFNAMSIZ) + return (EINVAL); + error = if_delgroup(ifp, groupname); if (error != 0) return (error); break; - + } default: error = ENOIOCTL; break; @@ -3022,9 +3032,17 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td) goto out_noref; case SIOCGIFGMEMB: - error = if_getgroupmembers((struct ifgroupreq *)data); - goto out_noref; + { + struct ifgroupreq *req; + req = (struct ifgroupreq *)data; + if (strnlen(req->ifgr_name, IFNAMSIZ) == IFNAMSIZ) { + error = EINVAL; + goto out_noref; + } + error = if_getgroupmembers(req); + goto out_noref; + } #if defined(INET) || defined(INET6) case SIOCSVH: case SIOCGVH: diff --git a/sys/netgraph/ng_nat.c b/sys/netgraph/ng_nat.c index ae083608a199..9c09d3305ef9 100644 --- a/sys/netgraph/ng_nat.c +++ b/sys/netgraph/ng_nat.c @@ -812,7 +812,8 @@ ng_nat_rcvdata(hook_p hook, item_p item ) if (ip->ip_v != IPVERSION) goto send; /* other IP version, let it pass */ - if (m->m_pkthdr.len < ipofs + ntohs(ip->ip_len)) + uint16_t ip_len = ntohs(ip->ip_len); + if (m->m_pkthdr.len < (ipofs + ip_len)) goto send; /* packet too short (i.e. fragmented or broken) */ /* @@ -846,50 +847,68 @@ ng_nat_rcvdata(hook_p hook, item_p item ) if (rval == PKT_ALIAS_RESPOND) m->m_flags |= M_SKIP_FIREWALL; - m->m_pkthdr.len = m->m_len = ntohs(ip->ip_len) + ipofs; - if ((ip->ip_off & htons(IP_OFFMASK)) == 0 && - ip->ip_p == IPPROTO_TCP) { - struct tcphdr *th = (struct tcphdr *)((caddr_t)ip + - (ip->ip_hl << 2)); + /* Re-read just in case it has been updated */ + ip_len = ntohs(ip->ip_len); + int new_m_len = ip_len + ipofs; + if (new_m_len > (m->m_len + M_TRAILINGSPACE(m))) { /* - * Here is our terrible HACK. - * - * Sometimes LibAlias edits contents of TCP packet. - * In this case it needs to recompute full TCP - * checksum. However, the problem is that LibAlias - * doesn't have any idea about checksum offloading - * in kernel. To workaround this, we do not do - * checksumming in LibAlias, but only mark the - * packets in th_x2 field. If we receive a marked - * packet, we calculate correct checksum for it - * aware of offloading. - * - * Why do I do such a terrible hack instead of - * recalculating checksum for each packet? - * Because the previous checksum was not checked! - * Recalculating checksums for EVERY packet will - * hide ALL transmission errors. Yes, marked packets - * still suffer from this problem. But, sigh, natd(8) - * has this problem, too. + * This is just a safety railguard to make sure LibAlias has not + * screwed the IP packet up somehow, should probably be KASSERT() + * at some point. Calling in_delayed_cksum() will parse IP packet + * again and reliably panic if there is less data than the IP + * header declares, there might be some other places too. */ + log(LOG_ERR, "ng_nat_rcvdata: outgoing packet corrupted, " + "not enough data: expected %d, available (%d - %d)\n", + ip_len, m->m_len + (int)M_TRAILINGSPACE(m), ipofs); + NG_FREE_ITEM(item); + return (ENXIO); + } + + m->m_pkthdr.len = m->m_len = new_m_len; - if (th->th_x2) { - uint16_t ip_len = ntohs(ip->ip_len); + if ((ip->ip_off & htons(IP_OFFMASK)) != 0 || ip->ip_p != IPPROTO_TCP) + goto send; - th->th_x2 = 0; - th->th_sum = in_pseudo(ip->ip_src.s_addr, - ip->ip_dst.s_addr, htons(IPPROTO_TCP + - ip_len - (ip->ip_hl << 2))); + uint16_t pl_offset = ip->ip_hl << 2; + struct tcphdr *th = (struct tcphdr *)((caddr_t)ip + pl_offset); - if ((m->m_pkthdr.csum_flags & CSUM_TCP) == 0) { - m->m_pkthdr.csum_data = offsetof(struct tcphdr, - th_sum); - in_delayed_cksum(m); - } - } - } + /* + * Here is our terrible HACK. + * + * Sometimes LibAlias edits contents of TCP packet. + * In this case it needs to recompute full TCP + * checksum. However, the problem is that LibAlias + * doesn't have any idea about checksum offloading + * in kernel. To workaround this, we do not do + * checksumming in LibAlias, but only mark the + * packets in th_x2 field. If we receive a marked + * packet, we calculate correct checksum for it + * aware of offloading. + * + * Why do I do such a terrible hack instead of + * recalculating checksum for each packet? + * Because the previous checksum was not checked! + * Recalculating checksums for EVERY packet will + * hide ALL transmission errors. Yes, marked packets + * still suffer from this problem. But, sigh, natd(8) + * has this problem, too. + */ + + if (!th->th_x2) + goto send; + + th->th_x2 = 0; + th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, + htons(IPPROTO_TCP + ip_len - pl_offset)); + + if ((m->m_pkthdr.csum_flags & CSUM_TCP) != 0) + goto send; + + m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum); + in_delayed_cksum_o(m, ipofs); send: if (hook == priv->in) diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c index e534fdd77635..129dc1cfe892 100644 --- a/sys/netinet/in_proto.c +++ b/sys/netinet/in_proto.c @@ -110,6 +110,8 @@ SYSCTL_NODE(_net_inet, IPPROTO_ICMP, icmp, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, "ICMP"); SYSCTL_NODE(_net_inet, IPPROTO_UDP, udp, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, "UDP"); +SYSCTL_NODE(_net_inet, IPPROTO_UDPLITE, udplite, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, + "UDP-Lite"); SYSCTL_NODE(_net_inet, IPPROTO_TCP, tcp, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, "TCP"); #if defined(SCTP) || defined(SCTP_SUPPORT) diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 66051c9c711c..e3ef8e2c7dd9 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1045,14 +1045,14 @@ done: } void -in_delayed_cksum(struct mbuf *m) +in_delayed_cksum_o(struct mbuf *m, uint16_t iph_offset) { struct ip *ip; struct udphdr *uh; uint16_t cklen, csum, offset; - ip = mtod(m, struct ip *); - offset = ip->ip_hl << 2 ; + ip = (struct ip *)mtodo(m, iph_offset); + offset = iph_offset + (ip->ip_hl << 2); if (m->m_pkthdr.csum_flags & CSUM_UDP) { /* if udp header is not in the first mbuf copy udplen */ @@ -1079,6 +1079,13 @@ in_delayed_cksum(struct mbuf *m) *(u_short *)mtodo(m, offset) = csum; } +void +in_delayed_cksum(struct mbuf *m) +{ + + in_delayed_cksum_o(m, 0); +} + /* * IP socket option processing. */ diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 3220679d749f..a1402f4fa268 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -259,6 +259,7 @@ VNET_DECLARE(struct pfil_head *, inet_local_pfil_head); #define PFIL_INET_LOCAL_NAME "inet-local" void in_delayed_cksum(struct mbuf *m); +void in_delayed_cksum_o(struct mbuf *m, uint16_t o); /* Hooks for ipfw, dummynet, divert etc. Most are declared in raw_ip.c */ /* diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 6829d2a743f2..81b378f496c9 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -654,7 +654,7 @@ tcp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *inp, } } m->m_pkthdr.tcp_tun_port = port = uh->uh_sport; - bcopy(th, uh, m->m_len - off); + bcopy(th, uh, m->m_len - off - sizeof(struct udphdr)); m->m_len -= sizeof(struct udphdr); m->m_pkthdr.len -= sizeof(struct udphdr); /* diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 077c3a5f6ef3..713f6a35ad45 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -1175,7 +1175,7 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, /* * If listening socket requested TCP digests, check that * received ACK has signature and it is correct. - * If not, drop the ACK and leave sc entry in th cache, + * If not, drop the ACK and leave sc entry in the cache, * because SYN was received with correct signature. */ if (sc->sc_flags & SCF_SIGNATURE) { @@ -1387,6 +1387,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, struct tcpcb *tp; struct socket *rv = NULL; struct syncache *sc = NULL; + struct ucred *cred; struct syncache_head *sch; struct mbuf *ipopts = NULL; u_int ltflags; @@ -1415,6 +1416,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, */ KASSERT(SOLISTENING(so), ("%s: %p not listening", __func__, so)); tp = sototcpcb(so); + cred = V_tcp_syncache.see_other ? NULL : crhold(so->so_cred); #ifdef INET6 if (inc->inc_flags & INC_ISIPV6) { @@ -1643,16 +1645,16 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, /* * sc_cred is only used in syncache_pcblist() to list TCP endpoints in * TCPS_SYN_RECEIVED state when V_tcp_syncache.see_other is false. - * Therefore, store the credentials and take a reference count only - * when needed: + * Therefore, store the credentials only when needed: * - sc is allocated from the zone and not using the on stack instance. * - the sysctl variable net.inet.tcp.syncache.see_other is false. * The reference count is decremented when a zone allocated sc is * freed in syncache_free(). */ - if (sc != &scs && !V_tcp_syncache.see_other) - sc->sc_cred = crhold(so->so_cred); - else + if (sc != &scs && !V_tcp_syncache.see_other) { + sc->sc_cred = cred; + cred = NULL; + } else sc->sc_cred = NULL; sc->sc_port = port; sc->sc_ipopts = ipopts; @@ -1790,6 +1792,8 @@ donenoprobe: tcp_fastopen_decrement_counter(tfo_pending); tfo_expanded: + if (cred != NULL) + crfree(cred); if (sc == NULL || sc == &scs) { #ifdef MAC mac_syncache_destroy(&maclabel); diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 65a9fbc84ff7..1c687e94bb4a 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -515,9 +515,12 @@ tcp_timer_persist(struct tcpcb *tp) if (progdrop || (tp->t_rxtshift >= V_tcp_retries && (ticks - tp->t_rcvtime >= tcp_maxpersistidle || ticks - tp->t_rcvtime >= TCP_REXMTVAL(tp) * tcp_totbackoff))) { - if (!progdrop) + if (progdrop) { + tcp_log_end_status(tp, TCP_EI_STATUS_PROGRESS); + } else { TCPSTAT_INC(tcps_persistdrop); - tcp_log_end_status(tp, TCP_EI_STATUS_PERSIST_MAX); + tcp_log_end_status(tp, TCP_EI_STATUS_PERSIST_MAX); + } goto dropit; } /* diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 88df8f8d38fc..a1000dadf583 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -852,6 +852,11 @@ SYSCTL_PROC(_net_inet_udp, UDPCTL_PCBLIST, pcblist, udp_pcblist, "S,xinpcb", "List of active UDP sockets"); +SYSCTL_PROC(_net_inet_udplite, OID_AUTO, pcblist, + CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, IPPROTO_UDPLITE, + udp_pcblist, "S,xinpcb", + "List of active UDP-Lite sockets"); + #ifdef INET static int udp_getcred(SYSCTL_HANDLER_ARGS) @@ -1141,7 +1146,19 @@ udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, else INP_RLOCK(inp); NET_EPOCH_ENTER(et); +#ifdef INET6 + if ((flags & PRUS_IPV6) != 0) { + if ((inp->in6p_outputopts != NULL) && + (inp->in6p_outputopts->ip6po_tclass != -1)) + tos = (u_char)inp->in6p_outputopts->ip6po_tclass; + else + tos = 0; + } else { + tos = inp->inp_ip_tos; + } +#else tos = inp->inp_ip_tos; +#endif if (control != NULL) { /* * XXX: Currently, we assume all the optional information is @@ -1165,6 +1182,23 @@ udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, error = udp_v4mapped_pktinfo(cm, &src, inp, flags); if (error != 0) break; + if (((flags & PRUS_IPV6) != 0) && + (cm->cmsg_level == IPPROTO_IPV6) && + (cm->cmsg_type == IPV6_TCLASS)) { + int tclass; + + if (cm->cmsg_len != CMSG_LEN(sizeof(int))) { + error = EINVAL; + break; + } + tclass = *(int *)CMSG_DATA(cm); + if (tclass < -1 || tclass > 255) { + error = EINVAL; + break; + } + if (tclass != -1) + tos = (u_char)tclass; + } #endif if (cm->cmsg_level != IPPROTO_IP) continue; diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h index 51272e7c9349..569b7b8d5240 100644 --- a/sys/netinet/udp_var.h +++ b/sys/netinet/udp_var.h @@ -141,6 +141,7 @@ void kmod_udpstat_inc(int statnum); kmod_udpstat_inc(offsetof(struct udpstat, name) / sizeof(uint64_t)) SYSCTL_DECL(_net_inet_udp); +SYSCTL_DECL(_net_inet_udplite); VNET_DECLARE(struct inpcbinfo, udbinfo); VNET_DECLARE(struct inpcbinfo, ulitecbinfo); diff --git a/sys/netpfil/ipfw/pmod/tcpmod.c b/sys/netpfil/ipfw/pmod/tcpmod.c index d7400f4fd5ed..138fefe22a98 100644 --- a/sys/netpfil/ipfw/pmod/tcpmod.c +++ b/sys/netpfil/ipfw/pmod/tcpmod.c @@ -58,7 +58,8 @@ VNET_DEFINE_STATIC(uint16_t, tcpmod_setmss_eid) = 0; #define V_tcpmod_setmss_eid VNET(tcpmod_setmss_eid) static int -tcpmod_setmss(struct mbuf **mp, struct tcphdr *tcp, int tlen, uint16_t mss) +tcpmod_setmss(struct mbuf **mp, struct tcphdr *tcp, int tlen, uint16_t mss, + int *done) { struct mbuf *m; u_char *cp; @@ -73,8 +74,10 @@ tcpmod_setmss(struct mbuf **mp, struct tcphdr *tcp, int tlen, uint16_t mss) * TCP header with options. */ *mp = m = m_pullup(m, m->m_pkthdr.len); - if (m == NULL) + if (m == NULL) { + *done = 1; return (ret); + } } /* Parse TCP options. */ for (tlen -= sizeof(struct tcphdr), cp = (u_char *)(tcp + 1); @@ -115,7 +118,7 @@ tcpmod_setmss(struct mbuf **mp, struct tcphdr *tcp, int tlen, uint16_t mss) #ifdef INET6 static int -tcpmod_ipv6_setmss(struct mbuf **mp, uint16_t mss) +tcpmod_ipv6_setmss(struct mbuf **mp, uint16_t mss, int *done) { struct ip6_hdr *ip6; struct ip6_hbh *hbh; @@ -143,13 +146,13 @@ tcpmod_ipv6_setmss(struct mbuf **mp, uint16_t mss) /* We must have TCP options and enough data in a packet. */ if (hlen <= sizeof(struct tcphdr) || hlen > plen) return (IP_FW_DENY); - return (tcpmod_setmss(mp, tcp, hlen, mss)); + return (tcpmod_setmss(mp, tcp, hlen, mss, done)); } #endif /* INET6 */ #ifdef INET static int -tcpmod_ipv4_setmss(struct mbuf **mp, uint16_t mss) +tcpmod_ipv4_setmss(struct mbuf **mp, uint16_t mss, int *done) { struct tcphdr *tcp; struct ip *ip; @@ -163,7 +166,7 @@ tcpmod_ipv4_setmss(struct mbuf **mp, uint16_t mss) /* We must have TCP options and enough data in a packet. */ if (hlen <= sizeof(struct tcphdr) || hlen > plen) return (IP_FW_DENY); - return (tcpmod_setmss(mp, tcp, hlen, mss)); + return (tcpmod_setmss(mp, tcp, hlen, mss, done)); } #endif /* INET */ @@ -207,19 +210,23 @@ ipfw_tcpmod(struct ip_fw_chain *chain, struct ip_fw_args *args, switch (args->f_id.addr_type) { #ifdef INET case 4: - ret = tcpmod_ipv4_setmss(&args->m, htons(icmd->arg1)); + ret = tcpmod_ipv4_setmss(&args->m, htons(icmd->arg1), + done); break; #endif #ifdef INET6 case 6: - ret = tcpmod_ipv6_setmss(&args->m, htons(icmd->arg1)); + ret = tcpmod_ipv6_setmss(&args->m, htons(icmd->arg1), + done); break; #endif } /* * We return zero in both @ret and @done on success, and ipfw_chk() * will update rule counters. Otherwise a packet will not be matched - * by rule. + * by rule. We passed @done around above in case we hit a fatal error + * somewhere, we'll return non-zero but signal that rule processing + * cannot succeed. */ return (ret); } diff --git a/sys/netpfil/pf/if_pfsync.c b/sys/netpfil/pf/if_pfsync.c index 8c080b472653..2a5cb0612d36 100644 --- a/sys/netpfil/pf/if_pfsync.c +++ b/sys/netpfil/pf/if_pfsync.c @@ -530,6 +530,9 @@ pfsync_state_import(union pfsync_state_union *sp, int flags, int msg_version) PF_RULES_RASSERT(); + if (strnlen(sp->pfs_1301.ifname, IFNAMSIZ) == IFNAMSIZ) + return (EINVAL); + if (sp->pfs_1301.creatorid == 0) { if (V_pf_status.debug >= PF_DEBUG_MISC) printf("%s: invalid creator id: %08x\n", __func__, diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index d95f36d06ee3..cf53ea638095 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -4645,6 +4645,17 @@ DIOCCHANGEADDR_error: error = ENODEV; break; } + if (strnlen(io->pfrio_table.pfrt_anchor, MAXPATHLEN) + == MAXPATHLEN) { + error = EINVAL; + goto fail; + } + if (strnlen(io->pfrio_table.pfrt_name, PF_TABLE_NAME_SIZE) + == PF_TABLE_NAME_SIZE) { + error = EINVAL; + goto fail; + } + PF_RULES_WLOCK(); error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c index 6a913883cc5c..bf05855439bc 100644 --- a/sys/x86/x86/local_apic.c +++ b/sys/x86/x86/local_apic.c @@ -371,9 +371,12 @@ lvt_mode_impl(struct lapic *la, struct lvt *lvt, u_int pin, uint32_t value) case APIC_LVT_DM_SMI: case APIC_LVT_DM_INIT: case APIC_LVT_DM_EXTINT: - if (!lvt->lvt_edgetrigger && bootverbose) { - printf("lapic%u: Forcing LINT%u to edge trigger\n", - la->la_id, pin); + if (!lvt->lvt_edgetrigger) { + if (bootverbose) { + printf( + "lapic%u: Forcing LINT%u to edge trigger\n", + la->la_id, pin); + } value &= ~APIC_LVT_TM; } /* Use a vector of 0. */ diff --git a/tests/sys/netpfil/pf/ioctl/validation.c b/tests/sys/netpfil/pf/ioctl/validation.c index 1ce8999dcb91..651e6837acd7 100644 --- a/tests/sys/netpfil/pf/ioctl/validation.c +++ b/tests/sys/netpfil/pf/ioctl/validation.c @@ -32,6 +32,7 @@ #include <net/if.h> #include <net/pfvar.h> +#include <errno.h> #include <fcntl.h> #include <stdio.h> @@ -192,6 +193,38 @@ ATF_TC_CLEANUP(gettables, tc) COMMON_CLEANUP(); } +ATF_TC_WITH_CLEANUP(clrtables); +ATF_TC_HEAD(clrtables, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); + atf_tc_set_md_var(tc, "require.kmods", "pf"); +} + +ATF_TC_BODY(clrtables, tc) +{ + struct pfioc_table io; + struct pfr_table tbl; + int flags; + + COMMON_HEAD(); + + flags = 0; + + memset(&io, '/', sizeof(io)); + io.pfrio_flags = flags; + io.pfrio_buffer = &tbl; + io.pfrio_esize = 0; + io.pfrio_size = 1; + + if (ioctl(dev, DIOCRCLRTABLES, &io) == 0) + atf_tc_fail("Request with unterminated anchor name succeeded"); +} + +ATF_TC_CLEANUP(clrtables, tc) +{ + COMMON_CLEANUP(); +} + ATF_TC_WITH_CLEANUP(gettstats); ATF_TC_HEAD(gettstats, tc) { @@ -894,11 +927,36 @@ ATF_TC_CLEANUP(rpool_mtx2, tc) } +ATF_TC_WITH_CLEANUP(addstate); +ATF_TC_HEAD(addstate, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); + atf_tc_set_md_var(tc, "require.kmods", "pfsync"); +} + +ATF_TC_BODY(addstate, tc) +{ + struct pfioc_state st; + + COMMON_HEAD(); + + memset(&st, 'a', sizeof(st)); + st.state.timeout = PFTM_TCP_FIRST_PACKET; + + ATF_CHECK_ERRNO(EINVAL, ioctl(dev, DIOCADDSTATE, &st) == -1); +} + +ATF_TC_CLEANUP(addstate, tc) +{ + COMMON_CLEANUP(); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, addtables); ATF_TP_ADD_TC(tp, deltables); ATF_TP_ADD_TC(tp, gettables); + ATF_TP_ADD_TC(tp, clrtables); ATF_TP_ADD_TC(tp, getastats); ATF_TP_ADD_TC(tp, gettstats); ATF_TP_ADD_TC(tp, clrtstats); @@ -918,6 +976,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, tag); ATF_TP_ADD_TC(tp, rpool_mtx); ATF_TP_ADD_TC(tp, rpool_mtx2); + ATF_TP_ADD_TC(tp, addstate); return (atf_no_error()); } diff --git a/usr.bin/bsdcat/Makefile b/usr.bin/bsdcat/Makefile index 8e730e634ea6..0377a4c48f5f 100644 --- a/usr.bin/bsdcat/Makefile +++ b/usr.bin/bsdcat/Makefile @@ -12,7 +12,7 @@ BSDCAT_VERSION_STRING!= sed -n '/define.*ARCHIVE_VERSION_ONLY_STRING/{s,[^0-9.], SRCS= bsdcat.c cmdline.c .PATH: ${_LIBARCHIVEDIR}/libarchive_fe -SRCS+= err.c +SRCS+= lafe_err.c CFLAGS+= -DBSDCAT_VERSION_STRING=\"${BSDCAT_VERSION_STRING}\" CFLAGS+= -DPLATFORM_CONFIG_H=\"${_LIBARCHIVECONFDIR}/config_freebsd.h\" diff --git a/usr.bin/cpio/Makefile b/usr.bin/cpio/Makefile index b52c9645ebb5..a52a12ea361b 100644 --- a/usr.bin/cpio/Makefile +++ b/usr.bin/cpio/Makefile @@ -12,7 +12,7 @@ BSDCPIO_VERSION_STRING!= sed -n '/define.*ARCHIVE_VERSION_ONLY_STRING/{s,[^0-9.] SRCS= cpio.c cmdline.c .PATH: ${_LIBARCHIVEDIR}/libarchive_fe -SRCS+= err.c line_reader.c passphrase.c +SRCS+= lafe_err.c line_reader.c passphrase.c CFLAGS+= -DBSDCPIO_VERSION_STRING=\"${BSDCPIO_VERSION_STRING}\" CFLAGS+= -DPLATFORM_CONFIG_H=\"${_LIBARCHIVECONFDIR}/config_freebsd.h\" diff --git a/usr.bin/cpio/tests/Makefile b/usr.bin/cpio/tests/Makefile index d99b1c37e226..e06f7fc34de3 100644 --- a/usr.bin/cpio/tests/Makefile +++ b/usr.bin/cpio/tests/Makefile @@ -27,7 +27,7 @@ CFLAGS.test_utils.c+= -Wno-cast-align CPIO_SRCS= cmdline.c .PATH: ${_LIBARCHIVEDIR}/libarchive_fe -CPIO_SRCS+= err.c +CPIO_SRCS+= lafe_err.c .PATH: ${_LIBARCHIVEDIR}/cpio/test TESTS_SRCS= \ diff --git a/usr.bin/id/id.c b/usr.bin/id/id.c index 238c6f2bf709..342a891e4165 100644 --- a/usr.bin/id/id.c +++ b/usr.bin/id/id.c @@ -79,19 +79,13 @@ main(int argc, char *argv[]) { struct group *gr; struct passwd *pw; -#ifdef USE_BSM_AUDIT - bool Aflag; -#endif - bool Gflag, Mflag, Pflag; + bool Aflag, Gflag, Mflag, Pflag; bool cflag, dflag, gflag, nflag, pflag, rflag, sflag, uflag; int ch, combo, error, id; const char *myname, *optstr; char loginclass[MAXLOGNAME]; -#ifdef USE_BSM_AUDIT - Aflag = false; -#endif - Gflag = Mflag = Pflag = false; + Aflag = Gflag = Mflag = Pflag = false; cflag = dflag = gflag = nflag = pflag = rflag = sflag = uflag = false; myname = getprogname(); diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c index 363224d5f913..898158ce288a 100644 --- a/usr.bin/netstat/inet.c +++ b/usr.bin/netstat/inet.c @@ -90,7 +90,7 @@ static void inetprint(const char *, struct in_addr *, int, const char *, int, const int); #endif #ifdef INET6 -static int udp_done, tcp_done, sdp_done; +static int udp_done, udplite_done, tcp_done, sdp_done; #endif /* INET6 */ static int @@ -107,6 +107,9 @@ pcblist_sysctl(int proto, const char *name, char **bufp) case IPPROTO_UDP: mibvar = "net.inet.udp.pcblist"; break; + case IPPROTO_UDPLITE: + mibvar = "net.inet.udplite.pcblist"; + break; default: mibvar = "net.inet.raw.pcblist"; break; @@ -229,11 +232,18 @@ protopr(u_long off, const char *name, int af1, int proto) udp_done = 1; #endif break; + case IPPROTO_UDPLITE: +#ifdef INET6 + if (udplite_done != 0) + return; + else + udplite_done = 1; +#endif + break; } if (!pcblist_sysctl(proto, name, &buf)) return; - if (istcp && (cflag || Cflag)) { fnamelen = strlen("Stack"); cnamelen = strlen("CC"); @@ -325,18 +335,18 @@ protopr(u_long off, const char *name, int af1, int proto) "Proto", "Listen", "Local Address"); else if (Tflag) xo_emit((Aflag && !Wflag) ? - "{T:/%-5.5s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-18.18s} {T:/%s}" : + "{T:/%-9.9s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-18.18s} {T:/%s}" : ((!Wflag || af1 == AF_INET) ? - "{T:/%-5.5s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-22.22s} {T:/%s}" : - "{T:/%-5.5s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-45.45s} {T:/%s}"), + "{T:/%-9.9s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-22.22s} {T:/%s}" : + "{T:/%-9.9s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-45.45s} {T:/%s}"), "Proto", "Rexmit", "OOORcv", "0-win", "Local Address", "Foreign Address"); else { xo_emit((Aflag && !Wflag) ? - "{T:/%-5.5s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-18.18s} {T:/%-18.18s}" : + "{T:/%-9.9s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-18.18s} {T:/%-18.18s}" : ((!Wflag || af1 == AF_INET) ? - "{T:/%-5.5s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-22.22s} {T:/%-22.22s}" : - "{T:/%-5.5s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-45.45s} {T:/%-45.45s}"), + "{T:/%-9.9s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-22.22s} {T:/%-22.22s}" : + "{T:/%-9.9s} {T:/%-6.6s} {T:/%-6.6s} {T:/%-45.45s} {T:/%-45.45s}"), "Proto", "Recv-Q", "Send-Q", "Local Address", "Foreign Address"); if (!xflag && !Rflag) @@ -389,9 +399,14 @@ protopr(u_long off, const char *name, int af1, int proto) vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? "4" : ""; if (istcp && (tp->t_flags & TF_TOE) != 0) - xo_emit("{:protocol/%-3.3s%-2.2s/%s%s} ", "toe", vchar); - else - xo_emit("{:protocol/%-3.3s%-2.2s/%s%s} ", name, vchar); + xo_emit("{:protocol/%-3.3s%-6.6s/%s%s} ", "toe", vchar); + else { + int len; + + len = max (2, 9 - strlen(name)); + xo_emit("{:protocol/%.7s%-*.*s/%s%s} ", name, len, len, + vchar); + } if (Lflag) { char buf1[33]; diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c index 481284cb88a6..a60d951c8d39 100644 --- a/usr.bin/netstat/main.c +++ b/usr.bin/netstat/main.c @@ -96,6 +96,8 @@ static struct protox { tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, { -1 , N_UDPSTAT, 1, protopr, udp_stats, NULL, "udp", 1, IPPROTO_UDP }, + { -1, -1, 1, protopr, + NULL, NULL, "udplite", 1, IPPROTO_UDPLITE }, #ifdef SCTP { -1, N_SCTPSTAT, 1, sctp_protopr, sctp_stats, NULL, "sctp", 1, IPPROTO_SCTP }, @@ -142,6 +144,8 @@ static struct protox ip6protox[] = { tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, { -1 , N_UDPSTAT, 1, protopr, udp_stats, NULL, "udp", 1, IPPROTO_UDP }, + { -1, -1, 1, protopr, + NULL, NULL, "udplite", 1, IPPROTO_UDPLITE }, { -1 , N_IP6STAT, 1, protopr, ip6_stats, ip6_ifstats, "ip6", 1, IPPROTO_RAW }, { -1 , N_ICMP6STAT, 1, protopr, diff --git a/usr.bin/sockstat/sockstat.1 b/usr.bin/sockstat/sockstat.1 index eba4b1c4aed5..abd83f049703 100644 --- a/usr.bin/sockstat/sockstat.1 +++ b/usr.bin/sockstat/sockstat.1 @@ -25,7 +25,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd October 7, 2025 +.Dd October 9, 2025 .Dt SOCKSTAT 1 .Os .Sh NAME @@ -194,6 +194,7 @@ is specified (only for SCTP or TCP). The path state if .Fl s is specified (only for SCTP). +This column is only shown when there is at least one path state to show. .It Li CONN STATE The connection state if .Fl s diff --git a/usr.bin/sockstat/sockstat.c b/usr.bin/sockstat/sockstat.c index 4548eb8a0b11..587647e5950f 100644 --- a/usr.bin/sockstat/sockstat.c +++ b/usr.bin/sockstat/sockstat.c @@ -99,11 +99,13 @@ static int opt_U; /* Show remote UDP encapsulation port number */ static int opt_u; /* Show Unix domain sockets */ static int opt_v; /* Verbose mode */ static int opt_w; /* Wide print area for addresses */ +static bool show_path_state = false; /* * Default protocols to use if no -P was defined. */ -static const char *default_protos[] = {"sctp", "tcp", "udp", "divert" }; +static const char *default_protos[] = {"sctp", "tcp", "udp", "udplite", + "divert" }; static size_t default_numprotos = nitems(default_protos); static int *protos; /* protocols to use */ @@ -519,6 +521,7 @@ gather_sctp(void) ((xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE) || (xstcb->last == 1))) { RB_INSERT(socks_t, &socks, sock); + show_path_state = true; } else { free_socket(sock); } @@ -684,6 +687,10 @@ gather_inet(int proto) varname = "net.inet.udp.pcblist"; protoname = "udp"; break; + case IPPROTO_UDPLITE: + varname = "net.inet.udplite.pcblist"; + protoname = "udplite"; + break; case IPPROTO_DIVERT: varname = "net.inet.divert.pcblist"; protoname = "div"; @@ -732,6 +739,7 @@ gather_inet(int proto) protoname = xtp->t_flags & TF_TOE ? "toe" : "tcp"; break; case IPPROTO_UDP: + case IPPROTO_UDPLITE: case IPPROTO_DIVERT: xip = (struct xinpcb *)xig; if (!check_ksize(xip->xi_len, struct xinpcb)) @@ -1159,7 +1167,7 @@ displaysock(struct sock *s, int pos) faddr = s->faddr; first = 1; while (laddr != NULL || faddr != NULL) { - offset = 37; + offset = 40; while (pos < offset) pos += xprintf(" "); switch (s->family) { @@ -1296,7 +1304,7 @@ displaysock(struct sock *s, int pos) } offset += 7; } - if (opt_s) { + if (opt_s && show_path_state) { if (faddr != NULL && s->proto == IPPROTO_SCTP && s->state != SCTP_CLOSED && @@ -1387,7 +1395,7 @@ display(void) int n, pos; if (opt_q != 1) { - printf("%-8s %-10s %-5s %-3s %-6s %-*s %-*s", + printf("%-8s %-10s %-5s %-3s %-9s %-*s %-*s", "USER", "COMMAND", "PID", "FD", "PROTO", opt_w ? 45 : 21, "LOCAL ADDRESS", opt_w ? 45 : 21, "FOREIGN ADDRESS"); @@ -1401,7 +1409,8 @@ display(void) if (opt_U) printf(" %-6s", "ENCAPS"); if (opt_s) { - printf(" %-12s", "PATH STATE"); + if (show_path_state) + printf(" %-12s", "PATH STATE"); printf(" %-12s", "CONN STATE"); } if (opt_b) diff --git a/usr.bin/tar/Makefile b/usr.bin/tar/Makefile index 9260315fb30b..8b0d3e4a6cf0 100644 --- a/usr.bin/tar/Makefile +++ b/usr.bin/tar/Makefile @@ -17,7 +17,7 @@ SRCS= bsdtar.c \ write.c .PATH: ${_LIBARCHIVEDIR}/libarchive_fe -SRCS+= err.c \ +SRCS+= lafe_err.c \ line_reader.c \ passphrase.c diff --git a/usr.bin/tar/tests/Makefile b/usr.bin/tar/tests/Makefile index 34f87cb65ea2..fe3dd3e8e6ed 100644 --- a/usr.bin/tar/tests/Makefile +++ b/usr.bin/tar/tests/Makefile @@ -28,6 +28,7 @@ TESTS_SRCS= \ test_0.c \ test_basic.c \ test_copy.c \ + test_crlf_mtree.c \ test_empty_mtree.c \ test_extract_tar_bz2.c \ test_extract_tar_grz.c \ diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c index 47d6aef8f6ff..a6b6d4ec187e 100644 --- a/usr.bin/truss/syscalls.c +++ b/usr.bin/truss/syscalls.c @@ -401,7 +401,7 @@ static const struct syscall_decode decoded_syscalls[] = { { .name = "nanosleep", .ret_type = 1, .nargs = 1, .args = { { Timespec, 0 } } }, { .name = "nmount", .ret_type = 1, .nargs = 3, - .args = { { Ptr, 0 }, { UInt, 1 }, { Mountflags, 2 } } }, + .args = { { Iovec | IN, 0 }, { UInt, 1 }, { Mountflags, 2 } } }, { .name = "open", .ret_type = 1, .nargs = 3, .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } }, { .name = "openat", .ret_type = 1, .nargs = 4, diff --git a/usr.bin/unzip/Makefile b/usr.bin/unzip/Makefile index 7193ab58b5a3..b14122f93ae6 100644 --- a/usr.bin/unzip/Makefile +++ b/usr.bin/unzip/Makefile @@ -13,7 +13,7 @@ BSDUNZIP_VERSION_STRING!= sed -n '/define.*ARCHIVE_VERSION_ONLY_STRING/{s,[^0-9. SRCS= bsdunzip.c .PATH: ${_LIBARCHIVEDIR}/libarchive_fe -SRCS+= cmdline.c err.c passphrase.c +SRCS+= cmdline.c lafe_err.c passphrase.c CFLAGS+= -DBSDUNZIP_VERSION_STRING=\"${BSDUNZIP_VERSION_STRING}\" CFLAGS+= -DPLATFORM_CONFIG_H=\"${_LIBARCHIVECONFDIR}/config_freebsd.h\" diff --git a/usr.bin/unzip/tests/Makefile b/usr.bin/unzip/tests/Makefile index 85fc4b88cd78..fd5254a55912 100644 --- a/usr.bin/unzip/tests/Makefile +++ b/usr.bin/unzip/tests/Makefile @@ -24,7 +24,7 @@ CFLAGS+= -I${_LIBARCHIVEDIR}/libarchive_fe -I${_LIBARCHIVEDIR}/test_utils CFLAGS.test_utils.c+= -Wno-cast-align .PATH: ${_LIBARCHIVEDIR}/libarchive_fe -UNZIP_SRCS+= err.c +UNZIP_SRCS+= lafe_err.c .PATH: ${_LIBARCHIVEDIR}/unzip/test TESTS_SRCS= \ |
