diff options
Diffstat (limited to 'lib')
329 files changed, 14126 insertions, 4711 deletions
diff --git a/lib/Makefile b/lib/Makefile index 1f69b4208738..3417e7b30cb4 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -109,6 +109,7 @@ SUBDIR= ${SUBDIR_BOOTSTRAP} \ libwrap \ libxo \ liby \ + libyaml \ libz \ libzstd \ ncurses \ @@ -175,18 +176,24 @@ SUBDIR.${MK_FILE}+= libmagic SUBDIR.${MK_GPIO}+= libgpio SUBDIR.${MK_GSSAPI}+= libgssapi librpcsec_gss SUBDIR.${MK_ICONV}+= libiconv_modules +.if ${MK_MITKRB5} == "no" SUBDIR.${MK_KERBEROS_SUPPORT}+= libcom_err +.endif SUBDIR.${MK_LDNS}+= libldns SUBDIR.${MK_STATS}+= libstats # The libraries under libclang_rt can only be built by clang. -.if ${COMPILER_TYPE} == "clang" && ${MK_CLANG} != "no" +.if (${COMPILER_TYPE} == "clang" || make(clean) || make(cleandir)) && \ + ${MK_CLANG} != "no" _libclang_rt= libclang_rt .elif (${MK_ASAN} != "no" || ${MK_UBSAN} != "no") && make(all) .error Requested build with sanitizers but cannot build runtime libraries! .endif +# This construct disables libefivar for 32-bit build. +.if ${MACHINE_CPUARCH} != "i386" SUBDIR.${MK_EFI}+= libefivar +.endif SUBDIR.${MK_GOOGLETEST}+= googletest SUBDIR.${MK_NETGRAPH}+= libnetgraph SUBDIR.${MK_NIS}+= libypclnt diff --git a/lib/atf/Makefile.inc b/lib/atf/Makefile.inc index c776c2f8f84e..f8f329842eb4 100644 --- a/lib/atf/Makefile.inc +++ b/lib/atf/Makefile.inc @@ -27,6 +27,3 @@ CFLAGS+= -DHAVE_CONFIG_H WARNS?= 3 - -# Permit use of auto_ptr for compilers defaulting to C++17 or later -CXXSTD= c++11 diff --git a/lib/atf/libatf-c++/Makefile b/lib/atf/libatf-c++/Makefile index 221a16657c2a..985a79b7dc03 100644 --- a/lib/atf/libatf-c++/Makefile +++ b/lib/atf/libatf-c++/Makefile @@ -48,9 +48,6 @@ CFLAGS+= -I. CFLAGS+= -DHAVE_CONFIG_H -# Silence warnings about usage of deprecated std::auto_ptr -CXXWARNFLAGS+= -Wno-deprecated-declarations - SRCS= application.cpp \ build.cpp \ check.cpp \ diff --git a/lib/atf/libatf-c/Makefile b/lib/atf/libatf-c/Makefile index 9fd36dc913f3..4cfee2ed824f 100644 --- a/lib/atf/libatf-c/Makefile +++ b/lib/atf/libatf-c/Makefile @@ -119,6 +119,8 @@ MLINKS+= atf-c.3 ATF_CHECK.3 \ atf-c.3 atf_tc_fail.3 \ atf-c.3 atf_tc_fail_nonfatal.3 \ atf-c.3 atf_tc_pass.3 \ + atf-c.3 atf_tc_require_kmod.3 \ + atf-c.3 atf_tc_require_prog.3 \ atf-c.3 atf_tc_skip.3 \ atf-c.3 atf_utils_cat_file.3 \ atf-c.3 atf_utils_compare_file.3 \ diff --git a/lib/clang/libclang/Makefile b/lib/clang/libclang/Makefile index d7e1532d2a8c..7eb2c99b25c8 100644 --- a/lib/clang/libclang/Makefile +++ b/lib/clang/libclang/Makefile @@ -1,7 +1,22 @@ .include <bsd.init.mk> .include "../clang.pre.mk" +.if defined(TOOLS_PREFIX) +# Build static library during cross-tools stage LIB= clang +INTERNALLIB= +.else +PACKAGE= clang +SHLIB_CXX= clang +SHLIB_MAJOR= 19 +PRIVATELIB= +.if ${MACHINE} == "powerpc" +# Work around "relocation R_PPC_GOT16 out of range" errors +PICFLAG= -fPIC +.endif +.endif + +SHARED_CXXFLAGS+= -UPIC # To avoid compile errors CFLAGS+= -I${.OBJDIR} CFLAGS+= -I${OBJTOP}/lib/clang/libllvm @@ -70,7 +85,7 @@ SRCS_MIN+= AST/CommentParser.cpp SRCS_MIN+= AST/CommentSema.cpp SRCS_MIN+= AST/ComparisonCategories.cpp SRCS_MIN+= AST/ComputeDependence.cpp -SRCS_FUL+= AST/DataCollection.cpp +SRCS_MIN+= AST/DataCollection.cpp SRCS_MIN+= AST/Decl.cpp SRCS_MIN+= AST/DeclBase.cpp SRCS_MIN+= AST/DeclCXX.cpp @@ -158,7 +173,9 @@ SRCS_MIN+= AST/VTableBuilder.cpp SRCS_MIN+= ASTMatchers/ASTMatchFinder.cpp SRCS_MIN+= ASTMatchers/ASTMatchersInternal.cpp SRCS_MIN+= ASTMatchers/Dynamic/Diagnostics.cpp +SRCS_MIN+= ASTMatchers/Dynamic/Marshallers.cpp SRCS_MIN+= ASTMatchers/Dynamic/Registry.cpp +SRCS_MIN+= ASTMatchers/Dynamic/VariantValue.cpp SRCS_MIN+= Analysis/AnalysisDeclContext.cpp SRCS_MIN+= Analysis/BodyFarm.cpp SRCS_MIN+= Analysis/CFG.cpp @@ -424,27 +441,27 @@ SRCS_MIN+= ExtractAPI/DeclarationFragments.cpp SRCS_MIN+= ExtractAPI/ExtractAPIConsumer.cpp SRCS_MIN+= ExtractAPI/Serialization/SymbolGraphSerializer.cpp SRCS_MIN+= ExtractAPI/TypedefUnderlyingTypeResolver.cpp -SRCS_EXT+= Format/AffectedRangeManager.cpp -SRCS_EXT+= Format/BreakableToken.cpp -SRCS_EXT+= Format/ContinuationIndenter.cpp -SRCS_EXT+= Format/DefinitionBlockSeparator.cpp -SRCS_EXT+= Format/Format.cpp -SRCS_EXT+= Format/FormatToken.cpp -SRCS_EXT+= Format/FormatTokenLexer.cpp -SRCS_EXT+= Format/IntegerLiteralSeparatorFixer.cpp -SRCS_EXT+= Format/MacroCallReconstructor.cpp -SRCS_EXT+= Format/MacroExpander.cpp +SRCS_MIN+= Format/AffectedRangeManager.cpp +SRCS_MIN+= Format/BreakableToken.cpp +SRCS_MIN+= Format/ContinuationIndenter.cpp +SRCS_MIN+= Format/DefinitionBlockSeparator.cpp +SRCS_MIN+= Format/Format.cpp +SRCS_MIN+= Format/FormatToken.cpp +SRCS_MIN+= Format/FormatTokenLexer.cpp +SRCS_MIN+= Format/IntegerLiteralSeparatorFixer.cpp +SRCS_MIN+= Format/MacroCallReconstructor.cpp +SRCS_MIN+= Format/MacroExpander.cpp SRCS_EXT+= Format/MatchFilePath.cpp -SRCS_EXT+= Format/NamespaceEndCommentsFixer.cpp -SRCS_EXT+= Format/ObjCPropertyAttributeOrderFixer.cpp -SRCS_EXT+= Format/QualifierAlignmentFixer.cpp -SRCS_EXT+= Format/SortJavaScriptImports.cpp -SRCS_EXT+= Format/TokenAnalyzer.cpp -SRCS_EXT+= Format/TokenAnnotator.cpp -SRCS_EXT+= Format/UnwrappedLineFormatter.cpp -SRCS_EXT+= Format/UnwrappedLineParser.cpp -SRCS_EXT+= Format/UsingDeclarationsSorter.cpp -SRCS_EXT+= Format/WhitespaceManager.cpp +SRCS_MIN+= Format/NamespaceEndCommentsFixer.cpp +SRCS_MIN+= Format/ObjCPropertyAttributeOrderFixer.cpp +SRCS_MIN+= Format/QualifierAlignmentFixer.cpp +SRCS_MIN+= Format/SortJavaScriptImports.cpp +SRCS_MIN+= Format/TokenAnalyzer.cpp +SRCS_MIN+= Format/TokenAnnotator.cpp +SRCS_MIN+= Format/UnwrappedLineFormatter.cpp +SRCS_MIN+= Format/UnwrappedLineParser.cpp +SRCS_MIN+= Format/UsingDeclarationsSorter.cpp +SRCS_MIN+= Format/WhitespaceManager.cpp SRCS_MIN+= Frontend/ASTConsumers.cpp SRCS_MIN+= Frontend/ASTMerge.cpp SRCS_MIN+= Frontend/ASTUnit.cpp @@ -824,10 +841,19 @@ SRCS_MIN+= Tooling/ArgumentsAdjusters.cpp SRCS_MIN+= Tooling/CommonOptionsParser.cpp SRCS_MIN+= Tooling/CompilationDatabase.cpp SRCS_MIN+= Tooling/Core/Replacement.cpp +SRCS_MIN+= Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +SRCS_MIN+= Tooling/DependencyScanning/DependencyScanningService.cpp +SRCS_MIN+= Tooling/DependencyScanning/DependencyScanningTool.cpp +SRCS_MIN+= Tooling/DependencyScanning/DependencyScanningWorker.cpp +SRCS_MIN+= Tooling/DependencyScanning/ModuleDepCollector.cpp +SRCS_MIN+= Tooling/ExpandResponseFilesCompilationDatabase.cpp SRCS_MIN+= Tooling/FileMatchTrie.cpp -SRCS_EXT+= Tooling/Inclusions/HeaderIncludes.cpp -SRCS_EXT+= Tooling/Inclusions/IncludeStyle.cpp +SRCS_MIN+= Tooling/GuessTargetAndModeCompilationDatabase.cpp +SRCS_MIN+= Tooling/Inclusions/HeaderIncludes.cpp +SRCS_MIN+= Tooling/Inclusions/IncludeStyle.cpp +SRCS_MIN+= Tooling/InterpolatingCompilationDatabase.cpp SRCS_MIN+= Tooling/JSONCompilationDatabase.cpp +SRCS_MIN+= Tooling/LocateToolCompilationDatabase.cpp SRCS_MIN+= Tooling/Refactoring.cpp SRCS_MIN+= Tooling/RefactoringCallbacks.cpp SRCS_MIN+= Tooling/Tooling.cpp @@ -844,6 +870,21 @@ SRCS_ALL+= ${SRCS_LDB} .endif SRCS+= ${SRCS_ALL:O} +LIBDEPS+= llvm + +.if defined(TOOLS_PREFIX) +LIBPRIV= +LIBEXT= a +.else +LIBPRIV= private +LIBEXT= so +.endif + +.for lib in ${LIBDEPS} +DPADD+= ${OBJTOP}/lib/clang/lib${lib}/lib${LIBPRIV}${lib}.${LIBEXT} +LDADD+= ${OBJTOP}/lib/clang/lib${lib}/lib${LIBPRIV}${lib}.${LIBEXT} +.endfor + clang/AST/AbstractBasicReader.inc: \ ${CLANG_SRCS}/include/clang/AST/PropertiesBase.td ${CLANG_TBLGEN} -gen-clang-basic-reader \ @@ -1299,6 +1340,4 @@ CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/} .include "../clang.build.mk" -INTERNALLIB= - .include <bsd.lib.mk> diff --git a/lib/clang/liblldb/Makefile b/lib/clang/liblldb/Makefile index 26edeb966992..a3ff8e367864 100644 --- a/lib/clang/liblldb/Makefile +++ b/lib/clang/liblldb/Makefile @@ -1,7 +1,13 @@ .include <bsd.init.mk> .include "../lldb.pre.mk" -LIB= lldb +PACKAGE= lldb +SHLIB_CXX= lldb +SHLIB_MAJOR= 19 +PRIVATELIB= + +SHARED_CXXFLAGS+= -UPIC # To avoid compile errors + SRCDIR= lldb/source CFLAGS+= -I${LLDB_SRCS}/include @@ -744,6 +750,19 @@ SRCS+= Utility/VMRange.cpp SRCS+= Utility/XcodeSDK.cpp SRCS+= Version/Version.cpp +LIBDEPS+= clang +LIBDEPS+= llvm + +LIBPRIV= private +LIBEXT= so + +.for lib in ${LIBDEPS} +DPADD+= ${OBJTOP}/lib/clang/lib${lib}/lib${LIBPRIV}${lib}.${LIBEXT} +LDADD+= ${OBJTOP}/lib/clang/lib${lib}/lib${LIBPRIV}${lib}.${LIBEXT} +.endfor + +LIBADD+= kvm + LLDB_TBLGEN?= lldb-tblgen CommandOptions.inc: ${LLDB_SRCS}/source/Commands/Options.td @@ -779,8 +798,6 @@ CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/} .include "../clang.build.mk" -INTERNALLIB= - # Building lldb's bindings requires swig, but we do not want to include it in # the FreeBSD base system (as a build tool) because it has non-trivial # dependencies. As a workaround we commit the generated file. Requires the diff --git a/lib/clang/libllvm/Makefile b/lib/clang/libllvm/Makefile index 455d32b6f329..e634a72b4f90 100644 --- a/lib/clang/libllvm/Makefile +++ b/lib/clang/libllvm/Makefile @@ -1,8 +1,22 @@ .include <bsd.init.mk> .include "../llvm.pre.mk" +.if defined(TOOLS_PREFIX) +# Build static library during cross-tools stage LIB= llvm INTERNALLIB= +.else +PACKAGE= clang +SHLIB_CXX= llvm +SHLIB_MAJOR= 19 +PRIVATELIB= +.if ${MACHINE} == "powerpc" +# Work around "relocation R_PPC_GOT16 out of range" errors +PICFLAG= -fPIC +.endif +.endif + +SHARED_CXXFLAGS+= -UPIC # To avoid compile errors CFLAGS+= -I${.OBJDIR} CFLAGS+= -I${SRCTOP}/sys/contrib/zstd/lib @@ -139,7 +153,6 @@ SRCS_MIN+= Analysis/RegionPass.cpp SRCS_MIN+= Analysis/RegionPrinter.cpp SRCS_MIN+= Analysis/ReplayInlineAdvisor.cpp SRCS_MIN+= Analysis/ScalarEvolution.cpp -SRCS_MIN+= Analysis/ScalarEvolution.cpp SRCS_MIN+= Analysis/ScalarEvolutionAliasAnalysis.cpp SRCS_MIN+= Analysis/ScalarEvolutionDivision.cpp SRCS_MIN+= Analysis/ScalarEvolutionNormalization.cpp @@ -509,24 +522,24 @@ SRCS_EXT+= DWP/DWP.cpp SRCS_EXT+= DWP/DWPError.cpp SRCS_MIW+= DebugInfo/BTF/BTFContext.cpp SRCS_MIW+= DebugInfo/BTF/BTFParser.cpp -SRCS_EXT+= DebugInfo/CodeView/AppendingTypeTableBuilder.cpp +SRCS_MIN+= DebugInfo/CodeView/AppendingTypeTableBuilder.cpp SRCS_MIN+= DebugInfo/CodeView/CVSymbolVisitor.cpp SRCS_MIN+= DebugInfo/CodeView/CVTypeVisitor.cpp SRCS_MIN+= DebugInfo/CodeView/CodeViewError.cpp SRCS_MIN+= DebugInfo/CodeView/CodeViewRecordIO.cpp SRCS_MIN+= DebugInfo/CodeView/ContinuationRecordBuilder.cpp SRCS_MIN+= DebugInfo/CodeView/DebugChecksumsSubsection.cpp -SRCS_EXT+= DebugInfo/CodeView/DebugCrossExSubsection.cpp -SRCS_EXT+= DebugInfo/CodeView/DebugCrossImpSubsection.cpp +SRCS_MIN+= DebugInfo/CodeView/DebugCrossExSubsection.cpp +SRCS_MIN+= DebugInfo/CodeView/DebugCrossImpSubsection.cpp SRCS_MIN+= DebugInfo/CodeView/DebugFrameDataSubsection.cpp SRCS_MIN+= DebugInfo/CodeView/DebugInlineeLinesSubsection.cpp SRCS_MIN+= DebugInfo/CodeView/DebugLinesSubsection.cpp SRCS_MIN+= DebugInfo/CodeView/DebugStringTableSubsection.cpp -SRCS_MIW+= DebugInfo/CodeView/DebugSubsection.cpp -SRCS_EXT+= DebugInfo/CodeView/DebugSubsectionRecord.cpp -SRCS_EXT+= DebugInfo/CodeView/DebugSubsectionVisitor.cpp -SRCS_EXT+= DebugInfo/CodeView/DebugSymbolRVASubsection.cpp -SRCS_EXT+= DebugInfo/CodeView/DebugSymbolsSubsection.cpp +SRCS_MIN+= DebugInfo/CodeView/DebugSubsection.cpp +SRCS_MIN+= DebugInfo/CodeView/DebugSubsectionRecord.cpp +SRCS_MIN+= DebugInfo/CodeView/DebugSubsectionVisitor.cpp +SRCS_MIN+= DebugInfo/CodeView/DebugSymbolRVASubsection.cpp +SRCS_MIN+= DebugInfo/CodeView/DebugSymbolsSubsection.cpp SRCS_MIN+= DebugInfo/CodeView/EnumTables.cpp SRCS_MIN+= DebugInfo/CodeView/Formatters.cpp SRCS_MIN+= DebugInfo/CodeView/GlobalTypeTableBuilder.cpp @@ -540,7 +553,7 @@ SRCS_EXT+= DebugInfo/CodeView/StringsAndChecksums.cpp SRCS_MIN+= DebugInfo/CodeView/SymbolDumper.cpp SRCS_MIN+= DebugInfo/CodeView/SymbolRecordHelpers.cpp SRCS_MIN+= DebugInfo/CodeView/SymbolRecordMapping.cpp -SRCS_EXT+= DebugInfo/CodeView/SymbolSerializer.cpp +SRCS_MIN+= DebugInfo/CodeView/SymbolSerializer.cpp SRCS_MIN+= DebugInfo/CodeView/TypeDumpVisitor.cpp SRCS_MIN+= DebugInfo/CodeView/TypeHashing.cpp SRCS_MIN+= DebugInfo/CodeView/TypeIndex.cpp @@ -549,37 +562,37 @@ SRCS_EXT+= DebugInfo/CodeView/TypeRecordHelpers.cpp SRCS_MIN+= DebugInfo/CodeView/TypeRecordMapping.cpp SRCS_MIN+= DebugInfo/CodeView/TypeStreamMerger.cpp SRCS_MIN+= DebugInfo/CodeView/TypeTableCollection.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFAcceleratorTable.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFAddressRange.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFCompileUnit.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFContext.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFDataExtractor.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFDebugAbbrev.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFDebugAddr.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFDebugArangeSet.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFDebugAranges.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFDebugFrame.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFDebugInfoEntry.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFDebugLine.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFDebugLoc.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFDebugMacro.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFDebugPubTable.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFDebugRangeList.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFDebugRnglists.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFDie.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFAcceleratorTable.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFAddressRange.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFCompileUnit.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFContext.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFDataExtractor.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFDebugAbbrev.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFDebugAddr.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFDebugArangeSet.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFDebugAranges.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFDebugFrame.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFDebugInfoEntry.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFDebugLine.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFDebugLoc.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFDebugMacro.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFDebugPubTable.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFDebugRangeList.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFDebugRnglists.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFDie.cpp SRCS_MIN+= DebugInfo/DWARF/DWARFExpression.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFFormValue.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFGdbIndex.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFListTable.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFTypePrinter.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFTypeUnit.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFUnit.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFUnitIndex.cpp -SRCS_MIW+= DebugInfo/DWARF/DWARFVerifier.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFFormValue.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFGdbIndex.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFListTable.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFTypePrinter.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFTypeUnit.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFUnit.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFUnitIndex.cpp +SRCS_MIN+= DebugInfo/DWARF/DWARFVerifier.cpp SRCS_MIN+= DebugInfo/MSF/MSFBuilder.cpp SRCS_MIN+= DebugInfo/MSF/MSFCommon.cpp -SRCS_EXT+= DebugInfo/MSF/MSFError.cpp +SRCS_MIN+= DebugInfo/MSF/MSFError.cpp SRCS_MIN+= DebugInfo/MSF/MappedBlockStream.cpp SRCS_EXT+= DebugInfo/PDB/GenericError.cpp SRCS_EXT+= DebugInfo/PDB/IPDBSourceFile.cpp @@ -867,7 +880,7 @@ SRCS_MIN+= LTO/LTO.cpp SRCS_MIN+= LTO/LTOBackend.cpp SRCS_EXL+= LTO/LTOCodeGenerator.cpp SRCS_EXL+= LTO/LTOModule.cpp -SRCS_EXL+= LTO/SummaryBasedOptimizations.cpp +SRCS_MIN+= LTO/SummaryBasedOptimizations.cpp SRCS_EXL+= LTO/ThinLTOCodeGenerator.cpp SRCS_MIN+= LTO/UpdateCompilerUsed.cpp SRCS_MIN+= Linker/IRMover.cpp @@ -892,7 +905,7 @@ SRCS_MIN+= MC/MCContext.cpp SRCS_MIN+= MC/MCDXContainerStreamer.cpp SRCS_MIN+= MC/MCDXContainerWriter.cpp SRCS_XDL+= MC/MCDisassembler/Disassembler.cpp -SRCS_XDW+= MC/MCDisassembler/MCDisassembler.cpp +SRCS_MIN+= MC/MCDisassembler/MCDisassembler.cpp SRCS_XDW+= MC/MCDisassembler/MCExternalSymbolizer.cpp SRCS_MIN+= MC/MCDisassembler/MCRelocationInfo.cpp SRCS_XDW+= MC/MCDisassembler/MCSymbolizer.cpp @@ -1006,9 +1019,9 @@ SRCS_MIW+= ObjCopy/wasm/WasmWriter.cpp SRCS_MIN+= Object/Archive.cpp SRCS_MIN+= Object/ArchiveWriter.cpp SRCS_MIN+= Object/Binary.cpp -SRCS_MIW+= Object/BuildID.cpp +SRCS_MIN+= Object/BuildID.cpp SRCS_MIN+= Object/COFFImportFile.cpp -SRCS_MIW+= Object/COFFModuleDefinition.cpp +SRCS_MIN+= Object/COFFModuleDefinition.cpp SRCS_MIN+= Object/COFFObjectFile.cpp SRCS_MIN+= Object/Decompressor.cpp SRCS_MIN+= Object/ELF.cpp @@ -1018,31 +1031,34 @@ SRCS_MIW+= Object/FaultMapParser.cpp SRCS_MIN+= Object/IRObjectFile.cpp SRCS_MIN+= Object/IRSymtab.cpp SRCS_MIN+= Object/MachOObjectFile.cpp -SRCS_MIW+= Object/MachOUniversal.cpp +SRCS_MIN+= Object/MachOUniversal.cpp SRCS_MIW+= Object/MachOUniversalWriter.cpp -SRCS_MIW+= Object/Minidump.cpp +SRCS_MIN+= Object/Minidump.cpp SRCS_MIN+= Object/ModuleSymbolTable.cpp SRCS_EXT+= Object/Object.cpp SRCS_MIN+= Object/ObjectFile.cpp -SRCS_MIW+= Object/OffloadBinary.cpp +SRCS_MIN+= Object/OffloadBinary.cpp SRCS_MIN+= Object/RecordStreamer.cpp -SRCS_MIW+= Object/RelocationResolver.cpp +SRCS_MIN+= Object/RelocationResolver.cpp SRCS_MIW+= Object/SymbolSize.cpp SRCS_MIN+= Object/SymbolicFile.cpp -SRCS_MIW+= Object/TapiFile.cpp -SRCS_MIW+= Object/TapiUniversal.cpp +SRCS_MIN+= Object/TapiFile.cpp +SRCS_MIN+= Object/TapiUniversal.cpp SRCS_MIN+= Object/WasmObjectFile.cpp SRCS_MIW+= Object/WindowsMachineFlag.cpp SRCS_MIN+= Object/WindowsResource.cpp SRCS_MIN+= Object/XCOFFObjectFile.cpp SRCS_MIN+= ObjectYAML/COFFYAML.cpp -SRCS_EXT+= ObjectYAML/CodeViewYAMLDebugSections.cpp -SRCS_EXT+= ObjectYAML/CodeViewYAMLSymbols.cpp -SRCS_EXT+= ObjectYAML/CodeViewYAMLTypes.cpp +SRCS_MIN+= ObjectYAML/CodeViewYAMLDebugSections.cpp +SRCS_MIN+= ObjectYAML/CodeViewYAMLSymbols.cpp +SRCS_MIN+= ObjectYAML/CodeViewYAMLTypeHashing.cpp +SRCS_MIN+= ObjectYAML/CodeViewYAMLTypes.cpp +SRCS_MIN+= ObjectYAML/DWARFEmitter.cpp SRCS_MIN+= ObjectYAML/DWARFYAML.cpp +SRCS_MIN+= ObjectYAML/ELFEmitter.cpp SRCS_MIN+= ObjectYAML/ELFYAML.cpp SRCS_MIN+= ObjectYAML/MachOYAML.cpp -SRCS_EXT+= ObjectYAML/YAML.cpp +SRCS_MIN+= ObjectYAML/YAML.cpp SRCS_MIN+= Option/Arg.cpp SRCS_MIN+= Option/ArgList.cpp SRCS_MIN+= Option/OptTable.cpp @@ -1135,7 +1151,7 @@ SRCS_MIN+= Support/ErrorHandling.cpp SRCS_MIN+= Support/ExponentialBackoff.cpp SRCS_MIN+= Support/ExtensibleRTTI.cpp SRCS_MIN+= Support/FileCollector.cpp -SRCS_MIW+= Support/FileOutputBuffer.cpp +SRCS_MIN+= Support/FileOutputBuffer.cpp SRCS_MIN+= Support/FileUtilities.cpp SRCS_MIN+= Support/FloatingPointMode.cpp SRCS_MIN+= Support/FoldingSet.cpp @@ -1161,7 +1177,7 @@ SRCS_MIW+= Support/MSP430Attributes.cpp SRCS_MIN+= Support/ManagedStatic.cpp SRCS_MIN+= Support/MathExtras.cpp SRCS_MIN+= Support/MemAlloc.cpp -SRCS_MIW+= Support/Memory.cpp +SRCS_MIN+= Support/Memory.cpp SRCS_MIN+= Support/MemoryBuffer.cpp SRCS_MIN+= Support/MemoryBufferRef.cpp SRCS_MIN+= Support/NativeFormatting.cpp @@ -1200,7 +1216,7 @@ SRCS_MIN+= Support/SuffixTree.cpp SRCS_MIN+= Support/SuffixTreeNode.cpp SRCS_EXT+= Support/SystemUtils.cpp SRCS_LLD+= Support/TarWriter.cpp -SRCS_MIW+= Support/ThreadPool.cpp +SRCS_MIN+= Support/ThreadPool.cpp SRCS_MIN+= Support/Threading.cpp SRCS_MIN+= Support/TimeProfiler.cpp SRCS_MIN+= Support/Timer.cpp @@ -1695,21 +1711,22 @@ SRCS_MIN+= TargetParser/SubtargetFeature.cpp SRCS_MIN+= TargetParser/TargetParser.cpp SRCS_MIN+= TargetParser/Triple.cpp SRCS_MIN+= TargetParser/X86TargetParser.cpp -SRCS_MIW+= TextAPI/Architecture.cpp -SRCS_MIW+= TextAPI/ArchitectureSet.cpp +SRCS_MIN+= TextAPI/Architecture.cpp +SRCS_MIN+= TextAPI/ArchitectureSet.cpp SRCS_MIW+= TextAPI/BinaryReader/DylibReader.cpp -SRCS_MIW+= TextAPI/InterfaceFile.cpp -SRCS_MIW+= TextAPI/PackedVersion.cpp -SRCS_MIW+= TextAPI/Platform.cpp +SRCS_MIN+= TextAPI/InterfaceFile.cpp +SRCS_MIN+= TextAPI/PackedVersion.cpp +SRCS_MIN+= TextAPI/Platform.cpp SRCS_MIW+= TextAPI/RecordVisitor.cpp -SRCS_MIW+= TextAPI/Symbol.cpp -SRCS_MIW+= TextAPI/SymbolSet.cpp -SRCS_MIW+= TextAPI/Target.cpp -SRCS_MIW+= TextAPI/TextAPIError.cpp -SRCS_MIW+= TextAPI/TextStub.cpp -SRCS_MIW+= TextAPI/TextStubCommon.cpp -SRCS_MIW+= TextAPI/TextStubV5.cpp -SRCS_MIW+= TextAPI/Utils.cpp +SRCS_MIW+= TextAPI/RecordsSlice.cpp +SRCS_MIN+= TextAPI/Symbol.cpp +SRCS_MIN+= TextAPI/SymbolSet.cpp +SRCS_MIN+= TextAPI/Target.cpp +SRCS_MIN+= TextAPI/TextAPIError.cpp +SRCS_MIN+= TextAPI/TextStub.cpp +SRCS_MIN+= TextAPI/TextStubCommon.cpp +SRCS_MIN+= TextAPI/TextStubV5.cpp +SRCS_MIN+= TextAPI/Utils.cpp SRCS_MIN+= ToolDrivers/llvm-dlltool/DlltoolDriver.cpp SRCS_MIW+= ToolDrivers/llvm-lib/LibDriver.cpp SRCS_MIN+= Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp diff --git a/lib/clang/llvm.build.mk b/lib/clang/llvm.build.mk index 2520637e2d06..e88b2ff1033e 100644 --- a/lib/clang/llvm.build.mk +++ b/lib/clang/llvm.build.mk @@ -119,7 +119,7 @@ LDFLAGS+= -Wl,-m,elf64lriscv_fbsd .endif .endif -CXXSTD?= c++17 +CXXSTD= c++17 CXXFLAGS+= -fno-exceptions CXXFLAGS+= -fno-rtti .if ${.MAKE.OS} == "FreeBSD" || !defined(BOOTSTRAPPING) diff --git a/lib/csu/common/crtbegin.c b/lib/csu/common/crtbegin.c index 06fe990052f7..8ef9b8923c21 100644 --- a/lib/csu/common/crtbegin.c +++ b/lib/csu/common/crtbegin.c @@ -98,36 +98,3 @@ asm ( ".popsection \n" ); #endif - -/* - * Handler for gcj. These provide a _Jv_RegisterClasses function and fill - * out the .jcr section. We just need to call this function with a pointer - * to the appropriate section. - */ -extern void _Jv_RegisterClasses(void *) __weak_symbol; -static void register_classes(void) __used; - -static crt_func __JCR_LIST__[] __section(".jcr") __used = { }; - -#ifndef CTORS_CONSTRUCTORS -__attribute__((constructor)) -#endif -static void -register_classes(void) -{ - - if (_Jv_RegisterClasses != NULL && __JCR_LIST__[0] != 0) - _Jv_RegisterClasses(__JCR_LIST__); -} - -/* - * We can't use constructors when they use the .ctors section as they may be - * placed before __CTOR_LIST__. - */ -#ifdef CTORS_CONSTRUCTORS -asm ( - ".pushsection .init \n" - "\t" INIT_CALL_SEQ(register_classes) "\n" - ".popsection \n" -); -#endif diff --git a/lib/csu/common/crtend.c b/lib/csu/common/crtend.c index bf25c1d836a9..9eb75de2ef60 100644 --- a/lib/csu/common/crtend.c +++ b/lib/csu/common/crtend.c @@ -26,10 +26,6 @@ typedef void (*crt_func)(void); -static crt_func __JCR_END__[] __section(".jcr") __used = { - (crt_func)0 -}; - #ifdef HAVE_CTORS /* diff --git a/lib/csu/tests/Makefile b/lib/csu/tests/Makefile index c9a0e6eff5da..b76ef590c88f 100644 --- a/lib/csu/tests/Makefile +++ b/lib/csu/tests/Makefile @@ -4,6 +4,7 @@ SUBDIR= dso TESTS_SUBDIRS= dynamic TESTS_SUBDIRS+= dynamiclib TESTS_SUBDIRS+= dynamicpie +TESTS_SUBDIRS+= errno TESTS_SUBDIRS+= static SUBDIR_DEPEND_dynamiclib=dso diff --git a/lib/csu/tests/dso/Makefile b/lib/csu/tests/dso/Makefile index 6c1d00e9fb58..431168de0328 100644 --- a/lib/csu/tests/dso/Makefile +++ b/lib/csu/tests/dso/Makefile @@ -1,4 +1,6 @@ .PATH: ${.CURDIR:H} + +PACKAGE= tests SHLIB= h_csu SHLIB_NAME= libh_csu.so SHLIB_MAJOR= 1 diff --git a/lib/csu/tests/errno/Makefile b/lib/csu/tests/errno/Makefile new file mode 100644 index 000000000000..eae54a936294 --- /dev/null +++ b/lib/csu/tests/errno/Makefile @@ -0,0 +1,18 @@ +PLAIN_TESTS_C= errno_test \ + errno_static_test \ + errno_thr_test \ + errno_thr_static_test + +SRCS.errno_static_test= errno_test.c +LDFLAGS.errno_static_test= -static + +SRCS.errno_thr_test= errno_test.c +LIBADD.errno_thr_test= pthread + +SRCS.errno_thr_static_test= errno_test.c +LDFLAGS.errno_thr_static_test= -static +LIBADD.errno_thr_static_test= pthread + +MK_PIE:= no + +.include <bsd.test.mk> diff --git a/lib/csu/tests/errno/errno_test.c b/lib/csu/tests/errno/errno_test.c new file mode 100644 index 000000000000..d190c7fd2959 --- /dev/null +++ b/lib/csu/tests/errno/errno_test.c @@ -0,0 +1,23 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Mark Johnston <markj@FreeBSD.org> + */ + +#include <errno.h> +#include <stdlib.h> + +static void __attribute__((constructor)) +f(void) +{ + errno = 42; +} + +int +main(void) +{ + /* errno must be zero upon program startup. */ + if (errno != 0) + exit(1); + exit(0); +} diff --git a/lib/csu/tests/init_test.c b/lib/csu/tests/init_test.c index 47bd9b7e64d7..2d4484735f76 100644 --- a/lib/csu/tests/init_test.c +++ b/lib/csu/tests/init_test.c @@ -38,9 +38,6 @@ typedef void (*func_ptr)(void); -extern volatile int jcr_run; -extern const func_ptr *jcr_ptr; -extern const void *jcr_func_ptr; extern volatile int ctors_run; extern volatile int preinit_array_run; extern volatile int preinit_array_state; @@ -48,37 +45,11 @@ extern volatile int init_array_run; extern volatile int init_array_state; #ifndef DSO_BASE -volatile int jcr_run; -const func_ptr *jcr_ptr; volatile int ctors_run; volatile int preinit_array_run; volatile int preinit_array_state = -1; volatile int init_array_run; volatile int init_array_state = -1; - -void _Jv_RegisterClasses(const func_ptr *); - -__section(".jcr") __used static func_ptr jcr_func = (func_ptr)1; -const void *jcr_func_ptr = &jcr_func; - -void -_Jv_RegisterClasses(const func_ptr *jcr) -{ - - jcr_run = 1; - jcr_ptr = jcr; -} -#endif - -#ifndef DSO_LIB -ATF_TC_WITHOUT_HEAD(jcr_test); -ATF_TC_BODY(jcr_test, tc) -{ - - ATF_REQUIRE_MSG(jcr_run == 1, ".jcr not run"); - ATF_REQUIRE_MSG(jcr_ptr == jcr_func_ptr, - "Incorrect pointer passed to _Jv_RegisterClasses"); -} #endif #ifndef DSO_BASE @@ -160,7 +131,6 @@ ATF_TC_BODY(init_array_test, tc) ATF_TP_ADD_TCS(tp) { - ATF_TP_ADD_TC(tp, jcr_test); ATF_TP_ADD_TC(tp, ctors_test); ATF_TP_ADD_TC(tp, preinit_array_test); ATF_TP_ADD_TC(tp, init_array_test); diff --git a/lib/geom/eli/geli.8 b/lib/geom/eli/geli.8 index d34e15dc4ad8..876caf67ab40 100644 --- a/lib/geom/eli/geli.8 +++ b/lib/geom/eli/geli.8 @@ -857,7 +857,7 @@ must allocate a buffer for every write operation, used when performing encryption. This sysctl reports the maximum size in bytes for which geli will perform the allocation using -.Xr UMA 9 , +.Xr uma 9 , as opposed to .Xr malloc 9 . .It Va kern.geom.eli.visible_passphrase : No 0 diff --git a/lib/geom/raid/graid.8 b/lib/geom/raid/graid.8 index f722fd5c17bd..4ef0cd22e703 100644 --- a/lib/geom/raid/graid.8 +++ b/lib/geom/raid/graid.8 @@ -275,7 +275,7 @@ NVIDIA metadata format does not support volumes above 2TiB. .Sh SYSCTL VARIABLES The following .Xr sysctl 8 -variable can be used to control the behavior of the +variables can be used to control the behavior of the .Nm RAID GEOM class. .Bl -tag -width indent diff --git a/lib/lib80211/regdomain.xml b/lib/lib80211/regdomain.xml index 557af0349cb0..16b74445f429 100644 --- a/lib/lib80211/regdomain.xml +++ b/lib/lib80211/regdomain.xml @@ -494,6 +494,10 @@ <flags>IEEE80211_CHAN_PASSIVE</flags> <flags>IEEE80211_CHAN_DFS</flags> </band> + <band> + <freqband ref="A20_5745_5865"/> + <maxpower>13</maxpower> + </band> </netband> <netband mode="11ng"> <band> @@ -548,6 +552,14 @@ <flags>IEEE80211_CHAN_PASSIVE</flags> <flags>IEEE80211_CHAN_DFS</flags> </band> + <band> + <freqband ref="NA20_5745_5865"/> + <maxpower>13</maxpower> + </band> + <band> + <freqband ref="NA40_5745_5845"/> + <maxpower>13</maxpower> + </band> </netband> <netband mode="11ac"> <!-- 5150-5250/80, 200 mW, indoor --> @@ -645,7 +657,7 @@ <flags>IEEE80211_CHAN_DFS</flags> </band> <band> - <freqband ref="AC2_5745_5805_40"/> + <freqband ref="AC2_5745_5845_40"/> <maxpower>13</maxpower> <flags>IEEE80211_CHAN_HT40</flags> <flags>IEEE80211_CHAN_VHT40</flags> @@ -658,13 +670,6 @@ <flags>IEEE80211_CHAN_VHT80</flags> <flags>IEEE80211_CHAN_DFS</flags> </band> - <band> - <freqband ref="AC2_5745_5885_160"/> - <maxpower>13</maxpower> - <flags>IEEE80211_CHAN_HT40</flags> - <flags>IEEE80211_CHAN_VHT160</flags> - <flags>IEEE80211_CHAN_DFS</flags> - </band> </netband> </rd> @@ -1187,6 +1192,202 @@ </netband> </rd> +<rd id="taiwan"> + <name>TAIWAN</name> + <netband mode="11b"> + <band> + <freqband ref="F1_2412_2472"/> + <maxpower>30</maxpower> + <flags>IEEE80211_CHAN_B</flags> + </band> + </netband> + + <netband mode="11g"> + <band> + <freqband ref="F1_2412_2472"/> + <maxpower>30</maxpower> + <flags>IEEE80211_CHAN_G</flags> + </band> + </netband> + + <netband mode="11ng"> + <band> + <freqband ref="F1_2412_2472"/> + <maxpower>30</maxpower> + <flags>IEEE80211_CHAN_G</flags> + <flags>IEEE80211_CHAN_HT20</flags> + </band> + <band> + <freqband ref="H4_2412_2472"/> + <maxpower>30</maxpower> + <flags>IEEE80211_CHAN_G</flags> + <flags>IEEE80211_CHAN_HT40</flags> + </band> + </netband> + + <netband mode="11a"> + <band> + <freqband ref="F1_5160_5240"/> + <maxpower>23</maxpower> + </band> + <band> + <freqband ref="F1_5260_5340"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_DFS</flags> + </band> + <band> + <freqband ref="F1_5480_5720"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_DFS</flags> + </band> + <band> + <freqband ref="F1_5745_5845"/> + <maxpower>30</maxpower> + </band> + </netband> + + <netband mode="11na"> + <band> + <freqband ref="F1_5160_5240"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_HT20</flags> + </band> + <band> + <freqband ref="H4_5180_5240"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_HT40</flags> + </band> + + <band> + <freqband ref="F1_5260_5340"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_HT20</flags> + <flags>IEEE80211_CHAN_DFS</flags> + </band> + <band> + <freqband ref="H4_5260_5320"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_HT40</flags> + <flags>IEEE80211_CHAN_DFS</flags> + </band> + + <band> + <freqband ref="F1_5480_5720"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_HT20</flags> + <flags>IEEE80211_CHAN_DFS</flags> + </band> + <band> + <freqband ref="H4_5500_5720"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_HT40</flags> + <flags>IEEE80211_CHAN_DFS</flags> + </band> + + <band> + <freqband ref="F1_5745_5845"/> + <maxpower>30</maxpower> + <flags>IEEE80211_CHAN_HT20</flags> + </band> + <band> + <freqband ref="H4_5745_5845"/> + <maxpower>30</maxpower> + <flags>IEEE80211_CHAN_HT40</flags> + </band> + </netband> + + <netband mode="11ac"> + <band> + <freqband ref="AC2_5160_5240_20"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_HT20</flags> + <flags>IEEE80211_CHAN_VHT20</flags> + </band> + <band> + <freqband ref="AC2_5180_5240_40"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_HT40</flags> + <flags>IEEE80211_CHAN_VHT40</flags> + </band> + <band> + <freqband ref="AC2_5180_5240_80"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_HT40</flags> + <flags>IEEE80211_CHAN_VHT80</flags> + </band> + + <band> + <freqband ref="AC2_5260_5340_20"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_HT20</flags> + <flags>IEEE80211_CHAN_VHT20</flags> + <flags>IEEE80211_CHAN_DFS</flags> + </band> + <band> + <freqband ref="AC2_5260_5320_40"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_HT40</flags> + <flags>IEEE80211_CHAN_VHT40</flags> + <flags>IEEE80211_CHAN_DFS</flags> + </band> + <band> + <freqband ref="AC2_5260_5320_80"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_HT40</flags> + <flags>IEEE80211_CHAN_VHT80</flags> + <flags>IEEE80211_CHAN_DFS</flags> + </band> + + <band> + <freqband ref="AC2_5480_5700_20"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_HT20</flags> + <flags>IEEE80211_CHAN_VHT20</flags> + <flags>IEEE80211_CHAN_DFS</flags> + </band> + <band> + <freqband ref="AC2_5500_5720_40"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_HT40</flags> + <flags>IEEE80211_CHAN_VHT40</flags> + <flags>IEEE80211_CHAN_DFS</flags> + </band> + <band> + <freqband ref="AC2_5500_5720_80"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_HT40</flags> + <flags>IEEE80211_CHAN_VHT80</flags> + <flags>IEEE80211_CHAN_DFS</flags> + </band> + <band> + <freqband ref="AC2_5500_5640_160"/> + <maxpower>23</maxpower> + <flags>IEEE80211_CHAN_HT40</flags> + <flags>IEEE80211_CHAN_VHT160</flags> + <flags>IEEE80211_CHAN_DFS</flags> + </band> + + <band> + <freqband ref="AC2_5745_5845_20"/> + <maxpower>30</maxpower> + <flags>IEEE80211_CHAN_HT20</flags> + <flags>IEEE80211_CHAN_VHT20</flags> + </band> + <band> + <freqband ref="AC2_5745_5845_40"/> + <maxpower>30</maxpower> + <flags>IEEE80211_CHAN_HT40</flags> + <flags>IEEE80211_CHAN_VHT40</flags> + </band> + <band> + <freqband ref="AC2_5745_5805_80"/> + <maxpower>30</maxpower> + <flags>IEEE80211_CHAN_HT40</flags> + <flags>IEEE80211_CHAN_VHT80</flags> + </band> + </netband> +</rd> + <!-- Rest Of World --> <rd id="row"> @@ -1781,7 +1982,7 @@ <isocc>760</isocc> <name>Syria</name> <rd ref="none"/> </country> <country id="TW"> - <isocc>158</isocc> <name>Taiwan</name> <rd ref="row"/> + <isocc>158</isocc> <name>Taiwan</name> <rd ref="taiwan"/> </country> <country id="TH"> <isocc>764</isocc> <name>Thailand</name> <rd ref="none"/> @@ -1904,6 +2105,11 @@ <flags>IEEE80211_CHAN_A</flags> </freqband> <!-- 5150-5250/80 --> +<freqband id="F1_5160_5240"> + <freqstart>5120</freqstart> <freqend>5240</freqend> + <chanwidth>20</chanwidth> <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> <freqband id="AC2_5160_5240_20"> <freqstart>5160</freqstart> <freqend>5240</freqend> <chanwidth>20</chanwidth> <chansep>20</chansep> @@ -1925,6 +2131,11 @@ <flags>IEEE80211_CHAN_A</flags> </freqband> <!-- 5250-5350/80 --> +<freqband id="F1_5260_5340"> + <freqstart>5260</freqstart> <freqend>5340</freqend> + <chanwidth>20</chanwidth> <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> <freqband id="AC2_5260_5340_20"> <freqstart>5260</freqstart> <freqend>5340</freqend> <chanwidth>20</chanwidth> <chansep>20</chansep> @@ -1941,6 +2152,11 @@ <flags>IEEE80211_CHAN_A</flags> </freqband> <!-- 5470-5725/160 --> +<freqband id="F1_5480_5720"> + <freqstart>5480</freqstart> <freqend>5720</freqend> + <chanwidth>20</chanwidth> <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> <freqband id="AC2_5480_5700_20"> <freqstart>5480</freqstart> <freqend>5700</freqend> <chanwidth>20</chanwidth> <chansep>20</chansep> @@ -1961,7 +2177,38 @@ <chanwidth>160</chanwidth> <chansep>20</chansep> <flags>IEEE80211_CHAN_A</flags> </freqband> +<!-- 5500-5720/80 --> +<freqband id="AC2_5500_5720_40"> + <freqstart>5500</freqstart> <freqend>5720</freqend> + <chanwidth>40</chanwidth> <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> +<freqband id="AC2_5500_5720_80"> + <freqstart>5500</freqstart> <freqend>5720</freqend> + <chanwidth>80</chanwidth> <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> <!-- 5725-5875/80 short range --> +<freqband id="F1_5745_5825"> + <freqstart>5745</freqstart> <freqend>5825</freqend> + <chanwidth>20</chanwidth> <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> +<freqband id="F1_5745_5845"> + <freqstart>5745</freqstart> <freqend>5845</freqend> + <chanwidth>20</chanwidth> <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> +<freqband id="H4_5745_5845"> + <freqstart>5745</freqstart> <freqend>5845</freqend> + <chanwidth>40</chanwidth> <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> +<freqband id="AC2_5745_5845_20"> + <freqstart>5745</freqstart> <freqend>5845</freqend> + <chanwidth>20</chanwidth> <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> <freqband id="AC2_5745_5865_20"> <freqstart>5745</freqstart> <freqend>5865</freqend> <chanwidth>20</chanwidth> <chansep>20</chansep> @@ -1972,6 +2219,11 @@ <chanwidth>40</chanwidth> <chansep>20</chansep> <flags>IEEE80211_CHAN_A</flags> </freqband> +<freqband id="AC2_5745_5845_40"> + <freqstart>5745</freqstart> <freqend>5845</freqend> + <chanwidth>40</chanwidth> <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> <freqband id="AC2_5745_5805_80"> <freqstart>5745</freqstart> <freqend>5805</freqend> <chanwidth>80</chanwidth> <chansep>20</chansep> @@ -2027,6 +2279,11 @@ <chanwidth>20</chanwidth> <chansep>20</chansep> <flags>IEEE80211_CHAN_A</flags> </freqband> +<freqband id="H4_5500_5720"> + <freqstart>5500</freqstart> <freqend>5720</freqend> + <chanwidth>40</chanwidth> <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> <freqband id="H4_5500_5580"> <freqstart>5500</freqstart> <freqend>5580</freqend> <chanwidth>40</chanwidth> <chansep>20</chansep> @@ -2052,6 +2309,29 @@ <chanwidth>20</chanwidth> <chansep>20</chansep> <flags>IEEE80211_CHAN_A</flags> </freqband> +<freqband id="A20_5745_5865"> + <freqstart>5745</freqstart> + <freqend>5865</freqend> + <chanwidth>20</chanwidth> + <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> +</freqband> +<freqband id="NA20_5745_5865"> + <freqstart>5745</freqstart> + <freqend>5865</freqend> + <chanwidth>20</chanwidth> + <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> + <flags>IEEE80211_CHAN_HT20</flags> +</freqband> +<freqband id="NA40_5745_5845"> + <freqstart>5745</freqstart> + <freqend>5845</freqend> + <chanwidth>40</chanwidth> + <chansep>20</chansep> + <flags>IEEE80211_CHAN_A</flags> + <flags>IEEE80211_CHAN_HT40</flags> +</freqband> <freqband id="F1_5660_5700"> <freqstart>5660</freqstart> <freqend>5700</freqend> <chanwidth>20</chanwidth> <chansep>20</chansep> diff --git a/lib/libarchive/Makefile b/lib/libarchive/Makefile index a68b938ca978..fed73c388318 100644 --- a/lib/libarchive/Makefile +++ b/lib/libarchive/Makefile @@ -42,11 +42,11 @@ SRCS= archive_acl.c \ archive_entry_stat.c \ archive_entry_strmode.c \ archive_entry_xattr.c \ - archive_getdate.c \ archive_hmac.c \ archive_match.c \ archive_options.c \ archive_pack_dev.c \ + archive_parse_date.c \ archive_pathmatch.c \ archive_ppmd7.c \ archive_ppmd8.c \ @@ -101,6 +101,7 @@ SRCS= archive_acl.c \ archive_read_support_format_zip.c \ archive_string.c \ archive_string_sprintf.c \ + archive_time.c \ archive_util.c \ archive_version_details.c \ archive_virtual.c \ diff --git a/lib/libarchive/tests/Makefile b/lib/libarchive/tests/Makefile index 0562197e6936..07c5fe24dd30 100644 --- a/lib/libarchive/tests/Makefile +++ b/lib/libarchive/tests/Makefile @@ -17,6 +17,7 @@ PROGS+= libarchive_test CFLAGS+= -I${.CURDIR} -I${.CURDIR:H} -I${.OBJDIR} CFLAGS+= -I${_LIBARCHIVEDIR}/libarchive -I${_LIBARCHIVEDIR}/libarchive/test CFLAGS+= -I${_LIBARCHIVEDIR}/test_utils +CFLAGS+= -I${SRCTOP}/sys/contrib/zstd/lib CFLAGS.test_utils.c+= -Wno-cast-align @@ -38,11 +39,11 @@ TESTS_SRCS= \ test_archive_clear_error.c \ test_archive_cmdline.c \ test_archive_digest.c \ - test_archive_getdate.c \ test_archive_match_time.c \ test_archive_match_owner.c \ test_archive_match_path.c \ test_archive_pathmatch.c \ + test_archive_parse_date.c \ test_archive_read.c \ test_archive_read_add_passphrase.c \ test_archive_read_close_twice.c \ @@ -72,6 +73,7 @@ TESTS_SRCS= \ test_compat_bzip2.c \ test_compat_cpio.c \ test_compat_gtar.c \ + test_compat_gtar_large.c \ test_compat_gzip.c \ test_compat_lz4.c \ test_compat_lzip.c \ @@ -148,7 +150,9 @@ TESTS_SRCS= \ test_read_format_gtar_filename.c \ test_read_format_gtar_gz.c \ test_read_format_gtar_lzma.c \ + test_read_format_gtar_redundant_L.c \ test_read_format_gtar_sparse.c \ + test_read_format_gtar_sparse_length.c \ test_read_format_gtar_sparse_skip_entry.c \ test_read_format_huge_rpm.c \ test_read_format_iso_Z.c \ @@ -178,6 +182,7 @@ TESTS_SRCS= \ test_read_format_rar_encryption_partially.c \ test_read_format_rar_filter.c \ test_read_format_rar_invalid1.c \ + test_read_format_rar_overflow.c \ test_read_format_raw.c \ test_read_format_tar.c \ test_read_format_tar_concatenated.c \ @@ -186,7 +191,10 @@ TESTS_SRCS= \ test_read_format_tar_empty_with_gnulabel.c \ test_read_format_tar_filename.c \ test_read_format_tar_invalid_pax_size.c \ + test_read_format_tar_mac_metadata.c \ + test_read_format_tar_pax_g_large.c \ test_read_format_tar_pax_large_attr.c \ + test_read_format_tar_pax_negative_time.c \ test_read_format_tbz.c \ test_read_format_tgz.c \ test_read_format_tlz.c \ @@ -219,6 +227,7 @@ TESTS_SRCS= \ test_read_format_zip_with_invalid_traditional_eocd.c \ test_read_format_zip_zip64.c \ test_read_large.c \ + test_read_pax_empty_val_no_nl.c \ test_read_pax_xattr_rht_security_selinux.c \ test_read_pax_xattr_schily.c \ test_read_pax_truncated.c \ @@ -287,6 +296,7 @@ TESTS_SRCS= \ test_write_format_mtree_classic_indent.c \ test_write_format_mtree_fflags.c \ test_write_format_mtree_no_separator.c \ + test_write_format_mtree_preset_digests.c \ test_write_format_mtree_quoted_filename.c \ test_write_format_pax.c \ test_write_format_raw.c \ @@ -303,6 +313,9 @@ TESTS_SRCS= \ test_write_format_xar_empty.c \ test_write_format_zip.c \ test_write_format_zip_compression_store.c \ + test_write_format_zip_compression_zstd.c \ + test_write_format_zip_compression_bzip2.c \ + test_write_format_zip_compression_lzmaxz.c \ test_write_format_zip_empty.c \ test_write_format_zip_empty_zip64.c \ test_write_format_zip_entry_size_unset.c \ @@ -447,6 +460,7 @@ ${PACKAGE}FILES+= test_read_format_7zip_bcj2_copy_2.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_bcj2_copy_lzma.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_bcj2_deflate.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_deflate_arm64.7z.uu +${PACKAGE}FILES+= test_read_format_7zip_deflate_powerpc.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_bcj2_lzma1_1.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_bcj2_lzma1_2.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_bcj2_lzma2_1.7z.uu @@ -476,16 +490,23 @@ ${PACKAGE}FILES+= test_read_format_7zip_lzma1_lzma2.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_lzma2.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_lzma2_arm.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_lzma2_arm64.7z.uu +${PACKAGE}FILES+= test_read_format_7zip_lzma2_powerpc.7z.uu +${PACKAGE}FILES+= test_read_format_7zip_lzma2_riscv.7z.uu +${PACKAGE}FILES+= test_read_format_7zip_lzma2_sparc.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_malformed.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_malformed2.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_packinfo_digests.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_ppmd.7z.uu +${PACKAGE}FILES+= test_read_format_7zip_sfx_elf.elf.uu +${PACKAGE}FILES+= test_read_format_7zip_sfx_modified_pe.exe.uu +${PACKAGE}FILES+= test_read_format_7zip_sfx_pe.exe.uu ${PACKAGE}FILES+= test_read_format_7zip_solid_zstd.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_symbolic_name.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_zstd.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_zstd_arm.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_zstd_bcj.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_zstd_nobcj.7z.uu +${PACKAGE}FILES+= test_read_format_7zip_zstd_sparc.7z.uu ${PACKAGE}FILES+= test_read_format_7zip_win_attrib.7z.uu ${PACKAGE}FILES+= test_read_format_ar.ar.uu ${PACKAGE}FILES+= test_read_format_cab_1.cab.uu @@ -504,12 +525,14 @@ ${PACKAGE}FILES+= test_read_format_cpio_svr4_gzip_rpm.rpm.uu ${PACKAGE}FILES+= test_read_format_gtar_filename_cp866.tar.Z.uu ${PACKAGE}FILES+= test_read_format_gtar_filename_eucjp.tar.Z.uu ${PACKAGE}FILES+= test_read_format_gtar_filename_koi8r.tar.Z.uu +${PACKAGE}FILES+= test_read_format_gtar_redundant_L.tar.Z.uu ${PACKAGE}FILES+= test_read_format_gtar_sparse_1_13.tar.uu ${PACKAGE}FILES+= test_read_format_gtar_sparse_1_17.tar.uu ${PACKAGE}FILES+= test_read_format_gtar_sparse_1_17_posix00.tar.uu ${PACKAGE}FILES+= test_read_format_gtar_sparse_1_17_posix01.tar.uu ${PACKAGE}FILES+= test_read_format_gtar_sparse_1_17_posix10.tar.uu ${PACKAGE}FILES+= test_read_format_gtar_sparse_1_17_posix10_modified.tar.uu +${PACKAGE}FILES+= test_read_format_gtar_sparse_length.tar.Z.uu ${PACKAGE}FILES+= test_read_format_gtar_sparse_skip_entry.tar.Z.uu ${PACKAGE}FILES+= test_read_format_huge_rpm.rpm.uu ${PACKAGE}FILES+= test_read_format_iso.iso.Z.uu @@ -550,6 +573,7 @@ ${PACKAGE}FILES+= test_read_format_rar_compress_normal.rar.uu ${PACKAGE}FILES+= test_read_format_rar_encryption_data.rar.uu ${PACKAGE}FILES+= test_read_format_rar_encryption_header.rar.uu ${PACKAGE}FILES+= test_read_format_rar_encryption_partially.rar.uu +${PACKAGE}FILES+= test_read_format_rar_endarc_huge.rar.uu ${PACKAGE}FILES+= test_read_format_rar_filter.rar.uu ${PACKAGE}FILES+= test_read_format_rar_invalid1.rar.uu ${PACKAGE}FILES+= test_read_format_rar_multi_lzss_blocks.rar.uu @@ -557,12 +581,15 @@ ${PACKAGE}FILES+= test_read_format_rar_multivolume.part0001.rar.uu ${PACKAGE}FILES+= test_read_format_rar_multivolume.part0002.rar.uu ${PACKAGE}FILES+= test_read_format_rar_multivolume.part0003.rar.uu ${PACKAGE}FILES+= test_read_format_rar_multivolume.part0004.rar.uu +${PACKAGE}FILES+= test_read_format_rar_newsub_huge.rar.uu ${PACKAGE}FILES+= test_read_format_rar_noeof.rar.uu +${PACKAGE}FILES+= test_read_format_rar_overflow.rar.uu ${PACKAGE}FILES+= test_read_format_rar_ppmd_lzss_conversion.rar.uu ${PACKAGE}FILES+= test_read_format_rar_ppmd_use_after_free.rar.uu ${PACKAGE}FILES+= test_read_format_rar_ppmd_use_after_free2.rar.uu ${PACKAGE}FILES+= test_read_format_rar_sfx.exe.uu ${PACKAGE}FILES+= test_read_format_rar_subblock.rar.uu +${PACKAGE}FILES+= test_read_format_rar_symlink_huge.rar.uu ${PACKAGE}FILES+= test_read_format_rar_unicode.rar.uu ${PACKAGE}FILES+= test_read_format_rar_windows.rar.uu ${PACKAGE}FILES+= test_read_format_rar4_encrypted.rar.uu @@ -627,11 +654,15 @@ ${PACKAGE}FILES+= test_read_format_tar_empty_with_gnulabel.tar.uu ${PACKAGE}FILES+= test_read_format_tar_empty_pax.tar.Z.uu ${PACKAGE}FILES+= test_read_format_tar_filename_koi8r.tar.Z.uu ${PACKAGE}FILES+= test_read_format_tar_invalid_pax_size.tar.uu +${PACKAGE}FILES+= test_read_format_tar_mac_metadata_1.tar.uu +${PACKAGE}FILES+= test_read_format_tar_pax_g_large.tar.uu ${PACKAGE}FILES+= test_read_format_tar_pax_large_attr.tar.Z.uu +${PACKAGE}FILES+= test_read_format_tar_pax_negative_time.tar.uu ${PACKAGE}FILES+= test_read_format_ustar_filename_cp866.tar.Z.uu ${PACKAGE}FILES+= test_read_format_ustar_filename_eucjp.tar.Z.uu ${PACKAGE}FILES+= test_read_format_ustar_filename_koi8r.tar.Z.uu ${PACKAGE}FILES+= test_read_format_warc.warc.uu +${PACKAGE}FILES+= test_read_format_warc_incomplete.warc.uu ${PACKAGE}FILES+= test_read_format_xar_doublelink.xar.uu ${PACKAGE}FILES+= test_read_format_xar_duplicate_filename_node.xar.uu ${PACKAGE}FILES+= test_read_format_zip.zip.uu @@ -691,6 +722,7 @@ ${PACKAGE}FILES+= test_read_large_splitted_rar_ab.uu ${PACKAGE}FILES+= test_read_large_splitted_rar_ac.uu ${PACKAGE}FILES+= test_read_large_splitted_rar_ad.uu ${PACKAGE}FILES+= test_read_large_splitted_rar_ae.uu +${PACKAGE}FILES+= test_read_pax_empty_val_no_nl.tar.uu ${PACKAGE}FILES+= test_read_pax_xattr_rht_security_selinux.tar.uu ${PACKAGE}FILES+= test_read_pax_xattr_schily.tar.uu ${PACKAGE}FILES+= test_read_splitted_rar_aa.uu diff --git a/lib/libbe/be.c b/lib/libbe/be.c index e0ced1c5bcfc..613235d5e908 100644 --- a/lib/libbe/be.c +++ b/lib/libbe/be.c @@ -1,28 +1,7 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * +/* * Copyright (c) 2017 Kyle J. Kneitinger <kyle@kneit.in> * - * 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 REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * SPDX-License-Identifier: BSD-2-Clause */ #include <sys/param.h> diff --git a/lib/libbe/be.h b/lib/libbe/be.h index 0e4486fbb6d2..01ee94fd03ca 100644 --- a/lib/libbe/be.h +++ b/lib/libbe/be.h @@ -1,28 +1,7 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * +/* * Copyright (c) 2017 Kyle J. Kneitinger <kyle@kneit.in> * - * 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 REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * SPDX-License-Identifier: BSD-2-Clause */ #ifndef _LIBBE_H diff --git a/lib/libbe/be_access.c b/lib/libbe/be_access.c index 67b30d3fb4fb..a7eb6b703cda 100644 --- a/lib/libbe/be_access.c +++ b/lib/libbe/be_access.c @@ -1,30 +1,9 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * +/* * Copyright (c) 2017 Kyle J. Kneitinger <kyle@kneit.in> * Copyright (c) 2018 Kyle Evans <kevans@FreeBSD.org> * Copyright (c) 2019 Wes Maag <wes@jwmaag.org> * - * 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 REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * SPDX-License-Identifier: BSD-2-Clause */ #include <sys/cdefs.h> @@ -33,6 +12,8 @@ #include "be.h" #include "be_impl.h" +#define LIBBE_MOUNT_PREFIX "be_mount." + struct be_mountcheck_info { const char *path; char *name; @@ -164,7 +145,11 @@ be_umount_iter(zfs_handle_t *zfs_hdl, void *data) if (!zfs_is_mounted(zfs_hdl, &mountpoint)) { return (0); } - free(mountpoint); + + if (info->depth == 0 && info->mountpoint == NULL) + info->mountpoint = mountpoint; + else + free(mountpoint); if (zfs_unmount(zfs_hdl, NULL, info->mntflags) != 0) { switch (errno) { @@ -255,7 +240,17 @@ be_mount(libbe_handle_t *lbh, const char *bootenv, const char *mountpoint, /* Create mountpoint if it is not specified */ if (mountpoint == NULL) { - strlcpy(mnt_temp, "/tmp/be_mount.XXXX", sizeof(mnt_temp)); + const char *tmpdir; + + tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL) + tmpdir = _PATH_TMP; + + if (snprintf(mnt_temp, sizeof(mnt_temp), "%s%s%sXXXX", tmpdir, + tmpdir[strlen(tmpdir) - 1] == '/' ? "" : "/", + LIBBE_MOUNT_PREFIX) >= (int)sizeof(mnt_temp)) + return (set_error(lbh, BE_ERR_PATHLEN)); + if (mkdtemp(mnt_temp) == NULL) return (set_error(lbh, BE_ERR_IO)); } @@ -307,10 +302,32 @@ be_unmount(libbe_handle_t *lbh, const char *bootenv, int flags) info.depth = 0; if ((err = be_umount_iter(root_hdl, &info)) != 0) { + free(__DECONST(char *, info.mountpoint)); zfs_close(root_hdl); return (err); } + /* + * We'll attempt to remove the directory if we created it on a + * best-effort basis. rmdir(2) failure will not be reported. + */ + if (info.mountpoint != NULL) { + const char *mdir; + + mdir = strrchr(info.mountpoint, '/'); + if (mdir == NULL) + mdir = info.mountpoint; + else + mdir++; + + if (strncmp(mdir, LIBBE_MOUNT_PREFIX, + sizeof(LIBBE_MOUNT_PREFIX) - 1) == 0) { + (void)rmdir(info.mountpoint); + } + } + + free(__DECONST(char *, info.mountpoint)); + zfs_close(root_hdl); return (BE_ERR_SUCCESS); } diff --git a/lib/libbe/be_error.c b/lib/libbe/be_error.c index f515fe136f12..bb1e1ed88c5d 100644 --- a/lib/libbe/be_error.c +++ b/lib/libbe/be_error.c @@ -1,28 +1,7 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * +/* * Copyright (c) 2017 Kyle J. Kneitinger <kyle@kneit.in> * - * 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 REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * SPDX-License-Identifier: BSD-2-Clause */ #include <sys/cdefs.h> diff --git a/lib/libbe/be_impl.h b/lib/libbe/be_impl.h index 0327f8abaa0a..11d1e0ddca28 100644 --- a/lib/libbe/be_impl.h +++ b/lib/libbe/be_impl.h @@ -1,28 +1,7 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * +/* * Copyright (c) 2017 Kyle J. Kneitinger <kyle@kneit.in> * - * 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 REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * SPDX-License-Identifier: BSD-2-Clause */ #ifndef _LIBBE_IMPL_H diff --git a/lib/libbe/be_info.c b/lib/libbe/be_info.c index 509b56cb8cf5..4b0f611ce421 100644 --- a/lib/libbe/be_info.c +++ b/lib/libbe/be_info.c @@ -1,29 +1,8 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * +/* * Copyright (c) 2017 Kyle J. Kneitinger <kyle@kneit.in> * Copyright (c) 2018 Kyle Evans <kevans@FreeBSD.org> * - * 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 REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * SPDX-License-Identifier: BSD-2-Clause */ #include <sys/cdefs.h> diff --git a/lib/libbe/libbe.3 b/lib/libbe/libbe.3 index 4d9439206b7b..3b10711dd0f9 100644 --- a/lib/libbe/libbe.3 +++ b/lib/libbe/libbe.3 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 9, 2024 +.Dd April 20, 2025 .Dt LIBBE 3 .Os .Sh NAME @@ -358,6 +358,10 @@ If is .Dv NULL , a mount point will be generated in +.Ev TMPDIR +or, if +.Ev TMPDIR +is not set, .Pa /tmp using .Xr mkdtemp 3 . @@ -392,6 +396,13 @@ This list of properties matches the properties collected by The .Fn be_unmount function will unmount the given boot environment. +If the mount point looks like it was created by +.Fn be_mount , +then +.Fn be_unmount +will attempt to +.Xr rmdir 2 +the mountpoint after a successful unmount. Setting the .Dv BE_MNT_FORCE flag will pass diff --git a/lib/libc/amd64/static_tls.h b/lib/libc/amd64/static_tls.h deleted file mode 100644 index 1ee738b231c7..000000000000 --- a/lib/libc/amd64/static_tls.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - */ - -#ifndef _LIBC_AMD64_STATIC_TLS_H -#define _LIBC_AMD64_STATIC_TLS_H - -static __inline uintptr_t -_libc_get_static_tls_base(size_t offset) -{ - uintptr_t tlsbase; - - __asm __volatile("movq %%fs:0, %0" : "=r" (tlsbase)); - tlsbase -= offset; - return (tlsbase); -} - -#endif diff --git a/lib/libc/arm/aeabi/Symbol.map b/lib/libc/arm/aeabi/Symbol.map index 175884c82881..515794004ba7 100644 --- a/lib/libc/arm/aeabi/Symbol.map +++ b/lib/libc/arm/aeabi/Symbol.map @@ -6,50 +6,6 @@ FBSDprivate_1.0 { __aeabi_atexit; - __aeabi_dcmpeq; - __aeabi_dcmplt; - __aeabi_dcmple; - __aeabi_dcmpge; - __aeabi_dcmpgt; - __aeabi_dcmpun; - - __aeabi_cdcmpeq; - __aeabi_cdcmple; - __aeabi_cdrcmple; - - __aeabi_d2iz; - __aeabi_d2f; - - __aeabi_dadd; - __aeabi_ddiv; - __aeabi_dmul; - __aeabi_dsub; - - - __aeabi_fcmpeq; - __aeabi_fcmplt; - __aeabi_fcmple; - __aeabi_fcmpge; - __aeabi_fcmpgt; - __aeabi_fcmpun; - - __aeabi_cfcmpeq; - __aeabi_cfcmple; - __aeabi_cfrcmple; - - __aeabi_f2iz; - __aeabi_f2d; - - __aeabi_fadd; - __aeabi_fdiv; - __aeabi_fmul; - __aeabi_fsub; - - - __aeabi_i2d; - __aeabi_i2f; - - __aeabi_memclr; __aeabi_memclr4; __aeabi_memclr8; diff --git a/lib/libc/arm/aeabi/aeabi_int_div.S b/lib/libc/arm/aeabi/aeabi_int_div.S index 708b478b3881..bb002c2716f7 100644 --- a/lib/libc/arm/aeabi/aeabi_int_div.S +++ b/lib/libc/arm/aeabi/aeabi_int_div.S @@ -37,11 +37,13 @@ */ ENTRY(__aeabi_uidiv_compat) + .hidden __aeabi_uidiv_compat .symver __aeabi_uidiv_compat, __aeabi_uidiv@ b __udivsi3 END(__aeabi_uidiv_compat) ENTRY(__aeabi_idiv_compat) + .hidden __aeabi_idiv_compat .symver __aeabi_idiv_compat, __aeabi_idiv@ b __divsi3 END(__aeabi_idiv_compat) diff --git a/lib/libc/arm/aeabi/aeabi_vfp.h b/lib/libc/arm/aeabi/aeabi_vfp.h index 3b70fe06fab3..4f3bb2ef969b 100644 --- a/lib/libc/arm/aeabi/aeabi_vfp.h +++ b/lib/libc/arm/aeabi/aeabi_vfp.h @@ -40,7 +40,9 @@ #define AEABI_ENTRY(x) ENTRY(__aeabi_ ## x ## _vfp) #define AEABI_END(x) END(__aeabi_ ## x ## _vfp) #else -#define AEABI_ENTRY(x) ENTRY(__aeabi_ ## x) +#define AEABI_ENTRY(x) \ + ENTRY(__aeabi_ ## x) \ + .symver __aeabi_##x, __aeabi_##x##@FBSDprivate_1.0; #define AEABI_END(x) END(__aeabi_ ## x) #endif diff --git a/lib/libc/arm/static_tls.h b/lib/libc/arm/static_tls.h deleted file mode 100644 index 557748d75347..000000000000 --- a/lib/libc/arm/static_tls.h +++ /dev/null @@ -1,45 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - */ - -#ifndef _LIBC_ARM_STATIC_TLS_H -#define _LIBC_ARM_STATIC_TLS_H - -static __inline uintptr_t -_libc_get_static_tls_base(size_t offset) -{ - uintptr_t tlsbase; - - __asm __volatile("mrc p15, 0, %0, c13, c0, 3" : "=r" (tlsbase)); - - tlsbase += offset; - return (tlsbase); -} - -#endif diff --git a/lib/libc/csu/libc_start1.c b/lib/libc/csu/libc_start1.c index 045ea1e68141..5b08ba03ba8c 100644 --- a/lib/libc/csu/libc_start1.c +++ b/lib/libc/csu/libc_start1.c @@ -28,6 +28,7 @@ #include <sys/param.h> #include <sys/elf.h> #include <sys/elf_common.h> +#include <errno.h> #include <stdlib.h> #include "libc_private.h" @@ -169,6 +170,13 @@ __libc_start1(int argc, char *argv[], char *env[], void (*cleanup)(void), } handle_static_init(argc, argv, env); + + /* + * C17 4.3 paragraph 3: + * The value of errno in the initial thread is zero at program + * startup. + */ + errno = 0; exit(mainX(argc, argv, env)); } @@ -194,5 +202,6 @@ __libc_start1_gcrt(int argc, char *argv[], char *env[], monstartup(eprolp, etextp); handle_static_init(argc, argv, env); + errno = 0; exit(mainX(argc, argv, env)); } diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index 9b92e52cdfad..4d064d18d36e 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -89,6 +89,7 @@ SRCS+= \ glob.c \ glob-compat11.c \ initgroups.c \ + inotify.c \ isatty.c \ isinf.c \ isnan.c \ @@ -134,6 +135,7 @@ SRCS+= \ setmode.c \ setproctitle.c \ setprogname.c \ + sig2str.c \ siginterrupt.c \ siglist.c \ signal.c \ @@ -159,6 +161,8 @@ SRCS+= \ ttyname.c \ ttyslot.c \ ualarm.c \ + uexterr_format.c \ + uexterr_gettext.c \ ulimit.c \ uname.c \ unvis-compat.c \ @@ -168,6 +172,11 @@ SRCS+= \ valloc.c \ wordexp.c +.if ${COMPILER_FEATURES:Mblocks} +CFLAGS.fts.c= -fblocks +CFLAGS.glob.c= -fblocks +.endif + CFLAGS.arc4random.c= -I${SRCTOP}/sys -I${SRCTOP}/sys/crypto/chacha20 CFLAGS.sysconf.c= -I${SRCTOP}/contrib/tzcode @@ -362,7 +371,8 @@ MLINKS+=exec.3 execl.3 \ exec.3 exect.3 \ exec.3 execv.3 \ exec.3 execvP.3 \ - exec.3 execvp.3 + exec.3 execvp.3 \ + exec.3 execvpe.3 MLINKS+=fpclassify.3 finite.3 \ fpclassify.3 finitef.3 \ fpclassify.3 isfinite.3 \ @@ -465,7 +475,10 @@ MLINKS+=posix_spawn.3 posix_spawnp.3 \ posix_spawnattr_getsigdefault.3 posix_spawnattr_setsigdefault.3 \ posix_spawnattr_getsigmask.3 posix_spawnattr_setsigmask.3 \ posix_spawnattr_init.3 posix_spawnattr_destroy.3 -MLINKS+=psignal.3 strsignal.3 \ +MLINKS+=psignal.3 psiginfo.3 \ + psignal.3 sig2str.3 \ + psignal.3 str2sig.3 \ + psignal.3 strsignal.3 \ psignal.3 sys_siglist.3 \ psignal.3 sys_signame.3 MLINKS+=pwcache.3 gid_from_group.3 \ @@ -487,8 +500,11 @@ MLINKS+=rand48.3 _rand48.3 \ MLINKS+=rtld_get_var.3 \ rtld_set_var.3 MLINKS+=scandir.3 alphasort.3 \ - scandir.3 scandirat.3 \ + scandir.3 fdscandir.3 \ + scandir.3 fdscandir_b.3 \ scandir.3 scandir_b.3 \ + scandir.3 scandirat.3 \ + scandir.3 scandirat_b.3 \ scandir.3 versionsort.3 MLINKS+=sem_open.3 sem_close.3 \ sem_open.3 sem_unlink.3 diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map index ca3974e6b747..26f638568efc 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -458,8 +458,20 @@ FBSD_1.8 { aio_read2; aio_write2; execvpe; + fdscandir; + fdscandir_b; + fts_open_b; + glob_b; + inotify_add_watch; + inotify_init; + inotify_init1; + psiginfo; rtld_get_var; rtld_set_var; + scandirat_b; + uexterr_gettext; + sig2str; + str2sig; }; FBSDprivate_1.0 { @@ -584,10 +596,10 @@ FBSDprivate_1.0 { __libc_tcdrain; - __pthread_distribute_static_tls; __pthread_map_stacks_exec; __fillcontextx; __fillcontextx2; __getcontextx_size; __makecontext; + __uexterr_format; }; diff --git a/lib/libc/gen/_pthread_stubs.c b/lib/libc/gen/_pthread_stubs.c index 2a0cebadd5fd..d867ee4db51e 100644 --- a/lib/libc/gen/_pthread_stubs.c +++ b/lib/libc/gen/_pthread_stubs.c @@ -63,6 +63,7 @@ static int stub_getname_np(pthread_t, char *, size_t); #define PJT_DUAL_ENTRY(entry) \ (pthread_func_t)entry, (pthread_func_t)entry +__attribute__((visibility("protected"))) pthread_func_entry_t __thr_jtable[PJT_MAX] = { [PJT_ATFORK] = {PJT_DUAL_ENTRY(stub_zero)}, [PJT_ATTR_DESTROY] = {PJT_DUAL_ENTRY(stub_zero)}, diff --git a/lib/libc/gen/alarm.3 b/lib/libc/gen/alarm.3 index 8aeda29481eb..4a24cc6d7216 100644 --- a/lib/libc/gen/alarm.3 +++ b/lib/libc/gen/alarm.3 @@ -63,7 +63,7 @@ Due to .Xr setitimer 2 restriction the maximum number of .Fa seconds -allowed is 100000000. +allowed is 100,000,000. .Sh RETURN VALUES The return value of .Fn alarm diff --git a/lib/libc/gen/dlfcn.c b/lib/libc/gen/dlfcn.c index bffee3952e0d..ae1c8d83df19 100644 --- a/lib/libc/gen/dlfcn.c +++ b/lib/libc/gen/dlfcn.c @@ -229,7 +229,7 @@ _dl_iterate_phdr_locked( return (1); _once(&dl_phdr_info_once, dl_init_phdr_info); ti.ti_module = 1; - ti.ti_offset = 0; + ti.ti_offset = -TLS_DTV_OFFSET; phdr_info.dlpi_tls_data = __tls_get_addr(&ti); ret = callback(&phdr_info, sizeof(phdr_info), data); return (ret); diff --git a/lib/libc/gen/dup3.3 b/lib/libc/gen/dup3.3 index f2798930797b..338a9ae74c64 100644 --- a/lib/libc/gen/dup3.3 +++ b/lib/libc/gen/dup3.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 16, 2013 +.Dd May 17, 2025 .Dt DUP3 3 .Os .Sh NAME @@ -47,6 +47,11 @@ The close-on-exec flag on the new file descriptor is determined by the bit in .Fa flags . .Pp +The close-on-fork flag on the new file descriptor is determined by the +.Dv O_CLOFORK +bit in +.Fa flags . +.Pp If .Fa oldd \*(Ne @@ -91,7 +96,9 @@ argument. The .Fa flags argument has bits set other than -.Dv O_CLOEXEC . +.Dv O_CLOEXEC +or +.Dv O_CLOFORK . .El .Sh SEE ALSO .Xr accept 2 , @@ -112,3 +119,7 @@ The .Fn dup3 function appeared in .Fx 10.0 . +The +.Dv O_CLOFORK +flag appeared in +.Fx 15.0 . diff --git a/lib/libc/gen/dup3.c b/lib/libc/gen/dup3.c index fca1e99fb47b..1401c1f5b607 100644 --- a/lib/libc/gen/dup3.c +++ b/lib/libc/gen/dup3.c @@ -39,21 +39,22 @@ int __dup3(int, int, int); int __dup3(int oldfd, int newfd, int flags) { - int how; + int fdflags; if (oldfd == newfd) { errno = EINVAL; return (-1); } - if (flags & ~O_CLOEXEC) { + if ((flags & ~(O_CLOEXEC | O_CLOFORK)) != 0) { errno = EINVAL; return (-1); } - how = (flags & O_CLOEXEC) ? F_DUP2FD_CLOEXEC : F_DUP2FD; + fdflags = ((flags & O_CLOEXEC) != 0 ? FD_CLOEXEC : 0) | + ((flags & O_CLOFORK) != 0 ? FD_CLOFORK : 0); - return (_fcntl(oldfd, how, newfd)); + return (_fcntl(oldfd, F_DUP3FD | (fdflags << F_DUP3FD_SHIFT), newfd)); } __weak_reference(__dup3, dup3); diff --git a/lib/libc/gen/elf_utils.c b/lib/libc/gen/elf_utils.c index 5b87e012d0eb..3714a0dc42b5 100644 --- a/lib/libc/gen/elf_utils.c +++ b/lib/libc/gen/elf_utils.c @@ -31,14 +31,16 @@ #include <sys/mman.h> #include <sys/resource.h> #include <sys/sysctl.h> + +#include <machine/tls.h> + #include <link.h> #include <stddef.h> #include <string.h> + #include "libc_private.h" -#include "static_tls.h" void __pthread_map_stacks_exec(void); -void __pthread_distribute_static_tls(size_t, void *, size_t, size_t); int __elf_phdr_match_addr(struct dl_phdr_info *phdr_info, void *addr) @@ -102,24 +104,3 @@ __pthread_map_stacks_exec(void) ((void (*)(void))__libc_interposing[INTERPOS_map_stacks_exec])(); } - -void -__libc_distribute_static_tls(size_t offset, void *src, size_t len, - size_t total_len) -{ - uintptr_t tlsbase; - - tlsbase = _libc_get_static_tls_base(offset); - memcpy((void *)tlsbase, src, len); - memset((char *)tlsbase + len, 0, total_len - len); -} - -#pragma weak __pthread_distribute_static_tls -void -__pthread_distribute_static_tls(size_t offset, void *src, size_t len, - size_t total_len) -{ - - ((void (*)(size_t, void *, size_t, size_t))__libc_interposing[ - INTERPOS_distribute_static_tls])(offset, src, len, total_len); -} diff --git a/lib/libc/gen/err.c b/lib/libc/gen/err.c index 24ea242560b8..16cbe27693e7 100644 --- a/lib/libc/gen/err.c +++ b/lib/libc/gen/err.c @@ -30,9 +30,12 @@ */ #include "namespace.h" +#include <sys/exterrvar.h> #include <err.h> #include <errno.h> +#include <exterr.h> #include <stdarg.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -43,6 +46,11 @@ static FILE *err_file; /* file to use for error output */ static void (*err_exit)(int); +static void verrci(bool doexterr, int eval, int code, const char *fmt, + va_list ap) __printf0like(4, 0) __dead2; +static void vwarnci(bool doexterr, int code, const char *fmt, va_list ap) + __printf0like(3, 0); + /* * This is declared to take a `void *' so that the caller is not required * to include <stdio.h> first. However, it is really a `FILE *', and the @@ -70,14 +78,14 @@ _err(int eval, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - verrc(eval, errno, fmt, ap); + verrci(true, eval, errno, fmt, ap); va_end(ap); } void verr(int eval, const char *fmt, va_list ap) { - verrc(eval, errno, fmt, ap); + verrci(true, eval, errno, fmt, ap); } void @@ -85,13 +93,24 @@ errc(int eval, int code, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - verrc(eval, code, fmt, ap); + verrci(false, eval, code, fmt, ap); va_end(ap); } void verrc(int eval, int code, const char *fmt, va_list ap) { + verrci(false, eval, code, fmt, ap); +} + +static void +vexterr(bool doexterr, int code, const char *fmt, va_list ap) +{ + char exterr[UEXTERROR_MAXLEN]; /* libc knows the buffer size */ + int extstatus; + + if (doexterr) + extstatus = uexterr_gettext(exterr, sizeof(exterr)); if (err_file == NULL) err_set_file(NULL); fprintf(err_file, "%s: ", _getprogname()); @@ -99,7 +118,16 @@ verrc(int eval, int code, const char *fmt, va_list ap) vfprintf(err_file, fmt, ap); fprintf(err_file, ": "); } - fprintf(err_file, "%s\n", strerror(code)); + fprintf(err_file, "%s", strerror(code)); + if (doexterr && extstatus == 0 && exterr[0] != '\0') + fprintf(err_file, " (extended error %s)", exterr); + fprintf(err_file, "\n"); +} + +static void +verrci(bool doexterr, int eval, int code, const char *fmt, va_list ap) +{ + vexterr(doexterr, code, fmt, ap); if (err_exit) err_exit(eval); exit(eval); @@ -157,17 +185,16 @@ warnc(int code, const char *fmt, ...) void vwarnc(int code, const char *fmt, va_list ap) { + vwarnci(false, code, fmt, ap); +} + +static void +vwarnci(bool doexterr, int code, const char *fmt, va_list ap) +{ int saved_errno; saved_errno = errno; - if (err_file == NULL) - err_set_file(NULL); - fprintf(err_file, "%s: ", _getprogname()); - if (fmt != NULL) { - vfprintf(err_file, fmt, ap); - fprintf(err_file, ": "); - } - fprintf(err_file, "%s\n", strerror(code)); + vexterr(doexterr, code, fmt, ap); errno = saved_errno; } diff --git a/lib/libc/gen/exec.c b/lib/libc/gen/exec.c index d9285733e965..926c50d64852 100644 --- a/lib/libc/gen/exec.c +++ b/lib/libc/gen/exec.c @@ -136,7 +136,7 @@ execv(const char *name, char * const *argv) int execvp(const char *name, char * const *argv) { - return (execvpe(name, argv, environ)); + return (__libc_execvpe(name, argv, environ)); } static int @@ -288,7 +288,7 @@ execvP(const char *name, const char *path, char * const argv[]) } int -execvpe(const char *name, char * const argv[], char * const envp[]) +__libc_execvpe(const char *name, char * const argv[], char * const envp[]) { const char *path; @@ -298,3 +298,5 @@ execvpe(const char *name, char * const argv[], char * const envp[]) return (execvPe(name, path, argv, envp)); } + +__weak_reference(__libc_execvpe, execvpe); diff --git a/lib/libc/gen/fdopendir.c b/lib/libc/gen/fdopendir.c index 67c0766b6d83..df6709fbcb85 100644 --- a/lib/libc/gen/fdopendir.c +++ b/lib/libc/gen/fdopendir.c @@ -30,14 +30,13 @@ */ #include "namespace.h" -#include <sys/param.h> +#include <sys/types.h> +#include <sys/stat.h> #include <dirent.h> #include <errno.h> #include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> +#include <stdbool.h> #include "un-namespace.h" #include "gen-private.h" diff --git a/lib/libc/gen/fnmatch.3 b/lib/libc/gen/fnmatch.3 index 804bc968c1ce..7f020fec58e3 100644 --- a/lib/libc/gen/fnmatch.3 +++ b/lib/libc/gen/fnmatch.3 @@ -27,7 +27,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 2, 2022 +.Dd April 7, 2025 .Dt FNMATCH 3 .Os .Sh NAME @@ -129,12 +129,8 @@ otherwise, it returns the value .Sh STANDARDS The current implementation of the .Fn fnmatch -function -.Em does not -conform to +function is expected to conform to .St -p1003.2 . -Collating symbol expressions, equivalence class expressions and -character class expressions are not supported. .Sh HISTORY A predecessor to .Fn fnmatch , diff --git a/lib/libc/gen/fnmatch.c b/lib/libc/gen/fnmatch.c index fb1829e69502..1c583a9d23e2 100644 --- a/lib/libc/gen/fnmatch.c +++ b/lib/libc/gen/fnmatch.c @@ -67,7 +67,8 @@ #define RANGE_NOMATCH 0 #define RANGE_ERROR (-1) -static int rangematch(const char *, wchar_t, int, char **, mbstate_t *); +static int rangematch(const char *, wchar_t, const char *, int, char **, + char **, mbstate_t *, mbstate_t *); static int fnmatch1(const char *, const char *, const char *, int, mbstate_t, mbstate_t); @@ -85,7 +86,7 @@ fnmatch1(const char *pattern, const char *string, const char *stringstart, { const char *bt_pattern, *bt_string; mbstate_t bt_patmbs, bt_strmbs; - char *newp; + char *newp, *news; char c; wchar_t pc, sc; size_t pclen, sclen; @@ -151,8 +152,10 @@ fnmatch1(const char *pattern, const char *string, const char *stringstart, * there is no way having it match more characters * can help us, given that we are already here. */ - bt_pattern = pattern, bt_patmbs = patmbs; - bt_string = string, bt_strmbs = strmbs; + bt_pattern = pattern; + bt_patmbs = patmbs; + bt_string = string; + bt_strmbs = strmbs; break; case '[': if (sc == EOS) @@ -164,17 +167,17 @@ fnmatch1(const char *pattern, const char *string, const char *stringstart, ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) goto backtrack; - switch (rangematch(pattern, sc, flags, &newp, - &patmbs)) { + switch (rangematch(pattern, sc, string + sclen, flags, + &newp, &news, &patmbs, &strmbs)) { case RANGE_ERROR: goto norm; case RANGE_MATCH: pattern = newp; + string = news; break; case RANGE_NOMATCH: goto backtrack; } - string += sclen; break; case '\\': if (!(flags & FNM_NOESCAPE)) { @@ -218,8 +221,10 @@ fnmatch1(const char *pattern, const char *string, const char *stringstart, if (sc == '/' && flags & FNM_PATHNAME) return (FNM_NOMATCH); bt_string += sclen; - pattern = bt_pattern, patmbs = bt_patmbs; - string = bt_string, strmbs = bt_strmbs; + pattern = bt_pattern; + patmbs = bt_patmbs; + string = bt_string; + strmbs = bt_strmbs; } break; } @@ -228,15 +233,20 @@ fnmatch1(const char *pattern, const char *string, const char *stringstart, } static int -rangematch(const char *pattern, wchar_t test, int flags, char **newp, - mbstate_t *patmbs) +rangematch(const char *pattern, wchar_t test, const char *string, int flags, + char **newp, char **news, mbstate_t *patmbs, mbstate_t *strmbs) { int negate, ok; wchar_t c, c2; size_t pclen; const char *origpat; struct xlocale_collate *table = - (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; + (struct xlocale_collate *)__get_locale()->components[XLC_COLLATE]; + wchar_t buf[COLLATE_STR_LEN]; /* STR_LEN defined in collate.h */ + const char *cp, *savestring; + int special; + mbstate_t save; + size_t sclen, len; /* * A bracket expression starting with an unquoted circumflex @@ -259,20 +269,132 @@ rangematch(const char *pattern, wchar_t test, int flags, char **newp, ok = 0; origpat = pattern; for (;;) { + c = 0; if (*pattern == ']' && pattern > origpat) { - pattern++; break; } else if (*pattern == '\0') { return (RANGE_ERROR); } else if (*pattern == '/' && (flags & FNM_PATHNAME)) { return (RANGE_NOMATCH); - } else if (*pattern == '\\' && !(flags & FNM_NOESCAPE)) + } else if (*pattern == '\\' && !(flags & FNM_NOESCAPE)) { pattern++; - pclen = mbrtowc(&c, pattern, MB_LEN_MAX, patmbs); - if (pclen == (size_t)-1 || pclen == (size_t)-2) - return (RANGE_NOMATCH); - pattern += pclen; + } else if (*pattern == '[' && + ((special = *(pattern + 1)) == '.' || + special == '=' || special == ':')) { + cp = (pattern += 2); + while ((cp = strchr(cp, special))) { + if (*(cp + 1) == ']') + break; + cp++; + } + if (!cp) + return (RANGE_ERROR); + if (special == '.') { +treat_like_collating_symbol: + len = __collate_collating_symbol(buf, + COLLATE_STR_LEN, pattern, + cp - pattern, patmbs); + if (len == (size_t)-1 || len == 0) + return (RANGE_ERROR); + pattern = cp + 2; + if (len > 1) { + wchar_t *wp, sc; + /* + * No multi-character collation + * symbols as start of range. + */ + if (*(cp + 2) == '-' && + *(cp + 3) != EOS && + *(cp + 3) != ']') + return (RANGE_ERROR); + wp = buf; + if (test != *wp++) + continue; + if (len == 1) { + ok = 1; + break; + } + memcpy(&save, strmbs, sizeof(save)); + savestring = string; + while (--len > 0) { + sclen = mbrtowc(&sc, string, + MB_LEN_MAX, strmbs); + if (sclen == (size_t)-1 || + sclen == (size_t)-2) { + sc = (unsigned char)*string; + sclen = 1; + memset(&strmbs, 0, + sizeof(strmbs)); + } + if (sc != *wp++) { + memcpy(strmbs, &save, + sizeof(save)); + string = savestring; + break; + } + string += sclen; + } + if (len == 0) { + ok = 1; + break; + } + continue; /* no match */ + } + c = *buf; + } else if (special == '=') { + int ec; + memcpy(&save, patmbs, sizeof(save)); + ec = __collate_equiv_class(pattern, + cp - pattern, patmbs); + if (ec < 0) + return (RANGE_ERROR); + if (ec == 0) { + memcpy(patmbs, &save, sizeof(save)); + goto treat_like_collating_symbol; + } + pattern = cp + 2; + /* no equivalence classes as start of range */ + if (*(cp + 2) == '-' && *(cp + 3) != EOS && + *(cp + 3) != ']') + return (RANGE_ERROR); + len = __collate_equiv_match(ec, NULL, 0, test, + string, strlen(string), strmbs, &sclen); + if (len < 0) + return (RANGE_ERROR); + if (len > 0) { + ok = 1; + string += sclen; + break; + } + continue; + } else { /* special == ':' */ + wctype_t charclass; + char name[CHARCLASS_NAME_MAX + 1]; + /* no character classes as start of range */ + if (*(cp + 2) == '-' && *(cp + 3) != EOS && + *(cp + 3) != ']') + return (RANGE_ERROR); + /* assume character class names are ascii */ + if (cp - pattern > CHARCLASS_NAME_MAX) + return (RANGE_ERROR); + strlcpy(name, pattern, cp - pattern + 1); + pattern = cp + 2; + if ((charclass = wctype(name)) == 0) + return (RANGE_ERROR); + if (iswctype(test, charclass)) { + ok = 1; + break; + } + continue; + } + } + if (!c) { + pclen = mbrtowc(&c, pattern, MB_LEN_MAX, patmbs); + if (pclen == (size_t)-1 || pclen == (size_t)-2) + return (RANGE_NOMATCH); + pattern += pclen; + } if (flags & FNM_CASEFOLD) c = towlower(c); @@ -288,6 +410,37 @@ rangematch(const char *pattern, wchar_t test, int flags, char **newp, if (c2 == EOS) return (RANGE_ERROR); + if ((c2 == '[' && (special = *pattern) == '.') || + special == '=' || special == ':') { + + /* + * No equivalence classes or character + * classes as end of range. + */ + if (special == '=' || special == ':') + return (RANGE_ERROR); + cp = ++pattern; + while ((cp = strchr(cp, special))) { + if (*(cp + 1) == ']') + break; + cp++; + } + if (!cp) + return (RANGE_ERROR); + len = __collate_collating_symbol(buf, + COLLATE_STR_LEN, pattern, + cp - pattern, patmbs); + + /* + * No multi-character collation symbols + * as end of range. + */ + if (len != 1) + return (RANGE_ERROR); + pattern = cp + 2; + c2 = *buf; + } + if (flags & FNM_CASEFOLD) c2 = towlower(c2); @@ -295,12 +448,44 @@ rangematch(const char *pattern, wchar_t test, int flags, char **newp, c <= test && test <= c2 : __wcollate_range_cmp(c, test) <= 0 && __wcollate_range_cmp(test, c2) <= 0 - ) + ) { ok = 1; - } else if (c == test) + break; + } + } else if (c == test) { ok = 1; + break; + } } - *newp = (char *)pattern; + /* go to end of bracket expression */ + special = 0; + while (*pattern != ']') { + if (*pattern == 0) + return (RANGE_ERROR); + if (*pattern == special) { + if (*++pattern == ']') { + special = 0; + pattern++; + } + continue; + } + if (!special && *pattern == '[') { + special = *++pattern; + if (special != '.' && special != '=' && special != ':') + special = 0; + else + pattern++; + continue; + } + pclen = mbrtowc(&c, pattern, MB_LEN_MAX, patmbs); + if (pclen == (size_t)-1 || pclen == (size_t)-2) + return (RANGE_NOMATCH); + pattern += pclen; + } + + *newp = (char *)++pattern; + *news = (char *)string; + return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH); } diff --git a/lib/libc/gen/fts.3 b/lib/libc/gen/fts.3 index 468b14115ec6..ee558b892c8c 100644 --- a/lib/libc/gen/fts.3 +++ b/lib/libc/gen/fts.3 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd January 12, 2014 +.Dd June 30, 2025 .Dt FTS 3 .Os .Sh NAME @@ -37,6 +37,8 @@ .In fts.h .Ft FTS * .Fn fts_open "char * const *path_argv" "int options" "int (*compar)(const FTSENT * const *, const FTSENT * const *)" +.Ft FTS * +.Fn fts_open_b "char * const *path_argv" "int options" "int (^compar)(const FTSENT * const *, const FTSENT * const *)" .Ft FTSENT * .Fn fts_read "FTS *ftsp" .Ft FTSENT * @@ -59,7 +61,9 @@ functions are provided for traversing file hierarchies. A simple overview is that the .Fn fts_open -function returns a +and +.Fn fts_open_b +functions return a .Dq handle on a file hierarchy, which is then supplied to the other @@ -176,6 +180,12 @@ by one of the other values. .It Dv FTS_DNR A directory which cannot be read. +This immediately follows +.Dv FTS_D , +in place of +.Dv FTS_DP , +when the directory could not be entered, or could be entered but not +read. This is an error return, and the .Fa fts_errno field will be set to indicate what caused the error. @@ -186,6 +196,8 @@ or .Ql ..\& which was not specified as a file name to .Fn fts_open +or +.Fn fts_open_b (see .Dv FTS_SEEDOT ) . .It Dv FTS_DP @@ -234,6 +246,8 @@ A path for accessing the file from the current directory. The path for the file relative to the root of the traversal. This path contains the path specified to .Fn fts_open +or +.Fn fts_open_b as a prefix. .It Fa fts_pathlen The length of the string referenced by @@ -380,12 +394,16 @@ must be specified. The options are selected by .Em or Ns 'ing the following values: -.Bl -tag -width "FTS_PHYSICAL" +.Bl -tag -width "FTS_COMFOLLOWDIR" .It Dv FTS_COMFOLLOW This option causes any symbolic link specified as a root path to be followed immediately whether or not .Dv FTS_LOGICAL is also specified. +.It Dv FTS_COMFOLLOWDIR +This option is similar to +.Dv FTS_COMFOLLOW , +but only follows symbolic links to directories. .It Dv FTS_LOGICAL This option causes the .Nm @@ -441,6 +459,15 @@ field to and leave the contents of the .Fa statp field undefined. +.It Dv FTS_NOSTAT_TYPE +This option is similar to +.Dv FTS_NOSTAT , +but attempts to populate +.Fa fts_info +based on information from the +.Fa d_type +field of +.Vt struct dirent . .It Dv FTS_PHYSICAL This option causes the .Nm @@ -518,6 +545,15 @@ the directory traversal order is in the order listed in .Fa path_argv for the root paths, and in the order listed in the directory for everything else. +.Sh FTS_OPEN_B +The +.Fn fts_open_b +function is identical to +.Fn fts_open +except that it takes a block pointer instead of a function pointer. +The block is copied before +.Fn fts_open_b +returns, so the original can safely go out of scope or be released. .Sh FTS_READ The .Fn fts_read @@ -593,9 +629,13 @@ As a special case, if has not yet been called for a hierarchy, .Fn fts_children will return a pointer to the files in the logical directory specified to -.Fn fts_open , +.Fn fts_open +or +.Fn fts_open_b , i.e., the arguments specified to -.Fn fts_open . +.Fn fts_open +or +.Fn fts_open_b . Otherwise, if the .Vt FTSENT structure most recently returned by @@ -716,6 +756,8 @@ function closes a file hierarchy stream .Fa ftsp and restores the current directory to the directory from which .Fn fts_open +or +.Fn fts_open_b was called to open .Fa ftsp . The @@ -723,29 +765,38 @@ The function returns 0 on success, and \-1 if an error occurs. .Sh ERRORS -The function +The .Fn fts_open -may fail and set +and +.Fn fts_open_b +functions may fail and set .Va errno for any of the errors specified for the library functions .Xr open 2 and .Xr malloc 3 . +The +.Fn fts_open_b +function may also fail and set +.Va errno +to +.Dv ENOSYS +if the blocks runtime is missing. .Pp -The function +The .Fn fts_close -may fail and set +function may fail and set .Va errno for any of the errors specified for the library functions .Xr chdir 2 and .Xr close 2 . .Pp -The functions +The .Fn fts_read and .Fn fts_children -may fail and set +functions may fail and set .Va errno for any of the errors specified for the library functions .Xr chdir 2 , @@ -755,12 +806,12 @@ for any of the errors specified for the library functions and .Xr stat 2 . .Pp -In addition, +In addition, the .Fn fts_children , -.Fn fts_open +.Fn fts_open , and .Fn fts_set -may fail and set +functions may fail and set .Va errno as follows: .Bl -tag -width Er @@ -788,6 +839,13 @@ functions were introduced in principally to provide for alternative interfaces to the .Nm functionality using different data structures. +Blocks support and the +.Dv FTS_COMFOLLOWDIR +and +.Dv FTS_NOSTAT +options were added in +.Fx 15.0 +based on similar functionality in macOS. .Sh BUGS The .Fn fts_open diff --git a/lib/libc/gen/fts.c b/lib/libc/gen/fts.c index 80f98a993123..cce959ba836a 100644 --- a/lib/libc/gen/fts.c +++ b/lib/libc/gen/fts.c @@ -48,6 +48,19 @@ #include "gen-private.h" +#ifdef __BLOCKS__ +#include <Block.h> +#else +#include "block_abi.h" +typedef DECLARE_BLOCK(int, fts_block, + const FTSENT * const *, const FTSENT * const *); +void qsort_b(void *, size_t, size_t, fts_block); +#endif /* __BLOCKS__ */ +/* only present if linked with blocks runtime */ +void *_Block_copy(const void *) __weak_symbol; +void _Block_release(const void *) __weak_symbol; +extern void *_NSConcreteGlobalBlock[] __weak_symbol; + static FTSENT *fts_alloc(FTS *, char *, size_t); static FTSENT *fts_build(FTS *, int); static void fts_lfree(FTSENT *); @@ -102,39 +115,21 @@ static const char *ufslike_filesystems[] = { 0 }; -FTS * -fts_open(char * const *argv, int options, - int (*compar)(const FTSENT * const *, const FTSENT * const *)) +static FTS * +__fts_open(FTS *sp, char * const *argv) { - struct _fts_private *priv; - FTS *sp; FTSENT *p, *root; FTSENT *parent, *tmp; size_t len, nitems; - /* Options check. */ - if (options & ~FTS_OPTIONMASK) { - errno = EINVAL; - return (NULL); - } - - /* fts_open() requires at least one path */ - if (*argv == NULL) { - errno = EINVAL; - return (NULL); - } - - /* Allocate/initialize the stream. */ - if ((priv = calloc(1, sizeof(*priv))) == NULL) - return (NULL); - sp = &priv->ftsp_fts; - sp->fts_compar = compar; - sp->fts_options = options; - /* Logical walks turn on NOCHDIR; symbolic links are too hard. */ if (ISSET(FTS_LOGICAL)) SET(FTS_NOCHDIR); + /* NOSTAT_TYPE implies NOSTAT */ + if (ISSET(FTS_NOSTAT_TYPE)) + SET(FTS_NOSTAT); + /* * Start out with 1K of path space, and enough, in any case, * to hold the user's paths. @@ -158,7 +153,9 @@ fts_open(char * const *argv, int options, p->fts_level = FTS_ROOTLEVEL; p->fts_parent = parent; p->fts_accpath = p->fts_name; - p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW), -1); + p->fts_info = fts_stat(sp, p, + ISSET(FTS_COMFOLLOWDIR) ? -1 : ISSET(FTS_COMFOLLOW), + -1); /* Command-line "." and ".." are real directories. */ if (p->fts_info == FTS_DOT) @@ -168,7 +165,7 @@ fts_open(char * const *argv, int options, * If comparison routine supplied, traverse in sorted * order; otherwise traverse in the order specified. */ - if (compar) { + if (sp->fts_compar) { p->fts_link = root; root = p; } else { @@ -181,7 +178,7 @@ fts_open(char * const *argv, int options, } } } - if (compar && nitems > 1) + if (sp->fts_compar && nitems > 1) root = fts_sort(sp, root, nitems); /* @@ -214,6 +211,97 @@ mem1: free(sp); return (NULL); } +FTS * +fts_open(char * const *argv, int options, + int (*compar)(const FTSENT * const *, const FTSENT * const *)) +{ + struct _fts_private *priv; + FTS *sp; + + /* Options check. */ + if (options & ~FTS_OPTIONMASK) { + errno = EINVAL; + return (NULL); + } + + /* fts_open() requires at least one path */ + if (*argv == NULL) { + errno = EINVAL; + return (NULL); + } + + /* Allocate/initialize the stream. */ + if ((priv = calloc(1, sizeof(*priv))) == NULL) + return (NULL); + sp = &priv->ftsp_fts; + sp->fts_compar = compar; + sp->fts_options = options; + + return (__fts_open(sp, argv)); +} + +#ifdef __BLOCKS__ +FTS * +fts_open_b(char * const *argv, int options, + int (^compar)(const FTSENT * const *, const FTSENT * const *)) +#else +FTS * +fts_open_b(char * const *argv, int options, fts_block compar) +#endif /* __BLOCKS__ */ +{ + struct _fts_private *priv; + FTS *sp; + + /* No blocks, no problems. */ + if (compar == NULL) + return (fts_open(argv, options, NULL)); + + /* Avoid segfault if blocks runtime is missing. */ + if (_Block_copy == NULL) { + errno = ENOSYS; + return (NULL); + } + + /* Options check. */ + if (options & ~FTS_OPTIONMASK) { + errno = EINVAL; + return (NULL); + } + + /* fts_open() requires at least one path */ + if (*argv == NULL) { + errno = EINVAL; + return (NULL); + } + + /* Allocate/initialize the stream. */ + if ((priv = calloc(1, sizeof(*priv))) == NULL) + return (NULL); + sp = &priv->ftsp_fts; +#ifdef __BLOCKS__ + compar = Block_copy(compar); +#else + if (compar->isa != &_NSConcreteGlobalBlock) + compar = _Block_copy(compar); +#endif /* __BLOCKS__ */ + if (compar == NULL) { + free(priv); + return (NULL); + } + sp->fts_compar_b = compar; + sp->fts_options = options | FTS_COMPAR_B; + + if ((sp = __fts_open(sp, argv)) == NULL) { +#ifdef __BLOCKS__ + Block_release(compar); +#else + if (compar->isa != &_NSConcreteGlobalBlock) + _Block_release(compar); +#endif /* __BLOCKS__ */ + } + return (sp); +} + static void fts_load(FTS *sp, FTSENT *p) { @@ -265,6 +353,17 @@ fts_close(FTS *sp) free(sp->fts_array); free(sp->fts_path); + /* Free up any block pointer. */ + if (ISSET(FTS_COMPAR_B) && sp->fts_compar_b != NULL) { +#ifdef __BLOCKS__ + Block_release(sp->fts_compar_b); +#else + if (((fts_block)(sp->fts_compar_b))->isa != + &_NSConcreteGlobalBlock) + _Block_release(sp->fts_compar_b); +#endif /* __BLOCKS__ */ + } + /* Return to original directory, save errno if necessary. */ if (!ISSET(FTS_NOCHDIR)) { saved_errno = fchdir(sp->fts_rfd) ? errno : 0; @@ -650,14 +749,10 @@ fts_build(FTS *sp, int type) * Open the directory for reading. If this fails, we're done. * If being called from fts_read, set the fts_info field. */ -#ifdef FTS_WHITEOUT if (ISSET(FTS_WHITEOUT)) oflag = DTF_NODUP; else oflag = DTF_HIDEW | DTF_NODUP; -#else -#define __opendir2(path, flag) opendir(path) -#endif if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) { if (type == BREAD) { cur->fts_info = FTS_DNR; @@ -784,10 +879,8 @@ mem1: saved_errno = errno; p->fts_parent = sp->fts_cur; p->fts_pathlen = len + dnamlen; -#ifdef FTS_WHITEOUT if (dp->d_type == DT_WHT) p->fts_flags |= FTS_ISW; -#endif if (cderrno) { if (nlinks) { @@ -796,12 +889,8 @@ mem1: saved_errno = errno; } else p->fts_info = FTS_NSOK; p->fts_accpath = cur->fts_accpath; - } else if (nlinks == 0 -#ifdef DT_DIR - || (nostat && - dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN) -#endif - ) { + } else if (nlinks == 0 || (nostat && + dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)) { p->fts_accpath = ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name; p->fts_info = FTS_NSOK; @@ -821,6 +910,25 @@ mem1: saved_errno = errno; p->fts_info == FTS_DC || p->fts_info == FTS_DOT)) --nlinks; } + if (p->fts_info == FTS_NSOK && ISSET(FTS_NOSTAT_TYPE)) { + switch (dp->d_type) { + case DT_FIFO: + case DT_CHR: + case DT_BLK: + case DT_SOCK: + p->fts_info = FTS_DEFAULT; + break; + case DT_REG: + p->fts_info = FTS_F; + break; + case DT_LNK: + p->fts_info = FTS_SL; + break; + case DT_WHT: + p->fts_info = FTS_W; + break; + } + } /* We walk in directory order so "ls -f" doesn't get upset. */ p->fts_link = NULL; @@ -897,18 +1005,19 @@ fts_stat(FTS *sp, FTSENT *p, int follow, int dfd) dev_t dev; ino_t ino; struct stat *sbp, sb; - int saved_errno; + int ret, saved_errno; const char *path; - if (dfd == -1) - path = p->fts_accpath, dfd = AT_FDCWD; - else + if (dfd == -1) { + path = p->fts_accpath; + dfd = AT_FDCWD; + } else { path = p->fts_name; + } /* If user needs stat info, stat buffer already allocated. */ sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; -#ifdef FTS_WHITEOUT /* Check for whiteout. */ if (p->fts_flags & FTS_ISW) { if (sbp != &sb) { @@ -917,22 +1026,27 @@ fts_stat(FTS *sp, FTSENT *p, int follow, int dfd) } return (FTS_W); } -#endif /* - * If doing a logical walk, or application requested FTS_FOLLOW, do - * a stat(2). If that fails, check for a non-existent symlink. If - * fail, set the errno from the stat call. + * If doing a logical walk, or caller requested FTS_COMFOLLOW, do + * a full stat(2). If that fails, do an lstat(2) to check for a + * non-existent symlink. If that fails, set the errno from the + * stat(2) call. + * + * As a special case, if stat(2) succeeded but the target is not a + * directory and follow is negative (indicating FTS_COMFOLLOWDIR + * rather than FTS_COMFOLLOW), we also revert to lstat(2). */ if (ISSET(FTS_LOGICAL) || follow) { - if (fstatat(dfd, path, sbp, 0)) { + if ((ret = fstatat(dfd, path, sbp, 0)) != 0 || + (follow < 0 && !S_ISDIR(sbp->st_mode))) { saved_errno = errno; if (fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) { p->fts_errno = saved_errno; goto err; } errno = 0; - if (S_ISLNK(sbp->st_mode)) + if (ret != 0 && S_ISLNK(sbp->st_mode)) return (FTS_SLNONE); } } else if (fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) { @@ -977,21 +1091,6 @@ err: memset(sbp, 0, sizeof(struct stat)); return (FTS_DEFAULT); } -/* - * The comparison function takes pointers to pointers to FTSENT structures. - * Qsort wants a comparison function that takes pointers to void. - * (Both with appropriate levels of const-poisoning, of course!) - * Use a trampoline function to deal with the difference. - */ -static int -fts_compar(const void *a, const void *b) -{ - FTS *parent; - - parent = (*(const FTSENT * const *)a)->fts_fts; - return (*parent->fts_compar)(a, b); -} - static FTSENT * fts_sort(FTS *sp, FTSENT *head, size_t nitems) { @@ -1014,7 +1113,18 @@ fts_sort(FTS *sp, FTSENT *head, size_t nitems) } for (ap = sp->fts_array, p = head; p; p = p->fts_link) *ap++ = p; - qsort(sp->fts_array, nitems, sizeof(FTSENT *), fts_compar); + if (ISSET(FTS_COMPAR_B)) { +#ifdef __BLOCKS__ + qsort_b(sp->fts_array, nitems, sizeof(FTSENT *), + (int (^)(const void *, const void *))sp->fts_compar_b); +#else + qsort_b(sp->fts_array, nitems, sizeof(FTSENT *), + sp->fts_compar_b); +#endif /* __BLOCKS__ */ + } else { + qsort(sp->fts_array, nitems, sizeof(FTSENT *), + (int (*)(const void *, const void *))sp->fts_compar); + } for (head = *(ap = sp->fts_array); --nitems; ++ap) ap[0]->fts_link = ap[1]; ap[0]->fts_link = NULL; diff --git a/lib/libc/gen/gen-private.h b/lib/libc/gen/gen-private.h index 3792a61ff942..b6749b3435cd 100644 --- a/lib/libc/gen/gen-private.h +++ b/lib/libc/gen/gen-private.h @@ -43,8 +43,8 @@ struct pthread_mutex; */ struct _dirdesc { int dd_fd; /* file descriptor associated with directory */ - long dd_loc; /* offset in current buffer */ - long dd_size; /* amount of data returned by getdirentries */ + size_t dd_loc; /* offset in current buffer */ + size_t dd_size; /* amount of data returned by getdirentries */ char *dd_buf; /* data buffer */ int dd_len; /* size of data buffer */ off_t dd_seek; /* magic cookie returned by getdirentries */ diff --git a/lib/libc/gen/glob.3 b/lib/libc/gen/glob.3 index 006e8decb3db..839d98ce02b5 100644 --- a/lib/libc/gen/glob.3 +++ b/lib/libc/gen/glob.3 @@ -27,11 +27,12 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd December 20, 2011 +.Dd June 23, 2025 .Dt GLOB 3 .Os .Sh NAME .Nm glob , +.Nm glob_b , .Nm globfree .Nd generate pathnames matching a pattern .Sh LIBRARY @@ -39,7 +40,9 @@ .Sh SYNOPSIS .In glob.h .Ft int -.Fn glob "const char * restrict pattern" "int flags" "int (*errfunc)(const char *, int)" "glob_t * restrict pglob" +.Fn glob "const char * restrict pattern" "int flags" "int (*errfunc)(const char *epath, int errno)" "glob_t * restrict pglob" +.Ft int +.Fn glob_b "const char * restrict pattern" "int flags" "int (^errblk)(const char *epath, int errno)" "glob_t * restrict pglob" .Ft void .Fn globfree "glob_t *pglob" .Sh DESCRIPTION @@ -272,10 +275,24 @@ is .Pf non- Dv NULL , .Fn glob calls -.Fa \*(lp*errfunc\*(rp Ns ( Fa path , errno ) , +.Fa \*(lp*errfunc\*(rp Ns ( Fa path , errno ) . +This may be unintuitive: a pattern like +.Ql */Makefile +will try to +.Xr stat 2 +.Ql foo/Makefile +even if +.Ql foo +is not a directory, resulting in a +call to +.Fa errfunc . +The error routine can suppress this action by testing for +.Er ENOENT +and +.Er ENOTDIR ; however, the .Dv GLOB_ERR -flag will cause an immediate +flag will still cause an immediate return when this happens. .Pp If @@ -307,16 +324,27 @@ or returns zero, the error is ignored. .Pp The +.Fn glob_b +function is like +.Fn glob +except that the error callback is a block pointer instead of a function +pointer. +.Pp +The .Fn globfree function frees any space associated with .Fa pglob from a previous call(s) to -.Fn glob . +.Fn glob +or +.Fn glob_b . .Sh RETURN VALUES On successful completion, .Fn glob -returns zero. -In addition the fields of +and +.Fn glob_b +return zero. +In addition, the fields of .Fa pglob contain the values described below: .Bl -tag -width GLOB_NOCHECK @@ -324,12 +352,16 @@ contain the values described below: contains the total number of matched pathnames so far. This includes other matches from previous invocations of .Fn glob +or +.Fn glob_b if .Dv GLOB_APPEND was specified. .It Fa gl_matchc contains the number of matched pathnames in the current invocation of -.Fn glob . +.Fn glob +or +.Fn glob_b . .It Fa gl_flags contains a copy of the .Fa flags @@ -352,6 +384,8 @@ are undefined. .Pp If .Fn glob +or +.Fn glob_b terminates due to an error, it sets errno and returns one of the following non-zero constants, which are defined in the include file @@ -397,6 +431,14 @@ g.gl_pathv[0] = "ls"; g.gl_pathv[1] = "-l"; execvp("ls", g.gl_pathv); .Ed +.Sh CAVEATS +The +.Fn glob +and +.Fn glob_b +functions +will not match filenames that begin with a period +unless this is specifically requested (e.g., by ".*"). .Sh SEE ALSO .Xr sh 1 , .Xr fnmatch 3 , @@ -435,6 +477,10 @@ and .Fn globfree functions first appeared in .Bx 4.4 . +The +.Fn glob_b +function first appeared in +.Fx 15.0 . .Sh BUGS Patterns longer than .Dv MAXPATHLEN @@ -442,7 +488,9 @@ may cause unchecked errors. .Pp The .Fn glob -argument +and +.Fn glob_b +functions may fail and set errno for any of the errors specified for the library routines .Xr stat 2 , diff --git a/lib/libc/gen/glob.c b/lib/libc/gen/glob.c index 7a988196549a..f7da5f0cda09 100644 --- a/lib/libc/gen/glob.c +++ b/lib/libc/gen/glob.c @@ -88,8 +88,11 @@ #include <unistd.h> #include <wchar.h> +#include "block_abi.h" #include "collate.h" +typedef DECLARE_BLOCK(int, glob_b_block, const char*, int); + /* * glob(3) expansion limits. Stop the expansion if any of these limits * is reached. This caps the runtime in the face of DoS attacks. See @@ -104,8 +107,8 @@ struct glob_limit { size_t l_brace_cnt; size_t l_path_lim; - size_t l_readdir_cnt; - size_t l_stat_cnt; + size_t l_readdir_cnt; + size_t l_stat_cnt; size_t l_string_cnt; }; @@ -179,9 +182,8 @@ static int err_aborted(glob_t *, int, char *); static void qprintf(const char *, Char *); #endif -int -glob(const char * __restrict pattern, int flags, - int (*errfunc)(const char *, int), glob_t * __restrict pglob) +static int +__glob(const char *pattern, glob_t *pglob) { struct glob_limit limit = { 0, 0, 0, 0, 0 }; const char *patnext; @@ -192,25 +194,23 @@ glob(const char * __restrict pattern, int flags, int too_long; patnext = pattern; - if (!(flags & GLOB_APPEND)) { + if (!(pglob->gl_flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; - if (!(flags & GLOB_DOOFFS)) + if (!(pglob->gl_flags & GLOB_DOOFFS)) pglob->gl_offs = 0; } - if (flags & GLOB_LIMIT) { + if (pglob->gl_flags & GLOB_LIMIT) { limit.l_path_lim = pglob->gl_matchc; if (limit.l_path_lim == 0) limit.l_path_lim = GLOB_LIMIT_PATH; } - pglob->gl_flags = flags & ~GLOB_MAGCHAR; - pglob->gl_errfunc = errfunc; pglob->gl_matchc = 0; bufnext = patbuf; bufend = bufnext + MAXPATHLEN - 1; too_long = 1; - if (flags & GLOB_NOESCAPE) { + if (pglob->gl_flags & GLOB_NOESCAPE) { memset(&mbs, 0, sizeof(mbs)); while (bufnext <= bufend) { clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs); @@ -250,15 +250,45 @@ glob(const char * __restrict pattern, int flags, return (err_nomatch(pglob, &limit, pattern)); *bufnext = EOS; - if (flags & GLOB_BRACE) + if (pglob->gl_flags & GLOB_BRACE) return (globexp0(patbuf, pglob, &limit, pattern)); else return (glob0(patbuf, pglob, &limit, pattern)); } +int +glob(const char * __restrict pattern, int flags, + int (*errfunc)(const char *, int), glob_t * __restrict pglob) +{ + int rv; + + pglob->gl_flags = flags & ~(GLOB_MAGCHAR | _GLOB_ERR_BLOCK); + pglob->gl_errfunc = errfunc; + rv = __glob(pattern, pglob); + pglob->gl_errfunc = NULL; + + return (rv); +} + +int +glob_b(const char * __restrict pattern, int flags, + glob_b_block block, glob_t * __restrict pglob) +{ + int rv; + + pglob->gl_flags = flags & ~GLOB_MAGCHAR; + pglob->gl_flags |= _GLOB_ERR_BLOCK; + pglob->gl_errblk = block; + rv = __glob(pattern, pglob); + pglob->gl_errblk = NULL; + + return (rv); +} + static int globexp0(const Char *pattern, glob_t *pglob, struct glob_limit *limit, - const char *origpat) { + const char *origpat) +{ int rv; size_t oldpathc; @@ -724,7 +754,7 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last, return (GLOB_NOSPACE); } *pathend = EOS; - if (pglob->gl_errfunc != NULL && + if ((pglob->gl_errfunc != NULL || pglob->gl_errblk != NULL) && g_Ctoc(pathbuf, buf, sizeof(buf))) { errno = E2BIG; return (GLOB_NOSPACE); @@ -1085,10 +1115,21 @@ err_nomatch(glob_t *pglob, struct glob_limit *limit, const char *origpat) { } static int -err_aborted(glob_t *pglob, int err, char *buf) { - if ((pglob->gl_errfunc != NULL && pglob->gl_errfunc(buf, err)) || - (pglob->gl_flags & GLOB_ERR)) +err_aborted(glob_t *pglob, int err, char *buf) +{ + int rv = 0; + + if ((pglob->gl_flags & _GLOB_ERR_BLOCK) != 0) { + if (pglob->gl_errblk != NULL) + rv = CALL_BLOCK((glob_b_block)pglob->gl_errblk, buf, + errno); + } else if (pglob->gl_errfunc != NULL) { + rv = pglob->gl_errfunc(buf, errno); + } + /* GLOB_ERR is allowed to override the error callback function. */ + if (rv != 0 || pglob->gl_flags & GLOB_ERR) { return (GLOB_ABORTED); + } return (0); } diff --git a/lib/libc/gen/inotify.c b/lib/libc/gen/inotify.c new file mode 100644 index 000000000000..7ce53aaccd58 --- /dev/null +++ b/lib/libc/gen/inotify.c @@ -0,0 +1,48 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Klara, Inc. + */ + +#include "namespace.h" +#include <sys/fcntl.h> +#include <sys/inotify.h> +#include <sys/specialfd.h> +#include "un-namespace.h" +#include "libc_private.h" + +/* + * Provide compatibility with libinotify, which uses different values for these + * flags. + */ +#define IN_NONBLOCK_OLD 0x80000 +#define IN_CLOEXEC_OLD 0x00800 + +int +inotify_add_watch(int fd, const char *pathname, uint32_t mask) +{ + return (inotify_add_watch_at(fd, AT_FDCWD, pathname, mask)); +} + +int +inotify_init1(int flags) +{ + struct specialfd_inotify args; + + if ((flags & IN_NONBLOCK_OLD) != 0) { + flags &= ~IN_NONBLOCK_OLD; + flags |= IN_NONBLOCK; + } + if ((flags & IN_CLOEXEC_OLD) != 0) { + flags &= ~IN_CLOEXEC_OLD; + flags |= IN_CLOEXEC; + } + args.flags = flags; + return (__sys___specialfd(SPECIALFD_INOTIFY, &args, sizeof(args))); +} + +int +inotify_init(void) +{ + return (inotify_init1(0)); +} diff --git a/lib/libc/gen/libc_interposing_table.c b/lib/libc/gen/libc_interposing_table.c index d15d32711910..025a67ac3eac 100644 --- a/lib/libc/gen/libc_interposing_table.c +++ b/lib/libc/gen/libc_interposing_table.c @@ -42,7 +42,7 @@ interpos_func_t __libc_interposing[INTERPOS_MAX] = { SLOT(spinlock, __libc_spinlock_stub), SLOT(spinunlock, __libc_spinunlock_stub), SLOT(map_stacks_exec, __libc_map_stacks_exec), - SLOT(distribute_static_tls, __libc_distribute_static_tls), + SLOT(uexterr_gettext, __libc_uexterr_gettext), }; #undef SLOT diff --git a/lib/libc/gen/opendir.c b/lib/libc/gen/opendir.c index 956c92c321e8..08d9eb10eaa2 100644 --- a/lib/libc/gen/opendir.c +++ b/lib/libc/gen/opendir.c @@ -30,14 +30,7 @@ */ #include "namespace.h" -#include <sys/param.h> - #include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> #include "un-namespace.h" #include "gen-private.h" diff --git a/lib/libc/gen/opendir2.c b/lib/libc/gen/opendir2.c index 30a9030693e4..c5c2e662efd8 100644 --- a/lib/libc/gen/opendir2.c +++ b/lib/libc/gen/opendir2.c @@ -30,11 +30,12 @@ */ #include "namespace.h" -#include <sys/param.h> +#include <sys/types.h> #include <dirent.h> #include <errno.h> #include <fcntl.h> +#include <stdbool.h> #include <stdlib.h> #include <string.h> #include <unistd.h> @@ -52,8 +53,7 @@ __opendir2(const char *name, int flags) if ((flags & (__DTF_READALL | __DTF_SKIPREAD)) != 0) return (NULL); - if ((fd = _open(name, - O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC)) == -1) + if ((fd = _open(name, O_DIRECTORY | O_RDONLY | O_CLOEXEC)) == -1) return (NULL); dir = __opendir_common(fd, flags, false); @@ -243,20 +243,18 @@ _filldir(DIR *dirp, bool use_current_pos) return (true); } +/* + * Return true if the file descriptor is associated with a file from a + * union file system or from a file system mounted with the union flag. + */ static bool is_unionstack(int fd) { - int unionstack; - - unionstack = _fcntl(fd, F_ISUNIONSTACK, 0); - if (unionstack != -1) - return (unionstack); - /* - * Should not happen unless running on a kernel without the op, - * but no use rendering the system useless in such a case. + * This call shouldn't fail, but if it does, just assume that the + * answer is no. */ - return (0); + return (_fcntl(fd, F_ISUNIONSTACK, 0) > 0); } /* @@ -266,6 +264,7 @@ DIR * __opendir_common(int fd, int flags, bool use_current_pos) { DIR *dirp; + ssize_t ret; int incr; int saved_errno; bool unionstack; @@ -315,13 +314,11 @@ __opendir_common(int fd, int flags, bool use_current_pos) * to prime dd_seek. This also checks if the * fd passed to fdopendir() is a directory. */ - dirp->dd_size = _getdirentries(dirp->dd_fd, + ret = _getdirentries(dirp->dd_fd, dirp->dd_buf, dirp->dd_len, &dirp->dd_seek); - if (dirp->dd_size < 0) { - if (errno == EINVAL) - errno = ENOTDIR; + if (ret < 0) goto fail; - } + dirp->dd_size = (size_t)ret; dirp->dd_flags |= __DTF_SKIPREAD; } else { dirp->dd_size = 0; diff --git a/lib/libc/gen/posix_spawn.c b/lib/libc/gen/posix_spawn.c index ee2ce05ff317..a5b732696b8c 100644 --- a/lib/libc/gen/posix_spawn.c +++ b/lib/libc/gen/posix_spawn.c @@ -261,7 +261,7 @@ _posix_spawn_thr(void *data) } envp = psa->envp != NULL ? psa->envp : environ; if (psa->use_env_path) - execvpe(psa->path, psa->argv, envp); + __libc_execvpe(psa->path, psa->argv, envp); else _execve(psa->path, psa->argv, envp); psa->error = errno; diff --git a/lib/libc/gen/psignal.3 b/lib/libc/gen/psignal.3 index cd3cef0b44a9..098b7b02a9b9 100644 --- a/lib/libc/gen/psignal.3 +++ b/lib/libc/gen/psignal.3 @@ -25,14 +25,17 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 30, 2016 +.Dd May 10, 2025 .Dt PSIGNAL 3 .Os .Sh NAME .Nm psignal , +.Nm psiginfo , .Nm strsignal , .Nm sys_siglist , -.Nm sys_signame +.Nm sys_signame , +.Nm sig2str , +.Nm str2sig .Nd system signal messages .Sh LIBRARY .Lb libc @@ -40,11 +43,17 @@ .In signal.h .Ft void .Fn psignal "int sig" "const char *s" +.Ft void +.Fn psiginfo "const siginfo_t *si" "const char *s" .Vt extern const char * const sys_siglist[] ; .Vt extern const char * const sys_signame[] ; .In string.h .Ft "char *" .Fn strsignal "int sig" +.Ft int +.Fn sig2str "int signum" "char *str" +.Ft int +.Fn str2sig "char *str" "int *pnum" .Sh DESCRIPTION The .Fn psignal @@ -79,6 +88,16 @@ the string .Dq "Unknown signal" is produced. .Pp +The +.Fn psiginfo +function is similar to +.Fn psignal , +except that the signal number information is taken from the +.Fa si +argument which is a +.Vt siginfo_t +structure. +.Pp The message strings can be accessed directly through the external array .Va sys_siglist , @@ -95,12 +114,65 @@ contains a count of the strings in .Va sys_siglist and .Va sys_signame . +.Pp +The +.Fn sig2str +function translates the signal number +.Fa signum +to the signal name, without the +.Dq SIG +prefix, and stores it at the location specified by +.Fa str , +which should be large enough to hold the name and the terminating +.Dv NUL +byte. +The symbol +.Dv SIG2STR_MAX +gives the maximum size in bytes required. +.Pp +The +.Fn str2sig +function translates the signal name +.Fa str +to a signal number and stores it in the location referenced by +.Fa pnum . +The name in +.Fa str +can be either the name of the signal, with or without the +.Dq SIG +prefix, or a decimal number. .Sh SEE ALSO .Xr sigaction 2 , .Xr perror 3 , .Xr strerror 3 +.Sh STANDARDS +The +.Fn psignal +and +.Fn psiginfo +functions are defined by +.St -p1003.1-2008 +, while the +.Fn sig2str +and +.Fn str2sig +functions are defined by +.St -p1003.1-2024 . .Sh HISTORY The .Fn psignal function appeared in .Bx 4.2 . +The +.Fn psiginfo +function appeared in +.Fx 14.3 , +.Nx 6.0 , +and +.Dx 4.1 . +The +.Fn sig2str +and +.Fn str2sig +functions appeared in +.Fx 15.0 . diff --git a/lib/libc/gen/psignal.c b/lib/libc/gen/psignal.c index ab044f683d86..291a6a9337a0 100644 --- a/lib/libc/gen/psignal.c +++ b/lib/libc/gen/psignal.c @@ -55,3 +55,9 @@ psignal(int sig, const char *s) (void)_write(STDERR_FILENO, c, strlen(c)); (void)_write(STDERR_FILENO, "\n", 1); } + +void +psiginfo(const siginfo_t *si, const char *s) +{ + psignal(si->si_signo, s); +} diff --git a/lib/libc/gen/readdir.c b/lib/libc/gen/readdir.c index 2a2fa999b7ce..b70102954df1 100644 --- a/lib/libc/gen/readdir.c +++ b/lib/libc/gen/readdir.c @@ -48,8 +48,9 @@ struct dirent * _readdir_unlocked(DIR *dirp, int flags) { struct dirent *dp; - long initial_seek; - long initial_loc = 0; + off_t initial_seek; + size_t initial_loc = 0; + ssize_t ret; for (;;) { if (dirp->dd_loc >= dirp->dd_size) { @@ -61,11 +62,13 @@ _readdir_unlocked(DIR *dirp, int flags) } if (dirp->dd_loc == 0 && !(dirp->dd_flags & (__DTF_READALL | __DTF_SKIPREAD))) { + dirp->dd_size = 0; initial_seek = dirp->dd_seek; - dirp->dd_size = _getdirentries(dirp->dd_fd, + ret = _getdirentries(dirp->dd_fd, dirp->dd_buf, dirp->dd_len, &dirp->dd_seek); - if (dirp->dd_size <= 0) + if (ret <= 0) return (NULL); + dirp->dd_size = (size_t)ret; _fixtelldir(dirp, initial_seek, initial_loc); } dirp->dd_flags &= ~__DTF_SKIPREAD; diff --git a/lib/libc/gen/rtld_get_var.3 b/lib/libc/gen/rtld_get_var.3 index e211d78345e3..092114e86d78 100644 --- a/lib/libc/gen/rtld_get_var.3 +++ b/lib/libc/gen/rtld_get_var.3 @@ -103,4 +103,4 @@ is unknown. The .Nm function first appeared in -.Fx 15.0 . +.Fx 14.3 . diff --git a/lib/libc/gen/scandir.3 b/lib/libc/gen/scandir.3 index 6656842c251f..3da4500cefb9 100644 --- a/lib/libc/gen/scandir.3 +++ b/lib/libc/gen/scandir.3 @@ -25,13 +25,16 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 31, 2023 +.Dd June 25, 2025 .Dt SCANDIR 3 .Os .Sh NAME .Nm scandir , +.Nm fdscandir , .Nm scandirat , .Nm scandir_b , +.Nm fdscandir_b , +.Nm fdscandirat_b , .Nm alphasort , .Nm versionsort .Nd scan a directory @@ -47,6 +50,13 @@ .Fa "int \*(lp*compar\*(rp\*(lpconst struct dirent **, const struct dirent **\*(rp" .Fc .Ft int +.Fo fdscandir +.Fa "int dirfd" +.Fa "struct dirent ***namelist" +.Fa "int \*(lp*select\*(rp\*(lpconst struct dirent *\*(rp" +.Fa "int \*(lp*compar\*(rp\*(lpconst struct dirent **, const struct dirent **\*(rp" +.Fc +.Ft int .Fo scandirat .Fa "int dirfd" .Fa "const char *dirname" @@ -62,6 +72,21 @@ .Fa "int \*(lp^compar\*(rp\*(lpconst struct dirent **, const struct dirent **\*(rp" .Fc .Ft int +.Fo fdscandir_b +.Fa "int dirfd" +.Fa "struct dirent ***namelist" +.Fa "int \*(lp^select\*(rp\*(lpconst struct dirent *\*(rp" +.Fa "int \*(lp^compar\*(rp\*(lpconst struct dirent **, const struct dirent **\*(rp" +.Fc +.Ft int +.Fo scandirat_b +.Fa "int dirfd" +.Fa "const char *dirname" +.Fa "struct dirent ***namelist" +.Fa "int \*(lp^select\*(rp\*(lpconst struct dirent *\*(rp" +.Fa "int \*(lp^compar\*(rp\*(lpconst struct dirent **, const struct dirent **\*(rp" +.Fc +.Ft int .Fn alphasort "const struct dirent **d1" "const struct dirent **d2" .Ft int .Fn versionsort "const struct dirent **d1" "const struct dirent **d2" @@ -77,7 +102,8 @@ entries using It returns the number of entries in the array. A pointer to the array of directory entries is stored in the location referenced by -.Fa namelist . +.Fa namelist +(even if no entries were selected). .Pp The .Fa select @@ -118,6 +144,13 @@ The memory allocated for the array can be deallocated with by freeing each pointer in the array and then the array itself. .Pp The +.Fn fdscandir +function is similar to +.Fn scandir , +but takes a file descriptor referencing a directory instead of a path. +The file descriptor is left open on return, regardless of outcome. +.Pp +The .Fn scandirat function is similar to .Fn scandir , @@ -151,17 +184,67 @@ See for additional details. .Pp The -.Fn scandir_b -function behaves in the same way as +.Fn scandir_b , +.Fn fdscandir_b , +and +.Fn scandirat_b +functions behave in the same way as .Fn scandir , -but takes blocks as arguments instead of function pointers and calls +.Fn fdscandir , +and +.Fn scandirat , +respectively, +but take blocks as arguments instead of function pointers and call .Fn qsort_b rather than .Fn qsort . .Sh DIAGNOSTICS -Returns \-1 if the directory cannot be opened for reading or if +The +.Fn scandir , +.Fn fdscandir , +.Fn scandirat , +.Fn scandir_b , +.Fn fdscandir_b , +and +.Fn scandirat_b +functions return the number of directory entries found on succes. +If the directory cannot be opened for reading, an error occurs +while reading the directory, or .Xr malloc 3 -cannot allocate enough memory to hold all the data structures. +cannot allocate enough memory to hold all the directory entries, +they return \-1 and set +.Va errno +to an appropriate value. +.Sh ERRORS +The +.Fn scandir , +.Fn scandirat , +.Fn scandir_b , +and +.Fn scandirat_b +functions may fail and set +.Va errno +for any of the errors specified for the +.Xr opendir 3 , +.Xr malloc 3 , +.Xr readdir 3 , +and +.Xr closedir 3 +functions. +.Pp +The +.Fn fdscandir +and +.Fn fdscandir_b +functions may fail and set +.Va errno +for any of the errors specified for the +.Xr fdopendir 3 , +.Xr malloc 3 , +.Xr readdir 3 , +and +.Xr closedir 3 +functions. .Sh SEE ALSO .Xr openat 2 , .Xr directory 3 , @@ -172,8 +255,25 @@ cannot allocate enough memory to hold all the data structures. .Xr dir 5 .Sh STANDARDS The +.Fn alphasort +and +.Fn scandir +functions are expected to conform to +.St -p1003.1-2008 . +The +.Fn scandirat +and .Fn versionsort -function is a GNU extension and conforms to no standard. +functions are GNU extensions and conform to no standard. +The +.Fn fdscandir , +.Fn scandir_b , +.Fn fdscandir_b , +and +.Fn scandirat_b +functions are +.Fx +extensions. .Sh HISTORY The .Fn scandir @@ -182,8 +282,19 @@ and functions appeared in .Bx 4.2 . The +.Fn scandir_b +function was added in +.Fx 11.0 . +The .Fn scandirat and .Fn versionsort functions were added in .Fx 13.2 . +The +.Fn fdscandir , +.Fn fdscandir_b , +and +.Fn scandirat_b +functions were added in +.Fx 15.0 . diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c index f59f57047278..fb589f4b36b6 100644 --- a/lib/libc/gen/scandir.c +++ b/lib/libc/gen/scandir.c @@ -38,6 +38,7 @@ #include "namespace.h" #include <dirent.h> +#include <errno.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> @@ -64,71 +65,76 @@ static int scandir_thunk_cmp(const void *p1, const void *p2, void *thunk); static int #ifdef I_AM_SCANDIR_B -scandir_b_dirp(DIR *dirp, struct dirent ***namelist, select_block select, +scandir_dirp_b(DIR *dirp, struct dirent ***namelist, select_block select, dcomp_block dcomp) #else scandir_dirp(DIR *dirp, struct dirent ***namelist, - int (*select)(const struct dirent *), int (*dcomp)(const struct dirent **, - const struct dirent **)) + int (*select)(const struct dirent *), + int (*dcomp)(const struct dirent **, const struct dirent **)) #endif { - struct dirent *d, *p, **names = NULL; - size_t arraysz, numitems; + struct dirent *d, *p = NULL, **names = NULL, **names2; + size_t arraysz = 32, numitems = 0; + int serrno; - numitems = 0; - arraysz = 32; /* initial estimate of the array size */ - names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *)); + names = malloc(arraysz * sizeof(*names)); if (names == NULL) - goto fail; + return (-1); - while ((d = readdir(dirp)) != NULL) { + while (errno = 0, (d = readdir(dirp)) != NULL) { if (select != NULL && !SELECT(d)) continue; /* just selected names */ /* * Make a minimum size copy of the data */ - p = (struct dirent *)malloc(_GENERIC_DIRSIZ(d)); + p = malloc(_GENERIC_DIRSIZ(d)); if (p == NULL) goto fail; p->d_fileno = d->d_fileno; p->d_type = d->d_type; p->d_reclen = d->d_reclen; p->d_namlen = d->d_namlen; - bcopy(d->d_name, p->d_name, p->d_namlen + 1); + memcpy(p->d_name, d->d_name, p->d_namlen + 1); /* * Check to make sure the array has space left and * realloc the maximum size. */ if (numitems >= arraysz) { - struct dirent **names2; - - names2 = reallocarray(names, arraysz, - 2 * sizeof(struct dirent *)); - if (names2 == NULL) { - free(p); + arraysz = arraysz * 2; + names2 = reallocarray(names, arraysz, sizeof(*names)); + if (names2 == NULL) goto fail; - } names = names2; - arraysz *= 2; } names[numitems++] = p; } - closedir(dirp); - if (numitems && dcomp != NULL) + /* + * Since we can't simultaneously return both -1 and a count, we + * must either suppress the error or discard the partial result. + * The latter seems the lesser of two evils. + */ + if (errno != 0) + goto fail; + if (numitems > 0 && dcomp != NULL) { #ifdef I_AM_SCANDIR_B - qsort_b(names, numitems, sizeof(struct dirent *), (void*)dcomp); + qsort_b(names, numitems, sizeof(struct dirent *), + (void *)dcomp); #else qsort_r(names, numitems, sizeof(struct dirent *), scandir_thunk_cmp, &dcomp); #endif + } *namelist = names; return (numitems); fail: + serrno = errno; + if (numitems == 0 || names[numitems - 1] != p) + free(p); while (numitems > 0) free(names[--numitems]); free(names); - closedir(dirp); + errno = serrno; return (-1); } @@ -138,44 +144,87 @@ scandir_b(const char *dirname, struct dirent ***namelist, select_block select, dcomp_block dcomp) #else scandir(const char *dirname, struct dirent ***namelist, - int (*select)(const struct dirent *), int (*dcomp)(const struct dirent **, - const struct dirent **)) + int (*select)(const struct dirent *), + int (*dcomp)(const struct dirent **, const struct dirent **)) #endif { DIR *dirp; + int ret, serrno; dirp = opendir(dirname); if (dirp == NULL) return (-1); - return ( + ret = #ifdef I_AM_SCANDIR_B - scandir_b_dirp + scandir_dirp_b #else scandir_dirp #endif - (dirp, namelist, select, dcomp)); + (dirp, namelist, select, dcomp); + serrno = errno; + closedir(dirp); + errno = serrno; + return (ret); } -#ifndef I_AM_SCANDIR_B int -scandirat(int dirfd, const char *dirname, struct dirent ***namelist, - int (*select)(const struct dirent *), int (*dcomp)(const struct dirent **, - const struct dirent **)) +#ifdef I_AM_SCANDIR_B +fdscandir_b(int dirfd, struct dirent ***namelist, select_block select, + dcomp_block dcomp) +#else +fdscandir(int dirfd, struct dirent ***namelist, + int (*select)(const struct dirent *), + int (*dcomp)(const struct dirent **, const struct dirent **)) +#endif { DIR *dirp; - int fd; + int ret, serrno; + + dirp = fdopendir(dirfd); + if (dirp == NULL) + return (-1); + ret = +#ifdef I_AM_SCANDIR_B + scandir_dirp_b +#else + scandir_dirp +#endif + (dirp, namelist, select, dcomp); + serrno = errno; + fdclosedir(dirp); + errno = serrno; + return (ret); +} + +int +#ifdef I_AM_SCANDIR_B +scandirat_b(int dirfd, const char *dirname, struct dirent ***namelist, + select_block select, dcomp_block dcomp) +#else +scandirat(int dirfd, const char *dirname, struct dirent ***namelist, + int (*select)(const struct dirent *), + int (*dcomp)(const struct dirent **, const struct dirent **)) +#endif +{ + int fd, ret, serrno; fd = _openat(dirfd, dirname, O_RDONLY | O_DIRECTORY | O_CLOEXEC); if (fd == -1) return (-1); - dirp = fdopendir(fd); - if (dirp == NULL) { - _close(fd); - return (-1); - } - return (scandir_dirp(dirp, namelist, select, dcomp)); + ret = +#ifdef I_AM_SCANDIR_B + fdscandir_b +#else + fdscandir +#endif + (fd, namelist, select, dcomp); + serrno = errno; + _close(fd); + errno = serrno; + return (ret); } +#ifndef I_AM_SCANDIR_B /* * Alphabetic order comparison routine for those who want it. * POSIX 2008 requires that alphasort() uses strcoll(). diff --git a/lib/libc/gen/sig2str.c b/lib/libc/gen/sig2str.c new file mode 100644 index 000000000000..869a09ab9db4 --- /dev/null +++ b/lib/libc/gen/sig2str.c @@ -0,0 +1,113 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Ricardo Branco <rbranco@suse.de>. + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + */ + +/* + * Translate between signal names and numbers + */ +#include "namespace.h" +#include <ctype.h> +#include <limits.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ssp/ssp.h> +#include "un-namespace.h" + +static const char rtmin_str[] = "RTMIN"; +static const char rtmax_str[] = "RTMAX"; + +int +__ssp_real(sig2str)(int signum, char *str) +{ + if (signum <= 0 || signum > SIGRTMAX) + return (-1); + + if (signum < sys_nsig) + (void)strlcpy(str, sys_signame[signum], SIG2STR_MAX); + else if (signum < SIGRTMIN) + (void)snprintf(str, SIG2STR_MAX, "%d", signum); + else if (signum == SIGRTMIN) + (void)strlcpy(str, rtmin_str, SIG2STR_MAX); + else if (signum == SIGRTMAX) + (void)strlcpy(str, rtmax_str, SIG2STR_MAX); + else if (signum <= (SIGRTMIN + SIGRTMAX) / 2) + (void)snprintf(str, SIG2STR_MAX, "%s+%d", + rtmin_str, signum - SIGRTMIN); + else + (void)snprintf(str, SIG2STR_MAX, "%s-%d", + rtmax_str, SIGRTMAX - signum); + + return (0); +} + +int +str2sig(const char * restrict str, int * restrict pnum) +{ + const char *errstr; + long long n; + int sig; + int rtend = sizeof(rtmin_str) - 1; + + if (strncasecmp(str, "SIG", 3) == 0) + str += 3; + + if (strncasecmp(str, rtmin_str, sizeof(rtmin_str) - 1) == 0 || + strncasecmp(str, rtmax_str, sizeof(rtmax_str) - 1) == 0) { + sig = (toupper(str[4]) == 'X') ? SIGRTMAX : SIGRTMIN; + n = 0; + if (str[rtend] == '+' || str[rtend] == '-') { + n = strtonum(str + rtend, INT_MIN, INT_MAX, &errstr); + if (n == 0 || errstr != NULL) + return (-1); + } else if (str[rtend] != '\0') { + return (-1); + } + sig += (int)n; + if (sig < SIGRTMIN || sig > SIGRTMAX) + return (-1); + *pnum = sig; + return (0); + } + + if (isdigit((unsigned char)str[0])) { + n = strtonum(str, 1, SIGRTMAX, &errstr); + if (errstr == NULL) { + *pnum = (int)n; + return (0); + } + } + + for (sig = 1; sig < sys_nsig; sig++) { + if (strcasecmp(sys_signame[sig], str) == 0) { + *pnum = sig; + return (0); + } + } + + return (-1); +} diff --git a/lib/libc/gen/sysconf.c b/lib/libc/gen/sysconf.c index be42dd238b56..66562d0e29f0 100644 --- a/lib/libc/gen/sysconf.c +++ b/lib/libc/gen/sysconf.c @@ -34,6 +34,7 @@ #include "namespace.h" #include <sys/param.h> +#include <sys/exterrvar.h> #include <sys/time.h> #include <sys/sysctl.h> #include <sys/resource.h> @@ -286,6 +287,8 @@ do_NAME_MAX: mib[0] = CTL_P1003_1B; mib[1] = CTL_P1003_1B_MQ_OPEN_MAX; goto yesno; + case _SC_NSIG: + return (_SIG_MAXSIG); case _SC_PAGESIZE: return (getpagesize()); case _SC_RTSIG_MAX: @@ -567,7 +570,7 @@ yesno: case _SC_IPV6: #if _POSIX_IPV6 == 0 sverrno = errno; - value = _socket(PF_INET6, SOCK_DGRAM, 0); + value = _socket(PF_INET6, SOCK_CLOEXEC | SOCK_DGRAM, 0); errno = sverrno; if (value >= 0) { _close(value); @@ -602,6 +605,8 @@ yesno: return (-1); return ((long)value); #endif + case _SC_UEXTERR_MAXLEN: + return (UEXTERROR_MAXLEN); default: errno = EINVAL; diff --git a/lib/libc/gen/sysctl.3 b/lib/libc/gen/sysctl.3 index fb68ddd60edc..95e33dc802be 100644 --- a/lib/libc/gen/sysctl.3 +++ b/lib/libc/gen/sysctl.3 @@ -502,7 +502,6 @@ specifies the current process. .It Dv KERN_PROC_ENV Ta "Set of strings" .It Dv KERN_PROC_AUXV Ta "Elf_Auxinfo []" .It Dv KERN_PROC_RLIMIT Ta "Integer" -.It Dv KERN_PROC_RLIMIT_USAGE Ta "rlim_t []" .It Dv KERN_PROC_PS_STRINGS Ta "Integer" .It Dv KERN_PROC_UMASK Ta "Integer/short" .It Dv KERN_PROC_OSREL Ta "Integer" @@ -511,6 +510,7 @@ specifies the current process. .It Dv KERN_PROC_NFDS Ta "Integer" .It Dv KERN_PROC_SIGFASTBLK Ta "Integer" .It Dv KERN_PROC_VM_LAYOUT Ta "struct kinfo_vm_layout" +.It Dv KERN_PROC_RLIMIT_USAGE Ta "rlim_t []" .It Dv KERN_PROC_KQUEUE Ta "struct kinfo_knote []" .El .Pp @@ -549,13 +549,6 @@ Additinal OID name element must be supplied, specifiing the resource name as in .Xr getrlimit 2 . The call returns the given resource limit for the process. -.It Dv KERN_PROC_RLIMIT_USAGE -Like -.Dv KERN_PROC_RLIMIT , -but instead of the limit, returns the accounted resource usage. -For resources which do not have a meaningful current value, -.Li \-1 -is returned. .It Dv KERN_PROC_PS_STRINGS Returns the location of the .Vt ps_strings @@ -585,6 +578,13 @@ Returns the address of the location, if active. .It Dv KERN_PROC_VM_LAYOUT Fills a structure describing process virtual address space layout. +.It Dv KERN_PROC_RLIMIT_USAGE +Like +.Dv KERN_PROC_RLIMIT , +but instead of the limit, returns the accounted resource usage. +For resources which do not have a meaningful current value, +.Li \-1 +is returned. .It Dv KERN_PROC_KQUEUE Fills an array of structures describing events registered with the specified kqueue. diff --git a/lib/libc/gen/telldir.c b/lib/libc/gen/telldir.c index b751fafd975f..1731cc4d7a2c 100644 --- a/lib/libc/gen/telldir.c +++ b/lib/libc/gen/telldir.c @@ -118,7 +118,7 @@ _seekdir(DIR *dirp, long loc) struct dirent *dp; union ddloc_packed ddloc; off_t loc_seek; - long loc_loc; + size_t loc_loc; ddloc.l = loc; @@ -171,7 +171,7 @@ _seekdir(DIR *dirp, long loc) * fetching a new block to fix any such telldir locations. */ void -_fixtelldir(DIR *dirp, long oldseek, long oldloc) +_fixtelldir(DIR *dirp, off_t oldseek, size_t oldloc) { struct ddloc_mem *lp; diff --git a/lib/libc/gen/telldir.h b/lib/libc/gen/telldir.h index 6d113491e819..02fd52af9060 100644 --- a/lib/libc/gen/telldir.h +++ b/lib/libc/gen/telldir.h @@ -46,9 +46,9 @@ */ struct ddloc_mem { LIST_ENTRY(ddloc_mem) loc_lqe; /* entry in list */ - long loc_index; /* key associated with structure */ + size_t loc_index; /* key associated with structure */ off_t loc_seek; /* magic cookie returned by getdirentries */ - long loc_loc; /* offset of entry in buffer */ + size_t loc_loc; /* offset of entry in buffer */ }; #ifdef __LP64__ @@ -102,7 +102,7 @@ bool _filldir(DIR *, bool); struct dirent *_readdir_unlocked(DIR *, int); void _reclaim_telldir(DIR *); void _seekdir(DIR *, long); -void _fixtelldir(DIR *dirp, long oldseek, long oldloc); +void _fixtelldir(DIR *dirp, off_t oldseek, size_t oldloc); DIR *__opendir_common(int, int, bool); #define RDU_SKIP 0x0001 diff --git a/lib/libc/gen/tls.c b/lib/libc/gen/tls.c index 30b4fc583c98..b26b13d45589 100644 --- a/lib/libc/gen/tls.c +++ b/lib/libc/gen/tls.c @@ -80,13 +80,13 @@ static void *libc_tls_init; void * __libc_tls_get_addr(void *vti) { - uintptr_t *dtv; + struct dtv *dtv; tls_index *ti; dtv = _tcb_get()->tcb_dtv; ti = vti; - return ((char *)(dtv[ti->ti_module + 1] + ti->ti_offset) + - TLS_DTV_OFFSET); + return (dtv->dtv_slots[ti->ti_module - 1].dtvs_tls + + (ti->ti_offset + TLS_DTV_OFFSET)); } #ifdef __i386__ @@ -151,7 +151,8 @@ libc_free_aligned(void *ptr) * where TP points (with bias) to TLS and TCB immediately precedes TLS without * any alignment gap[4]. Only TLS should be aligned. The TCB[0] points to DTV * vector and DTV values are biased by constant value (TLS_DTV_OFFSET) from - * real addresses[5]. + * real addresses. However, like RTLD, we don't actually bias the DTV values, + * instead we compensate in __tls_get_addr for ti_offset's bias. * * [1] Ulrich Drepper: ELF Handling for Thread-Local Storage * www.akkadia.org/drepper/tls.pdf @@ -167,8 +168,6 @@ libc_free_aligned(void *ptr) * but we must follow this rule due to suboptimal _tcb_set() * (aka <ARCH>_SET_TP) implementation. This function doesn't expect TP but * TCB as argument. - * - * [5] I'm not able to validate "values are biased" assertions. */ /* @@ -201,11 +200,9 @@ get_tls_block_ptr(void *tcb, size_t tcbsize) void __libc_free_tls(void *tcb, size_t tcbsize, size_t tcbalign __unused) { - Elf_Addr *dtv; - Elf_Addr **tls; + struct dtv *dtv; - tls = (Elf_Addr **)tcb; - dtv = tls[0]; + dtv = ((struct tcb *)tcb)->tcb_dtv; __je_bootstrap_free(dtv); libc_free_aligned(get_tls_block_ptr(tcb, tcbsize)); } @@ -233,7 +230,8 @@ __libc_free_tls(void *tcb, size_t tcbsize, size_t tcbalign __unused) void * __libc_allocate_tls(void *oldtcb, size_t tcbsize, size_t tcbalign) { - Elf_Addr *dtv, **tcb; + struct dtv *dtv; + struct tcb *tcb; char *tls_block, *tls; size_t extra_size, maxalign, post_size, pre_size, tls_block_size; @@ -262,7 +260,7 @@ __libc_allocate_tls(void *oldtcb, size_t tcbsize, size_t tcbalign) abort(); } memset(tls_block, 0, tls_block_size); - tcb = (Elf_Addr **)(tls_block + pre_size + extra_size); + tcb = (struct tcb *)(tls_block + pre_size + extra_size); tls = (char *)tcb + TLS_TCB_SIZE + post_size; if (oldtcb != NULL) { @@ -271,19 +269,20 @@ __libc_allocate_tls(void *oldtcb, size_t tcbsize, size_t tcbalign) libc_free_aligned(oldtcb); /* Adjust the DTV. */ - dtv = tcb[0]; - dtv[2] = (Elf_Addr)(tls + TLS_DTV_OFFSET); + dtv = tcb->tcb_dtv; + dtv->dtv_slots[0].dtvs_tls = tls; } else { - dtv = __je_bootstrap_malloc(3 * sizeof(Elf_Addr)); + dtv = __je_bootstrap_malloc(sizeof(struct dtv) + + sizeof(struct dtv_slot)); if (dtv == NULL) { tls_msg("__libc_allocate_tls: Out of memory.\n"); abort(); } /* Build the DTV. */ - tcb[0] = dtv; - dtv[0] = 1; /* Generation. */ - dtv[1] = 1; /* Segments count. */ - dtv[2] = (Elf_Addr)(tls + TLS_DTV_OFFSET); + tcb->tcb_dtv = dtv; + dtv->dtv_gen = 1; /* Generation. */ + dtv->dtv_size = 1; /* Segments count. */ + dtv->dtv_slots[0].dtvs_tls = tls; if (libc_tls_init_size > 0) memcpy(tls, libc_tls_init, libc_tls_init_size); @@ -303,8 +302,8 @@ void __libc_free_tls(void *tcb, size_t tcbsize __unused, size_t tcbalign) { size_t size; - Elf_Addr* dtv; - Elf_Addr tlsstart, tlsend; + struct dtv *dtv; + uintptr_t tlsstart, tlsend; /* * Figure out the size of the initial TLS block so that we can @@ -313,8 +312,8 @@ __libc_free_tls(void *tcb, size_t tcbsize __unused, size_t tcbalign) tcbalign = MAX(tcbalign, libc_tls_init_align); size = roundup2(libc_tls_static_space, tcbalign); - dtv = ((Elf_Addr**)tcb)[1]; - tlsend = (Elf_Addr) tcb; + dtv = ((struct tcb *)tcb)->tcb_dtv; + tlsend = (uintptr_t)tcb; tlsstart = tlsend - size; libc_free_aligned((void*)tlsstart); __je_bootstrap_free(dtv); @@ -324,61 +323,60 @@ __libc_free_tls(void *tcb, size_t tcbsize __unused, size_t tcbalign) * Allocate Static TLS using the Variant II method. */ void * -__libc_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign) +__libc_allocate_tls(void *oldtcb, size_t tcbsize, size_t tcbalign) { size_t size; - char *tls; - Elf_Addr *dtv; - Elf_Addr segbase, oldsegbase; + char *tls_block, *tls; + struct dtv *dtv; + struct tcb *tcb; tcbalign = MAX(tcbalign, libc_tls_init_align); size = roundup2(libc_tls_static_space, tcbalign); - if (tcbsize < 2 * sizeof(Elf_Addr)) - tcbsize = 2 * sizeof(Elf_Addr); - tls = libc_malloc_aligned(size + tcbsize, tcbalign); - if (tls == NULL) { + if (tcbsize < 2 * sizeof(uintptr_t)) + tcbsize = 2 * sizeof(uintptr_t); + tls_block = libc_malloc_aligned(size + tcbsize, tcbalign); + if (tls_block == NULL) { tls_msg("__libc_allocate_tls: Out of memory.\n"); abort(); } - memset(tls, 0, size + tcbsize); - dtv = __je_bootstrap_malloc(3 * sizeof(Elf_Addr)); + memset(tls_block, 0, size + tcbsize); + dtv = __je_bootstrap_malloc(sizeof(struct dtv) + + sizeof(struct dtv_slot)); if (dtv == NULL) { tls_msg("__libc_allocate_tls: Out of memory.\n"); abort(); } - segbase = (Elf_Addr)(tls + size); - ((Elf_Addr*)segbase)[0] = segbase; - ((Elf_Addr*)segbase)[1] = (Elf_Addr) dtv; + tcb = (struct tcb *)(tls_block + size); + tls = (char *)tcb - libc_tls_static_space; + tcb->tcb_self = tcb; + tcb->tcb_dtv = dtv; - dtv[0] = 1; - dtv[1] = 1; - dtv[2] = segbase - libc_tls_static_space; + dtv->dtv_gen = 1; + dtv->dtv_size = 1; + dtv->dtv_slots[0].dtvs_tls = tls; - if (oldtls) { + if (oldtcb != NULL) { /* * Copy the static TLS block over whole. */ - oldsegbase = (Elf_Addr) oldtls; - memcpy((void *)(segbase - libc_tls_static_space), - (const void *)(oldsegbase - libc_tls_static_space), + memcpy(tls, (const char *)oldtcb - libc_tls_static_space, libc_tls_static_space); /* * We assume that this block was the one we created with * allocate_initial_tls(). */ - _rtld_free_tls(oldtls, 2*sizeof(Elf_Addr), sizeof(Elf_Addr)); + _rtld_free_tls(oldtcb, 2 * sizeof(uintptr_t), + sizeof(uintptr_t)); } else { - memcpy((void *)(segbase - libc_tls_static_space), - libc_tls_init, libc_tls_init_size); - memset((void *)(segbase - libc_tls_static_space + - libc_tls_init_size), 0, + memcpy(tls, libc_tls_init, libc_tls_init_size); + memset(tls + libc_tls_init_size, 0, libc_tls_static_space - libc_tls_init_size); } - return (void*) segbase; + return (tcb); } #endif /* TLS_VARIANT_II */ @@ -386,7 +384,7 @@ __libc_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign) #else void * -__libc_allocate_tls(void *oldtls __unused, size_t tcbsize __unused, +__libc_allocate_tls(void *oldtcb __unused, size_t tcbsize __unused, size_t tcbalign __unused) { return (0); diff --git a/lib/libc/gen/ualarm.3 b/lib/libc/gen/ualarm.3 index f4e0973b133a..dfd9ddd5f434 100644 --- a/lib/libc/gen/ualarm.3 +++ b/lib/libc/gen/ualarm.3 @@ -70,7 +70,7 @@ restriction the maximum number of .Fa microseconds and .Fa interval -is limited to 100000000000000 +is limited to 100,000,000,000,000 (in case this value fits in the unsigned integer). .Sh RETURN VALUES When the signal has successfully been caught, diff --git a/lib/libc/gen/uexterr_format.c b/lib/libc/gen/uexterr_format.c new file mode 100644 index 000000000000..e8ddfbd578e3 --- /dev/null +++ b/lib/libc/gen/uexterr_format.c @@ -0,0 +1,35 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 The FreeBSD Foundation + * All rights reserved. + * + * This software were developed by Konstantin Belousov <kib@FreeBSD.org> + * under sponsorship from the FreeBSD Foundation. + */ + +#include <sys/types.h> +#include <sys/exterrvar.h> +#include <exterr.h> +#include <stdio.h> +#include <string.h> + +int +__uexterr_format(const struct uexterror *ue, char *buf, size_t bufsz) +{ + if (bufsz > UEXTERROR_MAXLEN) + bufsz = UEXTERROR_MAXLEN; + if (ue->error == 0) { + strlcpy(buf, "", bufsz); + return (0); + } + if (ue->msg[0] == '\0') { + snprintf(buf, bufsz, + "errno %d category %u (src line %u) p1 %#jx p2 %#jx", + ue->error, ue->cat, ue->src_line, + (uintmax_t)ue->p1, (uintmax_t)ue->p2); + } else { + strlcpy(buf, ue->msg, bufsz); + } + return (0); +} diff --git a/lib/libc/gen/uexterr_gettext.c b/lib/libc/gen/uexterr_gettext.c new file mode 100644 index 000000000000..5b8a5cd17a48 --- /dev/null +++ b/lib/libc/gen/uexterr_gettext.c @@ -0,0 +1,43 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 The FreeBSD Foundation + * All rights reserved. + * + * This software were developed by Konstantin Belousov <kib@FreeBSD.org> + * under sponsorship from the FreeBSD Foundation. + */ + +#define _WANT_P_OSREL +#include <sys/param.h> +#include <sys/exterrvar.h> +#include <exterr.h> +#include <string.h> +#include "libc_private.h" + +static struct uexterror uexterr = { + .ver = UEXTERROR_VER, +}; + +int __getosreldate(void); + +static void uexterr_ctr(void) __attribute__((constructor)); +static void +uexterr_ctr(void) +{ + if (__getosreldate() >= P_OSREL_EXTERRCTL) + exterrctl(EXTERRCTL_ENABLE, 0, &uexterr); +} + +int +__libc_uexterr_gettext(char *buf, size_t bufsz) +{ + return (__uexterr_format(&uexterr, buf, bufsz)); +} + +int +uexterr_gettext(char *buf, size_t bufsz) +{ + return (((int (*)(char *, size_t)) + __libc_interposing[INTERPOS_uexterr_gettext])(buf, bufsz)); +} diff --git a/lib/libc/gen/wordexp.c b/lib/libc/gen/wordexp.c index f1437e30bbe2..f8080c20d121 100644 --- a/lib/libc/gen/wordexp.c +++ b/lib/libc/gen/wordexp.c @@ -265,7 +265,15 @@ cleanup: errno = serrno; return (error); } - if (wpid < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) + /* + * Check process exit status, but ignore ECHILD as the child may have + * been automatically reaped if the process had set SIG_IGN or + * SA_NOCLDWAIT for SIGCHLD, and our reason for waitpid was just to + * reap our own child on behalf of the calling process. + */ + if (wpid < 0 && errno != ECHILD) + return (WRDE_NOSPACE); /* abort for unknown reason */ + if (wpid >= 0 && (!WIFEXITED(status) || WEXITSTATUS(status) != 0)) return (WRDE_NOSPACE); /* abort for unknown reason */ /* diff --git a/lib/libc/i386/static_tls.h b/lib/libc/i386/static_tls.h deleted file mode 100644 index baf9dfc59a5a..000000000000 --- a/lib/libc/i386/static_tls.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - */ - -#ifndef _LIBC_I386_STATIC_TLS_H -#define _LIBC_I386_STATIC_TLS_H - -static __inline uintptr_t -_libc_get_static_tls_base(size_t offset) -{ - uintptr_t tlsbase; - - __asm __volatile("movl %%gs:0, %0" : "=r" (tlsbase)); - tlsbase -= offset; - return (tlsbase); -} - -#endif diff --git a/lib/libc/include/block_abi.h b/lib/libc/include/block_abi.h index e04998d6148d..cf670c6c079e 100644 --- a/lib/libc/include/block_abi.h +++ b/lib/libc/include/block_abi.h @@ -37,7 +37,7 @@ * compilers that support blocks and exposing the ABI in the source for other * compilers. */ -#define CALL_BLOCK(name, ...) name(__VA_ARGS__) +#define CALL_BLOCK(name, ...) (name)(__VA_ARGS__) #else // !__BLOCKS__ #define DECLARE_BLOCK(retTy, name, argTys, ...)\ struct {\ diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h index 4c244f962b2b..db4cbc32be35 100644 --- a/lib/libc/include/libc_private.h +++ b/lib/libc/include/libc_private.h @@ -249,8 +249,9 @@ enum { INTERPOS_map_stacks_exec, INTERPOS_fdatasync, INTERPOS_clock_nanosleep, - INTERPOS_distribute_static_tls, + INTERPOS__reserved0, /* was distribute_static_tls */ INTERPOS_pdfork, + INTERPOS_uexterr_gettext, INTERPOS_MAX }; @@ -345,6 +346,7 @@ struct __ucontext; struct __wrusage; enum idtype; +int __libc_execvpe(const char *, char * const *, char * const *); int __libc_sigaction(int, const struct sigaction *, struct sigaction *) __hidden; int __libc_sigprocmask(int, const __sigset_t *, __sigset_t *) @@ -359,8 +361,6 @@ struct dl_phdr_info; int __elf_phdr_match_addr(struct dl_phdr_info *, void *); void __init_elf_aux_vector(void); void __libc_map_stacks_exec(void); -void __libc_distribute_static_tls(__size_t, void *, __size_t, __size_t); -__uintptr_t __libc_static_tls_base(__size_t); void _pthread_cancel_enter(int); void _pthread_cancel_leave(int); @@ -379,4 +379,8 @@ struct __nl_cat_d *__catopen_l(const char *name, int type, int __strerror_rl(int errnum, char *strerrbuf, size_t buflen, struct _xlocale *locale); +struct uexterror; +int __uexterr_format(const struct uexterror *ue, char *buf, size_t bufsz); +int __libc_uexterr_gettext(char *buf, size_t bufsz); + #endif /* _LIBC_PRIVATE_H_ */ diff --git a/lib/libc/locale/collate.c b/lib/libc/locale/collate.c index 8e3635485f10..c0fc4c91481d 100644 --- a/lib/libc/locale/collate.c +++ b/lib/libc/locale/collate.c @@ -43,6 +43,7 @@ #include <sys/mman.h> #include <assert.h> +#include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -732,3 +733,261 @@ __collate_equiv_value(locale_t locale, const wchar_t *str, size_t len) } return (0); } + +/* + * __collate_collating_symbol takes the multibyte string specified by + * src and slen, and using ps, converts that to a wide character. Then + * it is checked to verify it is a collating symbol, and then copies + * it to the wide character string specified by dst and dlen (the + * results are not null terminated). The length of the wide characters + * copied to dst is returned if successful. Zero is returned if no such + * collating symbol exists. (size_t)-1 is returned if there are wide-character + * conversion errors, if the length of the converted string is greater that + * COLLATE_STR_LEN or if dlen is too small. It is up to the calling routine to + * preserve the mbstate_t structure as needed. + */ +size_t +__collate_collating_symbol(wchar_t *dst, size_t dlen, const char *src, + size_t slen, mbstate_t *ps) +{ + wchar_t wname[COLLATE_STR_LEN]; + wchar_t w, *wp; + struct xlocale_collate *table; + size_t len, l; + + table = + (struct xlocale_collate *)__get_locale()->components[XLC_COLLATE]; + /* POSIX locale */ + if (table->__collate_load_error) { + if (dlen < 1) + return ((size_t)-1); + if (slen != 1 || !isascii(*src)) + return (0); + *dst = *src; + return (1); + } + for (wp = wname, len = 0; slen > 0; len++) { + l = mbrtowc(&w, src, slen, ps); + if (l == (size_t)-1 || l == (size_t)-2) + return ((size_t)-1); + if (l == 0) + break; + if (len >= COLLATE_STR_LEN) + return ((size_t)-1); + *wp++ = w; + src += l; + slen -= l; + } + if (len == 0 || len > dlen) + return ((size_t)-1); + if (len == 1) { + if (*wname <= UCHAR_MAX) { + if (table->char_pri_table[*wname].pri[0] >= 0) { + if (dlen > 0) + *dst = *wname; + return (1); + } + return (0); + } else if (table->info->large_count > 0) { + collate_large_t *match; + match = largesearch(table, *wname); + if (match && match->pri.pri[0] >= 0) { + if (dlen > 0) + *dst = *wname; + return (1); + } + } + return (0); + } + *wp = 0; + if (table->info->chain_count > 0) { + collate_chain_t *match; + int ll; + match = chainsearch(table, wname, &ll); + if (match) { + if (ll < dlen) + dlen = ll; + wcsncpy(dst, wname, dlen); + return (dlen); + } + } + return (0); +} + +/* + * __collate_equiv_class returns the equivalence class number for the symbol + * specified by src and slen, using ps to convert from multi-byte to wide + * character. Zero is returned if the symbol is not in an equivalence + * class. -1 is returned if there are wide character conversion errors, + * if there are any greater-than-8-bit characters or if a multi-byte symbol + * is greater or equal to COLLATE_STR_LEN in length. It is up to the calling + * routine to preserve the mbstate_t structure as needed. + */ +int +__collate_equiv_class(const char *src, size_t slen, mbstate_t *ps) +{ + wchar_t wname[COLLATE_STR_LEN]; + wchar_t w, *wp; + struct xlocale_collate *table; + size_t len, l; + int e; + + table = + (struct xlocale_collate *)__get_locale()->components[XLC_COLLATE]; + /* POSIX locale */ + if (table->__collate_load_error) + return (0); + for (wp = wname, len = 0; slen > 0; len++) { + l = mbrtowc(&w, src, slen, ps); + if (l == (size_t)-1 || l == (size_t)-2) + return (-1); + if (l == 0) + break; + if (len >= COLLATE_STR_LEN) + return (-1); + *wp++ = w; + src += l; + slen -= l; + } + if (len == 0) + return (-1); + if (len == 1) { + e = -1; + if (*wname <= UCHAR_MAX) + e = table->char_pri_table[*wname].pri[0]; + else if (table->info->large_count > 0) { + collate_large_t *match; + match = largesearch(table, *wname); + if (match) + e = match->pri.pri[0]; + } + if (e == 0) + return (IGNORE_EQUIV_CLASS); + return (e > 0 ? e : 0); + } + *wp = 0; + if (table->info->chain_count > 0) { + collate_chain_t *match; + int ll; + match = chainsearch(table, wname, &ll); + if (match) { + e = match->pri[0]; + if (e == 0) + return (IGNORE_EQUIV_CLASS); + return (e < 0 ? -e : e); + } + } + return (0); +} + + +/* + * __collate_equiv_match tries to match any single or multi-character symbol + * in equivalence class equiv_class in the multi-byte string specified by src + * and slen. If start is non-zero, it is taken to be the first (pre-converted) + * wide character. Subsequence wide characters, if needed, will use ps in + * the conversion. On a successful match, the length of the matched string + * is returned (including the start character). If dst is non-NULL, the + * matched wide-character string is copied to dst, a wide character array of + * length dlen (the results are not zero-terminated). If rlen is non-NULL, + * the number of character in src actually used is returned. Zero is + * returned by __collate_equiv_match if there is no match. (size_t)-1 is + * returned on error: if there were conversion errors or if dlen is too small + * to accept the results. On no match or error, ps is restored to its incoming + * state. + */ +size_t +__collate_equiv_match(int equiv_class, wchar_t *dst, size_t dlen, wchar_t start, + const char *src, size_t slen, mbstate_t *ps, size_t *rlen) +{ + wchar_t w; + size_t len, l, clen; + int i; + wchar_t buf[COLLATE_STR_LEN], *wp; + mbstate_t save; + const char *s = src; + struct xlocale_collate *table; + size_t sl = slen; + collate_chain_t *ch = NULL; + + table = + (struct xlocale_collate *)__get_locale()->components[XLC_COLLATE]; + /* POSIX locale */ + if (table->__collate_load_error) + return ((size_t)-1); + if (equiv_class == IGNORE_EQUIV_CLASS) + equiv_class = 0; + if (ps) + save = *ps; + wp = buf; + len = clen = 0; + if (start) { + *wp++ = start; + len = 1; + } + /* convert up to the max chain length */ + while (sl > 0 && len < table->info->chain_max_len) { + l = mbrtowc(&w, s, sl, ps); + if (l == (size_t)-1 || l == (size_t)-2 || l == 0) + break; + *wp++ = w; + s += l; + clen += l; + sl -= l; + len++; + } + *wp = 0; + if (len > 1 && (ch = chainsearch(table, buf, &i)) != NULL) { + int e = ch->pri[0]; + if (e < 0) + e = -e; + if (e == equiv_class) + goto found; + } + /* try single character */ + i = 1; + if (*buf <= UCHAR_MAX) { + if (equiv_class == table->char_pri_table[*buf].pri[0]) + goto found; + } else if (table->info->large_count > 0) { + collate_large_t *match; + match = largesearch(table, *buf); + if (match && equiv_class == match->pri.pri[0]) + goto found; + } + /* no match */ + if (ps) + *ps = save; + return (0); +found: + /* + * If we converted more than we used, restore to initial + * and reconvert up to what did match. + */ + if (i < len) { + len = i; + if (ps) + *ps = save; + if (start) + i--; + clen = 0; + while (i-- > 0) { + l = mbrtowc(&w, src, slen, ps); + src += l; + clen += l; + slen -= l; + } + } + if (dst) { + if (dlen < len) { + if (ps) + *ps = save; + return ((size_t)-1); + } + for (wp = buf; len > 0; len--) + *dst++ = *wp++; + } + if (rlen) + *rlen = clen; + return (len); +} diff --git a/lib/libc/locale/collate.h b/lib/libc/locale/collate.h index f157d8651899..64e0e6f2337d 100644 --- a/lib/libc/locale/collate.h +++ b/lib/libc/locale/collate.h @@ -38,6 +38,7 @@ #include <sys/types.h> #include <limits.h> +#include <wchar.h> #include "xlocale_private.h" /* @@ -65,6 +66,8 @@ #define DIRECTIVE_DIRECTION_MASK (DIRECTIVE_FORWARD | DIRECTIVE_BACKWARD) +#define IGNORE_EQUIV_CLASS 1 + /* * The collate file format is as follows: * @@ -85,6 +88,7 @@ typedef struct collate_info { uint8_t directive_count; uint8_t directive[COLL_WEIGHTS_MAX]; + uint8_t chain_max_len; /* In padding */ int32_t pri_count[COLL_WEIGHTS_MAX]; int32_t flags; int32_t chain_count; @@ -126,8 +130,13 @@ struct xlocale_collate { }; __BEGIN_DECLS -int __collate_load_tables(const char *); +size_t __collate_collating_symbol(wchar_t *, size_t, const char *, size_t, + mbstate_t *); +int __collate_equiv_class(const char *, size_t, mbstate_t *); int __collate_equiv_value(locale_t, const wchar_t *, size_t); +size_t __collate_equiv_match(int, wchar_t *, size_t, wchar_t, const char *, + size_t, mbstate_t *, size_t *); +int __collate_load_tables(const char *); void _collate_lookup(struct xlocale_collate *,const wchar_t *, int *, int *, int, const int **); int __collate_range_cmp(char, char); diff --git a/lib/libc/locale/euc.c b/lib/libc/locale/euc.c index c54a6ceceff2..c110fc61b375 100644 --- a/lib/libc/locale/euc.c +++ b/lib/libc/locale/euc.c @@ -426,7 +426,7 @@ _EUC_wcrtomb_impl(char * __restrict s, wchar_t wc, /* This first check excludes CS1, which is implicitly valid. */ if ((wc < 0xa100) || (wc > 0xffff)) { /* Check for valid CS2 or CS3 */ - nm = (wc >> ((len - 1) * 8)); + nm = (wc >> ((len - 1) * 8)) & 0xff; if (nm == cs2) { if (len != cs2width) { errno = EILSEQ; diff --git a/lib/libc/net/Makefile.inc b/lib/libc/net/Makefile.inc index 558cf7be5771..7e9e5295c78c 100644 --- a/lib/libc/net/Makefile.inc +++ b/lib/libc/net/Makefile.inc @@ -1,7 +1,7 @@ # machine-independent net sources .PATH: ${LIBC_SRCTOP}/net -CONFS+= net/hosts net/hosts.equiv net/networks net/nsswitch.conf net/protocols +CONFS+= net/hosts net/hosts.equiv net/networks ${.OBJDIR}/nsswitch.conf net/protocols SRCS+= base64.c ether_addr.c eui64.c \ gai_strerror.c getaddrinfo.c \ gethostbydns.c gethostbyht.c gethostbynis.c gethostnamadr.c \ @@ -141,7 +141,8 @@ MLINKS+=inet6_opt_init.3 inet6_opt_append.3 \ inet6_rthdr_space.3 inet6_rthdr_reverse.3 \ inet6_rthdr_space.3 inet6_rthdr_segments.3 MLINKS+=linkaddr.3 link_addr.3 \ - linkaddr.3 link_ntoa.3 + linkaddr.3 link_ntoa.3 \ + linkaddr.3 link_ntoa_r.3 MLINKS+=rcmd.3 iruserok.3 \ rcmd.3 iruserok_sa.3 \ rcmd.3 rcmd_af.3 \ @@ -176,9 +177,13 @@ MLINKS+=hesiod.3 hesiod_init.3 \ hesiod.3 hesiod_end.3 .endif -afterinstallconfig: modify-nsswitch-conf -modify-nsswitch-conf: .PHONY +all: ${.OBJDIR}/nsswitch.conf + +# Manually stage nsswitch.conf in the object directory so that we can edit it +# before installing. +${.OBJDIR}/nsswitch.conf: ${LIBC_SRCTOP}/net/nsswitch.conf + cp -f ${LIBC_SRCTOP}/net/nsswitch.conf ${.TARGET} .if ${MK_NIS} == "no" sed -i "" -e 's/.*_compat:/# &/' -e 's/compat$$/files/' \ - ${DESTDIR}/etc/nsswitch.conf + ${.TARGET} .endif diff --git a/lib/libc/net/Symbol.map b/lib/libc/net/Symbol.map index ebc3a56b549f..25e79b4e5807 100644 --- a/lib/libc/net/Symbol.map +++ b/lib/libc/net/Symbol.map @@ -138,6 +138,10 @@ FBSD_1.3 { sctp_sendv; }; +FBSD_1.8 { + link_ntoa_r; +}; + FBSDprivate_1.0 { _nsdispatch; _nsyyerror; /* generated from nslexer.l */ diff --git a/lib/libc/net/getaddrinfo.c b/lib/libc/net/getaddrinfo.c index 2b9499d5099b..b8af23ebe8da 100644 --- a/lib/libc/net/getaddrinfo.c +++ b/lib/libc/net/getaddrinfo.c @@ -2341,9 +2341,14 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap) if (res_searchN(hostname, &q, res) < 0) { free(buf); free(buf2); - if (res->res_h_errno == NO_DATA) + switch (res->res_h_errno) { + case NO_DATA: return (NS_ADDRFAMILY); - return (NS_NOTFOUND); + case TRY_AGAIN: + return (NS_TRYAGAIN); + default: + return (NS_NOTFOUND); + } } /* prefer IPv6 */ if (q.next) { @@ -2705,9 +2710,18 @@ res_queryN(const char *name, struct res_target *target, res_state res) int n; u_int oflags; struct res_target *t; - int rcode; + u_int rcode; int ancount; + /* + * Extend rcode values in the scope of this function. The DNS header + * rcode we use in this function (hp->rcode) is limited by 4 bits, so + * anything starting from 16 is safe wrt aliasing. However, nameser.h + * already has extended enum __ns_rcode, so for future safety let's use + * even larger values. + */ +#define RCODE_UNREACH 32 +#define RCODE_TIMEDOUT 33 rcode = NOERROR; ancount = 0; @@ -2768,7 +2782,29 @@ again: printf(";; res_nquery: retry without EDNS0\n"); goto again; } - rcode = hp->rcode; /* record most recent error */ + /* + * Historically if a DNS server replied with ICMP port + * unreach res_nsend() would signal that with + * ECONNREFUSED and the upper layers would convert that + * into TRY_AGAIN. See 3a0b3b673936b and deeper. + * Also, res_nsend() may set errno to ECONNREFUSED due + * to internal failures. This may not be intentional, + * but we also treat that as soft failures. + * + * A more practical case is when a DNS server(s) were + * queried and didn't respond anything, which usually + * indicates a soft network failure. + */ + switch (errno) { + case ECONNREFUSED: + rcode = RCODE_UNREACH; + break; + case ETIMEDOUT: + rcode = RCODE_TIMEDOUT; + break; + default: + rcode = hp->rcode; + } #ifdef DEBUG if (res->options & RES_DEBUG) printf(";; res_query: send error\n"); @@ -2800,6 +2836,8 @@ again: case NXDOMAIN: RES_SET_H_ERRNO(res, HOST_NOT_FOUND); break; + case RCODE_UNREACH: + case RCODE_TIMEDOUT: case SERVFAIL: RES_SET_H_ERRNO(res, TRY_AGAIN); break; @@ -2862,10 +2900,6 @@ res_searchN(const char *name, struct res_target *target, res_state res) ret = res_querydomainN(name, NULL, target, res); if (ret > 0 || trailing_dot) return (ret); - if (errno == ECONNREFUSED) { - RES_SET_H_ERRNO(res, TRY_AGAIN); - return (-1); - } switch (res->res_h_errno) { case NO_DATA: case HOST_NOT_FOUND: @@ -2906,7 +2940,6 @@ res_searchN(const char *name, struct res_target *target, res_state res) ret = res_querydomainN(name, *domain, target, res); if (ret > 0) return (ret); - /* * If no server present, give up. * If name isn't found in this domain, @@ -2920,11 +2953,6 @@ res_searchN(const char *name, struct res_target *target, res_state res) * but try the input name below in case it's * fully-qualified. */ - if (errno == ECONNREFUSED) { - RES_SET_H_ERRNO(res, TRY_AGAIN); - return (-1); - } - switch (res->res_h_errno) { case NO_DATA: got_nodata++; @@ -2933,8 +2961,8 @@ res_searchN(const char *name, struct res_target *target, res_state res) /* keep trying */ break; case TRY_AGAIN: - got_servfail++; if (hp->rcode == SERVFAIL) { + got_servfail++; /* try next search element, if any */ break; } diff --git a/lib/libc/net/linkaddr.3 b/lib/libc/net/linkaddr.3 index ee3ea3056c71..38ee6a0aedea 100644 --- a/lib/libc/net/linkaddr.3 +++ b/lib/libc/net/linkaddr.3 @@ -28,12 +28,13 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd February 28, 2007 +.Dd May 9, 2025 .Dt LINK_ADDR 3 .Os .Sh NAME .Nm link_addr , -.Nm link_ntoa +.Nm link_ntoa , +.Nm link_ntoa_r .Nd elementary address specification routines for link level access .Sh LIBRARY .Lb libc @@ -41,16 +42,29 @@ .In sys/types.h .In sys/socket.h .In net/if_dl.h -.Ft void +.Ft int .Fn link_addr "const char *addr" "struct sockaddr_dl *sdl" .Ft char * .Fn link_ntoa "const struct sockaddr_dl *sdl" +.Ft int +.Fn link_ntoa_r "const struct sockaddr_dl *sdl" "char *obuf" "size_t *buflen" .Sh DESCRIPTION The routine .Fn link_addr -interprets character strings representing -link-level addresses, returning binary information suitable -for use in system calls. +parses a character string +.Fa addr +representing a link-level address, +and stores the resulting address in the structure pointed to by +.Fa sdl . +A link-level address consists of an optional interface name, followed by +a colon (which is required in all cases), followed by an address +consisting of either a string of hexadecimal digits, or a series of +hexadecimal octets separated by one of the characters +.Sq "." , +.Sq ":" , +or +.Sq - . +.Pp The routine .Fn link_ntoa takes @@ -60,9 +74,34 @@ address and returns an string representing some of the information present, including the link level address itself, and the interface name or number, if present. +The returned string is stored in a static buffer. This facility is experimental and is still subject to change. .Pp +The routine +.Fn link_ntoa_r +behaves like +.Fn link_ntoa , +except the string is placed in the provided buffer instead of a static +buffer. +The caller should initialize +.Fa buflen +to the number of bytes available in +.Fa obuf . +On return, +.Fa buflen +is set to the actual number of bytes required for the output buffer, +including the NUL terminator. +If +.Fa obuf +is NULL, then +.Fa buflen +is set as described, but nothing is written. +This may be used to determine the required length of the buffer before +calling +.Fn link_ntoa_r +a second time. +.Pp For .Fn link_addr , the string @@ -94,12 +133,21 @@ The .Fn link_ntoa function always returns a null terminated string. +.Pp +The +.Fn link_ntoa_r +function returns 0 on success, or -1 if the provided buffer was not +large enough; in the latter case, the contents of the buffer are +indeterminate, but a trailing NUL will always be written if the buffer +was at least one byte in size. +.Pp The .Fn link_addr -function -has no return value. -(See -.Sx BUGS . ) +function returns 0 on success. +If the address did not appear to be a valid link-level address, -1 is +returned and +.Va errno +is set to indicate the error. .Sh SEE ALSO .Xr getnameinfo 3 .Sh HISTORY @@ -109,15 +157,14 @@ and .Fn link_ntoa functions appeared in .Bx 4.3 Reno . +The +.Fn link_ntoa_r +function appeared in +.Fx 15.0 . .Sh BUGS The returned values for link_ntoa reside in a static memory area. .Pp -The function -.Fn link_addr -should diagnose improperly formed input, and there should be an unambiguous -way to recognize this. -.Pp If the .Va sdl_len field of the link socket address diff --git a/lib/libc/net/linkaddr.c b/lib/libc/net/linkaddr.c index dedc910b9474..5be4c0a7a43e 100644 --- a/lib/libc/net/linkaddr.c +++ b/lib/libc/net/linkaddr.c @@ -31,135 +31,261 @@ #include <sys/types.h> #include <sys/socket.h> + #include <net/if.h> #include <net/if_dl.h> + +#include <assert.h> +#include <errno.h> +#include <stdint.h> #include <string.h> -/* States*/ -#define NAMING 0 -#define GOTONE 1 -#define GOTTWO 2 -#define RESET 3 -/* Inputs */ -#define DIGIT (4*0) -#define END (4*1) -#define DELIM (4*2) -#define LETTER (4*3) - -void +int link_addr(const char *addr, struct sockaddr_dl *sdl) { char *cp = sdl->sdl_data; char *cplim = sdl->sdl_len + (char *)sdl; - int byte = 0, state = NAMING, new; + const char *nptr; + size_t newsize; + int error = 0; + char delim = 0; + /* Initialise the sdl to zero, except for sdl_len. */ bzero((char *)&sdl->sdl_family, sdl->sdl_len - 1); sdl->sdl_family = AF_LINK; - do { - state &= ~LETTER; - if ((*addr >= '0') && (*addr <= '9')) { - new = *addr - '0'; - } else if ((*addr >= 'a') && (*addr <= 'f')) { - new = *addr - 'a' + 10; - } else if ((*addr >= 'A') && (*addr <= 'F')) { - new = *addr - 'A' + 10; - } else if (*addr == 0) { - state |= END; - } else if (state == NAMING && - (((*addr >= 'A') && (*addr <= 'Z')) || - ((*addr >= 'a') && (*addr <= 'z')))) - state |= LETTER; - else - state |= DELIM; - addr++; - switch (state /* | INPUT */) { - case NAMING | DIGIT: - case NAMING | LETTER: - *cp++ = addr[-1]; - continue; - case NAMING | DELIM: - state = RESET; - sdl->sdl_nlen = cp - sdl->sdl_data; - continue; - case GOTTWO | DIGIT: - *cp++ = byte; - /* FALLTHROUGH */ - case RESET | DIGIT: - state = GOTONE; - byte = new; - continue; - case GOTONE | DIGIT: - state = GOTTWO; - byte = new + (byte << 4); - continue; - default: /* | DELIM */ - state = RESET; - *cp++ = byte; - byte = 0; - continue; - case GOTONE | END: - case GOTTWO | END: - *cp++ = byte; - /* FALLTHROUGH */ - case RESET | END: + + /* + * Everything up to the first ':' is the interface name. Usually the + * ':' should always be present even if there's no interface name, but + * since this interface was poorly specified in the past, accept a + * missing colon as meaning no interface name. + */ + if ((nptr = strchr(addr, ':')) != NULL) { + size_t namelen = nptr - addr; + + /* Ensure the sdl is large enough to store the name. */ + if (namelen > cplim - cp) { + errno = ENOSPC; + return (-1); + } + + memcpy(cp, addr, namelen); + cp += namelen; + sdl->sdl_nlen = namelen; + /* Skip the interface name and the colon. */ + addr += namelen + 1; + } + + /* + * The remainder of the string should be hex digits representing the + * address, with optional delimiters. Each two hex digits form one + * octet, but octet output can be forced using a delimiter, so we accept + * a long string of hex digits, or a mix of delimited and undelimited + * digits like "1122.3344.5566", or delimited one- or two-digit octets + * like "1.22.3". + * + * If anything fails at this point, exit the loop so we set sdl_alen and + * sdl_len based on whatever we did manage to parse. This preserves + * compatibility with the 4.3BSD version of link_addr, which had no way + * to indicate an error and would just return. + */ +#define DIGIT(c) \ + (((c) >= '0' && (c) <= '9') ? ((c) - '0') \ + : ((c) >= 'a' && (c) <= 'f') ? ((c) - 'a' + 10) \ + : ((c) >= 'A' && (c) <= 'F') ? ((c) - 'A' + 10) \ + : (-1)) +#define ISDELIM(c) (((c) == '.' || (c) == ':' || (c) == '-') && \ + (delim == 0 || delim == (c))) + + for (;;) { + int digit, digit2; + + /* + * Treat any leading delimiters as empty bytes. This supports + * the (somewhat obsolete) form of Ethernet addresses with empty + * octets, e.g. "1::3:4:5:6". + */ + while (ISDELIM(*addr) && cp < cplim) { + delim = *addr++; + *cp++ = 0; + } + + /* Did we reach the end of the string? */ + if (*addr == '\0') + break; + + /* + * If not, the next character must be a digit, so make sure we + * have room for at least one more octet. + */ + + if (cp >= cplim) { + error = ENOSPC; + break; + } + + if ((digit = DIGIT(*addr)) == -1) { + error = EINVAL; break; } - break; - } while (cp < cplim); + + ++addr; + + /* If the next character is another digit, consume it. */ + if ((digit2 = DIGIT(*addr)) != -1) { + digit = (digit << 4) | digit2; + ++addr; + } + + if (ISDELIM(*addr)) { + /* + * If the digit is followed by a delimiter, write it + * and consume the delimiter. + */ + delim = *addr++; + *cp++ = digit; + } else if (DIGIT(*addr) != -1) { + /* + * If two digits are followed by a third digit, treat + * the two digits we have as a single octet and + * continue. + */ + *cp++ = digit; + } else if (*addr == '\0') { + /* If the digit is followed by EOS, we're done. */ + *cp++ = digit; + break; + } else { + /* Otherwise, the input was invalid. */ + error = EINVAL; + break; + } + } +#undef DIGIT +#undef ISDELIM + + /* How many bytes did we write to the address? */ sdl->sdl_alen = cp - LLADDR(sdl); - new = cp - (char *)sdl; - if (new > sizeof(*sdl)) - sdl->sdl_len = new; - return; + + /* + * The user might have given us an sdl which is larger than sizeof(sdl); + * in that case, record the actual size of the new sdl. + */ + newsize = cp - (char *)sdl; + if (newsize > sizeof(*sdl)) + sdl->sdl_len = (u_char)newsize; + + if (error == 0) + return (0); + + errno = error; + return (-1); } -static const char hexlist[] = "0123456789abcdef"; char * link_ntoa(const struct sockaddr_dl *sdl) { static char obuf[64]; + size_t buflen; _Static_assert(sizeof(obuf) >= IFNAMSIZ + 20, "obuf is too small"); + + /* + * Ignoring the return value of link_ntoa_r() is safe here because it + * always writes the terminating NUL. This preserves the traditional + * behaviour of link_ntoa(). + */ + buflen = sizeof(obuf); + (void)link_ntoa_r(sdl, obuf, &buflen); + return obuf; +} + +int +link_ntoa_r(const struct sockaddr_dl *sdl, char *obuf, size_t *buflen) +{ + static const char hexlist[] = "0123456789abcdef"; char *out; const u_char *in, *inlim; int namelen, i, rem; + size_t needed; - namelen = (sdl->sdl_nlen <= IFNAMSIZ) ? sdl->sdl_nlen : IFNAMSIZ; + assert(sdl); + assert(buflen); + /* obuf may be null */ + needed = 1; /* 1 for the NUL */ out = obuf; - rem = sizeof(obuf); + if (obuf) + rem = *buflen; + else + rem = 0; + +/* + * Check if at least n bytes are available in the output buffer, plus 1 for the + * trailing NUL. If not, set rem = 0 so we stop writing. + * Either way, increment needed by the amount we would have written. + */ +#define CHECK(n) do { \ + if ((SIZE_MAX - (n)) >= needed) \ + needed += (n); \ + if (rem >= ((n) + 1)) \ + rem -= (n); \ + else \ + rem = 0; \ + } while (0) + +/* + * Write the char c to the output buffer, unless the buffer is full. + * Note that if obuf is NULL, rem is always zero. + */ +#define OUT(c) do { \ + if (rem > 0) \ + *out++ = (c); \ + } while (0) + + namelen = (sdl->sdl_nlen <= IFNAMSIZ) ? sdl->sdl_nlen : IFNAMSIZ; if (namelen > 0) { - bcopy(sdl->sdl_data, out, namelen); - out += namelen; - rem -= namelen; + CHECK(namelen); + if (rem > 0) { + bcopy(sdl->sdl_data, out, namelen); + out += namelen; + } + if (sdl->sdl_alen > 0) { - *out++ = ':'; - rem--; + CHECK(1); + OUT(':'); } } - in = (const u_char *)sdl->sdl_data + sdl->sdl_nlen; + in = (const u_char *)LLADDR(sdl); inlim = in + sdl->sdl_alen; - while (in < inlim && rem > 1) { - if (in != (const u_char *)sdl->sdl_data + sdl->sdl_nlen) { - *out++ = '.'; - rem--; + while (in < inlim) { + if (in != (const u_char *)LLADDR(sdl)) { + CHECK(1); + OUT('.'); } i = *in++; if (i > 0xf) { - if (rem < 3) - break; - *out++ = hexlist[i >> 4]; - *out++ = hexlist[i & 0xf]; - rem -= 2; + CHECK(2); + OUT(hexlist[i >> 4]); + OUT(hexlist[i & 0xf]); } else { - if (rem < 2) - break; - *out++ = hexlist[i]; - rem--; + CHECK(1); + OUT(hexlist[i]); } } - *out = 0; - return (obuf); + +#undef CHECK +#undef OUT + + /* + * We always leave enough room for the NUL if possible, but the user + * might have passed a NULL or zero-length buffer. + */ + if (out && *buflen) + *out = '\0'; + + *buflen = needed; + return ((rem > 0) ? 0 : -1); } diff --git a/lib/libc/powerpc/static_tls.h b/lib/libc/powerpc/static_tls.h deleted file mode 100644 index 9ae38c71a515..000000000000 --- a/lib/libc/powerpc/static_tls.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - */ - -#ifndef _LIBC_POWERPC_STATIC_TLS_H -#define _LIBC_POWERPC_STATIC_TLS_H - -static __inline uintptr_t -_libc_get_static_tls_base(size_t offset) -{ - uintptr_t tlsbase; - - __asm __volatile("mr %0,2" : "=r"(tlsbase)); - tlsbase += offset - 0x7008; - return (tlsbase); -} - -#endif diff --git a/lib/libc/powerpc64/static_tls.h b/lib/libc/powerpc64/static_tls.h deleted file mode 100644 index 014b8a931453..000000000000 --- a/lib/libc/powerpc64/static_tls.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - */ - -#ifndef _LIBC_POWERPC64_STATIC_TLS_H -#define _LIBC_POWERPC64_STATIC_TLS_H - -static __inline uintptr_t -_libc_get_static_tls_base(size_t offset) -{ - uintptr_t tlsbase; - - __asm __volatile("mr %0,13" : "=r"(tlsbase)); - tlsbase += offset - 0x7010; - return (tlsbase); -} - -#endif diff --git a/lib/libc/riscv/static_tls.h b/lib/libc/riscv/static_tls.h deleted file mode 100644 index ce9fa23338a6..000000000000 --- a/lib/libc/riscv/static_tls.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - */ - -#ifndef _LIBC_RISCV_STATIC_TLS_H -#define _LIBC_RISCV_STATIC_TLS_H - -static __inline uintptr_t -_libc_get_static_tls_base(size_t offset) -{ - uintptr_t tlsbase; - - __asm __volatile("mv %0, tp" : "=r"(tlsbase)); - tlsbase += offset; - return (tlsbase); -} - -#endif diff --git a/lib/libc/rpc/rpc_secure.3 b/lib/libc/rpc/rpc_secure.3 index 11b871b5c99d..ce59bba7115f 100644 --- a/lib/libc/rpc/rpc_secure.3 +++ b/lib/libc/rpc/rpc_secure.3 @@ -266,8 +266,7 @@ Inverse of .Fn netname2user . .Sh SEE ALSO .Xr rpc 3 , -.Xr xdr 3 , -.Xr keyserv 8 +.Xr xdr 3 .Pp The following manuals: .Rs diff --git a/lib/libc/rpc/svc_nl.c b/lib/libc/rpc/svc_nl.c index 5cce44d9d98f..cff364063c5c 100644 --- a/lib/libc/rpc/svc_nl.c +++ b/lib/libc/rpc/svc_nl.c @@ -92,7 +92,7 @@ svc_nl_create(const char *service) .nl_family = PF_NETLINK, }; struct nl_softc *sc; - SVCXPRT *xprt; + SVCXPRT *xprt = NULL; void *buf = NULL; uint16_t family; ssize_t len = 1024; @@ -133,6 +133,7 @@ svc_nl_create(const char *service) return (xprt); fail: + free(xprt); free(buf); snl_free(&sc->snl); free(sc); diff --git a/lib/libc/stdio/mktemp.3 b/lib/libc/stdio/mktemp.3 index 2b8b2d6c9e44..8d38dd2cd57e 100644 --- a/lib/libc/stdio/mktemp.3 +++ b/lib/libc/stdio/mktemp.3 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd July 29, 2019 +.Dd July 07, 2025 .Dt MKTEMP 3 .Os .Sh NAME @@ -101,9 +101,10 @@ The permitted flags are .Dv O_DIRECT , .Dv O_SHLOCK , .Dv O_EXLOCK , -.Dv O_SYNC +.Dv O_SYNC , +.Dv O_CLOEXEC and -.Dv O_CLOEXEC . +.Dv O_CLOFORK . .Pp The .Fn mkstemps diff --git a/lib/libc/stdio/mktemp.c b/lib/libc/stdio/mktemp.c index 8aff226acf14..a2f80ee7b0dd 100644 --- a/lib/libc/stdio/mktemp.c +++ b/lib/libc/stdio/mktemp.c @@ -121,7 +121,7 @@ _gettemp(int dfd, char *path, int *doopen, int domkdir, int slen, int oflags) if ((doopen != NULL && domkdir) || slen < 0 || (oflags & ~(O_APPEND | O_DIRECT | O_SHLOCK | O_EXLOCK | O_SYNC | - O_CLOEXEC)) != 0) { + O_CLOEXEC | O_CLOFORK)) != 0) { errno = EINVAL; return (0); } diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc index bea82445304d..ca199a669be1 100644 --- a/lib/libc/stdlib/Makefile.inc +++ b/lib/libc/stdlib/Makefile.inc @@ -31,7 +31,7 @@ SYM_MAPS+= ${LIBC_SRCTOP}/stdlib/Symbol.map # machine-dependent stdlib sources .sinclude "${LIBC_SRCTOP}/${LIBC_ARCH}/stdlib/Makefile.inc" -MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 \ +MAN+= a64l.3 abort.3 abs.3 atexit.3 atof.3 \ atoi.3 atol.3 at_quick_exit.3 bsearch.3 \ div.3 exit.3 getenv.3 getopt.3 getopt_long.3 getsubopt.3 \ hcreate.3 imaxabs.3 imaxdiv.3 insque.3 labs.3 ldiv.3 llabs.3 lldiv.3 \ diff --git a/lib/libc/stdlib/Symbol.map b/lib/libc/stdlib/Symbol.map index d74df869cf54..2b79ca2ece8b 100644 --- a/lib/libc/stdlib/Symbol.map +++ b/lib/libc/stdlib/Symbol.map @@ -127,6 +127,10 @@ FBSD_1.7 { secure_getenv; }; +FBSD_1.8 { + getenv_r; +}; + FBSDprivate_1.0 { __system; _system; diff --git a/lib/libc/stdlib/alloca.3 b/lib/libc/stdlib/alloca.3 deleted file mode 100644 index d2111872ae0b..000000000000 --- a/lib/libc/stdlib/alloca.3 +++ /dev/null @@ -1,85 +0,0 @@ -.\" Copyright (c) 1980, 1991, 1993 -.\" The Regents of the University of California. 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. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. -.\" -.Dd September 5, 2006 -.Dt ALLOCA 3 -.Os -.Sh NAME -.Nm alloca -.Nd memory allocator -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft void * -.Fn alloca "size_t size" -.Sh DESCRIPTION -The -.Fn alloca -function -allocates -.Fa size -bytes of space in the stack frame of the caller. -This temporary space is automatically freed on -return. -.Sh RETURN VALUES -The -.Fn alloca -function returns a pointer to the beginning of the allocated space. -.Sh SEE ALSO -.Xr brk 2 , -.Xr calloc 3 , -.Xr getpagesize 3 , -.Xr malloc 3 , -.Xr realloc 3 -.Sh HISTORY -The -.Fn alloca -function appeared in -.At 32v . -.\" .Bx ?? . -.\" The function appeared in 32v, pwb and pwb.2 and in 3bsd 4bsd -.\" The first man page (or link to a man page that I can find at the -.\" moment is 4.3... -.Sh BUGS -The -.Fn alloca -function -is machine and compiler dependent; -its use is discouraged. -.Pp -The -.Fn alloca -function is slightly unsafe because it cannot ensure that the pointer -returned points to a valid and usable block of memory. -The allocation made may exceed the bounds of the stack, or even go -further into other objects in memory, and -.Fn alloca -cannot determine such an error. -Avoid -.Fn alloca -with large unbounded allocations. diff --git a/lib/libc/stdlib/atexit.c b/lib/libc/stdlib/atexit.c index e5aa66c51f38..6e4a12f9e530 100644 --- a/lib/libc/stdlib/atexit.c +++ b/lib/libc/stdlib/atexit.c @@ -35,6 +35,7 @@ #include "namespace.h" #include <errno.h> #include <link.h> +#include <stdbool.h> #include <stddef.h> #include <stdlib.h> #include <unistd.h> @@ -56,6 +57,8 @@ _Block_copy(void*); #define ATEXIT_FN_CXA 2 static pthread_mutex_t atexit_mutex = PTHREAD_MUTEX_INITIALIZER; +static void *current_finalize_dso = NULL; +static bool call_finalize_again = false; #define _MUTEX_LOCK(x) if (__isthreaded) _pthread_mutex_lock(x) #define _MUTEX_UNLOCK(x) if (__isthreaded) _pthread_mutex_unlock(x) @@ -115,6 +118,9 @@ atexit_register(struct atexit_fn *fptr) __atexit = p; } p->fns[p->ind++] = *fptr; + if (current_finalize_dso != NULL && + current_finalize_dso == fptr->fn_dso) + call_finalize_again = true; _MUTEX_UNLOCK(&atexit_mutex); return 0; } @@ -208,33 +214,38 @@ __cxa_finalize(void *dso) } _MUTEX_LOCK(&atexit_mutex); - for (p = __atexit; p; p = p->next) { - for (n = p->ind; --n >= 0;) { - if (p->fns[n].fn_type == ATEXIT_FN_EMPTY) - continue; /* already been called */ - fn = p->fns[n]; - if (dso != NULL && dso != fn.fn_dso) { - /* wrong DSO ? */ - if (!has_phdr || global_exit || - !__elf_phdr_match_addr(&phdr_info, - fn.fn_ptr.cxa_func)) - continue; + current_finalize_dso = dso; + do { + call_finalize_again = false; + for (p = __atexit; p; p = p->next) { + for (n = p->ind; --n >= 0;) { + if (p->fns[n].fn_type == ATEXIT_FN_EMPTY) + continue; /* already been called */ + fn = p->fns[n]; + if (dso != NULL && dso != fn.fn_dso) { + /* wrong DSO ? */ + if (!has_phdr || global_exit || + !__elf_phdr_match_addr(&phdr_info, + fn.fn_ptr.cxa_func)) + continue; + } + /* + Mark entry to indicate that this particular + handler has already been called. + */ + p->fns[n].fn_type = ATEXIT_FN_EMPTY; + _MUTEX_UNLOCK(&atexit_mutex); + + /* Call the function of correct type. */ + if (fn.fn_type == ATEXIT_FN_CXA) + fn.fn_ptr.cxa_func(fn.fn_arg); + else if (fn.fn_type == ATEXIT_FN_STD) + fn.fn_ptr.std_func(); + _MUTEX_LOCK(&atexit_mutex); } - /* - Mark entry to indicate that this particular handler - has already been called. - */ - p->fns[n].fn_type = ATEXIT_FN_EMPTY; - _MUTEX_UNLOCK(&atexit_mutex); - - /* Call the function of correct type. */ - if (fn.fn_type == ATEXIT_FN_CXA) - fn.fn_ptr.cxa_func(fn.fn_arg); - else if (fn.fn_type == ATEXIT_FN_STD) - fn.fn_ptr.std_func(); - _MUTEX_LOCK(&atexit_mutex); } - } + } while (call_finalize_again); + current_finalize_dso = NULL; _MUTEX_UNLOCK(&atexit_mutex); if (dso == NULL) _MUTEX_DESTROY(&atexit_mutex); diff --git a/lib/libc/stdlib/getenv.3 b/lib/libc/stdlib/getenv.3 index 1337ec867237..045a1831dfdc 100644 --- a/lib/libc/stdlib/getenv.3 +++ b/lib/libc/stdlib/getenv.3 @@ -29,12 +29,13 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 14, 2023 +.Dd April 22, 2025 .Dt GETENV 3 .Os .Sh NAME .Nm clearenv , .Nm getenv , +.Nm getenv_r , .Nm putenv , .Nm secure_getenv , .Nm setenv , @@ -48,6 +49,8 @@ .Fn clearenv "void" .Ft char * .Fn getenv "const char *name" +.Ft int +.Fn getenv_r "const char *name" "char *buf" "size_t len" .Ft char * .Fn secure_getenv "const char *name" .Ft int @@ -71,7 +74,8 @@ and .Pp The .Fn getenv -function obtains the current value of the environment variable, +function obtains the current value of the environment variable +designated by .Fa name . The application should not modify the string pointed to by the @@ -79,13 +83,23 @@ to by the function. .Pp The +.Fn getenv_r +function obtains the current value of the environment variable +designated by +.Fa name +and copies it into the buffer +.Fa buf +of length +.Fa len . +.Pp +The .Fn secure_getenv returns .Va NULL when the environment cannot be trusted, otherwise it acts like .Fn getenv . The environment currently is not trusted when -.Xr issetugid 3 +.Xr issetugid 2 returns a non-zero value, but other conditions may be added in the future. .Pp @@ -157,12 +171,13 @@ function returns if the process is in "secure execution," otherwise it will call .Fn getenv . .Pp -.Rv -std clearenv setenv putenv unsetenv +.Rv -std clearenv getenv_r setenv putenv unsetenv .Sh ERRORS .Bl -tag -width Er .It Bq Er EINVAL The function .Fn getenv , +.Fn getenv_r , .Fn setenv or .Fn unsetenv @@ -191,6 +206,11 @@ is the first character in This does not follow the .Tn POSIX specification. +.It Bq Er ENOENT +The function +.Fn getenv_r +failed because the requested variable was not found in the +environment. .It Bq Er ENOMEM The function .Fn setenv , @@ -198,6 +218,11 @@ The function or .Fn putenv failed because they were unable to allocate memory for the environment. +.It Bq Er ERANGE +The function +.Fn getenv_r +failed because the value of the requested variable was too long to fit +in the provided buffer. .El .Sh SEE ALSO .Xr csh 1 , @@ -251,6 +276,13 @@ and .Fn secure_getenv functions were added in .Fx 14 . +.Pp +The +.Fn getenv_r +function first appeared in +.Nx 4.0 +and was added in +.Fx 15 . .Sh BUGS Successive calls to .Fn setenv diff --git a/lib/libc/stdlib/getenv.c b/lib/libc/stdlib/getenv.c index f8f59526421a..c1d0b7a559d5 100644 --- a/lib/libc/stdlib/getenv.c +++ b/lib/libc/stdlib/getenv.c @@ -28,6 +28,7 @@ #include "namespace.h" #include <sys/types.h> +#include <ssp/ssp.h> #include <errno.h> #include <stdbool.h> #include <stddef.h> @@ -444,6 +445,41 @@ getenv(const char *name) /* + * Like getenv(), but copies the value into the provided buffer. + */ +int +__ssp_real(getenv_r)(const char *name, char *buf, size_t len) +{ + const char *val; + size_t nameLen; + int envNdx; + + if (name == NULL || (nameLen = __strleneq(name)) == 0) { + errno = EINVAL; + return (-1); + } + + if (environ == NULL || environ[0] == NULL) { + val = NULL; + } else if (envVars == NULL || environ != intEnviron) { + val = __findenv_environ(name, nameLen); + } else { + envNdx = envVarsTotal - 1; + val = __findenv(name, nameLen, &envNdx, true); + } + if (val == NULL) { + errno = ENOENT; + return (-1); + } + if (strlcpy(buf, val, len) >= len) { + errno = ERANGE; + return (-1); + } + return (0); +} + + +/* * Runs getenv() unless the current process is tainted by uid or gid changes, in * which case it will return NULL. */ diff --git a/lib/libc/stdlib/getopt_long.3 b/lib/libc/stdlib/getopt_long.3 index f8bb1f1b6b11..d6998d13822a 100644 --- a/lib/libc/stdlib/getopt_long.3 +++ b/lib/libc/stdlib/getopt_long.3 @@ -217,7 +217,7 @@ an error and return Specifying .Ql \&: in -.Fa optstr +.Fa optstring will cause the error message to be suppressed and .Ql \&: to be returned instead. @@ -229,7 +229,7 @@ a leading or .Ql \&- in -.Fa optstr +.Fa optstring also has special meaning. If either of these are specified, they must appear before .Ql \&: . diff --git a/lib/libc/stdtime/strftime.c b/lib/libc/stdtime/strftime.c index 5943e6387174..89c9e4cf88ff 100644 --- a/lib/libc/stdtime/strftime.c +++ b/lib/libc/stdtime/strftime.c @@ -1,4 +1,6 @@ /* + * SPDX-License-Identifier: BSD-4.3TAHOE + * * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * diff --git a/lib/libc/string/memccpy.3 b/lib/libc/string/memccpy.3 index 2de981449119..0d35a68fce67 100644 --- a/lib/libc/string/memccpy.3 +++ b/lib/libc/string/memccpy.3 @@ -80,7 +80,7 @@ The function conforms to .St -p1003.1-2004 and -.St -isoC-2024 . +.St -isoC-2023 . .Sh HISTORY The .Fn memccpy diff --git a/lib/libc/string/memset.3 b/lib/libc/string/memset.3 index f2dba3ec5a48..f6ab9dacb516 100644 --- a/lib/libc/string/memset.3 +++ b/lib/libc/string/memset.3 @@ -141,4 +141,4 @@ conforms to K.3.7.4.1. .Fn memset_explicit conforms to -.St -isoC-2024 . +.St -isoC-2023 . diff --git a/lib/libc/sys/closefrom.c b/lib/libc/sys/closefrom.c index 292702fad38c..76ed4e744397 100644 --- a/lib/libc/sys/closefrom.c +++ b/lib/libc/sys/closefrom.c @@ -26,20 +26,12 @@ */ #include <sys/param.h> -#include <sys/syscall.h> #include <unistd.h> #include "libc_private.h" -#define CLOSE_RANGE_OSREL 1300091 - void closefrom(int lowfd) { - - if (__getosreldate() >= CLOSE_RANGE_OSREL) - __sys_close_range(MAX(0, lowfd), ~0U, 0); - else - /* Fallback to closefrom(2) on older kernels. */ - syscall(SYS_freebsd12_closefrom, lowfd); + __sys_close_range(MAX(0, lowfd), ~0U, 0); } diff --git a/lib/libc/tests/gen/Makefile b/lib/libc/tests/gen/Makefile index 87f2b8320d25..8c2151105209 100644 --- a/lib/libc/tests/gen/Makefile +++ b/lib/libc/tests/gen/Makefile @@ -7,14 +7,28 @@ ATF_TESTS_C+= fmtcheck2_test ATF_TESTS_C+= fmtmsg_test ATF_TESTS_C+= fnmatch2_test ATF_TESTS_C+= fpclassify2_test +.if ${COMPILER_FEATURES:Mblocks} +ATF_TESTS_C+= fts_blocks_test +.endif +ATF_TESTS_C+= fts_misc_test +ATF_TESTS_C+= fts_options_test ATF_TESTS_C+= ftw_test ATF_TESTS_C+= getentropy_test ATF_TESTS_C+= getmntinfo_test ATF_TESTS_C+= glob2_test +.if ${COMPILER_FEATURES:Mblocks} +ATF_TESTS_C+= glob_blocks_test +.endif ATF_TESTS_C+= makecontext_test +ATF_TESTS_C+= opendir_test ATF_TESTS_C+= popen_test ATF_TESTS_C+= posix_spawn_test ATF_TESTS_C+= realpath2_test +ATF_TESTS_C+= scandir_test +.if ${COMPILER_FEATURES:Mblocks} +ATF_TESTS_C+= scandir_blocks_test +.endif +ATF_TESTS_C+= sig2str_test ATF_TESTS_C+= sigsetops_test ATF_TESTS_C+= wordexp_test @@ -92,6 +106,20 @@ TEST_METADATA.setdomainname_test+= is_exclusive=true TESTS_SUBDIRS= execve TESTS_SUBDIRS+= posix_spawn +# Tests that require address sanitizer +.if ${COMPILER_FEATURES:Masan} +.for t in scandir_test realpath2_test +CFLAGS.${t}.c+= -fsanitize=address +LDFLAGS.${t}+= -fsanitize=address +.endfor +.endif + +# Tests that require blocks support +.for t in fts_blocks_test glob_blocks_test scandir_blocks_test +CFLAGS.${t}.c+= -fblocks +LIBADD.${t}+= BlocksRuntime +.endfor + # The old testcase name TEST_FNMATCH= test-fnmatch CLEANFILES+= ${GEN_SH_CASE_TESTCASES} diff --git a/lib/libc/tests/gen/fnmatch_test.c b/lib/libc/tests/gen/fnmatch_test.c index 6cdf5f2a05fa..0ff7400a4a4f 100644 --- a/lib/libc/tests/gen/fnmatch_test.c +++ b/lib/libc/tests/gen/fnmatch_test.c @@ -26,6 +26,7 @@ #include <sys/param.h> #include <errno.h> +#include <locale.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -176,10 +177,90 @@ ATF_TC_BODY(fnmatch_test, tc) } +ATF_TC(fnmatch_characterclass); +ATF_TC_HEAD(fnmatch_characterclass, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test fnmatch with character classes"); +} + +ATF_TC_BODY(fnmatch_characterclass, tc) +{ + ATF_CHECK(fnmatch("[[:alnum:]]", "a", 0) == 0); + ATF_CHECK(fnmatch("[[:cntrl:]]", "\a", 0) == 0); + ATF_CHECK(fnmatch("[[:lower:]]", "a", 0) == 0); + ATF_CHECK(fnmatch("[[:space:]]", " ", 0) == 0); + ATF_CHECK(fnmatch("[[:alpha:]]", "a", 0) == 0); + ATF_CHECK(fnmatch("[[:digit:]]", "0", 0) == 0); + ATF_CHECK(fnmatch("[[:print:]]", "a", 0) == 0); + ATF_CHECK(fnmatch("[[:upper:]]", "A", 0) == 0); + ATF_CHECK(fnmatch("[[:blank:]]", " ", 0) == 0); + ATF_CHECK(fnmatch("[[:graph:]]", "a", 0) == 0); + ATF_CHECK(fnmatch("[[:punct:]]", ".", 0) == 0); + ATF_CHECK(fnmatch("[[:xdigit:]]", "f", 0) == 0); + + /* + * POSIX.1, section 9.3.5. states that '[:' and ':]' + * should be interpreted as character classes symbol only + * when part of a bracket expression. + */ + ATF_CHECK(fnmatch("[:alnum:]", "a", 0) == 0); + ATF_CHECK(fnmatch("[:alnum:]", ":", 0) == 0); + ATF_CHECK(fnmatch("[:alnum:]", "1", 0) != 0); +} + +ATF_TC(fnmatch_collsym); +ATF_TC_HEAD(fnmatch_collsym, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test fnmatch with collating symbols"); +} + +ATF_TC_BODY(fnmatch_collsym, tc) +{ + setlocale(LC_ALL, "cs_CZ.UTF-8"); + ATF_CHECK(fnmatch("[ch]", "ch", 0) != 0); + ATF_CHECK(fnmatch("[[.ch.]]", "ch", 0) == 0); + ATF_CHECK(fnmatch("[[.ch.]]h", "chh", 0) == 0); + + /* + * POSIX.1, section 9.3.5. states that '[.' and '.]' + * should be interpreted as a collating symbol only + * when part of a bracket expression. + */ + ATF_CHECK(fnmatch("[.ch.]", "c", 0) == 0); + ATF_CHECK(fnmatch("[.ch.]", "h", 0) == 0); + ATF_CHECK(fnmatch("[.ch.]", ".", 0) == 0); +} + +ATF_TC(fnmatch_equivclass); +ATF_TC_HEAD(fnmatch_equivclass, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test fnmatch with equivalence classes"); +} + +ATF_TC_BODY(fnmatch_equivclass, tc) +{ + setlocale(LC_ALL, "en_US.UTF-8"); + ATF_CHECK(fnmatch("[[=a=]]b", "ab", 0) == 0); + ATF_CHECK(fnmatch("[[=a=]]b", "Ab", 0) == 0); + ATF_CHECK(fnmatch("[[=à=]]b", "ab", 0) == 0); + ATF_CHECK(fnmatch("[[=a=]]b", "àb", 0) == 0); + + /* + * POSIX.1, section 9.3.5. states that '[=' and '=]' + * should be interpreted as an equivalence class only + * when part of a bracket expression. + */ + ATF_CHECK(fnmatch("[=a=]b", "=b", 0) == 0); + ATF_CHECK(fnmatch("[=a=]b", "ab", 0) == 0); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, fnmatch_test); + ATF_TP_ADD_TC(tp, fnmatch_collsym); + ATF_TP_ADD_TC(tp, fnmatch_characterclass); + ATF_TP_ADD_TC(tp, fnmatch_equivclass); return (atf_no_error()); } diff --git a/lib/libc/tests/gen/fts_blocks_test.c b/lib/libc/tests/gen/fts_blocks_test.c new file mode 100644 index 000000000000..f020dd8dea45 --- /dev/null +++ b/lib/libc/tests/gen/fts_blocks_test.c @@ -0,0 +1,68 @@ +/*- + * Copyright (c) 2025 Klara, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <sys/stat.h> + +#include <fcntl.h> +#include <fts.h> + +#include <atf-c.h> + +/* + * Create two directories with three files each in lexicographical order, + * then call FTS with a sort block that sorts in reverse lexicographical + * order. This has the least chance of getting a false positive due to + * differing file system semantics. UFS will return the files in the + * order they were created while ZFS will sort them lexicographically; in + * both cases, the order we expect is the reverse. + */ +ATF_TC(fts_blocks_test); +ATF_TC_HEAD(fts_blocks_test, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Test FTS with a block in lieu of a comparison function"); +} +ATF_TC_BODY(fts_blocks_test, tc) +{ + char *args[] = { + "bar", "foo", NULL + }; + char *paths[] = { + "foo", "z", "y", "x", "foo", + "bar", "c", "b", "a", "bar", + NULL + }; + char **expect = paths; + FTS *fts; + FTSENT *ftse; + + ATF_REQUIRE_EQ(0, mkdir("bar", 0755)); + ATF_REQUIRE_EQ(0, close(creat("bar/a", 0644))); + ATF_REQUIRE_EQ(0, close(creat("bar/b", 0644))); + ATF_REQUIRE_EQ(0, close(creat("bar/c", 0644))); + ATF_REQUIRE_EQ(0, mkdir("foo", 0755)); + ATF_REQUIRE_EQ(0, close(creat("foo/x", 0644))); + ATF_REQUIRE_EQ(0, close(creat("foo/y", 0644))); + ATF_REQUIRE_EQ(0, close(creat("foo/z", 0644))); + fts = fts_open_b(args, 0, + ^(const FTSENT * const *a, const FTSENT * const *b) { + return (strcmp((*b)->fts_name, (*a)->fts_name)); + }); + ATF_REQUIRE_MSG(fts != NULL, "fts_open_b(): %m"); + while ((ftse = fts_read(fts)) != NULL && *expect != NULL) { + ATF_CHECK_STREQ(*expect, ftse->fts_name); + expect++; + } + ATF_CHECK_EQ(NULL, ftse); + ATF_CHECK_EQ(NULL, *expect); + ATF_REQUIRE_EQ_MSG(0, fts_close(fts), "fts_close(): %m"); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, fts_blocks_test); + return (atf_no_error()); +} diff --git a/lib/libc/tests/gen/fts_misc_test.c b/lib/libc/tests/gen/fts_misc_test.c new file mode 100644 index 000000000000..91640078f63c --- /dev/null +++ b/lib/libc/tests/gen/fts_misc_test.c @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 2025 Klara, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <sys/stat.h> + +#include <fcntl.h> +#include <fts.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <atf-c.h> + +#include "fts_test.h" + +ATF_TC(fts_unrdir); +ATF_TC_HEAD(fts_unrdir, tc) +{ + atf_tc_set_md_var(tc, "descr", "unreadable directories"); + atf_tc_set_md_var(tc, "require.user", "unprivileged"); +} +ATF_TC_BODY(fts_unrdir, tc) +{ + ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); + ATF_REQUIRE_EQ(0, mkdir("dir/unr", 0100)); + ATF_REQUIRE_EQ(0, mkdir("dir/unx", 0400)); + fts_test(tc, &(struct fts_testcase){ + (char *[]){ "dir", NULL }, + FTS_PHYSICAL, + (struct fts_expect[]){ + { FTS_D, "dir", "dir" }, + { FTS_D, "unr", "unr" }, + { FTS_DNR, "unr", "unr" }, + { FTS_D, "unx", "unx" }, + { FTS_DP, "unx", "unx" }, + { FTS_DP, "dir", "dir" }, + { 0 } + }, + }); +} + +ATF_TC(fts_unrdir_nochdir); +ATF_TC_HEAD(fts_unrdir_nochdir, tc) +{ + atf_tc_set_md_var(tc, "descr", "unreadable directories (nochdir)"); + atf_tc_set_md_var(tc, "require.user", "unprivileged"); +} +ATF_TC_BODY(fts_unrdir_nochdir, tc) +{ + ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); + ATF_REQUIRE_EQ(0, mkdir("dir/unr", 0100)); + ATF_REQUIRE_EQ(0, mkdir("dir/unx", 0400)); + fts_test(tc, &(struct fts_testcase){ + (char *[]){ "dir", NULL }, + FTS_PHYSICAL | FTS_NOCHDIR, + (struct fts_expect[]){ + { FTS_D, "dir", "dir" }, + { FTS_D, "unr", "dir/unr" }, + { FTS_DNR, "unr", "dir/unr" }, + { FTS_D, "unx", "dir/unx" }, + { FTS_DP, "unx", "dir/unx" }, + { FTS_DP, "dir", "dir" }, + { 0 } + }, + }); +} + +ATF_TP_ADD_TCS(tp) +{ + fts_check_debug(); + ATF_TP_ADD_TC(tp, fts_unrdir); + ATF_TP_ADD_TC(tp, fts_unrdir_nochdir); + return (atf_no_error()); +} diff --git a/lib/libc/tests/gen/fts_options_test.c b/lib/libc/tests/gen/fts_options_test.c new file mode 100644 index 000000000000..fc3015138a49 --- /dev/null +++ b/lib/libc/tests/gen/fts_options_test.c @@ -0,0 +1,394 @@ +/*- + * Copyright (c) 2025 Klara, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <sys/stat.h> + +#include <fcntl.h> +#include <fts.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <atf-c.h> + +#include "fts_test.h" + +static char *all_paths[] = { + "dir", + "dirl", + "file", + "filel", + "dead", + "noent", + NULL +}; + +/* + * Prepare the files and directories we will be inspecting. + */ +static void +fts_options_prepare(const struct atf_tc *tc) +{ + ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); + ATF_REQUIRE_EQ(0, close(creat("file", 0644))); + ATF_REQUIRE_EQ(0, close(creat("dir/file", 0644))); + ATF_REQUIRE_EQ(0, symlink("..", "dir/up")); + ATF_REQUIRE_EQ(0, symlink("dir", "dirl")); + ATF_REQUIRE_EQ(0, symlink("file", "filel")); + ATF_REQUIRE_EQ(0, symlink("noent", "dead")); +} + +ATF_TC(fts_options_logical); +ATF_TC_HEAD(fts_options_logical, tc) +{ + atf_tc_set_md_var(tc, "descr", "FTS_LOGICAL"); +} +ATF_TC_BODY(fts_options_logical, tc) +{ + fts_options_prepare(tc); + fts_test(tc, &(struct fts_testcase){ + all_paths, + FTS_LOGICAL, + (struct fts_expect[]){ + { FTS_DL, "dead", "dead" }, + { FTS_D, "dir", "dir" }, + { FTS_F, "file", "dir/file" }, + { FTS_D, "up", "dir/up" }, + { FTS_DL, "dead", "dir/up/dead" }, + { FTS_DC, "dir", "dir/up/dir" }, + { FTS_DC, "dirl", "dir/up/dirl" }, + { FTS_F, "file", "dir/up/file" }, + { FTS_F, "filel", "dir/up/filel" }, + { FTS_DP, "up", "dir/up" }, + { FTS_DP, "dir", "dir" }, + { FTS_D, "dirl", "dirl" }, + { FTS_F, "file", "dirl/file" }, + { FTS_D, "up", "dirl/up" }, + { FTS_DL, "dead", "dirl/up/dead" }, + { FTS_DC, "dir", "dirl/up/dir" }, + { FTS_DC, "dirl", "dirl/up/dirl" }, + { FTS_F, "file", "dirl/up/file" }, + { FTS_F, "filel", "dirl/up/filel" }, + { FTS_DP, "up", "dirl/up" }, + { FTS_DP, "dirl", "dirl" }, + { FTS_F, "file", "file" }, + { FTS_F, "filel", "filel" }, + { FTS_NS, "noent", "noent" }, + { 0 } + }, + }); +} + +ATF_TC(fts_options_logical_nostat); +ATF_TC_HEAD(fts_options_logical_nostat, tc) +{ + atf_tc_set_md_var(tc, "descr", "FTS_LOGICAL | FTS_NOSTAT"); +} +ATF_TC_BODY(fts_options_logical_nostat, tc) +{ + /* + * While FTS_LOGICAL is not documented as being incompatible with + * FTS_NOSTAT, and FTS does not clear FTS_NOSTAT if FTS_LOGICAL is + * set, FTS_LOGICAL effectively nullifies FTS_NOSTAT by overriding + * the follow check in fts_stat(). In theory, FTS could easily be + * changed to only stat links (to check what they point to) in the + * FTS_LOGICAL | FTS_NOSTAT case, which would produce a different + * result here, so keep the test around in case that ever happens. + */ + atf_tc_expect_fail("FTS_LOGICAL nullifies FTS_NOSTAT"); + fts_options_prepare(tc); + fts_test(tc, &(struct fts_testcase){ + all_paths, + FTS_LOGICAL | FTS_NOSTAT, + (struct fts_expect[]){ + { FTS_DL, "dead", "dead" }, + { FTS_D, "dir", "dir" }, + { FTS_NSOK, "file", "dir/file" }, + { FTS_D, "up", "dir/up" }, + { FTS_DL, "dead", "dir/up/dead" }, + { FTS_DC, "dir", "dir/up/dir" }, + { FTS_DC, "dirl", "dir/up/dirl" }, + { FTS_NSOK, "file", "dir/up/file" }, + { FTS_NSOK, "filel", "dir/up/filel" }, + { FTS_DP, "up", "dir/up" }, + { FTS_DP, "dir", "dir" }, + { FTS_D, "dirl", "dirl" }, + { FTS_NSOK, "file", "dirl/file" }, + { FTS_D, "up", "dirl/up" }, + { FTS_DL, "dead", "dirl/up/dead" }, + { FTS_DC, "dir", "dirl/up/dir" }, + { FTS_DC, "dirl", "dirl/up/dirl" }, + { FTS_NSOK, "file", "dirl/up/file" }, + { FTS_NSOK, "filel", "dirl/up/filel" }, + { FTS_DP, "up", "dirl/up" }, + { FTS_DP, "dirl", "dirl" }, + { FTS_F, "file", "file" }, + { FTS_F, "filel", "filel" }, + { FTS_NS, "noent", "noent" }, + { 0 } + }, + }); +} + +ATF_TC(fts_options_logical_seedot); +ATF_TC_HEAD(fts_options_logical_seedot, tc) +{ + atf_tc_set_md_var(tc, "descr", "FTS_LOGICAL | FTS_SEEDOT"); +} +ATF_TC_BODY(fts_options_logical_seedot, tc) +{ + fts_options_prepare(tc); + fts_test(tc, &(struct fts_testcase){ + all_paths, + FTS_LOGICAL | FTS_SEEDOT, + (struct fts_expect[]){ + { FTS_DL, "dead", "dead" }, + { FTS_D, "dir", "dir" }, + { FTS_DOT, ".", "dir/." }, + { FTS_DOT, "..", "dir/.." }, + { FTS_F, "file", "dir/file" }, + { FTS_D, "up", "dir/up" }, + { FTS_DOT, ".", "dir/up/." }, + { FTS_DOT, "..", "dir/up/.." }, + { FTS_DL, "dead", "dir/up/dead" }, + { FTS_DC, "dir", "dir/up/dir" }, + { FTS_DC, "dirl", "dir/up/dirl" }, + { FTS_F, "file", "dir/up/file" }, + { FTS_F, "filel", "dir/up/filel" }, + { FTS_DP, "up", "dir/up" }, + { FTS_DP, "dir", "dir" }, + { FTS_D, "dirl", "dirl" }, + { FTS_DOT, ".", "dirl/." }, + { FTS_DOT, "..", "dirl/.." }, + { FTS_F, "file", "dirl/file" }, + { FTS_D, "up", "dirl/up" }, + { FTS_DOT, ".", "dirl/up/." }, + { FTS_DOT, "..", "dirl/up/.." }, + { FTS_DL, "dead", "dirl/up/dead" }, + { FTS_DC, "dir", "dirl/up/dir" }, + { FTS_DC, "dirl", "dirl/up/dirl" }, + { FTS_F, "file", "dirl/up/file" }, + { FTS_F, "filel", "dirl/up/filel" }, + { FTS_DP, "up", "dirl/up" }, + { FTS_DP, "dirl", "dirl" }, + { FTS_F, "file", "file" }, + { FTS_F, "filel", "filel" }, + { FTS_NS, "noent", "noent" }, + { 0 } + }, + }); +} + +ATF_TC(fts_options_physical); +ATF_TC_HEAD(fts_options_physical, tc) +{ + atf_tc_set_md_var(tc, "descr", "FTS_PHYSICAL"); +} +ATF_TC_BODY(fts_options_physical, tc) +{ + fts_options_prepare(tc); + fts_test(tc, &(struct fts_testcase){ + all_paths, + FTS_PHYSICAL, + (struct fts_expect[]){ + { FTS_SL, "dead", "dead" }, + { FTS_D, "dir", "dir" }, + { FTS_F, "file", "file" }, + { FTS_SL, "up", "up" }, + { FTS_DP, "dir", "dir" }, + { FTS_SL, "dirl", "dirl" }, + { FTS_F, "file", "file" }, + { FTS_SL, "filel", "filel" }, + { FTS_NS, "noent", "noent" }, + { 0 } + }, + }); +} + +ATF_TC(fts_options_physical_nochdir); +ATF_TC_HEAD(fts_options_physical_nochdir, tc) +{ + atf_tc_set_md_var(tc, "descr", "FTS_PHYSICAL | FTS_NOCHDIR"); +} +ATF_TC_BODY(fts_options_physical_nochdir, tc) +{ + fts_options_prepare(tc); + fts_test(tc, &(struct fts_testcase){ + all_paths, + FTS_PHYSICAL | FTS_NOCHDIR, + (struct fts_expect[]){ + { FTS_SL, "dead", "dead" }, + { FTS_D, "dir", "dir" }, + { FTS_F, "file", "dir/file" }, + { FTS_SL, "up", "dir/up" }, + { FTS_DP, "dir", "dir" }, + { FTS_SL, "dirl", "dirl" }, + { FTS_F, "file", "file" }, + { FTS_SL, "filel", "filel" }, + { FTS_NS, "noent", "noent" }, + { 0 } + }, + }); +} + +ATF_TC(fts_options_physical_comfollow); +ATF_TC_HEAD(fts_options_physical_comfollow, tc) +{ + atf_tc_set_md_var(tc, "descr", "FTS_PHYSICAL | FTS_COMFOLLOW"); +} +ATF_TC_BODY(fts_options_physical_comfollow, tc) +{ + fts_options_prepare(tc); + fts_test(tc, &(struct fts_testcase){ + all_paths, + FTS_PHYSICAL | FTS_COMFOLLOW, + (struct fts_expect[]){ + { FTS_DL, "dead", "dead" }, + { FTS_D, "dir", "dir" }, + { FTS_F, "file", "file" }, + { FTS_SL, "up", "up" }, + { FTS_DP, "dir", "dir" }, + { FTS_D, "dirl", "dirl" }, + { FTS_F, "file", "file" }, + { FTS_SL, "up", "up" }, + { FTS_DP, "dirl", "dirl" }, + { FTS_F, "file", "file" }, + { FTS_F, "filel", "filel" }, + { FTS_NS, "noent", "noent" }, + { 0 } + }, + }); +} + +ATF_TC(fts_options_physical_comfollowdir); +ATF_TC_HEAD(fts_options_physical_comfollowdir, tc) +{ + atf_tc_set_md_var(tc, "descr", "FTS_PHYSICAL | FTS_COMFOLLOWDIR"); +} +ATF_TC_BODY(fts_options_physical_comfollowdir, tc) +{ + fts_options_prepare(tc); + fts_test(tc, &(struct fts_testcase){ + all_paths, + FTS_PHYSICAL | FTS_COMFOLLOWDIR, + (struct fts_expect[]){ + { FTS_DL, "dead", "dead" }, + { FTS_D, "dir", "dir" }, + { FTS_F, "file", "file" }, + { FTS_SL, "up", "up" }, + { FTS_DP, "dir", "dir" }, + { FTS_D, "dirl", "dirl" }, + { FTS_F, "file", "file" }, + { FTS_SL, "up", "up" }, + { FTS_DP, "dirl", "dirl" }, + { FTS_F, "file", "file" }, + { FTS_SL, "filel", "filel" }, + { FTS_NS, "noent", "noent" }, + { 0 } + }, + }); +} + +ATF_TC(fts_options_physical_nostat); +ATF_TC_HEAD(fts_options_physical_nostat, tc) +{ + atf_tc_set_md_var(tc, "descr", "FTS_PHYSICAL | FTS_NOSTAT"); +} +ATF_TC_BODY(fts_options_physical_nostat, tc) +{ + fts_options_prepare(tc); + fts_test(tc, &(struct fts_testcase){ + all_paths, + FTS_PHYSICAL | FTS_NOSTAT, + (struct fts_expect[]){ + { FTS_SL, "dead", "dead" }, + { FTS_D, "dir", "dir" }, + { FTS_NSOK, "file", "file" }, + { FTS_NSOK, "up", "up" }, + { FTS_DP, "dir", "dir" }, + { FTS_SL, "dirl", "dirl" }, + { FTS_F, "file", "file" }, + { FTS_SL, "filel", "filel" }, + { FTS_NS, "noent", "noent" }, + { 0 } + }, + }); +} + +ATF_TC(fts_options_physical_nostat_type); +ATF_TC_HEAD(fts_options_physical_nostat_type, tc) +{ + atf_tc_set_md_var(tc, "descr", "FTS_PHYSICAL | FTS_NOSTAT_TYPE"); +} +ATF_TC_BODY(fts_options_physical_nostat_type, tc) +{ + fts_options_prepare(tc); + fts_test(tc, &(struct fts_testcase){ + all_paths, + FTS_PHYSICAL | FTS_NOSTAT_TYPE, + (struct fts_expect[]){ + { FTS_SL, "dead", "dead" }, + { FTS_D, "dir", "dir" }, + { FTS_F, "file", "file" }, + { FTS_SL, "up", "up" }, + { FTS_DP, "dir", "dir" }, + { FTS_SL, "dirl", "dirl" }, + { FTS_F, "file", "file" }, + { FTS_SL, "filel", "filel" }, + { FTS_NS, "noent", "noent" }, + { 0 } + }, + }); +} + +ATF_TC(fts_options_physical_seedot); +ATF_TC_HEAD(fts_options_physical_seedot, tc) +{ + atf_tc_set_md_var(tc, "descr", "FTS_PHYSICAL | FTS_SEEDOT"); +} +ATF_TC_BODY(fts_options_physical_seedot, tc) +{ + fts_options_prepare(tc); + fts_test(tc, &(struct fts_testcase){ + all_paths, + FTS_PHYSICAL | FTS_SEEDOT, + (struct fts_expect[]){ + { FTS_SL, "dead", "dead" }, + { FTS_D, "dir", "dir" }, + { FTS_DOT, ".", "." }, + { FTS_DOT, "..", ".." }, + { FTS_F, "file", "file" }, + { FTS_SL, "up", "up" }, + { FTS_DP, "dir", "dir" }, + { FTS_SL, "dirl", "dirl" }, + { FTS_F, "file", "file" }, + { FTS_SL, "filel", "filel" }, + { FTS_NS, "noent", "noent" }, + { 0 } + }, + }); +} + +/* + * TODO: Add tests for FTS_XDEV and FTS_WHITEOUT + */ + +ATF_TP_ADD_TCS(tp) +{ + fts_check_debug(); + ATF_TP_ADD_TC(tp, fts_options_logical); + ATF_TP_ADD_TC(tp, fts_options_logical_nostat); + ATF_TP_ADD_TC(tp, fts_options_logical_seedot); + ATF_TP_ADD_TC(tp, fts_options_physical); + ATF_TP_ADD_TC(tp, fts_options_physical_nochdir); + ATF_TP_ADD_TC(tp, fts_options_physical_comfollow); + ATF_TP_ADD_TC(tp, fts_options_physical_comfollowdir); + ATF_TP_ADD_TC(tp, fts_options_physical_nostat); + ATF_TP_ADD_TC(tp, fts_options_physical_nostat_type); + ATF_TP_ADD_TC(tp, fts_options_physical_seedot); + return (atf_no_error()); +} diff --git a/lib/libc/tests/gen/fts_test.h b/lib/libc/tests/gen/fts_test.h new file mode 100644 index 000000000000..b3f15050f265 --- /dev/null +++ b/lib/libc/tests/gen/fts_test.h @@ -0,0 +1,81 @@ +/*- + * Copyright (c) 2025 Klara, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef FTS_TEST_H_INCLUDED +#define FTS_TEST_H_INCLUDED + +struct fts_expect { + int fts_info; + const char *fts_name; + const char *fts_accpath; +}; + +struct fts_testcase { + char **paths; + int fts_options; + struct fts_expect *fts_expect; +}; + +/* shorter name for dead links */ +#define FTS_DL FTS_SLNONE + +/* are we being debugged? */ +static bool fts_test_debug; + +/* + * Set debug flag if appropriate. + */ +static void +fts_check_debug(void) +{ + fts_test_debug = !getenv("__RUNNING_INSIDE_ATF_RUN") && + isatty(STDERR_FILENO); +} + +/* + * Lexical order for reproducability. + */ +static int +fts_lexical_compar(const FTSENT * const *a, const FTSENT * const *b) +{ + return (strcmp((*a)->fts_name, (*b)->fts_name)); +} + +/* + * Run FTS with the specified paths and options and verify that it + * produces the expected result in the correct order. + */ +static void +fts_test(const struct atf_tc *tc, const struct fts_testcase *fts_tc) +{ + FTS *fts; + FTSENT *ftse; + const struct fts_expect *expect = fts_tc->fts_expect; + long level = 0; + + fts = fts_open(fts_tc->paths, fts_tc->fts_options, fts_lexical_compar); + ATF_REQUIRE_MSG(fts != NULL, "fts_open(): %m"); + while ((ftse = fts_read(fts)) != NULL && expect->fts_name != NULL) { + if (expect->fts_info == FTS_DP || expect->fts_info == FTS_DNR) + level--; + if (fts_test_debug) { + fprintf(stderr, "%2ld %2d %s\n", level, + ftse->fts_info, ftse->fts_name); + } + ATF_CHECK_STREQ(expect->fts_name, ftse->fts_name); + ATF_CHECK_STREQ(expect->fts_accpath, ftse->fts_accpath); + ATF_CHECK_INTEQ(expect->fts_info, ftse->fts_info); + ATF_CHECK_INTEQ(level, ftse->fts_level); + if (expect->fts_info == FTS_D) + level++; + expect++; + } + ATF_CHECK_EQ(NULL, ftse); + ATF_CHECK_EQ(NULL, expect->fts_name); + ATF_REQUIRE_EQ_MSG(0, fts_close(fts), "fts_close(): %m"); +} + +#endif /* FTS_TEST_H_INCLUDED */ diff --git a/lib/libc/tests/gen/glob2_test.c b/lib/libc/tests/gen/glob2_test.c index 8f69c36fece7..ff1b36b830b8 100644 --- a/lib/libc/tests/gen/glob2_test.c +++ b/lib/libc/tests/gen/glob2_test.c @@ -25,9 +25,12 @@ */ #include <sys/param.h> +#include <sys/stat.h> + #include <errno.h> #include <fcntl.h> #include <glob.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -102,10 +105,80 @@ ATF_TC_BODY(glob_pathological_test, tc) } } +ATF_TC(glob_period); +ATF_TC_HEAD(glob_period, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Test behaviour when matching files that start with a period" + "(documented in the glob(3) CAVEATS section)."); +} +ATF_TC_BODY(glob_period, tc) +{ + int i; + glob_t g; + + atf_utils_create_file(".test", ""); + glob(".", 0, NULL, &g); + ATF_REQUIRE_MSG(g.gl_matchc == 1, + "glob(3) shouldn't match files starting with a period when using '.'"); + for (i = 0; i < g.gl_matchc; i++) + printf("%s\n", g.gl_pathv[i]); + glob(".*", 0, NULL, &g); + ATF_REQUIRE_MSG(g.gl_matchc == 3 && strcmp(g.gl_pathv[2], ".test") == 0, + "glob(3) should match files starting with a period when using '.*'"); +} + +static bool glob_callback_invoked; + +static int +errfunc(const char *path, int err) +{ + ATF_CHECK_STREQ(path, "test/"); + ATF_CHECK(err == EACCES); + glob_callback_invoked = true; + /* Suppress EACCES errors. */ + return (0); +} + +ATF_TC(glob_callback); +ATF_TC_HEAD(glob_callback, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Test ability of callback function to suppress errors"); + atf_tc_set_md_var(tc, "require.user", "unprivileged"); +} +ATF_TC_BODY(glob_callback, tc) +{ + glob_t g; + int rv; + + ATF_REQUIRE_EQ(0, mkdir("test", 0755)); + ATF_REQUIRE_EQ(0, symlink("foo", "test/foo")); + ATF_REQUIRE_EQ(0, chmod("test", 0)); + + glob_callback_invoked = false; + rv = glob("test/*", 0, errfunc, &g); + ATF_CHECK_MSG(glob_callback_invoked, + "glob(3) failed to invoke callback function"); + ATF_CHECK_EQ_MSG(GLOB_NOMATCH, rv, + "callback function failed to suppress EACCES"); + globfree(&g); + + /* GLOB_ERR should ignore the suppressed error. */ + glob_callback_invoked = false; + rv = glob("test/*", GLOB_ERR, errfunc, &g); + ATF_CHECK_MSG(glob_callback_invoked, + "glob(3) failed to invoke callback function"); + ATF_CHECK_EQ_MSG(GLOB_ABORTED, rv, + "GLOB_ERR didn't override callback function"); + globfree(&g); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, glob_pathological_test); - + ATF_TP_ADD_TC(tp, glob_period); + ATF_TP_ADD_TC(tp, glob_callback); return (atf_no_error()); } diff --git a/lib/libc/tests/gen/glob_blocks_test.c b/lib/libc/tests/gen/glob_blocks_test.c new file mode 100644 index 000000000000..629b90bee762 --- /dev/null +++ b/lib/libc/tests/gen/glob_blocks_test.c @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2025 Klara, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <sys/stat.h> + +#include <errno.h> +#include <glob.h> +#include <stdbool.h> + +#include <atf-c.h> + +ATF_TC(glob_b_callback); +ATF_TC_HEAD(glob_b_callback, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Test ability of callback block to suppress errors"); + atf_tc_set_md_var(tc, "require.user", "unprivileged"); +} +ATF_TC_BODY(glob_b_callback, tc) +{ + static bool glob_callback_invoked; + static int (^errblk)(const char *, int) = + ^(const char *path, int err) { + ATF_CHECK_STREQ(path, "test/"); + ATF_CHECK(err == EACCES); + glob_callback_invoked = true; + /* Suppress EACCES errors. */ + return (0); + }; + glob_t g; + int rv; + + ATF_REQUIRE_EQ(0, mkdir("test", 0755)); + ATF_REQUIRE_EQ(0, symlink("foo", "test/foo")); + ATF_REQUIRE_EQ(0, chmod("test", 0)); + + glob_callback_invoked = false; + rv = glob_b("test/*", 0, errblk, &g); + ATF_CHECK_MSG(glob_callback_invoked, + "glob(3) failed to invoke callback block"); + ATF_CHECK_EQ_MSG(GLOB_NOMATCH, rv, + "callback function failed to suppress EACCES"); + globfree(&g); + + /* GLOB_ERR should ignore the suppressed error. */ + glob_callback_invoked = false; + rv = glob_b("test/*", GLOB_ERR, errblk, &g); + ATF_CHECK_MSG(glob_callback_invoked, + "glob(3) failed to invoke callback block"); + ATF_CHECK_EQ_MSG(GLOB_ABORTED, rv, + "GLOB_ERR didn't override callback block"); + globfree(&g); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, glob_b_callback); + return (atf_no_error()); +} diff --git a/lib/libc/tests/gen/opendir_test.c b/lib/libc/tests/gen/opendir_test.c new file mode 100644 index 000000000000..b7481255654f --- /dev/null +++ b/lib/libc/tests/gen/opendir_test.c @@ -0,0 +1,145 @@ +/*- + * Copyright (c) 2025 Klara, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <sys/stat.h> + +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> + +#include <atf-c.h> + +/* + * Create a directory with a single subdirectory. + */ +static void +opendir_prepare(const struct atf_tc *tc) +{ + ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); + ATF_REQUIRE_EQ(0, mkdir("dir/subdir", 0755)); +} + +/* + * Assuming dirp represents the directory created by opendir_prepare(), + * verify that readdir() returns what we expected to see there. + */ +static void +opendir_check(const struct atf_tc *tc, DIR *dirp) +{ + struct dirent *ent; + + ATF_REQUIRE((ent = readdir(dirp)) != NULL); + ATF_CHECK_EQ(1, ent->d_namlen); + ATF_CHECK_STREQ(".", ent->d_name); + ATF_CHECK_EQ(DT_DIR, ent->d_type); + ATF_REQUIRE((ent = readdir(dirp)) != NULL); + ATF_CHECK_EQ(2, ent->d_namlen); + ATF_CHECK_STREQ("..", ent->d_name); + ATF_CHECK_EQ(DT_DIR, ent->d_type); + ATF_REQUIRE((ent = readdir(dirp)) != NULL); + ATF_CHECK_EQ(sizeof("subdir") - 1, ent->d_namlen); + ATF_CHECK_STREQ("subdir", ent->d_name); + ATF_CHECK_EQ(DT_DIR, ent->d_type); + ATF_CHECK(readdir(dirp) == NULL); + ATF_CHECK(readdir(dirp) == NULL); +} + +ATF_TC(opendir_ok); +ATF_TC_HEAD(opendir_ok, tc) +{ + atf_tc_set_md_var(tc, "descr", "Open a directory."); +} +ATF_TC_BODY(opendir_ok, tc) +{ + DIR *dirp; + + opendir_prepare(tc); + ATF_REQUIRE((dirp = opendir("dir")) != NULL); + opendir_check(tc, dirp); + ATF_CHECK_EQ(0, closedir(dirp)); +} + +ATF_TC(opendir_fifo); +ATF_TC_HEAD(opendir_fifo, tc) +{ + atf_tc_set_md_var(tc, "descr", "Do not hang if given a named pipe."); +} +ATF_TC_BODY(opendir_fifo, tc) +{ + DIR *dirp; + int fd; + + ATF_REQUIRE((fd = mkfifo("fifo", 0644)) >= 0); + ATF_REQUIRE_EQ(0, close(fd)); + ATF_REQUIRE((dirp = opendir("fifo")) == NULL); + ATF_CHECK_EQ(ENOTDIR, errno); +} + +ATF_TC(fdopendir_ok); +ATF_TC_HEAD(fdopendir_ok, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Open a directory from a directory descriptor."); +} +ATF_TC_BODY(fdopendir_ok, tc) +{ + DIR *dirp; + int dd; + + opendir_prepare(tc); + ATF_REQUIRE((dd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0); + ATF_REQUIRE((dirp = fdopendir(dd)) != NULL); + opendir_check(tc, dirp); + ATF_CHECK_EQ(dd, fdclosedir(dirp)); + ATF_CHECK_EQ(0, close(dd)); +} + +ATF_TC(fdopendir_ebadf); +ATF_TC_HEAD(fdopendir_ebadf, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Open a directory from an invalid descriptor."); +} +ATF_TC_BODY(fdopendir_ebadf, tc) +{ + DIR *dirp; + int dd; + + ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); + ATF_REQUIRE((dd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0); + ATF_CHECK_EQ(0, close(dd)); + ATF_REQUIRE((dirp = fdopendir(dd)) == NULL); + ATF_CHECK_EQ(EBADF, errno); +} + +ATF_TC(fdopendir_enotdir); +ATF_TC_HEAD(fdopendir_enotdir, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Open a directory from a non-directory descriptor."); +} +ATF_TC_BODY(fdopendir_enotdir, tc) +{ + DIR *dirp; + int fd; + + ATF_REQUIRE((fd = open("file", O_CREAT | O_RDWR, 0644)) >= 0); + ATF_REQUIRE((dirp = fdopendir(fd)) == NULL); + ATF_CHECK_EQ(ENOTDIR, errno); + ATF_CHECK_EQ(0, close(fd)); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, opendir_ok); + ATF_TP_ADD_TC(tp, fdopendir_ok); + ATF_TP_ADD_TC(tp, fdopendir_ebadf); + ATF_TP_ADD_TC(tp, fdopendir_enotdir); + ATF_TP_ADD_TC(tp, opendir_fifo); + return (atf_no_error()); +} diff --git a/lib/libc/tests/gen/scandir_blocks_test.c b/lib/libc/tests/gen/scandir_blocks_test.c new file mode 100644 index 000000000000..b94270bc410e --- /dev/null +++ b/lib/libc/tests/gen/scandir_blocks_test.c @@ -0,0 +1,118 @@ +/*- + * Copyright (c) 2025 Klara, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <sys/stat.h> + +#include <dirent.h> +#include <fcntl.h> +#include <stdlib.h> + +#include <atf-c.h> + +static void +scandir_blocks_prepare(const struct atf_tc *tc) +{ + ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); + ATF_REQUIRE_EQ(0, mkdir("dir/dir", 0755)); + ATF_REQUIRE_EQ(0, close(creat("dir/file", 0644))); + ATF_REQUIRE_EQ(0, symlink("file", "dir/link")); + ATF_REQUIRE_EQ(0, mkdir("dir/skip", 0755)); +} + +static void +scandir_blocks_verify(const struct atf_tc *tc, int n, struct dirent **namelist) +{ + ATF_REQUIRE_EQ_MSG(5, n, "return value is %d", n); + ATF_CHECK_STREQ("link", namelist[0]->d_name); + ATF_CHECK_STREQ("file", namelist[1]->d_name); + ATF_CHECK_STREQ("dir", namelist[2]->d_name); + ATF_CHECK_STREQ("..", namelist[3]->d_name); + ATF_CHECK_STREQ(".", namelist[4]->d_name); +} + +ATF_TC(scandir_b_test); +ATF_TC_HEAD(scandir_b_test, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scandir_b()"); +} +ATF_TC_BODY(scandir_b_test, tc) +{ + struct dirent **namelist = NULL; + int i, ret; + + scandir_blocks_prepare(tc); + ret = scandir_b("dir", &namelist, + ^(const struct dirent *ent) { + return (strcmp(ent->d_name, "skip") != 0); + }, + ^(const struct dirent **a, const struct dirent **b) { + return (strcmp((*b)->d_name, (*a)->d_name)); + }); + scandir_blocks_verify(tc, ret, namelist); + for (i = 0; i < ret; i++) + free(namelist[i]); + free(namelist); +} + +ATF_TC(fdscandir_b_test); +ATF_TC_HEAD(fdscandir_b_test, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test fdscandir_b()"); +} +ATF_TC_BODY(fdscandir_b_test, tc) +{ + struct dirent **namelist = NULL; + int fd, i, ret; + + scandir_blocks_prepare(tc); + ATF_REQUIRE((fd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0); + ret = fdscandir_b(fd, &namelist, + ^(const struct dirent *ent) { + return (strcmp(ent->d_name, "skip") != 0); + }, + ^(const struct dirent **a, const struct dirent **b) { + return (strcmp((*b)->d_name, (*a)->d_name)); + }); + scandir_blocks_verify(tc, ret, namelist); + for (i = 0; i < ret; i++) + free(namelist[i]); + free(namelist); + ATF_REQUIRE_EQ(0, close(fd)); +} + +ATF_TC(scandirat_b_test); +ATF_TC_HEAD(scandirat_b_test, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scandirat_b()"); +} +ATF_TC_BODY(scandirat_b_test, tc) +{ + struct dirent **namelist = NULL; + int fd, i, ret; + + scandir_blocks_prepare(tc); + ATF_REQUIRE((fd = open("dir", O_DIRECTORY | O_SEARCH)) >= 0); + ret = scandirat_b(fd, ".", &namelist, + ^(const struct dirent *ent) { + return (strcmp(ent->d_name, "skip") != 0); + }, + ^(const struct dirent **a, const struct dirent **b) { + return (strcmp((*b)->d_name, (*a)->d_name)); + }); + scandir_blocks_verify(tc, ret, namelist); + for (i = 0; i < ret; i++) + free(namelist[i]); + free(namelist); + ATF_REQUIRE_EQ(0, close(fd)); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, scandir_b_test); + ATF_TP_ADD_TC(tp, fdscandir_b_test); + ATF_TP_ADD_TC(tp, scandirat_b_test); + return (atf_no_error()); +} diff --git a/lib/libc/tests/gen/scandir_test.c b/lib/libc/tests/gen/scandir_test.c new file mode 100644 index 000000000000..afd25bf7c0b2 --- /dev/null +++ b/lib/libc/tests/gen/scandir_test.c @@ -0,0 +1,195 @@ +/*- + * Copyright (c) 2025 Klara, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <sys/stat.h> + +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> + +#include <atf-c.h> + +static void +scandir_prepare(const struct atf_tc *tc) +{ + ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); + ATF_REQUIRE_EQ(0, mkdir("dir/dir", 0755)); + ATF_REQUIRE_EQ(0, close(creat("dir/file", 0644))); + ATF_REQUIRE_EQ(0, symlink("file", "dir/link")); + ATF_REQUIRE_EQ(0, mkdir("dir/skip", 0755)); +} + +static void +scandir_verify(const struct atf_tc *tc, int n, struct dirent **namelist) +{ + ATF_REQUIRE_EQ_MSG(5, n, "return value is %d", n); + ATF_CHECK_STREQ("link", namelist[0]->d_name); + ATF_CHECK_STREQ("file", namelist[1]->d_name); + ATF_CHECK_STREQ("dir", namelist[2]->d_name); + ATF_CHECK_STREQ("..", namelist[3]->d_name); + ATF_CHECK_STREQ(".", namelist[4]->d_name); +} + +static int +scandir_select(const struct dirent *ent) +{ + return (strcmp(ent->d_name, "skip") != 0); +} + +static int +scandir_compare(const struct dirent **a, const struct dirent **b) +{ + return (strcmp((*b)->d_name, (*a)->d_name)); +} + +ATF_TC(scandir_test); +ATF_TC_HEAD(scandir_test, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scandir()"); +} +ATF_TC_BODY(scandir_test, tc) +{ + struct dirent **namelist = NULL; + int i, ret; + + scandir_prepare(tc); + ret = scandir("dir", &namelist, scandir_select, scandir_compare); + scandir_verify(tc, ret, namelist); + for (i = 0; i < ret; i++) + free(namelist[i]); + free(namelist); +} + +ATF_TC(fdscandir_test); +ATF_TC_HEAD(fdscandir_test, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test fdscandir()"); +} +ATF_TC_BODY(fdscandir_test, tc) +{ + struct dirent **namelist = NULL; + int fd, i, ret; + + scandir_prepare(tc); + ATF_REQUIRE((fd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0); + ret = fdscandir(fd, &namelist, scandir_select, scandir_compare); + scandir_verify(tc, ret, namelist); + for (i = 0; i < ret; i++) + free(namelist[i]); + free(namelist); + ATF_REQUIRE_EQ(0, close(fd)); +} + +ATF_TC(scandirat_test); +ATF_TC_HEAD(scandirat_test, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test scandirat()"); +} +ATF_TC_BODY(scandirat_test, tc) +{ + struct dirent **namelist = NULL; + int fd, i, ret; + + scandir_prepare(tc); + ATF_REQUIRE((fd = open("dir", O_DIRECTORY | O_SEARCH)) >= 0); + ret = scandirat(fd, ".", &namelist, scandir_select, scandir_compare); + scandir_verify(tc, ret, namelist); + for (i = 0; i < ret; i++) + free(namelist[i]); + free(namelist); + ATF_REQUIRE_EQ(0, close(fd)); +} + +static int +scandir_none(const struct dirent *ent __unused) +{ + return (0); +} + +ATF_TC(scandir_none); +ATF_TC_HEAD(scandir_none, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Test scandir() when no entries are selected"); +} +ATF_TC_BODY(scandir_none, tc) +{ + struct dirent **namelist = NULL; + + ATF_REQUIRE_EQ(0, scandir(".", &namelist, scandir_none, alphasort)); + ATF_REQUIRE(namelist); + free(namelist); +} + +/* + * Test that scandir() propagates errors from readdir(): we create a + * directory with enough entries that it can't be read in a single + * getdirentries() call, then abuse the selection callback to close the + * file descriptor scandir() is using after the first call, causing the + * next one to fail, and verify that readdir() returns an error instead of + * a partial result. We make two passes, one in which nothing was + * selected before the error occurred, and one in which everything was. + */ +static int scandir_error_count; +static int scandir_error_fd; +static int scandir_error_select_return; + +static int +scandir_error_select(const struct dirent *ent __unused) +{ + if (scandir_error_count++ == 0) + close(scandir_error_fd); + return (scandir_error_select_return); +} + +ATF_TC(scandir_error); +ATF_TC_HEAD(scandir_error, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Test that scandir() propagates errors from readdir()"); +} +ATF_TC_BODY(scandir_error, tc) +{ + char path[16]; + struct dirent **namelist = NULL; + int fd, i; + + ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); + for (i = 0; i < 1024; i++) { + snprintf(path, sizeof(path), "dir/%04x", i); + ATF_REQUIRE_EQ(0, symlink(path + 4, path)); + } + + /* first pass, select nothing */ + ATF_REQUIRE((fd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0); + scandir_error_count = 0; + scandir_error_fd = fd; + scandir_error_select_return = 0; + ATF_CHECK_ERRNO(EBADF, + fdscandir(fd, &namelist, scandir_error_select, NULL) < 0); + ATF_CHECK_EQ(NULL, namelist); + + /* second pass, select everything */ + ATF_REQUIRE((fd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0); + scandir_error_count = 0; + scandir_error_fd = fd; + scandir_error_select_return = 1; + ATF_CHECK_ERRNO(EBADF, + fdscandir(fd, &namelist, scandir_error_select, NULL) < 0); + ATF_CHECK_EQ(NULL, namelist); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, scandir_test); + ATF_TP_ADD_TC(tp, fdscandir_test); + ATF_TP_ADD_TC(tp, scandirat_test); + ATF_TP_ADD_TC(tp, scandir_none); + ATF_TP_ADD_TC(tp, scandir_error); + return (atf_no_error()); +} diff --git a/lib/libc/tests/gen/sig2str_test.c b/lib/libc/tests/gen/sig2str_test.c new file mode 100644 index 000000000000..00b6ebb2349a --- /dev/null +++ b/lib/libc/tests/gen/sig2str_test.c @@ -0,0 +1,213 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Ricardo Branco <rbranco@suse.de> + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <ctype.h> +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <string.h> + +#include <atf-c.h> + +static void +test_roundtrip(int signum) +{ + char str[SIG2STR_MAX]; + int sig; + + ATF_REQUIRE_EQ_MSG(sig2str(signum, str), 0, + "sig2str(%d) failed", signum); + ATF_REQUIRE_EQ_MSG(str2sig(str, &sig), 0, + "str2sig(\"%s\") failed", str); + ATF_REQUIRE_INTEQ_MSG(sig, signum, + "Mismatch: roundtrip conversion gave %d instead of %d", + sig, signum); +} + +ATF_TC_WITHOUT_HEAD(sig2str_valid); +ATF_TC_BODY(sig2str_valid, tc) +{ + int sig; + + for (sig = 1; sig < sys_nsig; sig++) { + test_roundtrip(sig); + } +} + +ATF_TC_WITHOUT_HEAD(sig2str_invalid); +ATF_TC_BODY(sig2str_invalid, tc) +{ + char buf[SIG2STR_MAX]; + + ATF_CHECK(sig2str(0, buf) != 0); + ATF_CHECK(sig2str(-1, buf) != 0); + ATF_CHECK(sig2str(SIGRTMAX + 1, buf) != 0); +} + +ATF_TC_WITHOUT_HEAD(str2sig_rtmin_rtmax); +ATF_TC_BODY(str2sig_rtmin_rtmax, tc) +{ + int sig; + + ATF_CHECK_MSG(str2sig("RTMIN", &sig) == 0, + "str2sig(\"RTMIN\") failed"); + ATF_CHECK_INTEQ_MSG(sig, SIGRTMIN, + "RTMIN mapped to %d, expected %d", sig, SIGRTMIN); + + ATF_CHECK_MSG(str2sig("RTMAX", &sig) == 0, + "str2sig(\"RTMAX\") failed"); + ATF_CHECK_INTEQ_MSG(sig, SIGRTMAX, + "RTMAX mapped to %d, expected %d", sig, SIGRTMAX); + + ATF_CHECK_MSG(str2sig("RTMIN+1", &sig) == 0, + "str2sig(\"RTMIN+1\") failed"); + ATF_CHECK_INTEQ_MSG(sig, SIGRTMIN + 1, + "RTMIN+1 mapped to %d, expected %d", sig, SIGRTMIN + 1); + + ATF_CHECK_MSG(str2sig("RTMAX-1", &sig) == 0, + "str2sig(\"RTMAX-1\") failed"); + ATF_CHECK_INTEQ_MSG(sig, SIGRTMAX - 1, + "RTMAX-1 mapped to %d, expected %d", sig, SIGRTMAX - 1); +} + +ATF_TC_WITHOUT_HEAD(str2sig_invalid_rt); +ATF_TC_BODY(str2sig_invalid_rt, tc) +{ + int i, sig; + + const char *invalid[] = { + "RTMIN+0", + "RTMAX-0", + "RTMIN-777", + "RTMIN+777", + "RTMAX-777", + "RTMAX+777", + "RTMIN-", + "RTMAX-", + "RTMIN0", + "RTMAX1", + "RTMIN+abc", + "RTMIN-abc", + NULL + }; + + for (i = 0; invalid[i] != NULL; i++) { + ATF_CHECK_MSG(str2sig(invalid[i], &sig) != 0, + "str2sig(\"%s\") unexpectedly succeeded", invalid[i]); + } +} + +ATF_TC_WITHOUT_HEAD(str2sig_fullname); +ATF_TC_BODY(str2sig_fullname, tc) +{ + char fullname[SIG2STR_MAX + 3]; + int n, sig; + + for (sig = 1; sig < sys_nsig; sig++) { + snprintf(fullname, sizeof(fullname), "SIG%s", sys_signame[sig]); + + ATF_CHECK_MSG(str2sig(fullname, &n) == 0, + "str2sig(\"%s\") failed with errno %d (%s)", + fullname, errno, strerror(errno)); + + ATF_CHECK_INTEQ_MSG(n, sig, + "Mismatch: %s = %d, str2sig(\"%s\") = %d", + sys_signame[sig], sig, fullname, n); + } +} + +ATF_TC_WITHOUT_HEAD(str2sig_lowercase); +ATF_TC_BODY(str2sig_lowercase, tc) +{ + char fullname[SIG2STR_MAX + 3]; + int n, sig; + + for (sig = 1; sig < sys_nsig; sig++) { + snprintf(fullname, sizeof(fullname), "sig%s", sys_signame[sig]); + for (size_t i = 3; i < strlen(fullname); i++) + fullname[i] = toupper((unsigned char)fullname[i]); + + ATF_CHECK_MSG(str2sig(fullname, &n) == 0, + "str2sig(\"%s\") failed with errno %d (%s)", + fullname, errno, strerror(errno)); + + ATF_CHECK_INTEQ_MSG(n, sig, + "Mismatch: %s = %d, str2sig(\"%s\") = %d", + sys_signame[sig], sig, fullname, n); + } +} + +ATF_TC_WITHOUT_HEAD(str2sig_numeric); +ATF_TC_BODY(str2sig_numeric, tc) +{ + char buf[16]; + int n, sig; + + for (sig = NSIG; sig < SIGRTMIN; sig++) { + snprintf(buf, sizeof(buf), "%d", sig); + ATF_CHECK_MSG(str2sig(buf, &n) == 0, + "str2sig(\"%s\") failed", buf); + ATF_CHECK_INTEQ_MSG(n, sig, + "Mismatch: str2sig(\"%s\") = %d, expected %d", + buf, n, sig); + } +} + +ATF_TC_WITHOUT_HEAD(str2sig_invalid); +ATF_TC_BODY(str2sig_invalid, tc) +{ + const char *invalid[] = { + "SIGDOESNOTEXIST", + "DOESNOTEXIST", + "INTERRUPT", + "", + "SIG", + "123abc", + "sig1extra", + NULL + }; + int i, sig; + + for (i = 0; invalid[i] != NULL; i++) { + ATF_CHECK_MSG(str2sig(invalid[i], &sig) != 0, + "str2sig(\"%s\") unexpectedly succeeded", invalid[i]); + } +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, sig2str_valid); + ATF_TP_ADD_TC(tp, sig2str_invalid); + ATF_TP_ADD_TC(tp, str2sig_rtmin_rtmax); + ATF_TP_ADD_TC(tp, str2sig_invalid_rt); + ATF_TP_ADD_TC(tp, str2sig_fullname); + ATF_TP_ADD_TC(tp, str2sig_lowercase); + ATF_TP_ADD_TC(tp, str2sig_numeric); + ATF_TP_ADD_TC(tp, str2sig_invalid); + return (atf_no_error()); +} diff --git a/lib/libc/tests/gen/wordexp_test.c b/lib/libc/tests/gen/wordexp_test.c index 909097fbf51e..a8b9d5509633 100644 --- a/lib/libc/tests/gen/wordexp_test.c +++ b/lib/libc/tests/gen/wordexp_test.c @@ -292,6 +292,31 @@ ATF_TC_BODY(with_SIGCHILD_handler_test, tc) ATF_REQUIRE(r == 0); } +ATF_TC_WITHOUT_HEAD(with_SIGCHILD_ignore_test); +ATF_TC_BODY(with_SIGCHILD_ignore_test, tc) +{ + struct sigaction sa; + wordexp_t we; + int r; + + /* With SIGCHLD set to ignore so that the kernel auto-reaps zombies. */ + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sa.sa_handler = SIG_IGN; + r = sigaction(SIGCHLD, &sa, NULL); + ATF_REQUIRE(r == 0); + r = wordexp("hello world", &we, 0); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 2); + ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0); + ATF_REQUIRE(we.we_wordv[2] == NULL); + wordfree(&we); + sa.sa_handler = SIG_DFL; + r = sigaction(SIGCHLD, &sa, NULL); + ATF_REQUIRE(r == 0); +} + ATF_TC_WITHOUT_HEAD(with_unused_non_default_IFS_test); ATF_TC_BODY(with_unused_non_default_IFS_test, tc) { @@ -350,6 +375,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, WRDE_BADCHAR_test); ATF_TP_ADD_TC(tp, WRDE_SYNTAX_test); ATF_TP_ADD_TC(tp, with_SIGCHILD_handler_test); + ATF_TP_ADD_TC(tp, with_SIGCHILD_ignore_test); ATF_TP_ADD_TC(tp, with_unused_non_default_IFS_test); ATF_TP_ADD_TC(tp, with_used_non_default_IFS_test); diff --git a/lib/libc/tests/locale/wctomb_test.c b/lib/libc/tests/locale/wctomb_test.c index 1e142ed74c48..ef2a6dcbe1e3 100644 --- a/lib/libc/tests/locale/wctomb_test.c +++ b/lib/libc/tests/locale/wctomb_test.c @@ -41,6 +41,18 @@ #include <atf-c.h> +ATF_TC_WITHOUT_HEAD(euccs1_test); +ATF_TC_BODY(euccs1_test, tc) +{ + wchar_t wc = 0x8e000000; + char buf[MB_LEN_MAX]; + + ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "zh_CN.eucCN"), + "zh_CN.eucCN") == 0); + + ATF_REQUIRE(wctomb(&buf[0], wc) == 4); +} + ATF_TC_WITHOUT_HEAD(wctomb_test); ATF_TC_BODY(wctomb_test, tc) { @@ -104,6 +116,7 @@ ATF_TC_BODY(wctomb_test, tc) ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, euccs1_test); ATF_TP_ADD_TC(tp, wctomb_test); return (atf_no_error()); diff --git a/lib/libc/tests/net/Makefile b/lib/libc/tests/net/Makefile index 0a49683ea3d1..24cff61e8d24 100644 --- a/lib/libc/tests/net/Makefile +++ b/lib/libc/tests/net/Makefile @@ -3,6 +3,9 @@ PACKAGE= tests ATF_TESTS_C+= ether_test ATF_TESTS_C+= eui64_aton_test ATF_TESTS_C+= eui64_ntoa_test +ATF_TESTS_CXX+= link_addr_test + +CXXSTD.link_addr_test= c++20 CFLAGS+= -I${.CURDIR} @@ -31,8 +34,7 @@ aton_ether_subr.c: gen_ether_subr ${SRCTOP}/sys/net/if_ethersubr.c .include "../Makefile.netbsd-tests" -# TODO: the testcases needs to be ported to FreeBSD -#TESTS_SUBDIRS= getaddrinfo +TESTS_SUBDIRS= getaddrinfo ${PACKAGE}FILES+= hosts ${PACKAGE}FILES+= resolv.conf diff --git a/lib/libc/tests/net/getaddrinfo/Makefile b/lib/libc/tests/net/getaddrinfo/Makefile index 5d98aa31a86a..1299e91615b7 100644 --- a/lib/libc/tests/net/getaddrinfo/Makefile +++ b/lib/libc/tests/net/getaddrinfo/Makefile @@ -1,14 +1,11 @@ PACKAGE= tests -TESTSRC= ${SRCTOP}/contrib/netbsd-tests/lib/libc/net/${.CURDIR:T} - .include <bsd.own.mk> BINDIR= ${TESTSDIR} -.error This testcase needs to be ported to FreeBSD (the output from getaddrinfo_test differs from NetBSD) - -NETBSD_ATF_TESTS_SH= getaddrinfo_test +ATF_TESTS_SH= getaddrinfo_test +ATF_TESTS_C= getaddrinfo PROGS= h_gai @@ -17,13 +14,33 @@ ${PACKAGE}DATA_FILESPACKAGE= tests ${PACKAGE}DATA_FILESDIR= ${TESTSDIR}/data -${PACKAGE}DATA_FILES+= basics_v4.exp basics_v4v6.exp -${PACKAGE}DATA_FILES+= no_host_v4.exp no_host_v4v6.exp -${PACKAGE}DATA_FILES+= no_serv_v4.exp no_serv_v4v6.exp -${PACKAGE}DATA_FILES+= sock_raw_v4.exp sock_raw_v4v6.exp -${PACKAGE}DATA_FILES+= spec_fam_v4.exp spec_fam_v4v6.exp -${PACKAGE}DATA_FILES+= scoped.exp -${PACKAGE}DATA_FILES+= unsup_fam.exp +${PACKAGE}DATA_FILES+= data/basics_v4.exp +${PACKAGE}DATA_FILES+= data/basics_v4_only.exp +${PACKAGE}DATA_FILES+= data/basics_v4v6.exp +${PACKAGE}DATA_FILES+= data/basics_v4v6_prefer_v4.exp +${PACKAGE}DATA_FILES+= data/no_host_v4.exp +${PACKAGE}DATA_FILES+= data/no_host_v4_only.exp +${PACKAGE}DATA_FILES+= data/no_host_v4v6.exp +${PACKAGE}DATA_FILES+= data/no_host_v4v6_prefer_v4.exp +${PACKAGE}DATA_FILES+= data/no_serv_v4.exp +${PACKAGE}DATA_FILES+= data/no_serv_v4_only.exp +${PACKAGE}DATA_FILES+= data/no_serv_v4v6.exp +${PACKAGE}DATA_FILES+= data/no_serv_v4v6_prefer_v4.exp +${PACKAGE}DATA_FILES+= data/scoped.exp +${PACKAGE}DATA_FILES+= data/scoped_v4_only.exp +${PACKAGE}DATA_FILES+= data/scoped_v4v6_prefer_v4.exp +${PACKAGE}DATA_FILES+= data/sock_raw_v4.exp +${PACKAGE}DATA_FILES+= data/sock_raw_v4_only.exp +${PACKAGE}DATA_FILES+= data/sock_raw_v4v6.exp +${PACKAGE}DATA_FILES+= data/sock_raw_v4v6_prefer_v4.exp +${PACKAGE}DATA_FILES+= data/spec_fam_v4.exp +${PACKAGE}DATA_FILES+= data/spec_fam_v4_only.exp +${PACKAGE}DATA_FILES+= data/spec_fam_v4v6.exp +${PACKAGE}DATA_FILES+= data/spec_fam_v4v6_prefer_v4.exp +${PACKAGE}DATA_FILES+= data/unsup_fam.exp +${PACKAGE}DATA_FILES+= data/unsup_fam_v4_only.exp +${PACKAGE}DATA_FILES+= data/unsup_fam_v4v6_prefer_v4.exp + .include "../../Makefile.netbsd-tests" diff --git a/lib/libc/tests/net/getaddrinfo/data/basics_v4.exp b/lib/libc/tests/net/getaddrinfo/data/basics_v4.exp new file mode 100644 index 000000000000..4f1ee3517211 --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/basics_v4.exp @@ -0,0 +1,42 @@ +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host ::1 serv http +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv http + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host 127.0.0.1 serv http +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host localhost serv http +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host ::1 serv tftp +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv tftp +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv tftp + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host 127.0.0.1 serv tftp +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv tftp +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv tftp + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host localhost serv tftp +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv tftp +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv tftp + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host ::1 serv echo +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv echo +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv echo +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv echo + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host 127.0.0.1 serv echo +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv echo +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv echo +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv echo + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host localhost serv echo +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv echo +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv echo +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv echo + diff --git a/lib/libc/tests/net/getaddrinfo/data/basics_v4_only.exp b/lib/libc/tests/net/getaddrinfo/data/basics_v4_only.exp new file mode 100644 index 000000000000..0a37d3212649 --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/basics_v4_only.exp @@ -0,0 +1,50 @@ +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host ::1 serv http +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv http + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host 127.0.0.1 serv http +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host localhost serv http +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http +ai4: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai5: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai6: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv http + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host ::1 serv tftp +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv tftp +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv tftp + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host 127.0.0.1 serv tftp +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv tftp +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv tftp + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host localhost serv tftp +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv tftp +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv tftp +ai3: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv tftp +ai4: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv tftp + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host ::1 serv echo +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv echo +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv echo +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv echo + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host 127.0.0.1 serv echo +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv echo +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv echo +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv echo + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host localhost serv echo +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv echo +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv echo +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv echo +ai4: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv echo +ai5: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv echo +ai6: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv echo + diff --git a/lib/libc/tests/net/getaddrinfo/data/basics_v4v6.exp b/lib/libc/tests/net/getaddrinfo/data/basics_v4v6.exp new file mode 100644 index 000000000000..b74758e93e2e --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/basics_v4v6.exp @@ -0,0 +1,50 @@ +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host ::1 serv http +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv http + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host 127.0.0.1 serv http +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host localhost serv http +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv http +ai4: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai5: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai6: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host ::1 serv tftp +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv tftp +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv tftp + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host 127.0.0.1 serv tftp +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv tftp +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv tftp + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host localhost serv tftp +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv tftp +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv tftp +ai3: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv tftp +ai4: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv tftp + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host ::1 serv echo +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv echo +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv echo +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv echo + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host 127.0.0.1 serv echo +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv echo +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv echo +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv echo + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host localhost serv echo +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv echo +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv echo +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv echo +ai4: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv echo +ai5: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv echo +ai6: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv echo + diff --git a/lib/libc/tests/net/getaddrinfo/data/basics_v4v6_prefer_v4.exp b/lib/libc/tests/net/getaddrinfo/data/basics_v4v6_prefer_v4.exp new file mode 100644 index 000000000000..0a37d3212649 --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/basics_v4v6_prefer_v4.exp @@ -0,0 +1,50 @@ +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host ::1 serv http +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv http + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host 127.0.0.1 serv http +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host localhost serv http +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http +ai4: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai5: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai6: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv http + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host ::1 serv tftp +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv tftp +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv tftp + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host 127.0.0.1 serv tftp +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv tftp +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv tftp + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host localhost serv tftp +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv tftp +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv tftp +ai3: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv tftp +ai4: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv tftp + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host ::1 serv echo +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv echo +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv echo +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv echo + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host 127.0.0.1 serv echo +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv echo +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv echo +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv echo + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host localhost serv echo +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv echo +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv echo +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv echo +ai4: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv echo +ai5: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv echo +ai6: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv echo + diff --git a/lib/libc/tests/net/getaddrinfo/data/generate_testdata.sh b/lib/libc/tests/net/getaddrinfo/data/generate_testdata.sh new file mode 100755 index 000000000000..f0425a3b0283 --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/generate_testdata.sh @@ -0,0 +1,45 @@ +#service ip6addrctl prefer_ipv4 +TEST=./h_gai +family=v4_only + +( $TEST ::1 http + $TEST 127.0.0.1 http + $TEST localhost http + $TEST ::1 tftp + $TEST 127.0.0.1 tftp + $TEST localhost tftp + $TEST ::1 echo + $TEST 127.0.0.1 echo + $TEST localhost echo ) > basics_${family}.exp + +( $TEST -4 localhost http + $TEST -6 localhost http ) > spec_fam_${family}.exp + +( $TEST '' http + $TEST '' echo + $TEST '' tftp + $TEST '' 80 + $TEST -P '' http + $TEST -P '' echo + $TEST -P '' tftp + $TEST -P '' 80 + $TEST -S '' 80 + $TEST -D '' 80 ) > no_host_${family}.exp + +( $TEST ::1 '' + $TEST 127.0.0.1 '' + $TEST localhost '' + $TEST '' '' ) > no_serv_${family}.exp + +( $TEST -R -p 0 localhost '' + $TEST -R -p 59 localhost '' + $TEST -R -p 59 localhost 80 + $TEST -R -p 59 localhost www + $TEST -R -p 59 ::1 '' ) > sock_raw_${family}.exp + +( $TEST -f 99 localhost '' ) > unsup_fam_${family}.exp + +( $TEST fe80::1%lo0 http +# IF=`ifconfig -a | grep -v '^ ' | sed -e 's/:.*//' | head -1 | awk '{print $1}'` +# $TEST fe80::1%$IF http +) > scoped_${family}.exp diff --git a/lib/libc/tests/net/getaddrinfo/data/no_host_v4.exp b/lib/libc/tests/net/getaddrinfo/data/no_host_v4.exp new file mode 100644 index 000000000000..7ed41cd9d88a --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/no_host_v4.exp @@ -0,0 +1,44 @@ +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv http +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv echo +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv echo +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv echo +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv echo + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv tftp +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv tftp +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv tftp + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv 80 +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x3 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv http +ai1: flags 0x3 family 2 socktype 2 protocol 17 addrlen 16 host 0.0.0.0 serv http +ai2: flags 0x3 family 2 socktype 1 protocol 6 addrlen 16 host 0.0.0.0 serv http +ai3: flags 0x3 family 2 socktype 5 protocol 132 addrlen 16 host 0.0.0.0 serv http + +arg: flags 0x3 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv echo +ai1: flags 0x3 family 2 socktype 2 protocol 17 addrlen 16 host 0.0.0.0 serv echo +ai2: flags 0x3 family 2 socktype 1 protocol 6 addrlen 16 host 0.0.0.0 serv echo +ai3: flags 0x3 family 2 socktype 5 protocol 132 addrlen 16 host 0.0.0.0 serv echo + +arg: flags 0x3 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv tftp +ai1: flags 0x3 family 2 socktype 2 protocol 17 addrlen 16 host 0.0.0.0 serv tftp +ai2: flags 0x3 family 2 socktype 1 protocol 6 addrlen 16 host 0.0.0.0 serv tftp + +arg: flags 0x3 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv 80 +ai1: flags 0x3 family 2 socktype 2 protocol 17 addrlen 16 host 0.0.0.0 serv http +ai2: flags 0x3 family 2 socktype 1 protocol 6 addrlen 16 host 0.0.0.0 serv http +ai3: flags 0x3 family 2 socktype 5 protocol 132 addrlen 16 host 0.0.0.0 serv http + +arg: flags 0x2 family 0 socktype 1 protocol 0 addrlen 0 host (empty) serv 80 +ai1: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 0 socktype 2 protocol 0 addrlen 0 host (empty) serv 80 +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http + diff --git a/lib/libc/tests/net/getaddrinfo/data/no_host_v4_only.exp b/lib/libc/tests/net/getaddrinfo/data/no_host_v4_only.exp new file mode 100644 index 000000000000..596799305117 --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/no_host_v4_only.exp @@ -0,0 +1,68 @@ +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv http +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv http +ai4: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai5: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai6: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv echo +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv echo +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv echo +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv echo +ai4: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv echo +ai5: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv echo +ai6: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv echo + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv tftp +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv tftp +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv tftp +ai3: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv tftp +ai4: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv tftp + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv 80 +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv http +ai4: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai5: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai6: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x3 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv http +ai1: flags 0x3 family 28 socktype 2 protocol 17 addrlen 28 host :: serv http +ai2: flags 0x3 family 28 socktype 1 protocol 6 addrlen 28 host :: serv http +ai3: flags 0x3 family 28 socktype 5 protocol 132 addrlen 28 host :: serv http +ai4: flags 0x3 family 2 socktype 2 protocol 17 addrlen 16 host 0.0.0.0 serv http +ai5: flags 0x3 family 2 socktype 1 protocol 6 addrlen 16 host 0.0.0.0 serv http +ai6: flags 0x3 family 2 socktype 5 protocol 132 addrlen 16 host 0.0.0.0 serv http + +arg: flags 0x3 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv echo +ai1: flags 0x3 family 28 socktype 2 protocol 17 addrlen 28 host :: serv echo +ai2: flags 0x3 family 28 socktype 1 protocol 6 addrlen 28 host :: serv echo +ai3: flags 0x3 family 28 socktype 5 protocol 132 addrlen 28 host :: serv echo +ai4: flags 0x3 family 2 socktype 2 protocol 17 addrlen 16 host 0.0.0.0 serv echo +ai5: flags 0x3 family 2 socktype 1 protocol 6 addrlen 16 host 0.0.0.0 serv echo +ai6: flags 0x3 family 2 socktype 5 protocol 132 addrlen 16 host 0.0.0.0 serv echo + +arg: flags 0x3 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv tftp +ai1: flags 0x3 family 28 socktype 2 protocol 17 addrlen 28 host :: serv tftp +ai2: flags 0x3 family 28 socktype 1 protocol 6 addrlen 28 host :: serv tftp +ai3: flags 0x3 family 2 socktype 2 protocol 17 addrlen 16 host 0.0.0.0 serv tftp +ai4: flags 0x3 family 2 socktype 1 protocol 6 addrlen 16 host 0.0.0.0 serv tftp + +arg: flags 0x3 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv 80 +ai1: flags 0x3 family 28 socktype 2 protocol 17 addrlen 28 host :: serv http +ai2: flags 0x3 family 28 socktype 1 protocol 6 addrlen 28 host :: serv http +ai3: flags 0x3 family 28 socktype 5 protocol 132 addrlen 28 host :: serv http +ai4: flags 0x3 family 2 socktype 2 protocol 17 addrlen 16 host 0.0.0.0 serv http +ai5: flags 0x3 family 2 socktype 1 protocol 6 addrlen 16 host 0.0.0.0 serv http +ai6: flags 0x3 family 2 socktype 5 protocol 132 addrlen 16 host 0.0.0.0 serv http + +arg: flags 0x2 family 0 socktype 1 protocol 0 addrlen 0 host (empty) serv 80 +ai1: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 0 socktype 2 protocol 0 addrlen 0 host (empty) serv 80 +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http + diff --git a/lib/libc/tests/net/getaddrinfo/data/no_host_v4v6.exp b/lib/libc/tests/net/getaddrinfo/data/no_host_v4v6.exp new file mode 100644 index 000000000000..596799305117 --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/no_host_v4v6.exp @@ -0,0 +1,68 @@ +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv http +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv http +ai4: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai5: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai6: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv echo +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv echo +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv echo +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv echo +ai4: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv echo +ai5: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv echo +ai6: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv echo + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv tftp +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv tftp +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv tftp +ai3: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv tftp +ai4: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv tftp + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv 80 +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv http +ai4: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai5: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai6: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x3 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv http +ai1: flags 0x3 family 28 socktype 2 protocol 17 addrlen 28 host :: serv http +ai2: flags 0x3 family 28 socktype 1 protocol 6 addrlen 28 host :: serv http +ai3: flags 0x3 family 28 socktype 5 protocol 132 addrlen 28 host :: serv http +ai4: flags 0x3 family 2 socktype 2 protocol 17 addrlen 16 host 0.0.0.0 serv http +ai5: flags 0x3 family 2 socktype 1 protocol 6 addrlen 16 host 0.0.0.0 serv http +ai6: flags 0x3 family 2 socktype 5 protocol 132 addrlen 16 host 0.0.0.0 serv http + +arg: flags 0x3 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv echo +ai1: flags 0x3 family 28 socktype 2 protocol 17 addrlen 28 host :: serv echo +ai2: flags 0x3 family 28 socktype 1 protocol 6 addrlen 28 host :: serv echo +ai3: flags 0x3 family 28 socktype 5 protocol 132 addrlen 28 host :: serv echo +ai4: flags 0x3 family 2 socktype 2 protocol 17 addrlen 16 host 0.0.0.0 serv echo +ai5: flags 0x3 family 2 socktype 1 protocol 6 addrlen 16 host 0.0.0.0 serv echo +ai6: flags 0x3 family 2 socktype 5 protocol 132 addrlen 16 host 0.0.0.0 serv echo + +arg: flags 0x3 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv tftp +ai1: flags 0x3 family 28 socktype 2 protocol 17 addrlen 28 host :: serv tftp +ai2: flags 0x3 family 28 socktype 1 protocol 6 addrlen 28 host :: serv tftp +ai3: flags 0x3 family 2 socktype 2 protocol 17 addrlen 16 host 0.0.0.0 serv tftp +ai4: flags 0x3 family 2 socktype 1 protocol 6 addrlen 16 host 0.0.0.0 serv tftp + +arg: flags 0x3 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv 80 +ai1: flags 0x3 family 28 socktype 2 protocol 17 addrlen 28 host :: serv http +ai2: flags 0x3 family 28 socktype 1 protocol 6 addrlen 28 host :: serv http +ai3: flags 0x3 family 28 socktype 5 protocol 132 addrlen 28 host :: serv http +ai4: flags 0x3 family 2 socktype 2 protocol 17 addrlen 16 host 0.0.0.0 serv http +ai5: flags 0x3 family 2 socktype 1 protocol 6 addrlen 16 host 0.0.0.0 serv http +ai6: flags 0x3 family 2 socktype 5 protocol 132 addrlen 16 host 0.0.0.0 serv http + +arg: flags 0x2 family 0 socktype 1 protocol 0 addrlen 0 host (empty) serv 80 +ai1: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 0 socktype 2 protocol 0 addrlen 0 host (empty) serv 80 +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http + diff --git a/lib/libc/tests/net/getaddrinfo/data/no_host_v4v6_prefer_v4.exp b/lib/libc/tests/net/getaddrinfo/data/no_host_v4v6_prefer_v4.exp new file mode 100644 index 000000000000..596799305117 --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/no_host_v4v6_prefer_v4.exp @@ -0,0 +1,68 @@ +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv http +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv http +ai4: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai5: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai6: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv echo +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv echo +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv echo +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv echo +ai4: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv echo +ai5: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv echo +ai6: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv echo + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv tftp +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv tftp +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv tftp +ai3: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv tftp +ai4: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv tftp + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv 80 +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv http +ai4: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai5: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai6: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x3 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv http +ai1: flags 0x3 family 28 socktype 2 protocol 17 addrlen 28 host :: serv http +ai2: flags 0x3 family 28 socktype 1 protocol 6 addrlen 28 host :: serv http +ai3: flags 0x3 family 28 socktype 5 protocol 132 addrlen 28 host :: serv http +ai4: flags 0x3 family 2 socktype 2 protocol 17 addrlen 16 host 0.0.0.0 serv http +ai5: flags 0x3 family 2 socktype 1 protocol 6 addrlen 16 host 0.0.0.0 serv http +ai6: flags 0x3 family 2 socktype 5 protocol 132 addrlen 16 host 0.0.0.0 serv http + +arg: flags 0x3 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv echo +ai1: flags 0x3 family 28 socktype 2 protocol 17 addrlen 28 host :: serv echo +ai2: flags 0x3 family 28 socktype 1 protocol 6 addrlen 28 host :: serv echo +ai3: flags 0x3 family 28 socktype 5 protocol 132 addrlen 28 host :: serv echo +ai4: flags 0x3 family 2 socktype 2 protocol 17 addrlen 16 host 0.0.0.0 serv echo +ai5: flags 0x3 family 2 socktype 1 protocol 6 addrlen 16 host 0.0.0.0 serv echo +ai6: flags 0x3 family 2 socktype 5 protocol 132 addrlen 16 host 0.0.0.0 serv echo + +arg: flags 0x3 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv tftp +ai1: flags 0x3 family 28 socktype 2 protocol 17 addrlen 28 host :: serv tftp +ai2: flags 0x3 family 28 socktype 1 protocol 6 addrlen 28 host :: serv tftp +ai3: flags 0x3 family 2 socktype 2 protocol 17 addrlen 16 host 0.0.0.0 serv tftp +ai4: flags 0x3 family 2 socktype 1 protocol 6 addrlen 16 host 0.0.0.0 serv tftp + +arg: flags 0x3 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv 80 +ai1: flags 0x3 family 28 socktype 2 protocol 17 addrlen 28 host :: serv http +ai2: flags 0x3 family 28 socktype 1 protocol 6 addrlen 28 host :: serv http +ai3: flags 0x3 family 28 socktype 5 protocol 132 addrlen 28 host :: serv http +ai4: flags 0x3 family 2 socktype 2 protocol 17 addrlen 16 host 0.0.0.0 serv http +ai5: flags 0x3 family 2 socktype 1 protocol 6 addrlen 16 host 0.0.0.0 serv http +ai6: flags 0x3 family 2 socktype 5 protocol 132 addrlen 16 host 0.0.0.0 serv http + +arg: flags 0x2 family 0 socktype 1 protocol 0 addrlen 0 host (empty) serv 80 +ai1: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 0 socktype 2 protocol 0 addrlen 0 host (empty) serv 80 +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http + diff --git a/lib/libc/tests/net/getaddrinfo/data/no_serv_v4.exp b/lib/libc/tests/net/getaddrinfo/data/no_serv_v4.exp new file mode 100644 index 000000000000..667234d2161f --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/no_serv_v4.exp @@ -0,0 +1,17 @@ +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host ::1 serv (empty) +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv 0 +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv 0 +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv 0 + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host 127.0.0.1 serv (empty) +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv 0 +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv 0 +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv 0 + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host localhost serv (empty) +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv 0 +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv 0 +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv 0 + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv (empty) +Name does not resolve diff --git a/lib/libc/tests/net/getaddrinfo/data/no_serv_v4_only.exp b/lib/libc/tests/net/getaddrinfo/data/no_serv_v4_only.exp new file mode 100644 index 000000000000..0d28490c8d81 --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/no_serv_v4_only.exp @@ -0,0 +1,20 @@ +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host ::1 serv (empty) +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv 0 +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv 0 +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv 0 + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host 127.0.0.1 serv (empty) +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv 0 +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv 0 +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv 0 + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host localhost serv (empty) +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv 0 +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv 0 +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv 0 +ai4: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv 0 +ai5: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv 0 +ai6: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv 0 + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv (empty) +Name does not resolve diff --git a/lib/libc/tests/net/getaddrinfo/data/no_serv_v4v6.exp b/lib/libc/tests/net/getaddrinfo/data/no_serv_v4v6.exp new file mode 100644 index 000000000000..53502547c40e --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/no_serv_v4v6.exp @@ -0,0 +1,20 @@ +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host ::1 serv (empty) +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv 0 +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv 0 +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv 0 + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host 127.0.0.1 serv (empty) +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv 0 +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv 0 +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv 0 + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host localhost serv (empty) +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv 0 +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv 0 +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv 0 +ai4: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv 0 +ai5: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv 0 +ai6: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv 0 + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv (empty) +Name does not resolve diff --git a/lib/libc/tests/net/getaddrinfo/data/no_serv_v4v6_prefer_v4.exp b/lib/libc/tests/net/getaddrinfo/data/no_serv_v4v6_prefer_v4.exp new file mode 100644 index 000000000000..0d28490c8d81 --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/no_serv_v4v6_prefer_v4.exp @@ -0,0 +1,20 @@ +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host ::1 serv (empty) +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv 0 +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv 0 +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv 0 + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host 127.0.0.1 serv (empty) +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv 0 +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv 0 +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv 0 + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host localhost serv (empty) +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv 0 +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv 0 +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv 0 +ai4: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv 0 +ai5: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv 0 +ai6: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv 0 + +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host (empty) serv (empty) +Name does not resolve diff --git a/lib/libc/tests/net/getaddrinfo/data/scoped.exp b/lib/libc/tests/net/getaddrinfo/data/scoped.exp new file mode 100644 index 000000000000..f5ddb4bf6feb --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/scoped.exp @@ -0,0 +1,5 @@ +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host fe80::1%lo0 serv http +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host fe80::1%lo0 serv http +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host fe80::1%lo0 serv http +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host fe80::1%lo0 serv http + diff --git a/lib/libc/tests/net/getaddrinfo/data/scoped_v4_only.exp b/lib/libc/tests/net/getaddrinfo/data/scoped_v4_only.exp new file mode 100644 index 000000000000..f5ddb4bf6feb --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/scoped_v4_only.exp @@ -0,0 +1,5 @@ +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host fe80::1%lo0 serv http +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host fe80::1%lo0 serv http +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host fe80::1%lo0 serv http +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host fe80::1%lo0 serv http + diff --git a/lib/libc/tests/net/getaddrinfo/data/scoped_v4v6_prefer_v4.exp b/lib/libc/tests/net/getaddrinfo/data/scoped_v4v6_prefer_v4.exp new file mode 100644 index 000000000000..f5ddb4bf6feb --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/scoped_v4v6_prefer_v4.exp @@ -0,0 +1,5 @@ +arg: flags 0x2 family 0 socktype 0 protocol 0 addrlen 0 host fe80::1%lo0 serv http +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host fe80::1%lo0 serv http +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host fe80::1%lo0 serv http +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host fe80::1%lo0 serv http + diff --git a/lib/libc/tests/net/getaddrinfo/data/sock_raw_v4.exp b/lib/libc/tests/net/getaddrinfo/data/sock_raw_v4.exp new file mode 100644 index 000000000000..021038b81dcc --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/sock_raw_v4.exp @@ -0,0 +1,13 @@ +arg: flags 0x2 family 0 socktype 3 protocol 0 addrlen 0 host localhost serv (empty) +ai1: flags 0x2 family 2 socktype 3 protocol 0 addrlen 16 host 127.0.0.1 serv 0 + +arg: flags 0x2 family 0 socktype 3 protocol 59 addrlen 0 host localhost serv (empty) +ai1: flags 0x2 family 2 socktype 3 protocol 59 addrlen 16 host 127.0.0.1 serv 0 + +arg: flags 0x2 family 0 socktype 3 protocol 59 addrlen 0 host localhost serv 80 +Service was not recognized for socket type +arg: flags 0x2 family 0 socktype 3 protocol 59 addrlen 0 host localhost serv www +Service was not recognized for socket type +arg: flags 0x2 family 0 socktype 3 protocol 59 addrlen 0 host ::1 serv (empty) +ai1: flags 0x2 family 28 socktype 3 protocol 59 addrlen 28 host ::1 serv 0 + diff --git a/lib/libc/tests/net/getaddrinfo/data/sock_raw_v4_only.exp b/lib/libc/tests/net/getaddrinfo/data/sock_raw_v4_only.exp new file mode 100644 index 000000000000..932c1faab0d3 --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/sock_raw_v4_only.exp @@ -0,0 +1,15 @@ +arg: flags 0x2 family 0 socktype 3 protocol 0 addrlen 0 host localhost serv (empty) +ai1: flags 0x2 family 2 socktype 3 protocol 0 addrlen 16 host 127.0.0.1 serv 0 +ai2: flags 0x2 family 28 socktype 3 protocol 0 addrlen 28 host ::1 serv 0 + +arg: flags 0x2 family 0 socktype 3 protocol 59 addrlen 0 host localhost serv (empty) +ai1: flags 0x2 family 2 socktype 3 protocol 59 addrlen 16 host 127.0.0.1 serv 0 +ai2: flags 0x2 family 28 socktype 3 protocol 59 addrlen 28 host ::1 serv 0 + +arg: flags 0x2 family 0 socktype 3 protocol 59 addrlen 0 host localhost serv 80 +Service was not recognized for socket type +arg: flags 0x2 family 0 socktype 3 protocol 59 addrlen 0 host localhost serv www +Service was not recognized for socket type +arg: flags 0x2 family 0 socktype 3 protocol 59 addrlen 0 host ::1 serv (empty) +ai1: flags 0x2 family 28 socktype 3 protocol 59 addrlen 28 host ::1 serv 0 + diff --git a/lib/libc/tests/net/getaddrinfo/data/sock_raw_v4v6.exp b/lib/libc/tests/net/getaddrinfo/data/sock_raw_v4v6.exp new file mode 100644 index 000000000000..e494271a3d35 --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/sock_raw_v4v6.exp @@ -0,0 +1,15 @@ +arg: flags 0x2 family 0 socktype 3 protocol 0 addrlen 0 host localhost serv (empty) +ai1: flags 0x2 family 28 socktype 3 protocol 0 addrlen 28 host ::1 serv 0 +ai2: flags 0x2 family 2 socktype 3 protocol 0 addrlen 16 host 127.0.0.1 serv 0 + +arg: flags 0x2 family 0 socktype 3 protocol 59 addrlen 0 host localhost serv (empty) +ai1: flags 0x2 family 28 socktype 3 protocol 59 addrlen 28 host ::1 serv 0 +ai2: flags 0x2 family 2 socktype 3 protocol 59 addrlen 16 host 127.0.0.1 serv 0 + +arg: flags 0x2 family 0 socktype 3 protocol 59 addrlen 0 host localhost serv 80 +Service was not recognized for socket type +arg: flags 0x2 family 0 socktype 3 protocol 59 addrlen 0 host localhost serv www +Service was not recognized for socket type +arg: flags 0x2 family 0 socktype 3 protocol 59 addrlen 0 host ::1 serv (empty) +ai1: flags 0x2 family 28 socktype 3 protocol 59 addrlen 28 host ::1 serv 0 + diff --git a/lib/libc/tests/net/getaddrinfo/data/sock_raw_v4v6_prefer_v4.exp b/lib/libc/tests/net/getaddrinfo/data/sock_raw_v4v6_prefer_v4.exp new file mode 100644 index 000000000000..932c1faab0d3 --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/sock_raw_v4v6_prefer_v4.exp @@ -0,0 +1,15 @@ +arg: flags 0x2 family 0 socktype 3 protocol 0 addrlen 0 host localhost serv (empty) +ai1: flags 0x2 family 2 socktype 3 protocol 0 addrlen 16 host 127.0.0.1 serv 0 +ai2: flags 0x2 family 28 socktype 3 protocol 0 addrlen 28 host ::1 serv 0 + +arg: flags 0x2 family 0 socktype 3 protocol 59 addrlen 0 host localhost serv (empty) +ai1: flags 0x2 family 2 socktype 3 protocol 59 addrlen 16 host 127.0.0.1 serv 0 +ai2: flags 0x2 family 28 socktype 3 protocol 59 addrlen 28 host ::1 serv 0 + +arg: flags 0x2 family 0 socktype 3 protocol 59 addrlen 0 host localhost serv 80 +Service was not recognized for socket type +arg: flags 0x2 family 0 socktype 3 protocol 59 addrlen 0 host localhost serv www +Service was not recognized for socket type +arg: flags 0x2 family 0 socktype 3 protocol 59 addrlen 0 host ::1 serv (empty) +ai1: flags 0x2 family 28 socktype 3 protocol 59 addrlen 28 host ::1 serv 0 + diff --git a/lib/libc/tests/net/getaddrinfo/data/spec_fam_v4.exp b/lib/libc/tests/net/getaddrinfo/data/spec_fam_v4.exp new file mode 100644 index 000000000000..924d2a16f47c --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/spec_fam_v4.exp @@ -0,0 +1,7 @@ +arg: flags 0x2 family 2 socktype 0 protocol 0 addrlen 0 host localhost serv http +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 28 socktype 0 protocol 0 addrlen 0 host localhost serv http +Address family for hostname not supported diff --git a/lib/libc/tests/net/getaddrinfo/data/spec_fam_v4_only.exp b/lib/libc/tests/net/getaddrinfo/data/spec_fam_v4_only.exp new file mode 100644 index 000000000000..af3506938503 --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/spec_fam_v4_only.exp @@ -0,0 +1,10 @@ +arg: flags 0x2 family 2 socktype 0 protocol 0 addrlen 0 host localhost serv http +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 28 socktype 0 protocol 0 addrlen 0 host localhost serv http +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv http + diff --git a/lib/libc/tests/net/getaddrinfo/data/spec_fam_v4v6.exp b/lib/libc/tests/net/getaddrinfo/data/spec_fam_v4v6.exp new file mode 100644 index 000000000000..af3506938503 --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/spec_fam_v4v6.exp @@ -0,0 +1,10 @@ +arg: flags 0x2 family 2 socktype 0 protocol 0 addrlen 0 host localhost serv http +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 28 socktype 0 protocol 0 addrlen 0 host localhost serv http +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv http + diff --git a/lib/libc/tests/net/getaddrinfo/data/spec_fam_v4v6_prefer_v4.exp b/lib/libc/tests/net/getaddrinfo/data/spec_fam_v4v6_prefer_v4.exp new file mode 100644 index 000000000000..af3506938503 --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/spec_fam_v4v6_prefer_v4.exp @@ -0,0 +1,10 @@ +arg: flags 0x2 family 2 socktype 0 protocol 0 addrlen 0 host localhost serv http +ai1: flags 0x2 family 2 socktype 2 protocol 17 addrlen 16 host 127.0.0.1 serv http +ai2: flags 0x2 family 2 socktype 1 protocol 6 addrlen 16 host 127.0.0.1 serv http +ai3: flags 0x2 family 2 socktype 5 protocol 132 addrlen 16 host 127.0.0.1 serv http + +arg: flags 0x2 family 28 socktype 0 protocol 0 addrlen 0 host localhost serv http +ai1: flags 0x2 family 28 socktype 2 protocol 17 addrlen 28 host ::1 serv http +ai2: flags 0x2 family 28 socktype 1 protocol 6 addrlen 28 host ::1 serv http +ai3: flags 0x2 family 28 socktype 5 protocol 132 addrlen 28 host ::1 serv http + diff --git a/lib/libc/tests/net/getaddrinfo/data/unsup_fam.exp b/lib/libc/tests/net/getaddrinfo/data/unsup_fam.exp new file mode 100644 index 000000000000..69e6b48a854b --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/unsup_fam.exp @@ -0,0 +1,2 @@ +arg: flags 0x2 family 99 socktype 0 protocol 0 addrlen 0 host localhost serv (empty) +Address family not recognized diff --git a/lib/libc/tests/net/getaddrinfo/data/unsup_fam_v4_only.exp b/lib/libc/tests/net/getaddrinfo/data/unsup_fam_v4_only.exp new file mode 100644 index 000000000000..69e6b48a854b --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/unsup_fam_v4_only.exp @@ -0,0 +1,2 @@ +arg: flags 0x2 family 99 socktype 0 protocol 0 addrlen 0 host localhost serv (empty) +Address family not recognized diff --git a/lib/libc/tests/net/getaddrinfo/data/unsup_fam_v4v6_prefer_v4.exp b/lib/libc/tests/net/getaddrinfo/data/unsup_fam_v4v6_prefer_v4.exp new file mode 100644 index 000000000000..69e6b48a854b --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/data/unsup_fam_v4v6_prefer_v4.exp @@ -0,0 +1,2 @@ +arg: flags 0x2 family 99 socktype 0 protocol 0 addrlen 0 host localhost serv (empty) +Address family not recognized diff --git a/lib/libc/tests/net/getaddrinfo/getaddrinfo.c b/lib/libc/tests/net/getaddrinfo/getaddrinfo.c new file mode 100644 index 000000000000..1e066add3119 --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/getaddrinfo.c @@ -0,0 +1,271 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Gleb Smirnoff <glebius@FreeBSD.org> + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <dlfcn.h> +#include <errno.h> +#include <netdb.h> +#include <stdlib.h> +#include <string.h> +#include <resolv.h> + +#include <atf-c.h> + +static const char goodname[] = "www.freebsd.org"; +static const char goodname_dot[] = "www.freebsd.org."; +static const char badname[] = "does-not-exist.freebsd.org"; +static const char badname_dot[] = "does-not-exist.freebsd.org."; +static const char ipv6onlyname[] = "beefy15.nyi.freebsd.org"; +static const char ipv6onlyname_dot[] = "beefy15.nyi.freebsd.org."; +static const char ipv4onlyname[] = "ipv4only.arpa"; +static const char ipv4onlyname_dot[] = "ipv4only.arpa."; +/* + * We need an IP address that doesn't exist, but not reported with ICMP + * unreachable by the nearest router. Let's try TEST-NET-3. + */ +static char badresolvconf[] = "nameserver 203.0.113.1"; +static char badresolvconf2[] = "nameserver 203.0.113.1\n" + "nameserver 203.0.113.2"; +static char *resconf = NULL; +FILE * +fopen(const char * restrict path, const char * restrict mode) +{ + static FILE *(*orig)(const char *, const char *); + + if (orig == NULL && (orig = dlsym(RTLD_NEXT, "fopen")) == NULL) + atf_libc_error(ENOENT, "dlsym(fopen): %s", dlerror()); + if (resconf != NULL && strcmp(path, _PATH_RESCONF) == 0) + return (fmemopen(resconf, strlen(resconf), mode)); + else + return (orig(path, mode)); +} + +static int send_error = 0; +ssize_t +send(int s, const void *msg, size_t len, int flags) +{ + static ssize_t (*orig)(int, const void *, size_t, int); + + if (orig == NULL && (orig = dlsym(RTLD_NEXT, "send")) == NULL) + atf_libc_error(ENOENT, "dlsym(send): %s", dlerror()); + if (send_error != 0) { + errno = send_error; + return (-1); + } else { + return (orig(s, msg, len, flags)); + } +} + +ATF_TC(basic); +ATF_TC_HEAD(basic, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} + +ATF_TC_BODY(basic, tc) +{ + static const struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_flags = AI_CANONNAME, + }; + struct addrinfo *res; + int rv; + + rv = getaddrinfo(goodname, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == 0, + "Expected 0, got %d (%s)", rv, gai_strerror(rv)); + freeaddrinfo(res); + + rv = getaddrinfo(goodname_dot, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == 0, + "Expected 0, got %d (%s)", rv, gai_strerror(rv)); + freeaddrinfo(res); + + rv = getaddrinfo(badname, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_NONAME, + "Expected %d (EAI_NONAME), got %d (%s)", + EAI_NONAME, rv, gai_strerror(rv)); + + rv = getaddrinfo(badname_dot, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_NONAME, + "Expected %d (EAI_NONAME), got %d (%s)", + EAI_NONAME, rv, gai_strerror(rv)); +} + +ATF_TC_WITHOUT_HEAD(timeout); +ATF_TC_BODY(timeout, tc) +{ + static const struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_flags = AI_CANONNAME, + }; + struct addrinfo *res; + int rv; + + resconf = badresolvconf; + rv = getaddrinfo(goodname, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_AGAIN, + "Expected %d (EAI_AGAIN), got %d (%s)", + EAI_AGAIN, rv, gai_strerror(rv)); + + rv = getaddrinfo(goodname_dot, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_AGAIN, + "Expected %d (EAI_AGAIN), got %d (%s)", + EAI_AGAIN, rv, gai_strerror(rv)); +} + +ATF_TC_WITHOUT_HEAD(timeout_specific); +ATF_TC_BODY(timeout_specific, tc) +{ + static const struct addrinfo hints = { + .ai_family = AF_INET, + .ai_socktype = SOCK_STREAM, + .ai_flags = AI_CANONNAME, + }; + struct addrinfo *res; + int rv; + + resconf = badresolvconf; + rv = getaddrinfo(goodname, "666", &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_AGAIN, + "Expected %d (EAI_AGAIN), got %d (%s)", + EAI_AGAIN, rv, gai_strerror(rv)); + + rv = getaddrinfo(goodname_dot, "666", &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_AGAIN, + "Expected %d (EAI_AGAIN), got %d (%s)", + EAI_AGAIN, rv, gai_strerror(rv)); +} + +ATF_TC_WITHOUT_HEAD(timeout2); +ATF_TC_BODY(timeout2, tc) +{ + static const struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_flags = AI_CANONNAME, + }; + struct addrinfo *res; + int rv; + + resconf = badresolvconf2; + rv = getaddrinfo(goodname, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_AGAIN, + "Expected %d (EAI_AGAIN), got %d (%s)", + EAI_AGAIN, rv, gai_strerror(rv)); + + rv = getaddrinfo(goodname_dot, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_AGAIN, + "Expected %d (EAI_AGAIN), got %d (%s)", + EAI_AGAIN, rv, gai_strerror(rv)); +} + +/* + * Emulate interface/network down. + */ +ATF_TC_WITHOUT_HEAD(netdown); +ATF_TC_BODY(netdown, tc) +{ + static const struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_flags = AI_CANONNAME, + }; + struct addrinfo *res; + int rv; + + send_error = ENETDOWN; + rv = getaddrinfo(goodname, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_AGAIN, + "Expected %d (EAI_AGAIN), got %d (%s)", + EAI_AGAIN, rv, gai_strerror(rv)); + + rv = getaddrinfo(goodname_dot, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_AGAIN, + "Expected %d (EAI_AGAIN), got %d (%s)", + EAI_AGAIN, rv, gai_strerror(rv)); +} + +/* + * See https://reviews.freebsd.org/D37139. + */ +ATF_TC(nofamily); +ATF_TC_HEAD(nofamily, tc) +{ + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); +} +ATF_TC_BODY(nofamily, tc) +{ + static const struct addrinfo hints4 = { + .ai_family = AF_INET, + .ai_flags = AI_CANONNAME, + }, hints6 = { + .ai_family = AF_INET6, + .ai_flags = AI_CANONNAME, + }; + struct addrinfo *res; + int rv; + + rv = getaddrinfo(ipv6onlyname, NULL, &hints4, &res); + ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY, + "Expected %d (EAI_ADDRFAMILY), got %d (%s)", + EAI_ADDRFAMILY, rv, gai_strerror(rv)); + + rv = getaddrinfo(ipv6onlyname_dot, NULL, &hints4, &res); + ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY, + "Expected %d (EAI_ADDRFAMILY), got %d (%s)", + EAI_ADDRFAMILY, rv, gai_strerror(rv)); + + rv = getaddrinfo(ipv4onlyname, NULL, &hints6, &res); + ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY, + "Expected %d (EAI_ADDRFAMILY), got %d (%s)", + EAI_ADDRFAMILY, rv, gai_strerror(rv)); + + rv = getaddrinfo(ipv4onlyname_dot, NULL, &hints6, &res); + ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY, + "Expected %d (EAI_ADDRFAMILY), got %d (%s)", + EAI_ADDRFAMILY, rv, gai_strerror(rv)); + + rv = getaddrinfo(badname, NULL, &hints4, &res); + ATF_REQUIRE_MSG(rv == EAI_NONAME, + "Expected %d (EAI_NONAME), got %d (%s)", + EAI_NONAME, rv, gai_strerror(rv)); + + rv = getaddrinfo(badname_dot, NULL, &hints6, &res); + ATF_REQUIRE_MSG(rv == EAI_NONAME, + "Expected %d (EAI_NONAME), got %d (%s)", + EAI_NONAME, rv, gai_strerror(rv)); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, basic); + ATF_TP_ADD_TC(tp, timeout); + ATF_TP_ADD_TC(tp, timeout_specific); + ATF_TP_ADD_TC(tp, timeout2); + ATF_TP_ADD_TC(tp, netdown); + ATF_TP_ADD_TC(tp, nofamily); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/net/getaddrinfo/getaddrinfo_test.sh b/lib/libc/tests/net/getaddrinfo/getaddrinfo_test.sh new file mode 100755 index 000000000000..dd17ab2e3f4a --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/getaddrinfo_test.sh @@ -0,0 +1,443 @@ +# $NetBSD: t_getaddrinfo.sh,v 1.2 2011/06/15 07:54:32 jmmv Exp $ + +# +# Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, and 2002 WIDE Project. +# 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. +# 3. Neither the name of the project nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``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 PROJECT OR CONTRIBUTORS 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. +# + +if [ "$(sysctl -i -n kern.features.vimage)" != 1 ]; then + atf_skip "This test requires VIMAGE" +fi + +vnet_mkjail() +{ + jailname=getaddrinfo_test_$1 + jail -c name=${jailname} persist vnet + ifconfig -j ${jailname} lo0 inet 127.0.0.1/8 + # For those machines not support IPv6 + ifconfig -j ${jailname} lo0 inet6 ::1/64 || true + service -j ${jailname} ip6addrctl $2 || true +} + +vnet_cleanup() +{ + jailname=getaddrinfo_test_$1 + jail -r ${jailname} +} + +check_output() +{ + if [ "$2" = "none" ]; then + if [ "$3" = "prefer_v6" ]; then + exp="${1}.exp" + else + exp="${1}_v4_only.exp" + fi + elif [ "$2" = "hosts" ]; then + lcl=$(cat /etc/hosts | sed -e 's/#.*$//' -e 's/[ ][ ]*/ /g' | awk '/ localhost($| )/ {printf "%s ", $1}') + if [ "${lcl%*::*}" = "${lcl}" ]; then + exp="${1}_v4_only.exp" + else + if [ "$3" = "prefer_v6" ]; then + exp="${1}_v4v6.exp" + else + exp="${1}_v4v6_prefer_v4.exp" + fi + fi + elif [ "$2" = "ifconfig" ]; then + lcl=$(ifconfig lo0 | grep inet6) + if [ -n "${lcl}" ]; then + if [ "$3" = "prefer_v6" ]; then + exp="${1}_v4v6.exp" + else + exp="${1}_v4v6_prefer_v4.exp" + fi + else + exp="${1}_v4_only.exp" + fi + else + atf_fail "Invalid family_match_type $2 requested." + fi + + cmp -s "$(atf_get_srcdir)/data/${exp}" out && return + diff -u "$(atf_get_srcdir)/data/${exp}" out || atf_fail "Actual output does not match expected output" +} + +atf_test_case basic_prefer_v4 cleanup +basic_prefer_v4_head() +{ + atf_set "descr" "Testing basic ones with prefer_v4" + atf_set "require.user" "root" +} +basic_prefer_v4_body() +{ + vnet_mkjail basic_prefer_v4 prefer_ipv4 + TEST="jexec getaddrinfo_test_basic_prefer_v4 $(atf_get_srcdir)/h_gai" + + ( $TEST ::1 http + $TEST 127.0.0.1 http + $TEST localhost http + $TEST ::1 tftp + $TEST 127.0.0.1 tftp + $TEST localhost tftp + $TEST ::1 echo + $TEST 127.0.0.1 echo + $TEST localhost echo ) > out 2>&1 + + check_output basics hosts prefer_v4 +} +basic_prefer_v4_cleanup() +{ + vnet_cleanup basic_prefer_v4 +} + +atf_test_case basic cleanup +basic_head() +{ + atf_set "descr" "Testing basic ones with prefer_v6" + atf_set "require.user" "root" +} +basic_body() +{ + vnet_mkjail basic prefer_ipv6 + TEST="jexec getaddrinfo_test_basic $(atf_get_srcdir)/h_gai" + + ( $TEST ::1 http + $TEST 127.0.0.1 http + $TEST localhost http + $TEST ::1 tftp + $TEST 127.0.0.1 tftp + $TEST localhost tftp + $TEST ::1 echo + $TEST 127.0.0.1 echo + $TEST localhost echo ) > out 2>&1 + + check_output basics ifconfig prefer_v6 +} +basic_cleanup() +{ + vnet_cleanup basic +} + +atf_test_case specific_prefer_v4 cleanup +specific_prefer_v4_head() +{ + atf_set "descr" "Testing specific address family with prefer_v4" + atf_set "require.user" "root" +} +specific_prefer_v4_body() +{ + vnet_mkjail specific_prefer_v4 prefer_ipv4 + TEST="jexec getaddrinfo_test_specific_prefer_v4 $(atf_get_srcdir)/h_gai" + + ( $TEST -4 localhost http + $TEST -6 localhost http ) > out 2>&1 + + check_output spec_fam hosts prefer_v4 +} +specific_prefer_v4_cleanup() +{ + vnet_cleanup specific_prefer_v4 +} + +atf_test_case specific cleanup +specific_head() +{ + atf_set "descr" "Testing specific address family with prefer_v6" + atf_set "require.user" "root" +} +specific_body() +{ + vnet_mkjail specific prefer_ipv6 + TEST="jexec getaddrinfo_test_specific $(atf_get_srcdir)/h_gai" + + ( $TEST -4 localhost http + $TEST -6 localhost http ) > out 2>&1 + + check_output spec_fam hosts prefer_v6 +} +specific_cleanup() +{ + vnet_cleanup specific +} + +atf_test_case empty_hostname_prefer_v4 cleanup +empty_hostname_prefer_v4_head() +{ + atf_set "descr" "Testing empty hostname with prefer_v4" + atf_set "require.user" "root" +} +empty_hostname_prefer_v4_body() +{ + vnet_mkjail empty_hostname_prefer_v4 prefer_ipv4 + TEST="jexec getaddrinfo_test_empty_hostname_prefer_v4 $(atf_get_srcdir)/h_gai" + + ( $TEST '' http + $TEST '' echo + $TEST '' tftp + $TEST '' 80 + $TEST -P '' http + $TEST -P '' echo + $TEST -P '' tftp + $TEST -P '' 80 + $TEST -S '' 80 + $TEST -D '' 80 ) > out 2>&1 + + check_output no_host ifconfig prefer_v4 +} +empty_hostname_prefer_v4_cleanup() +{ + vnet_cleanup empty_hostname_prefer_v4 +} + +atf_test_case empty_hostname cleanup +empty_hostname_head() +{ + atf_set "descr" "Testing empty hostname with prefer_v6" + atf_set "require.user" "root" +} +empty_hostname_body() +{ + vnet_mkjail empty_hostname prefer_ipv6 + TEST="jexec getaddrinfo_test_empty_hostname $(atf_get_srcdir)/h_gai" + + ( $TEST '' http + $TEST '' echo + $TEST '' tftp + $TEST '' 80 + $TEST -P '' http + $TEST -P '' echo + $TEST -P '' tftp + $TEST -P '' 80 + $TEST -S '' 80 + $TEST -D '' 80 ) > out 2>&1 + + check_output no_host ifconfig prefer_v6 +} +empty_hostname_cleanup() +{ + vnet_cleanup empty_hostname +} + +atf_test_case empty_servname_prefer_v4 cleanup +empty_servname_prefer_v4_head() +{ + atf_set "descr" "Testing empty service name with prefer_v4" + atf_set "require.user" "root" +} +empty_servname_prefer_v4_body() +{ + vnet_mkjail empty_servname_prefer_v4 prefer_ipv4 + TEST="jexec getaddrinfo_test_empty_servname_prefer_v4 $(atf_get_srcdir)/h_gai" + + ( $TEST ::1 '' + $TEST 127.0.0.1 '' + $TEST localhost '' + $TEST '' '' ) > out 2>&1 + + check_output no_serv hosts prefer_v4 +} +empty_servname_prefer_v4_cleanup() +{ + vnet_cleanup empty_servname_prefer_v4 +} + +atf_test_case empty_servname cleanup +empty_servname_head() +{ + atf_set "descr" "Testing empty service name with prefer_v6" + atf_set "require.user" "root" +} +empty_servname_body() +{ + vnet_mkjail empty_servname prefer_ipv6 + TEST="jexec getaddrinfo_test_empty_servname $(atf_get_srcdir)/h_gai" + + ( $TEST ::1 '' + $TEST 127.0.0.1 '' + $TEST localhost '' + $TEST '' '' ) > out 2>&1 + + check_output no_serv ifconfig prefer_v6 +} +empty_servname_cleanup() +{ + vnet_cleanup empty_servname +} + +atf_test_case sock_raw_prefer_v4 cleanup +sock_raw_prefer_v4_head() +{ + atf_set "descr" "Testing raw socket with prefer_v4" + atf_set "require.user" "root" +} +sock_raw_prefer_v4_body() +{ + vnet_mkjail sock_raw_prefer_v4 prefer_ipv4 + TEST="jexec getaddrinfo_test_sock_raw_prefer_v4 $(atf_get_srcdir)/h_gai" + + ( $TEST -R -p 0 localhost '' + $TEST -R -p 59 localhost '' + $TEST -R -p 59 localhost 80 + $TEST -R -p 59 localhost www + $TEST -R -p 59 ::1 '' ) > out 2>&1 + + check_output sock_raw hosts prefer_v4 +} +sock_raw_prefer_v4_cleanup() +{ + vnet_cleanup sock_raw_prefer_v4 +} + +atf_test_case sock_raw cleanup +sock_raw_head() +{ + atf_set "descr" "Testing raw socket with prefer_v6" + atf_set "require.user" "root" +} +sock_raw_body() +{ + vnet_mkjail sock_raw prefer_ipv6 + TEST="jexec getaddrinfo_test_sock_raw $(atf_get_srcdir)/h_gai" + + ( $TEST -R -p 0 localhost '' + $TEST -R -p 59 localhost '' + $TEST -R -p 59 localhost 80 + $TEST -R -p 59 localhost www + $TEST -R -p 59 ::1 '' ) > out 2>&1 + + check_output sock_raw ifconfig prefer_v6 +} +sock_raw_cleanup() +{ + vnet_cleanup sock_raw +} + +atf_test_case unsupported_family_prefer_v4 cleanup +unsupported_family_prefer_v4_head() +{ + atf_set "descr" "Testing unsupported family with prefer_v4" + atf_set "require.user" "root" +} +unsupported_family_prefer_v4_body() +{ + vnet_mkjail unsupported_family_prefer_v4 prefer_ipv4 + TEST="jexec getaddrinfo_test_unsupported_family_prefer_v4 $(atf_get_srcdir)/h_gai" + + ( $TEST -f 99 localhost '' ) > out 2>&1 + + check_output unsup_fam ifconfig prefer_v4 +} +unsupported_family_prefer_v4_cleanup() +{ + vnet_cleanup unsupported_family_prefer_v4 +} + +atf_test_case unsupported_family cleanup +unsupported_family_head() +{ + atf_set "descr" "Testing unsupported family with prefer_v6" + atf_set "require.user" "root" +} +unsupported_family_body() +{ + vnet_mkjail unsupported_family prefer_ipv6 + TEST="jexec getaddrinfo_test_unsupported_family $(atf_get_srcdir)/h_gai" + + ( $TEST -f 99 localhost '' ) > out 2>&1 + + check_output unsup_fam none prefer_v6 +} +unsupported_family_cleanup() +{ + vnet_cleanup unsupported_family +} + +atf_test_case scopeaddr_prefer_v4 cleanup +scopeaddr_prefer_v4_head() +{ + atf_set "descr" "Testing scoped address format with prefer_v4" + atf_set "require.user" "root" +} +scopeaddr_prefer_v4_body() +{ + vnet_mkjail scopeaddr_prefer_v4 prefer_ipv4 + TEST="jexec getaddrinfo_test_scopeaddr_prefer_v4 $(atf_get_srcdir)/h_gai" + + ( $TEST fe80::1%lo0 http +# IF=ifconfig -a | grep -v '^ ' | sed -e 's/:.*//' | head -1 | awk '{print $1}' +# $TEST fe80::1%$IF http + ) > out 2>&1 + + check_output scoped ifconfig prefer_v4 +} +scopeaddr_prefer_v4_cleanup() +{ + vnet_cleanup scopeaddr_prefer_v4 +} + +atf_test_case scopeaddr cleanup +scopeaddr_head() +{ + atf_set "descr" "Testing scoped address format with prefer_v6" + atf_set "require.user" "root" +} +scopeaddr_body() +{ + vnet_mkjail scopeaddr prefer_ipv6 + TEST="jexec getaddrinfo_test_scopeaddr $(atf_get_srcdir)/h_gai" + + ( $TEST fe80::1%lo0 http +# IF=ifconfig -a | grep -v '^ ' | sed -e 's/:.*//' | head -1 | awk '{print $1}' +# $TEST fe80::1%$IF http + ) > out 2>&1 + + check_output scoped none prefer_v6 +} +scopeaddr_cleanup() +{ + vnet_cleanup scopeaddr +} + +atf_init_test_cases() +{ + atf_add_test_case basic_prefer_v4 + atf_add_test_case specific_prefer_v4 + atf_add_test_case empty_hostname_prefer_v4 + atf_add_test_case empty_servname_prefer_v4 + atf_add_test_case sock_raw_prefer_v4 + atf_add_test_case unsupported_family_prefer_v4 + atf_add_test_case scopeaddr_prefer_v4 + + atf_add_test_case basic + atf_add_test_case specific + atf_add_test_case empty_hostname + atf_add_test_case empty_servname + atf_add_test_case sock_raw + atf_add_test_case unsupported_family + atf_add_test_case scopeaddr +} diff --git a/lib/libc/tests/net/link_addr_test.cc b/lib/libc/tests/net/link_addr_test.cc new file mode 100644 index 000000000000..b973b924dc13 --- /dev/null +++ b/lib/libc/tests/net/link_addr_test.cc @@ -0,0 +1,532 @@ +/* + * Copyright (c) 2025 Lexi Winter + * + * SPDX-License-Identifier: ISC + */ + +/* + * Tests for link_addr() and link_ntoa(). + * + * link_addr converts a string representing an (optionally null) interface name + * followed by an Ethernet address into a sockaddr_dl. The expected format is + * "[ifname]:lladdr". This means if ifname is not specified, the leading colon + * is still required. + * + * link_ntoa does the inverse of link_addr, returning a string representation + * of the address. + * + * Note that the output format of link_ntoa is not valid input for link_addr + * since the leading colon may be omitted. This is by design. + */ + +#include <sys/types.h> +#include <sys/socket.h> + +#include <net/ethernet.h> +#include <net/if_dl.h> + +#include <format> +#include <iostream> +#include <ranges> +#include <span> +#include <utility> +#include <vector> + +#include <cstddef> +#include <cstdint> + +#include <atf-c++.hpp> + +using namespace std::literals; + +/* + * Define operator== and operator<< for ether_addr so we can use them in + * ATF_EXPECT_EQ expressions. + */ + +bool +operator==(ether_addr a, ether_addr b) +{ + return (std::ranges::equal(a.octet, b.octet)); +} + +std::ostream & +operator<<(std::ostream &s, ether_addr a) +{ + for (unsigned i = 0; i < ETHER_ADDR_LEN; ++i) { + if (i > 0) + s << ":"; + + s << std::format("{:02x}", static_cast<int>(a.octet[i])); + } + + return (s); +} + +/* + * Create a sockaddr_dl from a string using link_addr(), and ensure the + * returned struct looks valid. + */ +sockaddr_dl +make_linkaddr(const std::string &addr) +{ + auto sdl = sockaddr_dl{}; + int ret; + + sdl.sdl_len = sizeof(sdl); + ret = ::link_addr(addr.c_str(), &sdl); + + ATF_REQUIRE_EQ(0, ret); + ATF_REQUIRE_EQ(AF_LINK, static_cast<int>(sdl.sdl_family)); + ATF_REQUIRE_EQ(true, sdl.sdl_len > 0); + ATF_REQUIRE_EQ(true, sdl.sdl_nlen >= 0); + + return (sdl); +} + +/* + * Return the data stored in a sockaddr_dl as a span. + */ +std::span<const char> +data(const sockaddr_dl &sdl) +{ + // sdl_len is the entire structure, but we only want the length of the + // data area. + auto dlen = sdl.sdl_len - offsetof(sockaddr_dl, sdl_data); + return {&sdl.sdl_data[0], dlen}; +} + +/* + * Return the interface name stored in a sockaddr_dl as a string. + */ +std::string_view +ifname(const sockaddr_dl &sdl) +{ + auto name = data(sdl).subspan(0, sdl.sdl_nlen); + return {name.begin(), name.end()}; +} + +/* + * Return the Ethernet address stored in a sockaddr_dl as an ether_addr. + */ +ether_addr +addr(const sockaddr_dl &sdl) +{ + ether_addr ret{}; + ATF_REQUIRE_EQ(ETHER_ADDR_LEN, sdl.sdl_alen); + std::ranges::copy(data(sdl).subspan(sdl.sdl_nlen, ETHER_ADDR_LEN), + &ret.octet[0]); + return (ret); +} + +/* + * Return the link address stored in a sockaddr_dl as a span of octets. + */ +std::span<const std::uint8_t> +lladdr(const sockaddr_dl &sdl) +{ + auto data = reinterpret_cast<const uint8_t *>(LLADDR(&sdl)); + return {data, data + sdl.sdl_alen}; +} + + +/* + * Some sample addresses we use for testing. Include at least one address for + * each format we want to support. + */ + +struct test_address { + std::string input; /* value passed to link_addr */ + std::string ntoa; /* expected return from link_ntoa */ + ether_addr addr{}; /* expected return from link_addr */ +}; + +std::vector<test_address> test_addresses{ + // No delimiter + {"001122334455"s, "0.11.22.33.44.55", + ether_addr{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}}, + + // Colon delimiter + {"00:11:22:33:44:55"s, "0.11.22.33.44.55", + ether_addr{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}}, + + // Dash delimiter + {"00-11-22-33-44-55"s, "0.11.22.33.44.55", + ether_addr{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}}, + + // Period delimiter (link_ntoa format) + {"00.11.22.33.44.55"s, "0.11.22.33.44.55", + ether_addr{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}}, + + // Period delimiter (Cisco format) + {"0011.2233.4455"s, "0.11.22.33.44.55", + ether_addr{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}}, + + // An addresses without leading zeroes. + {"0:1:02:30:4:55"s, "0.1.2.30.4.55", + ether_addr{0x00, 0x01, 0x02, 0x30, 0x04, 0x55}}, + + // An address with some uppercase letters. + {"AA:B:cC:Dd:e0:1f"s, "aa.b.cc.dd.e0.1f", + ether_addr{0xaa, 0x0b, 0xcc, 0xdd, 0xe0, 0x1f}}, + + // Addresses composed only of letters, to make sure they're not + // confused with an interface name. + + {"aabbccddeeff"s, "aa.bb.cc.dd.ee.ff", + ether_addr{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}}, + + {"aa:bb:cc:dd:ee:ff"s, "aa.bb.cc.dd.ee.ff", + ether_addr{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}}, + + // Address with a blank octet; this is an old form of Ethernet address. + {"00:11::33:44:55"s, "0.11.0.33.44.55", + ether_addr{0x00, 0x11, 0x00, 0x33, 0x44, 0x55}}, +}; + +/* + * Test without an interface name. + */ +ATF_TEST_CASE_WITHOUT_HEAD(basic) +ATF_TEST_CASE_BODY(basic) +{ + for (const auto &ta : test_addresses) { + // This does basic tests on the returned value. + auto sdl = make_linkaddr(":" + ta.input); + + // Check the ifname and address. + ATF_REQUIRE_EQ(""s, ifname(sdl)); + ATF_REQUIRE_EQ(ETHER_ADDR_LEN, static_cast<int>(sdl.sdl_alen)); + ATF_REQUIRE_EQ(ta.addr, addr(sdl)); + + // Check link_ntoa returns the expected value. + auto ntoa = std::string(::link_ntoa(&sdl)); + ATF_REQUIRE_EQ(ta.ntoa, ntoa); + } + +} + +/* + * Test with an interface name. + */ +ATF_TEST_CASE_WITHOUT_HEAD(ifname) +ATF_TEST_CASE_BODY(ifname) +{ + for (const auto &ta : test_addresses) { + auto sdl = make_linkaddr("ix0:" + ta.input); + + ATF_REQUIRE_EQ("ix0", ifname(sdl)); + ATF_REQUIRE_EQ(ETHER_ADDR_LEN, static_cast<int>(sdl.sdl_alen)); + ATF_REQUIRE_EQ(ta.addr, addr(sdl)); + + auto ntoa = std::string(::link_ntoa(&sdl)); + ATF_REQUIRE_EQ("ix0:" + ta.ntoa, ntoa); + } + +} + +/* + * Test with some invalid addresses. + */ +ATF_TEST_CASE_WITHOUT_HEAD(invalid) +ATF_TEST_CASE_BODY(invalid) +{ + auto const invalid_addresses = std::vector{ + // Invalid separator + ":1/2/3"s, + "ix0:1/2/3"s, + + // Multiple different separators + ":1.2-3"s, + "ix0:1.2-3"s, + + // An IP address + ":10.1.2.200/28"s, + "ix0:10.1.2.200/28"s, + + // Valid address followed by garbage + ":1.2.3xxx"s, + ":1.2.3.xxx"s, + "ix0:1.2.3xxx"s, + "ix0:1.2.3.xxx"s, + }; + + for (auto const &addr : invalid_addresses) { + int ret; + + auto sdl = sockaddr_dl{}; + sdl.sdl_len = sizeof(sdl); + + ret = link_addr(addr.c_str(), &sdl); + ATF_REQUIRE_EQ(-1, ret); + } +} + +/* + * Test some non-Ethernet addresses. + */ +ATF_TEST_CASE_WITHOUT_HEAD(nonether) +ATF_TEST_CASE_BODY(nonether) +{ + sockaddr_dl sdl; + + /* A short address */ + sdl = make_linkaddr(":1:23:cc"); + ATF_REQUIRE_EQ("", ifname(sdl)); + ATF_REQUIRE_EQ("1.23.cc"s, ::link_ntoa(&sdl)); + ATF_REQUIRE_EQ(3, sdl.sdl_alen); + ATF_REQUIRE_EQ(true, + std::ranges::equal(std::vector{0x01u, 0x23u, 0xccu}, lladdr(sdl))); + + /* A long address */ + sdl = make_linkaddr(":1:23:cc:a:b:c:d:e:f"); + ATF_REQUIRE_EQ("", ifname(sdl)); + ATF_REQUIRE_EQ("1.23.cc.a.b.c.d.e.f"s, ::link_ntoa(&sdl)); + ATF_REQUIRE_EQ(9, sdl.sdl_alen); + ATF_REQUIRE_EQ(true, std::ranges::equal( + std::vector{0x01u, 0x23u, 0xccu, 0xau, 0xbu, 0xcu, 0xdu, 0xeu, 0xfu}, + lladdr(sdl))); +} + +/* + * Test link_addr behaviour with undersized buffers. + */ +ATF_TEST_CASE_WITHOUT_HEAD(smallbuf) +ATF_TEST_CASE_BODY(smallbuf) +{ + static constexpr auto garbage = std::byte{0xcc}; + auto buf = std::vector<std::byte>(); + sockaddr_dl *sdl; + int ret; + + /* + * Make an sdl with an sdl_data member of the appropriate size, and + * place it in buf. Ensure it's followed by a trailing byte of garbage + * so we can test that link_addr doesn't write past the end. + */ + auto mksdl = [&buf](std::size_t datalen) -> sockaddr_dl * { + auto actual_size = datalen + offsetof(sockaddr_dl, sdl_data); + + buf.resize(actual_size + 1); + std::ranges::fill(buf, garbage); + + auto *sdl = new(reinterpret_cast<sockaddr_dl *>(&buf[0])) + sockaddr_dl; + sdl->sdl_len = actual_size; + return (sdl); + }; + + /* An sdl large enough to store the interface name */ + sdl = mksdl(3); + ret = link_addr("ix0:1.2.3", sdl); + ATF_REQUIRE(*rbegin(buf) == garbage); + ATF_REQUIRE_EQ(-1, ret); + ATF_REQUIRE_EQ(ENOSPC, errno); + ATF_REQUIRE_EQ(3, sdl->sdl_nlen); + ATF_REQUIRE_EQ("ix0", ifname(*sdl)); + ATF_REQUIRE_EQ(0, static_cast<int>(sdl->sdl_alen)); + + /* + * For these tests, test both with and without an interface name, since + * that will overflow the buffer in different places. + */ + + /* An empty sdl. Nothing may grow on this cursed ground. */ + + sdl = mksdl(0); + ret = link_addr("ix0:1.2.3", sdl); + ATF_REQUIRE(*rbegin(buf) == garbage); + ATF_REQUIRE_EQ(-1, ret); + ATF_REQUIRE_EQ(ENOSPC, errno); + ATF_REQUIRE_EQ(0, sdl->sdl_nlen); + ATF_REQUIRE_EQ(0, static_cast<int>(sdl->sdl_alen)); + + sdl = mksdl(0); + ret = link_addr(":1.2.3", sdl); + ATF_REQUIRE(*rbegin(buf) == garbage); + ATF_REQUIRE_EQ(-1, ret); + ATF_REQUIRE_EQ(ENOSPC, errno); + ATF_REQUIRE_EQ(0, sdl->sdl_nlen); + ATF_REQUIRE_EQ(0, static_cast<int>(sdl->sdl_alen)); + + /* + * An sdl large enough to store the interface name and two octets of the + * address. + */ + + sdl = mksdl(5); + ret = link_addr("ix0:1.2.3", sdl); + ATF_REQUIRE(*rbegin(buf) == garbage); + ATF_REQUIRE_EQ(-1, ret); + ATF_REQUIRE_EQ(ENOSPC, errno); + ATF_REQUIRE_EQ("ix0", ifname(*sdl)); + ATF_REQUIRE(std::ranges::equal( + std::vector{ 0x01, 0x02 }, lladdr(*sdl))); + + sdl = mksdl(2); + ret = link_addr(":1.2.3", sdl); + ATF_REQUIRE(*rbegin(buf) == garbage); + ATF_REQUIRE_EQ(-1, ret); + ATF_REQUIRE_EQ(ENOSPC, errno); + ATF_REQUIRE_EQ("", ifname(*sdl)); + ATF_REQUIRE(std::ranges::equal( + std::vector{ 0x01, 0x02 }, lladdr(*sdl))); + + /* + * An sdl large enough to store the entire address. + */ + + sdl = mksdl(6); + ret = link_addr("ix0:1.2.3", sdl); + ATF_REQUIRE(*rbegin(buf) == garbage); + ATF_REQUIRE_EQ(0, ret); + ATF_REQUIRE_EQ("ix0", ifname(*sdl)); + ATF_REQUIRE(std::ranges::equal( + std::vector{ 0x01, 0x02, 0x03 }, lladdr(*sdl))); + + sdl = mksdl(3); + ret = link_addr(":1.2.3", sdl); + ATF_REQUIRE(*rbegin(buf) == garbage); + ATF_REQUIRE_EQ(0, ret); + ATF_REQUIRE_EQ("", ifname(*sdl)); + ATF_REQUIRE(std::ranges::equal( + std::vector{ 0x01, 0x02, 0x03 }, lladdr(*sdl))); +} + +/* + * Test an extremely long address which would overflow link_ntoa's internal + * buffer. It should handle this by truncating the output. + * (Test for SA-16:37.libc / CVE-2016-6559.) + */ +ATF_TEST_CASE_WITHOUT_HEAD(overlong) +ATF_TEST_CASE_BODY(overlong) +{ + auto sdl = make_linkaddr( + ":01.02.03.04.05.06.07.08.09.0a.0b.0c.0d.0e.0f." + "11.12.13.14.15.16.17.18.19.1a.1b.1c.1d.1e.1f." + "22.22.23.24.25.26.27.28.29.2a.2b.2c.2d.2e.2f"); + + ATF_REQUIRE_EQ( + "1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.11.12.13.14.15.16.17.18.19.1a.1b."s, + ::link_ntoa(&sdl)); +} + +/* + * Test link_ntoa_r, the re-entrant version of link_ntoa(). + */ +ATF_TEST_CASE_WITHOUT_HEAD(link_ntoa_r) +ATF_TEST_CASE_BODY(link_ntoa_r) +{ + static constexpr char garbage = 0x41; + std::vector<char> buf; + sockaddr_dl sdl; + size_t len; + int ret; + + // Return the contents of buf as a string, using the NUL terminator to + // determine length. This is to ensure we're using the return value in + // the same way C code would, but we do a bit more verification to + // elicit a test failure rather than a SEGV if it's broken. + auto bufstr = [&buf]() -> std::string_view { + // Find the NUL. + auto end = std::ranges::find(buf, '\0'); + ATF_REQUIRE(end != buf.end()); + + // Intentionally chopping the NUL off. + return {begin(buf), end}; + }; + + // Resize the buffer and set the contents to a known garbage value, so + // we don't accidentally have a NUL in the right place when link_ntoa_r + // didn't put it there. + auto resetbuf = [&buf, &len](std::size_t size) { + len = size; + buf.resize(len); + std::ranges::fill(buf, garbage); + }; + + // Test a short address with a large buffer. + sdl = make_linkaddr("ix0:1.2.3"); + resetbuf(64); + ret = ::link_ntoa_r(&sdl, &buf[0], &len); + ATF_REQUIRE_EQ(0, ret); + ATF_REQUIRE_EQ(10, len); + ATF_REQUIRE_EQ("ix0:1.2.3"s, bufstr()); + + // Test a buffer which is exactly the right size. + sdl = make_linkaddr("ix0:1.2.3"); + resetbuf(10); + ret = ::link_ntoa_r(&sdl, &buf[0], &len); + ATF_REQUIRE_EQ(0, ret); + ATF_REQUIRE_EQ(10, len); + ATF_REQUIRE_EQ("ix0:1.2.3"sv, bufstr()); + + // Test various short buffers, using a table of buffer length and the + // output we expect. All of these should produce valid but truncated + // strings, with a trailing NUL and with buflen set correctly. + + auto buftests = std::vector<std::pair<std::size_t, std::string_view>>{ + {1u, ""sv}, + {2u, ""sv}, + {3u, ""sv}, + {4u, "ix0"sv}, + {5u, "ix0:"sv}, + {6u, "ix0:1"sv}, + {7u, "ix0:1."sv}, + {8u, "ix0:1.2"sv}, + {9u, "ix0:1.2."sv}, + }; + + for (auto const &[buflen, expected] : buftests) { + sdl = make_linkaddr("ix0:1.2.3"); + resetbuf(buflen); + ret = ::link_ntoa_r(&sdl, &buf[0], &len); + ATF_REQUIRE_EQ(-1, ret); + ATF_REQUIRE_EQ(10, len); + ATF_REQUIRE_EQ(expected, bufstr()); + } + + // Test a NULL buffer, which should just set buflen. + sdl = make_linkaddr("ix0:1.2.3"); + len = 0; + ret = ::link_ntoa_r(&sdl, NULL, &len); + ATF_REQUIRE_EQ(-1, ret); + ATF_REQUIRE_EQ(10, len); + + // A NULL buffer with a non-zero length should also be accepted. + sdl = make_linkaddr("ix0:1.2.3"); + len = 64; + ret = ::link_ntoa_r(&sdl, NULL, &len); + ATF_REQUIRE_EQ(-1, ret); + ATF_REQUIRE_EQ(10, len); + + // Test a non-NULL buffer, but with a length of zero. + sdl = make_linkaddr("ix0:1.2.3"); + resetbuf(1); + len = 0; + ret = ::link_ntoa_r(&sdl, &buf[0], &len); + ATF_REQUIRE_EQ(-1, ret); + ATF_REQUIRE_EQ(10, len); + // Check we really didn't write anything. + ATF_REQUIRE_EQ(garbage, buf[0]); + + // Test a buffer which would be truncated in the middle of a two-digit + // hex octet, which should not write the truncated octet at all. + sdl = make_linkaddr("ix0:1.22.3"); + resetbuf(8); + ret = ::link_ntoa_r(&sdl, &buf[0], &len); + ATF_REQUIRE_EQ(-1, ret); + ATF_REQUIRE_EQ(11, len); + ATF_REQUIRE_EQ("ix0:1."sv, bufstr()); +} + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, basic); + ATF_ADD_TEST_CASE(tcs, ifname); + ATF_ADD_TEST_CASE(tcs, smallbuf); + ATF_ADD_TEST_CASE(tcs, invalid); + ATF_ADD_TEST_CASE(tcs, nonether); + ATF_ADD_TEST_CASE(tcs, overlong); + ATF_ADD_TEST_CASE(tcs, link_ntoa_r); +} diff --git a/lib/libc/tests/secure/Makefile b/lib/libc/tests/secure/Makefile index beaa01457cfe..515f8f53a43e 100644 --- a/lib/libc/tests/secure/Makefile +++ b/lib/libc/tests/secure/Makefile @@ -10,6 +10,7 @@ FORTIFY_TCATS+= uio # non-sys/ headers FORTIFY_TCATS+= poll +FORTIFY_TCATS+= signal FORTIFY_TCATS+= stdlib FORTIFY_TCATS+= stdio FORTIFY_TCATS+= string diff --git a/lib/libc/tests/secure/fortify_signal_test.c b/lib/libc/tests/secure/fortify_signal_test.c new file mode 100644 index 000000000000..03cfb9a9a13a --- /dev/null +++ b/lib/libc/tests/secure/fortify_signal_test.c @@ -0,0 +1,316 @@ +/* @generated by `generate-fortify-tests.lua "signal"` */ + +#define _FORTIFY_SOURCE 2 +#define TMPFILE_SIZE (1024 * 32) + +#include <sys/param.h> +#include <sys/jail.h> +#include <sys/random.h> +#include <sys/resource.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <sys/wait.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <poll.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <sysexits.h> +#include <unistd.h> +#include <wchar.h> +#include <atf-c.h> + +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + +/* + * Create a new symlink to use for readlink(2) style tests, we'll just use a + * random target name to have something interesting to look at. + */ +static const char * __unused +new_symlink(size_t __len) +{ + static const char linkname[] = "link"; + char target[MAXNAMLEN]; + int error; + + ATF_REQUIRE(__len <= sizeof(target)); + + arc4random_buf(target, sizeof(target)); + + error = unlink(linkname); + ATF_REQUIRE(error == 0 || errno == ENOENT); + + error = symlink(target, linkname); + ATF_REQUIRE(error == 0); + + return (linkname); +} + +/* + * For our purposes, first descriptor will be the reader; we'll send both + * raw data and a control message over it so that the result can be used for + * any of our recv*() tests. + */ +static void __unused +new_socket(int sock[2]) +{ + unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 }; + static char sockbuf[256]; + ssize_t rv; + size_t total = 0; + struct msghdr hdr = { 0 }; + struct cmsghdr *cmsg; + int error, fd; + + error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + ATF_REQUIRE(error == 0); + + while (total != sizeof(sockbuf)) { + rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0); + + ATF_REQUIRE_MSG(rv > 0, + "expected bytes sent, got %zd with %zu left (size %zu, total %zu)", + rv, sizeof(sockbuf) - total, sizeof(sockbuf), total); + ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf), + "%zd exceeds total %zu", rv, sizeof(sockbuf)); + total += rv; + } + + hdr.msg_control = ctrl; + hdr.msg_controllen = sizeof(ctrl); + + cmsg = CMSG_FIRSTHDR(&hdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + fd = STDIN_FILENO; + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + + error = sendmsg(sock[1], &hdr, 0); + ATF_REQUIRE(error != -1); +} + +/* + * Constructs a tmpfile that we can use for testing read(2) and friends. + */ +static int __unused +new_tmpfile(void) +{ + char buf[1024]; + ssize_t rv; + size_t written; + int fd; + + fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE(fd >= 0); + + written = 0; + while (written < TMPFILE_SIZE) { + rv = write(fd, buf, sizeof(buf)); + ATF_REQUIRE(rv > 0); + + written += rv; + } + + ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); + return (fd); +} + +static void +disable_coredumps(void) +{ + struct rlimit rl = { 0 }; + + if (setrlimit(RLIMIT_CORE, &rl) == -1) + _exit(EX_OSERR); +} + +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + +ATF_TC(sig2str_before_end); +ATF_TC_HEAD(sig2str_before_end, tc) +{ +} +ATF_TC_BODY(sig2str_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[SIG2STR_MAX + 1]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = SIG2STR_MAX + 1; + const size_t __idx __unused = __len - 1; + + sig2str(1, __stack.__buf); +#undef BUF + +} + +ATF_TC(sig2str_end); +ATF_TC_HEAD(sig2str_end, tc) +{ +} +ATF_TC_BODY(sig2str_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[SIG2STR_MAX]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = SIG2STR_MAX; + const size_t __idx __unused = __len - 1; + + sig2str(1, __stack.__buf); +#undef BUF + +} + +ATF_TC(sig2str_heap_before_end); +ATF_TC_HEAD(sig2str_heap_before_end, tc) +{ +} +ATF_TC_BODY(sig2str_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (SIG2STR_MAX + 1); + const size_t __len = SIG2STR_MAX + 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + sig2str(1, __stack.__buf); +#undef BUF + +} + +ATF_TC(sig2str_heap_end); +ATF_TC_HEAD(sig2str_heap_end, tc) +{ +} +ATF_TC_BODY(sig2str_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (SIG2STR_MAX); + const size_t __len = SIG2STR_MAX; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + sig2str(1, __stack.__buf); +#undef BUF + +} + +ATF_TC(sig2str_heap_after_end); +ATF_TC_HEAD(sig2str_heap_after_end, tc) +{ +} +ATF_TC_BODY(sig2str_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (SIG2STR_MAX - 1); + const size_t __len = SIG2STR_MAX - 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + sig2str(1, __stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, sig2str_before_end); + ATF_TP_ADD_TC(tp, sig2str_end); + ATF_TP_ADD_TC(tp, sig2str_heap_before_end); + ATF_TP_ADD_TC(tp, sig2str_heap_end); + ATF_TP_ADD_TC(tp, sig2str_heap_after_end); + return (atf_no_error()); +} diff --git a/lib/libc/tests/secure/fortify_stdlib_test.c b/lib/libc/tests/secure/fortify_stdlib_test.c index ae021e8418f7..d0b1af78da86 100644 --- a/lib/libc/tests/secure/fortify_stdlib_test.c +++ b/lib/libc/tests/secure/fortify_stdlib_test.c @@ -305,6 +305,148 @@ monitor: } +ATF_TC(getenv_r_before_end); +ATF_TC_HEAD(getenv_r_before_end, tc) +{ +} +ATF_TC_BODY(getenv_r_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + getenv_r("PATH", __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getenv_r_end); +ATF_TC_HEAD(getenv_r_end, tc) +{ +} +ATF_TC_BODY(getenv_r_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + getenv_r("PATH", __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getenv_r_heap_before_end); +ATF_TC_HEAD(getenv_r_heap_before_end, tc) +{ +} +ATF_TC_BODY(getenv_r_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getenv_r("PATH", __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getenv_r_heap_end); +ATF_TC_HEAD(getenv_r_heap_end, tc) +{ +} +ATF_TC_BODY(getenv_r_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getenv_r("PATH", __stack.__buf, __len); +#undef BUF + +} + +ATF_TC(getenv_r_heap_after_end); +ATF_TC_HEAD(getenv_r_heap_after_end, tc) +{ +} +ATF_TC_BODY(getenv_r_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + getenv_r("PATH", __stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + ATF_TC(realpath_before_end); ATF_TC_HEAD(realpath_before_end, tc) { @@ -454,6 +596,11 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, arc4random_buf_heap_before_end); ATF_TP_ADD_TC(tp, arc4random_buf_heap_end); ATF_TP_ADD_TC(tp, arc4random_buf_heap_after_end); + ATF_TP_ADD_TC(tp, getenv_r_before_end); + ATF_TP_ADD_TC(tp, getenv_r_end); + ATF_TP_ADD_TC(tp, getenv_r_heap_before_end); + ATF_TP_ADD_TC(tp, getenv_r_heap_end); + ATF_TP_ADD_TC(tp, getenv_r_heap_after_end); ATF_TP_ADD_TC(tp, realpath_before_end); ATF_TP_ADD_TC(tp, realpath_end); ATF_TP_ADD_TC(tp, realpath_heap_before_end); diff --git a/lib/libc/tests/secure/generate-fortify-tests.lua b/lib/libc/tests/secure/generate-fortify-tests.lua index 36ff01af7a17..c9cd9353a869 100755 --- a/lib/libc/tests/secure/generate-fortify-tests.lua +++ b/lib/libc/tests/secure/generate-fortify-tests.lua @@ -478,6 +478,18 @@ local all_tests = { init = poll_init, }, }, + signal = { + -- <signal.h> + { + func = "sig2str", + bufsize = "SIG2STR_MAX", + arguments = { + "1", + "__buf", + }, + exclude = excludes_stack_overflow, + }, + }, stdio = { -- <stdio.h> { @@ -585,6 +597,15 @@ local all_tests = { exclude = excludes_stack_overflow, }, { + func = "getenv_r", + arguments = { + "\"PATH\"", + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + }, + { func = "realpath", bufsize = "PATH_MAX", arguments = { diff --git a/lib/libc/tests/stdio/scanfloat_test.c b/lib/libc/tests/stdio/scanfloat_test.c index a93238504dd1..635d93d560b3 100644 --- a/lib/libc/tests/stdio/scanfloat_test.c +++ b/lib/libc/tests/stdio/scanfloat_test.c @@ -59,88 +59,88 @@ ATF_TC_BODY(normalized_numbers, tc) buf[0] = '\0'; ATF_REQUIRE(setlocale(LC_NUMERIC, "")); - sscanf("3.141592", "%e", &f); + ATF_REQUIRE_EQ(1, sscanf("3.141592", "%e", &f)); ATF_REQUIRE(eq(FLT, f, 3.141592)); - sscanf("3.141592653589793", "%lf", &d); + ATF_REQUIRE_EQ(1, sscanf("3.141592653589793", "%lf", &d)); ATF_REQUIRE(eq(DBL, d, 3.141592653589793)); - sscanf("1.234568e+06", "%E", &f); + ATF_REQUIRE_EQ(1, sscanf("1.234568e+06", "%E", &f)); ATF_REQUIRE(eq(FLT, f, 1.234568e+06)); - sscanf("-1.234568e6", "%lF", &d); + ATF_REQUIRE_EQ(1, sscanf("-1.234568e6", "%lF", &d)); ATF_REQUIRE(eq(DBL, d, -1.234568e6)); - sscanf("+1.234568e-52", "%LG", &ld); + ATF_REQUIRE_EQ(1, sscanf("+1.234568e-52", "%LG", &ld)); ATF_REQUIRE(eq(LDBL, ld, 1.234568e-52L)); - sscanf("0.1", "%la", &d); + ATF_REQUIRE_EQ(1, sscanf("0.1", "%la", &d)); ATF_REQUIRE(eq(DBL, d, 0.1)); - sscanf("00.2", "%lA", &d); + ATF_REQUIRE_EQ(1, sscanf("00.2", "%lA", &d)); ATF_REQUIRE(eq(DBL, d, 0.2)); - sscanf("123456", "%5le%s", &d, buf); + ATF_REQUIRE_EQ(2, sscanf("123456", "%5le%s", &d, buf)); ATF_REQUIRE(eq(DBL, d, 12345.)); ATF_REQUIRE(strcmp(buf, "6") == 0); - sscanf("1.0Q", "%*5le%s", buf); + ATF_REQUIRE_EQ(1, sscanf("1.0Q", "%*5le%s", buf)); ATF_REQUIRE(strcmp(buf, "Q") == 0); - sscanf("-1.23e", "%e%s", &f, buf); + ATF_REQUIRE_EQ(2, sscanf("-1.23e", "%e%s", &f, buf)); ATF_REQUIRE(eq(FLT, f, -1.23)); ATF_REQUIRE(strcmp(buf, "e") == 0); - sscanf("1.25e+", "%le%s", &d, buf); + ATF_REQUIRE_EQ(2, sscanf("1.25e+", "%le%s", &d, buf)); ATF_REQUIRE(eq(DBL, d, 1.25)); ATF_REQUIRE(strcmp(buf, "e+") == 0); - sscanf("1.23E4E5", "%le%s", &d, buf); + ATF_REQUIRE_EQ(2, sscanf("1.23E4E5", "%le%s", &d, buf)); ATF_REQUIRE(eq(DBL, d, 1.23e4)); ATF_REQUIRE(strcmp(buf, "E5") == 0); - sscanf("12e6", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("12e6", "%le", &d)); ATF_REQUIRE(eq(DBL, d, 12e6)); - sscanf("1.a", "%le%s", &d, buf); + ATF_REQUIRE_EQ(2, sscanf("1.a", "%le%s", &d, buf)); ATF_REQUIRE(eq(DBL, d, 1.0)); ATF_REQUIRE(strcmp(buf, "a") == 0); - sscanf(".0p4", "%le%s", &d, buf); + ATF_REQUIRE_EQ(2, sscanf(".0p4", "%le%s", &d, buf)); ATF_REQUIRE(eq(DBL, d, 0.0)); ATF_REQUIRE(strcmp(buf, "p4") == 0); d = 0.25; - ATF_REQUIRE(sscanf(".", "%le", &d) == 0); + ATF_REQUIRE_EQ(0, sscanf(".", "%le", &d)); ATF_REQUIRE(d == 0.25); - sscanf("0x08", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("0x08", "%le", &d)); ATF_REQUIRE(d == 0x8p0); - sscanf("0x90a.bcdefP+09a", "%le%s", &d, buf); + ATF_REQUIRE_EQ(2, sscanf("0x90a.bcdefP+09a", "%le%s", &d, buf)); ATF_REQUIRE(d == 0x90a.bcdefp+09); ATF_REQUIRE(strcmp(buf, "a") == 0); #if (LDBL_MANT_DIG > DBL_MANT_DIG) && !defined(__i386__) - sscanf("3.14159265358979323846", "%Lg", &ld); + ATF_REQUIRE_EQ(1, sscanf("3.14159265358979323846", "%Lg", &ld)); ATF_REQUIRE(eq(LDBL, ld, 3.14159265358979323846L)); - sscanf(" 0X.0123456789abcdefffp-3g", "%Le%s", &ld, buf); + ATF_REQUIRE_EQ(2, sscanf(" 0X.0123456789abcdefffp-3g", "%Le%s", &ld, buf)); ATF_REQUIRE(ld == 0x0.0123456789abcdefffp-3L); ATF_REQUIRE(strcmp(buf, "g") == 0); #endif - sscanf("0xg", "%le%s", &d, buf); + ATF_REQUIRE_EQ(2, sscanf("0xg", "%le%s", &d, buf)); ATF_REQUIRE(d == 0.0); ATF_REQUIRE(strcmp(buf, "xg") == 0); ATF_REQUIRE(setlocale(LC_NUMERIC, "ru_RU.ISO8859-5")); /* decimalpoint==, */ - sscanf("1.23", "%le%s", &d, buf); + ATF_REQUIRE_EQ(2, sscanf("1.23", "%le%s", &d, buf)); ATF_REQUIRE(d == 1.0); ATF_REQUIRE(strcmp(buf, ".23") == 0); - sscanf("1,23", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("1,23", "%le", &d)); ATF_REQUIRE(d == 1.23); ATF_REQUIRE(setlocale(LC_NUMERIC, "")); @@ -156,40 +156,40 @@ ATF_TC_BODY(infinities_and_nans, tc) ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); - sscanf("-Inf", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("-Inf", "%le", &d)); ATF_REQUIRE(d < 0.0 && isinf(d)); - sscanf("iNfInItY and beyond", "%le%s", &d, buf); + ATF_REQUIRE_EQ(2, sscanf("iNfInItY and beyond", "%le%s", &d, buf)); ATF_REQUIRE(d > 0.0 && isinf(d)); ATF_REQUIRE(strcmp(buf, " and beyond")); - sscanf("NaN", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("NaN", "%le", &d)); ATF_REQUIRE(isnan(d)); - sscanf("NAN(123Y", "%le%s", &d, buf); + ATF_REQUIRE_EQ(2, sscanf("NAN(123Y", "%le%s", &d, buf)); ATF_REQUIRE(isnan(d)); ATF_REQUIRE(strcmp(buf, "(123Y") == 0); - sscanf("nan(f00f)plugh", "%le%s", &d, buf); + ATF_REQUIRE_EQ(2, sscanf("nan(f00f)plugh", "%le%s", &d, buf)); ATF_REQUIRE(isnan(d)); ATF_REQUIRE(strcmp(buf, "plugh") == 0); - sscanf("-nan", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("-nan", "%le", &d)); ATF_REQUIRE(isnan(d)); /* Only quiet NaNs should be returned. */ - sscanf("NaN", "%e", &f); - sscanf("nan", "%le", &d); - sscanf("nan", "%Le", &ld); - feclearexcept(FE_ALL_EXCEPT); + ATF_REQUIRE_EQ(1, sscanf("NaN", "%e", &f)); + ATF_REQUIRE_EQ(1, sscanf("nan", "%le", &d)); + ATF_REQUIRE_EQ(1, sscanf("nan", "%Le", &ld)); + ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT)); ATF_REQUIRE(f != f); ATF_REQUIRE(d != d); ATF_REQUIRE(ld != ld); ATF_REQUIRE(fetestexcept(FE_INVALID) == 0); - sscanf("nan(1234)", "%e", &f); - sscanf("nan(1234)", "%le", &d); - sscanf("nan(1234)", "%Le", &ld); - feclearexcept(FE_ALL_EXCEPT); + ATF_REQUIRE_EQ(1, sscanf("nan(1234)", "%e", &f)); + ATF_REQUIRE_EQ(1, sscanf("nan(1234)", "%le", &d)); + ATF_REQUIRE_EQ(1, sscanf("nan(1234)", "%Le", &ld)); + ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT)); ATF_REQUIRE(f != f); ATF_REQUIRE(d != d); ATF_REQUIRE(ld != ld); @@ -205,74 +205,74 @@ ATF_TC_BODY(rounding_tests, tc) ATF_REQUIRE(setlocale(LC_NUMERIC, "C")); - fesetround(FE_DOWNWARD); + ATF_REQUIRE_EQ(0, fesetround(FE_DOWNWARD)); - sscanf("1.999999999999999999999999999999999", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("1.999999999999999999999999999999999", "%le", &d)); ATF_REQUIRE(d < 2.0); - sscanf("0x1.ffffffffffffffp0", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("0x1.ffffffffffffffp0", "%le", &d)); ATF_REQUIRE(d < 2.0); - sscanf("1.999999999999999999999999999999999", "%Le", &ld); + ATF_REQUIRE_EQ(1, sscanf("1.999999999999999999999999999999999", "%Le", &ld)); ATF_REQUIRE(ld < 2.0); - sscanf("1.0571892669084007", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("1.0571892669084007", "%le", &d)); ATF_REQUIRE(d == 0x1.0ea3f4af0dc59p0); - sscanf("-1.0571892669084007", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("-1.0571892669084007", "%le", &d)); ATF_REQUIRE(d == -0x1.0ea3f4af0dc5ap0); - sscanf("1.0571892669084010", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("1.0571892669084010", "%le", &d)); ATF_REQUIRE(d == 0x1.0ea3f4af0dc5ap0); - sscanf("0x1.23p-5000", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("0x1.23p-5000", "%le", &d)); ATF_REQUIRE(d == 0.0); - sscanf("0x1.2345678p-1050", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("0x1.2345678p-1050", "%le", &d)); ATF_REQUIRE(d == 0x1.234567p-1050); - fesetround(FE_UPWARD); + ATF_REQUIRE_EQ(0, fesetround(FE_UPWARD)); - sscanf("1.0571892669084007", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("1.0571892669084007", "%le", &d)); ATF_REQUIRE(d == 0x1.0ea3f4af0dc5ap0); - sscanf("-1.0571892669084007", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("-1.0571892669084007", "%le", &d)); ATF_REQUIRE(d == -0x1.0ea3f4af0dc59p0); - sscanf("1.0571892669084010", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("1.0571892669084010", "%le", &d)); ATF_REQUIRE(d == 0x1.0ea3f4af0dc5bp0); - sscanf("0x1.23p-5000", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("0x1.23p-5000", "%le", &d)); ATF_REQUIRE(d == 0x1p-1074); - sscanf("0x1.2345678p-1050", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("0x1.2345678p-1050", "%le", &d)); ATF_REQUIRE(d == 0x1.234568p-1050); - fesetround(FE_TOWARDZERO); + ATF_REQUIRE_EQ(0, fesetround(FE_TOWARDZERO)); - sscanf("1.0571892669084007", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("1.0571892669084007", "%le", &d)); ATF_REQUIRE(d == 0x1.0ea3f4af0dc59p0); - sscanf("-1.0571892669084007", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("-1.0571892669084007", "%le", &d)); ATF_REQUIRE(d == -0x1.0ea3f4af0dc59p0); - sscanf("1.0571892669084010", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("1.0571892669084010", "%le", &d)); ATF_REQUIRE(d == 0x1.0ea3f4af0dc5ap0); - sscanf("0x1.23p-5000", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("0x1.23p-5000", "%le", &d)); ATF_REQUIRE(d == 0.0); - sscanf("0x1.2345678p-1050", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("0x1.2345678p-1050", "%le", &d)); ATF_REQUIRE(d == 0x1.234567p-1050); - fesetround(FE_TONEAREST); + ATF_REQUIRE_EQ(0, fesetround(FE_TONEAREST)); /* 1.0571892669084007 is slightly closer to 0x1.0ea3f4af0dc59p0 */ - sscanf("1.0571892669084007", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("1.0571892669084007", "%le", &d)); ATF_REQUIRE(d == 0x1.0ea3f4af0dc59p0); - sscanf("-1.0571892669084007", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("-1.0571892669084007", "%le", &d)); ATF_REQUIRE(d == -0x1.0ea3f4af0dc59p0); - sscanf("1.0571892669084010", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("1.0571892669084010", "%le", &d)); ATF_REQUIRE(d == 0x1.0ea3f4af0dc5bp0); /* strtod() should round small numbers to 0. */ - sscanf("0x1.23p-5000", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("0x1.23p-5000", "%le", &d)); ATF_REQUIRE(d == 0.0); /* Extra digits in a denormal shouldn't break anything. */ - sscanf("0x1.2345678p-1050", "%le", &d); + ATF_REQUIRE_EQ(1, sscanf("0x1.2345678p-1050", "%le", &d)); ATF_REQUIRE(d == 0x1.234568p-1050); } @@ -287,16 +287,16 @@ ATF_TC_BODY(strtod, tc) ATF_REQUIRE(strcmp("xy", endp) == 0); /* This used to cause an infinite loop and round the wrong way. */ - fesetround(FE_DOWNWARD); + ATF_REQUIRE_EQ(0, fesetround(FE_DOWNWARD)); ATF_REQUIRE(strtof("3.5e38", &endp) == FLT_MAX); ATF_REQUIRE(strtod("2e308", &endp) == DBL_MAX); - fesetround(FE_UPWARD); + ATF_REQUIRE_EQ(0, fesetround(FE_UPWARD)); ATF_REQUIRE(strtof("3.5e38", &endp) == INFINITY); ATF_REQUIRE(strtod("2e308", &endp) == INFINITY); - fesetround(FE_TOWARDZERO); + ATF_REQUIRE_EQ(0, fesetround(FE_TOWARDZERO)); ATF_REQUIRE(strtof("3.5e38", &endp) == FLT_MAX); ATF_REQUIRE(strtod("2e308", &endp) == DBL_MAX); - fesetround(FE_TONEAREST); + ATF_REQUIRE_EQ(0, fesetround(FE_TONEAREST)); ATF_REQUIRE(strtof("3.5e38", &endp) == INFINITY); ATF_REQUIRE(strtod("2e308", &endp) == INFINITY); } diff --git a/lib/libc/tests/stdlib/Makefile b/lib/libc/tests/stdlib/Makefile index 6f57b8014a1e..50726a5d8af6 100644 --- a/lib/libc/tests/stdlib/Makefile +++ b/lib/libc/tests/stdlib/Makefile @@ -1,12 +1,14 @@ .include <src.opts.mk> ATF_TESTS_C+= clearenv_test +ATF_TESTS_C+= cxa_atexit_test ATF_TESTS_C+= dynthr_test +ATF_TESTS_C+= getenv_r_test ATF_TESTS_C+= heapsort_test ATF_TESTS_C+= libc_exit_test ATF_TESTS_C+= mergesort_test ATF_TESTS_C+= qsort_test -.if ${COMPILER_TYPE} == "clang" +.if ${COMPILER_FEATURES:Mblocks} ATF_TESTS_C+= qsort_b_test .endif ATF_TESTS_C+= qsort_r_compat_test @@ -58,11 +60,9 @@ PROGS+= h_getopt h_getopt_long CFLAGS+= -I${.CURDIR} -CXXSTD.cxa_thread_atexit_test= c++11 -CXXSTD.cxa_thread_atexit_nothr_test= c++11 LIBADD.cxa_thread_atexit_test+= pthread -# Tests that requires Blocks feature +# Tests that require blocks support .for t in qsort_b_test CFLAGS.${t}.c+= -fblocks LIBADD.${t}+= BlocksRuntime @@ -79,5 +79,6 @@ LIBADD.libc_exit_test+= pthread LIBADD.strtod_test+= m SUBDIR+= dynthr_mod +SUBDIR+= libatexit .include <bsd.test.mk> diff --git a/lib/libc/tests/stdlib/cxa_atexit_test.c b/lib/libc/tests/stdlib/cxa_atexit_test.c new file mode 100644 index 000000000000..7e2cafbce850 --- /dev/null +++ b/lib/libc/tests/stdlib/cxa_atexit_test.c @@ -0,0 +1,132 @@ +/*- + * Copyright (c) 2025 Kyle Evans <kevans@FreeBSD.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <sys/wait.h> + +#include <dlfcn.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +#include <atf-c.h> + +#define ARBITRARY_EXIT_CODE 42 + +static char * +get_shlib(const char *srcdir) +{ + char *shlib; + + shlib = NULL; + if (asprintf(&shlib, "%s/libatexit.so", srcdir) < 0) + atf_tc_fail("failed to construct path to libatexit.so"); + return (shlib); +} + +static void +run_test(const atf_tc_t *tc, bool with_fatal_atexit, bool with_exit) +{ + pid_t p; + void (*set_fatal_atexit)(bool); + void (*set_exit_code)(int); + void *hdl; + char *shlib; + + shlib = get_shlib(atf_tc_get_config_var(tc, "srcdir")); + + hdl = dlopen(shlib, RTLD_LAZY); + ATF_REQUIRE_MSG(hdl != NULL, "dlopen: %s", dlerror()); + + free(shlib); + + if (with_fatal_atexit) { + set_fatal_atexit = dlsym(hdl, "set_fatal_atexit"); + ATF_REQUIRE_MSG(set_fatal_atexit != NULL, + "set_fatal_atexit: %s", dlerror()); + } + if (with_exit) { + set_exit_code = dlsym(hdl, "set_exit_code"); + ATF_REQUIRE_MSG(set_exit_code != NULL, "set_exit_code: %s", + dlerror()); + } + + p = atf_utils_fork(); + if (p == 0) { + /* + * Don't let the child clobber the results file; stderr/stdout + * have been replaced by atf_utils_fork() to capture it. We're + * intentionally using exit() instead of _exit() here to run + * __cxa_finalize at exit, otherwise we'd just leave it be. + */ + closefrom(3); + + if (with_fatal_atexit) + set_fatal_atexit(true); + if (with_exit) + set_exit_code(ARBITRARY_EXIT_CODE); + + dlclose(hdl); + + /* + * If the dtor was supposed to exit (most cases), then we should + * not have made it to this point. If it's not supposed to + * exit, then we just exit with success here because we might + * be expecting either a clean exit or a signal on our way out + * as the final __cxa_finalize tries to run a callback in the + * unloaded DSO. + */ + if (with_exit) + exit(1); + exit(0); + } + + dlclose(hdl); + atf_utils_wait(p, with_exit ? ARBITRARY_EXIT_CODE : 0, "", ""); +} + +ATF_TC_WITHOUT_HEAD(simple_cxa_atexit); +ATF_TC_BODY(simple_cxa_atexit, tc) +{ + /* + * This test exits in a global object's dtor so that we check for our + * dtor being run at dlclose() time. If it isn't, then the forked child + * will have a chance to exit(1) after dlclose() to raise a failure. + */ + run_test(tc, false, true); +} + +ATF_TC_WITHOUT_HEAD(late_cxa_atexit); +ATF_TC_BODY(late_cxa_atexit, tc) +{ + /* + * This test creates another global object during a __cxa_atexit handler + * invocation. It's been observed in the wild that we weren't executing + * it, then the DSO gets torn down and it was executed at application + * exit time instead. In the best case scenario we would crash if + * something else hadn't been mapped there. + */ + run_test(tc, true, false); +} + +ATF_TC_WITHOUT_HEAD(late_cxa_atexit_ran); +ATF_TC_BODY(late_cxa_atexit_ran, tc) +{ + /* + * This is a slight variation of the previous test where we trigger an + * exit() in our late-registered __cxa_atexit handler so that we can + * ensure it was ran *before* dlclose() finished and not through some + * weird chain of events afterwards. + */ + run_test(tc, true, true); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, simple_cxa_atexit); + ATF_TP_ADD_TC(tp, late_cxa_atexit); + ATF_TP_ADD_TC(tp, late_cxa_atexit_ran); + return (atf_no_error()); +} diff --git a/lib/libc/tests/stdlib/getenv_r_test.c b/lib/libc/tests/stdlib/getenv_r_test.c new file mode 100644 index 000000000000..8085b92b1064 --- /dev/null +++ b/lib/libc/tests/stdlib/getenv_r_test.c @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 2025 Klara, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <atf-c.h> + +ATF_TC_WITHOUT_HEAD(getenv_r_ok); +ATF_TC_BODY(getenv_r_ok, tc) +{ + const char *ident = atf_tc_get_ident(tc); + char buf[256]; + + ATF_REQUIRE_EQ(0, setenv("ATF_TC_IDENT", ident, 1)); + ATF_REQUIRE_EQ(0, getenv_r("ATF_TC_IDENT", buf, sizeof(buf))); + ATF_REQUIRE_STREQ(ident, buf); +} + +ATF_TC_WITHOUT_HEAD(getenv_r_einval); +ATF_TC_BODY(getenv_r_einval, tc) +{ + char buf[256]; + + errno = 0; + ATF_REQUIRE_EQ(-1, getenv_r(NULL, buf, sizeof(buf))); + ATF_REQUIRE_EQ(EINVAL, errno); + errno = 0; + ATF_REQUIRE_EQ(-1, getenv_r("", buf, sizeof(buf))); + ATF_REQUIRE_EQ(EINVAL, errno); + errno = 0; + ATF_REQUIRE_EQ(-1, getenv_r("A=B", buf, sizeof(buf))); + ATF_REQUIRE_EQ(EINVAL, errno); +} + +ATF_TC_WITHOUT_HEAD(getenv_r_enoent); +ATF_TC_BODY(getenv_r_enoent, tc) +{ + char buf[256]; + + errno = 0; + ATF_REQUIRE_EQ(-1, getenv_r("no such variable", buf, sizeof(buf))); + ATF_REQUIRE_EQ(ENOENT, errno); +} + +ATF_TC_WITHOUT_HEAD(getenv_r_erange); +ATF_TC_BODY(getenv_r_erange, tc) +{ + const char *ident = atf_tc_get_ident(tc); + char buf[256]; + + ATF_REQUIRE_EQ(0, setenv("ATF_TC_IDENT", ident, 1)); + errno = 0; + ATF_REQUIRE_EQ(-1, getenv_r("ATF_TC_IDENT", buf, strlen(ident))); + ATF_REQUIRE_EQ(ERANGE, errno); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, getenv_r_ok); + ATF_TP_ADD_TC(tp, getenv_r_einval); + ATF_TP_ADD_TC(tp, getenv_r_enoent); + ATF_TP_ADD_TC(tp, getenv_r_erange); + return (atf_no_error()); +} diff --git a/lib/libc/tests/stdlib/libatexit/Makefile b/lib/libc/tests/stdlib/libatexit/Makefile new file mode 100644 index 000000000000..9ba04c77af62 --- /dev/null +++ b/lib/libc/tests/stdlib/libatexit/Makefile @@ -0,0 +1,11 @@ +SHLIB_CXX= libatexit +SHLIB_NAME= libatexit.so +SHLIB_MAJOR= 1 +SHLIBDIR= ${TESTSDIR} +PACKAGE= tests +SRCS= libatexit.cc + +TESTSDIR:= ${TESTSBASE}/${RELDIR:C/libc\/tests/libc/:H} + + +.include <bsd.lib.mk> diff --git a/lib/libc/tests/stdlib/libatexit/libatexit.cc b/lib/libc/tests/stdlib/libatexit/libatexit.cc new file mode 100644 index 000000000000..bb286c97e421 --- /dev/null +++ b/lib/libc/tests/stdlib/libatexit/libatexit.cc @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2025 Kyle Evans <kevans@FreeBSD.org> + * + * SPDX-License-Identifier: BSD-2-Clause + * + */ + +#include <unistd.h> + +static int exit_code = -1; +static bool fatal_atexit; + +extern "C" { + void set_fatal_atexit(bool); + void set_exit_code(int); +} + +void +set_fatal_atexit(bool fexit) +{ + fatal_atexit = fexit; +} + +void +set_exit_code(int code) +{ + exit_code = code; +} + +struct other_object { + ~other_object() { + + /* + * In previous versions of our __cxa_atexit handling, we would + * never actually execute this handler because it's added during + * ~object() below; __cxa_finalize would never revisit it. We + * will allow the caller to configure us to exit with a certain + * exit code so that it can run us twice: once to ensure we + * don't crash at the end, and again to make sure the handler + * actually ran. + */ + if (exit_code != -1) + _exit(exit_code); + } +}; + +void +create_staticobj() +{ + static other_object obj; +} + +struct object { + ~object() { + /* + * If we're doing the fatal_atexit behavior (i.e., create an + * object that will add its own dtor for __cxa_finalize), then + * we don't exit here. + */ + if (fatal_atexit) + create_staticobj(); + else if (exit_code != -1) + _exit(exit_code); + } +}; + +static object obj; diff --git a/lib/libcam/Makefile b/lib/libcam/Makefile index c2f7b75bc878..d4efbbdf4d9b 100644 --- a/lib/libcam/Makefile +++ b/lib/libcam/Makefile @@ -3,7 +3,7 @@ PACKAGE= runtime LIB= cam SHLIBDIR?= /lib SRCS= camlib.c scsi_cmdparse.c scsi_all.c scsi_da.c scsi_sa.c cam.c \ - ata_all.c nvme_all.c smp_all.c scsi_wrap.c + ata_all.c nvme_all.c nvme_util.c smp_all.c scsi_wrap.c INCS= camlib.h scsi_wrap.h LIBADD= sbuf @@ -39,7 +39,8 @@ MLINKS+= cam.3 cam_open_device.3 \ ${SRCTOP}/sys/cam/ata \ ${SRCTOP}/sys/cam/nvme \ ${SRCTOP}/sys/cam/mmc \ - ${SRCTOP}/sys/cam/scsi + ${SRCTOP}/sys/cam/scsi \ + ${SRCTOP}/sys/dev/nvme CFLAGS+= -I${.CURDIR} -I${SRCTOP}/sys diff --git a/lib/libcasper/services/cap_dns/tests/dns_test.c b/lib/libcasper/services/cap_dns/tests/dns_test.c index 76534bbbebad..56d867e474f5 100644 --- a/lib/libcasper/services/cap_dns/tests/dns_test.c +++ b/lib/libcasper/services/cap_dns/tests/dns_test.c @@ -198,18 +198,17 @@ hostent_compare(const struct hostent *hp0, const struct hostent *hp1) static void runtest(cap_channel_t *capdns, unsigned int expected) { - unsigned int result, failure; + unsigned int result; struct addrinfo *ais, *aic, hints, *hintsp; struct hostent *hps, *hpc; struct in_addr ip4; struct in6_addr ip6; int caperr, syserr; - failure = result = 0; + result = 0; hps = gethostbyname("example.com"); if (hps == NULL) { - failure |= GETHOSTBYNAME; fprintf(stderr, "Unable to resolve %s IPv4.\n", "example.com"); } else { hpc = cap_gethostbyname(capdns, "example.com"); @@ -219,7 +218,6 @@ runtest(cap_channel_t *capdns, unsigned int expected) hps = gethostbyname2("example.com", AF_INET); if (hps == NULL) { - failure |= GETHOSTBYNAME2_AF_INET; fprintf(stderr, "Unable to resolve %s IPv4.\n", "example.com"); } else { hpc = cap_gethostbyname2(capdns, "example.com", AF_INET); @@ -229,7 +227,6 @@ runtest(cap_channel_t *capdns, unsigned int expected) hps = gethostbyname2("example.com", AF_INET6); if (hps == NULL) { - failure |= GETHOSTBYNAME2_AF_INET6; fprintf(stderr, "Unable to resolve %s IPv6.\n", "example.com"); } else { hpc = cap_gethostbyname2(capdns, "example.com", AF_INET6); @@ -250,7 +247,6 @@ runtest(cap_channel_t *capdns, unsigned int expected) syserr = getaddrinfo("freebsd.org", "25", hintsp, &ais); if (syserr != 0) { - failure |= GETADDRINFO_AF_UNSPEC; fprintf(stderr, "Unable to issue [system] getaddrinfo() for AF_UNSPEC: %s\n", gai_strerror(syserr)); @@ -268,7 +264,6 @@ runtest(cap_channel_t *capdns, unsigned int expected) hints.ai_family = AF_INET; syserr = getaddrinfo("freebsd.org", "25", hintsp, &ais); if (syserr != 0) { - failure |= GETADDRINFO_AF_INET; fprintf(stderr, "Unable to issue [system] getaddrinfo() for AF_UNSPEC: %s\n", gai_strerror(syserr)); @@ -286,7 +281,6 @@ runtest(cap_channel_t *capdns, unsigned int expected) hints.ai_family = AF_INET6; syserr = getaddrinfo("freebsd.org", "25", hintsp, &ais); if (syserr != 0) { - failure |= GETADDRINFO_AF_INET6; fprintf(stderr, "Unable to issue [system] getaddrinfo() for AF_UNSPEC: %s\n", gai_strerror(syserr)); @@ -308,7 +302,6 @@ runtest(cap_channel_t *capdns, unsigned int expected) inet_pton(AF_INET, GOOGLE_DNS_IPV4, &ip4); hps = gethostbyaddr(&ip4, sizeof(ip4), AF_INET); if (hps == NULL) { - failure |= GETHOSTBYADDR_AF_INET; fprintf(stderr, "Unable to resolve %s.\n", GOOGLE_DNS_IPV4); } else { hpc = cap_gethostbyaddr(capdns, &ip4, sizeof(ip4), AF_INET); @@ -319,7 +312,6 @@ runtest(cap_channel_t *capdns, unsigned int expected) inet_pton(AF_INET6, GOOGLE_DNS_IPV6, &ip6); hps = gethostbyaddr(&ip6, sizeof(ip6), AF_INET6); if (hps == NULL) { - failure |= GETHOSTBYADDR_AF_INET6; fprintf(stderr, "Unable to resolve %s.\n", GOOGLE_DNS_IPV6); } else { hpc = cap_gethostbyaddr(capdns, &ip6, sizeof(ip6), AF_INET6); @@ -329,21 +321,6 @@ runtest(cap_channel_t *capdns, unsigned int expected) } } - /* - * If we had any failures, make sure that all lookups failed. If some - * succeeded and some failed, there's a problem with the test or the DNS - * and we should not fail silently. - */ - if (failure != 0) { - ATF_REQUIRE_MSG(failure == (GETHOSTBYNAME | - GETHOSTBYNAME2_AF_INET | GETHOSTBYNAME2_AF_INET6 | - GETADDRINFO_AF_UNSPEC | GETADDRINFO_AF_INET | - GETADDRINFO_AF_INET6 | - GETHOSTBYADDR_AF_INET | GETHOSTBYADDR_AF_INET6), - "expected all tests to fail, got 0x%x", failure); - atf_tc_skip( - "no name lookups succeeded, tests require Internet access"); - } ATF_REQUIRE_MSG(result == expected, "expected 0x%x, got 0x%x", expected, result); } @@ -367,6 +344,7 @@ cap_dns_init(void) ATF_TC(dns_no_limits); ATF_TC_HEAD(dns_no_limits, tc) { + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); } ATF_TC_BODY(dns_no_limits, tc) { @@ -386,6 +364,7 @@ ATF_TC_BODY(dns_no_limits, tc) ATF_TC(dns_all_limits); ATF_TC_HEAD(dns_all_limits, tc) { + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); } ATF_TC_BODY(dns_all_limits, tc) { @@ -417,6 +396,7 @@ ATF_TC_BODY(dns_all_limits, tc) ATF_TC(dns_name_limit); ATF_TC_HEAD(dns_name_limit, tc) { + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); } ATF_TC_BODY(dns_name_limit, tc) { @@ -448,6 +428,7 @@ ATF_TC_BODY(dns_name_limit, tc) ATF_TC(dns_addr_limit); ATF_TC_HEAD(dns_addr_limit, tc) { + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); } ATF_TC_BODY(dns_addr_limit, tc) { @@ -478,6 +459,7 @@ ATF_TC_BODY(dns_addr_limit, tc) ATF_TC(dns_inet_limit); ATF_TC_HEAD(dns_inet_limit, tc) { + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); } ATF_TC_BODY(dns_inet_limit, tc) { @@ -509,6 +491,7 @@ ATF_TC_BODY(dns_inet_limit, tc) ATF_TC(dns_inet6_limit); ATF_TC_HEAD(dns_inet6_limit, tc) { + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); } ATF_TC_BODY(dns_inet6_limit, tc) { @@ -540,6 +523,7 @@ ATF_TC_BODY(dns_inet6_limit, tc) ATF_TC(dns_name_inet_limit); ATF_TC_HEAD(dns_name_inet_limit, tc) { + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); } ATF_TC_BODY(dns_name_inet_limit, tc) { @@ -581,6 +565,7 @@ ATF_TC_BODY(dns_name_inet_limit, tc) ATF_TC(dns_name_inet6_limit); ATF_TC_HEAD(dns_name_inet6_limit, tc) { + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); } ATF_TC_BODY(dns_name_inet6_limit, tc) { @@ -622,6 +607,7 @@ ATF_TC_BODY(dns_name_inet6_limit, tc) ATF_TC(dns_addr_inet_limit); ATF_TC_HEAD(dns_addr_inet_limit, tc) { + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); } ATF_TC_BODY(dns_addr_inet_limit, tc) { @@ -662,6 +648,7 @@ ATF_TC_BODY(dns_addr_inet_limit, tc) ATF_TC(dns_addr_inet6_limit); ATF_TC_HEAD(dns_addr_inet6_limit, tc) { + atf_tc_set_md_var(tc, "require.config", "allow_network_access"); } ATF_TC_BODY(dns_addr_inet6_limit, tc) { diff --git a/lib/libcasper/services/cap_net/cap_net.c b/lib/libcasper/services/cap_net/cap_net.c index 40d18319ae28..5887fe3c407e 100644 --- a/lib/libcasper/services/cap_net/cap_net.c +++ b/lib/libcasper/services/cap_net/cap_net.c @@ -288,7 +288,7 @@ cap_getaddrinfo(cap_channel_t *chan, const char *hostname, const char *servname, const nvlist_t *nvlai; char nvlname[64]; nvlist_t *nvl; - int error, n; + int error, serrno, n; nvl = nvlist_create(0); nvlist_add_string(nvl, "cmd", "getaddrinfo"); @@ -311,7 +311,9 @@ cap_getaddrinfo(cap_channel_t *chan, const char *hostname, const char *servname, return (EAI_MEMORY); if (nvlist_get_number(nvl, "error") != 0) { error = (int)nvlist_get_number(nvl, "error"); + serrno = dnvlist_get_number(nvl, "errno", 0); nvlist_destroy(nvl); + errno = (error == EAI_SYSTEM) ? serrno : 0; return (error); } @@ -350,7 +352,7 @@ cap_getnameinfo(cap_channel_t *chan, const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) { nvlist_t *nvl; - int error; + int error, serrno; nvl = nvlist_create(0); nvlist_add_string(nvl, "cmd", "getnameinfo"); @@ -363,7 +365,9 @@ cap_getnameinfo(cap_channel_t *chan, const struct sockaddr *sa, socklen_t salen, return (EAI_MEMORY); if (nvlist_get_number(nvl, "error") != 0) { error = (int)nvlist_get_number(nvl, "error"); + serrno = dnvlist_get_number(nvl, "errno", 0); nvlist_destroy(nvl); + errno = (error == EAI_SYSTEM) ? serrno : 0; return (error); } @@ -858,19 +862,21 @@ net_getnameinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) char *host, *serv; size_t sabinsize, hostlen, servlen; socklen_t salen; - int error, flags; + int error, serrno, flags; const nvlist_t *funclimit; - if (!net_allowed_mode(limits, CAPNET_ADDR2NAME)) - return (ENOTCAPABLE); + host = serv = NULL; + if (!net_allowed_mode(limits, CAPNET_ADDR2NAME)) { + serrno = ENOTCAPABLE; + error = EAI_SYSTEM; + goto out; + } funclimit = NULL; if (limits != NULL) { funclimit = dnvlist_get_nvlist(limits, LIMIT_NV_ADDR2NAME, NULL); } - error = 0; - host = serv = NULL; memset(&sast, 0, sizeof(sast)); hostlen = (size_t)nvlist_get_number(nvlin, "hostlen"); @@ -897,7 +903,8 @@ net_getnameinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) goto out; } if (!net_allowed_bsaddr(funclimit, sabin, sabinsize)) { - error = ENOTCAPABLE; + serrno = ENOTCAPABLE; + error = EAI_SYSTEM; goto out; } @@ -913,7 +920,8 @@ net_getnameinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) } if (!net_allowed_family(funclimit, (int)sast.ss_family)) { - error = ENOTCAPABLE; + serrno = ENOTCAPABLE; + error = EAI_SYSTEM; goto out; } @@ -921,6 +929,7 @@ net_getnameinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) error = getnameinfo((struct sockaddr *)&sast, salen, host, hostlen, serv, servlen, flags); + serrno = errno; if (error != 0) goto out; @@ -932,6 +941,8 @@ out: if (error != 0) { free(host); free(serv); + if (error == EAI_SYSTEM) + nvlist_add_number(nvlout, "errno", serrno); } return (error); } @@ -961,12 +972,15 @@ net_getaddrinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) char nvlname[64]; nvlist_t *elem; unsigned int ii; - int error, family, n; + int error, serrno, family, n; const nvlist_t *funclimit; bool dnscache; - if (!net_allowed_mode(limits, CAPNET_NAME2ADDR)) - return (ENOTCAPABLE); + if (!net_allowed_mode(limits, CAPNET_NAME2ADDR)) { + serrno = ENOTCAPABLE; + error = EAI_SYSTEM; + goto out; + } dnscache = net_allowed_mode(limits, CAPNET_CONNECTDNS); funclimit = NULL; if (limits != NULL) { @@ -996,11 +1010,18 @@ net_getaddrinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) family = AF_UNSPEC; } - if (!net_allowed_family(funclimit, family)) - return (ENOTCAPABLE); - if (!net_allowed_hosts(funclimit, hostname, servname)) - return (ENOTCAPABLE); + if (!net_allowed_family(funclimit, family)) { + errno = ENOTCAPABLE; + error = EAI_SYSTEM; + goto out; + } + if (!net_allowed_hosts(funclimit, hostname, servname)) { + errno = ENOTCAPABLE; + error = EAI_SYSTEM; + goto out; + } error = getaddrinfo(hostname, servname, hintsp, &res); + serrno = errno; if (error != 0) { goto out; } @@ -1019,6 +1040,8 @@ net_getaddrinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) freeaddrinfo(res); error = 0; out: + if (error == EAI_SYSTEM) + nvlist_add_number(nvlout, "errno", serrno); return (error); } diff --git a/lib/libcasper/services/cap_net/cap_net.h b/lib/libcasper/services/cap_net/cap_net.h index 1e9a6021d240..75f936954199 100644 --- a/lib/libcasper/services/cap_net/cap_net.h +++ b/lib/libcasper/services/cap_net/cap_net.h @@ -93,18 +93,14 @@ struct hostent *cap_gethostbyaddr(cap_channel_t *chan, const void *addr, socklen_t len, int af); #else /* Capability functions. */ -#define cap_bind(chan, s, addr, addrlen) \ - bind(s, addr, addrlen) -#define cap_connect(chan, s, name, namelen) \ - connect(s, name, namelen) -#define cap_getaddrinfo(chan, hostname, servname, hints, res) \ - getaddrinfo(hostname, servname, hints, res) -#define cap_getnameinfo(chan, sa, salen, host, hostlen, serv, servlen, flags) \ - getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) +#define cap_bind(chan, ...) bind(__VA_ARGS__) +#define cap_connect(chan, ...) connect(__VA_ARGS__) +#define cap_getaddrinfo(chan, ...) getaddrinfo(__VA_ARGS__) +#define cap_getnameinfo(chan, ...) getnameinfo(__VA_ARGS__) /* Limit functions. */ -#define cap_net_limit_init(chan, mode) ((cap_net_limit_t *)malloc(8)) -#define cap_net_free(limit) free(limit) +#define cap_net_limit_init(chan, ...) ((cap_net_limit_t *)malloc(8)) +#define cap_net_free(...) free(__VA_ARGS__) static inline int cap_net_limit(cap_net_limit_t *limit) { @@ -155,9 +151,9 @@ cap_net_limit_bind(cap_net_limit_t *limit, } /* Deprecated functions. */ -#define cap_gethostbyname(chan, name) gethostbyname(name) -#define cap_gethostbyname2(chan, name, type) gethostbyname2(name, type) -#define cap_gethostbyaddr(chan, addr, len, type) gethostbyaddr(addr, len, type) +#define cap_gethostbyname(chan, ...) gethostbyname(__VA_ARGS__) +#define cap_gethostbyname2(chan, ...) gethostbyname2(__VA_ARGS__) +#define cap_gethostbyaddr(chan, ...) gethostbyaddr(__VA_ARGS__) #endif #endif /* !_CAP_NETWORK_H_ */ diff --git a/lib/libcom_err/Makefile b/lib/libcom_err/Makefile index 2bfd26bae968..f070fd534469 100644 --- a/lib/libcom_err/Makefile +++ b/lib/libcom_err/Makefile @@ -7,7 +7,7 @@ MAN= com_err.3 COM_ERRDIR= ${SRCTOP}/contrib/com_err CFLAGS+= -I${COM_ERRDIR} -LDFLAGS= -Wl,--no-undefined +LDFLAGS+= -Wl,--no-undefined VERSION_MAP= ${COM_ERRDIR}/version-script.map .include <bsd.lib.mk> diff --git a/lib/libcompiler_rt/Makefile.inc b/lib/libcompiler_rt/Makefile.inc index e2a2618232e1..57cfdee95541 100644 --- a/lib/libcompiler_rt/Makefile.inc +++ b/lib/libcompiler_rt/Makefile.inc @@ -208,7 +208,7 @@ SRCF+= trunctfsf2 .endif # These are already shipped by libc.a on some architectures. -.if ${MACHINE_CPUARCH} != "arm" && ${MACHINE_CPUARCH} != "riscv" +.if ${MACHINE_CPUARCH} != "riscv" SRCF+= adddf3 SRCF+= addsf3 SRCF+= divdf3 @@ -225,10 +225,8 @@ SRCF+= subsf3 SRCF+= truncdfsf2 .endif -.if ${MACHINE_CPUARCH} != "arm" SRCF+= comparedf2 SRCF+= comparesf2 -.endif # Helper to reduce complexity of _Float16 and __bf16 statements below. .if ${MACHINE_CPUARCH} == "aarch64" || \ @@ -274,10 +272,7 @@ CFLAGS+= -DEMIT_SYNC_ATOMICS .endif .for file in ${SRCF} -.if ${MACHINE_CPUARCH} == "arm" && (!defined(CPUTYPE) || ${CPUTYPE:M*soft*} == "") \ - && exists(${CRTSRC}/${CRTARCH}/${file}vfp.S) -SRCS+= ${file}vfp.S -. elif exists(${CRTSRC}/${CRTARCH}/${file}.S) +. if exists(${CRTSRC}/${CRTARCH}/${file}.S) SRCS+= ${file}.S . else SRCS+= ${file}.c @@ -285,7 +280,15 @@ SRCS+= ${file}.c .endfor .if ${MACHINE_CPUARCH} == "arm" +SRCS+= aeabi_cdcmp.S +SRCS+= aeabi_cdcmpeq_check_nan.c +SRCS+= aeabi_cfcmp.S +SRCS+= aeabi_cfcmpeq_check_nan.c +SRCS+= aeabi_dcmp.S SRCS+= aeabi_div0.c +SRCS+= aeabi_drsub.c +SRCS+= aeabi_fcmp.S +SRCS+= aeabi_frsub.c SRCS+= aeabi_idivmod.S SRCS+= aeabi_ldivmod.S SRCS+= aeabi_memcmp.S @@ -294,6 +297,7 @@ SRCS+= aeabi_memmove.S SRCS+= aeabi_memset.S SRCS+= aeabi_uidivmod.S SRCS+= aeabi_uldivmod.S + SRCS+= switch16.S SRCS+= switch32.S SRCS+= switch8.S diff --git a/lib/libcxxrt/Makefile b/lib/libcxxrt/Makefile index 7a683ba779f6..0f203b3a7cb1 100644 --- a/lib/libcxxrt/Makefile +++ b/lib/libcxxrt/Makefile @@ -23,7 +23,6 @@ SRCS+= typeinfo.cc WARNS?= 0 CFLAGS+= -isystem ${SRCDIR} -nostdinc++ -CXXSTD?= c++14 .if exists(Version.map.${MACHINE}) VERSION_MAP= ${.CURDIR}/Version.map.${MACHINE} diff --git a/lib/libedit/Makefile b/lib/libedit/Makefile index c307cd3e7880..f0254c1f42bc 100644 --- a/lib/libedit/Makefile +++ b/lib/libedit/Makefile @@ -8,7 +8,6 @@ EDITDIR= ${SRCTOP}/contrib/libedit SHLIB_MAJOR= 8 SHLIBDIR?= /lib -WARNS?= 3 LIB= edit LIBADD= tinfow diff --git a/lib/libefivar/efivar-dp-format.c b/lib/libefivar/efivar-dp-format.c index 3fa2833a7e7a..f2dcf1b91c01 100644 --- a/lib/libefivar/efivar-dp-format.c +++ b/lib/libefivar/efivar-dp-format.c @@ -28,7 +28,6 @@ * this file is taken from EDK2 and rototilled. */ -#include <sys/cdefs.h> #include <efivar.h> #include <stdio.h> #include <string.h> diff --git a/lib/libefivar/efivar-dp-parse.c b/lib/libefivar/efivar-dp-parse.c index 3382666730c4..51c134692f1e 100644 --- a/lib/libefivar/efivar-dp-parse.c +++ b/lib/libefivar/efivar-dp-parse.c @@ -28,7 +28,6 @@ * this file is taken from EDK2 and rototilled. */ -#include <sys/cdefs.h> #include <ctype.h> #include <efivar.h> #include <stdio.h> diff --git a/lib/libefivar/efivar.c b/lib/libefivar/efivar.c index fdcffc5403d6..c91bf5ea71bb 100644 --- a/lib/libefivar/efivar.c +++ b/lib/libefivar/efivar.c @@ -23,12 +23,12 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include <efivar.h> #include <sys/efiio.h> #include <sys/param.h> #include <errno.h> #include <fcntl.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -37,11 +37,11 @@ static int efi_fd = -2; -#define Z { 0, 0, 0, 0, 0, { 0 } } +#define Z { 0 } const efi_guid_t efi_guid_empty = Z; -static struct uuid_table guid_tbl [] = +static struct guid_table guid_tbl [] = { { "00000000-0000-0000-0000-000000000000", "zero", Z }, { "093e0fae-a6c4-4f50-9f1b-d41e2b89c19a", "sha512", Z }, @@ -75,32 +75,39 @@ static struct uuid_table guid_tbl [] = { "e2b36190-879b-4a3d-ad8d-f2e7bba32784", "rsa2048_sha256", Z }, { "ff3e5307-9fd0-48c9-85f1-8ad56c701e01", "sha384", Z }, { "f46ee6f4-4785-43a3-923d-7f786c3c8479", "lenovo_startup_interrupt", Z }, - { "ffffffff-ffff-ffff-ffff-ffffffffffff", "zzignore-this-guid", Z }, }; -#undef Z + +int +efi_str_to_guid(const char *s, efi_guid_t *guid) +{ + uint32_t status; + + /* knows efi_guid_t is binary compatible with uuid_t */ + uuid_from_string(s, (uuid_t *)guid, &status); + + return (status == uuid_s_ok ? 0 : -1); +} static void efi_guid_tbl_compile(void) { size_t i; - uint32_t status; - static int done = 0; + static bool done = false; + struct guid_table *ent; if (done) return; for (i = 0; i < nitems(guid_tbl); i++) { - uuid_from_string(guid_tbl[i].uuid_str, &guid_tbl[i].guid, - &status); - /* all f's is a bad version, so ignore that error */ - if (status != uuid_s_ok && status != uuid_s_bad_version) - fprintf(stderr, "Can't convert %s to a uuid for %s: %d\n", - guid_tbl[i].uuid_str, guid_tbl[i].name, (int)status); + ent = &guid_tbl[i]; + if (efi_str_to_guid(ent->uuid_str, &ent->guid) != 0) + fprintf(stderr, "Can't convert %s to a guid for %s\n", + ent->uuid_str, ent->name); } - done = 1; + done = true; } int -efi_known_guid(struct uuid_table **tbl) +efi_known_guid(struct guid_table **tbl) { *tbl = guid_tbl; @@ -121,7 +128,7 @@ efi_open_dev(void) } static void -efi_var_reset(struct efi_var_ioc *var) +efi_var_reset(struct efi_var_ioctl *var) { var->name = NULL; var->namesize = 0; @@ -162,7 +169,7 @@ int efi_get_variable(efi_guid_t guid, const char *name, uint8_t **data, size_t *data_size, uint32_t *attributes) { - struct efi_var_ioc var; + struct efi_var_ioctl var; int rv; static uint8_t buf[1024*32]; @@ -212,7 +219,7 @@ efi_get_variable_size(efi_guid_t guid, const char *name, int efi_get_next_variable_name(efi_guid_t **guid, char **name) { - struct efi_var_ioc var; + struct efi_var_ioctl var; int rv; static efi_char *buf; static size_t buflen = 256 * sizeof(efi_char); @@ -287,28 +294,23 @@ done: int efi_guid_cmp(const efi_guid_t *guid1, const efi_guid_t *guid2) { - uint32_t status; - - return uuid_compare(guid1, guid2, &status); + return (memcmp(guid1, guid2, sizeof(*guid1))); } int efi_guid_is_zero(const efi_guid_t *guid) { - uint32_t status; - - return uuid_is_nil(guid, &status); + return (memcmp(guid, &efi_guid_empty, sizeof(*guid)) == 0); } int efi_guid_to_name(efi_guid_t *guid, char **name) { size_t i; - uint32_t status; efi_guid_tbl_compile(); for (i = 0; i < nitems(guid_tbl); i++) { - if (uuid_equal(guid, &guid_tbl[i].guid, &status)) { + if (memcmp(guid, &guid_tbl[i].guid, sizeof(*guid)) == 0) { *name = strdup(guid_tbl[i].name); return (0); } @@ -332,8 +334,8 @@ efi_guid_to_str(const efi_guid_t *guid, char **sp) { uint32_t status; - /* knows efi_guid_t is a typedef of uuid_t */ - uuid_to_string(guid, sp, &status); + /* knows efi_guid_t is binary compatible with uuid_t */ + uuid_to_string((const uuid_t *)guid, sp, &status); return (status == uuid_s_ok ? 0 : -1); } @@ -357,7 +359,7 @@ int efi_set_variable(efi_guid_t guid, const char *name, uint8_t *data, size_t data_size, uint32_t attributes) { - struct efi_var_ioc var; + struct efi_var_ioctl var; int rv; if (efi_open_dev() == -1) @@ -379,17 +381,6 @@ errout: } int -efi_str_to_guid(const char *s, efi_guid_t *guid) -{ - uint32_t status; - - /* knows efi_guid_t is a typedef of uuid_t */ - uuid_from_string(s, guid, &status); - - return (status == uuid_s_ok ? 0 : -1); -} - -int efi_variables_supported(void) { diff --git a/lib/libefivar/efivar.h b/lib/libefivar/efivar.h index 7551205fda38..e159f4cccd3d 100644 --- a/lib/libefivar/efivar.h +++ b/lib/libefivar/efivar.h @@ -46,19 +46,14 @@ #endif -#ifndef _EFIVAR_EFI_GUID_T_DEF -#define _EFIVAR_EFI_GUID_T_DEF -typedef uuid_t efi_guid_t; -#endif - #if BYTE_ORDER == LITTLE_ENDIAN #define EFI_GUID(a, b, c, d, e0, e1, e2, e3, e4, e5) \ - ((efi_guid_t) {(a), (b), (c), (d) >> 8, (d) & 0xff, \ - { (e0), (e1), (e2), (e3), (e4), (e5) }}) + ((efi_guid_t) {(a), (b), (c), { (d) >> 8, (d) & 0xff, \ + (e0), (e1), (e2), (e3), (e4), (e5) }}) #else #define EFI_GUID(a, b, c, d, e0, e1, e2, e3, e4, e5) \ - ((efi_guid_t) {(a), (b), (c), (d) & 0xff, (d) >> 8, \ - { (e0), (e1), (e2), (e3), (e4), (e5) }}) + ((efi_guid_t) {(a), (b), (c), { (d) & 0xff, (d) >> 8, \ + (e0), (e1), (e2), (e3), (e4), (e5) }}) #endif #define EFI_GLOBAL_GUID EFI_GUID(0x8be4df61, 0x93ca, 0x11d2, 0xaa0d, \ @@ -85,14 +80,14 @@ int efi_str_to_guid(const char *s, efi_guid_t *guid); int efi_variables_supported(void); /* FreeBSD extensions */ -struct uuid_table +struct guid_table { const char *uuid_str; const char *name; efi_guid_t guid; }; -int efi_known_guid(struct uuid_table **); +int efi_known_guid(struct guid_table **); extern const efi_guid_t efi_guid_empty; diff --git a/lib/libefivar/uefi-dplib.h b/lib/libefivar/uefi-dplib.h index e801b5f26a81..6f76a9763a34 100644 --- a/lib/libefivar/uefi-dplib.h +++ b/lib/libefivar/uefi-dplib.h @@ -547,7 +547,7 @@ AllocateCopyPool(size_t l, const void *p) } static inline BOOLEAN -CompareGuid (const GUID *g1, const GUID *g2) +CompareGuid (const EFI_GUID *g1, const EFI_GUID *g2) { uint32_t ignored_status; @@ -578,7 +578,7 @@ StrHexToBytes(const char *str, size_t len, uint8_t *buf, size_t buflen) } static inline void -StrToGuid(const char *str, GUID *guid) +StrToGuid(const char *str, EFI_GUID *guid) { uint32_t status; @@ -599,7 +599,7 @@ WriteUnaligned64(void *ptr, uint64_t val) * Not to mention it's name.... Also, the error GUID is horrific. */ static inline const char * -guid_str(const GUID *g) +guid_str(const EFI_GUID *g) { static char buf[36 + 1]; char *str = NULL; @@ -614,7 +614,7 @@ guid_str(const GUID *g) free(str); return buf; } -#define G(x) guid_str((const GUID *)(const void *)x) +#define G(x) guid_str((const EFI_GUID *)(const void *)x) #endif #undef GLOBAL_REMOVE_IF_UNREFERENCED diff --git a/lib/libefivar/uefi-dputil.c b/lib/libefivar/uefi-dputil.c index 7969054e2ce2..6e8f3aeca2ce 100644 --- a/lib/libefivar/uefi-dputil.c +++ b/lib/libefivar/uefi-dputil.c @@ -28,7 +28,6 @@ * this file is taken from EDK2 and rototilled. */ -#include <sys/cdefs.h> #include <efivar.h> #include <limits.h> #include <stdio.h> diff --git a/lib/libexpat/expat_config.h b/lib/libexpat/expat_config.h index 2bb52a4baa03..748f75ee157d 100644 --- a/lib/libexpat/expat_config.h +++ b/lib/libexpat/expat_config.h @@ -89,7 +89,7 @@ #define PACKAGE_NAME "expat" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "expat 2.6.4" +#define PACKAGE_STRING "expat 2.7.1" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "expat" @@ -98,7 +98,7 @@ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "2.6.4" +#define PACKAGE_VERSION "2.7.1" /* Define to 1 if all of the C90 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for @@ -106,7 +106,7 @@ #define STDC_HEADERS 1 /* Version number of package */ -#define VERSION "2.6.4" +#define VERSION "2.7.1" /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ diff --git a/lib/libexpat/libbsdxml.3 b/lib/libexpat/libbsdxml.3 index 21c07d39e5e2..c91184840b70 100644 --- a/lib/libexpat/libbsdxml.3 +++ b/lib/libexpat/libbsdxml.3 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\"/ -.Dd December 8, 2024 +.Dd April 7, 2025 .Dt LIBBSDXML 3 .Os .Sh NAME @@ -34,7 +34,7 @@ .Sh DESCRIPTION The .Nm -library is a verbatim copy of the eXpat XML library version 2.6.4. +library is a verbatim copy of the eXpat XML library version 2.7.1. .Pp The .Nm diff --git a/lib/libgcc_eh/Makefile.inc b/lib/libgcc_eh/Makefile.inc index af59ee7aaa65..529ef7170485 100644 --- a/lib/libgcc_eh/Makefile.inc +++ b/lib/libgcc_eh/Makefile.inc @@ -38,7 +38,6 @@ CFLAGS+= -I${UNWINDINCDIR} CFLAGS+= -D_LIBUNWIND_IS_NATIVE_ONLY CFLAGS+= -D_LIBUNWIND_USE_FRAME_HEADER_CACHE CXXFLAGS+= -fno-rtti -CXXSTD?= c++11 STATIC_CXXFLAGS+= -fvisibility=hidden -fPIC # Probably need to just move this earlier or use CXXFLAGS .if ${MK_DIRDEPS_BUILD} == "yes" diff --git a/lib/libgcc_s/arm/Symbol.map b/lib/libgcc_s/arm/Symbol.map index 92b54761d810..ea0189eabaa0 100644 --- a/lib/libgcc_s/arm/Symbol.map +++ b/lib/libgcc_s/arm/Symbol.map @@ -2,6 +2,74 @@ */ GCC_3.5 { + __aeabi_cdcmple; + __aeabi_cdrcmple; + __aeabi_cfcmpeq; + __aeabi_cfcmple; + __aeabi_cfrcmple; + __aeabi_d2f; + __aeabi_d2h; +/* __aeabi_d2h_alt; */ + __aeabi_d2iz; + __aeabi_d2lz; + __aeabi_d2uiz; + __aeabi_d2ulz; + __aeabi_dadd; + __aeabi_dcmpeq; + __aeabi_dcmpge; + __aeabi_dcmpgt; + __aeabi_dcmple; + __aeabi_dcmplt; + __aeabi_dcmpun; + __aeabi_ddiv; + __aeabi_dmul; + __aeabi_dneg; + __aeabi_drsub; + __aeabi_dsub; + __aeabi_f2d; + __aeabi_f2h; +/* __aeabi_f2h_alt; */ + __aeabi_f2iz; + __aeabi_f2lz; + __aeabi_f2uiz; + __aeabi_f2ulz; + __aeabi_fadd; + __aeabi_fcmpeq; + __aeabi_fcmpge; + __aeabi_fcmpgt; + __aeabi_fcmple; + __aeabi_fcmplt; + __aeabi_fcmpun; + __aeabi_fdiv; + __aeabi_fmul; + __aeabi_fneg; + __aeabi_frsub; + __aeabi_fsub; + __aeabi_h2f; +/* __aeabi_h2f_alt; */ + __aeabi_i2d; + __aeabi_i2f; + __aeabi_idiv; + __aeabi_idiv0; + __aeabi_idivmod; + __aeabi_l2d; + __aeabi_l2f; + __aeabi_lasr; + __aeabi_lcmp; + __aeabi_ldiv0; + __aeabi_ldivmod; + __aeabi_llsl; + __aeabi_llsr; + __aeabi_lmul; + __aeabi_ui2d; + __aeabi_ui2f; + __aeabi_uidiv; + __aeabi_uidivmod; + __aeabi_ul2d; + __aeabi_ul2f; + __aeabi_ulcmp; + __aeabi_uldivmod; + _Unwind_Complete; _Unwind_VRS_Get; _Unwind_VRS_Set; diff --git a/lib/libifconfig/libifconfig.h b/lib/libifconfig/libifconfig.h index 8d5ca01b0ce6..fc835485a51e 100644 --- a/lib/libifconfig/libifconfig.h +++ b/lib/libifconfig/libifconfig.h @@ -29,6 +29,7 @@ #include <sys/types.h> #include <net/if.h> +#include <net/if_bridgevar.h> /* for ifbvlan_set_t */ #include <netinet/in.h> #include <netinet/ip_carp.h> @@ -64,6 +65,7 @@ struct lagg_reqport; struct ifconfig_bridge_status { struct ifbropreq *params; /**< current operational parameters */ struct ifbreq *members; /**< list of bridge members */ + ifbvlan_set_t *member_vlans; /**< bridge member vlan sets */ size_t members_count; /**< how many member interfaces */ uint32_t cache_size; /**< size of address cache */ uint32_t cache_lifetime; /**< address cache entry lifetime */ diff --git a/lib/libifconfig/libifconfig_bridge.c b/lib/libifconfig/libifconfig_bridge.c index 2a9bbc35858b..b4a920f488c5 100644 --- a/lib/libifconfig/libifconfig_bridge.c +++ b/lib/libifconfig/libifconfig_bridge.c @@ -66,40 +66,37 @@ ifconfig_bridge_get_bridge_status(ifconfig_handle_t *h, { struct ifbifconf members; struct ifbrparam cache_param; - struct _ifconfig_bridge_status *bridge; - char *buf; + struct _ifconfig_bridge_status *bridge = NULL; + char *buf = NULL; + members.ifbic_buf = NULL; *bridgep = NULL; bridge = calloc(1, sizeof(struct _ifconfig_bridge_status)); if (bridge == NULL) { h->error.errtype = OTHER; h->error.errcode = ENOMEM; - return (-1); + goto err; } bridge->inner.params = &bridge->params; if (ifconfig_bridge_ioctlwrap(h, name, BRDGGCACHE, &cache_param, sizeof(cache_param), false) != 0) { - free(bridge); - return (-1); + goto err; } bridge->inner.cache_size = cache_param.ifbrp_csize; if (ifconfig_bridge_ioctlwrap(h, name, BRDGGTO, &cache_param, sizeof(cache_param), false) != 0) { - free(bridge); - return (-1); + goto err; } bridge->inner.cache_lifetime = cache_param.ifbrp_ctime; if (ifconfig_bridge_ioctlwrap(h, name, BRDGPARAM, &bridge->params, sizeof(bridge->params), false) != 0) { - free(bridge); - return (-1); + goto err; } - members.ifbic_buf = NULL; for (size_t len = 8192; (buf = realloc(members.ifbic_buf, len)) != NULL; len *= 2) { @@ -107,27 +104,52 @@ ifconfig_bridge_get_bridge_status(ifconfig_handle_t *h, members.ifbic_len = len; if (ifconfig_bridge_ioctlwrap(h, name, BRDGGIFS, &members, sizeof(members), false) != 0) { - free(buf); - free(bridge); - return (-1); + goto err; } if ((members.ifbic_len + sizeof(*members.ifbic_req)) < len) break; } if (buf == NULL) { - free(members.ifbic_buf); - free(bridge); h->error.errtype = OTHER; h->error.errcode = ENOMEM; - return (-1); + goto err; } bridge->inner.members = members.ifbic_req; bridge->inner.members_count = members.ifbic_len / sizeof(*members.ifbic_req); + bridge->inner.member_vlans = calloc(bridge->inner.members_count, + sizeof(ifbvlan_set_t)); + if (bridge->inner.member_vlans == NULL) { + h->error.errtype = OTHER; + h->error.errcode = ENOMEM; + goto err; + } + for (size_t i = 0; i < bridge->inner.members_count; ++i) { + struct ifbif_vlan_req vreq; + memset(&vreq, 0, sizeof(vreq)); + strlcpy(vreq.bv_ifname, bridge->inner.members[i].ifbr_ifsname, + sizeof(vreq.bv_ifname)); + + if (ifconfig_bridge_ioctlwrap(h, name, BRDGGIFVLANSET, &vreq, + sizeof(vreq), false) != 0) { + goto err; + } + + __BIT_COPY(BRVLAN_SETSIZE, &vreq.bv_set, + &bridge->inner.member_vlans[i]); + } + *bridgep = &bridge->inner; return (0); + +err: + free(members.ifbic_buf); + if (bridge) + free(bridge->inner.member_vlans); + free(bridge); + return (-1); } void diff --git a/lib/libifconfig/libifconfig_sfp.c b/lib/libifconfig/libifconfig_sfp.c index 8292135d3e47..1ba6d231a992 100644 --- a/lib/libifconfig/libifconfig_sfp.c +++ b/lib/libifconfig/libifconfig_sfp.c @@ -24,6 +24,8 @@ * SUCH DAMAGE. */ +#define _WANT_SFF_8024_ID + #include <sys/types.h> #include <sys/param.h> #include <sys/ioctl.h> diff --git a/lib/libiscsiutil/libiscsiutil.h b/lib/libiscsiutil/libiscsiutil.h index c091c1d9753a..b50afa1c9409 100644 --- a/lib/libiscsiutil/libiscsiutil.h +++ b/lib/libiscsiutil/libiscsiutil.h @@ -95,6 +95,8 @@ struct rchap { size_t rchap_challenge_len; }; +__BEGIN_DECLS + struct chap *chap_new(void); char *chap_get_id(const struct chap *chap); char *chap_get_challenge(const struct chap *chap); @@ -174,4 +176,6 @@ void log_debugx(const char *, ...) __printflike(1, 2); char *checked_strdup(const char *); +__END_DECLS + #endif /* !__LIBISCSIUTIL_H__ */ diff --git a/lib/libjail/jail.c b/lib/libjail/jail.c index 8e5b420d677b..30282e67866c 100644 --- a/lib/libjail/jail.c +++ b/lib/libjail/jail.c @@ -59,6 +59,7 @@ static int jailparam_type(struct jailparam *jp); static int kldload_param(const char *name); static char *noname(const char *name); static char *nononame(const char *name); +static char *kvname(const char *name); char jail_errmsg[JAIL_ERRMSGLEN]; @@ -521,6 +522,11 @@ jailparam_set(struct jailparam *jp, unsigned njp, int flags) jiov[i - 1].iov_len = strlen(nname) + 1; } + } else if (jp[j].jp_flags & JP_KEYVALUE && + jp[j].jp_value == NULL) { + /* No value means key removal. */ + jiov[i].iov_base = NULL; + jiov[i].iov_len = 0; } else { /* * Try to fill in missing values with an empty string. @@ -907,22 +913,41 @@ jailparam_type(struct jailparam *jp) * the "no" counterpart to a boolean. */ nname = nononame(name); - if (nname == NULL) { - unknown_parameter: - snprintf(jail_errmsg, JAIL_ERRMSGLEN, - "unknown parameter: %s", jp->jp_name); - errno = ENOENT; - return (-1); + if (nname != NULL) { + snprintf(desc.s, sizeof(desc.s), SJPARAM ".%s", nname); + miblen = sizeof(mib) - 2 * sizeof(int); + if (sysctl(mib, 2, mib + 2, &miblen, desc.s, + strlen(desc.s)) >= 0) { + name = alloca(strlen(nname) + 1); + strcpy(name, nname); + free(nname); + jp->jp_flags |= JP_NOBOOL; + goto mib_desc; + } + free(nname); } - name = alloca(strlen(nname) + 1); - strcpy(name, nname); - free(nname); - snprintf(desc.s, sizeof(desc.s), SJPARAM ".%s", name); - miblen = sizeof(mib) - 2 * sizeof(int); - if (sysctl(mib, 2, mib + 2, &miblen, desc.s, - strlen(desc.s)) < 0) - goto unknown_parameter; - jp->jp_flags |= JP_NOBOOL; + /* + * It might be an assumed sub-node of a fmt='A,keyvalue' sysctl. + */ + nname = kvname(name); + if (nname != NULL) { + snprintf(desc.s, sizeof(desc.s), SJPARAM ".%s", nname); + miblen = sizeof(mib) - 2 * sizeof(int); + if (sysctl(mib, 2, mib + 2, &miblen, desc.s, + strlen(desc.s)) >= 0) { + name = alloca(strlen(nname) + 1); + strcpy(name, nname); + free(nname); + jp->jp_flags |= JP_KEYVALUE; + goto mib_desc; + } + free(nname); + } +unknown_parameter: + snprintf(jail_errmsg, JAIL_ERRMSGLEN, + "unknown parameter: %s", jp->jp_name); + errno = ENOENT; + return (-1); } mib_desc: mib[1] = 4; @@ -943,6 +968,12 @@ jailparam_type(struct jailparam *jp) else if ((desc.i & CTLTYPE) != CTLTYPE_NODE) goto unknown_parameter; } + /* Make sure it is a valid keyvalue param. */ + if (jp->jp_flags & JP_KEYVALUE) { + if ((desc.i & CTLTYPE) != CTLTYPE_STRING || + strcmp(desc.s, "A,keyvalue") != 0) + goto unknown_parameter; + } /* See if this is an array type. */ p = strchr(desc.s, '\0'); isarray = 0; @@ -1119,3 +1150,26 @@ nononame(const char *name) strcpy(nname, name + 2); return (nname); } + +static char * +kvname(const char *name) +{ + const char *p; + char *kvname; + size_t len; + + p = strchr(name, '.'); + if (p == NULL) + return (NULL); + + len = p - name; + kvname = malloc(len + 1); + if (kvname == NULL) { + strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN); + return (NULL); + } + strncpy(kvname, name, len); + kvname[len] = '\0'; + + return (kvname); +} diff --git a/lib/libjail/jail.h b/lib/libjail/jail.h index 27f07cd98802..6ce79b1b0528 100644 --- a/lib/libjail/jail.h +++ b/lib/libjail/jail.h @@ -33,6 +33,7 @@ #define JP_BOOL 0x02 #define JP_NOBOOL 0x04 #define JP_JAILSYS 0x08 +#define JP_KEYVALUE 0x10 #define JAIL_ERRMSGLEN 1024 diff --git a/lib/libkvm/kvm_amd64.c b/lib/libkvm/kvm_amd64.c index e3640cf12243..acc7ac017a3c 100644 --- a/lib/libkvm/kvm_amd64.c +++ b/lib/libkvm/kvm_amd64.c @@ -109,8 +109,9 @@ _amd64_initvtop(kvm_t *kd) { struct kvm_nlist nl[2]; amd64_physaddr_t pa; - kvaddr_t kernbase; + kvaddr_t kernbase, kernphys; amd64_pml4e_t *PML4; + int found = 0; kd->vmst = (struct vmstate *)_kvm_malloc(kd, sizeof(*kd->vmst)); if (kd->vmst == NULL) { @@ -123,16 +124,43 @@ _amd64_initvtop(kvm_t *kd) if (_kvm_read_core_phdrs(kd, &kd->vmst->phnum, &kd->vmst->phdr) == -1) return (-1); + + for (size_t i = 0; i < kd->vmst->phnum; i++) { + if (kd->vmst->phdr[i].p_type == PT_DUMP_DELTA) { + /* Account for the 2M hole at KERNBASE. */ + kernphys = kd->vmst->phdr[i].p_paddr - + kd->vmst->phdr[i].p_align; + kernbase = kd->vmst->phdr[i].p_vaddr; + + found = 1; + break; + } + } } - nl[0].n_name = "kernbase"; - nl[1].n_name = 0; + if (found == 0) { + nl[0].n_name = "kernbase"; + nl[1].n_name = 0; - if (kvm_nlist2(kd, nl) != 0) { - _kvm_err(kd, kd->program, "bad namelist - no kernbase"); - return (-1); + if (kvm_nlist2(kd, nl) != 0) { + _kvm_err(kd, kd->program, "bad namelist - no kernbase"); + return (-1); + } + + nl[0].n_name = "kernphys"; + nl[1].n_name = 0; + + /* XXX + * Relocatable kernels can still be loaded at 2M. + */ + if (kvm_nlist2(kd, nl) != 1) { + _kvm_err(kd, kd->program, "cannot determine kernphys"); + return (-1); + } + + kernphys = 0; + kernbase = nl[0].n_value; } - kernbase = nl[0].n_value; nl[0].n_name = "KPML4phys"; nl[1].n_name = 0; @@ -141,8 +169,8 @@ _amd64_initvtop(kvm_t *kd) _kvm_err(kd, kd->program, "bad namelist - no KPML4phys"); return (-1); } - if (kvm_read2(kd, (nl[0].n_value - kernbase), &pa, sizeof(pa)) != - sizeof(pa)) { + if (kvm_read2(kd, (nl[0].n_value - kernbase + kernphys), &pa, + sizeof(pa)) != sizeof(pa)) { _kvm_err(kd, kd->program, "cannot read KPML4phys"); return (-1); } diff --git a/lib/libkvm/kvm_open.3 b/lib/libkvm/kvm_open.3 index a7e428748215..9a32719d537b 100644 --- a/lib/libkvm/kvm_open.3 +++ b/lib/libkvm/kvm_open.3 @@ -29,7 +29,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 20, 2017 +.Dd June 22, 2025 .Dt KVM_OPEN 3 .Os .Sh NAME @@ -245,7 +245,20 @@ The value passed via was .Dv NULL . .El +.Sh NOTE +Full memory dumps taken on 13.x (excluding 13.0) and 14.x amd64 kernels +will cause both +.Fn kvm_open +and +.Fn kvm_open2 +to fail since they do not provide sufficient information to figure out +where in physical memory the kernel was loaded. +Full memory dumps have to be explicitly enabled by setting the +.Va debug.minidump +.Xr sysctl 8 +to 0. .Sh SEE ALSO +.Xr dumpon 8 , .Xr close 2 , .Xr open 2 , .Xr kvm 3 , diff --git a/lib/liblutok/Makefile b/lib/liblutok/Makefile index abb6ecd13ad4..08737afbb61a 100644 --- a/lib/liblutok/Makefile +++ b/lib/liblutok/Makefile @@ -18,8 +18,4 @@ CFLAGS+= -I${SRCTOP}/contrib/lutok/include \ WARNS?= 3 SHLIB_MAJOR= 0 -# lutok uses auto_ptr -CFLAGS+= -Wno-deprecated-declarations -CXXSTD= c++11 - .include <bsd.lib.mk> diff --git a/lib/liblzma/Makefile b/lib/liblzma/Makefile index 9f8ac443a8fc..27e0521f5884 100644 --- a/lib/liblzma/Makefile +++ b/lib/liblzma/Makefile @@ -80,16 +80,13 @@ SRCS+= common.c \ .PATH: ${LZMADIR}/check -SRCS+= check.c \ - crc32_table.c \ - crc64_table.c +SRCS+= check.c \ + crc32_fast.c \ + crc64_fast.c .if defined(MACHINE_ARCH) && ${MACHINE_ARCH} == "i386" SRCS+= crc32_x86.S \ crc64_x86.S ACFLAGS+= -Wa,--noexecstack -.else -SRCS+= crc32_fast.c \ - crc64_fast.c .endif .PATH: ${LZMADIR}/lz diff --git a/lib/liblzma/Symbol.map b/lib/liblzma/Symbol.map index 938b6191b4f4..0976e26a3c8d 100644 --- a/lib/liblzma/Symbol.map +++ b/lib/liblzma/Symbol.map @@ -118,6 +118,15 @@ XZ_5.6 { lzma_mt_block_size; }; +XZ_5.8 { + lzma_bcj_arm64_encode; + lzma_bcj_arm64_decode; + lzma_bcj_riscv_encode; + lzma_bcj_riscv_decode; + lzma_bcj_x86_encode; + lzma_bcj_x86_decode; +}; + XZprivate_1.0 { lzma_alloc; lzma_alloc_zero; diff --git a/lib/liblzma/Versions.def b/lib/liblzma/Versions.def index 25064d9d50e7..555ef25c8801 100644 --- a/lib/liblzma/Versions.def +++ b/lib/liblzma/Versions.def @@ -11,6 +11,9 @@ XZ_5.4 { XZ_5.6 { } XZ_5.4; -XZprivate_1.0 { +XZ_5.8 { } XZ_5.6; +XZprivate_1.0 { +} XZ_5.8; + diff --git a/lib/liblzma/config.h b/lib/liblzma/config.h index 3e51b0b92463..963d08c93e7a 100644 --- a/lib/liblzma/config.h +++ b/lib/liblzma/config.h @@ -68,6 +68,12 @@ /* Define to 1 if you have the <cpuid.h> header file. */ #define HAVE_CPUID_H 1 +/* Define to 1 if the 32-bit x86 CRC assembly files are used. */ +/* FreeBSD - only enabled for i386 */ +#if defined(__FreeBSD__) && defined(__i386__) +#define HAVE_CRC_X86_ASM 1 +#endif + /* Define if the GNU dcgettext() function is already present or preinstalled. */ /* FreeBSD - disabled intentionally */ @@ -193,6 +199,9 @@ */ /* #undef HAVE_LINUX_LANDLOCK */ +/* Define to 1 if 64-bit LoongArch CRC32 instructions are supported. */ +/* #undef HAVE_LOONGARCH_CRC32 */ + /* Define to 1 if .lz (lzip) decompression support is enabled. */ #define HAVE_LZIP_DECODER 1 @@ -335,6 +344,9 @@ /* Define to 1 if you have the 'utimes' function. */ /* #undef HAVE_UTIMES */ +/* Define to 1 if you have the 'vasprintf' function. */ +#define HAVE_VASPRINTF 1 + /* Define to 1 or 0, depending whether the compiler supports simple visibility declarations. */ #define HAVE_VISIBILITY 1 @@ -391,7 +403,7 @@ #define PACKAGE_NAME "XZ Utils" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "XZ Utils 5.6.3" +#define PACKAGE_STRING "XZ Utils 5.8.1" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "xz" @@ -400,7 +412,7 @@ #define PACKAGE_URL "https://tukaani.org/xz/" /* Define to the version of this package. */ -#define PACKAGE_VERSION "5.6.3" +#define PACKAGE_VERSION "5.8.1" /* Define to necessary symbol if this constant uses a non-standard name on your system. */ @@ -565,7 +577,7 @@ /* Version number of package */ -#define VERSION "5.6.3" +#define VERSION "5.8.1" /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ diff --git a/lib/libmd/Makefile b/lib/libmd/Makefile index d8c32063d6ce..547a134fc440 100644 --- a/lib/libmd/Makefile +++ b/lib/libmd/Makefile @@ -117,9 +117,12 @@ USE_ASM_SOURCES:=0 .endif .if ${USE_ASM_SOURCES} != 0 -.if exists(${MACHINE_ARCH}/sha.S) -SRCS+= sha.S +.if exists(${MACHINE_ARCH}/sha1block.S) +SRCS+= sha1block.S CFLAGS+= -DSHA1_ASM +.if exists(${MACHINE_ARCH}/sha1dispatch.c) +SRCS+= sha1dispatch.c +.endif .endif .if exists(${MACHINE_ARCH}/rmd160.S) SRCS+= rmd160.S @@ -135,7 +138,7 @@ CFLAGS+= -DSKEIN_ASM -DSKEIN_USE_ASM=1792 # list of block functions to replace w # the assembly vs C versions, and skein_block needs to be rebuilt if it changes. skein_block.o skein_block.pico: Makefile .endif -.if exists(${MACHINE_ARCH}/sha.S) || exists(${MACHINE_ARCH}/rmd160.S) || exists(${MACHINE_ARCH}/skein_block_asm.S) +.if exists(${MACHINE_ARCH}/rmd160.S) || exists(${MACHINE_ARCH}/skein_block_asm.S) ACFLAGS+= -DELF -Wa,--noexecstack .endif .if ${MACHINE_CPUARCH} == "aarch64" diff --git a/lib/libmd/aarch64/sha1block.S b/lib/libmd/aarch64/sha1block.S new file mode 100644 index 000000000000..56a0297efadd --- /dev/null +++ b/lib/libmd/aarch64/sha1block.S @@ -0,0 +1,490 @@ +/*- + * Copyright (c) 2024 Robert Clausecker <fuz@freebsd.org> + * + * SPDX-License-Identifier: BSD-2-Clause + * + * sha1block_sha1 implementation based on sha1-arm.c, + * written and placed in public domain by Jeffrey Walton + * based on code from ARM, and by Johannes Schneiders, Skip + * Hovsmith and Barry O'Rourke for the mbedTLS project. + */ + +#include <machine/asm.h> + +/* + * Scalar SHA1 implementation. + * + * Due to the ample register file available on AArch64, the w array is + * kept entirely in registers. The saved a-e variables are instead kept + * in memory as we don't have that much memory. + */ + + // sha1block(SHA1_CTX, buf, len) +ENTRY(_libmd_sha1block_scalar) +ctx .req x0 +buf .req x1 +len .req x2 +w .req sp +a .req w3 +b .req w4 +c .req w5 +d .req w6 +e .req w7 +k .req w8 +f .req w9 +tmp .req w10 +w_0 .req w11 +w_1 .req w12 +w_2 .req w13 +w_3 .req w14 +w_4 .req w15 +w_5 .req w16 +w_6 .req w17 +// w18 is the platform register +w_7 .req w19 +w_8 .req w20 +w_9 .req w21 +w_10 .req w22 +w_11 .req w23 +w_12 .req w24 +w_13 .req w25 +w_14 .req w26 +w_15 .req w27 + +.macro shuffle w_i, w_i3, w_i8, w_i14 + eor \w_i, \w_i, \w_i3 + eor tmp, \w_i8, \w_i14 + eor \w_i, \w_i, tmp // w[i-16] ^ w[i-14] ^ w[i-8] ^ w[i-3] + ror \w_i, \w_i, #31 // w[i] = ... ror #31 +.endm + +.macro func1 a, b, c, d, e + and f, \c, \b + bic tmp, \d, \b + orr f, f, tmp +.endm + +.macro func2 a, b, c, d, e + eor f, \b, \c + eor f, f, \d +.endm + +.macro func3 a, b, c, d, e + eor tmp, \b, \c + and f, \b, \c + and tmp, tmp, \d + orr f, f, tmp +.endm + +.macro func4 a, b, c, d, e + func2 \a, \b, \c, \d, \e +.endm + +.macro mix a, b, c, d, e, w_i + ror \b, \b, #2 + ror tmp, \a, #27 + add \e, \e, \w_i + add tmp, tmp, k + add \e, \e, f + add \e, \e, tmp // (a ror 27) + e + f + k + w[i] +.endm + +.macro round1 a, b, c, d, e, w_i + func1 \a, \b, \c, \d, \e + rev \w_i, \w_i + mix \a, \b, \c, \d, \e, \w_i +.endm + +.macro round func, a, b, c, d, e, w_i, w_i3, w_i8, w_i14 + shuffle \w_i, \w_i3, \w_i8, \w_i14 + \func \a, \b, \c, \d, \e + mix \a, \b, \c, \d, \e, \w_i +.endm + +.macro round1x a, b, c, d, e, w_i, w_i3, w_i8, w_i14 + round func1, \a, \b, \c, \d, \e, \w_i, \w_i3, \w_i8, \w_i14 +.endm + +.macro round2 a, b, c, d, e, w_i, w_i3, w_i8, w_i14 + round func2, \a, \b, \c, \d, \e, \w_i, \w_i3, \w_i8, \w_i14 +.endm + +.macro round3 a, b, c, d, e, w_i, w_i3, w_i8, w_i14 + round func3, \a, \b, \c, \d, \e, \w_i, \w_i3, \w_i8, \w_i14 +.endm + +.macro round4 a, b, c, d, e, w_i, w_i3, w_i8, w_i14 + round func4, \a, \b, \c, \d, \e, \w_i, \w_i3, \w_i8, \w_i14 +.endm + + ands len, len, #~63 // take length in multiples of block length + beq 1f // bail out if input empty + + sub sp, sp, #24+9*8 // allocate stack space + str x19, [sp, #24+0*8] + stp x20, x21, [sp, #24+1*8] + stp x22, x23, [sp, #24+3*8] + stp x24, x25, [sp, #24+5*8] + stp x26, x27, [sp, #24+7*8] + + ldp a, b, [ctx, #0] // load SHA1 state from context + ldp c, d, [ctx, #8] + ldr e, [ctx, #16] + +0: stp a, b, [sp, #0] // save old SHA1 state + stp c, d, [sp, #8] + str e, [sp, #16] + + movz k, #0x7999 // round constant 1 + movk k, #0x5a82, lsl #16 + + ldp w_0, w_1, [buf, #0*4] + round1 a, b, c, d, e, w_0 + round1 e, a, b, c, d, w_1 + + ldp w_2, w_3, [buf, #2*4] + round1 d, e, a, b, c, w_2 + round1 c, d, e, a, b, w_3 + + ldp w_4, w_5, [buf, #4*4] + round1 b, c, d, e, a, w_4 + round1 a, b, c, d, e, w_5 + + ldp w_6, w_7, [buf, #6*4] + round1 e, a, b, c, d, w_6 + round1 d, e, a, b, c, w_7 + + ldp w_8, w_9, [buf, #8*4] + round1 c, d, e, a, b, w_8 + round1 b, c, d, e, a, w_9 + + ldp w_10, w_11, [buf, #10*4] + round1 a, b, c, d, e, w_10 + round1 e, a, b, c, d, w_11 + + ldp w_12, w_13, [buf, #12*4] + round1 d, e, a, b, c, w_12 + round1 c, d, e, a, b, w_13 + + ldp w_14, w_15, [buf, #14*4] + round1 b, c, d, e, a, w_14 + round1 a, b, c, d, e, w_15 + + round1x e, a, b, c, d, w_0, w_13, w_8, w_2 + round1x d, e, a, b, c, w_1, w_14, w_9, w_3 + round1x c, d, e, a, b, w_2, w_15, w_10, w_4 + round1x b, c, d, e, a, w_3, w_0, w_11, w_5 + + movz k, #0xeba1 // round constant 2 + movk k, #0x6ed9, lsl #16 + + round2 a, b, c, d, e, w_4, w_1, w_12, w_6 + round2 e, a, b, c, d, w_5, w_2, w_13, w_7 + round2 d, e, a, b, c, w_6, w_3, w_14, w_8 + round2 c, d, e, a, b, w_7, w_4, w_15, w_9 + round2 b, c, d, e, a, w_8, w_5, w_0, w_10 + + round2 a, b, c, d, e, w_9, w_6, w_1, w_11 + round2 e, a, b, c, d, w_10, w_7, w_2, w_12 + round2 d, e, a, b, c, w_11, w_8, w_3, w_13 + round2 c, d, e, a, b, w_12, w_9, w_4, w_14 + round2 b, c, d, e, a, w_13, w_10, w_5, w_15 + + round2 a, b, c, d, e, w_14, w_11, w_6, w_0 + round2 e, a, b, c, d, w_15, w_12, w_7, w_1 + round2 d, e, a, b, c, w_0, w_13, w_8, w_2 + round2 c, d, e, a, b, w_1, w_14, w_9, w_3 + round2 b, c, d, e, a, w_2, w_15, w_10, w_4 + + round2 a, b, c, d, e, w_3, w_0, w_11, w_5 + round2 e, a, b, c, d, w_4, w_1, w_12, w_6 + round2 d, e, a, b, c, w_5, w_2, w_13, w_7 + round2 c, d, e, a, b, w_6, w_3, w_14, w_8 + round2 b, c, d, e, a, w_7, w_4, w_15, w_9 + + movz k, #0xbcdc // round constant 3 + movk k, #0x8f1b, lsl #16 + + round3 a, b, c, d, e, w_8, w_5, w_0, w_10 + round3 e, a, b, c, d, w_9, w_6, w_1, w_11 + round3 d, e, a, b, c, w_10, w_7, w_2, w_12 + round3 c, d, e, a, b, w_11, w_8, w_3, w_13 + round3 b, c, d, e, a, w_12, w_9, w_4, w_14 + + round3 a, b, c, d, e, w_13, w_10, w_5, w_15 + round3 e, a, b, c, d, w_14, w_11, w_6, w_0 + round3 d, e, a, b, c, w_15, w_12, w_7, w_1 + round3 c, d, e, a, b, w_0, w_13, w_8, w_2 + round3 b, c, d, e, a, w_1, w_14, w_9, w_3 + + round3 a, b, c, d, e, w_2, w_15, w_10, w_4 + round3 e, a, b, c, d, w_3, w_0, w_11, w_5 + round3 d, e, a, b, c, w_4, w_1, w_12, w_6 + round3 c, d, e, a, b, w_5, w_2, w_13, w_7 + round3 b, c, d, e, a, w_6, w_3, w_14, w_8 + + round3 a, b, c, d, e, w_7, w_4, w_15, w_9 + round3 e, a, b, c, d, w_8, w_5, w_0, w_10 + round3 d, e, a, b, c, w_9, w_6, w_1, w_11 + round3 c, d, e, a, b, w_10, w_7, w_2, w_12 + round3 b, c, d, e, a, w_11, w_8, w_3, w_13 + + movz k, #0xc1d6 // round constant 4 + movk k, #0xca62, lsl #16 + + round4 a, b, c, d, e, w_12, w_9, w_4, w_14 + round4 e, a, b, c, d, w_13, w_10, w_5, w_15 + round4 d, e, a, b, c, w_14, w_11, w_6, w_0 + round4 c, d, e, a, b, w_15, w_12, w_7, w_1 + round4 b, c, d, e, a, w_0, w_13, w_8, w_2 + + round4 a, b, c, d, e, w_1, w_14, w_9, w_3 + round4 e, a, b, c, d, w_2, w_15, w_10, w_4 + round4 d, e, a, b, c, w_3, w_0, w_11, w_5 + round4 c, d, e, a, b, w_4, w_1, w_12, w_6 + round4 b, c, d, e, a, w_5, w_2, w_13, w_7 + + round4 a, b, c, d, e, w_6, w_3, w_14, w_8 + round4 e, a, b, c, d, w_7, w_4, w_15, w_9 + round4 d, e, a, b, c, w_8, w_5, w_0, w_10 + round4 c, d, e, a, b, w_9, w_6, w_1, w_11 + round4 b, c, d, e, a, w_10, w_7, w_2, w_12 + + round4 a, b, c, d, e, w_11, w_8, w_3, w_13 + round4 e, a, b, c, d, w_12, w_9, w_4, w_14 + round4 d, e, a, b, c, w_13, w_10, w_5, w_15 + round4 c, d, e, a, b, w_14, w_11, w_6, w_0 + round4 b, c, d, e, a, w_15, w_12, w_7, w_1 + + ldp w_0, w_1, [sp, #0] // reload saved SHA1 state + ldp w_2, w_3, [sp, #8] + ldr w_4, [sp, #16] + + add a, a, w_0 + add b, b, w_1 + add c, c, w_2 + add d, d, w_3 + add e, e, w_4 + + add buf, buf, #64 + subs len, len, #64 + bhi 0b + + stp a, b, [ctx, #0] // write updated SHA1 state + stp c, d, [ctx, #8] + str e, [ctx, #16] + + ldr x19, [sp, #24+0*8] + ldp x20, x21, [sp, #24+1*8] + ldp x22, x23, [sp, #24+3*8] + ldp x24, x25, [sp, #24+5*8] + ldp x26, x27, [sp, #24+7*8] + add sp, sp, #24+9*8 + +1: ret +END(_libmd_sha1block_scalar) + +/* + * SHA1 implementation using the SHA1 instruction set extension. + */ + + .arch_extension sha2 + + // sha1block(SHA1_CTX, buf, len) +ENTRY(_libmd_sha1block_sha1) + /* ctx, buf, len: same as for sha1block_scalar */ +kaddr .req x3 +abcd .req v0 +abcd_q .req q0 // alias for use with scalar instructions +abcd_s .req s0 +e0 .req s1 +e0_v .req v1 +e1 .req s2 +abcd_saved .req v3 +e0_saved .req v4 +tmp0 .req v5 +tmp1 .req v6 +msg0 .req v16 +msg1 .req v17 +msg2 .req v18 +msg3 .req v19 +k0 .req v20 +k1 .req v21 +k2 .req v22 +k3 .req v23 + + ands len, len, #~63 // take length in multiples of block length + beq 1f // bail out if input empty + + ldr abcd_q, [ctx, #0] + ldr e0, [ctx, #16] + + adrp kaddr, k1234 + add kaddr, kaddr, #:lo12:k1234 + ld4r {k0.4s, k1.4s, k2.4s, k3.4s}, [kaddr] + +0: mov abcd_saved.16b, abcd.16b + mov e0_saved.16b, e0_v.16b + + ld1 {msg0.4s, msg1.4s, msg2.4s, msg3.4s}, [buf], #64 + rev32 msg0.16b, msg0.16b + rev32 msg1.16b, msg1.16b + rev32 msg2.16b, msg2.16b + rev32 msg3.16b, msg3.16b + + add tmp0.4s, msg0.4s, k0.4s + add tmp1.4s, msg1.4s, k0.4s + + /* rounds 0--3 */ + sha1h e1, abcd_s + sha1c abcd_q, e0, tmp0.4s + add tmp0.4s, msg2.4s, k0.4s + sha1su0 msg0.4s, msg1.4s, msg2.4s + + /* rounds 4--7 */ + sha1h e0, abcd_s + sha1c abcd_q, e1, tmp1.4s + add tmp1.4s, msg3.4s, k0.4s + sha1su1 msg0.4s, msg3.4s + sha1su0 msg1.4s, msg2.4s, msg3.4s + + /* rounds 8--11 */ + sha1h e1, abcd_s + sha1c abcd_q, e0, tmp0.4s + add tmp0.4s, msg0.4s, k0.4s + sha1su1 msg1.4s, msg0.4s + sha1su0 msg2.4s, msg3.4s, msg0.4s + + /* rounds 12--15 */ + sha1h e0, abcd_s + sha1c abcd_q, e1, tmp1.4s + add tmp1.4s, msg1.4s, k1.4s + sha1su1 msg2.4s, msg1.4s + sha1su0 msg3.4s, msg0.4s, msg1.4s + + /* rounds 16--19 */ + sha1h e1, abcd_s + sha1c abcd_q, e0, tmp0.4s + add tmp0.4s, msg2.4s, k1.4s + sha1su1 msg3.4s, msg2.4s + sha1su0 msg0.4s, msg1.4s, msg2.4s + + /* rounds 20--23 */ + sha1h e0, abcd_s + sha1p abcd_q, e1, tmp1.4s + add tmp1.4s, msg3.4s, k1.4s + sha1su1 msg0.4s, msg3.4s + sha1su0 msg1.4s, msg2.4s, msg3.4s + + /* rounds 24--27 */ + sha1h e1, abcd_s + sha1p abcd_q, e0, tmp0.4s + add tmp0.4s, msg0.4s, k1.4s + sha1su1 msg1.4s, msg0.4s + sha1su0 msg2.4s, msg3.4s, msg0.4s + + /* rounds 28--31 */ + sha1h e0, abcd_s + sha1p abcd_q, e1, tmp1.4s + add tmp1.4s, msg1.4s, k1.4s + sha1su1 msg2.4s, msg1.4s + sha1su0 msg3.4s, msg0.4s, msg1.4s + + /* rounds 32--35 */ + sha1h e1, abcd_s + sha1p abcd_q, e0, tmp0.4s + add tmp0.4s, msg2.4s, k2.4s + sha1su1 msg3.4s, msg2.4s + sha1su0 msg0.4s, msg1.4s, msg2.4s + + /* rounds 36--39 */ + sha1h e0, abcd_s + sha1p abcd_q, e1, tmp1.4s + add tmp1.4s, msg3.4s, k2.4s + sha1su1 msg0.4s, msg3.4s + sha1su0 msg1.4s, msg2.4s, msg3.4s + + /* rounds 40--43 */ + sha1h e1, abcd_s + sha1m abcd_q, e0, tmp0.4s + add tmp0.4s, msg0.4s, k2.4s + sha1su1 msg1.4s, msg0.4s + sha1su0 msg2.4s, msg3.4s, msg0.4s + + /* rounds 44--47 */ + sha1h e0, abcd_s + sha1m abcd_q, e1, tmp1.4s + add tmp1.4s, msg1.4s, k2.4s + sha1su1 msg2.4s, msg1.4s + sha1su0 msg3.4s, msg0.4s, msg1.4s + + /* rounds 48--51 */ + sha1h e1, abcd_s + sha1m abcd_q, e0, tmp0.4s + add tmp0.4s, msg2.4s, k2.4s + sha1su1 msg3.4s, msg2.4s + sha1su0 msg0.4s, msg1.4s, msg2.4s + + /* rounds 52--55 */ + sha1h e0, abcd_s + sha1m abcd_q, e1, tmp1.4s + add tmp1.4s, msg3.4s, k3.4s + sha1su1 msg0.4s, msg3.4s + sha1su0 msg1.4s, msg2.4s, msg3.4s + + /* rounds 56--59 */ + sha1h e1, abcd_s + sha1m abcd_q, e0, tmp0.4s + add tmp0.4s, msg0.4s, k3.4s + sha1su1 msg1.4s, msg0.4s + sha1su0 msg2.4s, msg3.4s, msg0.4s + + /* rounds 60--63 */ + sha1h e0, abcd_s + sha1p abcd_q, e1, tmp1.4s + add tmp1.4s, msg1.4s, k3.4s + sha1su1 msg2.4s, msg1.4s + sha1su0 msg3.4s, msg0.4s, msg1.4s + + /* rounds 64--67 */ + sha1h e1, abcd_s + sha1p abcd_q, e0, tmp0.4s + add tmp0.4s, msg2.4s, k3.4s + sha1su1 msg3.4s, msg2.4s + sha1su0 msg0.4s, msg1.4s, msg2.4s + + /* rounds 68--71 */ + sha1h e0, abcd_s + sha1p abcd_q, e1, tmp1.4s + add tmp1.4s, msg3.4s, k3.4s + sha1su1 msg0.4s, msg3.4s + + /* rounds 72--75 */ + sha1h e1, abcd_s + sha1p abcd_q, e0, tmp0.4s + + /* rounds 76--79 */ + sha1h e0, abcd_s + sha1p abcd_q, e1, tmp1.4s + + add e0_v.4s, e0_v.4s, e0_saved.4s + add abcd.4s, abcd.4s, abcd_saved.4s + + subs len, len, #64 + bhi 0b + + str abcd_q, [ctx, #0] + str e0, [ctx, #16] + +1: ret +END(_libmd_sha1block_sha1) + + .section .rodata + .balign 16 +k1234: .4byte 0x5a827999 + .4byte 0x6ed9eba1 + .4byte 0x8f1bbcdc + .4byte 0xca62c1d6 + .size k1234, .-k1234 + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libmd/aarch64/sha1dispatch.c b/lib/libmd/aarch64/sha1dispatch.c new file mode 100644 index 000000000000..e34bf0a1a344 --- /dev/null +++ b/lib/libmd/aarch64/sha1dispatch.c @@ -0,0 +1,24 @@ +/*- + * Copyright (c) 2024 Robert Clausecker <fuz@freebsd.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <machine/ifunc.h> +#include <sha.h> +#include <sys/auxv.h> + +extern void _libmd_sha1block_scalar(SHA1_CTX *, const void *, size_t); +extern void _libmd_sha1block_sha1(SHA1_CTX *, const void *, size_t); + +DEFINE_IFUNC(, void, sha1_block, (SHA1_CTX *, const void *, size_t)) +{ + unsigned long hwcap = 0; + + elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap)); + + if (hwcap & HWCAP_SHA1) + return (_libmd_sha1block_sha1); + else + return (_libmd_sha1block_scalar); +} diff --git a/lib/libmd/amd64/sha1block.S b/lib/libmd/amd64/sha1block.S new file mode 100644 index 000000000000..f1291ef2647a --- /dev/null +++ b/lib/libmd/amd64/sha1block.S @@ -0,0 +1,1851 @@ +/*- + * Copyright (c) 2013 The Go Authors. All rights reserved. + * Copyright (c) 2024 Robert Clausecker <fuz@freebsd.org> + * + * Adapted from Go's crypto/sha1/sha1block_amd64.s. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 COPYRIGHT + * OWNER OR CONTRIBUTORS 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 <machine/asm.h> + +/* + * SHA-1 block routine. See sha1c.c for C equivalent. + * + * There are 80 rounds of 4 types: + * - rounds 0-15 are type 1 and load data (round1 macro). + * - rounds 16-19 are type 1 and do not load data (round1x macro). + * - rounds 20-39 are type 2 and do not load data (round2 macro). + * - rounds 40-59 are type 3 and do not load data (round3 macro). + * - rounds 60-79 are type 4 and do not load data (round4 macro). + * + * Each round loads or shuffles the data, then computes a per-round + * function of b, c, d, and then mixes the result into and rotates the + * five registers a, b, c, d, e holding the intermediate results. + * + * The register rotation is implemented by rotating the arguments to + * the round macros instead of by explicit move instructions. + */ +.macro load index + mov (\index)*4(%rsi), %r10d + bswap %r10d + mov %r10d, (\index)*4(%rsp) +.endm + +.macro shuffle index + mov ((\index )&0xf)*4(%rsp), %r10d + xor ((\index- 3)&0xf)*4(%rsp), %r10d + xor ((\index- 8)&0xf)*4(%rsp), %r10d + xor ((\index-14)&0xf)*4(%rsp), %r10d + rol $1, %r10d + mov %r10d, ((\index)&0xf)*4(%rsp) +.endm + +.macro func1 a, b, c, d, e + mov \d, %r9d + xor \c, %r9d + and \b, %r9d + xor \d, %r9d +.endm + +.macro func2 a, b, c, d, e + mov \b, %r9d + xor \c, %r9d + xor \d, %r9d +.endm + +.macro func3 a, b, c, d, e + mov \b, %r8d + or \c, %r8d + and \d, %r8d + mov \b, %r9d + and \c, %r9d + or %r8d, %r9d +.endm + +.macro func4 a, b, c, d, e + func2 \a, \b, \c, \d, \e +.endm + +.macro mix a, b, c, d, e, const + rol $30, \b + add %r9d, \e + mov \a, %r8d + rol $5, %r8d + lea \const(\e, %r10d, 1), \e + add %r8d, \e +.endm + +.macro round1 a, b, c, d, e, index + load \index + func1 \a, \b, \c, \d, \e + mix \a, \b, \c, \d, \e, 0x5a827999 +.endm + +.macro round1x a, b, c, d, e, index + shuffle \index + func1 \a, \b, \c, \d, \e + mix \a, \b, \c, \d, \e, 0x5a827999 +.endm + +.macro round2 a, b, c, d, e, index + shuffle \index + func2 \a, \b, \c, \d, \e + mix \a, \b, \c, \d, \e, 0x6ed9eba1 +.endm + +.macro round3 a, b, c, d, e, index + shuffle \index + func3 \a, \b, \c, \d, \e + mix \a, \b, \c, \d, \e, 0x8f1bbcdc +.endm + +.macro round4 a, b, c, d, e, index + shuffle \index + func4 \a, \b, \c, \d, \e + mix \a, \b, \c, \d, \e, 0xca62c1d6 +.endm + + // sha1block(SHA1_CTX, buf, len) +ENTRY(_libmd_sha1block_scalar) + push %rbp + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + push %rdi // rdi: SHA1_CTX + sub $64+8, %rsp // 64 bytes for round keys + // plus alignment + + mov %rdi, %rbp + // rsi: buf + and $~63, %rdx // rdx: length in blocks + lea (%rsi, %rdx, 1), %rdi // rdi: end pointer + mov (%rbp), %eax // c->h0 + mov 4(%rbp), %ebx // c->h1 + mov 8(%rbp), %ecx // c->h2 + mov 12(%rbp), %edx // c->h3 + mov 16(%rbp), %ebp // c->h4 + + cmp %rsi, %rdi // any data to process? + je .Lend + +.Lloop: mov %eax, %r11d + mov %ebx, %r12d + mov %ecx, %r13d + mov %edx, %r14d + mov %ebp, %r15d + + round1 %eax, %ebx, %ecx, %edx, %ebp, 0 + round1 %ebp, %eax, %ebx, %ecx, %edx, 1 + round1 %edx, %ebp, %eax, %ebx, %ecx, 2 + round1 %ecx, %edx, %ebp, %eax, %ebx, 3 + round1 %ebx, %ecx, %edx, %ebp, %eax, 4 + + round1 %eax, %ebx, %ecx, %edx, %ebp, 5 + round1 %ebp, %eax, %ebx, %ecx, %edx, 6 + round1 %edx, %ebp, %eax, %ebx, %ecx, 7 + round1 %ecx, %edx, %ebp, %eax, %ebx, 8 + round1 %ebx, %ecx, %edx, %ebp, %eax, 9 + + round1 %eax, %ebx, %ecx, %edx, %ebp, 10 + round1 %ebp, %eax, %ebx, %ecx, %edx, 11 + round1 %edx, %ebp, %eax, %ebx, %ecx, 12 + round1 %ecx, %edx, %ebp, %eax, %ebx, 13 + round1 %ebx, %ecx, %edx, %ebp, %eax, 14 + + round1 %eax, %ebx, %ecx, %edx, %ebp, 15 + round1x %ebp, %eax, %ebx, %ecx, %edx, 16 + round1x %edx, %ebp, %eax, %ebx, %ecx, 17 + round1x %ecx, %edx, %ebp, %eax, %ebx, 18 + round1x %ebx, %ecx, %edx, %ebp, %eax, 19 + + round2 %eax, %ebx, %ecx, %edx, %ebp, 20 + round2 %ebp, %eax, %ebx, %ecx, %edx, 21 + round2 %edx, %ebp, %eax, %ebx, %ecx, 22 + round2 %ecx, %edx, %ebp, %eax, %ebx, 23 + round2 %ebx, %ecx, %edx, %ebp, %eax, 24 + + round2 %eax, %ebx, %ecx, %edx, %ebp, 25 + round2 %ebp, %eax, %ebx, %ecx, %edx, 26 + round2 %edx, %ebp, %eax, %ebx, %ecx, 27 + round2 %ecx, %edx, %ebp, %eax, %ebx, 28 + round2 %ebx, %ecx, %edx, %ebp, %eax, 29 + + round2 %eax, %ebx, %ecx, %edx, %ebp, 30 + round2 %ebp, %eax, %ebx, %ecx, %edx, 31 + round2 %edx, %ebp, %eax, %ebx, %ecx, 32 + round2 %ecx, %edx, %ebp, %eax, %ebx, 33 + round2 %ebx, %ecx, %edx, %ebp, %eax, 34 + + round2 %eax, %ebx, %ecx, %edx, %ebp, 35 + round2 %ebp, %eax, %ebx, %ecx, %edx, 36 + round2 %edx, %ebp, %eax, %ebx, %ecx, 37 + round2 %ecx, %edx, %ebp, %eax, %ebx, 38 + round2 %ebx, %ecx, %edx, %ebp, %eax, 39 + + round3 %eax, %ebx, %ecx, %edx, %ebp, 40 + round3 %ebp, %eax, %ebx, %ecx, %edx, 41 + round3 %edx, %ebp, %eax, %ebx, %ecx, 42 + round3 %ecx, %edx, %ebp, %eax, %ebx, 43 + round3 %ebx, %ecx, %edx, %ebp, %eax, 44 + + round3 %eax, %ebx, %ecx, %edx, %ebp, 45 + round3 %ebp, %eax, %ebx, %ecx, %edx, 46 + round3 %edx, %ebp, %eax, %ebx, %ecx, 47 + round3 %ecx, %edx, %ebp, %eax, %ebx, 48 + round3 %ebx, %ecx, %edx, %ebp, %eax, 49 + + round3 %eax, %ebx, %ecx, %edx, %ebp, 50 + round3 %ebp, %eax, %ebx, %ecx, %edx, 51 + round3 %edx, %ebp, %eax, %ebx, %ecx, 52 + round3 %ecx, %edx, %ebp, %eax, %ebx, 53 + round3 %ebx, %ecx, %edx, %ebp, %eax, 54 + + round3 %eax, %ebx, %ecx, %edx, %ebp, 55 + round3 %ebp, %eax, %ebx, %ecx, %edx, 56 + round3 %edx, %ebp, %eax, %ebx, %ecx, 57 + round3 %ecx, %edx, %ebp, %eax, %ebx, 58 + round3 %ebx, %ecx, %edx, %ebp, %eax, 59 + + round4 %eax, %ebx, %ecx, %edx, %ebp, 60 + round4 %ebp, %eax, %ebx, %ecx, %edx, 61 + round4 %edx, %ebp, %eax, %ebx, %ecx, 62 + round4 %ecx, %edx, %ebp, %eax, %ebx, 63 + round4 %ebx, %ecx, %edx, %ebp, %eax, 64 + + round4 %eax, %ebx, %ecx, %edx, %ebp, 65 + round4 %ebp, %eax, %ebx, %ecx, %edx, 66 + round4 %edx, %ebp, %eax, %ebx, %ecx, 67 + round4 %ecx, %edx, %ebp, %eax, %ebx, 68 + round4 %ebx, %ecx, %edx, %ebp, %eax, 69 + + round4 %eax, %ebx, %ecx, %edx, %ebp, 70 + round4 %ebp, %eax, %ebx, %ecx, %edx, 71 + round4 %edx, %ebp, %eax, %ebx, %ecx, 72 + round4 %ecx, %edx, %ebp, %eax, %ebx, 73 + round4 %ebx, %ecx, %edx, %ebp, %eax, 74 + + round4 %eax, %ebx, %ecx, %edx, %ebp, 75 + round4 %ebp, %eax, %ebx, %ecx, %edx, 76 + round4 %edx, %ebp, %eax, %ebx, %ecx, 77 + round4 %ecx, %edx, %ebp, %eax, %ebx, 78 + round4 %ebx, %ecx, %edx, %ebp, %eax, 79 + + add %r11d, %eax + add %r12d, %ebx + add %r13d, %ecx + add %r14d, %edx + add %r15d, %ebp + + add $64, %rsi + cmp %rdi, %rsi + jb .Lloop + +.Lend: add $64+8, %rsp + pop %rdi // SHA1_CTX + mov %eax, (%rdi) + mov %ebx, 4(%rdi) + mov %ecx, 8(%rdi) + mov %edx, 12(%rdi) + mov %ebp, 16(%rdi) + + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbx + pop %rbp + ret +END(_libmd_sha1block_scalar) + +/* + * This is the implementation using AVX2, BMI1 and BMI2. It is based on: + * "SHA-1 implementation with Intel(R) AVX2 instruction set extensions" + * From http://software.intel.com/en-us/articles + * (look for improving-the-performance-of-the-secure-hash-algorithm-1) + * This implementation is 2x unrolled, and interleaves vector instructions, + * used to precompute W, with scalar computation of current round + * for optimal scheduling. + */ + + /* trivial helper macros */ +.macro update_hash a, tb, c, d, e + add (%r9), \a + mov \a, (%r9) + add 4(%r9), \tb + mov \tb, 4(%r9) + add 8(%r9), \c + mov \c, 8(%r9) + add 12(%r9), \d + mov \d, 12(%r9) + add 16(%r9), \e + mov \e, 16(%r9) +.endm + + /* help macros for recalc, which does precomputations */ +.macro precalc0 offset + vmovdqu \offset(%r10), %xmm0 +.endm + +.macro precalc1 offset + vinserti128 $1, \offset(%r13), %ymm0, %ymm0 +.endm + +.macro precalc2 yreg + vpshufb %ymm10, %ymm0, \yreg +.endm + +.macro precalc4 yreg, k_offset + vpaddd \k_offset(%r8), \yreg, %ymm0 +.endm + +.macro precalc7 offset + vmovdqu %ymm0, (\offset)*2(%r14) +.endm + +/* + * Message scheduling pre-compute for rounds 0-15 + * r13 is a pointer to the even 64-byte block + * r10 is a pointer to the odd 64-byte block + * r14 is a pointer to the temp buffer + * xmm0 is used as a temp register + * yreg is clobbered as part of the computation + * offset chooses a 16 byte chunk within a block + * r8 is a pointer to the constants block + * k_offset chooses K constants relevant to this round + * xmm10 holds the swap mask + */ +.macro precalc00_15 offset, yreg + precalc0 \offset + precalc1 \offset + precalc2 \yreg + precalc4 \yreg, 0 + precalc7 \offset +.endm + + /* helper macros for precalc16_31 */ +.macro precalc16 reg_sub16, reg_sub12, reg_sub4, reg + vpalignr $8, \reg_sub16, \reg_sub12, \reg // w[i - 14] + vpsrldq $4, \reg_sub4, %ymm0 // w[i - 3] +.endm + +.macro precalc17 reg_sub16, reg_sub8, reg + vpxor \reg_sub8, \reg, \reg + vpxor \reg_sub16, %ymm0, %ymm0 +.endm + +.macro precalc18 reg + vpxor %ymm0, \reg, \reg + vpslldq $12, \reg, %ymm9 +.endm + +.macro precalc19 reg + vpslld $1, \reg, %ymm0 + vpsrld $31, \reg, \reg + .endm + +.macro precalc20 reg + vpor \reg, %ymm0, %ymm0 + vpslld $2, %ymm9, \reg +.endm + +.macro precalc21 reg + vpsrld $30, %ymm9, %ymm9 + vpxor \reg, %ymm0, %ymm0 +.endm + +.macro precalc23 reg, k_offset, offset + vpxor %ymm9, %ymm0, \reg + vpaddd \k_offset(%r8), \reg, %ymm0 + vmovdqu %ymm0, (\offset)(%r14) +.endm + +/* + * Message scheduling pre-compute for rounds 16-31 + * calculating last 32 w[i] values in 8 XMM registers + * pre-calculate K+w[i] values and store to mem + * for later load by ALU add instruction. + * "brute force" vectorization for rounds 16-31 only + * due to w[i]->w[i-3] dependency. + + clobbers 5 input ymm registers REG_SUB* + * uses xmm0 and xmm9 as temp registers + * As always, r8 is a pointer to constants block + * and r14 is a pointer to temp buffer + */ +.macro precalc16_31 reg, reg_sub4, reg_sub8, reg_sub12, reg_sub16, k_offset, offset + precalc16 \reg_sub16, \reg_sub12, \reg_sub4, \reg + precalc17 \reg_sub16, \reg_sub8, \reg + precalc18 \reg + precalc19 \reg + precalc20 \reg + precalc21 \reg + precalc23 \reg, \k_offset, \offset +.endm + + /* helper macros for precalc_32_79 */ +.macro precalc32 reg_sub8, reg_sub4 + vpalignr $8, \reg_sub8, \reg_sub4, %ymm0 +.endm + +.macro precalc33 reg_sub28, reg + vpxor \reg_sub28, \reg, \reg +.endm + +.macro precalc34 reg_sub16 + vpxor \reg_sub16, %ymm0, %ymm0 +.endm + +.macro precalc35 reg + vpxor %ymm0, \reg, \reg +.endm + +.macro precalc36 reg + vpslld $2, \reg, %ymm0 +.endm + +.macro precalc37 reg + vpsrld $30, \reg, \reg + vpor \reg, %ymm0, \reg +.endm + +.macro precalc39 reg, k_offset, offset + vpaddd \k_offset(%r8), \reg, %ymm0 + vmovdqu %ymm0, \offset(%r14) +.endm + +.macro precalc32_79 reg, reg_sub4, reg_sub8, reg_sub16, reg_sub28, k_offset, offset + precalc32 \reg_sub8, \reg_sub4 + precalc33 \reg_sub28, \reg + precalc34 \reg_sub16 + precalc35 \reg + precalc36 \reg + precalc37 \reg + precalc39 \reg, \k_offset, \offset +.endm + +.macro precalc + precalc00_15 0x00, %ymm15 + precalc00_15 0x10, %ymm14 + precalc00_15 0x20, %ymm13 + precalc00_15 0x30, %ymm12 + precalc16_31 %ymm8, %ymm12, %ymm13, %ymm14, %ymm15, 0x00, 0x080 + precalc16_31 %ymm7, %ymm8, %ymm12, %ymm13, %ymm14, 0x20, 0x0a0 + precalc16_31 %ymm5, %ymm7, %ymm8, %ymm12, %ymm13, 0x20, 0x0c0 + precalc16_31 %ymm3, %ymm5, %ymm7, %ymm8, %ymm12, 0x20, 0x0e0 + precalc32_79 %ymm15, %ymm3, %ymm5, %ymm8, %ymm14, 0x20, 0x100 + precalc32_79 %ymm14, %ymm15, %ymm3, %ymm7, %ymm13, 0x20, 0x120 + precalc32_79 %ymm13, %ymm14, %ymm15, %ymm5, %ymm12, 0x40, 0x140 + precalc32_79 %ymm12, %ymm13, %ymm14, %ymm3, %ymm8, 0x40, 0x160 + precalc32_79 %ymm8, %ymm12, %ymm13, %ymm15, %ymm7, 0x40, 0x180 + precalc32_79 %ymm7, %ymm8, %ymm12, %ymm14, %ymm5, 0x40, 0x1a0 + precalc32_79 %ymm5, %ymm7, %ymm8, %ymm13, %ymm3, 0x40, 0x1c0 + precalc32_79 %ymm3, %ymm5, %ymm7, %ymm12, %ymm15, 0x60, 0x1e0 + precalc32_79 %ymm15, %ymm3, %ymm5, %ymm8, %ymm14, 0x60, 0x200 + precalc32_79 %ymm14, %ymm15, %ymm3, %ymm7, %ymm13, 0x60, 0x220 + precalc32_79 %ymm13, %ymm14, %ymm15, %ymm5, %ymm12, 0x60, 0x240 + precalc32_79 %ymm12, %ymm13, %ymm14, %ymm3, %ymm8, 0x60, 0x260 +.endm + +/* + * Macros calculating individual rounds have general form + * calc_round_pre + precalc_round + calc_round_post + * calc_round_{pre,post} macros follow + */ +.macro calc_f1_pre offset, reg_a, reg_b, reg_c, reg_e + add \offset(%r15), \reg_e + andn \reg_c, \reg_a, %ebp + add \reg_b, \reg_e // add F from the previous round + rorx $0x1b, \reg_a, %r12d + rorx $2, \reg_a, \reg_b // for the next round +.endm + +/* + * Calculate F for the next round + */ +.macro calc_f1_post reg_a, reg_b, reg_e + and \reg_b, \reg_a // b & c + xor %ebp, \reg_a // F1 = (b&c) ^ (~b&d) + add %r12d, \reg_e +.endm + +/* + * Registers are cyclically rotated: + * edx -> eax -> edi -> esi -> ebx -> ecx + */ +.macro calc0 + mov %esi, %ebx // precalculate first round + rorx $2, %esi, %esi + andn %eax, %ebx, %ebp + and %edi, %ebx + xor %ebp, %ebx + calc_f1_pre 0x0, %ecx, %ebx, %edi, %edx + precalc0 0x80 + calc_f1_post %ecx, %esi, %edx +.endm + +.macro calc1 + calc_f1_pre 0x4, %edx, %ecx, %esi, %eax + precalc1 0x80 + calc_f1_post %edx, %ebx, %eax +.endm + +.macro calc2 + calc_f1_pre 0x8, %eax, %edx, %ebx, %edi + precalc2 %ymm15 + calc_f1_post %eax, %ecx, %edi +.endm + +.macro calc3 + calc_f1_pre 0xc, %edi, %eax, %ecx, %esi + calc_f1_post %edi, %edx, %esi +.endm + +.macro calc4 + calc_f1_pre 0x20, %esi, %edi, %edx, %ebx + precalc4 %ymm15, 0x0 + calc_f1_post %esi, %eax, %ebx +.endm + +.macro calc5 + calc_f1_pre 0x24, %ebx, %esi, %eax, %ecx + calc_f1_post %ebx, %edi, %ecx +.endm + +.macro calc6 + calc_f1_pre 0x28, %ecx, %ebx, %edi, %edx + calc_f1_post %ecx, %esi, %edx +.endm + +.macro calc7 + calc_f1_pre 0x2c, %edx, %ecx, %esi, %eax + precalc7 0x0 + calc_f1_post %edx, %ebx, %eax +.endm + +.macro calc8 + calc_f1_pre 0x40, %eax, %edx, %ebx, %edi + precalc0 0x90 + calc_f1_post %eax, %ecx, %edi +.endm + +.macro calc9 + calc_f1_pre 0x44, %edi, %eax, %ecx, %esi + precalc1 0x90 + calc_f1_post %edi, %edx, %esi +.endm + +.macro calc10 + calc_f1_pre 0x48, %esi, %edi, %edx, %ebx + precalc2 %ymm14 + calc_f1_post %esi, %eax, %ebx +.endm + +.macro calc11 + calc_f1_pre 0x4c, %ebx, %esi, %eax, %ecx + calc_f1_post %ebx, %edi, %ecx +.endm + +.macro calc12 + calc_f1_pre 0x60, %ecx, %ebx, %edi, %edx + precalc4 %ymm14, 0 + calc_f1_post %ecx, %esi, %edx +.endm + +.macro calc13 + calc_f1_pre 0x64, %edx, %ecx, %esi, %eax + calc_f1_post %edx, %ebx, %eax +.endm + +.macro calc14 + calc_f1_pre 0x68, %eax, %edx, %ebx, %edi + calc_f1_post %eax, %ecx, %edi +.endm + +.macro calc15 + calc_f1_pre 0x6c, %edi, %eax, %ecx, %esi + precalc7 0x10 + calc_f1_post %edi, %edx, %esi +.endm + +.macro calc16 + calc_f1_pre 0x80, %esi, %edi, %edx, %ebx + precalc0 0xa0 + calc_f1_post %esi, %eax, %ebx +.endm + +.macro calc17 + calc_f1_pre 0x84, %ebx, %esi, %eax, %ecx + precalc1 0xa0 + calc_f1_post %ebx, %edi, %ecx +.endm + +.macro calc18 + calc_f1_pre 0x88, %ecx, %ebx, %edi, %edx + precalc2 %ymm13 + calc_f1_post %ecx, %esi, %edx +.endm + +.macro calc_f2_pre offset, reg_a, reg_b, reg_e + add \offset(%r15), \reg_e + add \reg_b, \reg_e // add F from the previous round + rorx $0x1b, \reg_a, %r12d + rorx $2, \reg_a, \reg_b // for next round +.endm + +.macro calc_f2_post reg_a, reg_b, reg_c, reg_e + xor \reg_b, \reg_a + add %r12d, \reg_e + xor \reg_c, \reg_a +.endm + +.macro calc19 + calc_f2_pre 0x8c, %edx, %ecx, %eax + calc_f2_post %edx, %ebx, %esi, %eax +.endm + +.macro calc20 + calc_f2_pre 0xa0, %eax, %edx, %edi + precalc4 %ymm13, 0x0 + calc_f2_post %eax, %ecx, %ebx, %edi +.endm + +.macro calc21 + calc_f2_pre 0xa4, %edi, %eax, %esi + calc_f2_post %edi, %edx, %ecx, %esi +.endm + +.macro calc22 + calc_f2_pre 0xa8, %esi, %edi, %ebx + calc_f2_post %esi, %eax, %edx, %ebx +.endm + +.macro calc23 + calc_f2_pre 0xac, %ebx, %esi, %ecx + precalc7 0x20 + calc_f2_post %ebx, %edi, %eax, %ecx +.endm + +.macro calc24 + calc_f2_pre 0xc0, %ecx, %ebx, %edx + precalc0 0xb0 + calc_f2_post %ecx, %esi, %edi, %edx +.endm + +.macro calc25 + calc_f2_pre 0xc4, %edx, %ecx, %eax + precalc1 0xb0 + calc_f2_post %edx, %ebx, %esi, %eax +.endm + +.macro calc26 + calc_f2_pre 0xc8, %eax, %edx, %edi + precalc2 %ymm12 + calc_f2_post %eax, %ecx, %ebx, %edi +.endm + +.macro calc27 + calc_f2_pre 0xcc, %edi, %eax, %esi + calc_f2_post %edi, %edx, %ecx, %esi +.endm + +.macro calc28 + calc_f2_pre 0xe0, %esi, %edi, %ebx + precalc4 %ymm12, 0x0 + calc_f2_post %esi, %eax, %edx, %ebx +.endm + +.macro calc29 + calc_f2_pre 0xe4, %ebx, %esi, %ecx + calc_f2_post %ebx, %edi, %eax, %ecx +.endm + +.macro calc30 + calc_f2_pre 0xe8, %ecx, %ebx, %edx + calc_f2_post %ecx, %esi, %edi, %edx +.endm + +.macro calc31 + calc_f2_pre 0xec, %edx, %ecx, %eax + precalc7 0x30 + calc_f2_post %edx, %ebx, %esi, %eax +.endm + +.macro calc32 + calc_f2_pre 0x100, %eax, %edx, %edi + precalc16 %ymm15, %ymm14, %ymm12, %ymm8 + calc_f2_post %eax, %ecx, %ebx, %edi +.endm + +.macro calc33 + calc_f2_pre 0x104, %edi, %eax, %esi + precalc17 %ymm15, %ymm13, %ymm8 + calc_f2_post %edi, %edx, %ecx, %esi +.endm + +.macro calc34 + calc_f2_pre 0x108, %esi, %edi, %ebx + precalc18 %ymm8 + calc_f2_post %esi, %eax, %edx, %ebx +.endm + +.macro calc35 + calc_f2_pre 0x10c, %ebx, %esi, %ecx + precalc19 %ymm8 + calc_f2_post %ebx, %edi, %eax, %ecx +.endm + +.macro calc36 + calc_f2_pre 0x120, %ecx, %ebx, %edx + precalc20 %ymm8 + calc_f2_post %ecx, %esi, %edi, %edx +.endm + +.macro calc37 + calc_f2_pre 0x124, %edx, %ecx, %eax + precalc21 %ymm8 + calc_f2_post %edx, %ebx, %esi, %eax +.endm + +.macro calc38 + calc_f2_pre 0x128, %eax, %edx, %edi + calc_f2_post %eax, %ecx, %ebx, %edi +.endm + +.macro calc_f3_pre offset, reg_e + add \offset(%r15), \reg_e +.endm + +.macro calc_f3_post reg_a, reg_b, reg_c, reg_e, reg_tb + add \reg_tb, \reg_e // add F from the previous round + mov \reg_b, %ebp + or \reg_a, %ebp + rorx $0x1b, \reg_a, %r12d + rorx $2, \reg_a, \reg_tb + and \reg_c, %ebp // calculate F for the next round + and \reg_b, \reg_a + or %ebp, \reg_a + add %r12d, \reg_e +.endm + +.macro calc39 + calc_f3_pre 0x12c, %esi + precalc23 %ymm8, 0x0, 0x80 + calc_f3_post %edi, %edx, %ecx, %esi, %eax +.endm + +.macro calc40 + calc_f3_pre 0x140, %ebx + precalc16 %ymm14, %ymm13, %ymm8, %ymm7 + calc_f3_post %esi, %eax, %edx, %ebx, %edi +.endm + +.macro calc41 + calc_f3_pre 0x144, %ecx + precalc17 %ymm14, %ymm12, %ymm7 + calc_f3_post %ebx, %edi, %eax, %ecx, %esi +.endm + +.macro calc42 + calc_f3_pre 0x148, %edx + precalc18 %ymm7 + calc_f3_post %ecx, %esi, %edi, %edx, %ebx +.endm + +.macro calc43 + calc_f3_pre 0x14c, %eax + precalc19 %ymm7 + calc_f3_post %edx, %ebx, %esi, %eax, %ecx +.endm + +.macro calc44 + calc_f3_pre 0x160, %edi + precalc20 %ymm7 + calc_f3_post %eax, %ecx, %ebx, %edi, %edx +.endm + +.macro calc45 + calc_f3_pre 0x164, %esi + precalc21 %ymm7 + calc_f3_post %edi, %edx, %ecx, %esi, %eax +.endm + +.macro calc46 + calc_f3_pre 0x168, %ebx + calc_f3_post %esi, %eax, %edx, %ebx, %edi +.endm + +.macro calc47 + calc_f3_pre 0x16c, %ecx + vpxor %ymm9, %ymm0, %ymm7 + vpaddd 0x20(%r8), %ymm7, %ymm0 + vmovdqu %ymm0, 0xa0(%r14) + calc_f3_post %ebx, %edi, %eax, %ecx, %esi +.endm + +.macro calc48 + calc_f3_pre 0x180, %edx + precalc16 %ymm13, %ymm12, %ymm7, %ymm5 + calc_f3_post %ecx, %esi, %edi, %edx, %ebx +.endm + +.macro calc49 + calc_f3_pre 0x184, %eax + precalc17 %ymm13, %ymm8, %ymm5 + calc_f3_post %edx, %ebx, %esi, %eax, %ecx +.endm + +.macro calc50 + calc_f3_pre 0x188, %edi + precalc18 %ymm5 + calc_f3_post %eax, %ecx, %ebx, %edi, %edx +.endm + +.macro calc51 + calc_f3_pre 0x18c, %esi + precalc19 %ymm5 + calc_f3_post %edi, %edx, %ecx, %esi, %eax +.endm + +.macro calc52 + calc_f3_pre 0x1a0, %ebx + precalc20 %ymm5 + calc_f3_post %esi, %eax, %edx, %ebx, %edi +.endm + +.macro calc53 + calc_f3_pre 0x1a4, %ecx + precalc21 %ymm5 + calc_f3_post %ebx, %edi, %eax, %ecx, %esi +.endm + +.macro calc54 + calc_f3_pre 0x1a8, %edx + calc_f3_post %ecx, %esi, %edi, %edx, %ebx +.endm + +.macro calc55 + calc_f3_pre 0x1ac, %eax + precalc23 %ymm5, 0x20, 0xc0 + calc_f3_post %edx, %ebx, %esi, %eax, %ecx +.endm + +.macro calc56 + calc_f3_pre 0x1c0, %edi + precalc16 %ymm12, %ymm8, %ymm5, %ymm3 + calc_f3_post %eax, %ecx, %ebx, %edi, %edx +.endm + +.macro calc57 + calc_f3_pre 0x1c4, %esi + precalc17 %ymm12, %ymm7, %ymm3 + calc_f3_post %edi, %edx, %ecx, %esi, %eax +.endm + +.macro calc58 + calc_f3_pre 0x1c8, %ebx + precalc18 %ymm3 + calc_f3_post %esi, %eax, %edx, %ebx, %edi +.endm + +.macro calc59 + calc_f2_pre 0x1cc, %ebx, %esi, %ecx + precalc19 %ymm3 + calc_f2_post %ebx, %edi, %eax, %ecx +.endm + +.macro calc60 + calc_f2_pre 0x1e0, %ecx, %ebx, %edx + precalc20 %ymm3 + calc_f2_post %ecx, %esi, %edi, %edx +.endm + +.macro calc61 + calc_f2_pre 0x1e4, %edx, %ecx, %eax + precalc21 %ymm3 + calc_f2_post %edx, %ebx, %esi, %eax +.endm + +.macro calc62 + calc_f2_pre 0x1e8, %eax, %edx, %edi + calc_f2_post %eax, %ecx, %ebx, %edi +.endm + +.macro calc63 + calc_f2_pre 0x1ec, %edi, %eax, %esi + precalc23 %ymm3, 0x20, 0xe0 + calc_f2_post %edi, %edx, %ecx, %esi +.endm + +.macro calc64 + calc_f2_pre 0x200, %esi, %edi, %ebx + precalc32 %ymm5, %ymm3 + calc_f2_post %esi, %eax, %edx, %ebx +.endm + +.macro calc65 + calc_f2_pre 0x204, %ebx, %esi, %ecx + precalc33 %ymm14, %ymm15 + calc_f2_post %ebx, %edi, %eax, %ecx +.endm + +.macro calc66 + calc_f2_pre 0x208, %ecx, %ebx, %edx + precalc34 %ymm8 + calc_f2_post %ecx, %esi, %edi, %edx +.endm + +.macro calc67 + calc_f2_pre 0x20c, %edx, %ecx, %eax + precalc35 %ymm15 + calc_f2_post %edx, %ebx, %esi, %eax +.endm + +.macro calc68 + calc_f2_pre 0x220, %eax, %edx, %edi + precalc36 %ymm15 + calc_f2_post %eax, %ecx, %ebx, %edi +.endm + +.macro calc69 + calc_f2_pre 0x224, %edi, %eax, %esi + precalc37 %ymm15 + calc_f2_post %edi, %edx, %ecx, %esi +.endm + +.macro calc70 + calc_f2_pre 0x228, %esi, %edi, %ebx + calc_f2_post %esi, %eax, %edx, %ebx +.endm + +.macro calc71 + calc_f2_pre 0x22c, %ebx, %esi, %ecx + precalc39 %ymm15, 0x20, 0x100 + calc_f2_post %ebx, %edi, %eax, %ecx +.endm + +.macro calc72 + calc_f2_pre 0x240, %ecx, %ebx, %edx + precalc32 %ymm3, %ymm15 + calc_f2_post %ecx, %esi, %edi, %edx +.endm + +.macro calc73 + calc_f2_pre 0x244, %edx, %ecx, %eax + precalc33 %ymm13, %ymm14 + calc_f2_post %edx, %ebx, %esi, %eax +.endm + +.macro calc74 + calc_f2_pre 0x248, %eax, %edx, %edi + precalc34 %ymm7 + calc_f2_post %eax, %ecx, %ebx, %edi +.endm + +.macro calc75 + calc_f2_pre 0x24c, %edi, %eax, %esi + precalc35 %ymm14 + calc_f2_post %edi, %edx, %ecx, %esi +.endm + +.macro calc76 + calc_f2_pre 0x260, %esi, %edi, %ebx + precalc36 %ymm14 + calc_f2_post %esi, %eax, %edx, %ebx +.endm + +.macro calc77 + calc_f2_pre 0x264, %ebx, %esi, %ecx + precalc37 %ymm14 + calc_f2_post %ebx, %edi, %eax, %ecx +.endm + +.macro calc78 + calc_f2_pre 0x268, %ecx, %ebx, %edx + calc_f2_post %ecx, %esi, %edi, %edx +.endm + +.macro calc79 + add 0x26c(%r15), %eax + add %ecx, %eax + rorx $0x1b, %edx, %r12d + precalc39 %ymm14, 0x20, 0x120 + add %r12d, %eax +.endm + +/* + * Similar to calc0 + */ +.macro calc80 + mov %ecx, %edx // precalculate first round + rorx $2, %ecx, %ecx + andn %esi, %edx, %ebp + and %ebx, %edx + xor %ebp, %edx + calc_f1_pre 0x10, %eax, %edx, %ebx, %edi + precalc32 %ymm15, %ymm14 + calc_f1_post %eax, %ecx, %edi +.endm + +.macro calc81 + calc_f1_pre 0x14, %edi, %eax, %ecx, %esi + precalc33 %ymm12, %ymm13 + calc_f1_post %edi, %edx, %esi +.endm + +.macro calc82 + calc_f1_pre 0x18, %esi, %edi, %edx, %ebx + precalc34 %ymm5 + calc_f1_post %esi, %eax, %ebx +.endm + +.macro calc83 + calc_f1_pre 0x1c, %ebx, %esi, %eax, %ecx + precalc35 %ymm13 + calc_f1_post %ebx, %edi, %ecx +.endm + +.macro calc84 + calc_f1_pre 0x30, %ecx, %ebx, %edi, %edx + precalc36 %ymm13 + calc_f1_post %ecx, %esi, %edx +.endm + +.macro calc85 + calc_f1_pre 0x34, %edx, %ecx, %esi, %eax + precalc37 %ymm13 + calc_f1_post %edx, %ebx, %eax +.endm + +.macro calc86 + calc_f1_pre 0x38, %eax, %edx, %ebx, %edi + calc_f1_post %eax, %ecx, %edi +.endm + +.macro calc87 + calc_f1_pre 0x3c, %edi, %eax, %ecx, %esi + precalc39 %ymm13, 0x40, 0x140 + calc_f1_post %edi, %edx, %esi +.endm + +.macro calc88 + calc_f1_pre 0x50, %esi, %edi, %edx, %ebx + precalc32 %ymm14, %ymm13 + calc_f1_post %esi, %eax, %ebx +.endm + +.macro calc89 + calc_f1_pre 0x54, %ebx, %esi, %eax, %ecx + precalc33 %ymm8, %ymm12 + calc_f1_post %ebx, %edi, %ecx +.endm + +.macro calc90 + calc_f1_pre 0x58, %ecx, %ebx, %edi, %edx + precalc34 %ymm3 + calc_f1_post %ecx, %esi, %edx +.endm + +.macro calc91 + calc_f1_pre 0x5c, %edx, %ecx, %esi, %eax + precalc35 %ymm12 + calc_f1_post %edx, %ebx, %eax +.endm + +.macro calc92 + calc_f1_pre 0x70, %eax, %edx, %ebx, %edi + precalc36 %ymm12 + calc_f1_post %eax, %ecx, %edi +.endm + +.macro calc93 + calc_f1_pre 0x74, %edi, %eax, %ecx, %esi + precalc37 %ymm12 + calc_f1_post %edi, %edx, %esi +.endm + +.macro calc94 + calc_f1_pre 0x78, %esi, %edi, %edx, %ebx + calc_f1_post %esi, %eax, %ebx +.endm + +.macro calc95 + calc_f1_pre 0x7c, %ebx, %esi, %eax, %ecx + precalc39 %ymm12, 0x40, 0x160 + calc_f1_post %ebx, %edi, %ecx +.endm + +.macro calc96 + calc_f1_pre 0x90, %ecx, %ebx, %edi, %edx + precalc32 %ymm13, %ymm12 + calc_f1_post %ecx, %esi, %edx +.endm + +.macro calc97 + calc_f1_pre 0x94, %edx, %ecx, %esi, %eax + precalc33 %ymm7, %ymm8 + calc_f1_post %edx, %ebx, %eax +.endm + +.macro calc98 + calc_f1_pre 0x98, %eax, %edx, %ebx, %edi + precalc34 %ymm15 + calc_f1_post %eax, %ecx, %edi +.endm + +.macro calc99 + calc_f2_pre 0x9c, %edi, %eax, %esi + precalc35 %ymm8 + calc_f2_post %edi, %edx, %ecx, %esi +.endm + +.macro calc100 + calc_f2_pre 0xb0, %esi, %edi, %ebx + precalc36 %ymm8 + calc_f2_post %esi, %eax, %edx, %ebx +.endm + +.macro calc101 + calc_f2_pre 0xb4, %ebx, %esi, %ecx + precalc37 %ymm8 + calc_f2_post %ebx, %edi, %eax, %ecx +.endm + +.macro calc102 + calc_f2_pre 0xb8, %ecx, %ebx, %edx + calc_f2_post %ecx, %esi, %edi, %edx +.endm + +.macro calc103 + calc_f2_pre 0xbc, %edx, %ecx, %eax + precalc39 %ymm8, 0x40, 0x180 + calc_f2_post %edx, %ebx, %esi, %eax +.endm + +.macro calc104 + calc_f2_pre 0xd0, %eax, %edx, %edi + precalc32 %ymm12, %ymm8 + calc_f2_post %eax, %ecx, %ebx, %edi +.endm + +.macro calc105 + calc_f2_pre 0xd4, %edi, %eax, %esi + precalc33 %ymm5, %ymm7 + calc_f2_post %edi, %edx, %ecx, %esi +.endm + +.macro calc106 + calc_f2_pre 0xd8, %esi, %edi, %ebx + precalc34 %ymm14 + calc_f2_post %esi, %eax, %edx, %ebx +.endm + +.macro calc107 + calc_f2_pre 0xdc, %ebx, %esi, %ecx + precalc35 %ymm7 + calc_f2_post %ebx, %edi, %eax, %ecx +.endm + +.macro calc108 + calc_f2_pre 0xf0, %ecx, %ebx, %edx + precalc36 %ymm7 + calc_f2_post %ecx, %esi, %edi, %edx +.endm + +.macro calc109 + calc_f2_pre 0xf4, %edx, %ecx, %eax + precalc37 %ymm7 + calc_f2_post %edx, %ebx, %esi, %eax +.endm + +.macro calc110 + calc_f2_pre 0xf8, %eax, %edx, %edi + calc_f2_post %eax, %ecx, %ebx, %edi +.endm + +.macro calc111 + calc_f2_pre 0xfc, %edi, %eax, %esi + precalc39 %ymm7, 0x40, 0x1a0 + calc_f2_post %edi, %edx, %ecx, %esi +.endm + +.macro calc112 + calc_f2_pre 0x110, %esi, %edi, %ebx + precalc32 %ymm8, %ymm7 + calc_f2_post %esi, %eax, %edx, %ebx +.endm + +.macro calc113 + calc_f2_pre 0x114, %ebx, %esi, %ecx + precalc33 %ymm3, %ymm5 + calc_f2_post %ebx, %edi, %eax, %ecx +.endm + +.macro calc114 + calc_f2_pre 0x118, %ecx, %ebx, %edx + precalc34 %ymm13 + calc_f2_post %ecx, %esi, %edi, %edx +.endm + +.macro calc115 + calc_f2_pre 0x11c, %edx, %ecx, %eax + precalc35 %ymm5 + calc_f2_post %edx, %ebx, %esi, %eax +.endm + +.macro calc116 + calc_f2_pre 0x130, %eax, %edx, %edi + precalc36 %ymm5 + calc_f2_post %eax, %ecx, %ebx, %edi +.endm + +.macro calc117 + calc_f2_pre 0x134, %edi, %eax, %esi + precalc37 %ymm5 + calc_f2_post %edi, %edx, %ecx, %esi +.endm + +.macro calc118 + calc_f2_pre 0x138, %esi, %edi, %ebx + calc_f2_post %esi, %eax, %edx, %ebx +.endm + +.macro calc119 + calc_f3_pre 0x13c, %ecx + precalc39 %ymm5, 0x40, 0x1c0 + calc_f3_post %ebx, %edi, %eax, %ecx, %esi +.endm + +.macro calc120 + calc_f3_pre 0x150, %edx + precalc32 %ymm7, %ymm5 + calc_f3_post %ecx, %esi, %edi, %edx, %ebx +.endm + +.macro calc121 + calc_f3_pre 0x154, %eax + precalc33 %ymm15, %ymm3 + calc_f3_post %edx, %ebx, %esi, %eax, %ecx +.endm + +.macro calc122 + calc_f3_pre 0x158, %edi + precalc34 %ymm12 + calc_f3_post %eax, %ecx, %ebx, %edi, %edx +.endm + +.macro calc123 + calc_f3_pre 0x15c, %esi + precalc35 %ymm3 + calc_f3_post %edi, %edx, %ecx, %esi, %eax +.endm + +.macro calc124 + calc_f3_pre 0x170, %ebx + precalc36 %ymm3 + calc_f3_post %esi, %eax, %edx, %ebx, %edi +.endm + +.macro calc125 + calc_f3_pre 0x174, %ecx + precalc37 %ymm3 + calc_f3_post %ebx, %edi, %eax, %ecx, %esi +.endm + +.macro calc126 + calc_f3_pre 0x178, %edx + calc_f3_post %ecx, %esi, %edi, %edx, %ebx +.endm + +.macro calc127 + calc_f3_pre 0x17c, %eax + precalc39 %ymm3, 0x60, 0x1e0 + calc_f3_post %edx, %ebx, %esi, %eax, %ecx +.endm + +.macro calc128 + calc_f3_pre 0x190, %edi + precalc32 %ymm5, %ymm3 + calc_f3_post %eax, %ecx, %ebx, %edi, %edx +.endm + +.macro calc129 + calc_f3_pre 0x194, %esi + precalc33 %ymm14, %ymm15 + calc_f3_post %edi, %edx, %ecx, %esi, %eax +.endm + +.macro calc130 + calc_f3_pre 0x198, %ebx + precalc34 %ymm8 + calc_f3_post %esi, %eax, %edx, %ebx, %edi +.endm + +.macro calc131 + calc_f3_pre 0x19c, %ecx + precalc35 %ymm15 + calc_f3_post %ebx, %edi, %eax, %ecx, %esi +.endm + +.macro calc132 + calc_f3_pre 0x1b0, %edx + precalc36 %ymm15 + calc_f3_post %ecx, %esi, %edi, %edx, %ebx +.endm + +.macro calc133 + calc_f3_pre 0x1b4, %eax + precalc37 %ymm15 + calc_f3_post %edx, %ebx, %esi, %eax, %ecx +.endm + +.macro calc134 + calc_f3_pre 0x1b8, %edi + calc_f3_post %eax, %ecx, %ebx, %edi, %edx +.endm + +.macro calc135 + calc_f3_pre 0x1bc, %esi + precalc39 %ymm15, 0x60, 0x200 + calc_f3_post %edi, %edx, %ecx, %esi, %eax +.endm + +.macro calc136 + calc_f3_pre 0x1d0, %ebx + precalc32 %ymm3, %ymm15 + calc_f3_post %esi, %eax, %edx, %ebx, %edi +.endm + +.macro calc137 + calc_f3_pre 0x1d4, %ecx + precalc33 %ymm13, %ymm14 + calc_f3_post %ebx, %edi, %eax, %ecx, %esi +.endm + +.macro calc138 + calc_f3_pre 0x1d8, %edx + precalc34 %ymm7 + calc_f3_post %ecx, %esi, %edi, %edx, %ebx +.endm + +.macro calc139 + calc_f2_pre 0x1dc, %edx, %ecx, %eax + precalc35 %ymm14 + calc_f2_post %edx, %ebx, %esi, %eax +.endm + +.macro calc140 + calc_f2_pre 0x1f0, %eax, %edx, %edi + precalc36 %ymm14 + calc_f2_post %eax, %ecx, %ebx, %edi +.endm + +.macro calc141 + calc_f2_pre 0x1f4, %edi, %eax, %esi + precalc37 %ymm14 + calc_f2_post %edi, %edx, %ecx, %esi +.endm + +.macro calc142 + calc_f2_pre 0x1f8, %esi, %edi, %ebx + calc_f2_post %esi, %eax, %edx, %ebx +.endm + +.macro calc143 + calc_f2_pre 0x1fc, %ebx, %esi, %ecx + precalc39 %ymm14, 0x60, 0x220 + calc_f2_post %ebx, %edi, %eax, %ecx +.endm + +.macro calc144 + calc_f2_pre 0x210, %ecx, %ebx, %edx + precalc32 %ymm15, %ymm14 + calc_f2_post %ecx, %esi, %edi, %edx +.endm + +.macro calc145 + calc_f2_pre 0x214, %edx, %ecx, %eax + precalc33 %ymm12, %ymm13 + calc_f2_post %edx, %ebx, %esi, %eax +.endm + +.macro calc146 + calc_f2_pre 0x218, %eax, %edx, %edi + precalc34 %ymm5 + calc_f2_post %eax, %ecx, %ebx, %edi +.endm + +.macro calc147 + calc_f2_pre 0x21c, %edi, %eax, %esi + precalc35 %ymm13 + calc_f2_post %edi, %edx, %ecx, %esi +.endm + +.macro calc148 + calc_f2_pre 0x230, %esi, %edi, %ebx + precalc36 %ymm13 + calc_f2_post %esi, %eax, %edx, %ebx +.endm + +.macro calc149 + calc_f2_pre 0x234, %ebx, %esi, %ecx + precalc37 %ymm13 + calc_f2_post %ebx, %edi, %eax, %ecx +.endm + +.macro calc150 + calc_f2_pre 0x238, %ecx, %ebx, %edx + calc_f2_post %ecx, %esi, %edi, %edx +.endm + +.macro calc151 + calc_f2_pre 0x23c, %edx, %ecx, %eax + precalc39 %ymm13, 0x60, 0x240 + calc_f2_post %edx, %ebx, %esi, %eax +.endm + +.macro calc152 + calc_f2_pre 0x250, %eax, %edx, %edi + precalc32 %ymm14, %ymm13 + calc_f2_post %eax, %ecx, %ebx, %edi +.endm + +.macro calc153 + calc_f2_pre 0x254, %edi, %eax, %esi + precalc33 %ymm8, %ymm12 + calc_f2_post %edi, %edx, %ecx, %esi +.endm + +.macro calc154 + calc_f2_pre 0x258, %esi, %edi, %ebx + precalc34 %ymm3 + calc_f2_post %esi, %eax, %edx, %ebx +.endm + +.macro calc155 + calc_f2_pre 0x25c, %ebx, %esi, %ecx + precalc35 %ymm12 + calc_f2_post %ebx, %edi, %eax, %ecx +.endm + +.macro calc156 + calc_f2_pre 0x270, %ecx, %ebx, %edx + precalc36 %ymm12 + calc_f2_post %ecx, %esi, %edi, %edx +.endm + +.macro calc157 + calc_f2_pre 0x274, %edx, %ecx, %eax + precalc37 %ymm12 + calc_f2_post %edx, %ebx, %esi, %eax +.endm + +.macro calc158 + calc_f2_pre 0x278, %eax, %edx, %edi + calc_f2_post %eax, %ecx, %ebx, %edi +.endm + +.macro calc159 + add 0x27c(%r15), %esi + add %eax, %esi + rorx $0x1b, %edi, %r12d + precalc39 %ymm12, 0x60, 0x260 + add %r12d, %esi +.endm + + // sha1block(SHA1_CTX, buf, len) +ENTRY(_libmd_sha1block_avx2) + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + sub $1408+8, %rsp + + and $~63, %rdx + lea k_xmm_ar(%rip), %r8 + mov %rdi, %r9 + mov %rsi, %r10 + lea 64(%rsi), %r13 + lea 64(%rsi, %rdx), %r11 + cmp %r11, %r13 + cmovae %r8, %r13 + vmovdqu bswap_shufb_ctl(%rip), %ymm10 + + mov (%r9), %ecx + mov 4(%r9), %esi + mov 8(%r9), %edi + mov 12(%r9), %eax + mov 16(%r9), %edx + mov %rsp, %r14 + lea 2*4*80+32(%rsp), %r15 + precalc // precalc WK for first 2 blocks + xchg %r14, %r15 + + // this is unrolled +.Loop: cmp %r8, %r10 // we use the value of R8 (set below) + // as a signal of the last block + jne .Lbegin + add $1408+8, %rsp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + vzeroupper + ret + +.Lbegin: + calc0 + calc1 + calc2 + calc3 + calc4 + calc5 + calc6 + calc7 + calc8 + calc9 + calc10 + calc11 + calc12 + calc13 + calc14 + calc15 + calc16 + calc17 + calc18 + calc19 + calc20 + calc21 + calc22 + calc23 + calc24 + calc25 + calc26 + calc27 + calc28 + calc29 + calc30 + calc31 + calc32 + calc33 + calc34 + calc35 + calc36 + calc37 + calc38 + calc39 + calc40 + calc41 + calc42 + calc43 + calc44 + calc45 + calc46 + calc47 + calc48 + calc49 + calc50 + calc51 + calc52 + calc53 + calc54 + calc55 + calc56 + calc57 + calc58 + calc59 + + add $128, %r10 // move to the next even-64-byte block + cmp %r11, %r10 // is the current block the last one? + cmovae %r8, %r10 // signal the last iteration smartly + + calc60 + calc61 + calc62 + calc63 + calc64 + calc65 + calc66 + calc67 + calc68 + calc69 + calc70 + calc71 + calc72 + calc73 + calc74 + calc75 + calc76 + calc77 + calc78 + calc79 + + update_hash %eax, %edx, %ebx, %esi, %edi + cmp %r8, %r10 // is the current block the last one? + je .Loop + mov %edx, %ecx + + calc80 + calc81 + calc82 + calc83 + calc84 + calc85 + calc86 + calc87 + calc88 + calc89 + calc90 + calc91 + calc92 + calc93 + calc94 + calc95 + calc96 + calc97 + calc98 + calc99 + calc100 + calc101 + calc102 + calc103 + calc104 + calc105 + calc106 + calc107 + calc108 + calc109 + calc110 + calc111 + calc112 + calc113 + calc114 + calc115 + calc116 + calc117 + calc118 + calc119 + calc120 + calc121 + calc122 + calc123 + calc124 + calc125 + calc126 + calc127 + calc128 + calc129 + calc130 + calc131 + calc132 + calc133 + calc134 + calc135 + calc136 + calc137 + calc138 + calc139 + + add $128, %r13 // move to the next even-64-byte block + cmp %r11, %r13 // is the current block the last one? + cmovae %r8, %r10 + + calc140 + calc141 + calc142 + calc143 + calc144 + calc145 + calc146 + calc147 + calc148 + calc149 + calc150 + calc151 + calc152 + calc153 + calc154 + calc155 + calc156 + calc157 + calc158 + calc159 + + update_hash %esi, %edi, %edx, %ecx, %ebx + mov %esi, %r12d // reset state for AVX2 reg permutation + mov %edi, %esi + mov %edx, %edi + mov %ebx, %edx + mov %ecx, %eax + mov %r12d, %ecx + xchg %r14, %r15 + jmp .Loop +END(_libmd_sha1block_avx2) + + .section .rodata + .balign 32 +k_xmm_ar: + .fill 8, 4, 0x5a827999 + .fill 8, 4, 0x6ed9eba1 + .fill 8, 4, 0x8f1bbcdc + .fill 8, 4, 0xca62c1d6 + .size k_xmm_ar, .-k_xmm_ar + +bswap_shufb_ctl: + .4byte 0x00010203 + .4byte 0x04050607 + .4byte 0x08090a0b + .4byte 0x0c0d0e0f + .4byte 0x00010203 + .4byte 0x04050607 + .4byte 0x08090a0b + .4byte 0x0c0d0e0f + .size bswap_shufb_ctl, .-bswap_shufb_ctl + + /* + * SHA1 implementation using the Intel SHA extensions (SHANI). + * + * Imlemented according to the Intel white paper + * + * S. Gulley, V. Gopal, K. Yap, W. Feghali, J. Guilford, + * G. Wolrich: "Intel SHA Extensions: new instruction supporting + * the Secure Hash Algorithm on Intel® architecture processors", + * July 2013. + */ + // sha1block(SHA1_CTX, buf, len) +ENTRY(_libmd_sha1block_shani) + and $~63, %rdx // round length to block-size multiple + lea (%rsi, %rdx, 1), %rcx // end pointer + test %rdx, %rdx // nothing to do? + je 1f // if so, terminate immediately + + movdqu (%rdi), %xmm6 // h0, h1, h2, h3 + pxor %xmm7, %xmm7 + pshufd $0x1b, %xmm6, %xmm6 // h3, h2, h1, h0 + pinsrd $3, 16(%rdi), %xmm7 // h4 in the highest word of xmm7 + movdqu shuf_mask(%rip), %xmm4 + + // main loop +0: movdqa %xmm6, %xmm8 // stash ABCD + movdqa %xmm7, %xmm9 // stash E + + // rounds 0--3 + movdqu 0*16(%rsi), %xmm0 // load first message block + pshufb %xmm4, %xmm0 // and byte-swap + paddd %xmm0, %xmm7 // E += w[0] + movdqa %xmm6, %xmm5 // E' = A + sha1rnds4 $0, %xmm7, %xmm6 // perform rounds 0--3 + + // rounds 4--7 + movdqu 1*16(%rsi), %xmm1 + pshufb %xmm4, %xmm1 + sha1nexte %xmm1, %xmm5 + movdqa %xmm6, %xmm7 + sha1rnds4 $0, %xmm5, %xmm6 + sha1msg1 %xmm1, %xmm0 + + // rounds 8--11 + movdqu 2*16(%rsi), %xmm2 + pshufb %xmm4, %xmm2 + sha1nexte %xmm2, %xmm7 + movdqa %xmm6, %xmm5 + sha1rnds4 $0, %xmm7, %xmm6 + sha1msg1 %xmm2, %xmm1 + pxor %xmm2, %xmm0 + +.macro midround msg3, msg0, msg1, msg2, e1, e0, k + sha1nexte \msg3, \e1 + movdqa %xmm6, \e0 + sha1msg2 \msg3, \msg0 + sha1rnds4 $\k, \e1, %xmm6 + sha1msg1 \msg3, \msg2 + pxor \msg3, \msg1 +.endm + + movdqu 3*16(%rsi), %xmm3 // load third message block + pshufb %xmm4, %xmm3 + + add $4*16, %rsi + + midround %xmm3, %xmm0, %xmm1, %xmm2, %xmm5, %xmm7, 0 // 12--15 + midround %xmm0, %xmm1, %xmm2, %xmm3, %xmm7, %xmm5, 0 // 16--19 + midround %xmm1, %xmm2, %xmm3, %xmm0, %xmm5, %xmm7, 1 // 20--23 + midround %xmm2, %xmm3, %xmm0, %xmm1, %xmm7, %xmm5, 1 // 24--27 + midround %xmm3, %xmm0, %xmm1, %xmm2, %xmm5, %xmm7, 1 // 28--31 + midround %xmm0, %xmm1, %xmm2, %xmm3, %xmm7, %xmm5, 1 // 32--35 + midround %xmm1, %xmm2, %xmm3, %xmm0, %xmm5, %xmm7, 1 // 36--39 + midround %xmm2, %xmm3, %xmm0, %xmm1, %xmm7, %xmm5, 2 // 40--43 + midround %xmm3, %xmm0, %xmm1, %xmm2, %xmm5, %xmm7, 2 // 44--47 + midround %xmm0, %xmm1, %xmm2, %xmm3, %xmm7, %xmm5, 2 // 48--51 + midround %xmm1, %xmm2, %xmm3, %xmm0, %xmm5, %xmm7, 2 // 52--55 + midround %xmm2, %xmm3, %xmm0, %xmm1, %xmm7, %xmm5, 2 // 56--59 + midround %xmm3, %xmm0, %xmm1, %xmm2, %xmm5, %xmm7, 3 // 60--63 + midround %xmm0, %xmm1, %xmm2, %xmm3, %xmm7, %xmm5, 3 // 64--67 + + // rounds 68--71 + sha1nexte %xmm1, %xmm5 + movdqa %xmm6, %xmm7 + sha1msg2 %xmm1, %xmm2 + sha1rnds4 $3, %xmm5, %xmm6 + pxor %xmm1, %xmm3 + + // rounds 72--75 + sha1nexte %xmm2, %xmm7 + movdqa %xmm6, %xmm5 + sha1msg2 %xmm2, %xmm3 + sha1rnds4 $3, %xmm7, %xmm6 + + // rounds 76--79 + sha1nexte %xmm3, %xmm5 + movdqa %xmm6, %xmm7 + sha1rnds4 $3, %xmm5, %xmm6 + + sha1nexte %xmm9, %xmm7 // add saved E + paddd %xmm8, %xmm6 // add saved ABCD + + cmp %rsi, %rcx // end reached? + jne 0b + + pshufd $0x1b, %xmm6, %xmm6 // restore order of h0--h3 + movdqu %xmm6, (%rdi) // write h0--h3 + pextrd $3, %xmm7, 16(%rdi) // write h4 +1: ret +END(_libmd_sha1block_shani) + + .section .rodata + .balign 16 +shuf_mask: + .8byte 0x08090a0b0c0d0e0f + .8byte 0x0001020304050607 + .size shuf_mask, .-shuf_mask + + .section .note.GNU-stack,"",%progbits diff --git a/lib/libmd/amd64/sha1dispatch.c b/lib/libmd/amd64/sha1dispatch.c new file mode 100644 index 000000000000..86509195d56e --- /dev/null +++ b/lib/libmd/amd64/sha1dispatch.c @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 2016 The Go Authors. All rights reserved. + * Copyright (c) 2024 Robert Clausecker <fuz@freebsd.org> + * + * Adapted from Go's crypto/sha1/sha1block_amd64.go. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 COPYRIGHT + * OWNER OR CONTRIBUTORS 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 <machine/specialreg.h> +#include <sha.h> +#include <x86/ifunc.h> + +extern void _libmd_sha1block_scalar(SHA1_CTX *, const void *, size_t); +extern void _libmd_sha1block_avx2(SHA1_CTX *, const void *, size_t); +extern void _libmd_sha1block_shani(SHA1_CTX *, const void *, size_t); +static void sha1block_avx2_wrapper(SHA1_CTX *, const void *, size_t); + +#define AVX2_STDEXT_NEEDED \ + (CPUID_STDEXT_BMI1 | CPUID_STDEXT_AVX2 | CPUID_STDEXT_BMI2) + +DEFINE_UIFUNC(, void, sha1_block, (SHA1_CTX *, const void *, size_t)) +{ + if (cpu_stdext_feature & CPUID_STDEXT_SHA) + return (_libmd_sha1block_shani); + if ((cpu_stdext_feature & AVX2_STDEXT_NEEDED) == AVX2_STDEXT_NEEDED) + return (sha1block_avx2_wrapper); + else + return (_libmd_sha1block_scalar); +} + +static void +sha1block_avx2_wrapper(SHA1_CTX *c, const void *data, size_t len) +{ + if (len >= 256) { + /* + * sha1block_avx2 calculates sha1 for 2 block per iteration. + * It also interleaves the precalculation for next the block. + * So it may read up-to 192 bytes past the end of p. + * We may add checks inside sha1block_avx2, but this will + * just turn it into a copy of sha1block_scalar, + * so call it directly, instead. + */ + size_t safe_len = len - 128; + + if (safe_len % 128 != 0) + safe_len -= 64; + + _libmd_sha1block_avx2(c, data, safe_len); + _libmd_sha1block_scalar(c, data + safe_len, len - safe_len); + } else + _libmd_sha1block_scalar(c, data, len); +} diff --git a/lib/libmd/i386/sha.S b/lib/libmd/i386/sha.S deleted file mode 100644 index 3bb54aa9b251..000000000000 --- a/lib/libmd/i386/sha.S +++ /dev/null @@ -1,1951 +0,0 @@ -/* -*- Fundamental -*- Emacs' assembler mode hoses this file */ -#ifndef PIC -/* Run the C pre-processor over this file with one of the following defined - * ELF - elf object files, - * OUT - a.out object files, - * BSDI - BSDI style a.out object files - * SOL - Solaris style elf - */ - -#define TYPE(a,b) .type a,b -#define SIZE(a,b) .size a,b - -#if defined(OUT) || defined(BSDI) -#define sha1_block_x86 _sha1_block_x86 - -#endif - -#ifdef OUT -#define OK 1 -#define ALIGN 4 -#endif - -#ifdef BSDI -#define OK 1 -#define ALIGN 4 -#undef SIZE -#undef TYPE -#define SIZE(a,b) -#define TYPE(a,b) -#endif - -#if defined(ELF) || defined(SOL) -#define OK 1 -#define ALIGN 4 -#endif - -#ifndef OK -You need to define one of -ELF - elf systems - linux-elf, NetBSD and DG-UX -OUT - a.out systems - linux-a.out and FreeBSD -SOL - solaris systems, which are elf with strange comment lines -BSDI - a.out with a very primative version of as. -#endif - -/* Let the Assembler begin :-) */ - /* Don't even think of reading this code */ - /* It was automatically generated by sha1-586.pl */ - /* Which is a perl program used to generate the x86 assember for */ - /* any of elf, a.out, BSDI,Win32, or Solaris */ - /* eric <eay@cryptsoft.com> */ - - .file "sha1-586.s" - .version "01.01" -gcc2_compiled.: -.text - .p2align ALIGN -.globl sha1_block_x86 - TYPE(sha1_block_x86,@function) -sha1_block_x86: - pushl %esi - pushl %ebp - movl 20(%esp), %eax - movl 16(%esp), %esi - addl %esi, %eax - movl 12(%esp), %ebp - pushl %ebx - subl $64, %eax - pushl %edi - movl 4(%ebp), %ebx - subl $72, %esp - movl 12(%ebp), %edx - movl 16(%ebp), %edi - movl 8(%ebp), %ecx - movl %eax, 68(%esp) - /* First we need to setup the X array */ - movl (%esi), %eax -.L000start: - /* First, load the words onto the stack in network byte order */ -.byte 15 -.byte 200 /* bswapl %eax */ - movl %eax, (%esp) - movl 4(%esi), %eax -.byte 15 -.byte 200 /* bswapl %eax */ - movl %eax, 4(%esp) - movl 8(%esi), %eax -.byte 15 -.byte 200 /* bswapl %eax */ - movl %eax, 8(%esp) - movl 12(%esi), %eax -.byte 15 -.byte 200 /* bswapl %eax */ - movl %eax, 12(%esp) - movl 16(%esi), %eax -.byte 15 -.byte 200 /* bswapl %eax */ - movl %eax, 16(%esp) - movl 20(%esi), %eax -.byte 15 -.byte 200 /* bswapl %eax */ - movl %eax, 20(%esp) - movl 24(%esi), %eax -.byte 15 -.byte 200 /* bswapl %eax */ - movl %eax, 24(%esp) - movl 28(%esi), %eax -.byte 15 -.byte 200 /* bswapl %eax */ - movl %eax, 28(%esp) - movl 32(%esi), %eax -.byte 15 -.byte 200 /* bswapl %eax */ - movl %eax, 32(%esp) - movl 36(%esi), %eax -.byte 15 -.byte 200 /* bswapl %eax */ - movl %eax, 36(%esp) - movl 40(%esi), %eax -.byte 15 -.byte 200 /* bswapl %eax */ - movl %eax, 40(%esp) - movl 44(%esi), %eax -.byte 15 -.byte 200 /* bswapl %eax */ - movl %eax, 44(%esp) - movl 48(%esi), %eax -.byte 15 -.byte 200 /* bswapl %eax */ - movl %eax, 48(%esp) - movl 52(%esi), %eax -.byte 15 -.byte 200 /* bswapl %eax */ - movl %eax, 52(%esp) - movl 56(%esi), %eax -.byte 15 -.byte 200 /* bswapl %eax */ - movl %eax, 56(%esp) - movl 60(%esi), %eax -.byte 15 -.byte 200 /* bswapl %eax */ - movl %eax, 60(%esp) - /* We now have the X array on the stack */ - /* starting at sp-4 */ - movl %esi, 64(%esp) - - /* Start processing */ - movl (%ebp), %eax - /* 00_15 0 */ - movl %ecx, %esi - movl %eax, %ebp - xorl %edx, %esi - roll $5, %ebp - andl %ebx, %esi - addl %edi, %ebp -.byte 209 -.byte 203 /* rorl $1 %ebx */ - movl (%esp), %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - xorl %edx, %esi - leal 1518500249(%ebp,%edi,1),%ebp - movl %ebx, %edi - addl %ebp, %esi - xorl %ecx, %edi - movl %esi, %ebp - andl %eax, %edi - roll $5, %ebp - addl %edx, %ebp - movl 4(%esp), %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - xorl %ecx, %edi -.byte 209 -.byte 200 /* rorl $1 %eax */ - leal 1518500249(%ebp,%edx,1),%ebp - addl %ebp, %edi - /* 00_15 2 */ - movl %eax, %edx - movl %edi, %ebp - xorl %ebx, %edx - roll $5, %ebp - andl %esi, %edx - addl %ecx, %ebp -.byte 209 -.byte 206 /* rorl $1 %esi */ - movl 8(%esp), %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - xorl %ebx, %edx - leal 1518500249(%ebp,%ecx,1),%ebp - movl %esi, %ecx - addl %ebp, %edx - xorl %eax, %ecx - movl %edx, %ebp - andl %edi, %ecx - roll $5, %ebp - addl %ebx, %ebp - movl 12(%esp), %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - xorl %eax, %ecx -.byte 209 -.byte 207 /* rorl $1 %edi */ - leal 1518500249(%ebp,%ebx,1),%ebp - addl %ebp, %ecx - /* 00_15 4 */ - movl %edi, %ebx - movl %ecx, %ebp - xorl %esi, %ebx - roll $5, %ebp - andl %edx, %ebx - addl %eax, %ebp -.byte 209 -.byte 202 /* rorl $1 %edx */ - movl 16(%esp), %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - xorl %esi, %ebx - leal 1518500249(%ebp,%eax,1),%ebp - movl %edx, %eax - addl %ebp, %ebx - xorl %edi, %eax - movl %ebx, %ebp - andl %ecx, %eax - roll $5, %ebp - addl %esi, %ebp - movl 20(%esp), %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - xorl %edi, %eax -.byte 209 -.byte 201 /* rorl $1 %ecx */ - leal 1518500249(%ebp,%esi,1),%ebp - addl %ebp, %eax - /* 00_15 6 */ - movl %ecx, %esi - movl %eax, %ebp - xorl %edx, %esi - roll $5, %ebp - andl %ebx, %esi - addl %edi, %ebp -.byte 209 -.byte 203 /* rorl $1 %ebx */ - movl 24(%esp), %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - xorl %edx, %esi - leal 1518500249(%ebp,%edi,1),%ebp - movl %ebx, %edi - addl %ebp, %esi - xorl %ecx, %edi - movl %esi, %ebp - andl %eax, %edi - roll $5, %ebp - addl %edx, %ebp - movl 28(%esp), %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - xorl %ecx, %edi -.byte 209 -.byte 200 /* rorl $1 %eax */ - leal 1518500249(%ebp,%edx,1),%ebp - addl %ebp, %edi - /* 00_15 8 */ - movl %eax, %edx - movl %edi, %ebp - xorl %ebx, %edx - roll $5, %ebp - andl %esi, %edx - addl %ecx, %ebp -.byte 209 -.byte 206 /* rorl $1 %esi */ - movl 32(%esp), %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - xorl %ebx, %edx - leal 1518500249(%ebp,%ecx,1),%ebp - movl %esi, %ecx - addl %ebp, %edx - xorl %eax, %ecx - movl %edx, %ebp - andl %edi, %ecx - roll $5, %ebp - addl %ebx, %ebp - movl 36(%esp), %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - xorl %eax, %ecx -.byte 209 -.byte 207 /* rorl $1 %edi */ - leal 1518500249(%ebp,%ebx,1),%ebp - addl %ebp, %ecx - /* 00_15 10 */ - movl %edi, %ebx - movl %ecx, %ebp - xorl %esi, %ebx - roll $5, %ebp - andl %edx, %ebx - addl %eax, %ebp -.byte 209 -.byte 202 /* rorl $1 %edx */ - movl 40(%esp), %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - xorl %esi, %ebx - leal 1518500249(%ebp,%eax,1),%ebp - movl %edx, %eax - addl %ebp, %ebx - xorl %edi, %eax - movl %ebx, %ebp - andl %ecx, %eax - roll $5, %ebp - addl %esi, %ebp - movl 44(%esp), %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - xorl %edi, %eax -.byte 209 -.byte 201 /* rorl $1 %ecx */ - leal 1518500249(%ebp,%esi,1),%ebp - addl %ebp, %eax - /* 00_15 12 */ - movl %ecx, %esi - movl %eax, %ebp - xorl %edx, %esi - roll $5, %ebp - andl %ebx, %esi - addl %edi, %ebp -.byte 209 -.byte 203 /* rorl $1 %ebx */ - movl 48(%esp), %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - xorl %edx, %esi - leal 1518500249(%ebp,%edi,1),%ebp - movl %ebx, %edi - addl %ebp, %esi - xorl %ecx, %edi - movl %esi, %ebp - andl %eax, %edi - roll $5, %ebp - addl %edx, %ebp - movl 52(%esp), %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - xorl %ecx, %edi -.byte 209 -.byte 200 /* rorl $1 %eax */ - leal 1518500249(%ebp,%edx,1),%ebp - addl %ebp, %edi - /* 00_15 14 */ - movl %eax, %edx - movl %edi, %ebp - xorl %ebx, %edx - roll $5, %ebp - andl %esi, %edx - addl %ecx, %ebp -.byte 209 -.byte 206 /* rorl $1 %esi */ - movl 56(%esp), %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - xorl %ebx, %edx - leal 1518500249(%ebp,%ecx,1),%ebp - movl %esi, %ecx - addl %ebp, %edx - xorl %eax, %ecx - movl %edx, %ebp - andl %edi, %ecx - roll $5, %ebp - addl %ebx, %ebp - movl 60(%esp), %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - xorl %eax, %ecx -.byte 209 -.byte 207 /* rorl $1 %edi */ - leal 1518500249(%ebp,%ebx,1),%ebp - addl %ebp, %ecx - /* 16_19 16 */ - nop - movl (%esp), %ebp - movl 8(%esp), %ebx - xorl %ebp, %ebx - movl 32(%esp), %ebp - xorl %ebp, %ebx - movl 52(%esp), %ebp - xorl %ebp, %ebx - movl %edi, %ebp -.byte 209 -.byte 195 /* roll $1 %ebx */ - xorl %esi, %ebp - movl %ebx, (%esp) - andl %edx, %ebp - leal 1518500249(%ebx,%eax,1),%ebx - xorl %esi, %ebp - movl %ecx, %eax - addl %ebp, %ebx - roll $5, %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - addl %eax, %ebx - movl 4(%esp), %eax - movl 12(%esp), %ebp - xorl %ebp, %eax - movl 36(%esp), %ebp - xorl %ebp, %eax - movl 56(%esp), %ebp -.byte 209 -.byte 202 /* rorl $1 %edx */ - xorl %ebp, %eax -.byte 209 -.byte 192 /* roll $1 %eax */ - movl %edx, %ebp - xorl %edi, %ebp - movl %eax, 4(%esp) - andl %ecx, %ebp - leal 1518500249(%eax,%esi,1),%eax - xorl %edi, %ebp - movl %ebx, %esi - roll $5, %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %esi, %eax -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %ebp, %eax - /* 16_19 18 */ - movl 8(%esp), %ebp - movl 16(%esp), %esi - xorl %ebp, %esi - movl 40(%esp), %ebp - xorl %ebp, %esi - movl 60(%esp), %ebp - xorl %ebp, %esi - movl %ecx, %ebp -.byte 209 -.byte 198 /* roll $1 %esi */ - xorl %edx, %ebp - movl %esi, 8(%esp) - andl %ebx, %ebp - leal 1518500249(%esi,%edi,1),%esi - xorl %edx, %ebp - movl %eax, %edi - addl %ebp, %esi - roll $5, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - addl %edi, %esi - movl 12(%esp), %edi - movl 20(%esp), %ebp - xorl %ebp, %edi - movl 44(%esp), %ebp - xorl %ebp, %edi - movl (%esp), %ebp -.byte 209 -.byte 203 /* rorl $1 %ebx */ - xorl %ebp, %edi -.byte 209 -.byte 199 /* roll $1 %edi */ - movl %ebx, %ebp - xorl %ecx, %ebp - movl %edi, 12(%esp) - andl %eax, %ebp - leal 1518500249(%edi,%edx,1),%edi - xorl %ecx, %ebp - movl %esi, %edx - roll $5, %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %edx, %edi -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %ebp, %edi - /* 20_39 20 */ - movl 16(%esp), %edx - movl 24(%esp), %ebp - xorl %ebp, %edx - movl 48(%esp), %ebp - xorl %ebp, %edx - movl 4(%esp), %ebp - xorl %ebp, %edx - movl %esi, %ebp -.byte 209 -.byte 194 /* roll $1 %edx */ - xorl %eax, %ebp - movl %edx, 16(%esp) - xorl %ebx, %ebp - leal 1859775393(%edx,%ecx,1),%edx - movl %edi, %ecx - roll $5, %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - addl %ebp, %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - addl %ecx, %edx - /* 20_39 21 */ - movl 20(%esp), %ecx - movl 28(%esp), %ebp - xorl %ebp, %ecx - movl 52(%esp), %ebp - xorl %ebp, %ecx - movl 8(%esp), %ebp - xorl %ebp, %ecx - movl %edi, %ebp -.byte 209 -.byte 193 /* roll $1 %ecx */ - xorl %esi, %ebp - movl %ecx, 20(%esp) - xorl %eax, %ebp - leal 1859775393(%ecx,%ebx,1),%ecx - movl %edx, %ebx - roll $5, %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebp, %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebx, %ecx - /* 20_39 22 */ - movl 24(%esp), %ebx - movl 32(%esp), %ebp - xorl %ebp, %ebx - movl 56(%esp), %ebp - xorl %ebp, %ebx - movl 12(%esp), %ebp - xorl %ebp, %ebx - movl %edx, %ebp -.byte 209 -.byte 195 /* roll $1 %ebx */ - xorl %edi, %ebp - movl %ebx, 24(%esp) - xorl %esi, %ebp - leal 1859775393(%ebx,%eax,1),%ebx - movl %ecx, %eax - roll $5, %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - addl %ebp, %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - addl %eax, %ebx - /* 20_39 23 */ - movl 28(%esp), %eax - movl 36(%esp), %ebp - xorl %ebp, %eax - movl 60(%esp), %ebp - xorl %ebp, %eax - movl 16(%esp), %ebp - xorl %ebp, %eax - movl %ecx, %ebp -.byte 209 -.byte 192 /* roll $1 %eax */ - xorl %edx, %ebp - movl %eax, 28(%esp) - xorl %edi, %ebp - leal 1859775393(%eax,%esi,1),%eax - movl %ebx, %esi - roll $5, %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %ebp, %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %esi, %eax - /* 20_39 24 */ - movl 32(%esp), %esi - movl 40(%esp), %ebp - xorl %ebp, %esi - movl (%esp), %ebp - xorl %ebp, %esi - movl 20(%esp), %ebp - xorl %ebp, %esi - movl %ebx, %ebp -.byte 209 -.byte 198 /* roll $1 %esi */ - xorl %ecx, %ebp - movl %esi, 32(%esp) - xorl %edx, %ebp - leal 1859775393(%esi,%edi,1),%esi - movl %eax, %edi - roll $5, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - addl %ebp, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - addl %edi, %esi - /* 20_39 25 */ - movl 36(%esp), %edi - movl 44(%esp), %ebp - xorl %ebp, %edi - movl 4(%esp), %ebp - xorl %ebp, %edi - movl 24(%esp), %ebp - xorl %ebp, %edi - movl %eax, %ebp -.byte 209 -.byte 199 /* roll $1 %edi */ - xorl %ebx, %ebp - movl %edi, 36(%esp) - xorl %ecx, %ebp - leal 1859775393(%edi,%edx,1),%edi - movl %esi, %edx - roll $5, %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %ebp, %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %edx, %edi - /* 20_39 26 */ - movl 40(%esp), %edx - movl 48(%esp), %ebp - xorl %ebp, %edx - movl 8(%esp), %ebp - xorl %ebp, %edx - movl 28(%esp), %ebp - xorl %ebp, %edx - movl %esi, %ebp -.byte 209 -.byte 194 /* roll $1 %edx */ - xorl %eax, %ebp - movl %edx, 40(%esp) - xorl %ebx, %ebp - leal 1859775393(%edx,%ecx,1),%edx - movl %edi, %ecx - roll $5, %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - addl %ebp, %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - addl %ecx, %edx - /* 20_39 27 */ - movl 44(%esp), %ecx - movl 52(%esp), %ebp - xorl %ebp, %ecx - movl 12(%esp), %ebp - xorl %ebp, %ecx - movl 32(%esp), %ebp - xorl %ebp, %ecx - movl %edi, %ebp -.byte 209 -.byte 193 /* roll $1 %ecx */ - xorl %esi, %ebp - movl %ecx, 44(%esp) - xorl %eax, %ebp - leal 1859775393(%ecx,%ebx,1),%ecx - movl %edx, %ebx - roll $5, %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebp, %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebx, %ecx - /* 20_39 28 */ - movl 48(%esp), %ebx - movl 56(%esp), %ebp - xorl %ebp, %ebx - movl 16(%esp), %ebp - xorl %ebp, %ebx - movl 36(%esp), %ebp - xorl %ebp, %ebx - movl %edx, %ebp -.byte 209 -.byte 195 /* roll $1 %ebx */ - xorl %edi, %ebp - movl %ebx, 48(%esp) - xorl %esi, %ebp - leal 1859775393(%ebx,%eax,1),%ebx - movl %ecx, %eax - roll $5, %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - addl %ebp, %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - addl %eax, %ebx - /* 20_39 29 */ - movl 52(%esp), %eax - movl 60(%esp), %ebp - xorl %ebp, %eax - movl 20(%esp), %ebp - xorl %ebp, %eax - movl 40(%esp), %ebp - xorl %ebp, %eax - movl %ecx, %ebp -.byte 209 -.byte 192 /* roll $1 %eax */ - xorl %edx, %ebp - movl %eax, 52(%esp) - xorl %edi, %ebp - leal 1859775393(%eax,%esi,1),%eax - movl %ebx, %esi - roll $5, %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %ebp, %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %esi, %eax - /* 20_39 30 */ - movl 56(%esp), %esi - movl (%esp), %ebp - xorl %ebp, %esi - movl 24(%esp), %ebp - xorl %ebp, %esi - movl 44(%esp), %ebp - xorl %ebp, %esi - movl %ebx, %ebp -.byte 209 -.byte 198 /* roll $1 %esi */ - xorl %ecx, %ebp - movl %esi, 56(%esp) - xorl %edx, %ebp - leal 1859775393(%esi,%edi,1),%esi - movl %eax, %edi - roll $5, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - addl %ebp, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - addl %edi, %esi - /* 20_39 31 */ - movl 60(%esp), %edi - movl 4(%esp), %ebp - xorl %ebp, %edi - movl 28(%esp), %ebp - xorl %ebp, %edi - movl 48(%esp), %ebp - xorl %ebp, %edi - movl %eax, %ebp -.byte 209 -.byte 199 /* roll $1 %edi */ - xorl %ebx, %ebp - movl %edi, 60(%esp) - xorl %ecx, %ebp - leal 1859775393(%edi,%edx,1),%edi - movl %esi, %edx - roll $5, %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %ebp, %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %edx, %edi - /* 20_39 32 */ - movl (%esp), %edx - movl 8(%esp), %ebp - xorl %ebp, %edx - movl 32(%esp), %ebp - xorl %ebp, %edx - movl 52(%esp), %ebp - xorl %ebp, %edx - movl %esi, %ebp -.byte 209 -.byte 194 /* roll $1 %edx */ - xorl %eax, %ebp - movl %edx, (%esp) - xorl %ebx, %ebp - leal 1859775393(%edx,%ecx,1),%edx - movl %edi, %ecx - roll $5, %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - addl %ebp, %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - addl %ecx, %edx - /* 20_39 33 */ - movl 4(%esp), %ecx - movl 12(%esp), %ebp - xorl %ebp, %ecx - movl 36(%esp), %ebp - xorl %ebp, %ecx - movl 56(%esp), %ebp - xorl %ebp, %ecx - movl %edi, %ebp -.byte 209 -.byte 193 /* roll $1 %ecx */ - xorl %esi, %ebp - movl %ecx, 4(%esp) - xorl %eax, %ebp - leal 1859775393(%ecx,%ebx,1),%ecx - movl %edx, %ebx - roll $5, %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebp, %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebx, %ecx - /* 20_39 34 */ - movl 8(%esp), %ebx - movl 16(%esp), %ebp - xorl %ebp, %ebx - movl 40(%esp), %ebp - xorl %ebp, %ebx - movl 60(%esp), %ebp - xorl %ebp, %ebx - movl %edx, %ebp -.byte 209 -.byte 195 /* roll $1 %ebx */ - xorl %edi, %ebp - movl %ebx, 8(%esp) - xorl %esi, %ebp - leal 1859775393(%ebx,%eax,1),%ebx - movl %ecx, %eax - roll $5, %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - addl %ebp, %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - addl %eax, %ebx - /* 20_39 35 */ - movl 12(%esp), %eax - movl 20(%esp), %ebp - xorl %ebp, %eax - movl 44(%esp), %ebp - xorl %ebp, %eax - movl (%esp), %ebp - xorl %ebp, %eax - movl %ecx, %ebp -.byte 209 -.byte 192 /* roll $1 %eax */ - xorl %edx, %ebp - movl %eax, 12(%esp) - xorl %edi, %ebp - leal 1859775393(%eax,%esi,1),%eax - movl %ebx, %esi - roll $5, %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %ebp, %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %esi, %eax - /* 20_39 36 */ - movl 16(%esp), %esi - movl 24(%esp), %ebp - xorl %ebp, %esi - movl 48(%esp), %ebp - xorl %ebp, %esi - movl 4(%esp), %ebp - xorl %ebp, %esi - movl %ebx, %ebp -.byte 209 -.byte 198 /* roll $1 %esi */ - xorl %ecx, %ebp - movl %esi, 16(%esp) - xorl %edx, %ebp - leal 1859775393(%esi,%edi,1),%esi - movl %eax, %edi - roll $5, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - addl %ebp, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - addl %edi, %esi - /* 20_39 37 */ - movl 20(%esp), %edi - movl 28(%esp), %ebp - xorl %ebp, %edi - movl 52(%esp), %ebp - xorl %ebp, %edi - movl 8(%esp), %ebp - xorl %ebp, %edi - movl %eax, %ebp -.byte 209 -.byte 199 /* roll $1 %edi */ - xorl %ebx, %ebp - movl %edi, 20(%esp) - xorl %ecx, %ebp - leal 1859775393(%edi,%edx,1),%edi - movl %esi, %edx - roll $5, %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %ebp, %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %edx, %edi - /* 20_39 38 */ - movl 24(%esp), %edx - movl 32(%esp), %ebp - xorl %ebp, %edx - movl 56(%esp), %ebp - xorl %ebp, %edx - movl 12(%esp), %ebp - xorl %ebp, %edx - movl %esi, %ebp -.byte 209 -.byte 194 /* roll $1 %edx */ - xorl %eax, %ebp - movl %edx, 24(%esp) - xorl %ebx, %ebp - leal 1859775393(%edx,%ecx,1),%edx - movl %edi, %ecx - roll $5, %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - addl %ebp, %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - addl %ecx, %edx - /* 20_39 39 */ - movl 28(%esp), %ecx - movl 36(%esp), %ebp - xorl %ebp, %ecx - movl 60(%esp), %ebp - xorl %ebp, %ecx - movl 16(%esp), %ebp - xorl %ebp, %ecx - movl %edi, %ebp -.byte 209 -.byte 193 /* roll $1 %ecx */ - xorl %esi, %ebp - movl %ecx, 28(%esp) - xorl %eax, %ebp - leal 1859775393(%ecx,%ebx,1),%ecx - movl %edx, %ebx - roll $5, %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebp, %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebx, %ecx - /* 40_59 40 */ - movl 32(%esp), %ebx - movl 40(%esp), %ebp - xorl %ebp, %ebx - movl (%esp), %ebp - xorl %ebp, %ebx - movl 20(%esp), %ebp - xorl %ebp, %ebx - movl %edx, %ebp -.byte 209 -.byte 195 /* roll $1 %ebx */ - orl %edi, %ebp - movl %ebx, 32(%esp) - andl %esi, %ebp - leal 2400959708(%ebx,%eax,1),%ebx - movl %edx, %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - andl %edi, %eax - orl %eax, %ebp - movl %ecx, %eax - roll $5, %eax - addl %eax, %ebp - movl 36(%esp), %eax - addl %ebp, %ebx - movl 44(%esp), %ebp - xorl %ebp, %eax - movl 4(%esp), %ebp - xorl %ebp, %eax - movl 24(%esp), %ebp -.byte 209 -.byte 202 /* rorl $1 %edx */ - xorl %ebp, %eax -.byte 209 -.byte 192 /* roll $1 %eax */ - movl %ecx, %ebp - movl %eax, 36(%esp) - orl %edx, %ebp - leal 2400959708(%eax,%esi,1),%eax - movl %ecx, %esi - andl %edi, %ebp - andl %edx, %esi - orl %esi, %ebp - movl %ebx, %esi - roll $5, %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %esi, %ebp -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %ebp, %eax - /* 40_59 41 */ - /* 40_59 42 */ - movl 40(%esp), %esi - movl 48(%esp), %ebp - xorl %ebp, %esi - movl 8(%esp), %ebp - xorl %ebp, %esi - movl 28(%esp), %ebp - xorl %ebp, %esi - movl %ebx, %ebp -.byte 209 -.byte 198 /* roll $1 %esi */ - orl %ecx, %ebp - movl %esi, 40(%esp) - andl %edx, %ebp - leal 2400959708(%esi,%edi,1),%esi - movl %ebx, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - andl %ecx, %edi - orl %edi, %ebp - movl %eax, %edi - roll $5, %edi - addl %edi, %ebp - movl 44(%esp), %edi - addl %ebp, %esi - movl 52(%esp), %ebp - xorl %ebp, %edi - movl 12(%esp), %ebp - xorl %ebp, %edi - movl 32(%esp), %ebp -.byte 209 -.byte 203 /* rorl $1 %ebx */ - xorl %ebp, %edi -.byte 209 -.byte 199 /* roll $1 %edi */ - movl %eax, %ebp - movl %edi, 44(%esp) - orl %ebx, %ebp - leal 2400959708(%edi,%edx,1),%edi - movl %eax, %edx - andl %ecx, %ebp - andl %ebx, %edx - orl %edx, %ebp - movl %esi, %edx - roll $5, %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %edx, %ebp -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %ebp, %edi - /* 40_59 43 */ - /* 40_59 44 */ - movl 48(%esp), %edx - movl 56(%esp), %ebp - xorl %ebp, %edx - movl 16(%esp), %ebp - xorl %ebp, %edx - movl 36(%esp), %ebp - xorl %ebp, %edx - movl %esi, %ebp -.byte 209 -.byte 194 /* roll $1 %edx */ - orl %eax, %ebp - movl %edx, 48(%esp) - andl %ebx, %ebp - leal 2400959708(%edx,%ecx,1),%edx - movl %esi, %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - andl %eax, %ecx - orl %ecx, %ebp - movl %edi, %ecx - roll $5, %ecx - addl %ecx, %ebp - movl 52(%esp), %ecx - addl %ebp, %edx - movl 60(%esp), %ebp - xorl %ebp, %ecx - movl 20(%esp), %ebp - xorl %ebp, %ecx - movl 40(%esp), %ebp -.byte 209 -.byte 206 /* rorl $1 %esi */ - xorl %ebp, %ecx -.byte 209 -.byte 193 /* roll $1 %ecx */ - movl %edi, %ebp - movl %ecx, 52(%esp) - orl %esi, %ebp - leal 2400959708(%ecx,%ebx,1),%ecx - movl %edi, %ebx - andl %eax, %ebp - andl %esi, %ebx - orl %ebx, %ebp - movl %edx, %ebx - roll $5, %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebx, %ebp -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebp, %ecx - /* 40_59 45 */ - /* 40_59 46 */ - movl 56(%esp), %ebx - movl (%esp), %ebp - xorl %ebp, %ebx - movl 24(%esp), %ebp - xorl %ebp, %ebx - movl 44(%esp), %ebp - xorl %ebp, %ebx - movl %edx, %ebp -.byte 209 -.byte 195 /* roll $1 %ebx */ - orl %edi, %ebp - movl %ebx, 56(%esp) - andl %esi, %ebp - leal 2400959708(%ebx,%eax,1),%ebx - movl %edx, %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - andl %edi, %eax - orl %eax, %ebp - movl %ecx, %eax - roll $5, %eax - addl %eax, %ebp - movl 60(%esp), %eax - addl %ebp, %ebx - movl 4(%esp), %ebp - xorl %ebp, %eax - movl 28(%esp), %ebp - xorl %ebp, %eax - movl 48(%esp), %ebp -.byte 209 -.byte 202 /* rorl $1 %edx */ - xorl %ebp, %eax -.byte 209 -.byte 192 /* roll $1 %eax */ - movl %ecx, %ebp - movl %eax, 60(%esp) - orl %edx, %ebp - leal 2400959708(%eax,%esi,1),%eax - movl %ecx, %esi - andl %edi, %ebp - andl %edx, %esi - orl %esi, %ebp - movl %ebx, %esi - roll $5, %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %esi, %ebp -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %ebp, %eax - /* 40_59 47 */ - /* 40_59 48 */ - movl (%esp), %esi - movl 8(%esp), %ebp - xorl %ebp, %esi - movl 32(%esp), %ebp - xorl %ebp, %esi - movl 52(%esp), %ebp - xorl %ebp, %esi - movl %ebx, %ebp -.byte 209 -.byte 198 /* roll $1 %esi */ - orl %ecx, %ebp - movl %esi, (%esp) - andl %edx, %ebp - leal 2400959708(%esi,%edi,1),%esi - movl %ebx, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - andl %ecx, %edi - orl %edi, %ebp - movl %eax, %edi - roll $5, %edi - addl %edi, %ebp - movl 4(%esp), %edi - addl %ebp, %esi - movl 12(%esp), %ebp - xorl %ebp, %edi - movl 36(%esp), %ebp - xorl %ebp, %edi - movl 56(%esp), %ebp -.byte 209 -.byte 203 /* rorl $1 %ebx */ - xorl %ebp, %edi -.byte 209 -.byte 199 /* roll $1 %edi */ - movl %eax, %ebp - movl %edi, 4(%esp) - orl %ebx, %ebp - leal 2400959708(%edi,%edx,1),%edi - movl %eax, %edx - andl %ecx, %ebp - andl %ebx, %edx - orl %edx, %ebp - movl %esi, %edx - roll $5, %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %edx, %ebp -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %ebp, %edi - /* 40_59 49 */ - /* 40_59 50 */ - movl 8(%esp), %edx - movl 16(%esp), %ebp - xorl %ebp, %edx - movl 40(%esp), %ebp - xorl %ebp, %edx - movl 60(%esp), %ebp - xorl %ebp, %edx - movl %esi, %ebp -.byte 209 -.byte 194 /* roll $1 %edx */ - orl %eax, %ebp - movl %edx, 8(%esp) - andl %ebx, %ebp - leal 2400959708(%edx,%ecx,1),%edx - movl %esi, %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - andl %eax, %ecx - orl %ecx, %ebp - movl %edi, %ecx - roll $5, %ecx - addl %ecx, %ebp - movl 12(%esp), %ecx - addl %ebp, %edx - movl 20(%esp), %ebp - xorl %ebp, %ecx - movl 44(%esp), %ebp - xorl %ebp, %ecx - movl (%esp), %ebp -.byte 209 -.byte 206 /* rorl $1 %esi */ - xorl %ebp, %ecx -.byte 209 -.byte 193 /* roll $1 %ecx */ - movl %edi, %ebp - movl %ecx, 12(%esp) - orl %esi, %ebp - leal 2400959708(%ecx,%ebx,1),%ecx - movl %edi, %ebx - andl %eax, %ebp - andl %esi, %ebx - orl %ebx, %ebp - movl %edx, %ebx - roll $5, %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebx, %ebp -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebp, %ecx - /* 40_59 51 */ - /* 40_59 52 */ - movl 16(%esp), %ebx - movl 24(%esp), %ebp - xorl %ebp, %ebx - movl 48(%esp), %ebp - xorl %ebp, %ebx - movl 4(%esp), %ebp - xorl %ebp, %ebx - movl %edx, %ebp -.byte 209 -.byte 195 /* roll $1 %ebx */ - orl %edi, %ebp - movl %ebx, 16(%esp) - andl %esi, %ebp - leal 2400959708(%ebx,%eax,1),%ebx - movl %edx, %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - andl %edi, %eax - orl %eax, %ebp - movl %ecx, %eax - roll $5, %eax - addl %eax, %ebp - movl 20(%esp), %eax - addl %ebp, %ebx - movl 28(%esp), %ebp - xorl %ebp, %eax - movl 52(%esp), %ebp - xorl %ebp, %eax - movl 8(%esp), %ebp -.byte 209 -.byte 202 /* rorl $1 %edx */ - xorl %ebp, %eax -.byte 209 -.byte 192 /* roll $1 %eax */ - movl %ecx, %ebp - movl %eax, 20(%esp) - orl %edx, %ebp - leal 2400959708(%eax,%esi,1),%eax - movl %ecx, %esi - andl %edi, %ebp - andl %edx, %esi - orl %esi, %ebp - movl %ebx, %esi - roll $5, %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %esi, %ebp -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %ebp, %eax - /* 40_59 53 */ - /* 40_59 54 */ - movl 24(%esp), %esi - movl 32(%esp), %ebp - xorl %ebp, %esi - movl 56(%esp), %ebp - xorl %ebp, %esi - movl 12(%esp), %ebp - xorl %ebp, %esi - movl %ebx, %ebp -.byte 209 -.byte 198 /* roll $1 %esi */ - orl %ecx, %ebp - movl %esi, 24(%esp) - andl %edx, %ebp - leal 2400959708(%esi,%edi,1),%esi - movl %ebx, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - andl %ecx, %edi - orl %edi, %ebp - movl %eax, %edi - roll $5, %edi - addl %edi, %ebp - movl 28(%esp), %edi - addl %ebp, %esi - movl 36(%esp), %ebp - xorl %ebp, %edi - movl 60(%esp), %ebp - xorl %ebp, %edi - movl 16(%esp), %ebp -.byte 209 -.byte 203 /* rorl $1 %ebx */ - xorl %ebp, %edi -.byte 209 -.byte 199 /* roll $1 %edi */ - movl %eax, %ebp - movl %edi, 28(%esp) - orl %ebx, %ebp - leal 2400959708(%edi,%edx,1),%edi - movl %eax, %edx - andl %ecx, %ebp - andl %ebx, %edx - orl %edx, %ebp - movl %esi, %edx - roll $5, %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %edx, %ebp -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %ebp, %edi - /* 40_59 55 */ - /* 40_59 56 */ - movl 32(%esp), %edx - movl 40(%esp), %ebp - xorl %ebp, %edx - movl (%esp), %ebp - xorl %ebp, %edx - movl 20(%esp), %ebp - xorl %ebp, %edx - movl %esi, %ebp -.byte 209 -.byte 194 /* roll $1 %edx */ - orl %eax, %ebp - movl %edx, 32(%esp) - andl %ebx, %ebp - leal 2400959708(%edx,%ecx,1),%edx - movl %esi, %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - andl %eax, %ecx - orl %ecx, %ebp - movl %edi, %ecx - roll $5, %ecx - addl %ecx, %ebp - movl 36(%esp), %ecx - addl %ebp, %edx - movl 44(%esp), %ebp - xorl %ebp, %ecx - movl 4(%esp), %ebp - xorl %ebp, %ecx - movl 24(%esp), %ebp -.byte 209 -.byte 206 /* rorl $1 %esi */ - xorl %ebp, %ecx -.byte 209 -.byte 193 /* roll $1 %ecx */ - movl %edi, %ebp - movl %ecx, 36(%esp) - orl %esi, %ebp - leal 2400959708(%ecx,%ebx,1),%ecx - movl %edi, %ebx - andl %eax, %ebp - andl %esi, %ebx - orl %ebx, %ebp - movl %edx, %ebx - roll $5, %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebx, %ebp -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebp, %ecx - /* 40_59 57 */ - /* 40_59 58 */ - movl 40(%esp), %ebx - movl 48(%esp), %ebp - xorl %ebp, %ebx - movl 8(%esp), %ebp - xorl %ebp, %ebx - movl 28(%esp), %ebp - xorl %ebp, %ebx - movl %edx, %ebp -.byte 209 -.byte 195 /* roll $1 %ebx */ - orl %edi, %ebp - movl %ebx, 40(%esp) - andl %esi, %ebp - leal 2400959708(%ebx,%eax,1),%ebx - movl %edx, %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - andl %edi, %eax - orl %eax, %ebp - movl %ecx, %eax - roll $5, %eax - addl %eax, %ebp - movl 44(%esp), %eax - addl %ebp, %ebx - movl 52(%esp), %ebp - xorl %ebp, %eax - movl 12(%esp), %ebp - xorl %ebp, %eax - movl 32(%esp), %ebp -.byte 209 -.byte 202 /* rorl $1 %edx */ - xorl %ebp, %eax -.byte 209 -.byte 192 /* roll $1 %eax */ - movl %ecx, %ebp - movl %eax, 44(%esp) - orl %edx, %ebp - leal 2400959708(%eax,%esi,1),%eax - movl %ecx, %esi - andl %edi, %ebp - andl %edx, %esi - orl %esi, %ebp - movl %ebx, %esi - roll $5, %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %esi, %ebp -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %ebp, %eax - /* 40_59 59 */ - /* 20_39 60 */ - movl 48(%esp), %esi - movl 56(%esp), %ebp - xorl %ebp, %esi - movl 16(%esp), %ebp - xorl %ebp, %esi - movl 36(%esp), %ebp - xorl %ebp, %esi - movl %ebx, %ebp -.byte 209 -.byte 198 /* roll $1 %esi */ - xorl %ecx, %ebp - movl %esi, 48(%esp) - xorl %edx, %ebp - leal 3395469782(%esi,%edi,1),%esi - movl %eax, %edi - roll $5, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - addl %ebp, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - addl %edi, %esi - /* 20_39 61 */ - movl 52(%esp), %edi - movl 60(%esp), %ebp - xorl %ebp, %edi - movl 20(%esp), %ebp - xorl %ebp, %edi - movl 40(%esp), %ebp - xorl %ebp, %edi - movl %eax, %ebp -.byte 209 -.byte 199 /* roll $1 %edi */ - xorl %ebx, %ebp - movl %edi, 52(%esp) - xorl %ecx, %ebp - leal 3395469782(%edi,%edx,1),%edi - movl %esi, %edx - roll $5, %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %ebp, %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %edx, %edi - /* 20_39 62 */ - movl 56(%esp), %edx - movl (%esp), %ebp - xorl %ebp, %edx - movl 24(%esp), %ebp - xorl %ebp, %edx - movl 44(%esp), %ebp - xorl %ebp, %edx - movl %esi, %ebp -.byte 209 -.byte 194 /* roll $1 %edx */ - xorl %eax, %ebp - movl %edx, 56(%esp) - xorl %ebx, %ebp - leal 3395469782(%edx,%ecx,1),%edx - movl %edi, %ecx - roll $5, %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - addl %ebp, %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - addl %ecx, %edx - /* 20_39 63 */ - movl 60(%esp), %ecx - movl 4(%esp), %ebp - xorl %ebp, %ecx - movl 28(%esp), %ebp - xorl %ebp, %ecx - movl 48(%esp), %ebp - xorl %ebp, %ecx - movl %edi, %ebp -.byte 209 -.byte 193 /* roll $1 %ecx */ - xorl %esi, %ebp - movl %ecx, 60(%esp) - xorl %eax, %ebp - leal 3395469782(%ecx,%ebx,1),%ecx - movl %edx, %ebx - roll $5, %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebp, %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebx, %ecx - /* 20_39 64 */ - movl (%esp), %ebx - movl 8(%esp), %ebp - xorl %ebp, %ebx - movl 32(%esp), %ebp - xorl %ebp, %ebx - movl 52(%esp), %ebp - xorl %ebp, %ebx - movl %edx, %ebp -.byte 209 -.byte 195 /* roll $1 %ebx */ - xorl %edi, %ebp - movl %ebx, (%esp) - xorl %esi, %ebp - leal 3395469782(%ebx,%eax,1),%ebx - movl %ecx, %eax - roll $5, %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - addl %ebp, %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - addl %eax, %ebx - /* 20_39 65 */ - movl 4(%esp), %eax - movl 12(%esp), %ebp - xorl %ebp, %eax - movl 36(%esp), %ebp - xorl %ebp, %eax - movl 56(%esp), %ebp - xorl %ebp, %eax - movl %ecx, %ebp -.byte 209 -.byte 192 /* roll $1 %eax */ - xorl %edx, %ebp - movl %eax, 4(%esp) - xorl %edi, %ebp - leal 3395469782(%eax,%esi,1),%eax - movl %ebx, %esi - roll $5, %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %ebp, %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %esi, %eax - /* 20_39 66 */ - movl 8(%esp), %esi - movl 16(%esp), %ebp - xorl %ebp, %esi - movl 40(%esp), %ebp - xorl %ebp, %esi - movl 60(%esp), %ebp - xorl %ebp, %esi - movl %ebx, %ebp -.byte 209 -.byte 198 /* roll $1 %esi */ - xorl %ecx, %ebp - movl %esi, 8(%esp) - xorl %edx, %ebp - leal 3395469782(%esi,%edi,1),%esi - movl %eax, %edi - roll $5, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - addl %ebp, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - addl %edi, %esi - /* 20_39 67 */ - movl 12(%esp), %edi - movl 20(%esp), %ebp - xorl %ebp, %edi - movl 44(%esp), %ebp - xorl %ebp, %edi - movl (%esp), %ebp - xorl %ebp, %edi - movl %eax, %ebp -.byte 209 -.byte 199 /* roll $1 %edi */ - xorl %ebx, %ebp - movl %edi, 12(%esp) - xorl %ecx, %ebp - leal 3395469782(%edi,%edx,1),%edi - movl %esi, %edx - roll $5, %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %ebp, %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %edx, %edi - /* 20_39 68 */ - movl 16(%esp), %edx - movl 24(%esp), %ebp - xorl %ebp, %edx - movl 48(%esp), %ebp - xorl %ebp, %edx - movl 4(%esp), %ebp - xorl %ebp, %edx - movl %esi, %ebp -.byte 209 -.byte 194 /* roll $1 %edx */ - xorl %eax, %ebp - movl %edx, 16(%esp) - xorl %ebx, %ebp - leal 3395469782(%edx,%ecx,1),%edx - movl %edi, %ecx - roll $5, %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - addl %ebp, %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - addl %ecx, %edx - /* 20_39 69 */ - movl 20(%esp), %ecx - movl 28(%esp), %ebp - xorl %ebp, %ecx - movl 52(%esp), %ebp - xorl %ebp, %ecx - movl 8(%esp), %ebp - xorl %ebp, %ecx - movl %edi, %ebp -.byte 209 -.byte 193 /* roll $1 %ecx */ - xorl %esi, %ebp - movl %ecx, 20(%esp) - xorl %eax, %ebp - leal 3395469782(%ecx,%ebx,1),%ecx - movl %edx, %ebx - roll $5, %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebp, %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebx, %ecx - /* 20_39 70 */ - movl 24(%esp), %ebx - movl 32(%esp), %ebp - xorl %ebp, %ebx - movl 56(%esp), %ebp - xorl %ebp, %ebx - movl 12(%esp), %ebp - xorl %ebp, %ebx - movl %edx, %ebp -.byte 209 -.byte 195 /* roll $1 %ebx */ - xorl %edi, %ebp - movl %ebx, 24(%esp) - xorl %esi, %ebp - leal 3395469782(%ebx,%eax,1),%ebx - movl %ecx, %eax - roll $5, %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - addl %ebp, %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - addl %eax, %ebx - /* 20_39 71 */ - movl 28(%esp), %eax - movl 36(%esp), %ebp - xorl %ebp, %eax - movl 60(%esp), %ebp - xorl %ebp, %eax - movl 16(%esp), %ebp - xorl %ebp, %eax - movl %ecx, %ebp -.byte 209 -.byte 192 /* roll $1 %eax */ - xorl %edx, %ebp - movl %eax, 28(%esp) - xorl %edi, %ebp - leal 3395469782(%eax,%esi,1),%eax - movl %ebx, %esi - roll $5, %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %ebp, %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %esi, %eax - /* 20_39 72 */ - movl 32(%esp), %esi - movl 40(%esp), %ebp - xorl %ebp, %esi - movl (%esp), %ebp - xorl %ebp, %esi - movl 20(%esp), %ebp - xorl %ebp, %esi - movl %ebx, %ebp -.byte 209 -.byte 198 /* roll $1 %esi */ - xorl %ecx, %ebp - movl %esi, 32(%esp) - xorl %edx, %ebp - leal 3395469782(%esi,%edi,1),%esi - movl %eax, %edi - roll $5, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - addl %ebp, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - addl %edi, %esi - /* 20_39 73 */ - movl 36(%esp), %edi - movl 44(%esp), %ebp - xorl %ebp, %edi - movl 4(%esp), %ebp - xorl %ebp, %edi - movl 24(%esp), %ebp - xorl %ebp, %edi - movl %eax, %ebp -.byte 209 -.byte 199 /* roll $1 %edi */ - xorl %ebx, %ebp - movl %edi, 36(%esp) - xorl %ecx, %ebp - leal 3395469782(%edi,%edx,1),%edi - movl %esi, %edx - roll $5, %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %ebp, %edx -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %edx, %edi - /* 20_39 74 */ - movl 40(%esp), %edx - movl 48(%esp), %ebp - xorl %ebp, %edx - movl 8(%esp), %ebp - xorl %ebp, %edx - movl 28(%esp), %ebp - xorl %ebp, %edx - movl %esi, %ebp -.byte 209 -.byte 194 /* roll $1 %edx */ - xorl %eax, %ebp - movl %edx, 40(%esp) - xorl %ebx, %ebp - leal 3395469782(%edx,%ecx,1),%edx - movl %edi, %ecx - roll $5, %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - addl %ebp, %ecx -.byte 209 -.byte 206 /* rorl $1 %esi */ - addl %ecx, %edx - /* 20_39 75 */ - movl 44(%esp), %ecx - movl 52(%esp), %ebp - xorl %ebp, %ecx - movl 12(%esp), %ebp - xorl %ebp, %ecx - movl 32(%esp), %ebp - xorl %ebp, %ecx - movl %edi, %ebp -.byte 209 -.byte 193 /* roll $1 %ecx */ - xorl %esi, %ebp - movl %ecx, 44(%esp) - xorl %eax, %ebp - leal 3395469782(%ecx,%ebx,1),%ecx - movl %edx, %ebx - roll $5, %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebp, %ebx -.byte 209 -.byte 207 /* rorl $1 %edi */ - addl %ebx, %ecx - /* 20_39 76 */ - movl 48(%esp), %ebx - movl 56(%esp), %ebp - xorl %ebp, %ebx - movl 16(%esp), %ebp - xorl %ebp, %ebx - movl 36(%esp), %ebp - xorl %ebp, %ebx - movl %edx, %ebp -.byte 209 -.byte 195 /* roll $1 %ebx */ - xorl %edi, %ebp - movl %ebx, 48(%esp) - xorl %esi, %ebp - leal 3395469782(%ebx,%eax,1),%ebx - movl %ecx, %eax - roll $5, %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - addl %ebp, %eax -.byte 209 -.byte 202 /* rorl $1 %edx */ - addl %eax, %ebx - /* 20_39 77 */ - movl 52(%esp), %eax - movl 60(%esp), %ebp - xorl %ebp, %eax - movl 20(%esp), %ebp - xorl %ebp, %eax - movl 40(%esp), %ebp - xorl %ebp, %eax - movl %ecx, %ebp -.byte 209 -.byte 192 /* roll $1 %eax */ - xorl %edx, %ebp - movl %eax, 52(%esp) - xorl %edi, %ebp - leal 3395469782(%eax,%esi,1),%eax - movl %ebx, %esi - roll $5, %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %ebp, %esi -.byte 209 -.byte 201 /* rorl $1 %ecx */ - addl %esi, %eax - /* 20_39 78 */ - movl 56(%esp), %esi - movl (%esp), %ebp - xorl %ebp, %esi - movl 24(%esp), %ebp - xorl %ebp, %esi - movl 44(%esp), %ebp - xorl %ebp, %esi - movl %ebx, %ebp -.byte 209 -.byte 198 /* roll $1 %esi */ - xorl %ecx, %ebp - movl %esi, 56(%esp) - xorl %edx, %ebp - leal 3395469782(%esi,%edi,1),%esi - movl %eax, %edi - roll $5, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - addl %ebp, %edi -.byte 209 -.byte 203 /* rorl $1 %ebx */ - addl %edi, %esi - /* 20_39 79 */ - movl 60(%esp), %edi - movl 4(%esp), %ebp - xorl %ebp, %edi - movl 28(%esp), %ebp - xorl %ebp, %edi - movl 48(%esp), %ebp - xorl %ebp, %edi - movl %eax, %ebp -.byte 209 -.byte 199 /* roll $1 %edi */ - xorl %ebx, %ebp - movl %edi, 60(%esp) - xorl %ecx, %ebp - leal 3395469782(%edi,%edx,1),%edi - movl %esi, %edx - roll $5, %edx - addl %ebp, %edx - movl 92(%esp), %ebp -.byte 209 -.byte 200 /* rorl $1 %eax */ - addl %edx, %edi -.byte 209 -.byte 200 /* rorl $1 %eax */ - /* End processing */ - - movl 12(%ebp), %edx - addl %ebx, %edx - movl 4(%ebp), %ebx - addl %esi, %ebx - movl %eax, %esi - movl (%ebp), %eax - movl %edx, 12(%ebp) - addl %edi, %eax - movl 16(%ebp), %edi - addl %ecx, %edi - movl 8(%ebp), %ecx - addl %esi, %ecx - movl %eax, (%ebp) - movl 64(%esp), %esi - movl %ecx, 8(%ebp) - addl $64, %esi - movl 68(%esp), %eax - movl %edi, 16(%ebp) - cmpl %esi, %eax - movl %ebx, 4(%ebp) - jb .L001end - movl (%esi), %eax - jmp .L000start -.L001end: - addl $72, %esp - popl %edi - popl %ebx - popl %ebp - popl %esi - ret -.sha1_block_x86_end: - SIZE(sha1_block_x86,.sha1_block_x86_end-sha1_block_x86) -.ident "desasm.pl" -#endif diff --git a/lib/libmd/sha1c.c b/lib/libmd/sha1c.c index 83e402e132e7..128e0b991742 100644 --- a/lib/libmd/sha1c.c +++ b/lib/libmd/sha1c.c @@ -1,476 +1,244 @@ -/* crypto/sha/sha1dgst.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. +/*- + * Copyright (c) 2009 The Go Authors. All rights reserved. + * Copyright (c) 2024 Robert Clausecker <fuz@freebsd.org> + * + * Adapted from Go's crypto/sha1/sha1.go. * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * * 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 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the routines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 OR CONTRIBUTORS 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. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 COPYRIGHT + * OWNER OR CONTRIBUTORS 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 <sys/types.h> - -#include <stdio.h> +#include <assert.h> +#include <sha.h> +#include <stdint.h> #include <string.h> +#include <strings.h> +#include <sys/endian.h> -#if 0 -#include <machine/ansi.h> /* we use the __ variants of bit-sized types */ +#ifdef SHA1_ASM +extern void sha1_block(SHA1_CTX *, const void *, size_t); +#else +static void sha1_block(SHA1_CTX *, const void *, size_t); #endif -#include <machine/endian.h> -#undef SHA_0 -#define SHA_1 -#include "sha.h" -#include "sha_locl.h" +#define INIT0 0x67452301 +#define INIT1 0xEFCDAB89 +#define INIT2 0x98BADCFE +#define INIT3 0x10325476 +#define INIT4 0xC3D2E1F0 -/* - * The assembly-language code is not position-independent, so don't - * try to use it in a shared library. - */ -#ifdef PIC -#undef SHA1_ASM -#endif +#define K0 0x5A827999 +#define K1 0x6ED9EBA1 +#define K2 0x8F1BBCDC +#define K3 0xCA62C1D6 -static char *SHA1_version="SHA1 part of SSLeay 0.9.0b 11-Oct-1998"; +void +SHA1_Init(SHA1_CTX *c) +{ + c->h0 = INIT0; + c->h1 = INIT1; + c->h2 = INIT2; + c->h3 = INIT3; + c->h4 = INIT4; + c->Nl = 0; + c->Nh = 0; + c->num = 0; +} -/* Implemented from SHA-1 document - The Secure Hash Algorithm - */ +void +SHA1_Update(SHA1_CTX *c, const void *data, size_t len) +{ + uint64_t nn; + const char *p = data; -#define INIT_DATA_h0 (unsigned long)0x67452301L -#define INIT_DATA_h1 (unsigned long)0xefcdab89L -#define INIT_DATA_h2 (unsigned long)0x98badcfeL -#define INIT_DATA_h3 (unsigned long)0x10325476L -#define INIT_DATA_h4 (unsigned long)0xc3d2e1f0L - -#define K_00_19 0x5a827999L -#define K_20_39 0x6ed9eba1L -#define K_40_59 0x8f1bbcdcL -#define K_60_79 0xca62c1d6L - -#ifndef NOPROTO -# ifdef SHA1_ASM - void sha1_block_x86(SHA_CTX *c, const u_int32_t *p, int num); -# define sha1_block sha1_block_x86 -# else - void sha1_block(SHA_CTX *c, const u_int32_t *p, int num); -# endif -#else -# ifdef SHA1_ASM - void sha1_block_x86(); -# define sha1_block sha1_block_x86 -# else - void sha1_block(); -# endif -#endif + nn = (uint64_t)c->Nl | (uint64_t)c->Nh << 32; + nn += len; + c->Nl = (uint32_t)nn; + c->Nh = (uint32_t)(nn >> 32); + if (c->num > 0) { + size_t n = SHA_CBLOCK - c->num; -#if BYTE_ORDER == LITTLE_ENDIAN && defined(SHA1_ASM) -# define M_c2nl c2l -# define M_p_c2nl p_c2l -# define M_c2nl_p c2l_p -# define M_p_c2nl_p p_c2l_p -# define M_nl2c l2c -#else -# define M_c2nl c2nl -# define M_p_c2nl p_c2nl -# define M_c2nl_p c2nl_p -# define M_p_c2nl_p p_c2nl_p -# define M_nl2c nl2c -#endif + if (n > len) + n = len; + + memcpy((char *)c->data + c->num, p, n); + c->num += n; + if (c->num == SHA_CBLOCK) { + sha1_block(c, (void *)c->data, SHA_CBLOCK); + c->num = 0; + } + + p += n; + len -= n; + } + + if (len >= SHA_CBLOCK) { + size_t n = len & ~(size_t)(SHA_CBLOCK - 1); + + sha1_block(c, p, n); + p += n; + len -= n; + } -void SHA1_Init(SHA_CTX *c) - { - c->h0=INIT_DATA_h0; - c->h1=INIT_DATA_h1; - c->h2=INIT_DATA_h2; - c->h3=INIT_DATA_h3; - c->h4=INIT_DATA_h4; - c->Nl=0; - c->Nh=0; - c->num=0; + if (len > 0) { + memcpy(c->data, p, len); + c->num = len; } +} void -SHA1_Update(SHA_CTX *c, const void *in, size_t len) +SHA1_Final(unsigned char *md, SHA1_CTX *c) { - u_int32_t *p; - int ew,ec,sw,sc; - u_int32_t l; - const unsigned char *data = in; - - if (len == 0) return; - - l=(c->Nl+(len<<3))&0xffffffffL; - if (l < c->Nl) /* overflow */ - c->Nh++; - c->Nh+=(len>>29); - c->Nl=l; - - if (c->num != 0) - { - p=c->data; - sw=c->num>>2; - sc=c->num&0x03; - - if ((c->num+len) >= SHA_CBLOCK) - { - l= p[sw]; - M_p_c2nl(data,l,sc); - p[sw++]=l; - for (; sw<SHA_LBLOCK; sw++) - { - M_c2nl(data,l); - p[sw]=l; - } - len-=(SHA_CBLOCK-c->num); - - sha1_block(c,p,64); - c->num=0; - /* drop through and do the rest */ - } - else - { - c->num+=(int)len; - if ((sc+len) < 4) /* ugly, add char's to a word */ - { - l= p[sw]; - M_p_c2nl_p(data,l,sc,len); - p[sw]=l; - } - else - { - ew=(c->num>>2); - ec=(c->num&0x03); - l= p[sw]; - M_p_c2nl(data,l,sc); - p[sw++]=l; - for (; sw < ew; sw++) - { M_c2nl(data,l); p[sw]=l; } - if (ec) - { - M_c2nl_p(data,l,ec); - p[sw]=l; - } - } - return; - } + uint64_t len; + size_t t; + unsigned char tmp[SHA_CBLOCK + sizeof(uint64_t)] = {0x80, 0}; + + len = (uint64_t)c->Nl | (uint64_t)c->Nh << 32; + t = 64 + 56 - c->Nl % 64; + if (t > 64) + t -= 64; + + /* length in bits */ + len <<= 3; + be64enc(tmp + t, len); + SHA1_Update(c, tmp, t + 8); + assert(c->num == 0); + + be32enc(md + 0, c->h0); + be32enc(md + 4, c->h1); + be32enc(md + 8, c->h2); + be32enc(md + 12, c->h3); + be32enc(md + 16, c->h4); + + explicit_bzero(c, sizeof(*c)); +} + +#ifndef SHA1_ASM +static void +/* invariant: len is a multiple of SHA_CBLOCK */ +sha1_block(SHA1_CTX *c, const void *data, size_t len) +{ + uint32_t w[16]; + uint32_t h0 = c->h0, h1 = c->h1, h2 = c->h2, h3 = c->h3, h4 = c->h4; + const char *p = data; + + while (len >= SHA_CBLOCK) { + size_t i; + uint32_t a = h0, b = h1, c = h2, d = h3, e = h4; + uint32_t f, t, tmp; + +# pragma unroll + for (i = 0; i < 16; i++) + w[i] = be32dec(p + 4*i); + +# pragma unroll + for (i = 0; i < 16; i++) { + f = b & c | ~b & d; + t = (a << 5 | a >> 32 - 5) + f + e + w[i & 0xf] + K0; + e = d; + d = c; + c = b << 30 | b >> 32 - 30; + b = a; + a = t; } - /* We can only do the following code for assember, the reason - * being that the sha1_block 'C' version changes the values - * in the 'data' array. The assember code avoids this and - * copies it to a local array. I should be able to do this for - * the C version as well.... - */ -#if 1 -#if BYTE_ORDER == BIG_ENDIAN || defined(SHA1_ASM) - if ((((unsigned int)data)%sizeof(u_int32_t)) == 0) - { - sw=len/SHA_CBLOCK; - if (sw) - { - sw*=SHA_CBLOCK; - sha1_block(c,(u_int32_t *)data,sw); - data+=sw; - len-=sw; - } + +# pragma unroll + for (; i < 20; i++) { + tmp = w[i - 3 & 0xf] ^ w[i - 8 & 0xf] ^ w[i - 14 & 0xf] ^ w[i & 0xf]; + w[i & 0xf] = tmp << 1 | tmp >> 32 - 1; + + f = b & c | ~b & d; + t = (a << 5 | a >> 32 - 5) + f + e + w[i & 0xf] + K0; + e = d; + d = c; + c = b << 30 | b >> 32 - 30; + b = a; + a = t; } -#endif -#endif - /* we now can process the input data in blocks of SHA_CBLOCK - * chars and save the leftovers to c->data. */ - p=c->data; - while (len >= SHA_CBLOCK) - { -#if BYTE_ORDER == BIG_ENDIAN || BYTE_ORDER == LITTLE_ENDIAN - if (p != (u_int32_t *)data) - memcpy(p,data,SHA_CBLOCK); - data+=SHA_CBLOCK; -# if BYTE_ORDER == LITTLE_ENDIAN -# ifndef SHA1_ASM /* Will not happen */ - for (sw=(SHA_LBLOCK/4); sw; sw--) - { - Endian_Reverse32(p[0]); - Endian_Reverse32(p[1]); - Endian_Reverse32(p[2]); - Endian_Reverse32(p[3]); - p+=4; - } - p=c->data; -# endif -# endif -#else - for (sw=(SHA_BLOCK/4); sw; sw--) - { - M_c2nl(data,l); *(p++)=l; - M_c2nl(data,l); *(p++)=l; - M_c2nl(data,l); *(p++)=l; - M_c2nl(data,l); *(p++)=l; - } - p=c->data; -#endif - sha1_block(c,p,64); - len-=SHA_CBLOCK; + +# pragma unroll + for (; i < 40; i++) { + tmp = w[i - 3 & 0xf] ^ w[i - 8 & 0xf] ^ w[i - 14 & 0xf] ^ w[i & 0xf]; + w[i & 0xf] = tmp << 1 | tmp >> 32 - 1; + + f = b ^ c ^ d; + t = (a << 5 | a >> 32 - 5) + f + e + w[i & 0xf] + K1; + e = d; + d = c; + c = b << 30 | b >> 32 - 30; + b = a; + a = t; } - ec=(int)len; - c->num=ec; - ew=(ec>>2); - ec&=0x03; - - for (sw=0; sw < ew; sw++) - { M_c2nl(data,l); p[sw]=l; } - M_c2nl_p(data,l,ec); - p[sw]=l; - } -static void SHA1_Transform(SHA_CTX *c, unsigned char *b) - { - u_int32_t p[16]; -#if BYTE_ORDER != BIG_ENDIAN - u_int32_t *q; - int i; -#endif +# pragma unroll + for (; i < 60; i++) { + tmp = w[i - 3 & 0xf] ^ w[i - 8 & 0xf] ^ w[i - 14 & 0xf] ^ w[i & 0xf]; + w[i & 0xf] = tmp << 1 | tmp >> 32 - 1; + + f = (b | c) & d | b & c; + t = (a << 5 | a >> 32 - 5) + f + e + w[i & 0xf] + K2; + e = d; + d = c; + c = b << 30 | b >> 32 - 30; + b = a; + a = t; + } -#if BYTE_ORDER == BIG_ENDIAN || BYTE_ORDER == LITTLE_ENDIAN - memcpy(p,b,64); -#if BYTE_ORDER == LITTLE_ENDIAN - q=p; - for (i=(SHA_LBLOCK/4); i; i--) - { - Endian_Reverse32(q[0]); - Endian_Reverse32(q[1]); - Endian_Reverse32(q[2]); - Endian_Reverse32(q[3]); - q+=4; +# pragma unroll + for (; i < 80; i++) { + tmp = w[i - 3 & 0xf] ^ w[i - 8 & 0xf] ^ w[i - 14 & 0xf] ^ w[i & 0xf]; + w[i & 0xf] = tmp << 1 | tmp >> 32 - 1; + + f = b ^ c ^ d; + t = (a << 5 | a >> 32 - 5) + f + e + w[i & 0xf] + K3; + e = d; + d = c; + c = b << 30 | b >> 32 - 30; + b = a; + a = t; } -#endif -#else - q=p; - for (i=(SHA_LBLOCK/4); i; i--) - { - u_int32_t l; - c2nl(b,l); *(q++)=l; - c2nl(b,l); *(q++)=l; - c2nl(b,l); *(q++)=l; - c2nl(b,l); *(q++)=l; - } -#endif - sha1_block(c,p,64); - } -#ifndef SHA1_ASM + h0 += a; + h1 += b; + h2 += c; + h3 += d; + h4 += e; -void -sha1_block(SHA_CTX *c, const u_int32_t *W, int num) -{ - u_int32_t A,B,C,D,E,T; - u_int32_t X[16]; - - A=c->h0; - B=c->h1; - C=c->h2; - D=c->h3; - E=c->h4; - - for (;;) - { - BODY_00_15( 0,A,B,C,D,E,T,W); - BODY_00_15( 1,T,A,B,C,D,E,W); - BODY_00_15( 2,E,T,A,B,C,D,W); - BODY_00_15( 3,D,E,T,A,B,C,W); - BODY_00_15( 4,C,D,E,T,A,B,W); - BODY_00_15( 5,B,C,D,E,T,A,W); - BODY_00_15( 6,A,B,C,D,E,T,W); - BODY_00_15( 7,T,A,B,C,D,E,W); - BODY_00_15( 8,E,T,A,B,C,D,W); - BODY_00_15( 9,D,E,T,A,B,C,W); - BODY_00_15(10,C,D,E,T,A,B,W); - BODY_00_15(11,B,C,D,E,T,A,W); - BODY_00_15(12,A,B,C,D,E,T,W); - BODY_00_15(13,T,A,B,C,D,E,W); - BODY_00_15(14,E,T,A,B,C,D,W); - BODY_00_15(15,D,E,T,A,B,C,W); - BODY_16_19(16,C,D,E,T,A,B,W,W,W,W); - BODY_16_19(17,B,C,D,E,T,A,W,W,W,W); - BODY_16_19(18,A,B,C,D,E,T,W,W,W,W); - BODY_16_19(19,T,A,B,C,D,E,W,W,W,X); - - BODY_20_31(20,E,T,A,B,C,D,W,W,W,X); - BODY_20_31(21,D,E,T,A,B,C,W,W,W,X); - BODY_20_31(22,C,D,E,T,A,B,W,W,W,X); - BODY_20_31(23,B,C,D,E,T,A,W,W,W,X); - BODY_20_31(24,A,B,C,D,E,T,W,W,X,X); - BODY_20_31(25,T,A,B,C,D,E,W,W,X,X); - BODY_20_31(26,E,T,A,B,C,D,W,W,X,X); - BODY_20_31(27,D,E,T,A,B,C,W,W,X,X); - BODY_20_31(28,C,D,E,T,A,B,W,W,X,X); - BODY_20_31(29,B,C,D,E,T,A,W,W,X,X); - BODY_20_31(30,A,B,C,D,E,T,W,X,X,X); - BODY_20_31(31,T,A,B,C,D,E,W,X,X,X); - BODY_32_39(32,E,T,A,B,C,D,X); - BODY_32_39(33,D,E,T,A,B,C,X); - BODY_32_39(34,C,D,E,T,A,B,X); - BODY_32_39(35,B,C,D,E,T,A,X); - BODY_32_39(36,A,B,C,D,E,T,X); - BODY_32_39(37,T,A,B,C,D,E,X); - BODY_32_39(38,E,T,A,B,C,D,X); - BODY_32_39(39,D,E,T,A,B,C,X); - - BODY_40_59(40,C,D,E,T,A,B,X); - BODY_40_59(41,B,C,D,E,T,A,X); - BODY_40_59(42,A,B,C,D,E,T,X); - BODY_40_59(43,T,A,B,C,D,E,X); - BODY_40_59(44,E,T,A,B,C,D,X); - BODY_40_59(45,D,E,T,A,B,C,X); - BODY_40_59(46,C,D,E,T,A,B,X); - BODY_40_59(47,B,C,D,E,T,A,X); - BODY_40_59(48,A,B,C,D,E,T,X); - BODY_40_59(49,T,A,B,C,D,E,X); - BODY_40_59(50,E,T,A,B,C,D,X); - BODY_40_59(51,D,E,T,A,B,C,X); - BODY_40_59(52,C,D,E,T,A,B,X); - BODY_40_59(53,B,C,D,E,T,A,X); - BODY_40_59(54,A,B,C,D,E,T,X); - BODY_40_59(55,T,A,B,C,D,E,X); - BODY_40_59(56,E,T,A,B,C,D,X); - BODY_40_59(57,D,E,T,A,B,C,X); - BODY_40_59(58,C,D,E,T,A,B,X); - BODY_40_59(59,B,C,D,E,T,A,X); - - BODY_60_79(60,A,B,C,D,E,T,X); - BODY_60_79(61,T,A,B,C,D,E,X); - BODY_60_79(62,E,T,A,B,C,D,X); - BODY_60_79(63,D,E,T,A,B,C,X); - BODY_60_79(64,C,D,E,T,A,B,X); - BODY_60_79(65,B,C,D,E,T,A,X); - BODY_60_79(66,A,B,C,D,E,T,X); - BODY_60_79(67,T,A,B,C,D,E,X); - BODY_60_79(68,E,T,A,B,C,D,X); - BODY_60_79(69,D,E,T,A,B,C,X); - BODY_60_79(70,C,D,E,T,A,B,X); - BODY_60_79(71,B,C,D,E,T,A,X); - BODY_60_79(72,A,B,C,D,E,T,X); - BODY_60_79(73,T,A,B,C,D,E,X); - BODY_60_79(74,E,T,A,B,C,D,X); - BODY_60_79(75,D,E,T,A,B,C,X); - BODY_60_79(76,C,D,E,T,A,B,X); - BODY_60_79(77,B,C,D,E,T,A,X); - BODY_60_79(78,A,B,C,D,E,T,X); - BODY_60_79(79,T,A,B,C,D,E,X); - - c->h0=(c->h0+E)&0xffffffffL; - c->h1=(c->h1+T)&0xffffffffL; - c->h2=(c->h2+A)&0xffffffffL; - c->h3=(c->h3+B)&0xffffffffL; - c->h4=(c->h4+C)&0xffffffffL; - - num-=64; - if (num <= 0) break; - - A=c->h0; - B=c->h1; - C=c->h2; - D=c->h3; - E=c->h4; - - W+=16; - } + p += SHA_CBLOCK; + len -= SHA_CBLOCK; } -#endif -void SHA1_Final(unsigned char *md, SHA_CTX *c) - { - int i,j; - u_int32_t l; - u_int32_t *p; - static unsigned char end[4]={0x80,0x00,0x00,0x00}; - unsigned char *cp=end; - - /* c->num should definitly have room for at least one more byte. */ - p=c->data; - j=c->num; - i=j>>2; -#ifdef PURIFY - if ((j&0x03) == 0) p[i]=0; + c->h0 = h0; + c->h1 = h1; + c->h2 = h2; + c->h3 = h3; + c->h4 = h4; +} #endif - l=p[i]; - M_p_c2nl(cp,l,j&0x03); - p[i]=l; - i++; - /* i is the next 'undefined word' */ - if (c->num >= SHA_LAST_BLOCK) - { - for (; i<SHA_LBLOCK; i++) - p[i]=0; - sha1_block(c,p,64); - i=0; - } - for (; i<(SHA_LBLOCK-2); i++) - p[i]=0; - p[SHA_LBLOCK-2]=c->Nh; - p[SHA_LBLOCK-1]=c->Nl; -#if BYTE_ORDER == LITTLE_ENDIAN && defined(SHA1_ASM) - Endian_Reverse32(p[SHA_LBLOCK-2]); - Endian_Reverse32(p[SHA_LBLOCK-1]); -#endif - sha1_block(c,p,64); - cp=md; - l=c->h0; nl2c(l,cp); - l=c->h1; nl2c(l,cp); - l=c->h2; nl2c(l,cp); - l=c->h3; nl2c(l,cp); - l=c->h4; nl2c(l,cp); - - /* Clear the context state */ - explicit_bzero(&c, sizeof(c)); - } #ifdef WEAK_REFS /* When building libmd, provide weak references. Note: this is not diff --git a/lib/libnvmf/libnvmf.h b/lib/libnvmf/libnvmf.h index 9840e190a24f..7cdd7e433455 100644 --- a/lib/libnvmf/libnvmf.h +++ b/lib/libnvmf/libnvmf.h @@ -342,7 +342,8 @@ int nvmf_host_request_queues(struct nvmf_qpair *qp, u_int requested, */ int nvmf_handoff_host(const struct nvme_discovery_log_entry *dle, const char *hostnqn, struct nvmf_qpair *admin_qp, u_int num_queues, - struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata); + struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata, + uint32_t reconnect_delay, uint32_t controller_loss_timeout); /* * Disconnect an active host association previously handed off to the @@ -370,7 +371,8 @@ int nvmf_reconnect_params(int fd, nvlist_t **nvlp); */ int nvmf_reconnect_host(int fd, const struct nvme_discovery_log_entry *dle, const char *hostnqn, struct nvmf_qpair *admin_qp, u_int num_queues, - struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata); + struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata, + uint32_t reconnect_delay, uint32_t controller_loss_timeout); /* * Fetch connection status from an existing kernel host. diff --git a/lib/libnvmf/nvmf_host.c b/lib/libnvmf/nvmf_host.c index 89cdd5c6bb70..3266f8898296 100644 --- a/lib/libnvmf/nvmf_host.c +++ b/lib/libnvmf/nvmf_host.c @@ -792,7 +792,8 @@ static int prepare_queues_for_handoff(struct nvmf_ioc_nv *nv, const struct nvme_discovery_log_entry *dle, const char *hostnqn, struct nvmf_qpair *admin_qp, u_int num_queues, - struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata) + struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata, + uint32_t reconnect_delay, uint32_t controller_loss_timeout) { const struct nvmf_association *na = admin_qp->nq_association; nvlist_t *nvl, *nvl_qp, *nvl_rparams; @@ -820,6 +821,9 @@ prepare_queues_for_handoff(struct nvmf_ioc_nv *nv, nvlist_add_string(nvl_rparams, "hostnqn", hostnqn); nvlist_add_number(nvl_rparams, "num_io_queues", num_queues); nvlist_add_number(nvl_rparams, "kato", admin_qp->nq_kato); + nvlist_add_number(nvl_rparams, "reconnect_delay", reconnect_delay); + nvlist_add_number(nvl_rparams, "controller_loss_timeout", + controller_loss_timeout); nvlist_add_number(nvl_rparams, "io_qsize", io_queues[0]->nq_qsize); nvlist_add_bool(nvl_rparams, "sq_flow_control", na->na_params.sq_flow_control); @@ -842,6 +846,9 @@ prepare_queues_for_handoff(struct nvmf_ioc_nv *nv, nvl = nvlist_create(0); nvlist_add_number(nvl, "trtype", na->na_trtype); nvlist_add_number(nvl, "kato", admin_qp->nq_kato); + nvlist_add_number(nvl, "reconnect_delay", reconnect_delay); + nvlist_add_number(nvl, "controller_loss_timeout", + controller_loss_timeout); nvlist_move_nvlist(nvl, "rparams", nvl_rparams); /* First, the admin queue. */ @@ -872,7 +879,8 @@ prepare_queues_for_handoff(struct nvmf_ioc_nv *nv, int nvmf_handoff_host(const struct nvme_discovery_log_entry *dle, const char *hostnqn, struct nvmf_qpair *admin_qp, u_int num_queues, - struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata) + struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata, + uint32_t reconnect_delay, uint32_t controller_loss_timeout) { struct nvmf_ioc_nv nv; u_int i; @@ -885,7 +893,8 @@ nvmf_handoff_host(const struct nvme_discovery_log_entry *dle, } error = prepare_queues_for_handoff(&nv, dle, hostnqn, admin_qp, - num_queues, io_queues, cdata); + num_queues, io_queues, cdata, reconnect_delay, + controller_loss_timeout); if (error != 0) goto out; @@ -981,14 +990,16 @@ nvmf_reconnect_params(int fd, nvlist_t **nvlp) int nvmf_reconnect_host(int fd, const struct nvme_discovery_log_entry *dle, const char *hostnqn, struct nvmf_qpair *admin_qp, u_int num_queues, - struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata) + struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata, + uint32_t reconnect_delay, uint32_t controller_loss_timeout) { struct nvmf_ioc_nv nv; u_int i; int error; error = prepare_queues_for_handoff(&nv, dle, hostnqn, admin_qp, - num_queues, io_queues, cdata); + num_queues, io_queues, cdata, reconnect_delay, + controller_loss_timeout); if (error != 0) goto out; diff --git a/lib/libopenbsd/Makefile b/lib/libopenbsd/Makefile index 675ed476c51d..dca1c08b0aed 100644 --- a/lib/libopenbsd/Makefile +++ b/lib/libopenbsd/Makefile @@ -2,7 +2,8 @@ PACKAGE=lib${LIB} LIB= openbsd SRCS= imsg-buffer.c \ imsg.c \ - ohash.c + ohash.c \ + recallocarray.c .if !defined(BOOTSTRAPPING) # Skip getdtablecount.c when bootstrapping since it doesn't compile for Linux # and is not used by any of the bootstrap tools diff --git a/lib/libopenbsd/recallocarray.c b/lib/libopenbsd/recallocarray.c new file mode 100644 index 000000000000..11e1fda744c7 --- /dev/null +++ b/lib/libopenbsd/recallocarray.c @@ -0,0 +1,82 @@ +/* $OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $ */ +/* + * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <errno.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) + +void *recallocarray(void *, size_t, size_t, size_t); + +void * +recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size) +{ + size_t oldsize, newsize; + void *newptr; + + if (ptr == NULL) + return calloc(newnmemb, size); + + if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + newnmemb > 0 && SIZE_MAX / newnmemb < size) { + errno = ENOMEM; + return NULL; + } + newsize = newnmemb * size; + + if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + oldnmemb > 0 && SIZE_MAX / oldnmemb < size) { + errno = EINVAL; + return NULL; + } + oldsize = oldnmemb * size; + + /* + * Don't bother too much if we're shrinking just a bit, + * we do not shrink for series of small steps, oh well. + */ + if (newsize <= oldsize) { + size_t d = oldsize - newsize; + + if (d < oldsize / 2 && d < (size_t)getpagesize()) { + memset((char *)ptr + newsize, 0, d); + return ptr; + } + } + + newptr = malloc(newsize); + if (newptr == NULL) + return NULL; + + if (newsize > oldsize) { + memcpy(newptr, ptr, oldsize); + memset((char *)newptr + oldsize, 0, newsize - oldsize); + } else + memcpy(newptr, ptr, newsize); + + explicit_bzero(ptr, oldsize); + free(ptr); + + return newptr; +} diff --git a/lib/libpam/libpam/Makefile b/lib/libpam/libpam/Makefile index 9bd855f60ed8..dd19eba5c1ec 100644 --- a/lib/libpam/libpam/Makefile +++ b/lib/libpam/libpam/Makefile @@ -153,6 +153,7 @@ MAN?= openpam.3 \ MLINKS?= pam.conf.5 pam.d.5 +CFLAGS+= -DLOCALBASE=\"${LOCALBASE:U/usr/local}\" CFLAGS+= -I${OPENPAM}/include CFLAGS+= -DLIB_MAJ=${SHLIB_MAJOR} CFLAGS+= -DHAVE_DLFUNC=1 diff --git a/lib/libpam/modules/pam_krb5/Makefile b/lib/libpam/modules/pam_krb5/Makefile index 1c2831facd50..b537bf37b7f3 100644 --- a/lib/libpam/modules/pam_krb5/Makefile +++ b/lib/libpam/modules/pam_krb5/Makefile @@ -23,6 +23,59 @@ # SUCH DAMAGE. # +.include <src.opts.mk> + +.if ${MK_MITKRB5} != "no" +SRCDIR= ${SRCTOP}/contrib/pam-krb5 +.PATH: ${SRCDIR}/module \ + ${SRCDIR}/portable \ + ${SRCDIR}/pam-util \ + ${SRCDIR} + +PACKAGE= krb5 +LIB= pam_krb5 +LIBADD= com_err krb5 + +SRCS= account.c \ + alt-auth.c \ + args.c \ + auth.c \ + cache.c \ + context.c \ + dummy.c \ + fast.c \ + krb5-extra.c \ + logging.c \ + pam-util_options.c \ + module_options.c \ + pam_syslog.c \ + pam_vsyslog.c \ + password.c \ + prompting.c \ + public.c \ + setcred.c \ + support.c \ + vector.c + +MAN= pam-krb5.8 +MLINKS= pam-krb5.8 pam_krb5.8 + +CFLAGS= -I${SRCDIR} \ + -I${.CURDIR} \ + -fno-strict-aliasing \ + -Wno-error=incompatible-pointer-types-discards-qualifiers \ + -DHAVE_CONFIG_H + +WARNS?= 3 + +CLEANFILES= pam-util_options.c module_options.c + +pam-util_options.c: .PHONY + cp ${SRCDIR}/pam-util/options.c pam-util_options.c + +module_options.c: .PHONY + cp ${SRCDIR}/module/options.c module_options.c +.else PACKAGE= kerberos LIB= pam_krb5 @@ -35,4 +88,6 @@ WARNS?= 3 LIBADD+= krb5 +.endif + .include <bsd.lib.mk> diff --git a/lib/libpam/modules/pam_krb5/config.h b/lib/libpam/modules/pam_krb5/config.h new file mode 100644 index 000000000000..75695eef66a1 --- /dev/null +++ b/lib/libpam/modules/pam_krb5/config.h @@ -0,0 +1,412 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the `asprintf' function. */ +#define HAVE_ASPRINTF 1 + +/* Define to 1 if you have the declaration of `krb5_kt_free_entry', and to 0 + if you don't. */ +#define HAVE_DECL_KRB5_KT_FREE_ENTRY 1 + +/* Define to 1 if you have the declaration of `reallocarray', and to 0 if you + don't. */ +#define HAVE_DECL_REALLOCARRAY 1 + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the <et/com_err.h> header file. */ +/* #undef HAVE_ET_COM_ERR_H */ + +/* Define to 1 if you have the `explicit_bzero' function. */ +#define HAVE_EXPLICIT_BZERO 1 + +/* Define to 1 if you have the <hx509_err.h> header file. */ +/* #undef HAVE_HX509_ERR_H */ + +/* Define to 1 if you have the <ibm_svc/krb5_svc.h> header file. */ +/* #undef HAVE_IBM_SVC_KRB5_SVC_H */ + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `issetugid' function. */ +#define HAVE_ISSETUGID 1 + +/* Define to 1 if you have the <k5profile.h> header file. */ +/* #undef HAVE_K5PROFILE_H */ + +/* Define to enable kadmin client features. */ +#define HAVE_KADM5CLNT 1 + +/* Define to 1 if you have the `kadm5_init_krb5_context' function. */ +#define HAVE_KADM5_INIT_KRB5_CONTEXT 1 + +/* Define to 1 if you have the `kadm5_init_with_skey_ctx' function. */ +/* #undef HAVE_KADM5_INIT_WITH_SKEY_CTX */ + +/* Define to 1 if you have the <kadm5/kadm5_err.h> header file. */ +#define HAVE_KADM5_KADM5_ERR_H 1 + +/* Define to 1 if you have the <kerberosv5/com_err.h> header file. */ +/* #undef HAVE_KERBEROSV5_COM_ERR_H */ + +/* Define to 1 if you have the <kerberosv5/krb5.h> header file. */ +/* #undef HAVE_KERBEROSV5_KRB5_H */ + +/* Define to enable Kerberos features. */ +#define HAVE_KRB5 1 + +/* Define to 1 if you have the `krb5_appdefault_string' function. */ +#define HAVE_KRB5_APPDEFAULT_STRING 1 + +/* Define to 1 if you have the `krb5_cc_get_full_name' function. */ +#define HAVE_KRB5_CC_GET_FULL_NAME 1 + +/* Define to 1 if you have the `krb5_data_free' function. */ +/* #undef HAVE_KRB5_DATA_FREE */ + +/* Define to 1 if you have the `krb5_free_default_realm' function. */ +#define HAVE_KRB5_FREE_DEFAULT_REALM 1 + +/* Define to 1 if you have the `krb5_free_error_message' function. */ +#define HAVE_KRB5_FREE_ERROR_MESSAGE 1 + +/* Define to 1 if you have the `krb5_free_string' function. */ +#define HAVE_KRB5_FREE_STRING 1 + +/* Define to 1 if you have the `krb5_get_error_message' function. */ +#define HAVE_KRB5_GET_ERROR_MESSAGE 1 + +/* Define to 1 if you have the `krb5_get_error_string' function. */ +/* #undef HAVE_KRB5_GET_ERROR_STRING */ + +/* Define to 1 if you have the `krb5_get_err_txt' function. */ +/* #undef HAVE_KRB5_GET_ERR_TXT */ + +/* Define to 1 if you have the `krb5_get_init_creds_opt_alloc' function. */ +#define HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC 1 + +/* Define to 1 if you have the `krb5_get_init_creds_opt_free' function. */ +#define HAVE_KRB5_GET_INIT_CREDS_OPT_FREE 1 + +/* Define if krb5_get_init_creds_opt_free takes two arguments. */ +#define HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_2_ARGS 1 + +/* Define to 1 if you have the `krb5_get_init_creds_opt_set_anonymous' + function. */ +#define HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ANONYMOUS 1 + +/* Define to 1 if you have the + `krb5_get_init_creds_opt_set_change_password_prompt' function. */ +#define HAVE_KRB5_GET_INIT_CREDS_OPT_SET_CHANGE_PASSWORD_PROMPT 1 + +/* Define to 1 if you have the `krb5_get_init_creds_opt_set_default_flags' + function. */ +/* #undef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_DEFAULT_FLAGS */ + +/* Define to 1 if you have the `krb5_get_init_creds_opt_set_fast_ccache_name' + function. */ +#define HAVE_KRB5_GET_INIT_CREDS_OPT_SET_FAST_CCACHE_NAME 1 + +/* Define to 1 if you have the `krb5_get_init_creds_opt_set_out_ccache' + function. */ +#define HAVE_KRB5_GET_INIT_CREDS_OPT_SET_OUT_CCACHE 1 + +/* Define to 1 if you have the `krb5_get_init_creds_opt_set_pa' function. */ +#define HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PA 1 + +/* Define to 1 if you have the `krb5_get_init_creds_opt_set_pkinit' function. + */ +/* #undef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PKINIT */ + +/* Define if krb5_get_init_creds_opt_set_pkinit takes 9 arguments. */ +/* #undef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PKINIT_9_ARGS */ + +/* Define to 1 if you have the `krb5_get_profile' function. */ +/* #undef HAVE_KRB5_GET_PROFILE */ + +/* Define to 1 if you have the `krb5_get_prompt_types' function. */ +#define HAVE_KRB5_GET_PROMPT_TYPES 1 + +/* Define to 1 if you have the <krb5.h> header file. */ +#define HAVE_KRB5_H 1 + +/* Define if your Kerberos implementation is Heimdal. */ +/* #undef HAVE_KRB5_HEIMDAL */ + +/* Define to 1 if you have the `krb5_init_secure_context' function. */ +#define HAVE_KRB5_INIT_SECURE_CONTEXT 1 + +/* Define to 1 if you have the <krb5/krb5.h> header file. */ +#define HAVE_KRB5_KRB5_H 1 + +/* Define if your Kerberos implementation is MIT. */ +#define HAVE_KRB5_MIT 1 + +/* Define to 1 if you have the `krb5_principal_get_realm' function. */ +/* #undef HAVE_KRB5_PRINCIPAL_GET_REALM */ + +/* Define to 1 if you have the `krb5_principal_set_comp_string' function. */ +/* #undef HAVE_KRB5_PRINCIPAL_SET_COMP_STRING */ + +/* Define to 1 if the system has the type `krb5_realm'. */ +/* #undef HAVE_KRB5_REALM */ + +/* Define to 1 if you have the `krb5_set_password' function. */ +#define HAVE_KRB5_SET_PASSWORD 1 + +/* Define to 1 if you have the `krb5_set_trace_filename' function. */ +#define HAVE_KRB5_SET_TRACE_FILENAME 1 + +/* Define to 1 if you have the `krb5_svc_get_msg' function. */ +/* #undef HAVE_KRB5_SVC_GET_MSG */ + +/* Define to 1 if you have the `krb5_verify_init_creds_opt_init' function. */ +#define HAVE_KRB5_VERIFY_INIT_CREDS_OPT_INIT 1 + +/* Define to 1 if you have the `krb5_xfree' function. */ +/* #undef HAVE_KRB5_XFREE */ + +/* Define to 1 if the system has the type `long long int'. */ +#define HAVE_LONG_LONG_INT 1 + +/* Define to 1 if you have the <minix/config.h> header file. */ +/* #undef HAVE_MINIX_CONFIG_H */ + +/* Define to 1 if you have the `mkstemp' function. */ +#define HAVE_MKSTEMP 1 + +/* Define to 1 if you have the `pam_getenv' function. */ +#define HAVE_PAM_GETENV 1 + +/* Define to 1 if you have the `pam_getenvlist' function. */ +#define HAVE_PAM_GETENVLIST 1 + +/* Define to 1 if you have the `pam_modutil_getpwnam' function. */ +/* #undef HAVE_PAM_MODUTIL_GETPWNAM */ + +/* Define to 1 if you have the <pam/pam_appl.h> header file. */ +/* #undef HAVE_PAM_PAM_APPL_H */ + +/* Define to 1 if you have the <pam/pam_ext.h> header file. */ +/* #undef HAVE_PAM_PAM_EXT_H */ + +/* Define to 1 if you have the <pam/pam_modutil.h> header file. */ +/* #undef HAVE_PAM_PAM_MODUTIL_H */ + +/* Define to 1 if you have the `pam_syslog' function. */ +/* #undef HAVE_PAM_SYSLOG */ + +/* Define to 1 if you have the `pam_vsyslog' function. */ +/* #undef HAVE_PAM_VSYSLOG */ + +/* Define to 1 if you have the <profile.h> header file. */ +/* #undef HAVE_PROFILE_H */ + +/* Define to 1 if you have the `reallocarray' function. */ +#define HAVE_REALLOCARRAY 1 + +/* Define to 1 if you have the `regcomp' function. */ +#define HAVE_REGCOMP 1 + +/* Define to 1 if you have the <security/pam_appl.h> header file. */ +#define HAVE_SECURITY_PAM_APPL_H 1 + +/* Define to 1 if you have the <security/pam_ext.h> header file. */ +/* #undef HAVE_SECURITY_PAM_EXT_H */ + +/* Define to 1 if you have the <security/pam_modutil.h> header file. */ +/* #undef HAVE_SECURITY_PAM_MODUTIL_H */ + +/* Define to 1 if the system has the type `ssize_t'. */ +#define HAVE_SSIZE_T 1 + +/* Define to 1 if stdbool.h conforms to C99. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdio.h> header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strndup' function. */ +#define HAVE_STRNDUP 1 + +/* Define to 1 if you have the <sys/bittypes.h> header file. */ +/* #undef HAVE_SYS_BITTYPES_H */ + +/* Define to 1 if you have the <sys/select.h> header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/time.h> header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if the system has the type `unsigned long long int'. */ +#define HAVE_UNSIGNED_LONG_LONG_INT 1 + +/* Define to 1 if you have the <wchar.h> header file. */ +#define HAVE_WCHAR_H 1 + +/* Define to 1 if the system has the type `_Bool'. */ +#define HAVE__BOOL 1 + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* The name of the PAM module, used by the pam_vsyslog replacement. */ +#define MODULE_NAME "pam_krb5" + +/* Name of package */ +#define PACKAGE "pam-krb5" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "eagle@eyrie.org" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "pam-krb5" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "pam-krb5 4.11" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "pam-krb5" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "4.11" + +/* Define to const if PAM uses const in pam_get_item, empty otherwise. */ +#define PAM_CONST const + +/* Define to const if PAM uses const in pam_strerror, empty otherwise. */ +#define PAM_STRERROR_CONST const + +/* Define to the full path to openssl for some tests. */ +#define PATH_OPENSSL "/usr/bin/openssl" + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ +#define STDC_HEADERS 1 + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable general extensions on macOS. */ +#ifndef _DARWIN_C_SOURCE +# define _DARWIN_C_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable X/Open compliant socket functions that do not require linking + with -lxnet on HP-UX 11.11. */ +#ifndef _HPUX_ALT_XOPEN_SOCKET_API +# define _HPUX_ALT_XOPEN_SOCKET_API 1 +#endif +/* Identify the host operating system as Minix. + This macro does not affect the system headers' behavior. + A future release of Autoconf may stop defining this macro. */ +#ifndef _MINIX +/* # undef _MINIX */ +#endif +/* Enable general extensions on NetBSD. + Enable NetBSD compatibility extensions on Minix. */ +#ifndef _NETBSD_SOURCE +# define _NETBSD_SOURCE 1 +#endif +/* Enable OpenBSD compatibility extensions on NetBSD. + Oddly enough, this does nothing on OpenBSD. */ +#ifndef _OPENBSD_SOURCE +# define _OPENBSD_SOURCE 1 +#endif +/* Define to 1 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_SOURCE +/* # undef _POSIX_SOURCE */ +#endif +/* Define to 2 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_1_SOURCE +/* # undef _POSIX_1_SOURCE */ +#endif +/* Enable POSIX-compatible threading on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */ +#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ +# define __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */ +#ifndef __STDC_WANT_IEC_60559_BFP_EXT__ +# define __STDC_WANT_IEC_60559_BFP_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */ +#ifndef __STDC_WANT_IEC_60559_DFP_EXT__ +# define __STDC_WANT_IEC_60559_DFP_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */ +#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__ +# define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */ +#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ +# define __STDC_WANT_IEC_60559_TYPES_EXT__ 1 +#endif +/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */ +#ifndef __STDC_WANT_LIB_EXT2__ +# define __STDC_WANT_LIB_EXT2__ 1 +#endif +/* Enable extensions specified by ISO/IEC 24747:2009. */ +#ifndef __STDC_WANT_MATH_SPEC_FUNCS__ +# define __STDC_WANT_MATH_SPEC_FUNCS__ 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable X/Open extensions. Define to 500 only if necessary + to make mbstate_t available. */ +#ifndef _XOPEN_SOURCE +/* # undef _XOPEN_SOURCE */ +#endif + + +/* Version number of package */ +#define VERSION "4.11" + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ diff --git a/lib/libpam/modules/pam_krb5/pam-krb5.8 b/lib/libpam/modules/pam_krb5/pam-krb5.8 new file mode 100644 index 000000000000..3413748c7850 --- /dev/null +++ b/lib/libpam/modules/pam_krb5/pam-krb5.8 @@ -0,0 +1,1025 @@ +.\" -*- mode: troff; coding: utf-8 -*- +.\" Automatically generated by Pod::Man 5.0102 (Pod::Simple 3.45) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. +.ie n \{\ +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "PAM_KRB5 1" +.TH PAM_KRB5 1 2025-06-05 "perl v5.40.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH NAME +pam_krb5 \- Kerberos PAM module +.SH SYNOPSIS +.IX Header "SYNOPSIS" +.Vb 4 +\& auth sufficient pam_krb5.so minimum_uid=1000 +\& session required pam_krb5.so minimum_uid=1000 +\& account required pam_krb5.so minimum_uid=1000 +\& password sufficient pam_krb5.so minimum_uid=1000 +.Ve +.SH DESCRIPTION +.IX Header "DESCRIPTION" +The Kerberos service module for PAM, typically installed at +\&\fI/lib/security/pam_krb5.so\fR, provides functionality for the four PAM +operations: authentication, account management, session management, and +password management. \fIpam_krb5.so\fR is a shared object that is +dynamically loaded by the PAM subsystem as necessary, based on the system +PAM configuration. PAM is a system for plugging in external +authentication and session management modules so that each application +doesn't have to know the best way to check user authentication or create a +user session on that system. For details on how to configure PAM on your +system, see the PAM man page, often \fBpam\fR\|(7). +.PP +Here are the actions of this module when called from each group: +.IP auth 4 +.IX Item "auth" +Provides implementations of \fBpam_authenticate()\fR and \fBpam_setcred()\fR. The +former takes the username from the PAM session, prompts for the user's +password (unless configured to use an already-entered password), and then +performs a Kerberos initial authentication, storing the obtained +credentials (if successful) in a temporary ticket cache. The latter, +depending on the flags it is called with, either takes the contents of the +temporary ticket cache and writes it out to a persistent ticket cache +owned by the user or uses the temporary ticket cache to refresh an +existing user ticket cache. +.Sp +Passwords as long or longer than PAM_MAX_RESP_SIZE octets (normally 512 +octets) will be rejected, since excessively long passwords can be used as +a denial of service attack. +.Sp +After doing the initial authentication, the Kerberos PAM module will +attempt to obtain tickets for a key in the local system keytab and then +verify those tickets. Unless this step is performed, the authentication +is vulnerable to KDC spoofing, but it requires that the system have a +local key and that the PAM module be running as a user that can read the +keytab file (normally \fI/etc/krb5.keytab\fR. You can point the Kerberos PAM +module at a different keytab with the \fIkeytab\fR option. If that keytab +cannot be read or if no keys are found in it, the default (potentially +insecure) behavior is to skip this check. If you want to instead fail +authentication if the obtained tickets cannot be checked, set +\&\f(CW\*(C`verify_ap_req_nofail\*(C'\fR to true in the [libdefaults] section of +\&\fI/etc/krb5.conf\fR. Note that this will affect applications other than +this PAM module. +.Sp +By default, whenever the user is authenticated, a basic authorization +check will also be done using \fBkrb5_kuserok()\fR. The default behavior of +this function is to check the user's account for a \fI.k5login\fR file and, +if one is present, ensure that the user's principal is listed in that +file. If \fI.k5login\fR is not present, the default check is to ensure that +the user's principal is in the default local realm and the user portion of +the principal matches the account name (this can be changed by configuring +a custom aname to localname mapping in \fIkrb5.conf\fR; see the Kerberos +documentation for details). This can be customized with several +configuration options; see below. +.Sp +If the username provided to PAM contains an \f(CW\*(C`@\*(C'\fR and Kerberos can, +treating the username as a principal, map it to a local account name, +\&\fBpam_authenticate()\fR will change the PAM user to that local account name. +This allows users to log in with their Kerberos principal and let Kerberos +do the mapping to an account. This can be disabled with the +\&\fIno_update_user\fR option. Be aware, however, that this facility cannot be +used with OpenSSH. OpenSSH will reject usernames that don't match local +accounts before this remapping can be done and will pass an invalid +password to the PAM module. Also be aware that several other common PAM +modules, such as pam_securetty, expect to be able to look up the user with +\&\fBgetpwnam()\fR and cannot be called before pam_krb5 when using this feature. +.Sp +When \fBpam_setcred()\fR is called to initialize a new ticket cache, the +environment variable KRB5CCNAME is set to the path to that ticket cache. +By default, the cache will be named \fI/tmp/krb5cc_UID_RANDOM\fR where UID is +the user's UID and RANDOM is six randomly-chosen letters. This can be +configured with the \fIccache\fR and \fIccache_dir\fR options. +.Sp +pam\-krb5 does not use the default ticket cache location or +\&\fIdefault_cc_name\fR in the \f(CW\*(C`[libdefaults]\*(C'\fR section of \fIkrb5.conf\fR. The +default cache location would share a cache for all sessions of the same +user, which causes confusing behavior when the user logs out of one of +multiple sessions. +.Sp +If \fBpam_setcred()\fR initializes a new ticket cache, it will also set up that +ticket cache so that it will be deleted when the PAM session is closed. +Normally, the calling program (\fBlogin\fR, \fBsshd\fR, etc.) will run the +user's shell as a sub-process, wait for it to exit, and then close the PAM +session, thereby cleaning up the user's session. +.IP session 4 +.IX Item "session" +Provides implementations of \fBpam_open_session()\fR, which is equivalent to +calling \fBpam_setcred()\fR with the PAM_ESTABLISH_CRED flag, and +\&\fBpam_close_session()\fR, which destroys the ticket cache created by +\&\fBpam_setcred()\fR. +.IP account 4 +.IX Item "account" +Provides an implementation of \fBpam_acct_mgmt()\fR. All it does is do the same +authorization check as performed by the \fBpam_authenticate()\fR implementation +described above. +.IP password 4 +.IX Item "password" +Provides an implementation of \fBpam_chauthtok()\fR, which implements password +changes. The user is prompted for their existing password (unless +configured to use an already entered one) and the PAM module then obtains +credentials for the special Kerberos principal \f(CW\*(C`kadmin/changepw\*(C'\fR. It +then prompts the user for a new password, twice to ensure that the user +entered it properly (again, unless configured to use an already entered +password), and then does a Kerberos password change. +.Sp +Passwords as long or longer than PAM_MAX_RESP_SIZE octets (normally 512 +octets) will be rejected, since excessively long passwords can be used as +a denial of service attack. +.Sp +Unlike the normal Unix password module, this module will allow any user to +change any other user's password if they know the old password. Also, +unlike the normal Unix password module, root will always be prompted for +the old password, since root has no special status in Kerberos. (To +change passwords in Kerberos without knowing the old password, use +\&\fBkadmin\fR\|(8) instead.) +.PP +Both the account and session management calls of the Kerberos PAM module +will return PAM_IGNORE if called in the context of a PAM session for a +user who did not authenticate with Kerberos (a return code of \f(CW\*(C`ignore\*(C'\fR in +the Linux PAM configuration language). +.PP +Note that this module assumes the network is available in order to do a +Kerberos authentication. If the network is not available, some Kerberos +libraries have timeouts longer than the timeout imposed by the login +process. This means that using this module incautiously can make it +impossible to log on to console as root. For this reason, you should +always use the \fIignore_root\fR or \fIminimum_uid\fR options, list a local +authentication module such as \fBpam_unix\fR first with a control field of +\&\f(CW\*(C`sufficient\*(C'\fR so that the Kerberos PAM module will be skipped if local +password authentication was successful. +.PP +This is not the same PAM module as the Kerberos PAM module available from +Sourceforge, or the one included on Red Hat systems. It supports many of +the same options, has some additional options, and doesn't support some of +the options those modules do. +.SH CONFIGURATION +.IX Header "CONFIGURATION" +The Kerberos PAM module takes many options, not all of which are relevant +to every PAM group; options that are not relevant will be silently +ignored. Any of these options can be set in the PAM configuration as +arguments listed after \f(CW\*(C`pam_krb5.so\*(C'\fR. Some of the options can also be +set in the system \fIkrb5.conf\fR file; if this is possible, it will be noted +below in the option description. +.PP +To set a boolean option in the PAM configuration file, just give the name +of the option in the arguments. To set an option that takes an argument, +follow the option name with an equal sign (=) and the value, with no +separating whitespace. Whitespace in option arguments is not supported in +the PAM configuration. +.PP +To set an option for the PAM module in the system \fIkrb5.conf\fR file, put +that option in the \f(CW\*(C`[appdefaults]\*(C'\fR section. All options must be followed +by an equal sign (=) and a value, so for boolean options add \f(CW\*(C`= true\*(C'\fR. +The Kerberos PAM module will look for options either at the top level of +the \f(CW\*(C`[appdefaults]\*(C'\fR section or in a subsection named \f(CW\*(C`pam\*(C'\fR, inside or +outside a section for the realm. For example, the following fragment of a +\&\fIkrb5.conf\fR file would set \fIforwardable\fR to true, \fIminimum_uid\fR to +1000, and set \fIignore_k5login\fR only if the realm is EXAMPLE.COM. +.PP +.Vb 8 +\& [appdefaults] +\& forwardable = true +\& pam = { +\& minimum_uid = 1000 +\& EXAMPLE.COM = { +\& ignore_k5login = true +\& } +\& } +.Ve +.PP +For more information on the syntax of \fIkrb5.conf\fR, see \fBkrb5.conf\fR\|(5). +Note that options that depend on the realm will be set only on the basis +of the default realm, either as configured in \fBkrb5.conf\fR\|(5) or as set by +the \fIrealm\fR option described below. If the user authenticates to an +account qualified with a realm, that realm will not be used when +determining which options will apply. +.PP +There is no difference to the PAM module whether options are specified at +the top level or in a \f(CW\*(C`pam\*(C'\fR section; the \f(CW\*(C`pam\*(C'\fR section is supported in +case there are options that should be set for the PAM module but not for +other applications. +.PP +If the same option is set in \fIkrb5.conf\fR and in the PAM configuration, +the latter takes precedent. Note, however, that due to the configuration +syntax, there's no way to turn off a boolean option in the PAM +configuration that was turned on in \fIkrb5.conf\fR. +.PP +The start of each option description is annotated with the version of +pam\-krb5 in which that option was added with the current meaning. +.SS Authorization +.IX Subsection "Authorization" +.IP alt_auth_map=<format> 4 +.IX Item "alt_auth_map=<format>" +[3.12] This functions similarly to the \fIsearch_k5login\fR option. The +<format> argument is used as the authentication Kerberos principal, with +any \f(CW%s\fR in <format> replaced with the username. If the username +contains an \f(CW\*(C`@\*(C'\fR, only the part of the username before the realm is used +to replace \f(CW%s\fR. If <format> contains a realm, it will be used; +otherwise, the realm of the username (if any) will be appended to the +result. There is no quote removal. +.Sp +If this option is present, the default behavior is to try this alternate +principal first and then fall back to the standard behavior if it fails. +The primary usage is to allow alternative principals to be used for +authentication in programs like \fBsudo\fR. Most examples will look like: +.Sp +.Vb 1 +\& alt_auth_map=%s/root +.Ve +.Sp +which attempts authentication as the root instance of the username first +and then falls back to the regular username (but see \fIforce_alt_auth\fR and +\&\fIonly_alt_auth\fR). +.Sp +This option also allows a cheap way to attempt authentication in an +alternative realm first and then fall back to the primary realm. A +setting like: +.Sp +.Vb 1 +\& alt_auth_map=%s@EXAMPLE.COM +.Ve +.Sp +will attempt authentication in the EXAMPLE.COM realm first and then fall +back on the local default realm. This is more convenient than running the +module multiple times with multiple default realms set with \fIrealm\fR, but +it is very limited: only two realms can be tried, and the alternate realm +is always tried first. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR, although +normally it doesn't make sense to do that; normally it is used in the PAM +options of configuration for specific programs. It is only applicable to +the auth and account groups. If this option is set for the auth group, be +sure to set it for the account group as well or account authorization may +fail. +.IP force_alt_auth 4 +.IX Item "force_alt_auth" +[3.12] This option is used with \fIalt_auth_map\fR and forces authentication +as the mapped principal if that principal exists in the KDC. Only if the +KDC returns principal unknown does the Kerberos PAM module fall back to +normal authentication. This can be used to force authentication with an +alternate instance. If \fIalt_auth_map\fR is not set, it has no effect. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth group. +.IP ignore_k5login 4 +.IX Item "ignore_k5login" +[2.0] Never look for a \fI.k5login\fR file in the user's home directory. +Instead, only check that the Kerberos principal maps to the local account +name. The default check is to ensure the realm matches the local realm +and the user portion of the principal matches the local account name, but +this can be customized by setting up an aname to localname mapping in +\&\fIkrb5.conf\fR. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth and account groups. +.IP ignore_root 4 +.IX Item "ignore_root" +[1.1] Do not do anything if the username is \f(CW\*(C`root\*(C'\fR. The authentication +and password calls will silently fail (allowing that status to be ignored +via a control of \f(CW\*(C`optional\*(C'\fR or \f(CW\*(C`sufficient\*(C'\fR), and the account and +session calls (including pam_setcred) will return PAM_IGNORE, telling the +PAM library to proceed as if they weren't mentioned in the PAM +configuration. This option is supported and will remain, but normally you +want to use \fIminimum_uid\fR instead. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR. +.IP minimum_uid=<uid> 4 +.IX Item "minimum_uid=<uid>" +[2.0] Do not do anything if the authenticated account name corresponds to +a local account and that local account has a UID lower than <uid>. If +both of those conditions are true, the authentication and password calls +will silently fail (allowing that status to be ignored via a control of +\&\f(CW\*(C`optional\*(C'\fR or \f(CW\*(C`sufficient\*(C'\fR), and the account and session calls +(including pam_setcred) will return PAM_IGNORE, telling the PAM library to +proceed as if they weren't mentioned in the PAM configuration. +.Sp +Using this option is highly recommended if you don't need to use Kerberos +to authenticate password logins to the root account (which isn't +recommended since Kerberos requires a network connection). It provides +some defense in depth against user principals that happen to match a +system account incorrectly authenticating as that system account. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR. +.IP only_alt_auth 4 +.IX Item "only_alt_auth" +[3.12] This option is used with \fIalt_auth_map\fR and forces the use of the +mapped principal for authentication. It disables fallback to normal +authentication in all cases and overrides \fIsearch_k5login\fR and +\&\fIforce_alt_auth\fR. If \fIalt_auth_map\fR is not set, it has no effect and +the standard authentication behavior is used. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth group. +.IP search_k5login 4 +.IX Item "search_k5login" +[2.0] Normally, the Kerberos implementation of pam_authenticate attempts +to obtain tickets for the authenticating username in the local realm. If +this option is set and the local user has a \fI.k5login\fR file in their home +directory, the module will instead open and read that \fI.k5login\fR file, +attempting to use the supplied password to authenticate as each principal +listed there in turn. If any of those authentications succeed, the user +will be successfully authenticated; otherwise, authentication will fail. +This option is useful for allowing password authentication (via console or +\&\fBsshd\fR without GSS-API support) to shared accounts. If there is no +\&\fI.k5login\fR file, the behavior is the same as normal. Using this option +requires that the user's \fI.k5login\fR file be readable at the time of +authentication. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth group. +.SS "Kerberos Behavior" +.IX Subsection "Kerberos Behavior" +.IP anon_fast 4 +.IX Item "anon_fast" +[4.6] Attempt to use Flexible Authentication Secure Tunneling (FAST) by +first authenticating as the anonymous user (WELLKNOWN/ANONYMOUS) and using +its credentials as the FAST armor. This requires anonymous PKINIT be +enabled for the local realm, that PKINIT be configured on the local +system, and that the Kerberos library support FAST and anonymous PKINIT. +.Sp +FAST is a mechanism to protect Kerberos against password guessing attacks +and provide other security improvements. To work, FAST requires that a +ticket be obtained with a strong key to protect exchanges with potentially +weaker user passwords. This option uses anonymous authentication to +obtain that key and then uses it to protect the subsequent authentication. +.Sp +If anonymous PKINIT is not available or fails, FAST will not be used and +the authentication will proceed as normal. +.Sp +To instead use an existing ticket cache for the FAST credentials, use +\&\fIfast_ccache\fR instead of this option. If both \fIfast_ccache\fR and +\&\fIanon_fast\fR are set, the ticket cache named by \fIfast_ccache\fR will be +tried first, and the Kerberos PAM module will fall back on attempting +anonymous PKINIT if that cache could not be used. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth and password groups. +.Sp +The operation is the same as if using the \fIfast_ccache\fR option, but the +cache is created and destroyed automatically. If both \fIfast_ccache\fR and +\&\fIanon_fast\fR options are used, the \fIfast_ccache\fR takes precedent and no +anonymous authentication is done. +.IP fast_ccache=<ccache_name> 4 +.IX Item "fast_ccache=<ccache_name>" +[4.3] The same as \fIanon_fast\fR, but use an existing Kerberos ticket cache +rather than anonymous PKINIT. This allows use of FAST with a realm that +doesn't support PKINIT or doesn't support anonymous authentication. +.Sp +<ccache_name> should be a credential cache containing a ticket obtained +using a strong key, such as the randomized key for the host principal of +the local system. If <ccache_name> names a ticket cache that is readable +by the authenticating process and has tickets then FAST will be attempted. +The easiest way to use this option is to use a program like \fBk5start\fR to +maintain a ticket cache using the host's keytab. This ticket cache should +normally only be readable by root, so this option will not be able to +protect authentications done as non-root users (such as screensavers). +.Sp +If no credentials are present in the ticket cache, or if the ticket cache +does not exist or is not readable, FAST will not used and authentication +will proceed as normal. However, if the credentials in that ticket cache +are expired, authentication will fail if the KDC supports FAST. +.Sp +To use anonymous PKINIT to protect the FAST exchange, use the \fIanon_fast\fR +option instead. \fIanon_fast\fR is easier to configure, since no existing +ticket cache is required, but requires PKINIT be available and configured +and that the local realm support anonymous authentication. If both +\&\fIfast_ccache\fR and \fIanon_fast\fR are set, the ticket cache named by +\&\fIfast_ccache\fR will be tried first, and the Kerberos PAM module will fall +back on attempting anonymous PKINIT if that cache could not be used. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth and password groups. +.IP forwardable 4 +.IX Item "forwardable" +[1.0] Obtain forwardable tickets. If set (to either true or false, +although it can only be set to false in \fIkrb5.conf\fR), this overrides the +Kerberos library default set in the [libdefaults] section of \fIkrb5.conf\fR. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth group. +.IP keytab=<path> 4 +.IX Item "keytab=<path>" +[3.0] Specifies the keytab to use when validating the user's credentials. +The default is the default system keytab (normally \fI/etc/krb5.keytab\fR), +which is usually only readable by root. Applications not running as root +that use this PAM module for authentication may wish to point it to +another keytab the application can read. The first principal found in the +keytab will be used as the principal for credential verification. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth group. +.IP realm=<realm> 4 +.IX Item "realm=<realm>" +[2.2] Set the default Kerberos realm and obtain credentials in that realm, +rather than in the normal default realm for this system. If this option +is used, it should be set for all groups being used for consistent +results. This setting will affect authorization decisions since it +changes the default realm. This setting will also change the service +principal used to verify the obtained credentials to be in the specified +realm. +.Sp +If you only want to set the realm assumed for user principals without +changing the realm for authorization decisions or the service principal +used to verify credentials, see the \fIuser_realm\fR option. +.IP renew_lifetime=<lifetime> 4 +.IX Item "renew_lifetime=<lifetime>" +[2.0] Obtain renewable tickets with a maximum renewable lifetime of +<lifetime>. <lifetime> should be a Kerberos lifetime string such as +\&\f(CW\*(C`2d4h10m\*(C'\fR or a time in minutes. If set, this overrides the Kerberos +library default set in the [libdefaults] section of \fIkrb5.conf\fR. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth group. +.IP ticket_lifetime=<lifetime> 4 +.IX Item "ticket_lifetime=<lifetime>" +[3.0] Obtain tickets with a maximum lifetime of <lifetime>. <lifetime> +should be a Kerberos lifetime string such as \f(CW\*(C`2d4h10m\*(C'\fR or a time in +minutes. If set, this overrides the Kerberos library default set in the +[libdefaults] section of \fIkrb5.conf\fR. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth group. +.IP user_realm 4 +.IX Item "user_realm" +[4.6] Obtain credentials in the specified realm rather than in the default +realm for this system. If this option is used, it should be set for all +groups being used for consistent results (although the account group +currently doesn't care about realm). This will not change authorization +decisions. If the obtained credentials are supposed to allow access to a +shell account, the user will need an appropriate \fI.k5login\fR file entry or +the system will have to have a custom aname_to_localname mapping. +.SS "PAM Behavior" +.IX Subsection "PAM Behavior" +.IP clear_on_fail 4 +.IX Item "clear_on_fail" +[3.9] When changing passwords, PAM first does a preliminary check through +the complete password stack, and then calls each module again to do the +password change. After that preliminary check, the order of module +invocation is fixed. This means that even if the Kerberos password change +fails (or if one of the other password changes in the stack fails), other +password PAM modules in the stack will still be called even if the failing +module is marked required or requisite. When using multiple password PAM +modules to synchronize passwords between multiple systems when they +change, this behavior can cause unwanted differences between the +environments. +.Sp +Setting this option provides a way to work around this behavior. If this +option is set and a Kerberos password change is attempted and fails (due +to network errors or password strength checking on the KDC, for example), +this module will clear the stored password in the PAM stack. This will +force any subsequent modules that have \fIuse_authtok\fR set to fail so that +those environments won't get out of sync with the password in Kerberos. +The Kerberos PAM module will not meddle with the stored password if it +skips the user due to configuration such as minimum_uid. +.Sp +Unfortunately, setting this option interferes with other desirable PAM +configurations, such as attempting to change the password in Kerberos +first and falling back on the local Unix password database if that fails. +It therefore isn't the default. Turn it on (and list pam_krb5 first after +pam_cracklib if used) when synchronizing passwords between multiple +environments. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the password group. +.IP debug 4 +.IX Item "debug" +[1.0] Log more verbose trace and debugging information to syslog at +LOG_DEBUG priority, including entry and exit from each of the external PAM +interfaces (except pam_close_session). +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR. +.IP defer_pwchange 4 +.IX Item "defer_pwchange" +[3.11] By default, pam\-krb5 lets the Kerberos library handle prompting for +a password change if an account's password is expired during the auth +group. If this fails, \fBpam_authenticate()\fR returns an error. +.Sp +According to the PAM standard, this is not the correct way to handle +expired passwords. Instead, \fBpam_authenticate()\fR should return success +without attempting a password change, and then \fBpam_acct_mgmt()\fR should +return PAM_NEW_AUTHTOK_REQD, at which point the calling application is +responsible for either rejecting the authentication or calling +\&\fBpam_chauthtok()\fR. However, following the standard requires that all +applications call \fBpam_acct_mgmt()\fR and check its return status; otherwise, +expired accounts may be able to successfully authenticate. Many +applications do not do this. +.Sp +If this option is set, pam\-krb5 uses the fully correct PAM mechanism for +handling expired accounts instead of failing in \fBpam_authenticate()\fR. Due +to the security risk of widespread broken applications, be very careful +about enabling this option. It should normally only be turned on to solve +a specific problem (such as using Solaris Kerberos libraries that don't +support prompting for password changes during authentication), and then +only for specific applications known to call \fBpam_acct_mgmt()\fR and check its +return status properly. +.Sp +This option is only supported when pam\-krb5 is built with MIT Kerberos. +If built against Heimdal, this option does nothing and normal expired +password change handling still happens. (Heimdal is missing the required +API to implement this option, at least as of version 1.6.) +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth group. +.IP fail_pwchange 4 +.IX Item "fail_pwchange" +[4.2] By default, pam\-krb5 lets the Kerberos library handle prompting for +a password change if an account's password is expired during the auth +group. If this option is set, expired passwords are instead treated as an +authentication failure identical to an incorrect password. Also see +\&\fIdefer_pwchange\fR and \fIforce_pwchange\fR. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth group. +.IP force_pwchange 4 +.IX Item "force_pwchange" +[3.11] If this option is set and authentication fails with a Kerberos +error indicating the user's password is expired, attempt to immediately +change their password during the authenticate step. Under normal +circumstances, this is unnecessary. Most Kerberos libraries will do this +for you, and setting this option will prompt the user twice to change +their password if the first attempt (done by the Kerberos library) fails. +However, some system Kerberos libraries (such as Solaris's) have password +change prompting disabled in the Kerberos library; on those systems, you +can set this option to simulate the normal library behavior. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth group. +.IP no_update_user 4 +.IX Item "no_update_user" +[4.7] Normally, if pam\-krb5 is able to canonicalize the principal to a +local name using \fBkrb5_aname_to_localname()\fR or similar calls, it changes +the PAM_USER variable for this PAM session to the canonicalized local +name. Setting this option disables this behavior and leaves PAM_USER set +to the initial authentication identity. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth group. +.IP silent 4 +.IX Item "silent" +[1.0] Don't show messages and errors from Kerberos, such as warnings of +expiring passwords, to the user via the prompter. This is equivalent to +the behavior when the application passes in PAM_SILENT, but can be set in +the PAM configuration. +.Sp +This option is only applicable to the auth and password groups. +.IP trace=<log\-file> 4 +.IX Item "trace=<log-file>" +[4.6] Enables Kerberos library trace logging to the specified log file if +it is supported by the Kerberos library. This is intended for temporary +debugging. The specified file will be appended to without further +security checks, so do not specify a file in a publicly writable directory +like \fI/tmp\fR. +.SS PKINIT +.IX Subsection "PKINIT" +.IP pkinit_anchors=<anchors> 4 +.IX Item "pkinit_anchors=<anchors>" +[3.0] When doing PKINIT authentication, use <anchors> as the client trust +anchors. This is normally a reference to a file containing the trusted +certificate authorities. This option is only used if \fItry_pkinit\fR or +\&\fIuse_pkinit\fR are set. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth and password groups. +.IP pkinit_prompt 4 +.IX Item "pkinit_prompt" +[3.0] Before attempting PKINIT authentication, prompt the user to insert a +smart card. You may want to set this option for programs such as +\&\fBgnome-screensaver\fR that call PAM as soon as the mouse is touched and +don't give the user an opportunity to enter the smart card first. Any +information entered at the first prompt is ignored. If \fItry_pkinit\fR is +set, a user who wishes to use a password instead can just press Enter and +then enter their password as normal. This option is only used if +\&\fItry_pkinit\fR or \fIuse_pkinit\fR are set. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth and password groups. +.IP pkinit_user=<userid> 4 +.IX Item "pkinit_user=<userid>" +[3.0] When doing PKINIT authentication, use <userid> as the user ID. The +value of this string is highly dependent on the type of PKINIT +implementation you're using, but will generally be something like: +.Sp +.Vb 1 +\& PKCS11:/usr/lib/pkcs11/lib/soft\-pkcs11.so +.Ve +.Sp +to specify the module to use with a smart card. It may also point to a +user certificate or to other types of user IDs. See the Kerberos library +documentation for more details. This option is only used if \fItry_pkinit\fR +or \fIuse_pkinit\fR are set. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth and password groups. +.IP preauth_opt=<option> 4 +.IX Item "preauth_opt=<option>" +[3.3] Sets a preauth option (currently only applicable when built with MIT +Kerberos). <option> is either a key/value pair with the key separated +from the value by \f(CW\*(C`=\*(C'\fR or a boolean option (in which case it's turned on). +In \fIkrb5.conf\fR, multiple options should be separated by whitespace. In +the PAM configuration, this option can be given multiple times to set +multiple options. In either case, <option> may not contain whitespace. +.Sp +The primary use of this option, at least in the near future, will be to +set options for the MIT Kerberos PKINIT support. For the full list of +possible options, see the PKINIT plugin documentation. At the time of +this writing, \f(CW\*(C`X509_user_identity\*(C'\fR is equivalent to \fIpkinit_user\fR and +\&\f(CW\*(C`X509_anchors\*(C'\fR is equivalent to \fIpkinit_anchors\fR. \f(CW\*(C`flag_DSA_PROTOCOL\*(C'\fR +can only be set via this option. +.Sp +Any settings made with this option are applied after the \fIpkinit_anchors\fR +and \fIpkinit_user\fR options, so if an equivalent setting is made via +\&\fIpreauth_opt\fR, it will probably override the other setting. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth and password groups. Note that there is no way to +remove a setting made in \fIkrb5.conf\fR using the PAM configuration, but +options set in the PAM configuration are applied after options set in +\&\fIkrb5.conf\fR and therefore may override earlier settings. +.IP try_pkinit 4 +.IX Item "try_pkinit" +[3.0] Attempt PKINIT authentication before trying a regular password. You +will probably also need to set the \fIpkinit_user\fR configuration option. +If PKINIT fails, the PAM module will fall back on regular password +authentication. This option is currently only supported if pam\-krb5 was +built against Heimdal 0.8rc1 or later or MIT Kerberos 1.6.3 or later. +.Sp +If this option is set and pam\-krb5 is built against MIT Kerberos, and +PKINIT fails and the module falls back to password authentication, the +user's password will not be stored in the PAM stack for subsequent +modules. This is a bug in the interaction between the module and MIT +Kerberos that requires some reworking of the PKINIT authentication method +to fix. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth and password groups. +.IP use_pkinit 4 +.IX Item "use_pkinit" +[3.0, 4.9 for MIT Kerberos] Require PKINIT authentication. You will +probably also need to set the \fIpkinit_user\fR configuration option. If +PKINIT fails, authentication will fail. This option is only supported if +pam\-krb5 was built against Heimdal 0.8rc1 or later or MIT Kerberos 1.12 or +later. +.Sp +Be aware that, with MIT Kerberos, this option is implemented by using a +responder without a prompter, and thus any informational messages from the +Kerberos libraries or KDC during authentication will not be displayed. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth and password groups. +.SS Prompting +.IX Subsection "Prompting" +.IP banner=<banner> 4 +.IX Item "banner=<banner>" +[3.0] By default, the prompts when a user changes their password are: +.Sp +.Vb 3 +\& Current Kerberos password: +\& Enter new Kerberos password: +\& Retype new Kerberos password: +.Ve +.Sp +The string "Kerberos" is inserted so that users aren't confused about +which password they're changing. Setting this option replaces the word +"Kerberos" with whatever this option is set to. Setting this option to +the empty string removes the word before "password:" entirely. +.Sp +If set in the PAM configuration, <banner> may not contain whitespace. If +you want a value containing whitespace, set it in \fIkrb5.conf\fR. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the password group. +.IP expose_account 4 +.IX Item "expose_account" +[3.0] By default, the Kerberos PAM module password prompt is simply +"Password:". This avoids leaking any information about the system realm +or account to principal conversions. If this option is set, the string +"for <principal>" is added before the colon, where <principal> is the +user's principal. This string is also added before the colon on prompts +when changing the user's password. +.Sp +Enabling this option with ChallengeResponseAuthentication enabled in +OpenSSH may cause problems for some ssh clients that only recognize +"Password:" as a prompt. This option is automatically disabled if +\&\fIsearch_k5login\fR is enabled since the principal displayed would be +inaccurate. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth and password groups. +.IP force_first_pass 4 +.IX Item "force_first_pass" +[4.0] Use the password obtained by a previous authentication or password +module to authenticate the user without prompting the user again. If no +previous module obtained the user's password, fail without prompting the +user. Also see \fItry_first_pass\fR and \fIuse_first_pass\fR for weaker +versions of this option. +.Sp +This option is only applicable to the auth and password groups. For the +password group, it applies only to the old password. See \fIuse_authtok\fR +for a similar setting for the new password. +.IP no_prompt 4 +.IX Item "no_prompt" +[4.6] Never prompt for the current password. Instead, pass in a NULL +password to the Kerberos library and let the Kerberos library do the +prompting. This may be needed if, for example, the Kerberos library is +configured to use other authentication mechanisms than passwords and needs +full control over the prompting process. +.Sp +The major disadvantage of this option is that it means the PAM module will +never see the user's password and therefore cannot save it in the PAM +module data for any subsequent modules. In other words, this option +cannot be used if another module is in the stack behind the Kerberos PAM +module and wants to use \fIuse_first_pass\fR. The Kerberos library also +usually includes the principal in the prompt, and therefore this option +implies behavior similar to \fIexpose_account\fR. Similar to +\&\fIexpose_account\fR, this can cause problems with OpenSSH if +ChallengeResponseAuthentication is enabled, since clients may not +recognize password prompts other than "Password:". +.Sp +Using this option with \fIsearch_k5login\fR would result in a password prompt +for every principal listed in the user's \fI.k5login\fR file. This is +probably not desired behavior, although it's not prohibited by the module. +.Sp +This option is only applicable to the auth and password groups. For the +password group, it applies only to the authentication process; the user +will still be prompted for a new password. +.IP prompt_principal 4 +.IX Item "prompt_principal" +[3.6] Before prompting for the user's password (or using the previously +entered password, if \fItry_first_pass\fR, \fIuse_first_pass\fR, or +\&\fIforce_first_pass\fR are set), prompt the user for the Kerberos principal +to use for authentication. This allows the user to authenticate with a +different principal than the one corresponding to the local username, +provided that either a \fI.k5login\fR file or local Kerberos principal to +account mapping authorize that principal to access the local account. +.Sp +Be cautious when using this configuration option and don't use it with +OpenSSH PasswordAuthentication, only ChallengeResponseAuthentication. +Some PAM-enabled applications expect PAM modules to only prompt for +passwords and may even blindly give the password to the first prompt, no +matter what it is. Such applications, in combination with this option, +may expose the user's password in log messages and Kerberos requests. +.IP try_first_pass 4 +.IX Item "try_first_pass" +[1.0] If the authentication module isn't the first on the stack, and a +previous module obtained the user's password, use that password to +authenticate the user without prompting them again. If that +authentication fails, fall back on prompting the user for their password. +This option has no effect if the authentication module is first in the +stack or if no previous module obtained the user's password. Also see +\&\fIuse_first_pass\fR and \fIforce_first_pass\fR for stronger versions of this +option. +.Sp +This option is only applicable to the auth and password groups. For the +password group, it applies only to the old password. +.IP use_authtok 4 +.IX Item "use_authtok" +[4.0] Use the new password obtained by a previous password module when +changing passwords rather than prompting for the new password. If the new +password isn't available, fail. This can be used to require passwords be +checked by another, prior module, such as \fBpam_cracklib\fR. +.Sp +This option is only applicable to the password group. +.IP use_first_pass 4 +.IX Item "use_first_pass" +[1.0] Use the password obtained by a previous authentication module to +authenticate the user without prompting the user again. If no previous +module obtained the user's password for either an authentication or +password change, fall back on prompting the user. If a previous module +did obtain the user's password but authentication with that password +fails, fail without further prompting the user. Also see +\&\fItry_first_pass\fR and \fIforce_first_pass\fR for other versions of this +option. +.Sp +This option is only applicable to the auth and password groups. For the +password group, it applies only to the old password. See \fIuse_authtok\fR +for a similar setting for the new password. +.SS "Ticket Caches" +.IX Subsection "Ticket Caches" +.IP ccache=<pattern> 4 +.IX Item "ccache=<pattern>" +[2.0] Use <pattern> as the pattern for creating credential cache names. +<pattern> must be in the form <type>:<residual> where <type> and the +following colon are optional if a file cache should be used. The special +token \f(CW%u\fR, anywhere in <pattern>, is replaced with the user's numeric +UID. The special token \f(CW%p\fR, anywhere in <pattern>, is replaced with the +current process ID. +.Sp +If <pattern> ends in the literal string \f(CW\*(C`XXXXXX\*(C'\fR (six X's), that string +will be replaced by randomly generated characters and the ticket cache +will be created using \fBmkstemp\fR\|(3). This is strongly recommended if +<pattern> points to a world-writable directory. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth and session groups. +.IP ccache_dir=<directory> 4 +.IX Item "ccache_dir=<directory>" +[1.2] Store both the temporary ticket cache used during authentication and +user ticket caches in <directory> instead of in \fI/tmp\fR. The algorithm +for generating the ticket cache name is otherwise unchanged. <directory> +may be prefixed with \f(CW\*(C`FILE:\*(C'\fR to make the cache type unambiguous (and this +may be required on systems that use a cache type other than file as the +default). +.Sp +Be aware that pam_krb5 creates and stores a temporary ticket cache file +owned by root during the login process. If you set \fIccache\fR above to +avoid using the system \fI/tmp\fR directory for user ticket caches, you may +also want to set \fIccache_dir\fR to move those temporary caches to some +other location. This will allow pam_krb5 to continue working even if the +system \fI/tmp\fR directory is full. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth and session groups. +.IP no_ccache 4 +.IX Item "no_ccache" +[1.0] Do not create a ticket cache after authentication. This option +shouldn't be set in general, but is useful as part of the PAM +configuration for a particular service that uses PAM for authentication +but isn't creating user sessions and doesn't want the overhead of ever +writing the user credentials to disk. When using this option, the +application should only call \fBpam_authenticate()\fR; other functions like +\&\fBpam_setcred()\fR, \fBpam_start_session()\fR, and \fBpam_acct_mgmt()\fR don't make sense +with this option. Don't use this option if the application needs PAM +account and session management calls. +.Sp +This option is only applicable to the auth group. +.IP retain_after_close 4 +.IX Item "retain_after_close" +[2.3] Normally, the user's ticket cache is destroyed when either \fBpam_end()\fR +or \fBpam_close_session()\fR is called by the authenticating application so that +ticket caches aren't left behind after the user logs out. In some cases, +however, this isn't desirable. (On Solaris 8, for instance, the default +behavior means login will destroy the ticket cache before running the +user's shell.) If this option is set, the PAM module will never destroy +the user's ticket cache. If you set this, you may want to call +\&\fBkdestroy\fR in the shell's logout configuration or run a temporary file +removal program to avoid accumulating hundreds of ticket caches in +\&\fI/tmp\fR. +.Sp +This option can be set in \f(CW\*(C`[appdefaults]\*(C'\fR in \fIkrb5.conf\fR and is only +applicable to the auth and session groups. +.SH ENVIRONMENT +.IX Header "ENVIRONMENT" +.IP KRB5CCNAME 4 +.IX Item "KRB5CCNAME" +Set by \fBpam_setcred()\fR with the PAM_ESTABLISH_CRED option, and therefore +also by \fBpam_open_session()\fR, to point to the new credential cache for the +user. See the \fIccache\fR and \fIccache_dir\fR options. By default, the cache +name will be prefixed with \f(CW\*(C`FILE:\*(C'\fR to make the cache type unambiguous. +.IP PAM_KRB5CCNAME 4 +.IX Item "PAM_KRB5CCNAME" +Set by \fBpam_authenticate()\fR to point to the temporary ticket cache used for +authentication (unless the \fIno_ccache\fR option was given). \fBpam_setcred()\fR +then uses that environment variable to locate the temporary cache even if +it was not called in the same PAM session as \fBpam_authenticate()\fR (a problem +with \fBsshd\fR running in some modes). This environment variable is only +used internal to the PAM module. +.SH FILES +.IX Header "FILES" +.IP \fI/tmp/krb5cc_UID_RANDOM\fR 4 +.IX Item "/tmp/krb5cc_UID_RANDOM" +The default credential cache name. UID is the decimal UID of the local +user and RANDOM is a random six-character string. The pattern may be +changed with the \fIccache\fR option and the directory with the \fIccache_dir\fR +option. +.IP \fI/tmp/krb5cc_pam_RANDOM\fR 4 +.IX Item "/tmp/krb5cc_pam_RANDOM" +The credential cache name used for the temporary credential cache created +by \fBpam_authenticate()\fR. This cache is removed again when the PAM session +is ended or when \fBpam_setcred()\fR is called and will normally not be +user-visible. RANDOM is a random six-character string. +.IP \fI~/.k5login\fR 4 +.IX Item "~/.k5login" +File containing Kerberos principals that are allowed access to that +account. +.SH BUGS +.IX Header "BUGS" +If \fItry_pkinit\fR is set and pam\-krb5 is built with MIT Kerberos, the +user's password is not saved in the PAM data if PKINIT fails and the +module falls back to password authentication. +.SH CAVEATS +.IX Header "CAVEATS" +Be sure to list this module in the session group as well as the auth group +when using it for interactive logins. Otherwise, some applications (such +as OpenSSH) will not set up the user's ticket cache correctly. +.PP +The Kerberos library, via pam\-krb5, will prompt the user to change their +password if their password is expired, but when using OpenSSH, this will +only work when ChallengeResponseAuthentication is enabled. Unless this +option is enabled, OpenSSH doesn't pass PAM messages to the user and can +only respond to a simple password prompt. +.PP +If you are using MIT Kerberos, be aware that users whose passwords are +expired will not be prompted to change their password unless the KDC +configuration for your realm in [realms] in krb5.conf contains a +master_kdc setting or, if using DNS SRV records, you have a DNS entry for +_kerberos\-master as well as _kerberos. +.PP +\&\fBpam_authenticate()\fR returns failure when called for an ignored account, +requiring the system administrator to use \f(CW\*(C`optional\*(C'\fR or \f(CW\*(C`sufficient\*(C'\fR to +ignore the module and move on to the next module. It's arguably more +correct to return PAM_IGNORE, which causes the module to be ignored as if +it weren't in the configuration, but this increases the risk of +inadvertent security holes when listing pam\-krb5 as the only +authentication module. +.PP +This module treats the empty password as an authentication failure +rather than attempting to use that password to avoid unwanted prompting +behavior in the Kerberos libraries. If you have a Kerberos principal that +intentionally has an empty password, it won't work with this module. +.PP +This module will not refresh an existing ticket cache if called with an +effective UID or GID different than the real UID or GID, since refreshing +an existing ticket cache requires trusting the KRB5CCNAME environment +variable and the environment should not be trusted in a setuid context. +.PP +Old versions of OpenSSH are known to call pam_authenticate followed by +pam_setcred(PAM_REINITIALIZE_CRED) without first calling pam_open_session, +thereby requesting that an existing ticket cache be renewed (similar to +what a screensaver would want) rather than requesting a new ticket cache +be created. Since this behavior is indistinguishable at the PAM level +from a screensaver, pam\-krb5 when used with these old versions of OpenSSH +will refresh the ticket cache of the OpenSSH daemon rather than setting up +a new ticket cache for the user. The resulting ticket cache will have the +correct permissions, but will not be named correctly or referenced in the +user's environment and will be overwritten by the next user login. The +best solution to this problem is to upgrade OpenSSH. I'm not sure exactly +when this problem was fixed, but at the very least OpenSSH 4.3 and later +do not exhibit it. +.SH AUTHOR +.IX Header "AUTHOR" +pam\-krb5 was originally written by Frank Cusack. Andres Salomon made +extensive modifications, and then Russ Allbery <eagle@eyrie.org> adopted +it and made even more extensive modifications. Russ Allbery currently +maintains the module. +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright 2005\-2010, 2014, 2020 Russ Allbery <eagle@eyrie.org> +.PP +Copyright 2008\-2014 The Board of Trustees of the Leland Stanford Junior +University +.PP +Copying and distribution of this file, with or without modification, are +permitted in any medium without royalty provided the copyright notice and +this notice are preserved. This file is offered as-is, without any +warranty. +.PP +SPDX-License-Identifier: FSFAP +.SH "SEE ALSO" +.IX Header "SEE ALSO" +\&\fBkadmin\fR\|(8), \fBkdestroy\fR\|(1), \fBkrb5.conf\fR\|(5), \fBpam\fR\|(7), \fBpasswd\fR\|(1), \fBsyslog\fR\|(3) +.PP +The current version of this module is available from its web page at +<https://www.eyrie.org/~eagle/software/pam\-krb5/>. diff --git a/lib/libpam/modules/pam_krb5/pam_krb5.c b/lib/libpam/modules/pam_krb5/pam_krb5.c index 5f448165b20a..e13c1b794d5b 100644 --- a/lib/libpam/modules/pam_krb5/pam_krb5.c +++ b/lib/libpam/modules/pam_krb5/pam_krb5.c @@ -60,6 +60,10 @@ #include <krb5.h> #include <com_err.h> +#ifdef MK_MITKRB5 +/* For MIT KRB5 only. */ +#include <k5-int.h> +#endif #define PAM_SM_AUTH #define PAM_SM_ACCOUNT diff --git a/lib/libpam/modules/pam_ksu/Makefile b/lib/libpam/modules/pam_ksu/Makefile index c5fd72d9db7d..953ca23d1416 100644 --- a/lib/libpam/modules/pam_ksu/Makefile +++ b/lib/libpam/modules/pam_ksu/Makefile @@ -25,10 +25,21 @@ PACKAGE= kerberos +.include <src.opts.mk> + LIB= pam_ksu SRCS= pam_ksu.c MAN= pam_ksu.8 +WARNS?= 3 LIBADD+= krb5 +.if ${MK_MITKRB5} != "no" +WARNS= 2 +CFLAGS+= -I${SRCTOP}/crypto/krb5/src/include +CFLAGS+= -I${SRCTOP}/krb5/include +CFLAGS+= -include ${SRCTOP}/crypto/krb5/src/include/k5-int.h +CFLAGS+= -DMK_MITKRB5=yes +.endif + .include <bsd.lib.mk> diff --git a/lib/libpam/modules/pam_ksu/pam_ksu.c b/lib/libpam/modules/pam_ksu/pam_ksu.c index 47362c835c12..002613188d8c 100644 --- a/lib/libpam/modules/pam_ksu/pam_ksu.c +++ b/lib/libpam/modules/pam_ksu/pam_ksu.c @@ -48,6 +48,62 @@ static long get_su_principal(krb5_context, const char *, const char *, static int auth_krb5(pam_handle_t *, krb5_context, const char *, krb5_principal); +#ifdef MK_MITKRB5 +/* For MIT KRB5 only. */ + +/* + * XXX This entire module will need to be rewritten when heimdal + * XXX compatidibility is no longer needed. + */ +#define KRB5_DEFAULT_CCFILE_ROOT "/tmp/krb5cc_" +#define KRB5_DEFAULT_CCROOT "FILE:" KRB5_DEFAULT_CCFILE_ROOT + +/* + * XXX We will replace krb5_build_principal_va() with + * XXX krb5_build_principal_alloc_va() when Heimdal is finally + * XXX removed. + */ +krb5_error_code KRB5_CALLCONV +krb5_build_principal_va(krb5_context context, + krb5_principal princ, + unsigned int rlen, + const char *realm, + va_list ap); +typedef char *heim_general_string; +typedef heim_general_string Realm; +typedef Realm krb5_realm; +typedef const char *krb5_const_realm; + +static krb5_error_code +krb5_make_principal(krb5_context context, krb5_principal principal, + krb5_const_realm realm, ...) +{ + krb5_realm temp_realm = NULL; + krb5_error_code rc; + va_list ap; + + if (realm == NULL) { + if ((rc = krb5_get_default_realm(context, &temp_realm))) + return (rc); + realm=temp_realm; + } + va_start(ap, realm); + /* + * XXX Ideally we should be using krb5_build_principal_alloc_va() + * XXX here because krb5_build_principal_va() is deprecated. But, + * XXX this would require changes elsewhere in the calling code + * XXX to call krb5_free_principal() elsewhere to free the + * XXX principal. We can do that after Heimdal is removed from + * XXX our tree. + */ + rc = krb5_build_principal_va(context, principal, strlen(realm), realm, ap); + va_end(ap); + if (temp_realm) + free(temp_realm); + return (rc); +} +#endif + PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, int argc __unused, const char *argv[] __unused) @@ -217,7 +273,13 @@ get_su_principal(krb5_context context, const char *target_user, const char *curr if (rv != 0) return (errno); if (default_principal == NULL) { +#ifdef MK_MITKRB5 + /* For MIT KRB5. */ + rv = krb5_make_principal(context, default_principal, NULL, current_user, NULL); +#else + /* For Heimdal. */ rv = krb5_make_principal(context, &default_principal, NULL, current_user, NULL); +#endif if (rv != 0) { PAM_LOG("Could not determine default principal name."); return (rv); diff --git a/lib/libpam/modules/pam_xdg/pam_xdg.8 b/lib/libpam/modules/pam_xdg/pam_xdg.8 index 9b97d3626531..9b335751a9fb 100644 --- a/lib/libpam/modules/pam_xdg/pam_xdg.8 +++ b/lib/libpam/modules/pam_xdg/pam_xdg.8 @@ -22,7 +22,7 @@ .\" * 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. -.Dd August 22, 2024 +.Dd May 20, 2025 .Dt PAM_XDG 8 .Os .Sh NAME @@ -35,17 +35,26 @@ .Pa pam_xdg .Op Ar arguments .Sh DESCRIPTION -The xdg service module for PAM sets up the runtime directory according -to the XDG specifications. +The xdg service module for PAM creates the runtime files base directory +according to the Cross Desktop Group Base Directory Specification. .Pp By default the directory is created under -.Pa /var/run/xdg/<username> . +.Pa /var/run/xdg/ Ns $ Ns Ev USER . .Pp The following option may be passed to the authentication module: -.Bl -tag -width ".Cm runtime_dir_prefix" +.Bl -tag -width "runtime_dir_prefix=directory" .It Cm runtime_dir_prefix Ns = Ns Ar directory Use an alternate base directory .El +.Sh ENVIRONMENT +.Bl -tag -width indent +.It Ev XDG_RUNTIME_DIR +The location of the runtime files base directory created by this module. +Note that the module does not set this environment variable. +.El +.Sh STANDARDS +The directory created by this module conforms to the +.Lk https://specifications.freedesktop.org/basedir-spec XDG Base Directory Specification . .Sh SEE ALSO .Xr pam 3 , .Xr pam.conf 5 diff --git a/lib/libpam/pam.d/Makefile b/lib/libpam/pam.d/Makefile index 5dccf590ee4e..a58c37b6c223 100644 --- a/lib/libpam/pam.d/Makefile +++ b/lib/libpam/pam.d/Makefile @@ -22,18 +22,15 @@ CRONPACKAGE= cron .if ${MK_AT} != "no" CONFGROUPS+= AT -AT+= atrun +AT+= atrun ATPACKAGE+= at .endif .if ${MK_FTP} != "no" CONFGROUPS+= FTP -FTP+= ftpd -FTPPACKAGE= ftp - -LINKMODE= ${CONFMODE} -afterinstallconfig: - ${INSTALL_LINK} ${TAG_ARGS} ${DESTDIR}${CONFDIR}/ftpd ${DESTDIR}${CONFDIR}/ftp +FTP+= ftp ftpd +# Do not put these in the ftp package, since ports also use them. +FTPPACKAGE= runtime .endif .include <bsd.prog.mk> diff --git a/lib/libpam/pam.d/ftp b/lib/libpam/pam.d/ftp new file mode 100644 index 000000000000..1c255441dca6 --- /dev/null +++ b/lib/libpam/pam.d/ftp @@ -0,0 +1,13 @@ +# +# PAM configuration for the "ftp" service. This is not used by the FreeBSD +# ftpd(8), but is provided for compatibility with FTP servers from ports. +# + +# auth +auth include ftpd + +# account +account include ftpd + +# session +session include ftpd diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index e1cae22e2f3e..e4123fe02211 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -396,7 +396,7 @@ SNL_DECLARE_PARSER(getstatus_parser, struct genlmsghdr, snl_f_p_empty, ap_getsta #undef _OUT struct pfctl_status * -pfctl_get_status_h(struct pfctl_handle *h __unused) +pfctl_get_status_h(struct pfctl_handle *h) { struct pfctl_status *status; struct snl_errmsg_data e = {}; @@ -1209,6 +1209,19 @@ snl_add_msg_attr_uid(struct snl_writer *nw, uint32_t type, const struct pf_rule_ } static void +snl_add_msg_attr_threshold(struct snl_writer *nw, uint32_t type, const struct pfctl_threshold *th) +{ + int off; + + off = snl_add_msg_attr_nested(nw, type); + + snl_add_msg_attr_u32(nw, PF_TH_LIMIT, th->limit); + snl_add_msg_attr_u32(nw, PF_TH_SECONDS, th->seconds); + + snl_end_attr_nested(nw, off); +} + +static void snl_add_msg_attr_pf_rule(struct snl_writer *nw, uint32_t type, const struct pfctl_rule *r) { int off; @@ -1228,6 +1241,7 @@ snl_add_msg_attr_pf_rule(struct snl_writer *nw, uint32_t type, const struct pfct snl_add_msg_attr_rpool(nw, PF_RT_RPOOL_RDR, &r->rdr); snl_add_msg_attr_rpool(nw, PF_RT_RPOOL_NAT, &r->nat); snl_add_msg_attr_rpool(nw, PF_RT_RPOOL_RT, &r->route); + snl_add_msg_attr_threshold(nw, PF_RT_PKTRATE, &r->pktrate); snl_add_msg_attr_u32(nw, PF_RT_OS_FINGERPRINT, r->os_fingerprint); snl_add_msg_attr_u32(nw, PF_RT_RTABLEID, r->rtableid); snl_add_msg_attr_timeouts(nw, PF_RT_TIMEOUT, r->timeout); @@ -1237,6 +1251,7 @@ snl_add_msg_attr_pf_rule(struct snl_writer *nw, uint32_t type, const struct pfct snl_add_msg_attr_u32(nw, PF_RT_MAX_SRC_CONN, r->max_src_conn); snl_add_msg_attr_u32(nw, PF_RT_MAX_SRC_CONN_RATE_LIMIT, r->max_src_conn_rate.limit); snl_add_msg_attr_u32(nw, PF_RT_MAX_SRC_CONN_RATE_SECS, r->max_src_conn_rate.seconds); + snl_add_msg_attr_u16(nw, PF_RT_MAX_PKT_SIZE, r->max_pkt_size); snl_add_msg_attr_u16(nw, PF_RT_DNPIPE, r->dnpipe); snl_add_msg_attr_u16(nw, PF_RT_DNRPIPE, r->dnrpipe); @@ -1581,6 +1596,15 @@ static const struct snl_attr_parser ap_rule_uid[] = { SNL_DECLARE_ATTR_PARSER(rule_uid_parser, ap_rule_uid); #undef _OUT +#define _OUT(_field) offsetof(struct pfctl_threshold, _field) +static const struct snl_attr_parser ap_pfctl_threshold[] = { + { .type = PF_TH_LIMIT, .off = _OUT(limit), .cb = snl_attr_get_uint32 }, + { .type = PF_TH_SECONDS, .off = _OUT(seconds), .cb = snl_attr_get_uint32 }, + { .type = PF_TH_COUNT, .off = _OUT(count), .cb = snl_attr_get_uint32 }, +}; +SNL_DECLARE_ATTR_PARSER(pfctl_threshold_parser, ap_pfctl_threshold); +#undef _OUT + struct pfctl_nl_get_rule { struct pfctl_rule r; char anchor_call[MAXPATHLEN]; @@ -1668,6 +1692,8 @@ static struct snl_attr_parser ap_getrule[] = { { .type = PF_RT_SRC_NODES_LIMIT, .off = _OUT(r.src_nodes_type[PF_SN_LIMIT]), .cb = snl_attr_get_uint64 }, { .type = PF_RT_SRC_NODES_NAT, .off = _OUT(r.src_nodes_type[PF_SN_NAT]), .cb = snl_attr_get_uint64 }, { .type = PF_RT_SRC_NODES_ROUTE, .off = _OUT(r.src_nodes_type[PF_SN_ROUTE]), .cb = snl_attr_get_uint64 }, + { .type = PF_RT_PKTRATE, .off = _OUT(r.pktrate), .arg = &pfctl_threshold_parser, .cb = snl_attr_get_nested }, + { .type = PF_RT_MAX_PKT_SIZE, .off =_OUT(r.max_pkt_size), .cb = snl_attr_get_uint16 }, }; #undef _OUT SNL_DECLARE_PARSER(getrule_parser, struct genlmsghdr, snl_f_p_empty, ap_getrule); @@ -2271,6 +2297,9 @@ pfctl_set_syncookies(int dev, const struct pfctl_syncookies *s) if (ret != 0) return (ret); + if (state_limit == 0) + state_limit = INT_MAX; + lim = state_limit; hi = lim * s->highwater / 100; lo = lim * s->lowwater / 100; @@ -2311,6 +2340,9 @@ pfctl_get_syncookies(int dev, struct pfctl_syncookies *s) if (ret != 0) return (ret); + if (state_limit == 0) + state_limit = INT_MAX; + bzero(s, sizeof(*s)); nvl = nvlist_create(0); @@ -2995,16 +3027,6 @@ pfctl_get_ruleset(struct pfctl_handle *h, const char *path, uint32_t nr, struct return (e.error); } -#define _OUT(_field) offsetof(struct pfctl_threshold, _field) -static const struct snl_attr_parser ap_pfctl_threshold[] = { - { .type = PF_TH_LIMIT, .off = _OUT(limit), .cb = snl_attr_get_uint32 }, - { .type = PF_TH_SECONDS, .off = _OUT(seconds), .cb = snl_attr_get_uint32 }, - { .type = PF_TH_COUNT, .off = _OUT(count), .cb = snl_attr_get_uint32 }, - { .type = PF_TH_LAST, .off = _OUT(last), .cb = snl_attr_get_uint32 }, -}; -SNL_DECLARE_ATTR_PARSER(pfctl_threshold_parser, ap_pfctl_threshold); -#undef _OUT - #define _OUT(_field) offsetof(struct pfctl_src_node, _field) static struct snl_attr_parser ap_srcnode[] = { { .type = PF_SN_ADDR, .off = _OUT(addr), .cb = snl_attr_get_in6_addr }, @@ -3054,6 +3076,7 @@ pfctl_get_srcnodes(struct pfctl_handle *h, pfctl_get_srcnode_fn fn, void *arg) return (ENXIO); while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { + bzero(&sn, sizeof(sn)); if (!snl_parse_nlmsg(&h->ss, hdr, &srcnode_parser, &sn)) continue; @@ -3279,3 +3302,90 @@ pfctl_get_tstats(struct pfctl_handle *h, const struct pfr_table *filter, return (e.error); } +static struct snl_attr_parser ap_tstats_clr[] = { + { .type = PF_TS_NZERO, .off = 0, .cb = snl_attr_get_uint64 }, +}; +SNL_DECLARE_PARSER(tstats_clr_parser, struct genlmsghdr, snl_f_p_empty, ap_tstats_clr); + +int +pfctl_clear_tstats(struct pfctl_handle *h, const struct pfr_table *filter, + int *nzero, int flags) +{ + struct snl_writer nw; + struct snl_errmsg_data e = {}; + struct nlmsghdr *hdr; + uint64_t zero; + uint32_t seq_id; + int family_id; + + family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); + if (family_id == 0) + return (ENOTSUP); + + snl_init_writer(&h->ss, &nw); + hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_CLR_TSTATS); + + snl_add_msg_attr_string(&nw, PF_T_ANCHOR, filter->pfrt_anchor); + snl_add_msg_attr_string(&nw, PF_T_NAME, filter->pfrt_name); + snl_add_msg_attr_u32(&nw, PF_T_TABLE_FLAGS, filter->pfrt_flags); + snl_add_msg_attr_u32(&nw, PF_T_FLAGS, flags); + + if ((hdr = snl_finalize_msg(&nw)) == NULL) + return (ENXIO); + + seq_id = hdr->nlmsg_seq; + + if (!snl_send_message(&h->ss, hdr)) + return (ENXIO); + + while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { + if (!snl_parse_nlmsg(&h->ss, hdr, &tstats_clr_parser, &zero)) + continue; + if (nzero) + *nzero = (uint32_t)zero; + } + + return (e.error); +} + +int +pfctl_clear_addrs(struct pfctl_handle *h, const struct pfr_table *filter, + int *ndel, int flags) +{ + struct snl_writer nw; + struct snl_errmsg_data e = {}; + struct nlmsghdr *hdr; + uint64_t del; + uint32_t seq_id; + int family_id; + + family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); + if (family_id == 0) + return (ENOTSUP); + + snl_init_writer(&h->ss, &nw); + hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_CLR_ADDRS); + + snl_add_msg_attr_string(&nw, PF_T_ANCHOR, filter->pfrt_anchor); + snl_add_msg_attr_string(&nw, PF_T_NAME, filter->pfrt_name); + snl_add_msg_attr_u32(&nw, PF_T_TABLE_FLAGS, filter->pfrt_flags); + snl_add_msg_attr_u32(&nw, PF_T_FLAGS, flags); + + if ((hdr = snl_finalize_msg(&nw)) == NULL) + return (ENXIO); + + seq_id = hdr->nlmsg_seq; + + if (!snl_send_message(&h->ss, hdr)) + return (ENXIO); + + while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { + if (!snl_parse_nlmsg(&h->ss, hdr, &tstats_clr_parser, &del)) + continue; + if (ndel) + *ndel = (uint32_t)del; + } + + return (e.error); +} + diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h index c1c1da66746b..98a80758ca74 100644 --- a/lib/libpfctl/libpfctl.h +++ b/lib/libpfctl/libpfctl.h @@ -159,6 +159,13 @@ struct pfctl_rules_info { uint32_t ticket; }; +struct pfctl_threshold { + uint32_t limit; + uint32_t seconds; + uint32_t count; + uint32_t last; +}; + struct pfctl_rule { struct pf_rule_addr src; struct pf_rule_addr dst; @@ -181,6 +188,7 @@ struct pfctl_rule { struct pfctl_pool rdr; }; struct pfctl_pool route; + struct pfctl_threshold pktrate; uint64_t evaluations; uint64_t packets[2]; @@ -203,6 +211,7 @@ struct pfctl_rule { uint32_t limit; uint32_t seconds; } max_src_conn_rate; + uint16_t max_pkt_size; uint32_t qid; uint32_t pqid; uint16_t dnpipe; @@ -396,13 +405,6 @@ struct pfctl_syncookies { uint32_t halfopen_states; }; -struct pfctl_threshold { - uint32_t limit; - uint32_t seconds; - uint32_t count; - uint32_t last; -}; - struct pfctl_src_node { struct pf_addr addr; struct pf_addr raddr; @@ -554,5 +556,9 @@ int pfctl_del_table(struct pfctl_handle *h, struct pfr_table *table, typedef int (*pfctl_get_tstats_fn)(const struct pfr_tstats *t, void *arg); int pfctl_get_tstats(struct pfctl_handle *h, const struct pfr_table *filter, pfctl_get_tstats_fn fn, void *arg); +int pfctl_clear_tstats(struct pfctl_handle *h, const struct pfr_table *filter, + int *nzero, int flags); +int pfctl_clear_addrs(struct pfctl_handle *h, const struct pfr_table *filter, + int *ndel, int flags); #endif diff --git a/lib/libpmcstat/libpmcstat_image.c b/lib/libpmcstat/libpmcstat_image.c index 414ba133590b..69274dca31e8 100644 --- a/lib/libpmcstat/libpmcstat_image.c +++ b/lib/libpmcstat/libpmcstat_image.c @@ -193,6 +193,14 @@ pmcstat_image_link(struct pmcstat_process *pp, struct pmcstat_image *image, assert(image->pi_type != PMCSTAT_IMAGE_UNKNOWN && image->pi_type != PMCSTAT_IMAGE_INDETERMINABLE); + /* + * It's possible to have images with nothing of value in .text + * legitimately. We shouldn't have any samples from this image, so + * don't bother with a map entry either. + */ + if (image->pi_start == 0 && image->pi_end == 0) + return; + if ((pcmnew = malloc(sizeof(*pcmnew))) == NULL) err(EX_OSERR, "ERROR: Cannot create a map entry"); diff --git a/lib/libproc/libproc.h b/lib/libproc/libproc.h index 38a4faff94d5..a77bdbb35b59 100644 --- a/lib/libproc/libproc.h +++ b/lib/libproc/libproc.h @@ -105,8 +105,6 @@ typedef enum { REG_RVAL2 } proc_reg_t; -#define SIG2STR_MAX 8 - typedef struct lwpstatus { int pr_why; #define PR_REQUESTED 1 /* not implemented */ diff --git a/lib/libproc/proc_util.c b/lib/libproc/proc_util.c index bea50fb01098..a062b9a1f461 100644 --- a/lib/libproc/proc_util.c +++ b/lib/libproc/proc_util.c @@ -37,6 +37,7 @@ #include <err.h> #include <errno.h> #include <signal.h> +#include <stdio.h> #include <string.h> #include <unistd.h> @@ -180,8 +181,12 @@ proc_getwstat(struct proc_handle *phdl) char * proc_signame(int sig, char *name, size_t namesz) { + char buf[SIG2STR_MAX]; - strlcpy(name, strsignal(sig), namesz); + if (sig2str(sig, buf) == 0) + (void)snprintf(name, namesz, "SIG%s", buf); + else + (void)snprintf(name, namesz, "SIG#%d", sig); return (name); } diff --git a/lib/libprocstat/Makefile b/lib/libprocstat/Makefile index 229adc6015f7..e20518910ba3 100644 --- a/lib/libprocstat/Makefile +++ b/lib/libprocstat/Makefile @@ -52,18 +52,23 @@ MLINKS+=libprocstat.3 procstat_close.3 \ libprocstat.3 procstat_open_kvm.3 \ libprocstat.3 procstat_open_sysctl.3 -# XXX This is a hack. .if ${MK_CDDL} != "no" CFLAGS+= -DLIBPROCSTAT_ZFS SRCS+= zfs.c -OBJS+= zfs/zfs_defs.o -SUBDIR= zfs -zfs/zfs_defs.o: .PHONY - @cd ${.CURDIR}/zfs && ${MAKE} zfs_defs.o -zfs/zfs_defs.pico: .PHONY - @cd ${.CURDIR}/zfs && ${MAKE} zfs_defs.pico -zfs/zfs_defs.pieo: .PHONY - @cd ${.CURDIR}/zfs && ${MAKE} zfs_defs.pieo +ZFSTOP= ${SRCTOP}/sys/contrib/openzfs +CFLAGS.zfs.c+= -DIN_BASE +CFLAGS.zfs.c+= -DHAVE_ISSETUGID +CFLAGS.zfs.c+= -DZFS_DEBUG +CFLAGS.zfs.c+= -I${ZFSTOP}/include +CFLAGS.zfs.c+= -I${ZFSTOP}/lib/libspl/include +CFLAGS.zfs.c+= -I${ZFSTOP}/lib/libspl/include/os/freebsd +CFLAGS.zfs.c+= -I${ZFSTOP}/include/os/freebsd/zfs +CFLAGS.zfs.c+= -I${ZFSTOP}/module/icp/include +CFLAGS.zfs.c+= -I${SRCTOP}/sys +CFLAGS.zfs.c+= -I${SRCTOP}/sys/modules/zfs +CFLAGS.zfs.c+= -include ${ZFSTOP}/include/os/freebsd/spl/sys/ccompile.h +CFLAGS.zfs.c+= -include ${SRCTOP}/sys/modules/zfs/zfs_config.h +CFLAGS.zfs.c+= -Wno-cast-qual .endif .include <bsd.lib.mk> diff --git a/lib/libprocstat/cd9660.c b/lib/libprocstat/cd9660.c index de1140145527..ec37f49df0f6 100644 --- a/lib/libprocstat/cd9660.c +++ b/lib/libprocstat/cd9660.c @@ -52,9 +52,8 @@ #include <err.h> -#define _KERNEL +#define _WANT_ISO_MNT #include <isofs/cd9660/iso.h> -#undef _KERNEL #include <isofs/cd9660/cd9660_node.h> #include <kvm.h> diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c index 29f464ef6414..eb8137f6c76f 100644 --- a/lib/libprocstat/libprocstat.c +++ b/lib/libprocstat/libprocstat.c @@ -625,6 +625,10 @@ procstat_getfiles_kvm(struct procstat *procstat, struct kinfo_proc *kp, int mmap type = PS_FST_TYPE_EVENTFD; data = file.f_data; break; + case DTYPE_INOTIFY: + type = PS_FST_TYPE_INOTIFY; + data = file.f_data; + break; default: continue; } @@ -717,6 +721,7 @@ kinfo_type2fst(int kftype) { KF_TYPE_SOCKET, PS_FST_TYPE_SOCKET }, { KF_TYPE_VNODE, PS_FST_TYPE_VNODE }, { KF_TYPE_EVENTFD, PS_FST_TYPE_EVENTFD }, + { KF_TYPE_INOTIFY, PS_FST_TYPE_INOTIFY }, { KF_TYPE_UNKNOWN, PS_FST_TYPE_UNKNOWN } }; #define NKFTYPES (sizeof(kftypes2fst) / sizeof(*kftypes2fst)) diff --git a/lib/libprocstat/libprocstat.h b/lib/libprocstat/libprocstat.h index 0e9a4214414c..548747f90171 100644 --- a/lib/libprocstat/libprocstat.h +++ b/lib/libprocstat/libprocstat.h @@ -71,6 +71,7 @@ #define PS_FST_TYPE_PROCDESC 13 #define PS_FST_TYPE_DEV 14 #define PS_FST_TYPE_EVENTFD 15 +#define PS_FST_TYPE_INOTIFY 16 /* * Special descriptor numbers. diff --git a/lib/libprocstat/msdosfs.c b/lib/libprocstat/msdosfs.c index bb1ad65e6b1a..01345bb8d334 100644 --- a/lib/libprocstat/msdosfs.c +++ b/lib/libprocstat/msdosfs.c @@ -44,17 +44,15 @@ #include <sys/time.h> #include <sys/stat.h> #include <sys/vnode.h> +#include <sys/mount.h> #include <netinet/in.h> -#define _KERNEL -#include <sys/mount.h> +#define _WANT_MSDOSFS_INTERNALS #include <fs/msdosfs/bpb.h> #include <fs/msdosfs/msdosfsmount.h> -#undef _KERNEL - -#include <fs/msdosfs/denode.h> #include <fs/msdosfs/direntry.h> +#include <fs/msdosfs/denode.h> #include <fs/msdosfs/fat.h> #include <err.h> @@ -62,13 +60,6 @@ #include <stdio.h> #include <stdlib.h> -/* - * XXX - - * VTODE is defined in denode.h only if _KERNEL is defined, but that leads to - * header explosion - */ -#define VTODE(vp) ((struct denode *)getvnodedata(vp)) - #include "libprocstat.h" #include "common_kvm.h" diff --git a/lib/libprocstat/smbfs.c b/lib/libprocstat/smbfs.c index 136cceacb471..cbd32cf8f597 100644 --- a/lib/libprocstat/smbfs.c +++ b/lib/libprocstat/smbfs.c @@ -32,9 +32,8 @@ #include <sys/stat.h> #include <sys/time.h> #include <sys/vnode.h> -#define _KERNEL +#define _WANT_MOUNT #include <sys/mount.h> -#undef _KERNEL #include <netinet/in.h> diff --git a/lib/libprocstat/udf.c b/lib/libprocstat/udf.c index 9a110950f8b0..3298af6dec5f 100644 --- a/lib/libprocstat/udf.c +++ b/lib/libprocstat/udf.c @@ -32,9 +32,7 @@ #include <sys/stat.h> #include <sys/time.h> #include <sys/vnode.h> -#define _KERNEL #include <sys/mount.h> -#undef _KERNEL #include <netinet/in.h> diff --git a/lib/libprocstat/zfs.c b/lib/libprocstat/zfs.c index 665b1e5abe24..6dc23d7573fd 100644 --- a/lib/libprocstat/zfs.c +++ b/lib/libprocstat/zfs.c @@ -26,39 +26,36 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> /* __RENAME */ - -#include <stdbool.h> - #include <sys/param.h> -#define _KERNEL +#define _WANT_MOUNT #include <sys/mount.h> -#undef _KERNEL #include <sys/queue.h> #include <sys/stat.h> #include <sys/sysctl.h> #include <sys/time.h> #include <sys/vnode.h> +#define _WANT_ZNODE +#include <sys/zfs_context.h> +#include <sys/zfs_znode.h> #include <netinet/in.h> #include <err.h> #include <kvm.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #define ZFS #include "libprocstat.h" #include "common_kvm.h" -#include "zfs_defs.h" int zfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn) { struct mount mount, *mountptr; - void *znodeptr; - char *dataptr; + znode_t *kznodeptr, *znode; size_t len; int size; @@ -67,27 +64,30 @@ zfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn) warnx("error getting sysctl"); return (1); } - dataptr = malloc(size); - if (dataptr == NULL) { + znode = malloc(size); + if (znode == NULL) { warnx("error allocating memory for znode storage"); return (1); } - if ((size_t)size < offsetof_z_id + sizeof(uint64_t) || - (size_t)size < offsetof_z_mode + sizeof(mode_t) || - (size_t)size < offsetof_z_size + sizeof(uint64_t)) { + if ((size_t)size != sizeof(znode_t)) + warnx("znode_t size mismatch, data could be wrong"); + + if ((size_t)size < offsetof(znode_t, z_id) + sizeof(znode->z_id) || + (size_t)size < offsetof(znode_t, z_mode) + sizeof(znode->z_mode) || + (size_t)size < offsetof(znode_t, z_size) + sizeof(znode->z_size)) { warnx("znode_t size is too small"); goto bad; } - if ((size_t)size != sizeof_znode_t) - warnx("znode_t size mismatch, data could be wrong"); - - /* Since we have problems including vnode.h, we'll use the wrappers. */ - znodeptr = getvnodedata(vp); - if (!kvm_read_all(kd, (unsigned long)znodeptr, dataptr, - (size_t)size)) { - warnx("can't read znode at %p", (void *)znodeptr); + /* + * OpenZFS's libspl provides a dummy sys/vnode.h that shadows ours so + * struct vnode is an incomplete type. Use the wrapper until that is + * resolved. + */ + kznodeptr = getvnodedata(vp); + if (!kvm_read_all(kd, (unsigned long)kznodeptr, znode, (size_t)size)) { + warnx("can't read znode at %p", (void *)kznodeptr); goto bad; } @@ -103,12 +103,10 @@ zfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn) * under .zfs/. */ vn->vn_fsid = mount.mnt_stat.f_fsid.val[0]; - vn->vn_fileid = *(uint64_t *)(void *)(dataptr + offsetof_z_id); - vn->vn_mode = *(mode_t *)(void *)(dataptr + offsetof_z_mode); - vn->vn_size = *(uint64_t *)(void *)(dataptr + offsetof_z_size); - free(dataptr); + vn->vn_fileid = znode->z_id; + vn->vn_mode = znode->z_mode; + vn->vn_size = znode->z_size; return (0); bad: - free(dataptr); return (1); } diff --git a/lib/libprocstat/zfs/Makefile b/lib/libprocstat/zfs/Makefile deleted file mode 100644 index 5e1ebd44d1d3..000000000000 --- a/lib/libprocstat/zfs/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -.PATH: ${.CURDIR:H} - -SRCS= zfs_defs.c -OBJS= zfs_defs.o -WARNS?= 1 - -FORTIFY_SOURCE= 0 - -# We fake a kernel compilation environment in order to get the definition for -# 'zpool_t'. -CFLAGS+= -DIN_BASE -D__KERNEL__ -D_KERNEL -UKLD_TIED -DKLD_MODULE -CFLAGS+= -DHAVE_ISSETUGID -D_SYS_VMEM_H_ - -CFLAGS+= -fno-builtin -nostdlib - -CFLAGS+= -I${.CURDIR} -CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/include -CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/include/os/freebsd/spl -CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/include/os/freebsd/zfs -CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/include/os/freebsd -CFLAGS+= -I${SRCTOP}/sys/contrib/ck/include -CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/module/icp/include -CFLAGS+= -I${SRCTOP}/sys -I. -I.. - -CFLAGS+= -include ${SRCTOP}/sys/contrib/openzfs/include/os/freebsd/spl/sys/ccompile.h - -all: ${OBJS} -CLEANFILES= ${OBJS} - -.include <bsd.lib.mk> diff --git a/lib/libprocstat/zfs/Makefile.depend b/lib/libprocstat/zfs/Makefile.depend deleted file mode 100644 index 993ab0638f4a..000000000000 --- a/lib/libprocstat/zfs/Makefile.depend +++ /dev/null @@ -1,11 +0,0 @@ -# Autogenerated - do NOT edit! - -DIRDEPS = \ - include \ - - -.include <dirdeps.mk> - -.if ${DEP_RELDIR} == ${_DEP_RELDIR} -# local dependencies - needed for -jN in clean tree -.endif diff --git a/lib/libprocstat/zfs_defs.c b/lib/libprocstat/zfs_defs.c deleted file mode 100644 index 7f935c827118..000000000000 --- a/lib/libprocstat/zfs_defs.c +++ /dev/null @@ -1,81 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2020 Andriy Gapon <avg@FreeBSD.org> - * - * 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 REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/types.h> -/* - * Prevent some headers from getting included and fake some types - * in order to allow this file to compile without bringing in - * too many kernel build dependencies. - */ -#define _OPENSOLARIS_SYS_PATHNAME_H_ -#define _OPENSOLARIS_SYS_POLICY_H_ -#define _VNODE_PAGER_ - - -enum vtype { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO, VBAD, - VMARKER }; - -/* - * Vnode attributes. A field value of VNOVAL represents a field whose value - * is unavailable (getattr) or which is not to be changed (setattr). - */ -struct vattr { - enum vtype va_type; /* vnode type (for create) */ - u_short va_mode; /* files access mode and type */ - u_short va_padding0; - uid_t va_uid; /* owner user id */ - gid_t va_gid; /* owner group id */ - nlink_t va_nlink; /* number of references to file */ - dev_t va_fsid; /* filesystem id */ - ino_t va_fileid; /* file id */ - u_quad_t va_size; /* file size in bytes */ - long va_blocksize; /* blocksize preferred for i/o */ - struct timespec va_atime; /* time of last access */ - struct timespec va_mtime; /* time of last modification */ - struct timespec va_ctime; /* time file changed */ - struct timespec va_birthtime; /* time file created */ - u_long va_gen; /* generation number of file */ - u_long va_flags; /* flags defined for file */ - dev_t va_rdev; /* device the special file represents */ - u_quad_t va_bytes; /* bytes of disk space held by file */ - u_quad_t va_filerev; /* file modification number */ - u_int va_vaflags; /* operations flags, see below */ - long va_spare; /* remain quad aligned */ -}; - -#define _WANT_MOUNT -#include <sys/zfs_context.h> -#include <sys/zfs_znode.h> - -size_t sizeof_znode_t = sizeof(znode_t); -size_t offsetof_z_id = offsetof(znode_t, z_id); -size_t offsetof_z_size = offsetof(znode_t, z_size); -size_t offsetof_z_mode = offsetof(znode_t, z_mode); - -/* Keep pcpu.h satisfied. */ -uintptr_t *__start_set_pcpu; -uintptr_t *__stop_set_pcpu; diff --git a/lib/libprocstat/zfs_defs.h b/lib/libprocstat/zfs_defs.h deleted file mode 100644 index de17efba5630..000000000000 --- a/lib/libprocstat/zfs_defs.h +++ /dev/null @@ -1,36 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2020 Andriy Gapon <avg@FreeBSD.org> - * - * 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 REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. - */ - -#ifndef _LIBPROCSTAT_ZFS_DEFS_H -#define _LIBPROCSTAT_ZFS_DEFS_H - -extern size_t sizeof_znode_t; -extern size_t offsetof_z_id; -extern size_t offsetof_z_size; -extern size_t offsetof_z_mode; - -#endif /* _LIBPROCSTAT_ZFS_DEFS_H */ diff --git a/lib/libsecureboot/local.trust.mk b/lib/libsecureboot/local.trust.mk index b009139a2f68..f2da3d3ac452 100644 --- a/lib/libsecureboot/local.trust.mk +++ b/lib/libsecureboot/local.trust.mk @@ -84,7 +84,7 @@ VE_SIGNATURE_LIST?= RSA # you need to provide t*.pem or t*.asc files for each trust anchor # below assumes they are named ta_${ext}.pem eg ta_esig.pem for ECDSA .if empty(TRUST_ANCHORS) -TRUST_ANCHORS!= cd ${.CURDIR} && 'ls' -1 *.pem t*.asc 2> /dev/null +TRUST_ANCHORS!= cd ${.CURDIR} && 'ls' -1 *.pem t*.asc 2> /dev/null || echo .endif .if empty(TRUST_ANCHORS) && ${MK_LOADER_EFI_SECUREBOOT} != "yes" .error Need TRUST_ANCHORS see ${.PARSEDIR}/README.rst diff --git a/lib/libsys/Makefile.sys b/lib/libsys/Makefile.sys index 491c765e9416..3eb4bf85153d 100644 --- a/lib/libsys/Makefile.sys +++ b/lib/libsys/Makefile.sys @@ -224,6 +224,7 @@ MAN+= abort2.2 \ getsockopt.2 \ gettimeofday.2 \ getuid.2 \ + inotify.2 \ intro.2 \ ioctl.2 \ issetugid.2 \ @@ -448,6 +449,11 @@ MLINKS+=getrlimit.2 setrlimit.2 MLINKS+=getsockopt.2 setsockopt.2 MLINKS+=gettimeofday.2 settimeofday.2 MLINKS+=getuid.2 geteuid.2 +MLINKS+=inotify.2 inotify_init.2 \ + inotify.2 inotify_init1.2 \ + inotify.2 inotify_add_watch.2 \ + inotify.2 inotify_add_watch_at.2 \ + inotify.2 inotify_rm_watch.2 MLINKS+=intro.2 errno.2 MLINKS+=jail.2 jail_attach.2 \ jail.2 jail_get.2 \ diff --git a/lib/libsys/Symbol.sys.map b/lib/libsys/Symbol.sys.map index 225eca2fc0de..45e0160100af 100644 --- a/lib/libsys/Symbol.sys.map +++ b/lib/libsys/Symbol.sys.map @@ -378,8 +378,11 @@ FBSD_1.7 { }; FBSD_1.8 { + exterrctl; fchroot; getrlimitusage; + inotify_add_watch_at; + inotify_rm_watch; kcmp; setcred; }; diff --git a/lib/libsys/_libsys.h b/lib/libsys/_libsys.h index d06017edf6d9..1799906eb885 100644 --- a/lib/libsys/_libsys.h +++ b/lib/libsys/_libsys.h @@ -465,6 +465,9 @@ typedef int (__sys_kcmp_t)(pid_t, pid_t, int, uintptr_t, uintptr_t); typedef int (__sys_getrlimitusage_t)(u_int, int, rlim_t *); typedef int (__sys_fchroot_t)(int); typedef int (__sys_setcred_t)(u_int, const struct setcred *, size_t); +typedef int (__sys_exterrctl_t)(u_int, u_int, void *); +typedef int (__sys_inotify_add_watch_at_t)(int, int, const char *, uint32_t); +typedef int (__sys_inotify_rm_watch_t)(int, int); void __sys_exit(int rval); int __sys_fork(void); @@ -866,6 +869,9 @@ int __sys_kcmp(pid_t pid1, pid_t pid2, int type, uintptr_t idx1, uintptr_t idx2) int __sys_getrlimitusage(u_int which, int flags, rlim_t * res); int __sys_fchroot(int fd); int __sys_setcred(u_int flags, const struct setcred * wcred, size_t size); +int __sys_exterrctl(u_int op, u_int flags, void * ptr); +int __sys_inotify_add_watch_at(int fd, int dfd, const char * path, uint32_t mask); +int __sys_inotify_rm_watch(int fd, int wd); __END_DECLS #endif /* __LIBSYS_H_ */ diff --git a/lib/libsys/_umtx_op.2 b/lib/libsys/_umtx_op.2 index 974850fb8425..c590f8e8e0c8 100644 --- a/lib/libsys/_umtx_op.2 +++ b/lib/libsys/_umtx_op.2 @@ -210,6 +210,8 @@ Valid clock identifiers are a subset of those for .It .Dv CLOCK_SECOND .It +.Dv CLOCK_TAI +.It .Dv CLOCK_UPTIME .It .Dv CLOCK_UPTIME_FAST diff --git a/lib/libsys/accept.2 b/lib/libsys/accept.2 index 53926b3153d2..2da2af066a5b 100644 --- a/lib/libsys/accept.2 +++ b/lib/libsys/accept.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd October 9, 2014 +.Dd May 17, 2025 .Dt ACCEPT 2 .Os .Sh NAME @@ -85,6 +85,13 @@ and the close-on-exec flag on the new file descriptor can be set via the flag in the .Fa flags argument. +Similarly, the +.Dv O_CLOFORK +property can be set via the +.Dv SOCK_CLOFORK +flag in the +.Fa flags +argument. .Pp If no pending connections are present on the queue, and the original socket @@ -234,3 +241,8 @@ The .Fn accept4 system call appeared in .Fx 10.0 . +.Pp +The +.Dv SOCK_CLOFORK +flag appeared in +.Fx 15.0 . diff --git a/lib/libsys/aio_read.2 b/lib/libsys/aio_read.2 index 3a9601754c06..45779fff94c4 100644 --- a/lib/libsys/aio_read.2 +++ b/lib/libsys/aio_read.2 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd February 1, 2024 +.Dd March 27, 2025 .Dt AIO_READ 2 .Os .Sh NAME @@ -263,7 +263,9 @@ The .Fn aio_read2 and .Fn aio_readv -system calls are FreeBSD extensions, +system calls are +.Fx +extensions, and should not be used in portable code. .Sh HISTORY The diff --git a/lib/libsys/aio_waitcomplete.2 b/lib/libsys/aio_waitcomplete.2 index 1f20eca942ab..e7f993e0b796 100644 --- a/lib/libsys/aio_waitcomplete.2 +++ b/lib/libsys/aio_waitcomplete.2 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 21, 2016 +.Dd March 27, 2025 .Dt AIO_WAITCOMPLETE 2 .Os .Sh NAME @@ -91,8 +91,6 @@ The .Fn aio_waitcomplete system call fails if: .Bl -tag -width Er -.It Bq Er EINVAL -The specified time limit is invalid. .It Bq Er EAGAIN The process has not yet called .Fn aio_read @@ -101,6 +99,8 @@ or .It Bq Er EINTR A signal was delivered before the timeout expired and before any asynchronous I/O requests completed. +.It Bq Er EINVAL +The specified time limit is invalid. .It Bq Er EWOULDBLOCK .It Bq Er EINPROGRESS The specified time limit expired before any asynchronous I/O requests diff --git a/lib/libsys/aio_write.2 b/lib/libsys/aio_write.2 index f59406b8ab36..107e347ac335 100644 --- a/lib/libsys/aio_write.2 +++ b/lib/libsys/aio_write.2 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd February 1, 2024 +.Dd March 27, 2025 .Dt AIO_WRITE 2 .Os .Sh NAME @@ -265,7 +265,9 @@ The .Fn aio_write2 and .Fn aio_writev -system calls are FreeBSD extensions, +system calls are +.Fx +extensions, and should not be used in portable code. .Sh HISTORY The diff --git a/lib/libsys/amd64/Makefile.sys b/lib/libsys/amd64/Makefile.sys index 09947d998480..8134bdc422a6 100644 --- a/lib/libsys/amd64/Makefile.sys +++ b/lib/libsys/amd64/Makefile.sys @@ -3,6 +3,7 @@ SRCS+= \ amd64_get_gsbase.c \ amd64_set_fsbase.c \ amd64_set_gsbase.c \ + amd64_set_tlsbase.c \ rfork_thread.S MDASM= vfork.S cerror.S getcontext.S diff --git a/lib/libsys/amd64/Symbol.sys.map b/lib/libsys/amd64/Symbol.sys.map index 5f463c85f872..11e0507b6613 100644 --- a/lib/libsys/amd64/Symbol.sys.map +++ b/lib/libsys/amd64/Symbol.sys.map @@ -13,6 +13,10 @@ FBSD_1.6 { x86_pkru_unprotect_range; }; +FBSD_1.8 { + amd64_set_tlsbase; +}; + FBSDprivate_1.0 { _vfork; }; diff --git a/lib/libc/aarch64/static_tls.h b/lib/libsys/amd64/amd64_set_tlsbase.c index 2bb717eb75ce..a28441fbfc5d 100644 --- a/lib/libc/aarch64/static_tls.h +++ b/lib/libsys/amd64/amd64_set_tlsbase.c @@ -1,9 +1,10 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2019 The FreeBSD Foundation + * Copyright (c) 2025 The FreeBSD Foundation + * All rights reserved. * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> + * This software was developed by Konstantin Belousov * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without @@ -18,7 +19,7 @@ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 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) @@ -28,17 +29,23 @@ * SUCH DAMAGE. */ -#ifndef _LIBC_AARCH64_STATIC_TLS_H -#define _LIBC_AARCH64_STATIC_TLS_H +#define _WANT_P_OSREL +#include <sys/param.h> +#include <machine/cpufunc.h> +#include <machine/specialreg.h> +#include <machine/sysarch.h> +#include <x86/ifunc.h> +#include "libc_private.h" -static __inline uintptr_t -_libc_get_static_tls_base(size_t offset) +static int +amd64_set_tlsbase_syscall(void *addr) { - uintptr_t tlsbase; - - __asm __volatile("mrs %x0, tpidr_el0" : "=r" (tlsbase)); - tlsbase += offset; - return (tlsbase); + return (sysarch(AMD64_SET_TLSBASE, &addr)); } -#endif +DEFINE_UIFUNC(, int, amd64_set_tlsbase, (void *)) +{ + if (__getosreldate() >= P_OSREL_TLSBASE) + return (amd64_set_tlsbase_syscall); + return (amd64_set_fsbase); +} diff --git a/lib/libsys/auxv.3 b/lib/libsys/auxv.3 index 10ec10e8755c..b3b741937ac7 100644 --- a/lib/libsys/auxv.3 +++ b/lib/libsys/auxv.3 @@ -22,7 +22,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 September 16, 2022 +.Dd June 24, 2025 .Dt ELF_AUX_INFO 3 .Os .Sh NAME @@ -59,6 +59,12 @@ CPU / hardware feature flags .It AT_HWCAP2 CPU / hardware feature flags .Dv (sizeof(u_long)). +.It AT_HWCAP3 +CPU / hardware feature flags +.Dv (sizeof(u_long)). +.It AT_HWCAP4 +CPU / hardware feature flags +.Dv (sizeof(u_long)). .It AT_NCPUS Number of CPUs .Dv (sizeof(int)). diff --git a/lib/libsys/auxv.c b/lib/libsys/auxv.c index 1a4fd352950e..80702c66ba22 100644 --- a/lib/libsys/auxv.c +++ b/lib/libsys/auxv.c @@ -69,10 +69,10 @@ __init_elf_aux_vector(void) static int aux_once; static int pagesize, osreldate, canary_len, ncpus, pagesizes_len, bsdflags; -static int hwcap_present, hwcap2_present; +static int hwcap_present, hwcap2_present, hwcap3_present, hwcap4_present; static char *canary, *pagesizes, *execpath; static void *ps_strings, *timekeep; -static u_long hwcap, hwcap2; +static u_long hwcap, hwcap2, hwcap3, hwcap4; static void *fxrng_seed_version; static u_long usrstackbase, usrstacklim; @@ -123,6 +123,16 @@ init_aux(void) hwcap2 = (u_long)(aux->a_un.a_val); break; + case AT_HWCAP3: + hwcap3_present = 1; + hwcap3 = (u_long)(aux->a_un.a_val); + break; + + case AT_HWCAP4: + hwcap4_present = 1; + hwcap4 = (u_long)(aux->a_un.a_val); + break; + case AT_PAGESIZES: pagesizes = (char *)(aux->a_un.a_ptr); break; @@ -318,6 +328,20 @@ _elf_aux_info(int aux, void *buf, int buflen) } else res = ENOENT; break; + case AT_HWCAP3: + if (hwcap3_present && buflen == sizeof(u_long)) { + *(u_long *)buf = hwcap3; + res = 0; + } else + res = ENOENT; + break; + case AT_HWCAP4: + if (hwcap4_present && buflen == sizeof(u_long)) { + *(u_long *)buf = hwcap4; + res = 0; + } else + res = ENOENT; + break; case AT_PAGESIZES: if (pagesizes != NULL && pagesizes_len >= buflen) { memcpy(buf, pagesizes, buflen); diff --git a/lib/libsys/clock_gettime.2 b/lib/libsys/clock_gettime.2 index fcdc5be498f2..89551d0f720b 100644 --- a/lib/libsys/clock_gettime.2 +++ b/lib/libsys/clock_gettime.2 @@ -27,7 +27,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd June 28, 2024 +.Dd August 10, 2024 .Dt CLOCK_GETTIME 2 .Os .Sh NAME @@ -99,11 +99,24 @@ query, using an in-kernel cached value of the current second. Returns the execution time of the calling process. .It Dv CLOCK_THREAD_CPUTIME_ID Returns the execution time of the calling thread. +.It Dv CLOCK_TAI +Increments in SI seconds like a wall clock. +It uses a 1970 epoch and implements the TAI timescale. +Similar to +.Dv CLOCK_REALTIME , +but without leap seconds. +It will increase monotonically during a leap second. +Will return +.Er EINVAL +if the current offset between TAI and UTC is not known, +which may be the case early in boot before NTP or other time daemon has +synchronized. .El .Pp The clock IDs .Dv CLOCK_BOOTTIME , .Dv CLOCK_REALTIME , +.Dv CLOCK_TAI , .Dv CLOCK_MONOTONIC , and .Dv CLOCK_UPTIME @@ -202,7 +215,8 @@ The clock IDs .Dv CLOCK_MONOTONIC_PRECISE , .Dv CLOCK_REALTIME_FAST , .Dv CLOCK_REALTIME_PRECISE , -.Dv CLOCK_SECOND +.Dv CLOCK_SECOND , +.Dv CLOCK_TAI , .Dv CLOCK_UPTIME , .Dv CLOCK_UPTIME_FAST , and diff --git a/lib/libsys/closefrom.2 b/lib/libsys/closefrom.2 index aaa4c55607ac..1885a6fdeaa8 100644 --- a/lib/libsys/closefrom.2 +++ b/lib/libsys/closefrom.2 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 3, 2022 +.Dd May 17, 2025 .Dt CLOSEFROM 2 .Os .Sh NAME @@ -59,6 +59,8 @@ Supported .Bl -tag -width ".Dv CLOSE_RANGE_CLOEXEC" .It Dv CLOSE_RANGE_CLOEXEC Set the close-on-exec flag on descriptors in the range instead of closing them. +.It Dv CLOSE_RANGE_CLOFORK +Set the close-on-fork flag on descriptors in the range instead of closing them. .El .Sh RETURN VALUES Upon successful completion, @@ -90,3 +92,8 @@ The .Fn closefrom function first appeared in .Fx 8.0 . +.Pp +The +.Dv CLOSE_RANGE_CLOFORK +flag appeared in +.Fx 15.0 . diff --git a/lib/libsys/execve.2 b/lib/libsys/execve.2 index 5a35980e9555..dc85b9321e48 100644 --- a/lib/libsys/execve.2 +++ b/lib/libsys/execve.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd January 26, 2022 +.Dd July 02, 2025 .Dt EXECVE 2 .Os .Sh NAME @@ -127,7 +127,10 @@ flag is set (see and .Xr fcntl 2 ) . Descriptors that remain open are unaffected by -.Fn execve . +.Fn execve , +except those with the close-on-fork flag +.Dv FD_CLOFORK +which is cleared from all file descriptors. If any of the standard descriptors (0, 1, and/or 2) are closed at the time .Fn execve diff --git a/lib/libsys/fcntl.2 b/lib/libsys/fcntl.2 index b5d4abe35aeb..d67c38cfbc6c 100644 --- a/lib/libsys/fcntl.2 +++ b/lib/libsys/fcntl.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd December 7, 2021 +.Dd June 24, 2025 .Dt FCNTL 2 .Os .Sh NAME @@ -80,6 +80,18 @@ associated with the new file descriptor is cleared, so the file descriptor is to remain open across .Xr execve 2 system calls. +.It +The fork-on-exec flag +.Dv FD_CLOFORK +associated with the new file descriptor is cleared, so the file descriptor is +to remain open across +.Xr fork 2 +system calls. +.It +The +.Dv FD_RESOLVE_BENEATH +flag, described below, will be set if it was set on the original +descriptor. .El .It Dv F_DUPFD_CLOEXEC Like @@ -90,6 +102,15 @@ flag associated with the new file descriptor is set, so the file descriptor is closed when .Xr execve 2 system call executes. +.It Dv F_DUPFD_CLOFORK +Like +.Dv F_DUPFD , +but the +.Dv FD_CLOFORK +flag associated with the new file descriptor is set, so the file descriptor +is closed when +.Xr fork 2 +system call executes. .It Dv F_DUP2FD It is functionally equivalent to .Bd -literal -offset indent @@ -112,30 +133,58 @@ Use .Fn dup2 instead of .Dv F_DUP2FD . +.It Dv F_DUP3FD +Used to implement the +.Fn dup3 +call. +Do not use it. .It Dv F_GETFD -Get the close-on-exec flag associated with the file descriptor -.Fa fd -as -.Dv FD_CLOEXEC . -If the returned value ANDed with -.Dv FD_CLOEXEC -is 0, -the file will remain open across -.Fn exec , -otherwise the file will be closed upon execution of +Get the flags associated with the file descriptor +.Fa fd . +The following flags are defined: +.Bl -tag -width FD_RESOLVE_BENEATH +.It Dv FD_CLOEXEC +The file will be closed upon execution of .Fn exec .Fa ( arg is ignored). +Otherwise, the file descriptor will remain open. +.It Dv FD_CLOFORK +The file will be closed upon execution of the +.Fn fork +family of system calls. +.It Dv FD_RESOLVE_BENEATH +All path name lookups relative to that file descriptor +will behave as if the lookup had +.Dv O_RESOLVE_BENEATH +or +.Dv AT_RESOLVE_BENEATH +semantics. +It is not permitted to call +.Xr fchdir 2 +or +.Xr fchroot 2 +on such a file descriptor. +The +.Dv FD_RESOLVE_BENEATH +flag is sticky, meaning that it is preserved by +.Xr dup 2 +and similar operations, and opening a directory with +.Xr openat 2 +where the directory descriptor has the flag set causes the new directory +descriptor to also have the flag set. +.El .It Dv F_SETFD -Set the close-on-exec flag associated with -.Fa fd -to -.Fa arg , -where -.Fa arg -is either 0 or +Set flags associated with +.Fa fd . +The available flags are .Dv FD_CLOEXEC , -as described above. +.Dv FD_CLOFORK +and +.Dv FD_RESOLVE_BENEATH . +The +.Dv FD_RESOLVE_BENEATH +flag cannot be cleared once set. .It Dv F_GETFL Get descriptor status flags, as described below .Fa ( arg @@ -528,7 +577,7 @@ A new file descriptor. A file descriptor equal to .Fa arg . .It Dv F_GETFD -Value of flag (only the low-order bit is defined). +Value of flags. .It Dv F_GETFL Value of flags. .It Dv F_GETOWN @@ -762,8 +811,10 @@ for the reasons as stated in .Sh STANDARDS The .Dv F_DUP2FD -constant is non portable. -It is provided for compatibility with AIX and Solaris. +and +.Dv F_DUP3FD +constants are not portable. +They are provided for compatibility with AIX and Solaris. .Pp Per .St -susv4 , @@ -788,3 +839,10 @@ The .Dv F_DUP2FD constant first appeared in .Fx 7.1 . +.Pp +The +.Dv F_DUPFD_CLOFORK +and +.Dv F_DUP3FD +flags appeared in +.Fx 15.0 . diff --git a/lib/libsys/fhopen.2 b/lib/libsys/fhopen.2 index 5bd1e9f8d90b..aba53f1dd907 100644 --- a/lib/libsys/fhopen.2 +++ b/lib/libsys/fhopen.2 @@ -31,7 +31,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd June 29, 1999 +.Dd April 6, 2025 .Dt FHOPEN 2 .Os .Sh NAME @@ -75,6 +75,10 @@ together the flags used for the system call. All said flags are valid except for .Dv O_CREAT . +If the file handle refers to a named attribute or named attribute +directory, the +.Dv O_NAMEDATTR +flag must be specified. .Pp The .Fn fhstat @@ -116,6 +120,16 @@ Calling with .Dv O_CREAT set. +.It Bq Er ENOATTR +The file handle does not refer to a named attribute or named attribute +directory although the +.Dv O_NAMEDATTR +flag was specified. +.It Bq Er ENOATTR +The file handle refers to a named attribute or named attribute directory +although the +.Dv O_NAMEDATTR +flag was not specified. .It Bq Er ESTALE The file handle .Fa fhp @@ -125,7 +139,8 @@ is no longer valid. .Xr fstat 2 , .Xr fstatfs 2 , .Xr getfh 2 , -.Xr open 2 +.Xr open 2 , +.Xr named_attribute 9 .Sh HISTORY The .Fn fhopen , diff --git a/lib/libsys/fork.2 b/lib/libsys/fork.2 index 7d548a42890d..e59b208a9ff5 100644 --- a/lib/libsys/fork.2 +++ b/lib/libsys/fork.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 5, 2021 +.Dd May 17, 2024 .Dt FORK 2 .Os .Sh NAME @@ -68,6 +68,16 @@ by the parent. This descriptor copying is also used by the shell to establish standard input and output for newly created processes as well as to set up pipes. +Any file descriptors that were marked with the close-on-fork flag, +.Dv FD_CLOFORK +.Po see +.Fn fcntl 2 +and +.Dv O_CLOFORK +in +.Fn open 2 +.Pc , +will not be present in the child process, but remain open in the parent. .It The child process' resource utilizations are set to 0; see diff --git a/lib/libsys/getdirentries.2 b/lib/libsys/getdirentries.2 index 0e5840ce25cd..202ae133f548 100644 --- a/lib/libsys/getdirentries.2 +++ b/lib/libsys/getdirentries.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd September 5, 2023 +.Dd July 8, 2025 .Dt GETDIRENTRIES 2 .Os .Sh NAME @@ -178,9 +178,7 @@ or non-NULL .Fa basep point outside the allocated address space. .It Bq Er EINVAL -The file referenced by -.Fa fd -is not a directory, or +The value of .Fa nbytes is too small for returning a directory entry or block of entries, or the current position pointer is invalid. @@ -192,6 +190,10 @@ error occurred while reading from or writing to the file system. Corrupted data was detected while reading from the file system. .It Bq Er ENOENT Directory unlinked but still open. +.It Bq Er ENOTDIR +The file referenced by +.Fa fd +is not a directory. .El .Sh SEE ALSO .Xr lseek 2 , diff --git a/lib/libsys/getsockopt.2 b/lib/libsys/getsockopt.2 index 619540b53fae..8839b61597a2 100644 --- a/lib/libsys/getsockopt.2 +++ b/lib/libsys/getsockopt.2 @@ -679,7 +679,7 @@ The option originated in .Ox 4.9 and first appeared in -.Fx 15.0 . +.Fx 14.3 . The .Fx implementation aims to be source-compatible. diff --git a/lib/libsys/inotify.2 b/lib/libsys/inotify.2 new file mode 100644 index 000000000000..f94509d6f59e --- /dev/null +++ b/lib/libsys/inotify.2 @@ -0,0 +1,379 @@ +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.\" Copyright (c) 2025 Klara, Inc. +.\" +.Dd May 19, 2025 +.Dt INOTIFY 2 +.Os +.Sh NAME +.Nm inotify_init , +.Nm inotify_init1 , +.Nm inotify_add_watch , +.Nm inotify_add_watch_at , +.Nm inotify_rm_watch +.Nd monitor file system events +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In sys/inotify.h +.Ft int +.Fo inotify_init +.Fc +.Ft int +.Fo inotify_init1 +.Fa "int flags" +.Fc +.Ft int +.Fo inotify_add_watch +.Fa "int fd" +.Fa "const char *pathname" +.Fa "uint32_t mask" +.Fc +.Ft int +.Fo inotify_add_watch_at +.Fa "int fd" +.Fa "int dfd" +.Fa "const char *pathname" +.Fa "uint32_t mask" +.Fc +.Ft int +.Fo inotify_rm_watch +.Fa "int fd" +.Fa "uint32_t wd" +.Fc +.Bd -literal +struct inotify_event { + int wd; /* Watch descriptor */ + uint32_t mask; /* Event and flags */ + uint32_t cookie; /* Unique ID which links rename events */ + uint32_t len; /* Name field size, including nul bytes */ + char name[0]; /* Filename (nul-terminated) */ +}; +.Ed +.Sh DESCRIPTION +The inotify system calls provide an interface to monitor file system events. +They aim to be compatible with the Linux inotify interface. +The provided functionality is similar to the +.Dv EVFILT_VNODE +filter of the +.Xr kevent 2 +system call, but further allows monitoring of a directory without needing to +open each object in that directory. +This avoids races and reduces the number of file descriptors needed to monitor +a large file hierarchy. +.Pp +inotify allows one or more file system objects, generally files or directories, +to be watched for events, such as file open or close. +Watched objects are associated with a file descriptor returned +by +.Fn inotify_init +or +.Fn inotify_init1 . +When an event occurs, a record describing the event becomes available for +reading from the inotify file descriptor. +Each inotify descriptor thus refers to a queue of events waiting to be read. +inotify descriptors are inherited across +.Xr fork 2 +calls and may be passed to other processes via +.Xr unix 4 +sockets. +.Pp +The +.Fn inotify_init1 +system call accepts two flags. +The +.Dv IN_NONBLOCK +flag causes the inotify descriptor to be opened in non-blocking mode, such that +.Xr read 2 +calls will not block if no records are available to consume, and will instead +return +.Er EWOULDBLOCK . +The +.Dv IN_CLOEXEC +flag causes the inotify descriptor to be closed automatically when +.Xr execve 2 +is called. +.Pp +To watch a file or directory, the +.Fn inotify_add_watch +or +.Fn inotify_add_watch_at +system calls must be used. +They take a path and a mask of events to watch for, and return a +.Dq watch descriptor , +a non-negative integer which uniquely identifies the watched object within the +inotify descriptor. +.Pp +The +.Fn inotify_rm_watch +system call removes a watch from an inotify descriptor. +.Pp +When watching a directory, objects within the directory are monitored for events +as well as the directory itself. +A record describing an inotify event consists of a +.Dq struct inotify_event +followed by the name of the object in the directory being watched. +If the watched object itself generates an event, no name is present. +Extra nul bytes may follow the file name in order to provide alignment for a +subsequent record. +.Pp +The following events are defined: +.Bl -tag -width IN_CLOSE_NOWRITE +.It Dv IN_ACCESS +A file's contents were accessed, e.g., by +.Xr read 2 +.Xr copy_file_range 2 , +.Xr sendfile 2 , +or +.Xr getdirentries 2 . +.It Dv IN_ATTRIB +A file's metadata was changed, e.g., by +.Xr chmod 2 +or +.Xr unlink 2 . +.It Dv IN_CLOSE_WRITE +A file that was previously opened for writing was closed. +.It Dv IN_CLOSE_NOWRITE +A file that was previously opened read-only was closed. +.It Dv IN_CREATE +A file within a watched directory was created, e.g., by +.Xr open 2 , +.Xr mkdir 2 , +.Xr symlink 2 , +.Xr mknod 2 , +or +.Xr bind 2 . +.It Dv IN_DELETE +A file or directory within a watched directory was removed. +.It Dv IN_DELETE_SELF +The watched file or directory itself was deleted. +This event is generated only when the link count of the file drops +to zero. +.It Dv IN_MODIFY +A file's contents were modified, e.g., by +.Xr write 2 +or +.Xr copy_file_range 2 . +.It Dv IN_MOVE_SELF +The watched file or directory itself was renamed. +.It Dv IN_MOVED_FROM +A file or directory was moved from a watched directory. +.It Dv IN_MOVED_TO +A file or directory was moved into a watched directory. +A +.Xr rename 2 +call thus may generate two events, one for the old name and one for the new +name. +These are linked together by the +.Ar cookie +field in the inotify record, which can be compared to link the two records +to the same event. +.It Dv IN_OPEN +A file was opened. +.El +.Pp +Some additional flags may be set in inotify event records: +.Bl -tag -width IN_Q_OVERFLOW +.It Dv IN_IGNORED +When a watch is removed from a file, for example because it was created with the +.Dv IN_ONESHOT +flag, the file was deleted, or the watch was explicitly removed with +.Xr inotify_rm_watch 2 , +an event with this mask is generated to indicate that the watch will not +generate any more events. +Once this event is generated, the watch is automatically removed, and in +particular should not be removed manually with +.Xr inotify_rm_watch 2 . +.It Dv IN_ISDIR +When the subject of an event is a directory, this flag is set in the +.Ar mask +.It Dv IN_Q_OVERFLOW +One or more events were dropped, for example because of a kernel memory allocation +failure or because the event queue size hit a limit. +.It Dv IN_UNMOUNT +The filesystem containing the watched object was unmounted. +.El +.Pp +A number of flags may also be specified in the +.Ar mask +given to +.Fn inotify_add_watch +and +.Fn inotify_add_watch_at : +.Bl -tag -width IN_DONT_FOLLOW +.It Dv IN_DONT_FOLLOW +If +.Ar pathname +is a symbolic link, do not follow it. +.It Dv IN_EXCL_UNLINK +This currently has no effect, see the +.Sx BUGS +section. +.In Dv IN_MASK_ADD +When adding a watch to an object, and that object is already watched by the +same inotify descriptor, by default the mask of the existing watch is +overwritten. +When +.Dv IN_MASK_ADD +is specified, the mask of the existing watch is instead logically ORed with +the new mask. +.In Dv IN_MASK_CREATE +When +.Fn inotify_add watch +is used to add a watch to an object, +.Dv IN_MASK_CREATE +is specified, and that object is already watched by the same inotify descriptor, +return an error instead of updating the existing watch. +.In Dv IN_ONESHOT +Monitor the object for a single event, after which the watch is automatically +removed. +As part of removal, a +.Dv IN_IGNORED +event is generated. +.In Dv IN_ONLYDIR +When creating a watch, fail with +.Er ENOTDIR +if the path does not refer to a directory. +.El +.Sh SYSCTL VARIABLES +The following variables are available as both +.Xr sysctl 8 +variables and +.Xr loader 8 +tunables: +.Bl -tag -width 15 +.It Va vfs.inotify.max_events +The maximum number of inotify records that can be queued for a single +inotify descriptor. +Records in excess of this limit are discarded, and a single event with +mask equal to +.Dv IN_Q_OVERFLOW +will be present in the queue. +.It Va vfs.inotify.max_user_instances +The maximum number of inotify descriptors that can be created by a single +user. +.It Va vfs.inotify.max_user_watches +The maximum number of inotify watches per user. +.El +.Sh EXAMPLES +See the example program in +.Pa /usr/share/examples/inotify/inotify.c . +.Sh ERRORS +The +.Fn inotify_init +and +.Fn inotify_init1 +functions will fail if: +.Bl -tag -width Er +.It Bq Er ENFILE +The system limit on the total number of open files has been reached. +.It Bq Er EMFILE +A per-process limit on the number of open files has been reached. +.It Bq Er EMFILE +The system limit on the number of inotify descriptors has been reached. +.It Bq Er EINVAL +An unrecognized flag was passed to +.Fn inotify_init1 . +.El +.Pp +The +.Fn inotify_add_watch +and +.Fn inotify_add_watch_at +system calls will fail if: +.Bl -tag -width Er +.It Bq Er EBADF +The +.Ar fd +parameter is not a valid file descriptor. +.It Bq Er EINVAL +The +.Ar fd +parameter is not an inotify descriptor. +.It Bq Er EINVAL +The +.Ar mask +parameter does not specify an event, or +the +.Dv IN_MASK_CREATE +and +.Dv IN_MASK_ADD +flags are both set, or an unrecognized flag was passed. +.It Bq Er ENOTDIR +The +.Ar pathname +parameter refers to a file that is not a directory, and the +.Dv IN_ONLYDIR +flag was specified. +.It Bq Er ENOSPC +The per-user limit on the total number of inotify watches has been reached. +.It Bq Er ECAPMODE +The process is in capability mode and +.Fn inotify_add_watch +was called, or +.Fn inotify_add_watch_at +was called with +.Dv AT_FDCWD +as the directory file descriptor +.Ar dfd . +.It Bq Er ENOTCAPABLE +The process is in capability mode and +.Ar pathname +contains a +.Dq .. +component leading to a directory outside the directory hierarchy specified +by +.Ar dfd . +.El +.Pp +The +.Fn inotify_rm_watch +system call will fail if: +.Bl -tag -width Er +.It Bq Er EBADF +The +.Ar fd +parameter is not a valid file descriptor. +.It Bq Er EINVAL +The +.Ar fd +parameter is not an inotify descriptor. +.It Bq Er EINVAL +The +.Ar wd +parameter is not a valid watch descriptor. +.El +.Sh SEE ALSO +.Xr kevent 2 , +.Xr capsicum 4 +.Sh STANDARDS +The +.Nm +interface originates from Linux and is non-standard. +This implementation aims to be compatible with that of Linux and is based +on the documentation available at +.Pa https://man7.org/linux/man-pages/man7/inotify.7.html . +.Sh HISTORY +The inotify system calls first appeared in +.Fx 15.0 . +.Sh BUGS +If a file in a watched directory has multiple hard links, +an access via any hard link for that file will generate an event, even +if the accessed link belongs to an unwatched directory. +This is not the case for the Linux implementation, where only accesses +via the hard link in the watched directory will generate an event. +.Pp +If a watched directory contains multiple hard links of a file, an event +on one of the hard links will generate an inotify record for each link +in the directory. +.Pp +When a file is unlinked, no more events will be generated for that file, +even if it continues to be accessed. +By default, the Linux implementation will continue to generate events in +this case. +Thus, the +.Fx +implementation behaves as though +.Dv IN_EXCL_UNLINK +is always set. diff --git a/lib/libsys/nanosleep.2 b/lib/libsys/nanosleep.2 index 8a4931e51413..290565dbd6e1 100644 --- a/lib/libsys/nanosleep.2 +++ b/lib/libsys/nanosleep.2 @@ -27,7 +27,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 3, 2022 +.Dd May 3, 2025 .Dt NANOSLEEP 2 .Os .Sh NAME @@ -87,14 +87,6 @@ If, at the time of the call, the time value specified by is less than or equal to the time value of the specified clock, then .Fn clock_nanosleep returns immediately and the calling thread is not suspended. -.Pp -The suspension time may be longer than requested due to the -scheduling of other activity by the system. -It is also subject to the allowed time interval deviation -specified by the -.Va kern.timecounter.alloweddeviation -.Xr sysctl 8 -variable. An unmasked signal will terminate the sleep early, regardless of the .Dv SA_RESTART value on the interrupting signal. @@ -124,6 +116,8 @@ CLOCK_REALTIME_PRECISE .It CLOCK_SECOND .It +CLOCK_TAI +.It CLOCK_UPTIME .It CLOCK_UPTIME_FAST @@ -131,6 +125,32 @@ CLOCK_UPTIME_FAST CLOCK_UPTIME_PRECISE .El .Pp +The suspension time may be longer than requested due to the +scheduling of other activity by the system. +The clocks with the +.Dv _FAST +suffix and the +.Dv CLOCK_SECOND +are subject to the allowed time interval deviation specified by the +.Va kern.timecounter.alloweddeviation +.Xr sysctl 8 +variable. +The clocks with the +.Dv _PRECISE +suffix are always as precise as possible. +The +.Dv CLOCK_MONOTONIC , +.Dv CLOCK_REALTIME +and +.Dv CLOCK_UPTIME +are precise by default. +Setting the +.Va kern.timecounter.nanosleep_precise +.Xr sysctl 8 +to a false value would make those clocks to behave like the +.Dv _FAST +clocks. +.Pp The .Fn nanosleep function behaves like @@ -217,3 +237,19 @@ and was ported to .Ox 2.1 and .Fx 3.0 . +The +.Fn clock_nanosleep +system call has been available since +.Fx 11.1 . +.Pp +In +.Fx 15.0 +the default behavior of +.Fn clock_nanosleep +with +.Dv CLOCK_MONOTONIC , +.Dv CLOCK_REALTIME , +.Dv CLOCK_UPTIME +clocks and +.Fn nanosleep +has been switched to use precise clock. diff --git a/lib/libsys/open.2 b/lib/libsys/open.2 index d8540637b690..a0e905a8f375 100644 --- a/lib/libsys/open.2 +++ b/lib/libsys/open.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd February 28, 2025 +.Dd May 17, 2025 .Dt OPEN 2 .Os .Sh NAME @@ -195,6 +195,9 @@ error if file is not a directory .It Dv O_CLOEXEC automatically close file on .Xr execve 2 +.It Dv O_CLOFORK +automatically close file on any child process created with +.Fn fork 2 .It Dv O_VERIFY verify the contents of the file with .Xr mac_veriexec 4 @@ -210,6 +213,8 @@ record only the target path in the opened descriptor open file referenced by .Fa fd if path is empty +.It Dv O_NAMEDATTR +open a named attribute or named attribute directory .El .Pp Exactly one of the flags @@ -358,6 +363,27 @@ may be used to set .Dv FD_CLOEXEC flag for the newly returned file descriptor. .Pp +.Dv O_CLOFORK +may be used to set +.Dv FD_CLOFORK +flag for the newly returned file descriptor. +The file will be closed on any child process created with +.Fn fork 2 , +.Fn vfork 2 +or +.Fn rfork 2 +with the +.Dv RFFDG +flag, remaining open in the parent. +Both the +.Dv O_CLOEXEC +and +.Dv O_CLOFORK +flags can be modified with the +.Dv F_SETFD +.Fn fcntl 2 +command. +.Pp .Dv O_VERIFY may be used to indicate to the kernel that the contents of the file should be verified before allowing the open to proceed. @@ -464,6 +490,13 @@ flag for .Xr fstatat 2 and related syscalls. .Pp +Conversely, a file descriptor +.Dv fd +referencing a filesystem file can be converted to the +.Dv O_PATH +type of descriptor by using the following call +.Dl opath_fd = openat(fd, \[dq]\[dq], O_EMPTY_PATH | O_PATH); +.Pp If successful, .Fn open returns a non-negative integer, termed a file descriptor. @@ -499,6 +532,42 @@ and the description of the .Dv O_CLOEXEC flag. .Pp +When the +.Dv O_NAMEDATTR +flag is specified for an +.Fn openat +where the +.Fa fd +argument is for a file object, +a named attribute for the file object +is opened and not the file object itself. +If the +.Dv O_CREAT +flag has been specified as well, the named attribute will be +created if it does not exist. +When the +.Dv O_NAMEDATTR +flag is specified for a +.Fn open , +a named attribute for the current working directory is opened and +not the current working directory. +The +.Fa path +argument for this +.Fn openat +or +.Fn open +must be a single component name with no embedded +.Ql / . +If the +.Fa path +argument is +.Ql .\& +then the named attribute directory for the file object is opened. +(See +.Xr named_attribute 7 +for more information.) +.Pp The system imposes a limit on the number of file descriptors open simultaneously by one process. The @@ -730,6 +799,10 @@ contains a ".." component, the .Dv vfs.lookup_cap_dotdot .Xr sysctl 3 is set, and the process is in capability mode. +.It Bq Er ENOATTR +.Dv O_NAMEDATTR +has been specified and the file object is not a named attribute +directory or named attribute. .El .Sh SEE ALSO .Xr chmod 2 , @@ -745,7 +818,8 @@ is set, and the process is in capability mode. .Xr umask 2 , .Xr write 2 , .Xr fopen 3 , -.Xr capsicum 4 +.Xr capsicum 4 , +.Xr named_attribute 7 .Sh STANDARDS These functions are specified by .St -p1003.1-2008 . @@ -794,6 +868,11 @@ function was introduced in .Fx 8.0 . .Dv O_DSYNC appeared in 13.0. +.Dv O_NAMEDATTR +appeared in 15.0. +.Dv O_CLOFORK +appeared in +.Fx 15.0 . .Sh BUGS The .Fa mode diff --git a/lib/libsys/pathconf.2 b/lib/libsys/pathconf.2 index 786753f2d02a..79ac8310000d 100644 --- a/lib/libsys/pathconf.2 +++ b/lib/libsys/pathconf.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 6, 2021 +.Dd July 5, 2025 .Dt PATHCONF 2 .Os .Sh NAME @@ -175,6 +175,18 @@ hole size but still reports holes. Return 1 if a file system supports hole-punching (see .Xr fspacectl 2 ) , otherwise 0. +.It Li _PC_NAMEDATTR_ENABLED +Return 1 if named attributes are enabled for the file system, otherwise 0. +.It Li _PC_HAS_NAMEDATTR +Return 1 if one or more named attributes exist for the file, otherwise 0. +.It Li _PC_HAS_HIDDENSYSTEM +Return 1 if both +.Dv UF_HIDDEN +and +.Dv UF_SYSTEM +flags can be set by +.Xr chflags 2 , +otherwise 0. .El .Sh RETURN VALUES If the call to @@ -251,6 +263,7 @@ An I/O error occurred while reading from or writing to the file system. Corrupted data was detected while reading from the file system. .El .Sh SEE ALSO +.Xr chflags 2 , .Xr lseek 2 , .Xr sysctl 3 .Sh HISTORY diff --git a/lib/libsys/pipe.2 b/lib/libsys/pipe.2 index 9531c9717395..37d6eba420de 100644 --- a/lib/libsys/pipe.2 +++ b/lib/libsys/pipe.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd December 1, 2017 +.Dd May 17, 2025 .Dt PIPE 2 .Os .Sh NAME @@ -64,6 +64,8 @@ list, defined in .Bl -tag -width ".Dv O_NONBLOCK" .It Dv O_CLOEXEC Set the close-on-exec flag for the new file descriptors. +.It Dv O_CLOFORK +Set the close-on-fork flag for the new file descriptors. .It Dv O_NONBLOCK Set the non-blocking flag for the ends of the pipe. .El @@ -173,3 +175,8 @@ function became a wrapper around .Fn pipe2 in .Fx 11.0 . +.Pp +The +.Dv O_CLOFORK +flag appeared in +.Fx 15.0 . diff --git a/lib/libsys/procctl.2 b/lib/libsys/procctl.2 index 75804ba243f1..dfb7931de265 100644 --- a/lib/libsys/procctl.2 +++ b/lib/libsys/procctl.2 @@ -27,7 +27,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd December 14, 2024 +.Dd April 21, 2025 .Dt PROCCTL 2 .Os .Sh NAME @@ -133,17 +133,17 @@ dump. The .Va arg parameter must point to an integer variable holding one of the following values: -.Bl -tag -width PROC_LOGSIGEXIT_FORCE_DISABLE -.It Dv PROC_LOGSIGEXIT_FORCE_ENABLE +.Bl -tag -width PROC_LOGSIGEXIT_CTL_FORCE_DISABLE +.It Dv PROC_LOGSIGEXIT_CTL_FORCE_ENABLE Enables logging of exits due to signals that would normally cause a core dump. Logging is done via .Xr log 9 with a log level of .Dv LOG_INFO . -.It Dv PROC_LOGSIGEXIT_FORCE_DISABLE +.It Dv PROC_LOGSIGEXIT_CTL_FORCE_DISABLE Disables the logging of exits due to signals that would normally cause a core dump. -.It Dv PROC_LOGSIGEXIT_NOFORCE +.It Dv PROC_LOGSIGEXIT_CTL_NOFORCE The logging behavior is delegated to the .Xr sysctl 3 MIB variable @@ -155,10 +155,10 @@ The .Va arg parameter must point to an integer variable, where one of the following values is written: -.Bl -tag -width PROC_LOGSIGEXIT_FORCE_DISABLE -.It Dv PROC_LOGSIGEXIT_FORCE_ENABLE -.It Dv PROC_LOGSIGEXIT_FORCE_DISABLE -.It Dv PROC_LOGSIGEXIT_NOFORCE +.Bl -tag -width PROC_LOGSIGEXIT_CTL_FORCE_DISABLE +.It Dv PROC_LOGSIGEXIT_CTL_FORCE_ENABLE +.It Dv PROC_LOGSIGEXIT_CTL_FORCE_DISABLE +.It Dv PROC_LOGSIGEXIT_CTL_NOFORCE .El .It Dv PROC_PROTMAX_CTL Controls the maximum protection used for diff --git a/lib/libsys/ptrace.2 b/lib/libsys/ptrace.2 index 9b789a0e45b3..7aa24a3f820b 100644 --- a/lib/libsys/ptrace.2 +++ b/lib/libsys/ptrace.2 @@ -1,7 +1,7 @@ .\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $ .\" .\" This file is in the public domain. -.Dd August 18, 2023 +.Dd June 19, 2025 .Dt PTRACE 2 .Os .Sh NAME @@ -473,6 +473,16 @@ This request is like PT_CONTINUE, except that it does not allow specifying an alternate place to continue execution, and after it succeeds, the traced process is no longer traced and continues execution normally. +.Pp +The parent of the traced process will be sent a +.Dv SIGCHLD +to indicate that the process has continued from a stopped state regardless of +whether the process was in a stopped state prior to the corresponding +.Dv PT_ATTACH +request. +A +.Xr wait 2 +for the traced process would indicate that it had been continued. .It Dv PT_GETREGS This request reads the traced process's machine registers into the .Do diff --git a/lib/libsys/recv.2 b/lib/libsys/recv.2 index f3ee60b75663..b78cd70b8a1d 100644 --- a/lib/libsys/recv.2 +++ b/lib/libsys/recv.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd July 30, 2022 +.Dd May 17, 2025 .Dt RECV 2 .Os .Sh NAME @@ -164,6 +164,7 @@ one or more of the values: .It Dv MSG_WAITALL Ta wait for full request or error .It Dv MSG_DONTWAIT Ta do not block .It Dv MSG_CMSG_CLOEXEC Ta set received fds close-on-exec +.It Dv MSG_CMSG_CLOFORK Ta set received fds close-on-fork .It Dv MSG_WAITFORONE Ta do not block after receiving the first message (only for .Fn recvmmsg diff --git a/lib/libsys/sendfile.2 b/lib/libsys/sendfile.2 index 07a563d5ef82..6000e3e9828f 100644 --- a/lib/libsys/sendfile.2 +++ b/lib/libsys/sendfile.2 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 30, 2020 +.Dd June 24, 2025 .Dt SENDFILE 2 .Os .Sh NAME @@ -147,12 +147,6 @@ in a different context. .It Dv SF_NOCACHE The data sent to socket will not be cached by the virtual memory system, and will be freed directly to the pool of free pages. -.It Dv SF_SYNC -.Nm -sleeps until the network stack no longer references the VM pages -of the file, making subsequent modifications to it safe. -Please note that this is not a guarantee that the data has actually -been sent. .It Dv SF_USER_READAHEAD .Nm has some internal heuristics to do readahead when sending data. diff --git a/lib/libsys/setcred.2 b/lib/libsys/setcred.2 index a1b819d24c52..86f61ddfdb30 100644 --- a/lib/libsys/setcred.2 +++ b/lib/libsys/setcred.2 @@ -248,7 +248,7 @@ does not. The .Fn setcred system call appeared in -.Fx 15.0 . +.Fx 14.3 . .Pp Traditionally in UNIX, all credential changes beyond shuffles of effective, real and saved IDs have been done by setuid binaries that successively call multiple diff --git a/lib/libsys/socket.2 b/lib/libsys/socket.2 index a383cbcc4d80..b211611c6354 100644 --- a/lib/libsys/socket.2 +++ b/lib/libsys/socket.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd January 15, 2023 +.Dd May 17, 2025 .Dt SOCKET 2 .Os .Sh NAME @@ -121,6 +121,7 @@ argument: .Pp .Bd -literal -offset indent -compact SOCK_CLOEXEC Set close-on-exec on the new descriptor, +SOCK_CLOFORK Set close-on-fork on the new descriptor, SOCK_NONBLOCK Set non-blocking mode on the new socket .Ed .Pp @@ -331,7 +332,10 @@ argument of .Fn socket . The .Dv SOCK_CLOEXEC -flag is expected to conform to the next revision of the +and +.Dv SOCK_CLOFORK +flags are expected to conform to +.St -p1003.1-2024 . .Tn POSIX standard. The @@ -347,3 +351,8 @@ The .Fn socket system call appeared in .Bx 4.2 . +.Pp +The +.Dv SOCK_CLOFORK +flag appeared in +.Fx 15.0 . diff --git a/lib/libsys/socketpair.2 b/lib/libsys/socketpair.2 index 5874a0791f4d..60dec74f9cc2 100644 --- a/lib/libsys/socketpair.2 +++ b/lib/libsys/socketpair.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd February 10, 2018 +.Dd May 17, 2025 .Dt SOCKETPAIR 2 .Os .Sh NAME @@ -56,7 +56,8 @@ and The two sockets are indistinguishable. .Pp The -.Dv SOCK_CLOEXEC +.Dv SOCK_CLOEXEC , +.Dv SOCK_CLOFORK and .Dv SOCK_NONBLOCK flags in the diff --git a/lib/libsys/statfs.2 b/lib/libsys/statfs.2 index b411b3b6ff46..49e8b5120558 100644 --- a/lib/libsys/statfs.2 +++ b/lib/libsys/statfs.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 29, 2023 +.Dd April 7, 2025 .Dt STATFS 2 .Os .Sh NAME @@ -125,6 +125,9 @@ The file system resides locally. Mandatory Access Control (MAC) support for individual objects (see .Xr mac 4 ) . +.It Dv MNT_NAMEDATTR +The file system supports named attributes as described in +.Xr named_attribute 9 . .It Dv MNT_NFS4ACLS ACLs in NFSv4 variant are supported. .It Dv MNT_NOATIME @@ -260,7 +263,8 @@ each file or directory name or disk label .Pc . .Sh SEE ALSO .Xr fhstatfs 2 , -.Xr getfsstat 2 +.Xr getfsstat 2 , +.Xr named_attribute 9 .Sh HISTORY The .Fn statfs diff --git a/lib/libsys/symlink.2 b/lib/libsys/symlink.2 index 6892586f69f2..b5d878aaae50 100644 --- a/lib/libsys/symlink.2 +++ b/lib/libsys/symlink.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 30, 2020 +.Dd April 15, 2025 .Dt SYMLINK 2 .Os .Sh NAME @@ -92,6 +92,10 @@ or the entire length of either path name exceeded 1023 characters. A component of the .Fa name2 path prefix does not exist. +.It Bq Er EOPNOTSUPP +The file system containing the file named by +.Fa name2 +does not support symbolic links. .It Bq Er EACCES A component of the .Fa name2 diff --git a/lib/libsys/syscalls.map b/lib/libsys/syscalls.map index 474df2cd8b1c..69fce2ea7c63 100644 --- a/lib/libsys/syscalls.map +++ b/lib/libsys/syscalls.map @@ -807,4 +807,10 @@ FBSDprivate_1.0 { __sys_fchroot; _setcred; __sys_setcred; + _exterrctl; + __sys_exterrctl; + _inotify_add_watch_at; + __sys_inotify_add_watch_at; + _inotify_rm_watch; + __sys_inotify_rm_watch; }; diff --git a/lib/libsys/thr_new.2 b/lib/libsys/thr_new.2 index c0bcc8bbc7c2..a04327723c34 100644 --- a/lib/libsys/thr_new.2 +++ b/lib/libsys/thr_new.2 @@ -133,6 +133,15 @@ The flag is not currently implemented. .It Dv THR_SYSTEM_SCOPE Create the system scope thread. The flag is not currently implemented. +.It Dv THR_C_RUNTIME +Indicate that the new thread is created by the C language runtime. +It has architecture-specific meaning. +.Pp +On amd64, the flag requests that the specified +.Fa tls_base +was loaded into the +.Va %fsbase +register before calling a signal handler. .El .It Va rtp Real-time scheduling priority for the new thread. diff --git a/lib/libsys/timer_create.2 b/lib/libsys/timer_create.2 index e8489b390845..8f6ff2e27c51 100644 --- a/lib/libsys/timer_create.2 +++ b/lib/libsys/timer_create.2 @@ -126,7 +126,8 @@ the value of the timer ID. This implementation supports a .Fa clock_id of -.Dv CLOCK_REALTIME +.Dv CLOCK_REALTIME , +.Dv CLOCK_TAI , or .Dv CLOCK_MONOTONIC . .Pp diff --git a/lib/libsys/wait.2 b/lib/libsys/wait.2 index 3c649f3dfa77..eeddf77aeac7 100644 --- a/lib/libsys/wait.2 +++ b/lib/libsys/wait.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 27, 2024 +.Dd June 19, 2025 .Dt WAIT 2 .Os .Sh NAME @@ -273,6 +273,10 @@ Report the status of selected processes that have continued from a job control stop by receiving a .Dv SIGCONT signal. +.Xr ptrace 2 +can also cause a process to be continued, when a +.Dv PT_DETACH +request is issued to detach the debugger. .It Dv WNOHANG Do not block when there are no processes wishing to report status. @@ -450,7 +454,7 @@ value: .Bl -tag -width Ds .It Fn WIFCONTINUED status True if the process has not terminated, and -has continued after a job control stop. +has continued after a job control stop or detach of a debugger. This macro can be true only if the wait call specified the .Dv WCONTINUED option. diff --git a/lib/libsys/write.2 b/lib/libsys/write.2 index 5fea75150e3b..d2ff41ceead9 100644 --- a/lib/libsys/write.2 +++ b/lib/libsys/write.2 @@ -185,13 +185,6 @@ A signal interrupted the write before it could be completed. .It Bq Er EAGAIN The file was marked for non-blocking I/O, and no data could be written immediately. -.It Bq Er EROFS -An attempt was made to write over a disk label area at the beginning -of a slice. -Use -.Xr disklabel 8 -.Fl W -to enable writing on the disk label area. .It Bq Er EINVAL The value .Fa nbytes @@ -202,6 +195,9 @@ is greater than if the sysctl .Va debug.iosize_max_clamp is non-zero). +.It Bq Er EINVAL +The file descriptor refers to a raw device, and the write +offset or size is not a multiple of the device's block size. .It Bq Er EINTEGRITY The backing store for .Fa fd diff --git a/lib/libsysdecode/Makefile b/lib/libsysdecode/Makefile index b01877bb8bb8..ca020552a6e9 100644 --- a/lib/libsysdecode/Makefile +++ b/lib/libsysdecode/Makefile @@ -84,6 +84,7 @@ MLINKS+=sysdecode_mask.3 sysdecode_accessmode.3 \ sysdecode_mask.3 sysdecode_fileflags.3 \ sysdecode_mask.3 sysdecode_filemode.3 \ sysdecode_mask.3 sysdecode_flock_operation.3 \ + sysdecode_mask.3 sysdecode_inotifyflags.3 \ sysdecode_mask.3 sysdecode_mlockall_flags.3 \ sysdecode_mask.3 sysdecode_mmap_flags.3 \ sysdecode_mask.3 sysdecode_mmap_prot.3 \ diff --git a/lib/libsysdecode/flags.c b/lib/libsysdecode/flags.c index 32829d35dbe0..f8e26e6a9dae 100644 --- a/lib/libsysdecode/flags.c +++ b/lib/libsysdecode/flags.c @@ -23,7 +23,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #define L2CAP_SOCKET_CHECKED #include <sys/types.h> @@ -31,6 +30,7 @@ #include <sys/capsicum.h> #include <sys/event.h> #include <sys/extattr.h> +#include <sys/inotify.h> #include <sys/linker.h> #include <sys/mman.h> #include <sys/mount.h> @@ -196,7 +196,7 @@ sysdecode_vmprot(FILE *fp, int type, int *rem) } static struct name_table sockflags[] = { - X(SOCK_CLOEXEC) X(SOCK_NONBLOCK) XEND + X(SOCK_CLOEXEC) X(SOCK_CLOFORK) X(SOCK_NONBLOCK) XEND }; bool @@ -206,16 +206,17 @@ sysdecode_socket_type(FILE *fp, int type, int *rem) uintmax_t val; bool printed; - str = lookup_value(socktype, type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)); + str = lookup_value(socktype, + type & ~(SOCK_CLOEXEC | SOCK_CLOFORK | SOCK_NONBLOCK)); if (str != NULL) { fputs(str, fp); *rem = 0; printed = true; } else { - *rem = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK); + *rem = type & ~(SOCK_CLOEXEC | SOCK_CLOFORK | SOCK_NONBLOCK); printed = false; } - val = type & (SOCK_CLOEXEC | SOCK_NONBLOCK); + val = type & (SOCK_CLOEXEC | SOCK_CLOFORK | SOCK_NONBLOCK); print_mask_part(fp, sockflags, &val, &printed); return (printed); } @@ -351,6 +352,13 @@ sysdecode_getrusage_who(int who) return (lookup_value(rusage, who)); } +bool +sysdecode_inotifyflags(FILE *fp, int flag, int *rem) +{ + + return (print_mask_int(fp, inotifyflags, flag, rem)); +} + static struct name_table kevent_user_ffctrl[] = { X(NOTE_FFNOP) X(NOTE_FFAND) X(NOTE_FFOR) X(NOTE_FFCOPY) XEND @@ -556,7 +564,7 @@ sysdecode_nfssvc_flags(int flags) } static struct name_table pipe2flags[] = { - X(O_CLOEXEC) X(O_NONBLOCK) XEND + X(O_CLOEXEC) X(O_CLOFORK) X(O_NONBLOCK) XEND }; bool @@ -866,7 +874,7 @@ sysdecode_fcntl_cmd(int cmd) } static struct name_table fcntl_fd_arg[] = { - X(FD_CLOEXEC) X(0) XEND + X(FD_CLOEXEC) X(FD_CLOFORK) X(0) XEND }; bool diff --git a/lib/libsysdecode/mktables b/lib/libsysdecode/mktables index 87ab24ddf1a5..6b4f79402660 100644 --- a/lib/libsysdecode/mktables +++ b/lib/libsysdecode/mktables @@ -98,6 +98,7 @@ gen_table "extattrns" "EXTATTR_NAMESPACE_[A-Z]+[[:space:]]+0x[0-9]+" "sys/ gen_table "fadvisebehav" "POSIX_FADV_[A-Z]+[[:space:]]+[0-9]+" "sys/fcntl.h" gen_table "openflags" "O_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+" "sys/fcntl.h" "O_RDONLY|O_RDWR|O_WRONLY" gen_table "flockops" "LOCK_[A-Z]+[[:space:]]+0x[0-9]+" "sys/fcntl.h" +gen_table "inotifyflags" "IN_[A-Z_]+[[:space:]]+0x[0-9]+" "sys/inotify.h" "IN_CLOEXEC|IN_NONBLOCK" gen_table "kldsymcmd" "KLDSYM_[A-Z]+[[:space:]]+[0-9]+" "sys/linker.h" gen_table "kldunloadfflags" "LINKER_UNLOAD_[A-Z]+[[:space:]]+[0-9]+" "sys/linker.h" gen_table "lio_listiomodes" "LIO_(NO)?WAIT[[:space:]]+[0-9]+" "aio.h" @@ -145,7 +146,7 @@ gen_table "sockopttcp" "TCP_[[:alnum:]_]+[[:space:]]+[0-9]+" "neti gen_table "sockoptudp" "UDP_[[:alnum:]]+[[:space:]]+[0-9]+" "netinet/udp.h" "UDP_ENCAP_" gen_table "sockoptudplite" "UDPLITE_[[:alnum:]_]+[[:space:]]+[0-9]+" "netinet/udplite.h" gen_table "socktype" "SOCK_[A-Z]+[[:space:]]+[1-9]+[0-9]*" "sys/socket.h" -gen_table "thrcreateflags" "THR_[A-Z]+[[:space:]]+0x[0-9]+" "sys/thr.h" +gen_table "thrcreateflags" "THR_[A-Z_]+[[:space:]]+0x[0-9]+" "sys/thr.h" gen_table "umtxop" "UMTX_OP_[[:alnum:]][[:alnum:]_]*[[:space:]]+[0-9]+" "sys/umtx.h" gen_table "umtxopflags" "UMTX_OP__[[:alnum:]_]+[[:space:]]+[0-9]+" "sys/umtx.h" gen_table "vmprot" "VM_PROT_[A-Z_]+[[:space:]]+\(\(vm_prot_t\)[[:space:]]+0x[0-9]+\)" "vm/vm.h" diff --git a/lib/libsysdecode/sysdecode.h b/lib/libsysdecode/sysdecode.h index 8dc0bbea6f0d..c95d7f71379b 100644 --- a/lib/libsysdecode/sysdecode.h +++ b/lib/libsysdecode/sysdecode.h @@ -61,6 +61,7 @@ const char *sysdecode_getfsstat_mode(int _mode); const char *sysdecode_getrusage_who(int _who); const char *sysdecode_idtype(int _idtype); const char *sysdecode_ioctlname(unsigned long _val); +bool sysdecode_inotifyflags(FILE *_fp, int _flags, int *_rem); const char *sysdecode_ipproto(int _protocol); void sysdecode_kevent_fflags(FILE *_fp, short _filter, int _fflags, int _base); diff --git a/lib/libsysdecode/sysdecode_fcntl_arg.3 b/lib/libsysdecode/sysdecode_fcntl_arg.3 index ee3a030a79e4..d5648ce0adc3 100644 --- a/lib/libsysdecode/sysdecode_fcntl_arg.3 +++ b/lib/libsysdecode/sysdecode_fcntl_arg.3 @@ -54,7 +54,8 @@ are determined by .It Sy Command Ta Fa arg Sy Type Ta Sy Output Format .It .It Dv F_SETFD Ta Vt int Ta -.Dq FD_CLOEXEC +.Dq FD_CLOEXEC , +.Dq FD_CLOFORK or the value of .Fa arg in the indicated diff --git a/lib/libtelnet/Makefile b/lib/libtelnet/Makefile index 69e63af4e272..6bc2f5a51de0 100644 --- a/lib/libtelnet/Makefile +++ b/lib/libtelnet/Makefile @@ -19,7 +19,8 @@ CFLAGS+= -DENCRYPTION -DAUTHENTICATION -DSRA CFLAGS+= -DOPENSSL_API_COMPAT=0x10100000L .endif -.if ${MK_KERBEROS_SUPPORT} != "no" +.if ${MK_KERBEROS_SUPPORT} != "no" && ${MK_MITKRB5} != "yes" +# MIT KRB5 deprecated and removed 3DES. Therefore no telnet support. SRCS+= kerberos5.c CFLAGS+= -DKRB5 -DFORWARD -Dnet_write=telnet_net_write .endif diff --git a/lib/libthr/Makefile b/lib/libthr/Makefile index 19afa93f12be..c87be9475390 100644 --- a/lib/libthr/Makefile +++ b/lib/libthr/Makefile @@ -53,6 +53,7 @@ CFLAGS+=-D_PTHREAD_FORCED_UNWIND .endif LDFLAGS+=-Wl,-znodelete +LDFLAGS+=-Wl,-zinitfirst LDFLAGS+=-Wl,--auxiliary,libsys.so.7 VERSION_DEF=${SRCTOP}/lib/libc/Versions.def diff --git a/lib/libthr/arch/aarch64/include/pthread_md.h b/lib/libthr/arch/aarch64/include/pthread_md.h index 305abed55d3c..4316955f1d3d 100644 --- a/lib/libthr/arch/aarch64/include/pthread_md.h +++ b/lib/libthr/arch/aarch64/include/pthread_md.h @@ -54,4 +54,6 @@ _thr_resolve_machdep(void) { } +#define __thr_setup_tsd(thread) _tcb_set((thread)->tcb) + #endif /* _PTHREAD_MD_H_ */ diff --git a/lib/libthr/arch/aarch64/include/pthread_tls.h b/lib/libthr/arch/aarch64/include/pthread_tls.h deleted file mode 100644 index 4e02f8d4e03f..000000000000 --- a/lib/libthr/arch/aarch64/include/pthread_tls.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - */ - -#ifndef _ARCH_AARCH64_PTHREAD_TLS_H -#define _ARCH_AARCH64_PTHREAD_TLS_H - -static __inline uintptr_t -_get_static_tls_base(struct pthread *thr, size_t offset) -{ - uintptr_t tlsbase; - - tlsbase = (uintptr_t)thr->tcb; - tlsbase += offset; - return (tlsbase); -} - -#endif diff --git a/lib/libthr/arch/amd64/Makefile.inc b/lib/libthr/arch/amd64/Makefile.inc index f8013ea914ed..fe80e1a73cc9 100644 --- a/lib/libthr/arch/amd64/Makefile.inc +++ b/lib/libthr/arch/amd64/Makefile.inc @@ -3,3 +3,5 @@ # the extra context switch cost. This can measurably impact # performance when the application also does not use enough SSE. CFLAGS+=${CFLAGS_NO_SIMD} + +SRCS+= thr_machdep.c diff --git a/lib/libthr/arch/amd64/amd64/thr_machdep.c b/lib/libthr/arch/amd64/amd64/thr_machdep.c new file mode 100644 index 000000000000..d23e1689779c --- /dev/null +++ b/lib/libthr/arch/amd64/amd64/thr_machdep.c @@ -0,0 +1,48 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + * + */ + +#define _WANT_P_OSREL +#include <sys/param.h> +#include <errno.h> +#include <machine/sysarch.h> + +#include "libc_private.h" +#include "thr_private.h" + +void +__thr_setup_tsd(struct pthread *thread) +{ + void *base; + int error; + + if (__getosreldate() < P_OSREL_TLSBASE) { + amd64_set_tlsbase(thread->tcb); + return; + } + + /* + * Make tlsbase handling more compatible with code, like Go + * runtime, which wants to manage fsbase itself, and which do + * not need assistance in setting fsbase for signal handlers. + * + * If the main thread did not used amd64_set_tlsbase(), which + * means that rtld/libc was not utilized, do not use + * amd64_set_tlsbase() either. Also do not mark new threads + * as using C runtime with the THR_C_RUNTIME flag. + */ + error = sysarch(AMD64_GET_TLSBASE, &base); + if (error != 0 && errno == ESRCH) { + __thr_new_flags &= ~THR_C_RUNTIME; + amd64_set_fsbase(thread->tcb); + } else { + amd64_set_tlsbase(thread->tcb); + } +} diff --git a/lib/libthr/arch/amd64/include/pthread_md.h b/lib/libthr/arch/amd64/include/pthread_md.h index 85517c1aee70..02b73d90f006 100644 --- a/lib/libthr/arch/amd64/include/pthread_md.h +++ b/lib/libthr/arch/amd64/include/pthread_md.h @@ -57,4 +57,6 @@ _thr_resolve_machdep(void) { } +void __thr_setup_tsd(struct pthread *thread); + #endif diff --git a/lib/libthr/arch/amd64/include/pthread_tls.h b/lib/libthr/arch/amd64/include/pthread_tls.h deleted file mode 100644 index 2af0aeda4c85..000000000000 --- a/lib/libthr/arch/amd64/include/pthread_tls.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - */ - -#ifndef _ARCH_AMD64_PTHREAD_TLS_H -#define _ARCH_AMD64_PTHREAD_TLS_H - -static __inline uintptr_t -_get_static_tls_base(struct pthread *thr, size_t offset) -{ - uintptr_t tlsbase; - - tlsbase = (uintptr_t)thr->tcb; - tlsbase -= offset; - return (tlsbase); -} - -#endif diff --git a/lib/libthr/arch/arm/include/pthread_md.h b/lib/libthr/arch/arm/include/pthread_md.h index d616868bdee4..b90568e249ee 100644 --- a/lib/libthr/arch/arm/include/pthread_md.h +++ b/lib/libthr/arch/arm/include/pthread_md.h @@ -48,4 +48,6 @@ _get_curthread(void) return (NULL); } +#define __thr_setup_tsd(thread) _tcb_set((thread)->tcb) + #endif /* _PTHREAD_MD_H_ */ diff --git a/lib/libthr/arch/arm/include/pthread_tls.h b/lib/libthr/arch/arm/include/pthread_tls.h deleted file mode 100644 index 27a07f69f474..000000000000 --- a/lib/libthr/arch/arm/include/pthread_tls.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - */ - -#ifndef _ARCH_ARM_PTHREAD_TLS_H -#define _ARCH_ARM_PTHREAD_TLS_H - -static __inline uintptr_t -_get_static_tls_base(struct pthread *thr, size_t offset) -{ - uintptr_t tlsbase; - - tlsbase = (uintptr_t)thr->tcb; - tlsbase += offset; - return (tlsbase); -} - -#endif diff --git a/lib/libthr/arch/i386/include/pthread_md.h b/lib/libthr/arch/i386/include/pthread_md.h index 7e2c8d7330fc..43f84c3d0393 100644 --- a/lib/libthr/arch/i386/include/pthread_md.h +++ b/lib/libthr/arch/i386/include/pthread_md.h @@ -57,4 +57,6 @@ _thr_resolve_machdep(void) { } +#define __thr_setup_tsd(thread) _tcb_set((thread)->tcb) + #endif diff --git a/lib/libthr/arch/i386/include/pthread_tls.h b/lib/libthr/arch/i386/include/pthread_tls.h deleted file mode 100644 index b2d0f2dbe845..000000000000 --- a/lib/libthr/arch/i386/include/pthread_tls.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - */ - -#ifndef _ARCH_I386_PTHREAD_TLS_H -#define _ARCH_I386_PTHREAD_TLS_H - -static __inline uintptr_t -_get_static_tls_base(struct pthread *thr, size_t offset) -{ - uintptr_t tlsbase; - - tlsbase = (uintptr_t)thr->tcb; - tlsbase -= offset; - return (tlsbase); -} - -#endif diff --git a/lib/libthr/arch/powerpc/include/pthread_md.h b/lib/libthr/arch/powerpc/include/pthread_md.h index a5bc0265ed3a..291f2d9350d9 100644 --- a/lib/libthr/arch/powerpc/include/pthread_md.h +++ b/lib/libthr/arch/powerpc/include/pthread_md.h @@ -54,4 +54,6 @@ _thr_resolve_machdep(void) { } +#define __thr_setup_tsd(thread) _tcb_set((thread)->tcb) + #endif /* _PTHREAD_MD_H_ */ diff --git a/lib/libthr/arch/powerpc/include/pthread_tls.h b/lib/libthr/arch/powerpc/include/pthread_tls.h deleted file mode 100644 index e53164436018..000000000000 --- a/lib/libthr/arch/powerpc/include/pthread_tls.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - */ - -#ifndef _ARCH_POWERPC_PTHREAD_TLS_H -#define _ARCH_POWERPC_PTHREAD_TLS_H - -static __inline uintptr_t -_get_static_tls_base(struct pthread *thr, size_t offset) -{ - uintptr_t tlsbase; - - tlsbase = (uintptr_t)thr->tcb; - tlsbase += offset; - return (tlsbase); -} - -#endif diff --git a/lib/libthr/arch/riscv/include/pthread_md.h b/lib/libthr/arch/riscv/include/pthread_md.h index baddfe3ecb22..01dcc9c02b8c 100644 --- a/lib/libthr/arch/riscv/include/pthread_md.h +++ b/lib/libthr/arch/riscv/include/pthread_md.h @@ -61,4 +61,6 @@ _thr_resolve_machdep(void) { } +#define __thr_setup_tsd(thread) _tcb_set((thread)->tcb) + #endif /* _PTHREAD_MD_H_ */ diff --git a/lib/libthr/arch/riscv/include/pthread_tls.h b/lib/libthr/arch/riscv/include/pthread_tls.h deleted file mode 100644 index 0af1ddd4cfaf..000000000000 --- a/lib/libthr/arch/riscv/include/pthread_tls.h +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 The FreeBSD Foundation - * - * This software was developed by Konstantin Belousov <kib@FreeBSD.org> - * under sponsorship from the FreeBSD Foundation. - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - */ - -#ifndef _ARCH_RISCV_PTHREAD_TLS_H -#define _ARCH_RISCV_PTHREAD_TLS_H - -static __inline uintptr_t -_get_static_tls_base(struct pthread *thr, size_t offset) -{ - uintptr_t tlsbase; - - tlsbase = (uintptr_t)thr->tcb; - tlsbase += offset; - return (tlsbase); -} - -#endif diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map index f75ef4c9135e..3a5353a32dc3 100644 --- a/lib/libthr/pthread.map +++ b/lib/libthr/pthread.map @@ -136,7 +136,6 @@ FBSDprivate_1.0 { __pthread_mutex_lock; __pthread_mutex_timedlock; __pthread_mutex_trylock; - __pthread_distribute_static_tls; _pthread_atfork; _pthread_barrier_destroy; _pthread_barrier_init; @@ -339,5 +338,7 @@ FBSD_1.6 { }; FBSD_1.8 { + pthread_signals_block_np; + pthread_signals_unblock_np; pthread_sigqueue; }; diff --git a/lib/libthr/tests/dlopen/dso/Makefile b/lib/libthr/tests/dlopen/dso/Makefile index 0dac101f7186..74d8ada35ff1 100644 --- a/lib/libthr/tests/dlopen/dso/Makefile +++ b/lib/libthr/tests/dlopen/dso/Makefile @@ -1,6 +1,7 @@ TESTSRC= ${SRCTOP}/contrib/netbsd-tests/lib/libpthread/dlopen/dso WARNS?= 3 +PACKAGE= tests SHLIB= h_pthread_dlopen SHLIB_MAJOR= 1 SHLIB_NAME= h_pthread_dlopen.so.${SHLIB_MAJOR} diff --git a/lib/libthr/thread/thr_condattr.c b/lib/libthr/thread/thr_condattr.c index 0dc3e52bab5e..dc56363fc084 100644 --- a/lib/libthr/thread/thr_condattr.c +++ b/lib/libthr/thread/thr_condattr.c @@ -94,6 +94,7 @@ _pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id) if (attr == NULL || *attr == NULL) return (EINVAL); if (clock_id != CLOCK_REALTIME && + clock_id != CLOCK_TAI && clock_id != CLOCK_VIRTUAL && clock_id != CLOCK_PROF && clock_id != CLOCK_MONOTONIC) { diff --git a/lib/libthr/thread/thr_create.c b/lib/libthr/thread/thr_create.c index 2ae7cf0cd7b2..e56dbcfe30e1 100644 --- a/lib/libthr/thread/thr_create.c +++ b/lib/libthr/thread/thr_create.c @@ -27,10 +27,12 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define _WANT_P_OSREL #include "namespace.h" #include <sys/types.h> #include <sys/rtprio.h> #include <sys/signalvar.h> +#include <sys/exterrvar.h> #include <errno.h> #include <link.h> #include <stdlib.h> @@ -43,9 +45,13 @@ #include "libc_private.h" #include "thr_private.h" +int __getosreldate(void); + static int create_stack(struct pthread_attr *pattr); static void thread_start(struct pthread *curthread); +int __thr_new_flags = THR_C_RUNTIME; + __weak_reference(_pthread_create, pthread_create); int @@ -160,7 +166,7 @@ _pthread_create(pthread_t * __restrict thread, param.tls_size = sizeof(struct tcb); param.child_tid = &new_thread->tid; param.parent_tid = &new_thread->tid; - param.flags = 0; + param.flags = __thr_new_flags; if (new_thread->attr.flags & PTHREAD_SCOPE_SYSTEM) param.flags |= THR_SYSTEM_SCOPE; if (new_thread->attr.sched_inherit == PTHREAD_INHERIT_SCHED) @@ -285,6 +291,10 @@ thread_start(struct pthread *curthread) curthread->attr.stacksize_attr; #endif + curthread->uexterr.ver = UEXTERROR_VER; + if (__getosreldate() >= P_OSREL_EXTERRCTL) + exterrctl(EXTERRCTL_ENABLE, 0, &curthread->uexterr); + /* Run the current thread's start routine with argument: */ _pthread_exit(curthread->start_routine(curthread->arg)); diff --git a/lib/libthr/thread/thr_init.c b/lib/libthr/thread/thr_init.c index 8855491b91cb..64cf7d004070 100644 --- a/lib/libthr/thread/thr_init.c +++ b/lib/libthr/thread/thr_init.c @@ -33,6 +33,7 @@ * SUCH DAMAGE. */ +#define _WANT_P_OSREL #include "namespace.h" #include <sys/param.h> #include <sys/auxv.h> @@ -59,6 +60,7 @@ #include "libc_private.h" #include "thr_private.h" +int __getosreldate(void); char *_usrstack; struct pthread *_thr_initial; int _libthr_debug; @@ -352,7 +354,7 @@ _libpthread_init(struct pthread *curthread) _thread_active_threads = 1; /* Setup the thread specific data */ - _tcb_set(curthread->tcb); + __thr_setup_tsd(curthread); if (first) { _thr_initial = curthread; @@ -433,6 +435,10 @@ init_main_thread(struct pthread *thread) thread->unwind_stackend = _usrstack; #endif + thread->uexterr.ver = UEXTERROR_VER; + if (__getosreldate() >= P_OSREL_EXTERRCTL) + exterrctl(EXTERRCTL_ENABLE, EXTERRCTLF_FORCE, &thread->uexterr); + /* Others cleared to zero by thr_alloc() */ } diff --git a/lib/libthr/thread/thr_list.c b/lib/libthr/thread/thr_list.c index bbc1d2899cb9..cbf16179f619 100644 --- a/lib/libthr/thread/thr_list.c +++ b/lib/libthr/thread/thr_list.c @@ -30,13 +30,14 @@ #include <sys/types.h> #include <sys/queue.h> +#include <machine/tls.h> + #include <stdlib.h> #include <string.h> #include <pthread.h> #include "libc_private.h" #include "thr_private.h" -#include "static_tls.h" /*#define DEBUG_THREAD_LIST */ #ifdef DEBUG_THREAD_LIST @@ -150,11 +151,13 @@ _thr_alloc(struct pthread *curthread) if (total_threads > MAX_THREADS) return (NULL); atomic_add_int(&total_threads, 1); - thread = __thr_calloc(1, sizeof(struct pthread)); + thread = __thr_aligned_alloc_offset(_Alignof(struct pthread), + sizeof(struct pthread), 0); if (thread == NULL) { atomic_add_int(&total_threads, -1); return (NULL); } + memset(thread, 0, sizeof(*thread)); if ((thread->sleepqueue = _sleepq_alloc()) == NULL || (thread->wake_addr = _thr_alloc_wake_addr()) == NULL) { thr_destroy(curthread, thread); @@ -360,35 +363,3 @@ _thr_find_thread(struct pthread *curthread, struct pthread *thread, THREAD_LIST_UNLOCK(curthread); return (ret); } - -#include "pthread_tls.h" - -static void -thr_distribute_static_tls(uintptr_t tlsbase, void *src, size_t len, - size_t total_len) -{ - - memcpy((void *)tlsbase, src, len); - memset((char *)tlsbase + len, 0, total_len - len); -} - -void -__pthread_distribute_static_tls(size_t offset, void *src, size_t len, - size_t total_len) -{ - struct pthread *curthread, *thrd; - uintptr_t tlsbase; - - if (!_thr_is_inited()) { - tlsbase = _libc_get_static_tls_base(offset); - thr_distribute_static_tls(tlsbase, src, len, total_len); - return; - } - curthread = _get_curthread(); - THREAD_LIST_RDLOCK(curthread); - TAILQ_FOREACH(thrd, &_thread_list, tle) { - tlsbase = _get_static_tls_base(thrd, offset); - thr_distribute_static_tls(tlsbase, src, len, total_len); - } - THREAD_LIST_UNLOCK(curthread); -} diff --git a/lib/libthr/thread/thr_malloc.c b/lib/libthr/thread/thr_malloc.c index 9a81d6d1bd6b..48af9d1ea929 100644 --- a/lib/libthr/thread/thr_malloc.c +++ b/lib/libthr/thread/thr_malloc.c @@ -120,6 +120,19 @@ __thr_malloc(size_t nbytes) } void * +__thr_aligned_alloc_offset(size_t align, size_t size, size_t offset) +{ + struct pthread *curthread; + void *res; + + curthread = _get_curthread(); + thr_malloc_lock(curthread); + res = __crt_aligned_alloc_offset(align, size, offset); + thr_malloc_unlock(curthread); + return (res); +} + +void * __thr_realloc(void *cp, size_t nbytes) { struct pthread *curthread; diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index 926e868293cd..d7b889930365 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -40,6 +40,7 @@ #include <sys/queue.h> #include <sys/param.h> #include <sys/cpuset.h> +#include <sys/exterrvar.h> #include <machine/atomic.h> #include <errno.h> #include <limits.h> @@ -576,6 +577,8 @@ struct pthread { /* pthread_set/get_name_np */ char *name; + + struct uexterror uexterr; }; #define THR_SHOULD_GC(thrd) \ @@ -776,6 +779,8 @@ extern struct pthread *_single_thread __hidden; extern bool _thr_after_fork __hidden; +extern int __thr_new_flags; + /* * Function prototype definitions. */ @@ -981,8 +986,6 @@ void __pthread_cxa_finalize(struct dl_phdr_info *phdr_info); void _thr_tsd_unload(struct dl_phdr_info *phdr_info) __hidden; void _thr_sigact_unload(struct dl_phdr_info *phdr_info) __hidden; void _thr_stack_fix_protection(struct pthread *thrd); -void __pthread_distribute_static_tls(size_t offset, void *src, size_t len, - size_t total_len); int *__error_threaded(void) __hidden; void __thr_interpose_libc(void) __hidden; @@ -1014,6 +1017,7 @@ void __thr_pshared_destroy(void *key) __hidden; void __thr_pshared_atfork_pre(void) __hidden; void __thr_pshared_atfork_post(void) __hidden; +void *__thr_aligned_alloc_offset(size_t align, size_t size, size_t offset); void *__thr_calloc(size_t num, size_t size); void __thr_free(void *cp); void *__thr_malloc(size_t nbytes); diff --git a/lib/libthr/thread/thr_rtld.c b/lib/libthr/thread/thr_rtld.c index e5a7f86de288..3cfdfc548cf2 100644 --- a/lib/libthr/thread/thr_rtld.c +++ b/lib/libthr/thread/thr_rtld.c @@ -50,8 +50,11 @@ static int _thr_rtld_set_flag(int); static void _thr_rtld_wlock_acquire(void *); struct rtld_lock { - struct urwlock lock; - char _pad[CACHE_LINE_SIZE - sizeof(struct urwlock)]; + struct urwlock lock; + struct pthread *wowner; + u_int rlocks; + char _pad[CACHE_LINE_SIZE - sizeof(struct urwlock) - + sizeof(struct pthread *) - sizeof(u_int)]; }; static struct rtld_lock lock_place[MAX_RTLD_LOCKS] __aligned(CACHE_LINE_SIZE); @@ -116,9 +119,13 @@ _thr_rtld_rlock_acquire(void *lock) SAVE_ERRNO(); l = (struct rtld_lock *)lock; - THR_CRITICAL_ENTER(curthread); - while (_thr_rwlock_rdlock(&l->lock, 0, NULL) != 0) - ; + if (l->wowner == curthread) { + l->rlocks++; + } else { + THR_CRITICAL_ENTER(curthread); + while (_thr_rwlock_rdlock(&l->lock, 0, NULL) != 0) + ; + } curthread->rdlock_count++; RESTORE_ERRNO(); } @@ -137,6 +144,7 @@ _thr_rtld_wlock_acquire(void *lock) THR_CRITICAL_ENTER(curthread); while (_thr_rwlock_wrlock(&l->lock, NULL) != 0) ; + l->wowner = curthread; RESTORE_ERRNO(); } @@ -164,6 +172,14 @@ _thr_rtld_lock_release(void *lock) l->lock.rw_blocked_readers = 0; l->lock.rw_blocked_writers = 0; } + if ((state & URWLOCK_WRITE_OWNER) != 0) { + if (l->rlocks > 0) { + l->rlocks--; + return; + } else { + l->wowner = NULL; + } + } if (_thr_rwlock_unlock(&l->lock) == 0) { if ((state & URWLOCK_WRITE_OWNER) == 0) curthread->rdlock_count--; diff --git a/lib/libthr/thread/thr_sig.c b/lib/libthr/thread/thr_sig.c index c5ee5aa8423b..2cd3de512d1c 100644 --- a/lib/libthr/thread/thr_sig.c +++ b/lib/libthr/thread/thr_sig.c @@ -37,6 +37,7 @@ #include <stdlib.h> #include <string.h> #include <pthread.h> +#include <pthread_np.h> #include "un-namespace.h" #include "libc_private.h" @@ -163,6 +164,24 @@ _thr_signal_block_setup(struct pthread *curthread) __sys_sigfastblock(SIGFASTBLOCK_SETPTR, &curthread->fsigblock); } +void +pthread_signals_block_np(void) +{ + struct pthread *curthread; + + curthread = _get_curthread(); + _thr_signal_block(curthread); +} + +void +pthread_signals_unblock_np(void) +{ + struct pthread *curthread; + + curthread = _get_curthread(); + _thr_signal_unblock(curthread); +} + int _thr_send_sig(struct pthread *thread, int sig) { diff --git a/lib/libthr/thread/thr_switch_np.c b/lib/libthr/thread/thr_switch_np.c index 80cd34c15650..59a9a4c7e1a3 100644 --- a/lib/libthr/thread/thr_switch_np.c +++ b/lib/libthr/thread/thr_switch_np.c @@ -40,10 +40,13 @@ #include "thr_private.h" - __weak_reference(_pthread_switch_add_np, pthread_switch_add_np); __weak_reference(_pthread_switch_delete_np, pthread_switch_delete_np); +typedef void (*pthread_switch_routine_t)(pthread_t, pthread_t); +int _pthread_switch_add_np(pthread_switch_routine_t routine); +int _pthread_switch_delete_np(pthread_switch_routine_t routine); + int _pthread_switch_add_np(pthread_switch_routine_t routine __unused) { diff --git a/lib/libthr/thread/thr_syscalls.c b/lib/libthr/thread/thr_syscalls.c index 22f9c1f68ec2..188374a30070 100644 --- a/lib/libthr/thread/thr_syscalls.c +++ b/lib/libthr/thread/thr_syscalls.c @@ -66,9 +66,9 @@ */ #include "namespace.h" -#include <sys/types.h> -#include <sys/mman.h> #include <sys/param.h> +#include <sys/exterrvar.h> +#include <sys/mman.h> #include <sys/select.h> #include <sys/signalvar.h> #include <sys/socket.h> @@ -620,6 +620,15 @@ __thr_writev(int fd, const struct iovec *iov, int iovcnt) return (ret); } +static int +__thr_uexterr_gettext(char *buf, size_t bufsz) +{ + struct pthread *curthread; + + curthread = _get_curthread(); + return (__uexterr_format(&curthread->uexterr, buf, bufsz)); +} + void __thr_interpose_libc(void) { @@ -675,6 +684,7 @@ __thr_interpose_libc(void) SLOT(fdatasync); SLOT(clock_nanosleep); SLOT(pdfork); + SLOT(uexterr_gettext); #undef SLOT *(__libc_interposing_slot( INTERPOS__pthread_mutex_init_calloc_cb)) = diff --git a/lib/libufs/Makefile b/lib/libufs/Makefile index 12c742e6b871..ab913f834bb3 100644 --- a/lib/libufs/Makefile +++ b/lib/libufs/Makefile @@ -1,4 +1,4 @@ -PACKAGE= ufs +PACKAGE= libufs LIB= ufs SHLIBDIR?= /lib SHLIB_MAJOR= 8 diff --git a/lib/libunbound/config.h b/lib/libunbound/config.h index 17a6707c7102..a986bfc869a3 100644 --- a/lib/libunbound/config.h +++ b/lib/libunbound/config.h @@ -796,7 +796,7 @@ #define PACKAGE_NAME "unbound" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "unbound 1.22.0" +#define PACKAGE_STRING "unbound 1.23.0" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "unbound" @@ -805,7 +805,7 @@ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "1.22.0" +#define PACKAGE_VERSION "1.23.0" /* default pidfile location */ #define PIDFILE "/var/unbound/unbound.pid" @@ -828,7 +828,7 @@ #define ROOT_CERT_FILE "/var/unbound/icannbundle.pem" /* version number for resource files */ -#define RSRC_PACKAGE_VERSION 1,22,0,0 +#define RSRC_PACKAGE_VERSION 1,23,0,0 /* Directory to chdir to */ #define RUN_DIR "/var/unbound" diff --git a/lib/libusb/libusb.3 b/lib/libusb/libusb.3 index fe07e86623c8..74b85d4aa17e 100644 --- a/lib/libusb/libusb.3 +++ b/lib/libusb/libusb.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd January 26, 2023 +.Dd June 13, 2025 .Dt LIBUSB 3 .Os .Sh NAME @@ -106,6 +106,19 @@ Get the ASCII representation of the error given by the argument. This function does not return NULL. .Pp +.Ft int +.Fn libusb_setlocale "const char *locale" +Set locale for the error message when using +.Fn libusb_strerror +to +.Ft locale . +Note other +.Nm +implementations only support the first two bytes, that means +.Ql en-US +is equivalent to +.Ql en-CA . +.Pp .Ft const char * .Fn libusb_error_name "int code" Get the ASCII representation of the error enum given by the @@ -117,7 +130,7 @@ This function does not return NULL. .Fn libusb_set_debug "libusb_context *ctx" "int level" Set the debug level to .Fa level . -.Pp +.Sh DEVICE HANDLING AND ENUMERATION .Ft ssize_t .Fn libusb_get_device_list "libusb_context *ctx" "libusb_device ***list" Populate @@ -220,6 +233,11 @@ Close a device handle. Get the device contained by devh. Returns NULL on error. .Pp +.Ft libusb_device * +.Fn libusb_get_parent "libusb_device *dev" +Get dev's parent device. +Returns NULL if the device has no parent (i.e. is a root device). +.Pp .Ft int .Fn libusb_get_configuration "libusb_device_handle *devh" "int *config" Returns the value of the current configuration. diff --git a/lib/libusb/libusb.h b/lib/libusb/libusb.h index 732fc9dca1e0..6fb1c19fad13 100644 --- a/lib/libusb/libusb.h +++ b/lib/libusb/libusb.h @@ -210,12 +210,15 @@ enum libusb_error { LIBUSB_ERROR_OTHER = -99, }; +#define LIBUSB_ERROR_COUNT 14 + enum libusb_speed { LIBUSB_SPEED_UNKNOWN = 0, LIBUSB_SPEED_LOW = 1, LIBUSB_SPEED_FULL = 2, LIBUSB_SPEED_HIGH = 3, LIBUSB_SPEED_SUPER = 4, + LIBUSB_SPEED_SUPER_PLUS = 5, }; enum libusb_transfer_status { @@ -242,17 +245,6 @@ enum libusb_log_level { LIBUSB_LOG_LEVEL_DEBUG }; -/* XXX */ -/* libusb_set_debug should take parameters from libusb_log_level - * above according to - * https://libusb.sourceforge.io/api-1.0/group__libusb__lib.html - */ -enum libusb_debug_level { - LIBUSB_DEBUG_NO=0, - LIBUSB_DEBUG_FUNCTION=1, - LIBUSB_DEBUG_TRANSFER=2, -}; - #define LIBUSB_HOTPLUG_MATCH_ANY -1 typedef enum { @@ -417,7 +409,10 @@ typedef struct libusb_bos_descriptor { uint8_t bLength; uint8_t bDescriptorType; uint16_t wTotalLength; - uint8_t bNumDeviceCapabilities; +#ifndef bNumDeviceCapabilities +#define bNumDeviceCapabilities bNumDeviceCaps +#endif + uint8_t bNumDeviceCaps; struct libusb_usb_2_0_device_capability_descriptor *usb_2_0_ext_cap; struct libusb_ss_usb_device_capability_descriptor *ss_usb_cap; struct libusb_bos_dev_capability_descriptor **dev_capability; @@ -482,6 +477,7 @@ int libusb_init(libusb_context ** context); int libusb_init_context(libusb_context **, const struct libusb_init_option [], int num_options); void libusb_exit(struct libusb_context *ctx); int libusb_has_capability(uint32_t capability); +int libusb_setlocale(const char *locale); /* Device handling and enumeration */ @@ -502,6 +498,7 @@ int libusb_open(libusb_device * dev, libusb_device_handle ** devh); libusb_device_handle *libusb_open_device_with_vid_pid(libusb_context * ctx, uint16_t vendor_id, uint16_t product_id); void libusb_close(libusb_device_handle * devh); libusb_device *libusb_get_device(libusb_device_handle * devh); +libusb_device *libusb_get_parent(libusb_device * dev); int libusb_get_configuration(libusb_device_handle * devh, int *config); int libusb_set_configuration(libusb_device_handle * devh, int configuration); int libusb_claim_interface(libusb_device_handle * devh, int interface_number); diff --git a/lib/libusb/libusb01.c b/lib/libusb/libusb01.c index 7017016693af..f246e74353a6 100644 --- a/lib/libusb/libusb01.c +++ b/lib/libusb/libusb01.c @@ -130,6 +130,8 @@ usb_get_transfer_by_ep_no(usb_dev_handle * dev, uint8_t ep_no) bufsize = 4096; } else if (speed == LIBUSB20_SPEED_SUPER) { bufsize = 65536; + } else if (speed == LIBUSB20_SPEED_SUPER_PLUS) { + bufsize = 131072; } else { bufsize = 16384; } diff --git a/lib/libusb/libusb10.c b/lib/libusb/libusb10.c index afa25eabf459..6f1ca877fc28 100644 --- a/lib/libusb/libusb10.c +++ b/lib/libusb/libusb10.c @@ -3,6 +3,8 @@ * * Copyright (c) 2009 Sylvestre Gallon. All rights reserved. * Copyright (c) 2009-2023 Hans Petter Selasky + * Copyright (c) 2024 Aymeric Wibo + * Copyright (c) 2025 ShengYi Hung * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,15 +32,18 @@ #include LIBUSB_GLOBAL_INCLUDE_FILE #else #include <assert.h> +#include <ctype.h> #include <errno.h> #include <poll.h> #include <pthread.h> #include <signal.h> +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <time.h> +#include <sys/eventfd.h> #include <sys/fcntl.h> #include <sys/ioctl.h> #include <sys/queue.h> @@ -46,6 +51,7 @@ #endif #define libusb_device_handle libusb20_device +#define LIBUSB_LOG_BUFFER_SIZE 1024 #include "libusb20.h" #include "libusb20_desc.h" @@ -80,6 +86,52 @@ static const struct libusb_version libusb_version = { .describe = "https://www.freebsd.org" }; +static const struct libusb_language_context libusb_language_ctx[] = { + { + .lang_name = "en", + .err_strs = { + [-LIBUSB_SUCCESS] = "Success", + [-LIBUSB_ERROR_IO] = "I/O error", + [-LIBUSB_ERROR_INVALID_PARAM] = "Invalid parameter", + [-LIBUSB_ERROR_ACCESS] = "Permissions error", + [-LIBUSB_ERROR_NO_DEVICE] = "No device", + [-LIBUSB_ERROR_NOT_FOUND] = "Not found", + [-LIBUSB_ERROR_BUSY] = "Device busy", + [-LIBUSB_ERROR_TIMEOUT] = "Timeout", + [-LIBUSB_ERROR_OVERFLOW] = "Overflow", + [-LIBUSB_ERROR_PIPE] = "Pipe error", + [-LIBUSB_ERROR_INTERRUPTED] = "Interrupted", + [-LIBUSB_ERROR_NO_MEM] = "Out of memory", + [-LIBUSB_ERROR_NOT_SUPPORTED] ="Not supported", + [LIBUSB_ERROR_COUNT - 1] = "Other error", + [LIBUSB_ERROR_COUNT] = "Unknown error", + } + }, + { + .lang_name = "zh", + .err_strs = { + [-LIBUSB_SUCCESS] = "成功", + [-LIBUSB_ERROR_IO] = "I/O 錯誤", + [-LIBUSB_ERROR_INVALID_PARAM] = "不合法的參數", + [-LIBUSB_ERROR_ACCESS] = "權限錯誤", + [-LIBUSB_ERROR_NO_DEVICE] = "裝置不存在", + [-LIBUSB_ERROR_NOT_FOUND] = "不存在", + [-LIBUSB_ERROR_BUSY] = "裝置忙碌中", + [-LIBUSB_ERROR_TIMEOUT] = "逾時", + [-LIBUSB_ERROR_OVERFLOW] = "溢位", + [-LIBUSB_ERROR_PIPE] = "管道錯誤", + [-LIBUSB_ERROR_INTERRUPTED] = "被中斷", + [-LIBUSB_ERROR_NO_MEM] = "記憶體不足", + [-LIBUSB_ERROR_NOT_SUPPORTED] ="不支援", + [LIBUSB_ERROR_COUNT - 1] = "其他錯誤", + [LIBUSB_ERROR_COUNT] = "未知錯誤", + } + }, +}; + +static const struct libusb_language_context *default_language_context = + &libusb_language_ctx[0]; + const struct libusb_version * libusb_get_version(void) { @@ -118,17 +170,15 @@ libusb_set_nonblocking(int f) void libusb_interrupt_event_handler(libusb_context *ctx) { - uint8_t dummy; int err; if (ctx == NULL) return; - dummy = 0; - err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); - if (err < (int)sizeof(dummy)) { + err = eventfd_write(ctx->event, 1); + if (err < 0) { /* ignore error, if any */ - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "Waking up event loop failed!"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_ERROR, "Waking up event loop failed!"); } } @@ -145,7 +195,6 @@ libusb_init_context(libusb_context **context, struct libusb_context *ctx; pthread_condattr_t attr; char *debug, *ep; - int ret; if (num_options < 0) return (LIBUSB_ERROR_INVALID_PARAM); @@ -234,19 +283,16 @@ libusb_init_context(libusb_context **context, ctx->ctx_handler = NO_THREAD; ctx->hotplug_handler = NO_THREAD; - ret = pipe(ctx->ctrl_pipe); - if (ret < 0) { + ctx->event = eventfd(0, EFD_NONBLOCK); + if (ctx->event < 0) { pthread_mutex_destroy(&ctx->ctx_lock); pthread_mutex_destroy(&ctx->hotplug_lock); pthread_cond_destroy(&ctx->ctx_cond); free(ctx); return (LIBUSB_ERROR_OTHER); } - /* set non-blocking mode on the control pipe to avoid deadlock */ - libusb_set_nonblocking(ctx->ctrl_pipe[0]); - libusb_set_nonblocking(ctx->ctrl_pipe[1]); - libusb10_add_pollfd(ctx, &ctx->ctx_poll, NULL, ctx->ctrl_pipe[0], POLLIN); + libusb10_add_pollfd(ctx, &ctx->ctx_poll, NULL, ctx->event, POLLIN); pthread_mutex_lock(&default_context_lock); if (usbi_default_context == NULL) { @@ -257,7 +303,7 @@ libusb_init_context(libusb_context **context, if (context) *context = ctx; - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_init complete"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_INFO, "libusb_init complete"); signal(SIGPIPE, SIG_IGN); @@ -296,8 +342,7 @@ libusb_exit(libusb_context *ctx) /* XXX cleanup devices */ libusb10_remove_pollfd(ctx, &ctx->ctx_poll); - close(ctx->ctrl_pipe[0]); - close(ctx->ctrl_pipe[1]); + close(ctx->event); pthread_mutex_destroy(&ctx->ctx_lock); pthread_mutex_destroy(&ctx->hotplug_lock); pthread_cond_destroy(&ctx->ctx_cond); @@ -317,9 +362,9 @@ ssize_t libusb_get_device_list(libusb_context *ctx, libusb_device ***list) { struct libusb20_backend *usb_backend; - struct libusb20_device *pdev; + struct libusb20_device *pdev, *parent_dev; struct libusb_device *dev; - int i; + int i, j, k; ctx = GET_CONTEXT(ctx); @@ -371,6 +416,9 @@ libusb_get_device_list(libusb_context *ctx, libusb_device ***list) /* set context we belong to */ dev->ctx = ctx; + /* assume we have no parent by default */ + dev->parent_dev = NULL; + /* link together the two structures */ dev->os_priv = pdev; pdev->privLuData = dev; @@ -380,6 +428,25 @@ libusb_get_device_list(libusb_context *ctx, libusb_device ***list) } (*list)[i] = NULL; + /* for each device, find its parent */ + for (j = 0; j < i; j++) { + pdev = (*list)[j]->os_priv; + + for (k = 0; k < i; k++) { + if (k == j) + continue; + + parent_dev = (*list)[k]->os_priv; + + if (parent_dev->bus_number != pdev->bus_number) + continue; + if (parent_dev->device_address == pdev->parent_address) { + (*list)[j]->parent_dev = libusb_ref_device((*list)[k]); + break; + } + } + } + libusb20_be_free(usb_backend); return (i); } @@ -451,6 +518,8 @@ libusb_get_device_speed(libusb_device *dev) return (LIBUSB_SPEED_HIGH); case LIBUSB20_SPEED_SUPER: return (LIBUSB_SPEED_SUPER); + case LIBUSB20_SPEED_SUPER_PLUS: + return (LIBUSB_SPEED_SUPER_PLUS); default: break; } @@ -544,6 +613,7 @@ libusb_unref_device(libusb_device *dev) CTX_UNLOCK(dev->ctx); if (dev->refcnt == 0) { + libusb_unref_device(dev->parent_dev); libusb20_dev_free(dev->os_priv); free(dev); } @@ -605,7 +675,7 @@ libusb_open_device_with_vid_pid(libusb_context *ctx, uint16_t vendor_id, if (ctx == NULL) return (NULL); /* be NULL safe */ - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_with_vid_pid enter"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_open_device_with_vid_pid enter"); if ((i = libusb_get_device_list(ctx, &devs)) < 0) return (NULL); @@ -629,7 +699,7 @@ libusb_open_device_with_vid_pid(libusb_context *ctx, uint16_t vendor_id, } libusb_free_device_list(devs, 1); - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open_device_with_vid_pid leave"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_open_device_with_vid_pid leave"); return (pdev); } @@ -820,6 +890,12 @@ libusb_set_interface_alt_setting(struct libusb20_device *pdev, return (err ? LIBUSB_ERROR_OTHER : 0); } +libusb_device * +libusb_get_parent(libusb_device *dev) +{ + return (dev->parent_dev); +} + static struct libusb20_transfer * libusb10_get_transfer(struct libusb20_device *pdev, uint8_t endpoint, uint8_t xfer_index) @@ -1080,6 +1156,9 @@ libusb10_get_buffsize(struct libusb20_device *pdev, libusb_transfer *xfer) case LIBUSB20_SPEED_SUPER: ret = 65536; break; + case LIBUSB20_SPEED_SUPER_PLUS: + ret = 131072; + break; default: ret = 16384; break; @@ -1507,7 +1586,7 @@ libusb_submit_transfer(struct libusb_transfer *uxfer) dev = libusb_get_device(uxfer->dev_handle); - DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer enter"); + DPRINTF(dev->ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_submit_transfer enter"); sxfer = (struct libusb_super_transfer *)( (uint8_t *)uxfer - sizeof(*sxfer)); @@ -1542,7 +1621,7 @@ libusb_submit_transfer(struct libusb_transfer *uxfer) CTX_UNLOCK(dev->ctx); - DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_submit_transfer leave %d", err); + DPRINTF(dev->ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_submit_transfer leave %d", err); return (err); } @@ -1571,7 +1650,7 @@ libusb_cancel_transfer(struct libusb_transfer *uxfer) dev = libusb_get_device(devh); - DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer enter"); + DPRINTF(dev->ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_cancel_transfer enter"); sxfer = (struct libusb_super_transfer *)( (uint8_t *)uxfer - sizeof(*sxfer)); @@ -1632,7 +1711,7 @@ libusb_cancel_transfer(struct libusb_transfer *uxfer) CTX_UNLOCK(dev->ctx); - DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer leave"); + DPRINTF(dev->ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_cancel_transfer leave"); return (retval); } @@ -1697,38 +1776,26 @@ libusb_le16_to_cpu(uint16_t x) const char * libusb_strerror(int code) { - switch (code) { - case LIBUSB_SUCCESS: - return ("Success"); - case LIBUSB_ERROR_IO: - return ("I/O error"); - case LIBUSB_ERROR_INVALID_PARAM: - return ("Invalid parameter"); - case LIBUSB_ERROR_ACCESS: - return ("Permissions error"); - case LIBUSB_ERROR_NO_DEVICE: - return ("No device"); - case LIBUSB_ERROR_NOT_FOUND: - return ("Not found"); - case LIBUSB_ERROR_BUSY: - return ("Device busy"); - case LIBUSB_ERROR_TIMEOUT: - return ("Timeout"); - case LIBUSB_ERROR_OVERFLOW: - return ("Overflow"); - case LIBUSB_ERROR_PIPE: - return ("Pipe error"); - case LIBUSB_ERROR_INTERRUPTED: - return ("Interrupted"); - case LIBUSB_ERROR_NO_MEM: - return ("Out of memory"); - case LIBUSB_ERROR_NOT_SUPPORTED: - return ("Not supported"); - case LIBUSB_ERROR_OTHER: - return ("Other error"); - default: - return ("Unknown error"); - } + int entry = -code; + + if (code == LIBUSB_ERROR_OTHER) + entry = LIBUSB_ERROR_COUNT - 1; + /* + * The libusb upstream considers all code out of range a + * LIBUSB_ERROR_OTHER. In FreeBSD, it is a special unknown error. We + * preserve the FreeBSD implementation as I think it make sense. + */ + if (entry < 0 || entry >= LIBUSB_ERROR_COUNT) + entry = LIBUSB_ERROR_COUNT; + + /* + * Fall back to English one as the translation may be unimplemented + * when adding new error code. + */ + if (default_language_context->err_strs[entry] == NULL) + return (libusb_language_ctx[0].err_strs[entry]); + + return (default_language_context->err_strs[entry]); } const char * @@ -1782,3 +1849,58 @@ libusb_has_capability(uint32_t capability) return (0); } } + +void +libusb_log_va_args(struct libusb_context *ctx, enum libusb_log_level level, + const char *fmt, ...) +{ + static const char *log_prefix[5] = { + [LIBUSB_LOG_LEVEL_ERROR] = "LIBUSB_ERROR", + [LIBUSB_LOG_LEVEL_WARNING] = "LIBUSB_WARN", + [LIBUSB_LOG_LEVEL_INFO] = "LIBUSB_INFO", + [LIBUSB_LOG_LEVEL_DEBUG] = "LIBUSB_DEBUG", + }; + + char buffer[LIBUSB_LOG_BUFFER_SIZE]; + char new_fmt[LIBUSB_LOG_BUFFER_SIZE]; + va_list args; + + ctx = GET_CONTEXT(ctx); + + if (ctx->debug < level) + return; + + va_start(args, fmt); + + snprintf(new_fmt, sizeof(new_fmt), "%s: %s\n", log_prefix[level], fmt); + vsnprintf(buffer, sizeof(buffer), new_fmt, args); + fputs(buffer, stdout); + + va_end(args); +} + +/* + * Upstream code actually recognizes the first two characters to identify a + * language. We do so to provide API compatibility with setlocale. + */ +int +libusb_setlocale(const char *locale) +{ + size_t idx; + const char *lang; + + if (locale == NULL || strlen(locale) < 2 || + (locale[2] != '\0' && strchr("-_.", locale[2]) == NULL)) + return (LIBUSB_ERROR_INVALID_PARAM); + + for (idx = 0; idx < nitems(libusb_language_ctx); ++idx) { + lang = libusb_language_ctx[idx].lang_name; + if (tolower(locale[0]) == lang[0] && + tolower(locale[1]) == lang[1]) { + default_language_context = &libusb_language_ctx[idx]; + return (LIBUSB_SUCCESS); + } + } + + return (LIBUSB_ERROR_INVALID_PARAM); +} diff --git a/lib/libusb/libusb10.h b/lib/libusb/libusb10.h index 3402e0377c92..eced364ef857 100644 --- a/lib/libusb/libusb10.h +++ b/lib/libusb/libusb10.h @@ -29,6 +29,7 @@ #define __LIBUSB10_H__ #ifndef LIBUSB_GLOBAL_INCLUDE_FILE +#include <sys/cdefs.h> #include <sys/queue.h> #include <netlink/netlink.h> #include <netlink/netlink_generic.h> @@ -46,24 +47,11 @@ #define HOTPLUG_LOCK(ctx) pthread_mutex_lock(&(ctx)->hotplug_lock) #define HOTPLUG_UNLOCK(ctx) pthread_mutex_unlock(&(ctx)->hotplug_lock) -#define DPRINTF(ctx, dbg, format, ...) do { \ - switch (dbg) { \ - case LIBUSB_DEBUG_FUNCTION: \ - if ((ctx)->debug & LIBUSB_DEBUG_FUNCTION) { \ - printf("LIBUSB_FUNCTION: " \ - format "\n", ## __VA_ARGS__); \ - } \ - break; \ - case LIBUSB_DEBUG_TRANSFER: \ - if ((ctx)->debug & LIBUSB_DEBUG_TRANSFER) { \ - printf("LIBUSB_TRANSFER: " \ - format "\n", ## __VA_ARGS__); \ - } \ - break; \ - default: \ - break; \ - } \ -} while (0) +void libusb_log_va_args(struct libusb_context *ctx, enum libusb_log_level level, + const char *fmt, ...) __printflike(3, 4); + +#define DPRINTF(ctx, dbg, format, ...) \ + libusb_log_va_args(ctx, dbg, format, ##__VA_ARGS__) /* internal structures */ @@ -106,7 +94,7 @@ typedef enum { struct libusb_context { int debug; int debug_fixed; - int ctrl_pipe[2]; + int event; int tr_done_ref; int tr_done_gen; usb_event_mode_t usb_event_mode; @@ -142,6 +130,7 @@ struct libusb_device { struct libusb_super_pollfd dev_poll; struct libusb_context *ctx; + struct libusb_device *parent_dev; TAILQ_ENTRY(libusb_device) hotplug_entry; @@ -150,6 +139,12 @@ struct libusb_device { struct libusb20_device *os_priv; }; +struct libusb_language_context { + const char *lang_name; + /* All error Plus 1 UNKNOWN */ + const char *err_strs[LIBUSB_ERROR_COUNT + 1]; +}; + extern struct libusb_context *usbi_default_context; void libusb10_add_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd, struct libusb20_device *pdev, int fd, short events); diff --git a/lib/libusb/libusb10_desc.c b/lib/libusb/libusb10_desc.c index 3e36009cbb3a..5f4c46740688 100644 --- a/lib/libusb/libusb10_desc.c +++ b/lib/libusb/libusb10_desc.c @@ -470,10 +470,11 @@ libusb_parse_bos_descriptor(const void *buf, int len, ptr->bDescriptorType = dtype; ptr->wTotalLength = ((const uint8_t *)buf)[2] | (((const uint8_t *)buf)[3] << 8); - ptr->bNumDeviceCapabilities = ((const uint8_t *)buf)[4]; + ptr->bNumDeviceCaps = ((const uint8_t *)buf)[4]; ptr->usb_2_0_ext_cap = NULL; ptr->ss_usb_cap = NULL; - ptr->dev_capability = calloc(ptr->bNumDeviceCapabilities, sizeof(void *)); + ptr->dev_capability = calloc(ptr->bNumDeviceCaps, + sizeof(void *)); if (ptr->dev_capability == NULL) { free(ptr); return (LIBUSB_ERROR_NO_MEM); @@ -485,7 +486,7 @@ libusb_parse_bos_descriptor(const void *buf, int len, if (dlen >= 3 && ptr != NULL && dtype == LIBUSB_DT_DEVICE_CAPABILITY) { - if (index != ptr->bNumDeviceCapabilities) { + if (index != ptr->bNumDeviceCaps) { ptr->dev_capability[index] = malloc(dlen); if (ptr->dev_capability[index] == NULL) { libusb_free_bos_descriptor(ptr); @@ -542,7 +543,7 @@ libusb_parse_bos_descriptor(const void *buf, int len, } if (ptr != NULL) { - ptr->bNumDeviceCapabilities = index; + ptr->bNumDeviceCaps = index; return (0); /* success */ } @@ -557,7 +558,7 @@ libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos) if (bos == NULL) return; - for (i = 0; i != bos->bNumDeviceCapabilities; i++) + for (i = 0; i != bos->bNumDeviceCaps; i++) free(bos->dev_capability[i]); free(bos->dev_capability); free(bos); diff --git a/lib/libusb/libusb10_hotplug.c b/lib/libusb/libusb10_hotplug.c index b7573bf916ec..369539d4512e 100644 --- a/lib/libusb/libusb10_hotplug.c +++ b/lib/libusb/libusb10_hotplug.c @@ -73,7 +73,7 @@ netlink_init(libusb_context *ctx) if (modfind("nlsysevent") < 0) return (false); if (!snl_init(&ctx->ss, NETLINK_GENERIC) || (group = - snl_get_genl_mcast_group(&ctx->ss, "nlsysevent", "ACPI", NULL)) == 0) + snl_get_genl_mcast_group(&ctx->ss, "nlsysevent", "USB", NULL)) == 0) return (false); if (setsockopt(ctx->ss.fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group, @@ -140,6 +140,8 @@ verify_event_validity(libusb_context *ctx) return (valid_event); return (invalid_event); } + if (errno == EBADF) + return (broken_event); return (invalid_event); } else if (ctx->usb_event_mode == usb_event_devd) { char buf[DEVCTL_MAXBUF]; @@ -407,6 +409,7 @@ void libusb_hotplug_deregister_callback(libusb_context *ctx, HOTPLUG_LOCK(ctx); TAILQ_REMOVE(&ctx->hotplug_cbh, handle, entry); + libusb_interrupt_event_handler(ctx); HOTPLUG_UNLOCK(ctx); free(handle); diff --git a/lib/libusb/libusb10_io.c b/lib/libusb/libusb10_io.c index 59bac60c4672..dd541b09caa6 100644 --- a/lib/libusb/libusb10_io.c +++ b/lib/libusb/libusb10_io.c @@ -36,6 +36,7 @@ #include <string.h> #include <time.h> #include <unistd.h> +#include <sys/eventfd.h> #include <sys/queue.h> #include <sys/endian.h> #endif @@ -107,7 +108,7 @@ libusb10_handle_events_sub(struct libusb_context *ctx, struct timeval *tv) int i; int err; - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb10_handle_events_sub enter"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb10_handle_events_sub enter"); nfds = 0; i = 0; @@ -187,10 +188,8 @@ libusb10_handle_events_sub(struct libusb_context *ctx, struct timeval *tv) CTX_LOCK(ctx); } else { - uint8_t dummy; + eventfd_read(fds[i].fd, &(eventfd_t){0}); - while (read(fds[i].fd, &dummy, 1) == 1) - ; } } @@ -231,6 +230,7 @@ do_done: /* Wakeup other waiters */ pthread_cond_broadcast(&ctx->ctx_cond); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb10_handle_events_sub complete"); return (err); } @@ -314,7 +314,7 @@ libusb_wait_for_event(libusb_context *ctx, struct timeval *tv) int err; ctx = GET_CONTEXT(ctx); - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_wait_for_event enter"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_wait_for_event enter"); if (tv == NULL) { pthread_cond_wait(&ctx->ctx_cond, @@ -358,7 +358,7 @@ libusb_handle_events_timeout_completed(libusb_context *ctx, ctx = GET_CONTEXT(ctx); - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout_completed enter"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_handle_events_timeout_completed enter"); libusb_lock_events(ctx); @@ -374,7 +374,7 @@ libusb_handle_events_timeout_completed(libusb_context *ctx, libusb_unlock_events(ctx); - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout_completed exit"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_handle_events_timeout_completed exit"); return (err); } @@ -523,7 +523,7 @@ libusb10_do_transfer_cb(struct libusb_transfer *transfer) ctx = libusb10_get_context_by_device_handle(transfer->dev_handle); - DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "sync I/O done"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "sync I/O done"); pdone = transfer->user_data; *pdone = 1; @@ -613,12 +613,12 @@ libusb_bulk_transfer(libusb_device_handle *devh, ctx = libusb10_get_context_by_device_handle(devh); - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer enter"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_bulk_transfer enter"); ret = libusb10_do_transfer(devh, endpoint, data, length, transferred, timeout, LIBUSB_TRANSFER_TYPE_BULK); - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer leave"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_bulk_transfer leave"); return (ret); } @@ -632,12 +632,12 @@ libusb_interrupt_transfer(libusb_device_handle *devh, ctx = libusb10_get_context_by_device_handle(devh); - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer enter"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_interrupt_transfer enter"); ret = libusb10_do_transfer(devh, endpoint, data, length, transferred, timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT); - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer leave"); + DPRINTF(ctx, LIBUSB_LOG_LEVEL_DEBUG, "libusb_interrupt_transfer leave"); return (ret); } diff --git a/lib/libusb/libusb20.3 b/lib/libusb/libusb20.3 index 1d07db8f32a4..7854b0f8ed7e 100644 --- a/lib/libusb/libusb20.3 +++ b/lib/libusb/libusb20.3 @@ -858,6 +858,7 @@ returns the current speed of the given USB device. .It LIBUSB20_SPEED_HIGH .It LIBUSB20_SPEED_VARIABLE .It LIBUSB20_SPEED_SUPER +.It LIBUSB20_SPEED_SUPER_PLUS .El . .Pp diff --git a/lib/libusb/libusb20.h b/lib/libusb/libusb20.h index 7bca2f7508c7..c132c58a9f69 100644 --- a/lib/libusb/libusb20.h +++ b/lib/libusb/libusb20.h @@ -159,6 +159,7 @@ enum { LIBUSB20_SPEED_HIGH, LIBUSB20_SPEED_VARIABLE, LIBUSB20_SPEED_SUPER, + LIBUSB20_SPEED_SUPER_PLUS, }; /** \ingroup misc diff --git a/lib/libusb/libusb20_desc.h b/lib/libusb/libusb20_desc.h index 017148a34b1c..0f7c9294ebc8 100644 --- a/lib/libusb/libusb20_desc.h +++ b/lib/libusb/libusb20_desc.h @@ -298,11 +298,15 @@ LIBUSB20_MAKE_STRUCT(LIBUSB20_USB_20_DEVCAP_DESC); LIBUSB20_MAKE_STRUCT(LIBUSB20_SS_USB_DEVCAP_DESC); +#ifndef bNumDeviceCapabilities +#define bNumDeviceCapabilities bNumDeviceCaps +#endif + #define LIBUSB20_BOS_DESCRIPTOR(m,n) \ m(n, UINT8_T, bLength, ) \ m(n, UINT8_T, bDescriptorType, ) \ m(n, UINT16_T, wTotalLength, ) \ - m(n, UINT8_T, bNumDeviceCapabilities, ) \ + m(n, UINT8_T, bNumDeviceCaps, ) \ LIBUSB20_MAKE_STRUCT(LIBUSB20_BOS_DESCRIPTOR); diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile index 8178d33b7ba8..0639745d08fc 100644 --- a/lib/libutil/Makefile +++ b/lib/libutil/Makefile @@ -16,9 +16,10 @@ SRCS= _secure_path.c auth.c cpuset.c expand_number.c flopen.c fparseln.c \ kinfo_getvmobject.c kld.c \ login_auth.c login_cap.c \ login_class.c login_crypt.c login_ok.c login_times.c login_tty.c \ + mntopts.c \ pidfile.c property.c pty.c pw_scan.c pw_util.c quotafile.c \ realhostname.c stub.c trimdomain.c uucplock.c -INCS= libutil.h login_cap.h +INCS= libutil.h login_cap.h mntopts.h CFLAGS+= -DNO__SCCSID @@ -32,7 +33,8 @@ MAN+= cpuset.3 expand_number.3 flopen.3 fparseln.3 ftime.3 getlocalbase.3 \ hexdump.3 humanize_number.3 kinfo_getallproc.3 kinfo_getfile.3 \ kinfo_getproc.3 kinfo_getvmmap.3 kinfo_getvmobject.3 kld.3 \ login_auth.3 login_cap.3 \ - login_class.3 login_ok.3 login_times.3 login_tty.3 pidfile.3 \ + login_class.3 login_ok.3 login_times.3 login_tty.3 mntopts.3 \ + pidfile.3 \ property.3 pty.3 quotafile.3 realhostname.3 realhostname_sa.3 \ _secure_path.3 trimdomain.3 uucplock.3 pw_util.3 MAN+= login.conf.5 @@ -54,6 +56,14 @@ MLINKS+=login_times.3 in_lt.3 login_times.3 in_ltm.3 \ login_times.3 in_ltms.3 \ login_times.3 in_lts.3 \ login_times.3 parse_lt.3 +MLINKS+=mntopts.3 getmntopts.3 \ + mntopts.3 getmntpoint.3 \ + mntopts.3 chkdoreload.3 \ + mntopts.3 build_iovec.3 \ + mntopts.3 build_iovec_argf.3 \ + mntopts.3 free_iovec.3 \ + mntopts.3 checkpath.3 \ + mntopts.3 rmslashes.3 MLINKS+=pidfile.3 pidfile_close.3 \ pidfile.3 pidfile_fileno.3 \ pidfile.3 pidfile_open.3 \ diff --git a/lib/libutil/kinfo_getfile.c b/lib/libutil/kinfo_getfile.c index f1441bdf771a..345da657df81 100644 --- a/lib/libutil/kinfo_getfile.c +++ b/lib/libutil/kinfo_getfile.c @@ -27,6 +27,10 @@ kinfo_getfile(pid_t pid, int *cntp) error = sysctl(mib, nitems(mib), NULL, &len, NULL, 0); if (error) return (NULL); + /* + * Add extra space as the table may grow between requesting the size + * and fetching the data. + */ len = len * 4 / 3; buf = malloc(len); if (buf == NULL) diff --git a/lib/libutil/mntopts.3 b/lib/libutil/mntopts.3 new file mode 100644 index 000000000000..35f6d476fcec --- /dev/null +++ b/lib/libutil/mntopts.3 @@ -0,0 +1,377 @@ +.\" Copyright (c) 2023 Marshall Kirk McKusick +.\" Copyright (c) 1994 The Regents of the University of California. +.\" +.\" 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 AUTHORS AND CONTRIBUTORS ``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 AUTHORS OR CONTRIBUTORS 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. +.\" +.Dd April 21, 2025 +.Dt MNTOPTS 3 +.Os +.Sh NAME +.Nm getmntopts , +.Nm getmntpoint , +.Nm chkdoreload , +.Nm build_iovec , +.Nm build_iovec_argf , +.Nm free_iovec , +.Nm checkpath , +.Nm rmslashes +.Nd "mount point operations" +.Sh LIBRARY +.Lb libutil +.Sh SYNOPSIS +.In mntopts.h +.Ft void +.Fo getmntopts +.Fa "const char *options" "const struct mntopt *mopts" +.Fa "int *flagp" "int *altflagp" +.Fc +.Ft struct statfs * +.Fn getmntpoint "const char *name" +.Ft int +.Fo chkdoreload +.Fa "struct statfs *mntp" +.Fa "void (*prtmsg)(const char *fmt, ...)" +.Fc +.Ft void +.Fo build_iovec +.Fa "struct iovec **iov" "int *iovlen" "const char *name" "void *val" +.Fa "size_t len" +.Fc +.Ft void +.Fo build_iovec_argf +.Fa "struct iovec **iov" "int *iovlen" "const char *name" +.Fa "const char *fmt" "..." +.Fc +.Ft void +.Fn free_iovec "struct iovec **iov" "int *iovlen" +.Ft int +.Fn checkpath "const char *path" "char *resolved" +.Ft void +.Fn rmslashes "char *rrpin" "char *rrpout" +.Sh DESCRIPTION +The +.Nm mntopts +functions support operations associated with a mount point. +.Pp +The +.Fn getmntopts +function takes a comma separated option list and a list +of valid option names, and computes the bitmask +corresponding to the requested set of options. +.Pp +The string +.Fa options +is broken down into a sequence of comma separated tokens. +Each token is looked up in the table described by +.Fa mopts +and the bits in +the word referenced by either +.Fa flagp +or +.Fa altflagp +(depending on the +.Va m_altloc +field of the option's table entry) +are updated. +The flag words are not initialized by +.Fn getmntopts . +The table, +.Fa mopts , +has the following format: +.Bd -literal +struct mntopt { + char *m_option; /* option name */ + int m_inverse; /* is this a negative option, e.g., "dev" */ + int m_flag; /* bit to set, e.g., MNT_RDONLY */ + int m_altloc; /* non-zero to use altflagp rather than flagp */ +}; +.Ed +.Pp +The members of this structure are: +.Bl -tag -width m_inverse +.It Va m_option +the option name, +for example +.Dq Li suid . +.It Va m_inverse +tells +.Fn getmntopts +that the name has the inverse meaning of the +bit. +For example, +.Dq Li suid +is the string, whereas the +mount flag is +.Dv MNT_NOSUID . +In this case, the sense of the string and the flag +are inverted, so the +.Va m_inverse +flag should be set. +.It Va m_flag +the value of the bit to be set or cleared in +the flag word when the option is recognized. +The bit is set when the option is discovered, +but cleared if the option name was preceded +by the letters +.Dq Li no . +The +.Va m_inverse +flag causes these two operations to be reversed. +.It Va m_altloc +the bit should be set or cleared in +.Fa altflagp +rather than +.Fa flagp . +.El +.Pp +Each of the user visible +.Dv MNT_ +flags has a corresponding +.Dv MOPT_ +macro which defines an appropriate +.Vt "struct mntopt" +entry. +To simplify the program interface and ensure consistency across all +programs, a general purpose macro, +.Dv MOPT_STDOPTS , +is defined which +contains an entry for all the generic VFS options. +In addition, the macros +.Dv MOPT_FORCE +and +.Dv MOPT_UPDATE +exist to enable the +.Dv MNT_FORCE +and +.Dv MNT_UPDATE +flags to be set. +Finally, the table must be terminated by an entry with a +.Dv NULL +first element. +.Pp +The +.Fn getmntpoint +function takes the pathname of a possible mount point +or of a device (with or without +.Pa /dev/ +prepended to it). +If the pathname is a directory or a file, +.Fn getmntpoint +checks to see if the mount point currently has a filesystem +mounted on it. +If the pathname is a device, +.Fn getmntpoint +checks to see if it is currently mounted. +If there is an associated mount, a pointer to a +.Vt "struct statfs" +is returned. +The returned result is stored in a static buffer that is over-written +each time the +.Fn getmntpoint +function or the +.Xr getmntinfo 3 +library routine is called. +If no mount is found, NULL is returned. +.Pp +The +.Fn chkdoreload +function takes a pointer to a +.Vt "struct statfs" . +If the filesystem associated with the mount point is mounted read-only, +.Fn chkdoreload +requests the filesystem to reload all of its metadata from its backing store. +The second parameter is the function to call to print an error message +if the reload fails. +If no error message is desired, a +.Dv NULL +can be passed as the second argument. +The +.Fn chkdoreload +function returns zero on success or non-zero on failure. +.Pp +The +.Fn build_iovec +function adds a parameter to a list of parameters to be passed to the +.Xr nmount 2 +system call. +The parameter list is built up in +.Va iov +and its length is kept in +.Va iovlen . +Before the first call to +.Fn build_iovec , +.Va iov +should be set to +.Dv NULL +and +.Va iovlen +should be set to 0. +The parameter name is passed in +.Va name . +The value of the parameter name is pointed to by +.Va val . +The size of the value is passed in +.Va len . +If the value is a string, a +.Va len +of -1 is passed to indicate that the length should be determined using +.Xr strlen 3 . +If the parameter has no value, +.Va name +should be +.Dv NULL +and +.Va len +should be 0. +.Pp +The +.Fn build_iovec_argf +function adds a formatted parameter to a list of parameters to be passed +to the +.Xr nmount 2 +system call. +The parameter list is built up in +.Va iov +and its length is kept in +.Va iovlen . +Before the first call to +.Fn build_iovec_argf , +.Va iov +should be set to +.Dv NULL +and +.Va iovlen +should be set to 0. +The parameter name is passed in +.Va name . +The value of the parameter name is described by a format string pointed to by +.Va fmt . +If the parameter has no value, +.Va name +should be +.Dv NULL . +.Pp +The +.Fn free_iovec +function frees the memory in the +.Va iov +vector of the length specified in +.Va iovlen +that was previously allocated by the +.Fn build_iovec +and / or +.Fn build_iovec_argf +functions. +The +.Va iov +is set to +.Dv NULL +and the +.Va iovlen +is set to 0 to indicate that the space has been freed. +.Pp +The +.Fn checkpath +function uses +.Xr realpath 3 +to verify that its +.Va path +argument is valid and references a directory. +The +.Fn checkpath +function returns zero on success or non-zero on failure. +.Pp +The +.Fn rmslashes +function removes all double slashes and trailing slashes from its +.Va rrpin +pathname parameter and returns the resulting pathname in its +.Va rrpout +parameter. +.Sh EXAMPLES +Most commands will use the standard option set. +Local file systems which support the +.Dv MNT_UPDATE +flag, would also have an +.Dv MOPT_UPDATE +entry. +This can be declared and used as follows: +.Bd -literal +#include <mntopts.h> + +struct mntopt mopts[] = { + MOPT_STDOPTS, + MOPT_UPDATE, + { NULL } +}; + + ... + mntflags = mntaltflags = 0; + ... + getmntopts(options, mopts, &mntflags, &mntaltflags); + ... +.Ed +.Sh DIAGNOSTICS +If the external integer variable +.Va getmnt_silent +is zero, then the +.Fn getmntopts +function displays an error message and exits if an +unrecognized option is encountered. +Otherwise unrecognized options are silently ignored. +By default +.Va getmnt_silent +is zero. +.Sh SEE ALSO +.Xr err 3 , +.Xr mount 8 , +.Xr nmount 8 +.Sh HISTORY +The +.Fn getmntopts +function appeared in +.Bx 4.4 . +The +.Fn build_iovec , +.Fn build_iovec_argf , +.Fn free_iovec , +.Fn checkpath , +and +.Fn rmslashes +functions were added with +.Xr nmount 8 +in +.Fx 5.0 . +The +.Fn getmntpoint +and +.Fn chkdoreload +functions were added in +.Fx 13.2 . +.Pp +Historically, these functions were found in getmntopts.c in the sources for the +.Xr mount 8 +program. +As of +.Fx 15.0 +they are part of +.Nm libutil . diff --git a/lib/libutil/mntopts.c b/lib/libutil/mntopts.c new file mode 100644 index 000000000000..1d9347e3108a --- /dev/null +++ b/lib/libutil/mntopts.c @@ -0,0 +1,300 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1994 + * The Regents of the University of California. 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/param.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <sys/uio.h> + +#include <err.h> +#include <errno.h> +#include <mntopts.h> +#include <paths.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int getmnt_silent = 0; + +void +getmntopts(const char *options, const struct mntopt *m0, int *flagp, + int *altflagp) +{ + const struct mntopt *m; + int negative, len; + char *opt, *optbuf, *p; + int *thisflagp; + + /* Copy option string, since it is about to be torn asunder... */ + if ((optbuf = strdup(options)) == NULL) + err(1, NULL); + + for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) { + /* Check for "no" prefix. */ + if (opt[0] == 'n' && opt[1] == 'o') { + negative = 1; + opt += 2; + } else + negative = 0; + + /* + * for options with assignments in them (ie. quotas) + * ignore the assignment as it's handled elsewhere + */ + p = strchr(opt, '='); + if (p != NULL) + *++p = '\0'; + + /* Scan option table. */ + for (m = m0; m->m_option != NULL; ++m) { + len = strlen(m->m_option); + if (strncasecmp(opt, m->m_option, len) == 0) + if (opt[len] == '\0' || opt[len] == '=') + break; + } + + /* Save flag, or fail if option is not recognized. */ + if (m->m_option) { + thisflagp = m->m_altloc ? altflagp : flagp; + if (negative == m->m_inverse) + *thisflagp |= m->m_flag; + else + *thisflagp &= ~m->m_flag; + } else if (!getmnt_silent) { + errx(1, "-o %s: option not supported", opt); + } + } + + free(optbuf); +} + +void +rmslashes(char *rrpin, char *rrpout) +{ + char *rrpoutstart; + + *rrpout = *rrpin; + for (rrpoutstart = rrpout; *rrpin != '\0'; *rrpout++ = *rrpin++) { + + /* skip all double slashes */ + while (*rrpin == '/' && *(rrpin + 1) == '/') + rrpin++; + } + + /* remove trailing slash if necessary */ + if (rrpout - rrpoutstart > 1 && *(rrpout - 1) == '/') + *(rrpout - 1) = '\0'; + else + *rrpout = '\0'; +} + +int +checkpath(const char *path, char *resolved) +{ + struct stat sb; + + if (realpath(path, resolved) == NULL || stat(resolved, &sb) != 0) + return (1); + if (!S_ISDIR(sb.st_mode)) { + errno = ENOTDIR; + return (1); + } + return (0); +} + +int +checkpath_allow_file(const char *path, char *resolved) +{ + struct stat sb; + + if (realpath(path, resolved) == NULL || stat(resolved, &sb) != 0) + return (1); + if (!S_ISDIR(sb.st_mode) && !S_ISREG(sb.st_mode)) { + errno = ENOTDIR; + return (1); + } + return (0); +} + +/* + * Get the mount point information for name. Name may be mount point name + * or device name (with or without /dev/ preprended). + */ +struct statfs * +getmntpoint(const char *name) +{ + struct stat devstat, mntdevstat; + char device[sizeof(_PATH_DEV) - 1 + MNAMELEN]; + char *ddevname; + struct statfs *mntbuf, *statfsp; + int i, mntsize, isdev; + u_long len; + + if (stat(name, &devstat) != 0) + return (NULL); + if (S_ISCHR(devstat.st_mode) || S_ISBLK(devstat.st_mode)) + isdev = 1; + else + isdev = 0; + mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); + for (i = 0; i < mntsize; i++) { + statfsp = &mntbuf[i]; + if (isdev == 0) { + if (strcmp(name, statfsp->f_mntonname)) + continue; + return (statfsp); + } + ddevname = statfsp->f_mntfromname; + if (*ddevname != '/') { + if ((len = strlen(_PATH_DEV) + strlen(ddevname) + 1) > + sizeof(statfsp->f_mntfromname) || + len > sizeof(device)) + continue; + strncpy(device, _PATH_DEV, len); + strncat(device, ddevname, len); + if (stat(device, &mntdevstat) == 0) + strncpy(statfsp->f_mntfromname, device, len); + } + if (stat(ddevname, &mntdevstat) == 0 && + mntdevstat.st_rdev == devstat.st_rdev) + return (statfsp); + } + return (NULL); +} + +/* + * If possible reload a mounted filesystem. + * When prtmsg != NULL print a warning if a reload is attempted, but fails. + * Return 0 on success, 1 on failure. + */ +int +chkdoreload(struct statfs *mntp, + void (*prtmsg)(const char *, ...) __printflike(1,2)) +{ + struct iovec *iov; + int iovlen, error; + char errmsg[255]; + + /* + * If the filesystem is not mounted it does not need to be reloaded. + * If it is mounted for writing, then it could not have been opened + * for writing by a utility, so does not need to be reloaded. + */ + if (mntp == NULL || (mntp->f_flags & MNT_RDONLY) == 0) + return (0); + + /* + * We modified a mounted file system. Do a mount update on + * it so we can continue using it as safely as possible. + */ + iov = NULL; + iovlen = 0; + errmsg[0] = '\0'; + build_iovec(&iov, &iovlen, "fstype", __DECONST(void *, "ffs"), 4); + build_iovec(&iov, &iovlen, "from", mntp->f_mntfromname, (size_t)-1); + build_iovec(&iov, &iovlen, "fspath", mntp->f_mntonname, (size_t)-1); + build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); + build_iovec(&iov, &iovlen, "update", NULL, 0); + build_iovec(&iov, &iovlen, "reload", NULL, 0); + /* + * XX: We need the following line until we clean up + * nmount parsing of root mounts and NFS root mounts. + */ + build_iovec(&iov, &iovlen, "ro", NULL, 0); + error = nmount(iov, iovlen, mntp->f_flags); + free_iovec(&iov, &iovlen); + if (error == 0) + return (0); + if (prtmsg != NULL) + prtmsg("mount reload of '%s' failed: %s %s\n\n", + mntp->f_mntonname, strerror(errno), errmsg); + return (1); +} + +void +build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val, + size_t len) +{ + int i; + + if (*iovlen < 0) + return; + i = *iovlen; + *iov = realloc(*iov, sizeof **iov * (i + 2)); + if (*iov == NULL) { + *iovlen = -1; + return; + } + (*iov)[i].iov_base = strdup(name); + (*iov)[i].iov_len = strlen(name) + 1; + i++; + (*iov)[i].iov_base = val; + if (len == (size_t)-1) { + if (val != NULL) + len = strlen(val) + 1; + else + len = 0; + } + (*iov)[i].iov_len = (int)len; + *iovlen = ++i; +} + +/* + * This function is needed for compatibility with parameters + * which used to use the mount_argf() command for the old mount() syscall. + */ +void +build_iovec_argf(struct iovec **iov, int *iovlen, const char *name, + const char *fmt, ...) +{ + va_list ap; + char val[255] = { 0 }; + + va_start(ap, fmt); + vsnprintf(val, sizeof(val), fmt, ap); + va_end(ap); + build_iovec(iov, iovlen, name, strdup(val), (size_t)-1); +} + +/* + * Free the iovec and reset to NULL with zero length. Useful for calling + * nmount in a loop. + */ +void +free_iovec(struct iovec **iov, int *iovlen) +{ + int i; + + for (i = 0; i < *iovlen; i += 2) + free((*iov)[i].iov_base); + free(*iov); +} diff --git a/lib/libutil/mntopts.h b/lib/libutil/mntopts.h new file mode 100644 index 000000000000..0027b8ca7155 --- /dev/null +++ b/lib/libutil/mntopts.h @@ -0,0 +1,114 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1994 + * The Regents of the University of California. 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + */ + +#ifndef _MNTOPTS_H_ +#define _MNTOPTS_H_ + +struct mntopt { + const char *m_option; /* option name */ + int m_inverse; /* if a negative option, e.g. "atime" */ + long long m_flag; /* bit to set, e.g. MNT_RDONLY */ + int m_altloc; /* 1 => set bit in altflags */ +}; + +/* User-visible MNT_ flags. */ +#define MOPT_ASYNC { "async", 0, MNT_ASYNC, 0 } +#define MOPT_NOATIME { "atime", 1, MNT_NOATIME, 0 } +#define MOPT_NOEXEC { "exec", 1, MNT_NOEXEC, 0 } +#define MOPT_NOSUID { "suid", 1, MNT_NOSUID, 0 } +#define MOPT_NOSYMFOLLOW { "symfollow", 1, MNT_NOSYMFOLLOW, 0 } +#define MOPT_RDONLY { "rdonly", 0, MNT_RDONLY, 0 } +#define MOPT_SYNC { "sync", 0, MNT_SYNCHRONOUS, 0 } +#define MOPT_UNION { "union", 0, MNT_UNION, 0 } +#define MOPT_USERQUOTA { "userquota", 0, 0, 0 } +#define MOPT_GROUPQUOTA { "groupquota", 0, 0, 0 } +#define MOPT_NOCLUSTERR { "clusterr", 1, MNT_NOCLUSTERR, 0 } +#define MOPT_NOCLUSTERW { "clusterw", 1, MNT_NOCLUSTERW, 0 } +#define MOPT_SUIDDIR { "suiddir", 0, MNT_SUIDDIR, 0 } +#define MOPT_SNAPSHOT { "snapshot", 0, MNT_SNAPSHOT, 0 } +#define MOPT_MULTILABEL { "multilabel", 0, MNT_MULTILABEL, 0 } +#define MOPT_ACLS { "acls", 0, MNT_ACLS, 0 } +#define MOPT_NFS4ACLS { "nfsv4acls", 0, MNT_NFS4ACLS, 0 } +#define MOPT_AUTOMOUNTED { "automounted",0, MNT_AUTOMOUNTED, 0 } +#define MOPT_UNTRUSTED { "untrusted", 0, MNT_UNTRUSTED, 0 } + +/* Control flags. */ +#define MOPT_FORCE { "force", 0, MNT_FORCE, 0 } +#define MOPT_UPDATE { "update", 0, MNT_UPDATE, 0 } +#define MOPT_RO { "ro", 0, MNT_RDONLY, 0 } +#define MOPT_RW { "rw", 1, MNT_RDONLY, 0 } +#define MOPT_NOCOVER { "cover", 1, MNT_NOCOVER, 0 } +#define MOPT_EMPTYDIR { "emptydir", 0, MNT_EMPTYDIR, 0 } +/* This is parsed by mount(8), but is ignored by specific mount_*(8)s. */ +#define MOPT_AUTO { "auto", 0, 0, 0 } + +/* A handy macro as terminator of MNT_ array. */ +#define MOPT_END { NULL, 0, 0, 0 } + +#define MOPT_FSTAB_COMPAT \ + MOPT_RO, \ + MOPT_RW, \ + MOPT_AUTO + +/* Standard options which all mounts can understand. */ +#define MOPT_STDOPTS \ + MOPT_USERQUOTA, \ + MOPT_GROUPQUOTA, \ + MOPT_FSTAB_COMPAT, \ + MOPT_NOATIME, \ + MOPT_NOEXEC, \ + MOPT_SUIDDIR, /* must be before MOPT_NOSUID */ \ + MOPT_NOSUID, \ + MOPT_NOSYMFOLLOW, \ + MOPT_RDONLY, \ + MOPT_UNION, \ + MOPT_NOCLUSTERR, \ + MOPT_NOCLUSTERW, \ + MOPT_MULTILABEL, \ + MOPT_ACLS, \ + MOPT_NFS4ACLS, \ + MOPT_AUTOMOUNTED, \ + MOPT_UNTRUSTED, \ + MOPT_NOCOVER, \ + MOPT_EMPTYDIR + +void getmntopts(const char *, const struct mntopt *, int *, int *); +void rmslashes(char *, char *); +int checkpath(const char *, char resolved_path[]); +int checkpath_allow_file(const char *, char resolved_path[]); +struct statfs *getmntpoint(const char *); +int chkdoreload(struct statfs *, void (*)(const char *, ...) __printflike(1,2)); +extern int getmnt_silent; +void build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val, size_t len); +void build_iovec_argf(struct iovec **iov, int *iovlen, const char *name, const char *fmt, ...); +void free_iovec(struct iovec **iovec, int *iovlen); + +#endif /* !_MNTOPTS_H_ */ diff --git a/lib/libyaml/Makefile b/lib/libyaml/Makefile new file mode 100644 index 000000000000..6acd34f178a9 --- /dev/null +++ b/lib/libyaml/Makefile @@ -0,0 +1,29 @@ +LIBYAML_DIR= ${SRCTOP}/contrib/libyaml + +PACKAGE=lib${LIB} +LIB= yaml +PRIVATELIB= true +SHLIB_MAJOR= 1 +SRCS= api.c \ + dumper.c \ + emitter.c \ + loader.c \ + parser.c \ + reader.c \ + scanner.c \ + writer.c + +.PATH: ${LIBYAML_DIR}/src \ + ${LIBYAML_DIR}/include + +INCS= yaml.h + +WARNS?= 1 +CFLAGS+= -I${LIBYAML_DIR}/include \ + -I${LIBYAML_DIR}/src \ + -DYAML_VERSION_STRING=\"0.2.5\" \ + -DYAML_VERSION_MAJOR=0 \ + -DYAML_VERSION_MINOR=2 \ + -DYAML_VERSION_PATCH=5 + +.include <bsd.lib.mk> diff --git a/lib/msun/aarch64/fenv.h b/lib/msun/aarch64/fenv.h index 2148a68b053b..a435a9de5223 100644 --- a/lib/msun/aarch64/fenv.h +++ b/lib/msun/aarch64/fenv.h @@ -31,6 +31,7 @@ #ifndef _FENV_H_ #define _FENV_H_ +#include <sys/cdefs.h> #include <sys/_types.h> #ifndef __fenv_static diff --git a/lib/msun/arm/fenv.h b/lib/msun/arm/fenv.h index 5dded5d744fd..e8a30fcf496f 100644 --- a/lib/msun/arm/fenv.h +++ b/lib/msun/arm/fenv.h @@ -29,6 +29,7 @@ #ifndef _FENV_H_ #define _FENV_H_ +#include <sys/cdefs.h> #include <sys/_types.h> #ifndef __fenv_static diff --git a/lib/msun/riscv/fenv.h b/lib/msun/riscv/fenv.h index cc50f0659248..fd50463d479e 100644 --- a/lib/msun/riscv/fenv.h +++ b/lib/msun/riscv/fenv.h @@ -36,6 +36,7 @@ #ifndef _FENV_H_ #define _FENV_H_ +#include <sys/cdefs.h> #include <sys/_types.h> #ifndef __fenv_static diff --git a/lib/msun/src/math.h b/lib/msun/src/math.h index be7b86144738..aecc652ea08a 100644 --- a/lib/msun/src/math.h +++ b/lib/msun/src/math.h @@ -15,6 +15,7 @@ #ifndef _MATH_H_ #define _MATH_H_ +#include <sys/cdefs.h> #include <sys/_types.h> #include <machine/_limits.h> diff --git a/lib/msun/src/s_cbrt.c b/lib/msun/src/s_cbrt.c index 6bf84243adcd..568a36545216 100644 --- a/lib/msun/src/s_cbrt.c +++ b/lib/msun/src/s_cbrt.c @@ -90,7 +90,7 @@ cbrt(double x) * the result is larger in magnitude than cbrt(x) but not much more than * 2 23-bit ulps larger). With rounding towards zero, the error bound * would be ~5/6 instead of ~4/6. With a maximum error of 2 23-bit ulps - * in the rounded t, the infinite-precision error in the Newton + * in the rounded t, the infinite-precision error in the Halley * approximation barely affects third digit in the final error * 0.667; the error in the rounded t can be up to about 3 23-bit ulps * before the final error is larger than 0.667 ulps. @@ -99,7 +99,7 @@ cbrt(double x) u.bits=(u.bits+0x80000000)&0xffffffffc0000000ULL; t=u.value; - /* one step Newton iteration to 53 bits with error < 0.667 ulps */ + /* one step Halley iteration to 53 bits with error < 0.667 ulps */ s=t*t; /* t*t is exact */ r=x/s; /* error <= 0.5 ulps; |r| < |t| */ w=t+t; /* t+t is exact */ diff --git a/lib/msun/src/s_cbrtf.c b/lib/msun/src/s_cbrtf.c index a225d3edb982..c69e0fa5be12 100644 --- a/lib/msun/src/s_cbrtf.c +++ b/lib/msun/src/s_cbrtf.c @@ -50,7 +50,7 @@ cbrtf(float x) SET_FLOAT_WORD(t,sign|(hx/3+B1)); /* - * First step Newton iteration (solving t*t-x/t == 0) to 16 bits. In + * First step Halley iteration (solving t*t-x/t == 0) to 16 bits. In * double precision so that its terms can be arranged for efficiency * without causing overflow or underflow. */ @@ -59,7 +59,7 @@ cbrtf(float x) T=T*((double)x+x+r)/(x+r+r); /* - * Second step Newton iteration to 47 bits. In double precision for + * Second step Halley iteration to 47 bits. In double precision for * efficiency and accuracy. */ r=T*T*T; diff --git a/lib/msun/src/s_cbrtl.c b/lib/msun/src/s_cbrtl.c index f1950e2d4cef..ff527cc5e5e7 100644 --- a/lib/msun/src/s_cbrtl.c +++ b/lib/msun/src/s_cbrtl.c @@ -126,7 +126,7 @@ cbrtl(long double x) #endif /* - * Final step Newton iteration to 64 or 113 bits with + * Final step Halley iteration to 64 or 113 bits with * error < 0.667 ulps */ s=t*t; /* t*t is exact */ diff --git a/lib/ncurses/ncurses/Makefile b/lib/ncurses/ncurses/Makefile index 254f05a1e740..512a452ad6d0 100644 --- a/lib/ncurses/ncurses/Makefile +++ b/lib/ncurses/ncurses/Makefile @@ -8,8 +8,6 @@ SHLIBDIR?= /lib LIB= ncursesw SHLIB_MAJOR= 9 -NO_LINT= - GENSRCS= \ expanded.c \ lib_gen.c diff --git a/lib/ncurses/tinfo/Makefile b/lib/ncurses/tinfo/Makefile index e11d0e15245e..920bd6e5559c 100644 --- a/lib/ncurses/tinfo/Makefile +++ b/lib/ncurses/tinfo/Makefile @@ -8,8 +8,6 @@ SHLIBDIR?= /lib LIB= tinfow SHLIB_MAJOR= 9 -NO_LINT= - NCURSES_MAJOR!= egrep 'NCURSES_MAJOR[ ]*=' ${NCURSES_DIR}/dist.mk | sed -e 's%^[^0-9]*%%' NCURSES_MINOR!= egrep 'NCURSES_MINOR[ ]*=' ${NCURSES_DIR}/dist.mk | sed -e 's%^[^0-9]*%%' NCURSES_PATCH!= egrep 'NCURSES_PATCH[ ]*=' ${NCURSES_DIR}/dist.mk | sed -e 's%^[^0-9]*%%' diff --git a/lib/ofed/libibnetdisc/Makefile b/lib/ofed/libibnetdisc/Makefile index d3e0dd92509a..aac0bf0f5971 100644 --- a/lib/ofed/libibnetdisc/Makefile +++ b/lib/ofed/libibnetdisc/Makefile @@ -29,7 +29,6 @@ LIBADD= osmcomp ibmad ibumad CFLAGS+= -DHAVE_CONFIG_H=1 CFLAGS+= -I${_spath} CFLAGS+= -I${SYSROOT:U${DESTDIR}}/${INCLUDEDIR}/infiniband -CXXSTD= c++11 VERSION_MAP= ${_spath}/libibnetdisc.map .include <bsd.lib.mk> |