From ae019f102dd3cb6d975c087817d71c4289bc1670 Mon Sep 17 00:00:00 2001 From: purplerain Date: Thu, 11 Jul 2024 15:49:23 +0000 Subject: [PATCH] sync with OpenBSD -current --- distrib/sets/lists/base/mi | 1 + distrib/sets/lists/comp/mi | 1 + distrib/sets/lists/man/mi | 1 + lib/libc/stdlib/getenv.c | 4 +- lib/libcrypto/Makefile | 7 +- lib/libcrypto/Symbols.namespace | 3355 ----------------- lib/libcrypto/kdf/tls1_prf.c | 11 +- lib/libcrypto/man/EVP_PKEY_CTX_set_hkdf_md.3 | 5 +- .../man/EVP_PKEY_CTX_set_tls1_prf_md.3 | 171 + lib/libcrypto/man/Makefile | 3 +- lib/libssl/man/SSL_CTX_set_alpn_select_cb.3 | 78 +- lib/libssl/ssl_lib.c | 58 +- libexec/snmpd/snmpd_metrics/pf.c | 6 +- regress/lib/libcrypto/symbols/Makefile | 4 +- regress/lib/libcrypto/symbols/symbols.awk | 8 +- regress/lib/libssl/unit/ssl_set_alpn_protos.c | 222 +- regress/usr.bin/diff/t8.2 | 6 +- regress/usr.bin/diff/t9.2 | 18 +- sbin/dhcp6leased/dhcp6leased.c | 5 +- sbin/dhcp6leased/dhcp6leased.h | 4 +- sbin/dhcp6leased/engine.c | 100 +- sbin/dhcp6leased/frontend.c | 30 +- share/man/man4/bnxt.4 | 8 +- share/man/man5/port-modules.5 | 19 +- sys/arch/amd64/amd64/locore0.S | 20 +- sys/arch/amd64/include/vmmvar.h | 23 +- sys/arch/arm64/arm64/cpu.c | 101 +- sys/arch/arm64/conf/Makefile.arm64 | 4 +- sys/arch/arm64/include/cpu.h | 4 +- sys/arch/arm64/include/efivar.h | 7 +- sys/arch/arm64/include/vmmvar.h | 91 + sys/arch/arm64/stand/efiboot/efiboot.c | 5 +- sys/dev/efi/efi.c | 57 +- sys/dev/fdt/psci.c | 23 +- sys/dev/fdt/pscivar.h | 26 + sys/dev/fdt/qcscm.c | 87 +- sys/dev/pci/drm/include/linux/fb.h | 8 +- sys/dev/pci/if_iavf.c | 29 +- sys/dev/vmm/vmm.h | 17 +- sys/kern/kern_sig.c | 49 +- sys/kern/kern_sysctl.c | 39 +- sys/kern/vfs_syscalls.c | 6 +- usr.bin/mg/mg.1 | 8 +- usr.bin/ssh/sshd_config.5 | 6 +- usr.sbin/npppd/npppd/npppd.c | 12 +- usr.sbin/npppd/npppd/npppd.conf.5 | 32 +- usr.sbin/npppd/npppd/npppd.h | 144 +- usr.sbin/npppd/npppd/npppd_config.c | 7 +- usr.sbin/npppd/npppd/npppd_local.h | 10 +- usr.sbin/npppd/npppd/npppd_radius.c | 312 +- usr.sbin/npppd/npppd/npppd_radius.h | 30 +- usr.sbin/npppd/npppd/parse.y | 91 +- usr.sbin/pstat/pstat.c | 22 +- usr.sbin/radiusctl/radiusctl.8 | 5 +- usr.sbin/radiusd/parse.y | 5 +- usr.sbin/radiusd/radiusd.c | 21 +- usr.sbin/radiusd/radiusd.conf.5 | 8 +- usr.sbin/radiusd/radiusd_ipcp.8 | 66 +- usr.sbin/radiusd/radiusd_ipcp.c | 112 +- usr.sbin/vmctl/Makefile | 4 +- usr.sbin/vmd/Makefile | 23 +- usr.sbin/vmd/arm64_vm.c | 162 + usr.sbin/vmd/i8253.c | 5 +- usr.sbin/vmd/mc146818.c | 5 +- usr.sbin/vmd/mmio.c | 1046 ----- usr.sbin/vmd/ns8250.c | 7 +- usr.sbin/vmd/pci.c | 16 +- usr.sbin/vmd/pci.h | 11 +- usr.sbin/vmd/vioblk.c | 6 +- usr.sbin/vmd/virtio.c | 23 +- usr.sbin/vmd/virtio.h | 6 +- usr.sbin/vmd/vm.c | 1247 +----- usr.sbin/vmd/vmd.c | 131 +- usr.sbin/vmd/vmd.h | 47 +- usr.sbin/vmd/vmm.c | 6 +- usr.sbin/vmd/x86_mmio.c | 1045 +++++ usr.sbin/vmd/x86_vm.c | 1373 +++++++ 77 files changed, 4413 insertions(+), 6362 deletions(-) delete mode 100644 lib/libcrypto/Symbols.namespace create mode 100644 lib/libcrypto/man/EVP_PKEY_CTX_set_tls1_prf_md.3 create mode 100644 sys/arch/arm64/include/vmmvar.h create mode 100644 usr.sbin/vmd/arm64_vm.c create mode 100644 usr.sbin/vmd/x86_mmio.c create mode 100644 usr.sbin/vmd/x86_vm.c diff --git a/distrib/sets/lists/base/mi b/distrib/sets/lists/base/mi index 74b709737..66cf604c0 100644 --- a/distrib/sets/lists/base/mi +++ b/distrib/sets/lists/base/mi @@ -2510,6 +2510,7 @@ ./usr/libexec/ntalkd ./usr/libexec/radiusd ./usr/libexec/radiusd/radiusd_bsdauth +./usr/libexec/radiusd/radiusd_ipcp ./usr/libexec/radiusd/radiusd_radius ./usr/libexec/radiusd/radiusd_standard ./usr/libexec/reorder_kernel diff --git a/distrib/sets/lists/comp/mi b/distrib/sets/lists/comp/mi index 303d095ce..9d5b37b4a 100644 --- a/distrib/sets/lists/comp/mi +++ b/distrib/sets/lists/comp/mi @@ -1927,6 +1927,7 @@ ./usr/share/man/man3/EVP_PKEY_CTX_get_operation.3 ./usr/share/man/man3/EVP_PKEY_CTX_new.3 ./usr/share/man/man3/EVP_PKEY_CTX_set_hkdf_md.3 +./usr/share/man/man3/EVP_PKEY_CTX_set_tls1_prf_md.3 ./usr/share/man/man3/EVP_PKEY_add1_attr.3 ./usr/share/man/man3/EVP_PKEY_asn1_get_count.3 ./usr/share/man/man3/EVP_PKEY_asn1_new.3 diff --git a/distrib/sets/lists/man/mi b/distrib/sets/lists/man/mi index 284f38d04..4eac1a62b 100644 --- a/distrib/sets/lists/man/mi +++ b/distrib/sets/lists/man/mi @@ -2615,6 +2615,7 @@ ./usr/share/man/man8/radiusctl.8 ./usr/share/man/man8/radiusd.8 ./usr/share/man/man8/radiusd_bsdauth.8 +./usr/share/man/man8/radiusd_ipcp.8 ./usr/share/man/man8/radiusd_radius.8 ./usr/share/man/man8/radiusd_standard.8 ./usr/share/man/man8/rarpd.8 diff --git a/lib/libc/stdlib/getenv.c b/lib/libc/stdlib/getenv.c index 054497b43..068d70a99 100644 --- a/lib/libc/stdlib/getenv.c +++ b/lib/libc/stdlib/getenv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getenv.c,v 1.12 2016/03/13 18:34:21 guenther Exp $ */ +/* $OpenBSD: getenv.c,v 1.13 2024/07/10 14:17:58 jca Exp $ */ /* * Copyright (c) 1987, 1993 * The Regents of the University of California. All rights reserved. @@ -39,8 +39,6 @@ * Sets offset to be the offset of the name/value combination in the * environmental array, for use by putenv(3), setenv(3) and unsetenv(3). * Explicitly removes '=' in argument name. - * - * This routine *should* be a static; don't use it. */ char * __findenv(const char *name, int len, int *offset) diff --git a/lib/libcrypto/Makefile b/lib/libcrypto/Makefile index 96a0f197c..ef26b0c5f 100644 --- a/lib/libcrypto/Makefile +++ b/lib/libcrypto/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.199 2024/07/09 16:41:44 tb Exp $ +# $OpenBSD: Makefile,v 1.200 2024/07/10 13:30:14 beck Exp $ LIB= crypto LIBREBUILD=y @@ -53,7 +53,6 @@ CFLAGS+= -I${LCRYPTO_SRC}/x509 VERSION_SCRIPT= Symbols.map SYMBOL_LIST= ${.CURDIR}/Symbols.list -SYMBOL_NAMESPACE= ${.CURDIR}/Symbols.namespace .if (${MACHINE_CPU} == "amd64") || (${MACHINE_CPU} == "i386") SYMBOL_LIST+= ${.CURDIR}/arch/${MACHINE_CPU}/Symbols.list @@ -746,9 +745,9 @@ includes: prereq echo $$j; \ eval "$$j"; \ done; -${VERSION_SCRIPT}: ${SYMBOL_LIST} ${SYMBOL_NAMESPACE} +${VERSION_SCRIPT}: ${SYMBOL_LIST} { printf '{\n\tglobal:\n'; \ - sed '/^[._a-zA-Z]/s/$$/;/; s/^/ /' ${SYMBOL_NAMESPACE}; \ + sed '/^[._a-zA-Z]/s/$$/;/; s/^/ _libre_/' ${SYMBOL_LIST}; \ sed '/^[._a-zA-Z]/s/$$/;/; s/^/ /' ${SYMBOL_LIST}; \ printf '\n\tlocal:\n\t\t*;\n};\n'; } >$@.tmp && mv $@.tmp $@ diff --git a/lib/libcrypto/Symbols.namespace b/lib/libcrypto/Symbols.namespace deleted file mode 100644 index 48ee1b981..000000000 --- a/lib/libcrypto/Symbols.namespace +++ /dev/null @@ -1,3355 +0,0 @@ -_libre_HMAC -_libre_HMAC_CTX_copy -_libre_HMAC_CTX_free -_libre_HMAC_CTX_get_md -_libre_HMAC_CTX_new -_libre_HMAC_CTX_set_flags -_libre_HMAC_Final -_libre_HMAC_Init_ex -_libre_HMAC_Update -_libre_sk_num -_libre_sk_value -_libre_sk_set -_libre_sk_new -_libre_sk_new_null -_libre_sk_free -_libre_sk_pop_free -_libre_sk_insert -_libre_sk_delete -_libre_sk_delete_ptr -_libre_sk_find -_libre_sk_push -_libre_sk_unshift -_libre_sk_shift -_libre_sk_pop -_libre_sk_zero -_libre_sk_set_cmp_func -_libre_sk_dup -_libre_sk_sort -_libre_sk_is_sorted -_libre_PKCS7_ISSUER_AND_SERIAL_new -_libre_PKCS7_ISSUER_AND_SERIAL_free -_libre_d2i_PKCS7_ISSUER_AND_SERIAL -_libre_i2d_PKCS7_ISSUER_AND_SERIAL -_libre_PKCS7_ISSUER_AND_SERIAL_digest -_libre_d2i_PKCS7_fp -_libre_i2d_PKCS7_fp -_libre_PKCS7_dup -_libre_d2i_PKCS7_bio -_libre_i2d_PKCS7_bio -_libre_i2d_PKCS7_bio_stream -_libre_PEM_write_bio_PKCS7_stream -_libre_PKCS7_SIGNER_INFO_new -_libre_PKCS7_SIGNER_INFO_free -_libre_d2i_PKCS7_SIGNER_INFO -_libre_i2d_PKCS7_SIGNER_INFO -_libre_PKCS7_RECIP_INFO_new -_libre_PKCS7_RECIP_INFO_free -_libre_d2i_PKCS7_RECIP_INFO -_libre_i2d_PKCS7_RECIP_INFO -_libre_PKCS7_SIGNED_new -_libre_PKCS7_SIGNED_free -_libre_d2i_PKCS7_SIGNED -_libre_i2d_PKCS7_SIGNED -_libre_PKCS7_ENC_CONTENT_new -_libre_PKCS7_ENC_CONTENT_free -_libre_d2i_PKCS7_ENC_CONTENT -_libre_i2d_PKCS7_ENC_CONTENT -_libre_PKCS7_ENVELOPE_new -_libre_PKCS7_ENVELOPE_free -_libre_d2i_PKCS7_ENVELOPE -_libre_i2d_PKCS7_ENVELOPE -_libre_PKCS7_SIGN_ENVELOPE_new -_libre_PKCS7_SIGN_ENVELOPE_free -_libre_d2i_PKCS7_SIGN_ENVELOPE -_libre_i2d_PKCS7_SIGN_ENVELOPE -_libre_PKCS7_DIGEST_new -_libre_PKCS7_DIGEST_free -_libre_d2i_PKCS7_DIGEST -_libre_i2d_PKCS7_DIGEST -_libre_PKCS7_ENCRYPT_new -_libre_PKCS7_ENCRYPT_free -_libre_d2i_PKCS7_ENCRYPT -_libre_i2d_PKCS7_ENCRYPT -_libre_PKCS7_new -_libre_PKCS7_free -_libre_d2i_PKCS7 -_libre_i2d_PKCS7 -_libre_PKCS7_print_ctx -_libre_PKCS7_ctrl -_libre_PKCS7_set_type -_libre_PKCS7_set0_type_other -_libre_PKCS7_set_content -_libre_PKCS7_SIGNER_INFO_set -_libre_PKCS7_SIGNER_INFO_sign -_libre_PKCS7_add_signer -_libre_PKCS7_add_certificate -_libre_PKCS7_add_crl -_libre_PKCS7_content_new -_libre_PKCS7_dataVerify -_libre_PKCS7_signatureVerify -_libre_PKCS7_dataInit -_libre_PKCS7_dataFinal -_libre_PKCS7_dataDecode -_libre_PKCS7_add_signature -_libre_PKCS7_cert_from_signer_info -_libre_PKCS7_set_digest -_libre_PKCS7_get_signer_info -_libre_PKCS7_add_recipient -_libre_PKCS7_SIGNER_INFO_get0_algs -_libre_PKCS7_RECIP_INFO_get0_alg -_libre_PKCS7_add_recipient_info -_libre_PKCS7_RECIP_INFO_set -_libre_PKCS7_set_cipher -_libre_PKCS7_stream -_libre_PKCS7_get_issuer_and_serial -_libre_PKCS7_digest_from_attributes -_libre_PKCS7_add_signed_attribute -_libre_PKCS7_get_attribute -_libre_PKCS7_get_signed_attribute -_libre_PKCS7_set_signed_attributes -_libre_PKCS7_set_attributes -_libre_PKCS7_sign -_libre_PKCS7_sign_add_signer -_libre_PKCS7_final -_libre_PKCS7_verify -_libre_PKCS7_get0_signers -_libre_PKCS7_encrypt -_libre_PKCS7_decrypt -_libre_PKCS7_add_attrib_smimecap -_libre_PKCS7_get_smimecap -_libre_PKCS7_simple_smimecap -_libre_PKCS7_add_attrib_content_type -_libre_PKCS7_add0_attrib_signing_time -_libre_PKCS7_add1_attrib_digest -_libre_SMIME_write_PKCS7 -_libre_SMIME_read_PKCS7 -_libre_BIO_new_PKCS7 -_libre_ERR_load_PKCS7_strings -_libre_PKCS12_SAFEBAG_get0_attr -_libre_PKCS12_SAFEBAG_get0_attrs -_libre_PKCS12_SAFEBAG_get_nid -_libre_PKCS12_SAFEBAG_get_bag_nid -_libre_PKCS12_SAFEBAG_get1_cert -_libre_PKCS12_SAFEBAG_get1_crl -_libre_PKCS8_get_attr -_libre_PKCS12_mac_present -_libre_PKCS12_get0_mac -_libre_PKCS12_SAFEBAG_get0_p8inf -_libre_PKCS12_SAFEBAG_get0_pkcs8 -_libre_PKCS12_SAFEBAG_get0_safes -_libre_PKCS12_SAFEBAG_get0_type -_libre_PKCS8_decrypt -_libre_PKCS12_decrypt_skey -_libre_PKCS8_encrypt -_libre_PKCS12_unpack_p7data -_libre_PKCS12_unpack_p7encdata -_libre_PKCS12_unpack_authsafes -_libre_PKCS8_add_keyusage -_libre_PKCS12_get_friendlyname -_libre_PKCS12_verify_mac -_libre_PKCS12_set_mac -_libre_OPENSSL_asc2uni -_libre_OPENSSL_uni2asc -_libre_PKCS12_new -_libre_PKCS12_free -_libre_d2i_PKCS12 -_libre_i2d_PKCS12 -_libre_PKCS12_SAFEBAG_new -_libre_PKCS12_SAFEBAG_free -_libre_d2i_PKCS12_SAFEBAG -_libre_i2d_PKCS12_SAFEBAG -_libre_PKCS12_PBE_add -_libre_PKCS12_parse -_libre_PKCS12_create -_libre_i2d_PKCS12_bio -_libre_i2d_PKCS12_fp -_libre_d2i_PKCS12_bio -_libre_d2i_PKCS12_fp -_libre_PKCS12_newpass -_libre_ERR_load_PKCS12_strings -_libre_UI_new -_libre_UI_new_method -_libre_UI_free -_libre_UI_add_input_string -_libre_UI_dup_input_string -_libre_UI_add_verify_string -_libre_UI_dup_verify_string -_libre_UI_add_input_boolean -_libre_UI_dup_input_boolean -_libre_UI_add_info_string -_libre_UI_dup_info_string -_libre_UI_add_error_string -_libre_UI_dup_error_string -_libre_UI_construct_prompt -_libre_UI_add_user_data -_libre_UI_get0_user_data -_libre_UI_get0_result -_libre_UI_process -_libre_UI_ctrl -_libre_UI_get_ex_new_index -_libre_UI_set_ex_data -_libre_UI_get_ex_data -_libre_UI_set_default_method -_libre_UI_get_default_method -_libre_UI_get_method -_libre_UI_set_method -_libre_UI_OpenSSL -_libre_UI_create_method -_libre_UI_destroy_method -_libre_UI_method_set_opener -_libre_UI_method_set_writer -_libre_UI_method_set_flusher -_libre_UI_method_set_reader -_libre_UI_method_set_closer -_libre_UI_method_set_prompt_constructor -_libre_UI_method_get_opener -_libre_UI_method_get_writer -_libre_UI_method_get_flusher -_libre_UI_method_get_reader -_libre_UI_method_get_closer -_libre_UI_get_string_type -_libre_UI_get_input_flags -_libre_UI_get0_output_string -_libre_UI_get0_action_string -_libre_UI_get0_result_string -_libre_UI_get0_test_string -_libre_UI_get_result_minsize -_libre_UI_get_result_maxsize -_libre_UI_set_result -_libre_UI_UTIL_read_pw_string -_libre_UI_UTIL_read_pw -_libre_ERR_load_UI_strings -_libre_X509_CRL_up_ref -_libre_i2d_re_X509_CRL_tbs -_libre_X509_get_X509_PUBKEY -_libre_X509_verify_cert_error_string -_libre_X509_verify -_libre_X509_REQ_verify -_libre_NETSCAPE_SPKI_verify -_libre_NETSCAPE_SPKI_b64_decode -_libre_NETSCAPE_SPKI_b64_encode -_libre_NETSCAPE_SPKI_get_pubkey -_libre_NETSCAPE_SPKI_set_pubkey -_libre_X509_sign -_libre_X509_sign_ctx -_libre_X509_REQ_sign -_libre_X509_REQ_sign_ctx -_libre_X509_CRL_sign -_libre_X509_CRL_sign_ctx -_libre_NETSCAPE_SPKI_sign -_libre_X509_pubkey_digest -_libre_X509_digest -_libre_X509_CRL_digest -_libre_X509_REQ_digest -_libre_X509_NAME_digest -_libre_d2i_X509_fp -_libre_i2d_X509_fp -_libre_d2i_X509_CRL_fp -_libre_i2d_X509_CRL_fp -_libre_d2i_X509_REQ_fp -_libre_i2d_X509_REQ_fp -_libre_d2i_RSAPrivateKey_fp -_libre_i2d_RSAPrivateKey_fp -_libre_d2i_RSAPublicKey_fp -_libre_i2d_RSAPublicKey_fp -_libre_d2i_DSAPrivateKey_fp -_libre_i2d_DSAPrivateKey_fp -_libre_d2i_ECPrivateKey_fp -_libre_i2d_ECPrivateKey_fp -_libre_d2i_PKCS8_fp -_libre_i2d_PKCS8_fp -_libre_d2i_PKCS8_PRIV_KEY_INFO_fp -_libre_i2d_PKCS8_PRIV_KEY_INFO_fp -_libre_i2d_PKCS8PrivateKeyInfo_fp -_libre_i2d_PrivateKey_fp -_libre_d2i_PrivateKey_fp -_libre_d2i_X509_bio -_libre_i2d_X509_bio -_libre_d2i_X509_CRL_bio -_libre_i2d_X509_CRL_bio -_libre_d2i_X509_REQ_bio -_libre_i2d_X509_REQ_bio -_libre_d2i_RSAPrivateKey_bio -_libre_i2d_RSAPrivateKey_bio -_libre_d2i_RSAPublicKey_bio -_libre_i2d_RSAPublicKey_bio -_libre_d2i_DSAPrivateKey_bio -_libre_i2d_DSAPrivateKey_bio -_libre_d2i_ECPrivateKey_bio -_libre_i2d_ECPrivateKey_bio -_libre_d2i_PKCS8_bio -_libre_i2d_PKCS8_bio -_libre_d2i_PKCS8_PRIV_KEY_INFO_bio -_libre_i2d_PKCS8_PRIV_KEY_INFO_bio -_libre_i2d_PKCS8PrivateKeyInfo_bio -_libre_i2d_PrivateKey_bio -_libre_d2i_PrivateKey_bio -_libre_X509_cmp_time -_libre_X509_cmp_current_time -_libre_X509_time_adj -_libre_X509_time_adj_ex -_libre_X509_gmtime_adj -_libre_X509_get_default_cert_area -_libre_X509_get_default_cert_dir -_libre_X509_get_default_cert_file -_libre_X509_get_default_cert_dir_env -_libre_X509_get_default_cert_file_env -_libre_X509_get_default_private_dir -_libre_X509_to_X509_REQ -_libre_X509_REQ_to_X509 -_libre_X509_get_pubkey_parameters -_libre_X509_NAME_oneline -_libre_X509_get0_extensions -_libre_X509_get0_tbs_sigalg -_libre_X509_get0_uids -_libre_X509_set_version -_libre_X509_get_version -_libre_X509_set_serialNumber -_libre_X509_get_serialNumber -_libre_X509_get0_serialNumber -_libre_X509_set_issuer_name -_libre_X509_get_issuer_name -_libre_X509_set_subject_name -_libre_X509_get_subject_name -_libre_X509_set_notBefore -_libre_X509_set1_notBefore -_libre_X509_set_notAfter -_libre_X509_set1_notAfter -_libre_X509_get0_notBefore -_libre_X509_getm_notBefore -_libre_X509_get0_notAfter -_libre_X509_getm_notAfter -_libre_X509_set_pubkey -_libre_X509_get_pubkey -_libre_X509_get0_pubkey -_libre_X509_get0_pubkey_bitstr -_libre_X509_certificate_type -_libre_X509_get_signature_type -_libre_X509_REQ_set_version -_libre_X509_REQ_get_version -_libre_X509_REQ_set_subject_name -_libre_X509_REQ_get_subject_name -_libre_X509_REQ_set_pubkey -_libre_X509_REQ_get_pubkey -_libre_i2d_re_X509_REQ_tbs -_libre_X509_REQ_get0_pubkey -_libre_X509_REQ_extension_nid -_libre_X509_REQ_get_extension_nids -_libre_X509_REQ_set_extension_nids -_libre_X509_REQ_get_extensions -_libre_X509_REQ_add_extensions_nid -_libre_X509_REQ_add_extensions -_libre_X509_REQ_get_attr_count -_libre_X509_REQ_get_attr_by_NID -_libre_X509_REQ_get_attr_by_OBJ -_libre_X509_REQ_get_attr -_libre_X509_REQ_delete_attr -_libre_X509_REQ_add1_attr -_libre_X509_REQ_add1_attr_by_OBJ -_libre_X509_REQ_add1_attr_by_NID -_libre_X509_REQ_add1_attr_by_txt -_libre_X509_CRL_set_version -_libre_X509_CRL_set_issuer_name -_libre_X509_CRL_set_lastUpdate -_libre_X509_CRL_set1_lastUpdate -_libre_X509_CRL_set_nextUpdate -_libre_X509_CRL_set1_nextUpdate -_libre_X509_CRL_sort -_libre_X509_REVOKED_get0_extensions -_libre_X509_REVOKED_get0_revocationDate -_libre_X509_REVOKED_get0_serialNumber -_libre_X509_REVOKED_set_revocationDate -_libre_X509_REVOKED_set_serialNumber -_libre_X509_REQ_check_private_key -_libre_X509_check_private_key -_libre_X509_issuer_and_serial_cmp -_libre_X509_issuer_and_serial_hash -_libre_X509_issuer_name_cmp -_libre_X509_issuer_name_hash -_libre_X509_subject_name_cmp -_libre_X509_subject_name_hash -_libre_X509_issuer_name_hash_old -_libre_X509_subject_name_hash_old -_libre_X509_cmp -_libre_X509_NAME_cmp -_libre_X509_NAME_hash -_libre_X509_NAME_hash_old -_libre_X509_CRL_cmp -_libre_X509_CRL_match -_libre_X509_NAME_entry_count -_libre_X509_NAME_get_text_by_NID -_libre_X509_NAME_get_text_by_OBJ -_libre_X509_NAME_get_index_by_NID -_libre_X509_NAME_get_index_by_OBJ -_libre_X509_NAME_get_entry -_libre_X509_NAME_delete_entry -_libre_X509_NAME_add_entry -_libre_X509_NAME_add_entry_by_OBJ -_libre_X509_NAME_add_entry_by_NID -_libre_X509_NAME_ENTRY_create_by_txt -_libre_X509_NAME_ENTRY_create_by_NID -_libre_X509_NAME_add_entry_by_txt -_libre_X509_NAME_ENTRY_create_by_OBJ -_libre_X509_NAME_ENTRY_set_object -_libre_X509_NAME_ENTRY_set_data -_libre_X509_NAME_ENTRY_get_object -_libre_X509_NAME_ENTRY_get_data -_libre_X509_NAME_ENTRY_set -_libre_X509v3_get_ext_count -_libre_X509v3_get_ext_by_NID -_libre_X509v3_get_ext_by_OBJ -_libre_X509v3_get_ext_by_critical -_libre_X509v3_get_ext -_libre_X509v3_delete_ext -_libre_X509v3_add_ext -_libre_X509_get_ext_count -_libre_X509_get_ext_by_NID -_libre_X509_get_ext_by_OBJ -_libre_X509_get_ext_by_critical -_libre_X509_get_ext -_libre_X509_delete_ext -_libre_X509_add_ext -_libre_X509_get_ext_d2i -_libre_X509_add1_ext_i2d -_libre_X509_CRL_get_ext_count -_libre_X509_CRL_get_ext_by_NID -_libre_X509_CRL_get_ext_by_OBJ -_libre_X509_CRL_get_ext_by_critical -_libre_X509_CRL_get_ext -_libre_X509_CRL_delete_ext -_libre_X509_CRL_add_ext -_libre_X509_CRL_get_ext_d2i -_libre_X509_CRL_add1_ext_i2d -_libre_X509_REVOKED_get_ext_count -_libre_X509_REVOKED_get_ext_by_NID -_libre_X509_REVOKED_get_ext_by_OBJ -_libre_X509_REVOKED_get_ext_by_critical -_libre_X509_REVOKED_get_ext -_libre_X509_REVOKED_delete_ext -_libre_X509_REVOKED_add_ext -_libre_X509_REVOKED_get_ext_d2i -_libre_X509_REVOKED_add1_ext_i2d -_libre_X509_EXTENSION_create_by_NID -_libre_X509_EXTENSION_create_by_OBJ -_libre_X509_EXTENSION_set_object -_libre_X509_EXTENSION_set_critical -_libre_X509_EXTENSION_set_data -_libre_X509_EXTENSION_get_object -_libre_X509_EXTENSION_get_data -_libre_X509_EXTENSION_get_critical -_libre_X509at_get_attr_count -_libre_X509at_get_attr_by_NID -_libre_X509at_get_attr_by_OBJ -_libre_X509at_get_attr -_libre_X509at_delete_attr -_libre_X509at_add1_attr -_libre_X509at_add1_attr_by_OBJ -_libre_X509at_add1_attr_by_NID -_libre_X509at_add1_attr_by_txt -_libre_X509at_get0_data_by_OBJ -_libre_X509_ATTRIBUTE_create_by_NID -_libre_X509_ATTRIBUTE_create_by_OBJ -_libre_X509_ATTRIBUTE_create_by_txt -_libre_X509_ATTRIBUTE_set1_object -_libre_X509_ATTRIBUTE_set1_data -_libre_X509_ATTRIBUTE_get0_data -_libre_X509_ATTRIBUTE_count -_libre_X509_ATTRIBUTE_get0_object -_libre_X509_ATTRIBUTE_get0_type -_libre_X509_verify_cert -_libre_X509_find_by_issuer_and_serial -_libre_X509_find_by_subject -_libre_X509_check_trust -_libre_X509_up_ref -_libre_X509_chain_up_ref -_libre_ERR_load_X509_strings -_libre_X509_STORE_set_depth -_libre_X509_STORE_CTX_set_depth -_libre_X509_OBJECT_new -_libre_X509_OBJECT_free -_libre_X509_OBJECT_idx_by_subject -_libre_X509_OBJECT_retrieve_by_subject -_libre_X509_OBJECT_retrieve_match -_libre_X509_OBJECT_up_ref_count -_libre_X509_OBJECT_get_type -_libre_X509_OBJECT_get0_X509 -_libre_X509_OBJECT_get0_X509_CRL -_libre_X509_STORE_new -_libre_X509_STORE_free -_libre_X509_STORE_up_ref -_libre_X509_STORE_get0_objects -_libre_X509_STORE_get1_objects -_libre_X509_STORE_get_ex_data -_libre_X509_STORE_set_ex_data -_libre_X509_STORE_set_flags -_libre_X509_STORE_set_purpose -_libre_X509_STORE_set_trust -_libre_X509_STORE_set1_param -_libre_X509_STORE_get0_param -_libre_X509_STORE_get_verify_cb -_libre_X509_STORE_set_verify_cb -_libre_X509_STORE_CTX_new -_libre_X509_STORE_CTX_get1_issuer -_libre_X509_STORE_CTX_free -_libre_X509_STORE_CTX_init -_libre_X509_STORE_CTX_get0_cert -_libre_X509_STORE_CTX_get0_chain -_libre_X509_STORE_CTX_get0_store -_libre_X509_STORE_CTX_get0_untrusted -_libre_X509_STORE_CTX_set0_untrusted -_libre_X509_STORE_CTX_get1_certs -_libre_X509_STORE_CTX_get1_crls -_libre_X509_STORE_CTX_trusted_stack -_libre_X509_STORE_CTX_set0_trusted_stack -_libre_X509_STORE_CTX_cleanup -_libre_X509_STORE_add_lookup -_libre_X509_LOOKUP_hash_dir -_libre_X509_LOOKUP_file -_libre_X509_LOOKUP_mem -_libre_X509_STORE_add_cert -_libre_X509_STORE_add_crl -_libre_X509_STORE_CTX_get_by_subject -_libre_X509_STORE_CTX_get_obj_by_subject -_libre_X509_LOOKUP_ctrl -_libre_X509_load_cert_file -_libre_X509_load_crl_file -_libre_X509_load_cert_crl_file -_libre_X509_LOOKUP_free -_libre_X509_STORE_load_locations -_libre_X509_STORE_load_mem -_libre_X509_STORE_set_default_paths -_libre_X509_STORE_CTX_get_ex_new_index -_libre_X509_STORE_CTX_set_ex_data -_libre_X509_STORE_CTX_get_ex_data -_libre_X509_STORE_CTX_get_error -_libre_X509_STORE_CTX_set_error -_libre_X509_STORE_CTX_get_error_depth -_libre_X509_STORE_CTX_set_error_depth -_libre_X509_STORE_CTX_get_current_cert -_libre_X509_STORE_CTX_set_current_cert -_libre_X509_STORE_CTX_get0_current_issuer -_libre_X509_STORE_CTX_get0_current_crl -_libre_X509_STORE_CTX_get0_parent_ctx -_libre_X509_STORE_CTX_get_chain -_libre_X509_STORE_CTX_get1_chain -_libre_X509_STORE_CTX_set_cert -_libre_X509_STORE_CTX_set_chain -_libre_X509_STORE_CTX_set0_crls -_libre_X509_STORE_CTX_set_purpose -_libre_X509_STORE_CTX_set_trust -_libre_X509_STORE_CTX_set_flags -_libre_X509_STORE_CTX_set_time -_libre_X509_STORE_CTX_set0_verified_chain -_libre_X509_STORE_CTX_get_verify -_libre_X509_STORE_CTX_set_verify -_libre_X509_STORE_CTX_get_verify_cb -_libre_X509_STORE_CTX_set_verify_cb -_libre_X509_STORE_set_verify -_libre_X509_STORE_get_verify -_libre_X509_STORE_CTX_get_num_untrusted -_libre_X509_STORE_CTX_get0_param -_libre_X509_STORE_CTX_set0_param -_libre_X509_STORE_CTX_set_default -_libre_X509_VERIFY_PARAM_new -_libre_X509_VERIFY_PARAM_free -_libre_X509_VERIFY_PARAM_inherit -_libre_X509_VERIFY_PARAM_set1 -_libre_X509_VERIFY_PARAM_set1_name -_libre_X509_VERIFY_PARAM_set_flags -_libre_X509_VERIFY_PARAM_clear_flags -_libre_X509_VERIFY_PARAM_get_flags -_libre_X509_VERIFY_PARAM_set_purpose -_libre_X509_VERIFY_PARAM_set_trust -_libre_X509_VERIFY_PARAM_set_depth -_libre_X509_VERIFY_PARAM_set_auth_level -_libre_X509_VERIFY_PARAM_get_time -_libre_X509_VERIFY_PARAM_set_time -_libre_X509_VERIFY_PARAM_add0_policy -_libre_X509_VERIFY_PARAM_set1_policies -_libre_X509_VERIFY_PARAM_get_depth -_libre_X509_VERIFY_PARAM_set1_host -_libre_X509_VERIFY_PARAM_add1_host -_libre_X509_VERIFY_PARAM_set_hostflags -_libre_X509_VERIFY_PARAM_get0_peername -_libre_X509_VERIFY_PARAM_set1_email -_libre_X509_VERIFY_PARAM_set1_ip -_libre_X509_VERIFY_PARAM_set1_ip_asc -_libre_X509_VERIFY_PARAM_get0_name -_libre_X509_VERIFY_PARAM_get0 -_libre_X509_VERIFY_PARAM_get_count -_libre_X509_VERIFY_PARAM_add0_table -_libre_X509_VERIFY_PARAM_lookup -_libre_X509_VERIFY_PARAM_table_cleanup -_libre_BASIC_CONSTRAINTS_new -_libre_BASIC_CONSTRAINTS_free -_libre_d2i_BASIC_CONSTRAINTS -_libre_i2d_BASIC_CONSTRAINTS -_libre_AUTHORITY_KEYID_new -_libre_AUTHORITY_KEYID_free -_libre_d2i_AUTHORITY_KEYID -_libre_i2d_AUTHORITY_KEYID -_libre_PKEY_USAGE_PERIOD_new -_libre_PKEY_USAGE_PERIOD_free -_libre_d2i_PKEY_USAGE_PERIOD -_libre_i2d_PKEY_USAGE_PERIOD -_libre_GENERAL_NAME_new -_libre_GENERAL_NAME_free -_libre_d2i_GENERAL_NAME -_libre_i2d_GENERAL_NAME -_libre_GENERAL_NAME_dup -_libre_GENERAL_NAME_cmp -_libre_v2i_ASN1_BIT_STRING -_libre_i2v_ASN1_BIT_STRING -_libre_i2v_GENERAL_NAME -_libre_GENERAL_NAME_print -_libre_GENERAL_NAMES_new -_libre_GENERAL_NAMES_free -_libre_d2i_GENERAL_NAMES -_libre_i2d_GENERAL_NAMES -_libre_i2v_GENERAL_NAMES -_libre_v2i_GENERAL_NAMES -_libre_OTHERNAME_new -_libre_OTHERNAME_free -_libre_d2i_OTHERNAME -_libre_i2d_OTHERNAME -_libre_EDIPARTYNAME_new -_libre_EDIPARTYNAME_free -_libre_d2i_EDIPARTYNAME -_libre_i2d_EDIPARTYNAME -_libre_OTHERNAME_cmp -_libre_GENERAL_NAME_set0_value -_libre_GENERAL_NAME_get0_value -_libre_GENERAL_NAME_set0_othername -_libre_GENERAL_NAME_get0_otherName -_libre_i2s_ASN1_OCTET_STRING -_libre_s2i_ASN1_OCTET_STRING -_libre_EXTENDED_KEY_USAGE_new -_libre_EXTENDED_KEY_USAGE_free -_libre_d2i_EXTENDED_KEY_USAGE -_libre_i2d_EXTENDED_KEY_USAGE -_libre_i2a_ACCESS_DESCRIPTION -_libre_CERTIFICATEPOLICIES_new -_libre_CERTIFICATEPOLICIES_free -_libre_d2i_CERTIFICATEPOLICIES -_libre_i2d_CERTIFICATEPOLICIES -_libre_POLICYINFO_new -_libre_POLICYINFO_free -_libre_d2i_POLICYINFO -_libre_i2d_POLICYINFO -_libre_POLICYQUALINFO_new -_libre_POLICYQUALINFO_free -_libre_d2i_POLICYQUALINFO -_libre_i2d_POLICYQUALINFO -_libre_USERNOTICE_new -_libre_USERNOTICE_free -_libre_d2i_USERNOTICE -_libre_i2d_USERNOTICE -_libre_NOTICEREF_new -_libre_NOTICEREF_free -_libre_d2i_NOTICEREF -_libre_i2d_NOTICEREF -_libre_CRL_DIST_POINTS_new -_libre_CRL_DIST_POINTS_free -_libre_d2i_CRL_DIST_POINTS -_libre_i2d_CRL_DIST_POINTS -_libre_DIST_POINT_new -_libre_DIST_POINT_free -_libre_d2i_DIST_POINT -_libre_i2d_DIST_POINT -_libre_DIST_POINT_NAME_new -_libre_DIST_POINT_NAME_free -_libre_d2i_DIST_POINT_NAME -_libre_i2d_DIST_POINT_NAME -_libre_ISSUING_DIST_POINT_new -_libre_ISSUING_DIST_POINT_free -_libre_d2i_ISSUING_DIST_POINT -_libre_i2d_ISSUING_DIST_POINT -_libre_DIST_POINT_set_dpname -_libre_NAME_CONSTRAINTS_check -_libre_ACCESS_DESCRIPTION_new -_libre_ACCESS_DESCRIPTION_free -_libre_d2i_ACCESS_DESCRIPTION -_libre_i2d_ACCESS_DESCRIPTION -_libre_AUTHORITY_INFO_ACCESS_new -_libre_AUTHORITY_INFO_ACCESS_free -_libre_d2i_AUTHORITY_INFO_ACCESS -_libre_i2d_AUTHORITY_INFO_ACCESS -_libre_POLICY_MAPPING_new -_libre_POLICY_MAPPING_free -_libre_GENERAL_SUBTREE_new -_libre_GENERAL_SUBTREE_free -_libre_NAME_CONSTRAINTS_new -_libre_NAME_CONSTRAINTS_free -_libre_POLICY_CONSTRAINTS_new -_libre_POLICY_CONSTRAINTS_free -_libre_a2i_GENERAL_NAME -_libre_v2i_GENERAL_NAME -_libre_v2i_GENERAL_NAME_ex -_libre_X509V3_conf_free -_libre_X509V3_EXT_nconf_nid -_libre_X509V3_EXT_nconf -_libre_X509V3_EXT_add_nconf_sk -_libre_X509V3_EXT_add_nconf -_libre_X509V3_EXT_REQ_add_nconf -_libre_X509V3_EXT_CRL_add_nconf -_libre_X509V3_EXT_conf_nid -_libre_X509V3_EXT_conf -_libre_X509V3_EXT_add_conf -_libre_X509V3_EXT_REQ_add_conf -_libre_X509V3_EXT_CRL_add_conf -_libre_X509V3_add_value_bool_nf -_libre_X509V3_get_value_bool -_libre_X509V3_get_value_int -_libre_X509V3_set_nconf -_libre_X509V3_set_conf_lhash -_libre_X509V3_get_string -_libre_X509V3_get_section -_libre_X509V3_string_free -_libre_X509V3_section_free -_libre_X509V3_set_ctx -_libre_X509V3_add_value -_libre_X509V3_add_value_uchar -_libre_X509V3_add_value_bool -_libre_X509V3_add_value_int -_libre_i2s_ASN1_INTEGER -_libre_s2i_ASN1_INTEGER -_libre_i2s_ASN1_ENUMERATED -_libre_i2s_ASN1_ENUMERATED_TABLE -_libre_X509V3_EXT_get -_libre_X509V3_EXT_get_nid -_libre_X509V3_add_standard_extensions -_libre_X509V3_parse_list -_libre_X509V3_EXT_d2i -_libre_X509V3_get_d2i -_libre_X509V3_EXT_i2d -_libre_X509V3_add1_i2d -_libre_hex_to_string -_libre_string_to_hex -_libre_X509V3_EXT_val_prn -_libre_X509V3_EXT_print -_libre_X509V3_EXT_print_fp -_libre_X509V3_extensions_print -_libre_X509_check_ca -_libre_X509_check_purpose -_libre_X509_supported_extension -_libre_X509_check_issued -_libre_X509_check_akid -_libre_X509_PURPOSE_get_count -_libre_X509_PURPOSE_get0 -_libre_X509_PURPOSE_get_by_sname -_libre_X509_PURPOSE_get0_name -_libre_X509_PURPOSE_get0_sname -_libre_X509_PURPOSE_get_id -_libre_X509_get_extension_flags -_libre_X509_get_key_usage -_libre_X509_get_extended_key_usage -_libre_X509_get1_email -_libre_X509_REQ_get1_email -_libre_X509_email_free -_libre_X509_get1_ocsp -_libre_X509_check_host -_libre_X509_check_email -_libre_X509_check_ip -_libre_X509_check_ip_asc -_libre_a2i_IPADDRESS -_libre_a2i_IPADDRESS_NC -_libre_a2i_ipadd -_libre_X509V3_NAME_from_section -_libre_ASRange_new -_libre_ASRange_free -_libre_d2i_ASRange -_libre_i2d_ASRange -_libre_ASIdOrRange_new -_libre_ASIdOrRange_free -_libre_d2i_ASIdOrRange -_libre_i2d_ASIdOrRange -_libre_ASIdentifierChoice_new -_libre_ASIdentifierChoice_free -_libre_d2i_ASIdentifierChoice -_libre_i2d_ASIdentifierChoice -_libre_ASIdentifiers_new -_libre_ASIdentifiers_free -_libre_d2i_ASIdentifiers -_libre_i2d_ASIdentifiers -_libre_IPAddressRange_new -_libre_IPAddressRange_free -_libre_d2i_IPAddressRange -_libre_i2d_IPAddressRange -_libre_IPAddressOrRange_new -_libre_IPAddressOrRange_free -_libre_d2i_IPAddressOrRange -_libre_i2d_IPAddressOrRange -_libre_IPAddressChoice_new -_libre_IPAddressChoice_free -_libre_d2i_IPAddressChoice -_libre_i2d_IPAddressChoice -_libre_IPAddressFamily_new -_libre_IPAddressFamily_free -_libre_d2i_IPAddressFamily -_libre_i2d_IPAddressFamily -_libre_X509v3_asid_add_inherit -_libre_X509v3_asid_add_id_or_range -_libre_X509v3_addr_add_inherit -_libre_X509v3_addr_add_prefix -_libre_X509v3_addr_add_range -_libre_X509v3_addr_get_afi -_libre_X509v3_addr_get_range -_libre_X509v3_asid_is_canonical -_libre_X509v3_addr_is_canonical -_libre_X509v3_asid_canonize -_libre_X509v3_addr_canonize -_libre_X509v3_asid_inherits -_libre_X509v3_addr_inherits -_libre_X509v3_asid_subset -_libre_X509v3_addr_subset -_libre_X509v3_asid_validate_path -_libre_X509v3_addr_validate_path -_libre_X509v3_asid_validate_resource_set -_libre_X509v3_addr_validate_resource_set -_libre_ERR_load_X509V3_strings -_libre_ChaCha_set_key -_libre_ChaCha_set_iv -_libre_ChaCha -_libre_CRYPTO_chacha_20 -_libre_CRYPTO_xchacha_20 -_libre_CRYPTO_hchacha_20 -_libre_d2i_ASN1_SEQUENCE_ANY -_libre_i2d_ASN1_SEQUENCE_ANY -_libre_d2i_ASN1_SET_ANY -_libre_i2d_ASN1_SET_ANY -_libre_ASN1_TYPE_new -_libre_ASN1_TYPE_free -_libre_d2i_ASN1_TYPE -_libre_i2d_ASN1_TYPE -_libre_ASN1_TYPE_get -_libre_ASN1_TYPE_set -_libre_ASN1_TYPE_set1 -_libre_ASN1_TYPE_cmp -_libre_ASN1_OBJECT_new -_libre_ASN1_OBJECT_free -_libre_i2d_ASN1_OBJECT -_libre_d2i_ASN1_OBJECT -_libre_ASN1_STRING_new -_libre_ASN1_STRING_free -_libre_ASN1_STRING_copy -_libre_ASN1_STRING_dup -_libre_ASN1_STRING_type_new -_libre_ASN1_STRING_cmp -_libre_ASN1_STRING_set -_libre_ASN1_STRING_set0 -_libre_ASN1_STRING_length -_libre_ASN1_STRING_length_set -_libre_ASN1_STRING_type -_libre_ASN1_STRING_data -_libre_ASN1_STRING_get0_data -_libre_ASN1_BIT_STRING_new -_libre_ASN1_BIT_STRING_free -_libre_d2i_ASN1_BIT_STRING -_libre_i2d_ASN1_BIT_STRING -_libre_ASN1_BIT_STRING_set -_libre_ASN1_BIT_STRING_set_bit -_libre_ASN1_BIT_STRING_get_bit -_libre_ASN1_INTEGER_new -_libre_ASN1_INTEGER_free -_libre_d2i_ASN1_INTEGER -_libre_i2d_ASN1_INTEGER -_libre_d2i_ASN1_UINTEGER -_libre_ASN1_INTEGER_dup -_libre_ASN1_INTEGER_cmp -_libre_ASN1_ENUMERATED_new -_libre_ASN1_ENUMERATED_free -_libre_d2i_ASN1_ENUMERATED -_libre_i2d_ASN1_ENUMERATED -_libre_ASN1_UTCTIME_check -_libre_ASN1_UTCTIME_set -_libre_ASN1_UTCTIME_adj -_libre_ASN1_UTCTIME_set_string -_libre_ASN1_GENERALIZEDTIME_check -_libre_ASN1_GENERALIZEDTIME_set -_libre_ASN1_GENERALIZEDTIME_adj -_libre_ASN1_GENERALIZEDTIME_set_string -_libre_ASN1_OCTET_STRING_new -_libre_ASN1_OCTET_STRING_free -_libre_d2i_ASN1_OCTET_STRING -_libre_i2d_ASN1_OCTET_STRING -_libre_ASN1_OCTET_STRING_dup -_libre_ASN1_OCTET_STRING_cmp -_libre_ASN1_OCTET_STRING_set -_libre_ASN1_VISIBLESTRING_new -_libre_ASN1_VISIBLESTRING_free -_libre_d2i_ASN1_VISIBLESTRING -_libre_i2d_ASN1_VISIBLESTRING -_libre_ASN1_UNIVERSALSTRING_new -_libre_ASN1_UNIVERSALSTRING_free -_libre_d2i_ASN1_UNIVERSALSTRING -_libre_i2d_ASN1_UNIVERSALSTRING -_libre_ASN1_UTF8STRING_new -_libre_ASN1_UTF8STRING_free -_libre_d2i_ASN1_UTF8STRING -_libre_i2d_ASN1_UTF8STRING -_libre_ASN1_NULL_new -_libre_ASN1_NULL_free -_libre_d2i_ASN1_NULL -_libre_i2d_ASN1_NULL -_libre_ASN1_BMPSTRING_new -_libre_ASN1_BMPSTRING_free -_libre_d2i_ASN1_BMPSTRING -_libre_i2d_ASN1_BMPSTRING -_libre_ASN1_PRINTABLE_new -_libre_ASN1_PRINTABLE_free -_libre_d2i_ASN1_PRINTABLE -_libre_i2d_ASN1_PRINTABLE -_libre_DIRECTORYSTRING_new -_libre_DIRECTORYSTRING_free -_libre_d2i_DIRECTORYSTRING -_libre_i2d_DIRECTORYSTRING -_libre_DISPLAYTEXT_new -_libre_DISPLAYTEXT_free -_libre_d2i_DISPLAYTEXT -_libre_i2d_DISPLAYTEXT -_libre_ASN1_PRINTABLESTRING_new -_libre_ASN1_PRINTABLESTRING_free -_libre_d2i_ASN1_PRINTABLESTRING -_libre_i2d_ASN1_PRINTABLESTRING -_libre_ASN1_T61STRING_new -_libre_ASN1_T61STRING_free -_libre_d2i_ASN1_T61STRING -_libre_i2d_ASN1_T61STRING -_libre_ASN1_IA5STRING_new -_libre_ASN1_IA5STRING_free -_libre_d2i_ASN1_IA5STRING -_libre_i2d_ASN1_IA5STRING -_libre_ASN1_GENERALSTRING_new -_libre_ASN1_GENERALSTRING_free -_libre_d2i_ASN1_GENERALSTRING -_libre_i2d_ASN1_GENERALSTRING -_libre_ASN1_UTCTIME_new -_libre_ASN1_UTCTIME_free -_libre_d2i_ASN1_UTCTIME -_libre_i2d_ASN1_UTCTIME -_libre_ASN1_GENERALIZEDTIME_new -_libre_ASN1_GENERALIZEDTIME_free -_libre_d2i_ASN1_GENERALIZEDTIME -_libre_i2d_ASN1_GENERALIZEDTIME -_libre_ASN1_TIME_new -_libre_ASN1_TIME_free -_libre_d2i_ASN1_TIME -_libre_i2d_ASN1_TIME -_libre_ASN1_TIME_to_tm -_libre_ASN1_TIME_compare -_libre_ASN1_TIME_cmp_time_t -_libre_ASN1_TIME_normalize -_libre_ASN1_TIME_set_string_X509 -_libre_ASN1_TIME_diff -_libre_ASN1_TIME_set -_libre_ASN1_TIME_adj -_libre_ASN1_TIME_check -_libre_ASN1_TIME_to_generalizedtime -_libre_ASN1_TIME_set_string -_libre_i2a_ASN1_INTEGER -_libre_a2i_ASN1_INTEGER -_libre_i2a_ASN1_ENUMERATED -_libre_a2i_ASN1_ENUMERATED -_libre_i2a_ASN1_OBJECT -_libre_a2i_ASN1_STRING -_libre_i2a_ASN1_STRING -_libre_i2t_ASN1_OBJECT -_libre_a2d_ASN1_OBJECT -_libre_ASN1_OBJECT_create -_libre_ASN1_INTEGER_get_uint64 -_libre_ASN1_INTEGER_set_uint64 -_libre_ASN1_INTEGER_get_int64 -_libre_ASN1_INTEGER_set_int64 -_libre_ASN1_INTEGER_set -_libre_ASN1_INTEGER_get -_libre_BN_to_ASN1_INTEGER -_libre_ASN1_INTEGER_to_BN -_libre_ASN1_ENUMERATED_get_int64 -_libre_ASN1_ENUMERATED_set_int64 -_libre_ASN1_ENUMERATED_set -_libre_ASN1_ENUMERATED_get -_libre_BN_to_ASN1_ENUMERATED -_libre_ASN1_ENUMERATED_to_BN -_libre_ASN1_PRINTABLE_type -_libre_ASN1_get_object -_libre_ASN1_put_object -_libre_ASN1_put_eoc -_libre_ASN1_object_size -_libre_ASN1_item_dup -_libre_ASN1_d2i_fp -_libre_ASN1_item_d2i_fp -_libre_ASN1_i2d_fp -_libre_ASN1_item_i2d_fp -_libre_ASN1_STRING_print_ex_fp -_libre_ASN1_STRING_to_UTF8 -_libre_ASN1_d2i_bio -_libre_ASN1_item_d2i_bio -_libre_ASN1_i2d_bio -_libre_ASN1_item_i2d_bio -_libre_ASN1_UTCTIME_print -_libre_ASN1_GENERALIZEDTIME_print -_libre_ASN1_TIME_print -_libre_ASN1_STRING_print -_libre_ASN1_STRING_print_ex -_libre_ASN1_parse -_libre_ASN1_parse_dump -_libre_ASN1_tag2bit -_libre_ASN1_tag2str -_libre_ASN1_UNIVERSALSTRING_to_string -_libre_ASN1_TYPE_set_octetstring -_libre_ASN1_TYPE_get_octetstring -_libre_ASN1_TYPE_set_int_octetstring -_libre_ASN1_TYPE_get_int_octetstring -_libre_ASN1_item_pack -_libre_ASN1_item_unpack -_libre_ASN1_STRING_set_default_mask -_libre_ASN1_STRING_set_default_mask_asc -_libre_ASN1_STRING_get_default_mask -_libre_ASN1_mbstring_copy -_libre_ASN1_mbstring_ncopy -_libre_ASN1_STRING_set_by_NID -_libre_ASN1_STRING_TABLE_get -_libre_ASN1_item_new -_libre_ASN1_item_free -_libre_ASN1_item_d2i -_libre_ASN1_item_i2d -_libre_ASN1_generate_nconf -_libre_ASN1_generate_v3 -_libre_ASN1_item_print -_libre_SMIME_crlf_copy -_libre_SMIME_text -_libre_ERR_load_ASN1_strings -_libre_BIO_set_flags -_libre_BIO_test_flags -_libre_BIO_clear_flags -_libre_BIO_get_callback -_libre_BIO_set_callback -_libre_BIO_get_callback_ex -_libre_BIO_set_callback_ex -_libre_BIO_get_callback_arg -_libre_BIO_set_callback_arg -_libre_BIO_method_name -_libre_BIO_method_type -_libre_BIO_meth_new -_libre_BIO_meth_free -_libre_BIO_meth_get_write -_libre_BIO_meth_set_write -_libre_BIO_meth_get_read -_libre_BIO_meth_set_read -_libre_BIO_meth_get_puts -_libre_BIO_meth_set_puts -_libre_BIO_meth_get_gets -_libre_BIO_meth_set_gets -_libre_BIO_meth_get_ctrl -_libre_BIO_meth_set_ctrl -_libre_BIO_meth_get_create -_libre_BIO_meth_set_create -_libre_BIO_meth_get_destroy -_libre_BIO_meth_set_destroy -_libre_BIO_meth_get_callback_ctrl -_libre_BIO_meth_set_callback_ctrl -_libre_BIO_ctrl_pending -_libre_BIO_ctrl_wpending -_libre_BIO_ctrl_get_write_guarantee -_libre_BIO_ctrl_get_read_request -_libre_BIO_ctrl_reset_read_request -_libre_BIO_set_ex_data -_libre_BIO_get_ex_data -_libre_BIO_number_read -_libre_BIO_number_written -_libre_BIO_get_new_index -_libre_BIO_s_file -_libre_BIO_new_file -_libre_BIO_new_fp -_libre_BIO_new -_libre_BIO_free -_libre_BIO_up_ref -_libre_BIO_get_data -_libre_BIO_set_data -_libre_BIO_get_init -_libre_BIO_set_init -_libre_BIO_get_shutdown -_libre_BIO_set_shutdown -_libre_BIO_vfree -_libre_BIO_read -_libre_BIO_gets -_libre_BIO_write -_libre_BIO_puts -_libre_BIO_indent -_libre_BIO_ctrl -_libre_BIO_callback_ctrl -_libre_BIO_ptr_ctrl -_libre_BIO_int_ctrl -_libre_BIO_push -_libre_BIO_pop -_libre_BIO_free_all -_libre_BIO_find_type -_libre_BIO_next -_libre_BIO_set_next -_libre_BIO_get_retry_BIO -_libre_BIO_get_retry_reason -_libre_BIO_set_retry_reason -_libre_BIO_dup_chain -_libre_BIO_debug_callback -_libre_BIO_s_mem -_libre_BIO_new_mem_buf -_libre_BIO_s_socket -_libre_BIO_s_connect -_libre_BIO_s_accept -_libre_BIO_s_fd -_libre_BIO_s_log -_libre_BIO_s_bio -_libre_BIO_s_null -_libre_BIO_f_null -_libre_BIO_f_buffer -_libre_BIO_f_nbio_test -_libre_BIO_s_datagram -_libre_BIO_sock_should_retry -_libre_BIO_sock_non_fatal_error -_libre_BIO_dgram_non_fatal_error -_libre_BIO_fd_should_retry -_libre_BIO_fd_non_fatal_error -_libre_BIO_dump -_libre_BIO_dump_indent -_libre_BIO_gethostbyname -_libre_BIO_sock_error -_libre_BIO_socket_ioctl -_libre_BIO_socket_nbio -_libre_BIO_get_port -_libre_BIO_get_host_ip -_libre_BIO_get_accept_socket -_libre_BIO_accept -_libre_BIO_sock_init -_libre_BIO_sock_cleanup -_libre_BIO_set_tcp_ndelay -_libre_BIO_new_socket -_libre_BIO_new_dgram -_libre_BIO_new_fd -_libre_BIO_new_connect -_libre_BIO_new_accept -_libre_BIO_copy_next_retry -_libre_BIO_printf -_libre_ERR_load_BIO_strings -_libre_ASN1_item_ex_new -_libre_ASN1_item_ex_free -_libre_ASN1_item_ex_d2i -_libre_ASN1_item_ex_i2d -_libre_EC_GFp_simple_method -_libre_EC_GFp_mont_method -_libre_EC_GROUP_new -_libre_EC_GROUP_free -_libre_EC_GROUP_copy -_libre_EC_GROUP_dup -_libre_EC_GROUP_method_of -_libre_EC_METHOD_get_field_type -_libre_EC_GROUP_set_generator -_libre_EC_GROUP_get0_generator -_libre_EC_GROUP_get_order -_libre_EC_GROUP_order_bits -_libre_EC_GROUP_get_cofactor -_libre_EC_GROUP_set_curve_name -_libre_EC_GROUP_get_curve_name -_libre_EC_GROUP_set_asn1_flag -_libre_EC_GROUP_get_asn1_flag -_libre_EC_GROUP_set_point_conversion_form -_libre_EC_GROUP_get_point_conversion_form -_libre_EC_GROUP_get0_seed -_libre_EC_GROUP_get_seed_len -_libre_EC_GROUP_set_seed -_libre_EC_GROUP_set_curve -_libre_EC_GROUP_get_curve -_libre_EC_GROUP_get_degree -_libre_EC_GROUP_check -_libre_EC_GROUP_check_discriminant -_libre_EC_GROUP_cmp -_libre_EC_GROUP_new_curve_GFp -_libre_EC_GROUP_new_by_curve_name -_libre_EC_get_builtin_curves -_libre_EC_curve_nid2nist -_libre_EC_curve_nist2nid -_libre_EC_POINT_new -_libre_EC_POINT_free -_libre_EC_POINT_copy -_libre_EC_POINT_dup -_libre_EC_POINT_method_of -_libre_EC_POINT_set_to_infinity -_libre_EC_POINT_set_affine_coordinates -_libre_EC_POINT_get_affine_coordinates -_libre_EC_POINT_set_compressed_coordinates -_libre_EC_POINT_point2oct -_libre_EC_POINT_oct2point -_libre_EC_POINT_point2bn -_libre_EC_POINT_bn2point -_libre_EC_POINT_point2hex -_libre_EC_POINT_hex2point -_libre_EC_POINT_add -_libre_EC_POINT_dbl -_libre_EC_POINT_invert -_libre_EC_POINT_is_at_infinity -_libre_EC_POINT_is_on_curve -_libre_EC_POINT_cmp -_libre_EC_POINT_make_affine -_libre_EC_POINTs_make_affine -_libre_EC_POINTs_mul -_libre_EC_POINT_mul -_libre_EC_GROUP_precompute_mult -_libre_EC_GROUP_have_precompute_mult -_libre_EC_GROUP_get_basis_type -_libre_d2i_ECPKParameters -_libre_i2d_ECPKParameters -_libre_ECPKParameters_print -_libre_ECPKParameters_print_fp -_libre_EC_KEY_new -_libre_EC_KEY_get_flags -_libre_EC_KEY_set_flags -_libre_EC_KEY_clear_flags -_libre_EC_KEY_new_by_curve_name -_libre_EC_KEY_free -_libre_EC_KEY_copy -_libre_EC_KEY_dup -_libre_EC_KEY_up_ref -_libre_EC_KEY_get0_group -_libre_EC_KEY_set_group -_libre_EC_KEY_get0_private_key -_libre_EC_KEY_set_private_key -_libre_EC_KEY_get0_public_key -_libre_EC_KEY_set_public_key -_libre_EC_KEY_get_enc_flags -_libre_EC_KEY_set_enc_flags -_libre_EC_KEY_get_conv_form -_libre_EC_KEY_set_conv_form -_libre_EC_KEY_set_asn1_flag -_libre_EC_KEY_precompute_mult -_libre_EC_KEY_generate_key -_libre_EC_KEY_check_key -_libre_EC_KEY_set_public_key_affine_coordinates -_libre_d2i_ECPrivateKey -_libre_i2d_ECPrivateKey -_libre_d2i_ECParameters -_libre_i2d_ECParameters -_libre_o2i_ECPublicKey -_libre_i2o_ECPublicKey -_libre_ECParameters_print -_libre_EC_KEY_print -_libre_ECParameters_print_fp -_libre_EC_KEY_print_fp -_libre_EC_KEY_set_ex_data -_libre_EC_KEY_get_ex_data -_libre_EC_KEY_OpenSSL -_libre_EC_KEY_get_default_method -_libre_EC_KEY_set_default_method -_libre_EC_KEY_get_method -_libre_EC_KEY_set_method -_libre_EC_KEY_new_method -_libre_EC_KEY_METHOD_new -_libre_EC_KEY_METHOD_free -_libre_EC_KEY_METHOD_set_init -_libre_EC_KEY_METHOD_set_keygen -_libre_EC_KEY_METHOD_set_compute_key -_libre_EC_KEY_METHOD_get_init -_libre_EC_KEY_METHOD_get_keygen -_libre_EC_KEY_METHOD_get_compute_key -_libre_ECParameters_dup -_libre_ERR_load_EC_strings -_libre_ERR_put_error -_libre_ERR_set_error_data -_libre_ERR_get_error -_libre_ERR_get_error_line -_libre_ERR_get_error_line_data -_libre_ERR_peek_error -_libre_ERR_peek_error_line -_libre_ERR_peek_error_line_data -_libre_ERR_peek_last_error -_libre_ERR_peek_last_error_line -_libre_ERR_peek_last_error_line_data -_libre_ERR_clear_error -_libre_ERR_error_string -_libre_ERR_error_string_n -_libre_ERR_lib_error_string -_libre_ERR_func_error_string -_libre_ERR_reason_error_string -_libre_ERR_print_errors_cb -_libre_ERR_print_errors_fp -_libre_ERR_print_errors -_libre_ERR_asprintf_error_data -_libre_ERR_load_strings -_libre_ERR_unload_strings -_libre_ERR_load_ERR_strings -_libre_ERR_load_crypto_strings -_libre_ERR_free_strings -_libre_ERR_remove_thread_state -_libre_ERR_remove_state -_libre_ERR_get_next_error_library -_libre_ERR_set_mark -_libre_ERR_pop_to_mark -_libre_RAND_set_rand_method -_libre_RAND_get_rand_method -_libre_RAND_SSLeay -_libre_ERR_load_RAND_strings -_libre_ECDSA_SIG_new -_libre_ECDSA_SIG_free -_libre_i2d_ECDSA_SIG -_libre_d2i_ECDSA_SIG -_libre_ECDSA_SIG_get0 -_libre_ECDSA_SIG_get0_r -_libre_ECDSA_SIG_get0_s -_libre_ECDSA_SIG_set0 -_libre_ECDSA_do_sign -_libre_ECDSA_do_verify -_libre_ECDSA_size -_libre_ECDSA_sign -_libre_ECDSA_verify -_libre_EC_KEY_METHOD_set_sign -_libre_EC_KEY_METHOD_set_verify -_libre_EC_KEY_METHOD_get_sign -_libre_EC_KEY_METHOD_get_verify -_libre_HKDF -_libre_HKDF_extract -_libre_HKDF_expand -_libre_TS_REQ_new -_libre_TS_REQ_free -_libre_i2d_TS_REQ -_libre_d2i_TS_REQ -_libre_TS_REQ_dup -_libre_d2i_TS_REQ_fp -_libre_i2d_TS_REQ_fp -_libre_d2i_TS_REQ_bio -_libre_i2d_TS_REQ_bio -_libre_TS_MSG_IMPRINT_new -_libre_TS_MSG_IMPRINT_free -_libre_i2d_TS_MSG_IMPRINT -_libre_d2i_TS_MSG_IMPRINT -_libre_TS_MSG_IMPRINT_dup -_libre_d2i_TS_MSG_IMPRINT_fp -_libre_i2d_TS_MSG_IMPRINT_fp -_libre_d2i_TS_MSG_IMPRINT_bio -_libre_i2d_TS_MSG_IMPRINT_bio -_libre_TS_RESP_new -_libre_TS_RESP_free -_libre_i2d_TS_RESP -_libre_d2i_TS_RESP -_libre_PKCS7_to_TS_TST_INFO -_libre_TS_RESP_dup -_libre_d2i_TS_RESP_fp -_libre_i2d_TS_RESP_fp -_libre_d2i_TS_RESP_bio -_libre_i2d_TS_RESP_bio -_libre_TS_STATUS_INFO_new -_libre_TS_STATUS_INFO_free -_libre_i2d_TS_STATUS_INFO -_libre_d2i_TS_STATUS_INFO -_libre_TS_STATUS_INFO_dup -_libre_TS_TST_INFO_new -_libre_TS_TST_INFO_free -_libre_i2d_TS_TST_INFO -_libre_d2i_TS_TST_INFO -_libre_TS_TST_INFO_dup -_libre_d2i_TS_TST_INFO_fp -_libre_i2d_TS_TST_INFO_fp -_libre_d2i_TS_TST_INFO_bio -_libre_i2d_TS_TST_INFO_bio -_libre_TS_ACCURACY_new -_libre_TS_ACCURACY_free -_libre_i2d_TS_ACCURACY -_libre_d2i_TS_ACCURACY -_libre_TS_ACCURACY_dup -_libre_ESS_ISSUER_SERIAL_new -_libre_ESS_ISSUER_SERIAL_free -_libre_i2d_ESS_ISSUER_SERIAL -_libre_d2i_ESS_ISSUER_SERIAL -_libre_ESS_ISSUER_SERIAL_dup -_libre_ESS_CERT_ID_new -_libre_ESS_CERT_ID_free -_libre_i2d_ESS_CERT_ID -_libre_d2i_ESS_CERT_ID -_libre_ESS_CERT_ID_dup -_libre_ESS_SIGNING_CERT_new -_libre_ESS_SIGNING_CERT_free -_libre_i2d_ESS_SIGNING_CERT -_libre_d2i_ESS_SIGNING_CERT -_libre_ESS_SIGNING_CERT_dup -_libre_TS_REQ_set_version -_libre_TS_REQ_get_version -_libre_TS_REQ_set_msg_imprint -_libre_TS_REQ_get_msg_imprint -_libre_TS_MSG_IMPRINT_set_algo -_libre_TS_MSG_IMPRINT_get_algo -_libre_TS_MSG_IMPRINT_set_msg -_libre_TS_MSG_IMPRINT_get_msg -_libre_TS_REQ_set_policy_id -_libre_TS_REQ_get_policy_id -_libre_TS_REQ_set_nonce -_libre_TS_REQ_get_nonce -_libre_TS_REQ_set_cert_req -_libre_TS_REQ_get_cert_req -_libre_TS_REQ_get_exts -_libre_TS_REQ_ext_free -_libre_TS_REQ_get_ext_count -_libre_TS_REQ_get_ext_by_NID -_libre_TS_REQ_get_ext_by_OBJ -_libre_TS_REQ_get_ext_by_critical -_libre_TS_REQ_get_ext -_libre_TS_REQ_delete_ext -_libre_TS_REQ_add_ext -_libre_TS_REQ_get_ext_d2i -_libre_TS_REQ_print_bio -_libre_TS_RESP_set_status_info -_libre_TS_RESP_get_status_info -_libre_TS_STATUS_INFO_get0_failure_info -_libre_TS_STATUS_INFO_get0_text -_libre_TS_STATUS_INFO_get0_status -_libre_TS_STATUS_INFO_set_status -_libre_TS_RESP_set_tst_info -_libre_TS_RESP_get_token -_libre_TS_RESP_get_tst_info -_libre_TS_TST_INFO_set_version -_libre_TS_TST_INFO_get_version -_libre_TS_TST_INFO_set_policy_id -_libre_TS_TST_INFO_get_policy_id -_libre_TS_TST_INFO_set_msg_imprint -_libre_TS_TST_INFO_get_msg_imprint -_libre_TS_TST_INFO_set_serial -_libre_TS_TST_INFO_get_serial -_libre_TS_TST_INFO_set_time -_libre_TS_TST_INFO_get_time -_libre_TS_TST_INFO_set_accuracy -_libre_TS_TST_INFO_get_accuracy -_libre_TS_ACCURACY_set_seconds -_libre_TS_ACCURACY_get_seconds -_libre_TS_ACCURACY_set_millis -_libre_TS_ACCURACY_get_millis -_libre_TS_ACCURACY_set_micros -_libre_TS_ACCURACY_get_micros -_libre_TS_TST_INFO_set_ordering -_libre_TS_TST_INFO_get_ordering -_libre_TS_TST_INFO_set_nonce -_libre_TS_TST_INFO_get_nonce -_libre_TS_TST_INFO_set_tsa -_libre_TS_TST_INFO_get_tsa -_libre_TS_TST_INFO_get_exts -_libre_TS_TST_INFO_ext_free -_libre_TS_TST_INFO_get_ext_count -_libre_TS_TST_INFO_get_ext_by_NID -_libre_TS_TST_INFO_get_ext_by_OBJ -_libre_TS_TST_INFO_get_ext_by_critical -_libre_TS_TST_INFO_get_ext -_libre_TS_TST_INFO_delete_ext -_libre_TS_TST_INFO_add_ext -_libre_TS_TST_INFO_get_ext_d2i -_libre_TS_RESP_CTX_new -_libre_TS_RESP_CTX_free -_libre_TS_RESP_CTX_set_signer_cert -_libre_TS_RESP_CTX_set_signer_key -_libre_TS_RESP_CTX_set_def_policy -_libre_TS_RESP_CTX_set_certs -_libre_TS_RESP_CTX_add_policy -_libre_TS_RESP_CTX_add_md -_libre_TS_RESP_CTX_set_accuracy -_libre_TS_RESP_CTX_set_clock_precision_digits -_libre_TS_RESP_CTX_add_flags -_libre_TS_RESP_CTX_set_serial_cb -_libre_TS_RESP_CTX_set_time_cb -_libre_TS_RESP_CTX_set_extension_cb -_libre_TS_RESP_CTX_set_status_info -_libre_TS_RESP_CTX_set_status_info_cond -_libre_TS_RESP_CTX_add_failure_info -_libre_TS_RESP_CTX_get_request -_libre_TS_RESP_CTX_get_tst_info -_libre_TS_RESP_create_response -_libre_TS_RESP_verify_signature -_libre_TS_RESP_verify_response -_libre_TS_RESP_verify_token -_libre_TS_VERIFY_CTX_new -_libre_TS_VERIFY_CTX_free -_libre_TS_VERIFY_CTX_cleanup -_libre_TS_VERIFY_CTX_add_flags -_libre_TS_VERIFY_CTX_set_flags -_libre_TS_VERIFY_CTX_set_data -_libre_TS_VERIFY_CTX_set_store -_libre_TS_VERIFY_CTX_set_certs -_libre_TS_VERIFY_CTX_set_imprint -_libre_TS_REQ_to_TS_VERIFY_CTX -_libre_TS_RESP_print_bio -_libre_TS_STATUS_INFO_print_bio -_libre_TS_TST_INFO_print_bio -_libre_TS_ASN1_INTEGER_print_bio -_libre_TS_OBJ_print_bio -_libre_TS_ext_print_bio -_libre_TS_X509_ALGOR_print_bio -_libre_TS_MSG_IMPRINT_print_bio -_libre_TS_CONF_load_cert -_libre_TS_CONF_load_certs -_libre_TS_CONF_load_key -_libre_TS_CONF_get_tsa_section -_libre_TS_CONF_set_serial -_libre_TS_CONF_set_signer_cert -_libre_TS_CONF_set_certs -_libre_TS_CONF_set_signer_key -_libre_TS_CONF_set_def_policy -_libre_TS_CONF_set_policies -_libre_TS_CONF_set_digests -_libre_TS_CONF_set_accuracy -_libre_TS_CONF_set_clock_precision_digits -_libre_TS_CONF_set_ordering -_libre_TS_CONF_set_tsa_name -_libre_TS_CONF_set_ess_cert_id_chain -_libre_ERR_load_TS_strings -_libre_SM4_set_key -_libre_SM4_decrypt -_libre_SM4_encrypt -_libre_CRYPTO_poly1305_init -_libre_CRYPTO_poly1305_update -_libre_CRYPTO_poly1305_finish -_libre_ECDH_size -_libre_ECDH_compute_key -_libre_PEM_get_EVP_CIPHER_INFO -_libre_PEM_do_header -_libre_PEM_read_bio -_libre_PEM_write_bio -_libre_PEM_bytes_read_bio -_libre_PEM_ASN1_read_bio -_libre_PEM_ASN1_write_bio -_libre_PEM_X509_INFO_read_bio -_libre_PEM_X509_INFO_write_bio -_libre_PEM_read -_libre_PEM_write -_libre_PEM_ASN1_read -_libre_PEM_ASN1_write -_libre_PEM_X509_INFO_read -_libre_PEM_SignInit -_libre_PEM_SignUpdate -_libre_PEM_SignFinal -_libre_PEM_def_callback -_libre_PEM_proc_type -_libre_PEM_dek_info -_libre_PEM_read_X509 -_libre_PEM_read_bio_X509 -_libre_PEM_write_X509 -_libre_PEM_write_bio_X509 -_libre_PEM_read_X509_AUX -_libre_PEM_read_bio_X509_AUX -_libre_PEM_write_X509_AUX -_libre_PEM_write_bio_X509_AUX -_libre_PEM_read_X509_REQ -_libre_PEM_read_bio_X509_REQ -_libre_PEM_write_X509_REQ -_libre_PEM_write_bio_X509_REQ -_libre_PEM_write_X509_REQ_NEW -_libre_PEM_write_bio_X509_REQ_NEW -_libre_PEM_read_X509_CRL -_libre_PEM_read_bio_X509_CRL -_libre_PEM_write_X509_CRL -_libre_PEM_write_bio_X509_CRL -_libre_PEM_read_PKCS7 -_libre_PEM_read_bio_PKCS7 -_libre_PEM_write_PKCS7 -_libre_PEM_write_bio_PKCS7 -_libre_PEM_read_PKCS8 -_libre_PEM_read_bio_PKCS8 -_libre_PEM_write_PKCS8 -_libre_PEM_write_bio_PKCS8 -_libre_PEM_read_PKCS8_PRIV_KEY_INFO -_libre_PEM_read_bio_PKCS8_PRIV_KEY_INFO -_libre_PEM_write_PKCS8_PRIV_KEY_INFO -_libre_PEM_write_bio_PKCS8_PRIV_KEY_INFO -_libre_PEM_read_RSAPrivateKey -_libre_PEM_read_bio_RSAPrivateKey -_libre_PEM_write_RSAPrivateKey -_libre_PEM_write_bio_RSAPrivateKey -_libre_PEM_read_RSAPublicKey -_libre_PEM_read_bio_RSAPublicKey -_libre_PEM_write_RSAPublicKey -_libre_PEM_write_bio_RSAPublicKey -_libre_PEM_read_RSA_PUBKEY -_libre_PEM_read_bio_RSA_PUBKEY -_libre_PEM_write_RSA_PUBKEY -_libre_PEM_write_bio_RSA_PUBKEY -_libre_PEM_read_DSAPrivateKey -_libre_PEM_read_bio_DSAPrivateKey -_libre_PEM_write_DSAPrivateKey -_libre_PEM_write_bio_DSAPrivateKey -_libre_PEM_read_DSA_PUBKEY -_libre_PEM_read_bio_DSA_PUBKEY -_libre_PEM_write_DSA_PUBKEY -_libre_PEM_write_bio_DSA_PUBKEY -_libre_PEM_read_DSAparams -_libre_PEM_read_bio_DSAparams -_libre_PEM_write_DSAparams -_libre_PEM_write_bio_DSAparams -_libre_PEM_read_ECPKParameters -_libre_PEM_read_bio_ECPKParameters -_libre_PEM_write_ECPKParameters -_libre_PEM_write_bio_ECPKParameters -_libre_PEM_read_ECPrivateKey -_libre_PEM_read_bio_ECPrivateKey -_libre_PEM_write_ECPrivateKey -_libre_PEM_write_bio_ECPrivateKey -_libre_PEM_read_EC_PUBKEY -_libre_PEM_read_bio_EC_PUBKEY -_libre_PEM_write_EC_PUBKEY -_libre_PEM_write_bio_EC_PUBKEY -_libre_PEM_read_DHparams -_libre_PEM_read_bio_DHparams -_libre_PEM_write_DHparams -_libre_PEM_write_bio_DHparams -_libre_PEM_read_PrivateKey -_libre_PEM_read_bio_PrivateKey -_libre_PEM_write_PrivateKey -_libre_PEM_write_bio_PrivateKey -_libre_PEM_read_PUBKEY -_libre_PEM_read_bio_PUBKEY -_libre_PEM_write_PUBKEY -_libre_PEM_write_bio_PUBKEY -_libre_PEM_write_bio_PrivateKey_traditional -_libre_PEM_write_bio_PKCS8PrivateKey_nid -_libre_PEM_write_bio_PKCS8PrivateKey -_libre_i2d_PKCS8PrivateKey_bio -_libre_i2d_PKCS8PrivateKey_nid_bio -_libre_d2i_PKCS8PrivateKey_bio -_libre_i2d_PKCS8PrivateKey_fp -_libre_i2d_PKCS8PrivateKey_nid_fp -_libre_PEM_write_PKCS8PrivateKey_nid -_libre_d2i_PKCS8PrivateKey_fp -_libre_PEM_write_PKCS8PrivateKey -_libre_PEM_read_bio_Parameters -_libre_PEM_write_bio_Parameters -_libre_b2i_PrivateKey -_libre_b2i_PublicKey -_libre_b2i_PrivateKey_bio -_libre_b2i_PublicKey_bio -_libre_i2b_PrivateKey_bio -_libre_i2b_PublicKey_bio -_libre_b2i_PVK_bio -_libre_i2b_PVK_bio -_libre_ERR_load_PEM_strings -_libre_lh_new -_libre_lh_free -_libre_lh_insert -_libre_lh_delete -_libre_lh_retrieve -_libre_lh_doall -_libre_lh_doall_arg -_libre_lh_strhash -_libre_lh_num_items -_libre_SM3_Init -_libre_SM3_Update -_libre_SM3_Final -_libre_CT_POLICY_EVAL_CTX_new -_libre_CT_POLICY_EVAL_CTX_free -_libre_CT_POLICY_EVAL_CTX_get0_cert -_libre_CT_POLICY_EVAL_CTX_set1_cert -_libre_CT_POLICY_EVAL_CTX_get0_issuer -_libre_CT_POLICY_EVAL_CTX_set1_issuer -_libre_CT_POLICY_EVAL_CTX_get0_log_store -_libre_CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE -_libre_CT_POLICY_EVAL_CTX_get_time -_libre_CT_POLICY_EVAL_CTX_set_time -_libre_SCT_new -_libre_SCT_new_from_base64 -_libre_SCT_free -_libre_SCT_LIST_free -_libre_SCT_get_version -_libre_SCT_set_version -_libre_SCT_get_log_entry_type -_libre_SCT_set_log_entry_type -_libre_SCT_get0_log_id -_libre_SCT_set0_log_id -_libre_SCT_set1_log_id -_libre_SCT_get_timestamp -_libre_SCT_set_timestamp -_libre_SCT_get_signature_nid -_libre_SCT_set_signature_nid -_libre_SCT_get0_extensions -_libre_SCT_set0_extensions -_libre_SCT_set1_extensions -_libre_SCT_get0_signature -_libre_SCT_set0_signature -_libre_SCT_set1_signature -_libre_SCT_get_source -_libre_SCT_set_source -_libre_SCT_validation_status_string -_libre_SCT_print -_libre_SCT_LIST_print -_libre_SCT_get_validation_status -_libre_SCT_validate -_libre_SCT_LIST_validate -_libre_i2o_SCT_LIST -_libre_o2i_SCT_LIST -_libre_i2d_SCT_LIST -_libre_d2i_SCT_LIST -_libre_i2o_SCT -_libre_o2i_SCT -_libre_CTLOG_new -_libre_CTLOG_new_from_base64 -_libre_CTLOG_free -_libre_CTLOG_get0_name -_libre_CTLOG_get0_log_id -_libre_CTLOG_get0_public_key -_libre_CTLOG_STORE_new -_libre_CTLOG_STORE_free -_libre_CTLOG_STORE_get0_log_by_id -_libre_CTLOG_STORE_load_file -_libre_CTLOG_STORE_load_default_file -_libre__CONF_new_section -_libre__CONF_get_section -_libre__CONF_get_section_values -_libre__CONF_add_string -_libre__CONF_get_string -_libre__CONF_new_data -_libre__CONF_free_data -_libre_CMS_ContentInfo_new -_libre_CMS_ContentInfo_free -_libre_d2i_CMS_ContentInfo -_libre_i2d_CMS_ContentInfo -_libre_CMS_ReceiptRequest_new -_libre_CMS_ReceiptRequest_free -_libre_d2i_CMS_ReceiptRequest -_libre_i2d_CMS_ReceiptRequest -_libre_CMS_ContentInfo_print_ctx -_libre_CMS_get0_type -_libre_CMS_get_version -_libre_CMS_SignerInfo_get_version -_libre_CMS_dataInit -_libre_CMS_dataFinal -_libre_CMS_is_detached -_libre_CMS_set_detached -_libre_CMS_stream -_libre_d2i_CMS_bio -_libre_i2d_CMS_bio -_libre_BIO_new_CMS -_libre_i2d_CMS_bio_stream -_libre_PEM_write_bio_CMS_stream -_libre_SMIME_read_CMS -_libre_SMIME_write_CMS -_libre_CMS_final -_libre_CMS_sign -_libre_CMS_sign_receipt -_libre_CMS_data -_libre_CMS_data_create -_libre_CMS_digest_verify -_libre_CMS_digest_create -_libre_CMS_EncryptedData_decrypt -_libre_CMS_EncryptedData_encrypt -_libre_CMS_EncryptedData_set1_key -_libre_CMS_verify -_libre_CMS_verify_receipt -_libre_CMS_get0_signers -_libre_CMS_encrypt -_libre_CMS_decrypt -_libre_CMS_decrypt_set1_pkey -_libre_CMS_decrypt_set1_key -_libre_CMS_decrypt_set1_password -_libre_CMS_get0_RecipientInfos -_libre_CMS_RecipientInfo_type -_libre_CMS_RecipientInfo_get0_pkey_ctx -_libre_CMS_EnvelopedData_create -_libre_CMS_add1_recipient_cert -_libre_CMS_RecipientInfo_set0_pkey -_libre_CMS_RecipientInfo_ktri_cert_cmp -_libre_CMS_RecipientInfo_ktri_get0_algs -_libre_CMS_RecipientInfo_ktri_get0_signer_id -_libre_CMS_add0_recipient_key -_libre_CMS_RecipientInfo_kekri_get0_id -_libre_CMS_RecipientInfo_set0_key -_libre_CMS_RecipientInfo_kekri_id_cmp -_libre_CMS_RecipientInfo_set0_password -_libre_CMS_add0_recipient_password -_libre_CMS_RecipientInfo_decrypt -_libre_CMS_RecipientInfo_encrypt -_libre_CMS_uncompress -_libre_CMS_compress -_libre_CMS_set1_eContentType -_libre_CMS_get0_eContentType -_libre_CMS_add0_CertificateChoices -_libre_CMS_add0_cert -_libre_CMS_add1_cert -_libre_CMS_get1_certs -_libre_CMS_add0_RevocationInfoChoice -_libre_CMS_add0_crl -_libre_CMS_add1_crl -_libre_CMS_get1_crls -_libre_CMS_SignedData_init -_libre_CMS_add1_signer -_libre_CMS_SignerInfo_get0_pkey_ctx -_libre_CMS_SignerInfo_get0_md_ctx -_libre_CMS_get0_SignerInfos -_libre_CMS_SignerInfo_set1_signer_cert -_libre_CMS_SignerInfo_get0_signer_id -_libre_CMS_SignerInfo_cert_cmp -_libre_CMS_set1_signers_certs -_libre_CMS_SignerInfo_get0_algs -_libre_CMS_SignerInfo_get0_signature -_libre_CMS_SignerInfo_sign -_libre_CMS_SignerInfo_verify -_libre_CMS_SignerInfo_verify_content -_libre_CMS_add_smimecap -_libre_CMS_add_simple_smimecap -_libre_CMS_add_standard_smimecap -_libre_CMS_signed_get_attr_count -_libre_CMS_signed_get_attr_by_NID -_libre_CMS_signed_get_attr_by_OBJ -_libre_CMS_signed_get_attr -_libre_CMS_signed_delete_attr -_libre_CMS_signed_add1_attr -_libre_CMS_signed_add1_attr_by_OBJ -_libre_CMS_signed_add1_attr_by_NID -_libre_CMS_signed_add1_attr_by_txt -_libre_CMS_signed_get0_data_by_OBJ -_libre_CMS_unsigned_get_attr_count -_libre_CMS_unsigned_get_attr_by_NID -_libre_CMS_unsigned_get_attr_by_OBJ -_libre_CMS_unsigned_get_attr -_libre_CMS_unsigned_delete_attr -_libre_CMS_unsigned_add1_attr -_libre_CMS_unsigned_add1_attr_by_OBJ -_libre_CMS_unsigned_add1_attr_by_NID -_libre_CMS_unsigned_add1_attr_by_txt -_libre_CMS_unsigned_get0_data_by_OBJ -_libre_CMS_RecipientInfo_kari_get0_alg -_libre_CMS_RecipientInfo_kari_get0_reks -_libre_CMS_RecipientInfo_kari_get0_orig_id -_libre_CMS_RecipientInfo_kari_orig_id_cmp -_libre_CMS_RecipientEncryptedKey_get0_id -_libre_CMS_RecipientEncryptedKey_cert_cmp -_libre_CMS_RecipientInfo_kari_set0_pkey -_libre_CMS_RecipientInfo_kari_get0_ctx -_libre_CMS_RecipientInfo_kari_decrypt -_libre_CMS_SharedInfo_encode -_libre_ERR_load_CMS_strings -_libre_BUF_MEM_new -_libre_BUF_MEM_free -_libre_BUF_MEM_grow -_libre_BUF_MEM_grow_clean -_libre_ERR_load_BUF_strings -_libre_OpenSSL_version -_libre_OpenSSL_version_num -_libre_SSLeay_version -_libre_SSLeay -_libre_CRYPTO_get_ex_new_index -_libre_CRYPTO_new_ex_data -_libre_CRYPTO_dup_ex_data -_libre_CRYPTO_free_ex_data -_libre_CRYPTO_set_ex_data -_libre_CRYPTO_get_ex_data -_libre_CRYPTO_cleanup_all_ex_data -_libre_CRYPTO_lock -_libre_CRYPTO_add_lock -_libre_CRYPTO_set_mem_functions -_libre_CRYPTO_set_mem_ex_functions -_libre_OpenSSLDie -_libre_OPENSSL_cpu_caps -_libre_OPENSSL_init_crypto -_libre_OPENSSL_cleanup -_libre_ERR_load_CRYPTO_strings -_libre_CAST_set_key -_libre_CAST_ecb_encrypt -_libre_CAST_encrypt -_libre_CAST_decrypt -_libre_CAST_cbc_encrypt -_libre_CAST_cfb64_encrypt -_libre_CAST_ofb64_encrypt -_libre_idea_ecb_encrypt -_libre_idea_set_encrypt_key -_libre_idea_set_decrypt_key -_libre_idea_cbc_encrypt -_libre_idea_cfb64_encrypt -_libre_idea_ofb64_encrypt -_libre_idea_encrypt -_libre_OCSP_CERTID_dup -_libre_OCSP_sendreq_bio -_libre_OCSP_sendreq_new -_libre_OCSP_sendreq_nbio -_libre_OCSP_REQ_CTX_free -_libre_OCSP_REQ_CTX_set1_req -_libre_OCSP_REQ_CTX_add1_header -_libre_OCSP_cert_to_id -_libre_OCSP_cert_id_new -_libre_OCSP_request_add0_id -_libre_OCSP_request_add1_nonce -_libre_OCSP_basic_add1_nonce -_libre_OCSP_check_nonce -_libre_OCSP_copy_nonce -_libre_OCSP_request_set1_name -_libre_OCSP_request_add1_cert -_libre_OCSP_request_sign -_libre_OCSP_response_status -_libre_OCSP_response_get1_basic -_libre_OCSP_resp_get0_signature -_libre_OCSP_resp_get0_tbs_sigalg -_libre_OCSP_resp_get0_respdata -_libre_OCSP_resp_get0_signer -_libre_OCSP_resp_count -_libre_OCSP_resp_get0 -_libre_OCSP_resp_get0_produced_at -_libre_OCSP_resp_get0_certs -_libre_OCSP_resp_get0_id -_libre_OCSP_resp_find -_libre_OCSP_single_get0_status -_libre_OCSP_resp_find_status -_libre_OCSP_check_validity -_libre_OCSP_request_verify -_libre_OCSP_parse_url -_libre_OCSP_id_issuer_cmp -_libre_OCSP_id_cmp -_libre_OCSP_request_onereq_count -_libre_OCSP_request_onereq_get0 -_libre_OCSP_onereq_get0_id -_libre_OCSP_id_get0_info -_libre_OCSP_request_is_signed -_libre_OCSP_response_create -_libre_OCSP_basic_add1_status -_libre_OCSP_basic_add1_cert -_libre_OCSP_basic_sign -_libre_OCSP_crlID_new -_libre_OCSP_accept_responses_new -_libre_OCSP_archive_cutoff_new -_libre_OCSP_url_svcloc_new -_libre_OCSP_REQUEST_get_ext_count -_libre_OCSP_REQUEST_get_ext_by_NID -_libre_OCSP_REQUEST_get_ext_by_OBJ -_libre_OCSP_REQUEST_get_ext_by_critical -_libre_OCSP_REQUEST_get_ext -_libre_OCSP_REQUEST_delete_ext -_libre_OCSP_REQUEST_get1_ext_d2i -_libre_OCSP_REQUEST_add1_ext_i2d -_libre_OCSP_REQUEST_add_ext -_libre_OCSP_ONEREQ_get_ext_count -_libre_OCSP_ONEREQ_get_ext_by_NID -_libre_OCSP_ONEREQ_get_ext_by_OBJ -_libre_OCSP_ONEREQ_get_ext_by_critical -_libre_OCSP_ONEREQ_get_ext -_libre_OCSP_ONEREQ_delete_ext -_libre_OCSP_ONEREQ_get1_ext_d2i -_libre_OCSP_ONEREQ_add1_ext_i2d -_libre_OCSP_ONEREQ_add_ext -_libre_OCSP_BASICRESP_get_ext_count -_libre_OCSP_BASICRESP_get_ext_by_NID -_libre_OCSP_BASICRESP_get_ext_by_OBJ -_libre_OCSP_BASICRESP_get_ext_by_critical -_libre_OCSP_BASICRESP_get_ext -_libre_OCSP_BASICRESP_delete_ext -_libre_OCSP_BASICRESP_get1_ext_d2i -_libre_OCSP_BASICRESP_add1_ext_i2d -_libre_OCSP_BASICRESP_add_ext -_libre_OCSP_SINGLERESP_get_ext_count -_libre_OCSP_SINGLERESP_get_ext_by_NID -_libre_OCSP_SINGLERESP_get_ext_by_OBJ -_libre_OCSP_SINGLERESP_get_ext_by_critical -_libre_OCSP_SINGLERESP_get_ext -_libre_OCSP_SINGLERESP_delete_ext -_libre_OCSP_SINGLERESP_get1_ext_d2i -_libre_OCSP_SINGLERESP_add1_ext_i2d -_libre_OCSP_SINGLERESP_add_ext -_libre_OCSP_SINGLERESP_get0_id -_libre_OCSP_SINGLERESP_new -_libre_OCSP_SINGLERESP_free -_libre_d2i_OCSP_SINGLERESP -_libre_i2d_OCSP_SINGLERESP -_libre_OCSP_CERTSTATUS_new -_libre_OCSP_CERTSTATUS_free -_libre_d2i_OCSP_CERTSTATUS -_libre_i2d_OCSP_CERTSTATUS -_libre_OCSP_REVOKEDINFO_new -_libre_OCSP_REVOKEDINFO_free -_libre_d2i_OCSP_REVOKEDINFO -_libre_i2d_OCSP_REVOKEDINFO -_libre_OCSP_BASICRESP_new -_libre_OCSP_BASICRESP_free -_libre_d2i_OCSP_BASICRESP -_libre_i2d_OCSP_BASICRESP -_libre_OCSP_RESPDATA_new -_libre_OCSP_RESPDATA_free -_libre_d2i_OCSP_RESPDATA -_libre_i2d_OCSP_RESPDATA -_libre_OCSP_RESPID_new -_libre_OCSP_RESPID_free -_libre_d2i_OCSP_RESPID -_libre_i2d_OCSP_RESPID -_libre_OCSP_RESPONSE_new -_libre_OCSP_RESPONSE_free -_libre_d2i_OCSP_RESPONSE -_libre_i2d_OCSP_RESPONSE -_libre_d2i_OCSP_RESPONSE_bio -_libre_i2d_OCSP_RESPONSE_bio -_libre_OCSP_RESPBYTES_new -_libre_OCSP_RESPBYTES_free -_libre_d2i_OCSP_RESPBYTES -_libre_i2d_OCSP_RESPBYTES -_libre_OCSP_ONEREQ_new -_libre_OCSP_ONEREQ_free -_libre_d2i_OCSP_ONEREQ -_libre_i2d_OCSP_ONEREQ -_libre_OCSP_CERTID_new -_libre_OCSP_CERTID_free -_libre_d2i_OCSP_CERTID -_libre_i2d_OCSP_CERTID -_libre_OCSP_REQUEST_new -_libre_OCSP_REQUEST_free -_libre_d2i_OCSP_REQUEST -_libre_i2d_OCSP_REQUEST -_libre_d2i_OCSP_REQUEST_bio -_libre_i2d_OCSP_REQUEST_bio -_libre_OCSP_SIGNATURE_new -_libre_OCSP_SIGNATURE_free -_libre_d2i_OCSP_SIGNATURE -_libre_i2d_OCSP_SIGNATURE -_libre_OCSP_REQINFO_new -_libre_OCSP_REQINFO_free -_libre_d2i_OCSP_REQINFO -_libre_i2d_OCSP_REQINFO -_libre_OCSP_CRLID_new -_libre_OCSP_CRLID_free -_libre_d2i_OCSP_CRLID -_libre_i2d_OCSP_CRLID -_libre_OCSP_SERVICELOC_new -_libre_OCSP_SERVICELOC_free -_libre_d2i_OCSP_SERVICELOC -_libre_i2d_OCSP_SERVICELOC -_libre_OCSP_response_status_str -_libre_OCSP_cert_status_str -_libre_OCSP_crl_reason_str -_libre_OCSP_REQUEST_print -_libre_OCSP_RESPONSE_print -_libre_OCSP_basic_verify -_libre_ERR_load_OCSP_strings -_libre_MD5_Init -_libre_MD5_Update -_libre_MD5_Final -_libre_MD5 -_libre_MD5_Transform -_libre_MD4_Init -_libre_MD4_Update -_libre_MD4_Final -_libre_MD4 -_libre_MD4_Transform -_libre_TXT_DB_read -_libre_TXT_DB_write -_libre_TXT_DB_create_index -_libre_TXT_DB_free -_libre_TXT_DB_get_by_index -_libre_TXT_DB_insert -_libre_BN_set_flags -_libre_BN_get_flags -_libre_BN_with_flags -_libre_BN_GENCB_new -_libre_BN_GENCB_free -_libre_BN_GENCB_call -_libre_BN_GENCB_set_old -_libre_BN_GENCB_set -_libre_BN_GENCB_get_arg -_libre_BN_abs_is_word -_libre_BN_is_zero -_libre_BN_is_one -_libre_BN_is_word -_libre_BN_is_odd -_libre_BN_zero -_libre_BN_one -_libre_BN_value_one -_libre_BN_CTX_new -_libre_BN_CTX_free -_libre_BN_CTX_start -_libre_BN_CTX_get -_libre_BN_CTX_end -_libre_BN_rand -_libre_BN_pseudo_rand -_libre_BN_rand_range -_libre_BN_pseudo_rand_range -_libre_BN_num_bits -_libre_BN_num_bits_word -_libre_BN_new -_libre_BN_clear_free -_libre_BN_copy -_libre_BN_swap -_libre_BN_bin2bn -_libre_BN_bn2bin -_libre_BN_bn2binpad -_libre_BN_lebin2bn -_libre_BN_bn2lebinpad -_libre_BN_mpi2bn -_libre_BN_bn2mpi -_libre_BN_sub -_libre_BN_usub -_libre_BN_uadd -_libre_BN_add -_libre_BN_mul -_libre_BN_sqr -_libre_BN_set_negative -_libre_BN_is_negative -_libre_BN_nnmod -_libre_BN_mod_add -_libre_BN_mod_add_quick -_libre_BN_mod_sub -_libre_BN_mod_sub_quick -_libre_BN_mod_mul -_libre_BN_mod_sqr -_libre_BN_mod_lshift1 -_libre_BN_mod_lshift1_quick -_libre_BN_mod_lshift -_libre_BN_mod_lshift_quick -_libre_BN_mod_word -_libre_BN_div_word -_libre_BN_mul_word -_libre_BN_add_word -_libre_BN_sub_word -_libre_BN_set_word -_libre_BN_get_word -_libre_BN_cmp -_libre_BN_free -_libre_BN_is_bit_set -_libre_BN_lshift -_libre_BN_lshift1 -_libre_BN_exp -_libre_BN_mod_exp_mont_consttime -_libre_BN_mask_bits -_libre_BN_print_fp -_libre_BN_print -_libre_BN_rshift -_libre_BN_rshift1 -_libre_BN_clear -_libre_BN_dup -_libre_BN_ucmp -_libre_BN_set_bit -_libre_BN_clear_bit -_libre_BN_bn2hex -_libre_BN_bn2dec -_libre_BN_hex2bn -_libre_BN_dec2bn -_libre_BN_asc2bn -_libre_BN_kronecker -_libre_BN_mod_sqrt -_libre_BN_consttime_swap -_libre_BN_security_bits -_libre_BN_generate_prime_ex -_libre_BN_is_prime_ex -_libre_BN_is_prime_fasttest_ex -_libre_BN_MONT_CTX_new -_libre_BN_mod_mul_montgomery -_libre_BN_to_montgomery -_libre_BN_from_montgomery -_libre_BN_MONT_CTX_free -_libre_BN_MONT_CTX_set -_libre_BN_MONT_CTX_copy -_libre_BN_MONT_CTX_set_locked -_libre_BN_get_rfc2409_prime_768 -_libre_BN_get_rfc2409_prime_1024 -_libre_BN_get_rfc3526_prime_1536 -_libre_BN_get_rfc3526_prime_2048 -_libre_BN_get_rfc3526_prime_3072 -_libre_BN_get_rfc3526_prime_4096 -_libre_BN_get_rfc3526_prime_6144 -_libre_BN_get_rfc3526_prime_8192 -_libre_ERR_load_BN_strings -_libre_SHA1_Init -_libre_SHA1_Update -_libre_SHA1_Final -_libre_SHA1 -_libre_SHA1_Transform -_libre_SHA224_Init -_libre_SHA224_Update -_libre_SHA224_Final -_libre_SHA224 -_libre_SHA256_Init -_libre_SHA256_Update -_libre_SHA256_Final -_libre_SHA256 -_libre_SHA256_Transform -_libre_SHA384_Init -_libre_SHA384_Update -_libre_SHA384_Final -_libre_SHA384 -_libre_SHA512_Init -_libre_SHA512_Update -_libre_SHA512_Final -_libre_SHA512 -_libre_SHA512_Transform -_libre_RSA_new -_libre_RSA_new_method -_libre_RSA_bits -_libre_RSA_size -_libre_RSA_generate_key -_libre_RSA_generate_key_ex -_libre_RSA_check_key -_libre_RSA_public_encrypt -_libre_RSA_private_encrypt -_libre_RSA_public_decrypt -_libre_RSA_private_decrypt -_libre_RSA_free -_libre_RSA_up_ref -_libre_RSA_flags -_libre_RSA_set_default_method -_libre_RSA_get_default_method -_libre_RSA_get_method -_libre_RSA_set_method -_libre_RSA_PKCS1_OpenSSL -_libre_RSA_PKCS1_SSLeay -_libre_RSA_pkey_ctx_ctrl -_libre_d2i_RSAPublicKey -_libre_i2d_RSAPublicKey -_libre_d2i_RSAPrivateKey -_libre_i2d_RSAPrivateKey -_libre_RSA_PSS_PARAMS_new -_libre_RSA_PSS_PARAMS_free -_libre_d2i_RSA_PSS_PARAMS -_libre_i2d_RSA_PSS_PARAMS -_libre_RSA_OAEP_PARAMS_new -_libre_RSA_OAEP_PARAMS_free -_libre_d2i_RSA_OAEP_PARAMS -_libre_i2d_RSA_OAEP_PARAMS -_libre_RSA_print_fp -_libre_RSA_print -_libre_RSA_sign -_libre_RSA_verify -_libre_RSA_sign_ASN1_OCTET_STRING -_libre_RSA_verify_ASN1_OCTET_STRING -_libre_RSA_blinding_on -_libre_RSA_blinding_off -_libre_RSA_padding_add_PKCS1_type_1 -_libre_RSA_padding_check_PKCS1_type_1 -_libre_RSA_padding_add_PKCS1_type_2 -_libre_RSA_padding_check_PKCS1_type_2 -_libre_PKCS1_MGF1 -_libre_RSA_padding_add_PKCS1_OAEP -_libre_RSA_padding_check_PKCS1_OAEP -_libre_RSA_padding_add_PKCS1_OAEP_mgf1 -_libre_RSA_padding_check_PKCS1_OAEP_mgf1 -_libre_RSA_padding_add_none -_libre_RSA_padding_check_none -_libre_RSA_verify_PKCS1_PSS -_libre_RSA_padding_add_PKCS1_PSS -_libre_RSA_verify_PKCS1_PSS_mgf1 -_libre_RSA_padding_add_PKCS1_PSS_mgf1 -_libre_RSA_get_ex_new_index -_libre_RSA_set_ex_data -_libre_RSA_get_ex_data -_libre_RSA_security_bits -_libre_RSA_get0_key -_libre_RSA_set0_key -_libre_RSA_get0_crt_params -_libre_RSA_set0_crt_params -_libre_RSA_get0_factors -_libre_RSA_set0_factors -_libre_RSA_get0_n -_libre_RSA_get0_e -_libre_RSA_get0_d -_libre_RSA_get0_p -_libre_RSA_get0_q -_libre_RSA_get0_dmp1 -_libre_RSA_get0_dmq1 -_libre_RSA_get0_iqmp -_libre_RSA_get0_pss_params -_libre_RSA_clear_flags -_libre_RSA_test_flags -_libre_RSA_set_flags -_libre_RSAPublicKey_dup -_libre_RSAPrivateKey_dup -_libre_RSA_meth_new -_libre_RSA_meth_free -_libre_RSA_meth_dup -_libre_RSA_meth_set1_name -_libre_RSA_meth_set_priv_enc -_libre_RSA_meth_set_priv_dec -_libre_RSA_meth_get_finish -_libre_RSA_meth_set_finish -_libre_RSA_meth_set_pub_enc -_libre_RSA_meth_set_pub_dec -_libre_RSA_meth_set_mod_exp -_libre_RSA_meth_set_bn_mod_exp -_libre_RSA_meth_set_init -_libre_RSA_meth_set_keygen -_libre_RSA_meth_set_flags -_libre_RSA_meth_set0_app_data -_libre_RSA_meth_get0_name -_libre_RSA_meth_get_pub_enc -_libre_RSA_meth_get_pub_dec -_libre_RSA_meth_get_priv_enc -_libre_RSA_meth_get_priv_dec -_libre_RSA_meth_get_mod_exp -_libre_RSA_meth_get_bn_mod_exp -_libre_RSA_meth_get_init -_libre_RSA_meth_get_keygen -_libre_RSA_meth_get_flags -_libre_RSA_meth_get0_app_data -_libre_RSA_meth_get_sign -_libre_RSA_meth_set_sign -_libre_RSA_meth_get_verify -_libre_RSA_meth_set_verify -_libre_ERR_load_RSA_strings -_libre_OBJ_NAME_do_all -_libre_OBJ_NAME_do_all_sorted -_libre_OBJ_dup -_libre_OBJ_nid2obj -_libre_OBJ_nid2ln -_libre_OBJ_nid2sn -_libre_OBJ_obj2nid -_libre_OBJ_txt2obj -_libre_OBJ_obj2txt -_libre_OBJ_txt2nid -_libre_OBJ_ln2nid -_libre_OBJ_sn2nid -_libre_OBJ_cmp -_libre_OBJ_new_nid -_libre_OBJ_create -_libre_OBJ_cleanup -_libre_OBJ_create_objects -_libre_OBJ_length -_libre_OBJ_get0_data -_libre_OBJ_find_sigid_algs -_libre_OBJ_find_sigid_by_algs -_libre_ERR_load_OBJ_strings -_libre_CMAC_CTX_new -_libre_CMAC_CTX_cleanup -_libre_CMAC_CTX_free -_libre_CMAC_CTX_get0_cipher_ctx -_libre_CMAC_CTX_copy -_libre_CMAC_Init -_libre_CMAC_Update -_libre_CMAC_Final -_libre_d2i_DSAparams_bio -_libre_i2d_DSAparams_bio -_libre_d2i_DSAparams_fp -_libre_i2d_DSAparams_fp -_libre_DSAparams_dup -_libre_DSA_SIG_new -_libre_DSA_SIG_free -_libre_i2d_DSA_SIG -_libre_d2i_DSA_SIG -_libre_DSA_SIG_get0 -_libre_DSA_SIG_set0 -_libre_DSA_do_sign -_libre_DSA_do_verify -_libre_DSA_OpenSSL -_libre_DSA_set_default_method -_libre_DSA_get_default_method -_libre_DSA_set_method -_libre_DSA_new -_libre_DSA_new_method -_libre_DSA_free -_libre_DSA_up_ref -_libre_DSA_size -_libre_DSA_bits -_libre_DSA_sign_setup -_libre_DSA_sign -_libre_DSA_verify -_libre_DSA_get_ex_new_index -_libre_DSA_set_ex_data -_libre_DSA_get_ex_data -_libre_DSA_security_bits -_libre_d2i_DSAPublicKey -_libre_i2d_DSAPublicKey -_libre_d2i_DSAPrivateKey -_libre_i2d_DSAPrivateKey -_libre_d2i_DSAparams -_libre_i2d_DSAparams -_libre_DSA_generate_parameters_ex -_libre_DSA_generate_key -_libre_DSAparams_print -_libre_DSA_print -_libre_DSAparams_print_fp -_libre_DSA_print_fp -_libre_DSA_dup_DH -_libre_DSA_get0_pqg -_libre_DSA_set0_pqg -_libre_DSA_get0_key -_libre_DSA_set0_key -_libre_DSA_get0_p -_libre_DSA_get0_q -_libre_DSA_get0_g -_libre_DSA_get0_pub_key -_libre_DSA_get0_priv_key -_libre_DSA_clear_flags -_libre_DSA_test_flags -_libre_DSA_set_flags -_libre_DSA_get0_engine -_libre_DSA_meth_new -_libre_DSA_meth_free -_libre_DSA_meth_dup -_libre_DSA_meth_get0_name -_libre_DSA_meth_set1_name -_libre_DSA_meth_set_sign -_libre_DSA_meth_set_finish -_libre_ERR_load_DSA_strings -_libre_CRYPTO_cbc128_encrypt -_libre_CRYPTO_cbc128_decrypt -_libre_CRYPTO_ctr128_encrypt -_libre_CRYPTO_ctr128_encrypt_ctr32 -_libre_CRYPTO_ofb128_encrypt -_libre_CRYPTO_cfb128_encrypt -_libre_CRYPTO_cfb128_8_encrypt -_libre_CRYPTO_cfb128_1_encrypt -_libre_CRYPTO_gcm128_new -_libre_CRYPTO_gcm128_init -_libre_CRYPTO_gcm128_setiv -_libre_CRYPTO_gcm128_aad -_libre_CRYPTO_gcm128_encrypt -_libre_CRYPTO_gcm128_decrypt -_libre_CRYPTO_gcm128_encrypt_ctr32 -_libre_CRYPTO_gcm128_decrypt_ctr32 -_libre_CRYPTO_gcm128_finish -_libre_CRYPTO_gcm128_tag -_libre_CRYPTO_gcm128_release -_libre_CRYPTO_ccm128_init -_libre_CRYPTO_ccm128_setiv -_libre_CRYPTO_ccm128_aad -_libre_CRYPTO_ccm128_encrypt -_libre_CRYPTO_ccm128_decrypt -_libre_CRYPTO_ccm128_encrypt_ccm64 -_libre_CRYPTO_ccm128_decrypt_ccm64 -_libre_CRYPTO_ccm128_tag -_libre_CRYPTO_xts128_encrypt -_libre_X25519_keypair -_libre_X25519 -_libre_ED25519_keypair -_libre_ED25519_sign -_libre_ED25519_verify -_libre_d2i_DHparams_bio -_libre_i2d_DHparams_bio -_libre_d2i_DHparams_fp -_libre_i2d_DHparams_fp -_libre_DHparams_dup -_libre_DH_OpenSSL -_libre_DH_set_default_method -_libre_DH_get_default_method -_libre_DH_set_method -_libre_DH_new_method -_libre_DH_new -_libre_DH_free -_libre_DH_up_ref -_libre_DH_size -_libre_DH_bits -_libre_DH_get_ex_new_index -_libre_DH_set_ex_data -_libre_DH_get_ex_data -_libre_DH_security_bits -_libre_DH_get0_engine -_libre_DH_get0_pqg -_libre_DH_set0_pqg -_libre_DH_get0_key -_libre_DH_set0_key -_libre_DH_get0_p -_libre_DH_get0_q -_libre_DH_get0_g -_libre_DH_get0_priv_key -_libre_DH_get0_pub_key -_libre_DH_clear_flags -_libre_DH_test_flags -_libre_DH_set_flags -_libre_DH_get_length -_libre_DH_set_length -_libre_DH_generate_parameters -_libre_DH_generate_parameters_ex -_libre_DH_check -_libre_DH_check_pub_key -_libre_DH_generate_key -_libre_DH_compute_key -_libre_d2i_DHparams -_libre_i2d_DHparams -_libre_DHparams_print_fp -_libre_DHparams_print -_libre_ERR_load_DH_strings -_libre_OPENSSL_gmtime -_libre_OPENSSL_timegm -_libre_OPENSSL_posix_to_tm -_libre_OPENSSL_tm_to_posix -_libre_ENGINE_load_builtin_engines -_libre_ENGINE_load_dynamic -_libre_ENGINE_load_openssl -_libre_ENGINE_register_all_complete -_libre_ENGINE_cleanup -_libre_ENGINE_new -_libre_ENGINE_free -_libre_ENGINE_init -_libre_ENGINE_finish -_libre_ENGINE_by_id -_libre_ENGINE_get_id -_libre_ENGINE_get_name -_libre_ENGINE_set_default -_libre_ENGINE_get_default_RSA -_libre_ENGINE_set_default_RSA -_libre_ENGINE_ctrl_cmd -_libre_ENGINE_ctrl_cmd_string -_libre_ENGINE_load_private_key -_libre_ENGINE_load_public_key -_libre_RC4_set_key -_libre_RC4 -_libre_RIPEMD160_Init -_libre_RIPEMD160_Update -_libre_RIPEMD160_Final -_libre_RIPEMD160 -_libre_RIPEMD160_Transform -_libre_DES_ecb3_encrypt -_libre_DES_cbc_cksum -_libre_DES_cbc_encrypt -_libre_DES_ncbc_encrypt -_libre_DES_xcbc_encrypt -_libre_DES_cfb_encrypt -_libre_DES_ecb_encrypt -_libre_DES_encrypt1 -_libre_DES_encrypt2 -_libre_DES_encrypt3 -_libre_DES_decrypt3 -_libre_DES_ede3_cbc_encrypt -_libre_DES_ede3_cbcm_encrypt -_libre_DES_ede3_cfb64_encrypt -_libre_DES_ede3_cfb_encrypt -_libre_DES_ede3_ofb64_encrypt -_libre_DES_enc_read -_libre_DES_enc_write -_libre_DES_fcrypt -_libre_DES_crypt -_libre_DES_ofb_encrypt -_libre_DES_pcbc_encrypt -_libre_DES_quad_cksum -_libre_DES_random_key -_libre_DES_set_odd_parity -_libre_DES_check_key_parity -_libre_DES_is_weak_key -_libre_DES_set_key -_libre_DES_key_sched -_libre_DES_set_key_checked -_libre_DES_set_key_unchecked -_libre_DES_string_to_key -_libre_DES_string_to_2keys -_libre_DES_cfb64_encrypt -_libre_DES_ofb64_encrypt -_libre_BF_set_key -_libre_BF_encrypt -_libre_BF_decrypt -_libre_BF_ecb_encrypt -_libre_BF_cbc_encrypt -_libre_BF_cfb64_encrypt -_libre_BF_ofb64_encrypt -_libre_PEM_read_bio_CMS -_libre_PEM_read_CMS -_libre_PEM_write_bio_CMS -_libre_PEM_write_CMS -_libre_CMS_get1_ReceiptRequest -_libre_CMS_ReceiptRequest_create0 -_libre_CMS_add1_ReceiptRequest -_libre_CMS_ReceiptRequest_get0_values -_libre_WHIRLPOOL_Init -_libre_WHIRLPOOL_Update -_libre_WHIRLPOOL_BitUpdate -_libre_WHIRLPOOL_Final -_libre_WHIRLPOOL -_libre_Camellia_set_key -_libre_Camellia_encrypt -_libre_Camellia_decrypt -_libre_Camellia_ecb_encrypt -_libre_Camellia_cbc_encrypt -_libre_Camellia_cfb128_encrypt -_libre_Camellia_cfb1_encrypt -_libre_Camellia_cfb8_encrypt -_libre_Camellia_ofb128_encrypt -_libre_Camellia_ctr128_encrypt -_libre_AES_set_encrypt_key -_libre_AES_set_decrypt_key -_libre_AES_encrypt -_libre_AES_decrypt -_libre_AES_ecb_encrypt -_libre_AES_cbc_encrypt -_libre_AES_cfb128_encrypt -_libre_AES_cfb1_encrypt -_libre_AES_cfb8_encrypt -_libre_AES_ofb128_encrypt -_libre_AES_ctr128_encrypt -_libre_AES_ige_encrypt -_libre_AES_wrap_key -_libre_AES_unwrap_key -_libre_EVP_MD_type -_libre_EVP_MD_pkey_type -_libre_EVP_MD_size -_libre_EVP_MD_block_size -_libre_EVP_MD_flags -_libre_EVP_MD_CTX_md -_libre_EVP_MD_CTX_md_data -_libre_EVP_MD_CTX_pkey_ctx -_libre_EVP_MD_CTX_set_pkey_ctx -_libre_EVP_CIPHER_nid -_libre_EVP_CIPHER_block_size -_libre_EVP_CIPHER_key_length -_libre_EVP_CIPHER_iv_length -_libre_EVP_CIPHER_flags -_libre_EVP_CIPHER_CTX_cipher -_libre_EVP_CIPHER_CTX_encrypting -_libre_EVP_CIPHER_CTX_nid -_libre_EVP_CIPHER_CTX_block_size -_libre_EVP_CIPHER_CTX_key_length -_libre_EVP_CIPHER_CTX_iv_length -_libre_EVP_CIPHER_CTX_get_iv -_libre_EVP_CIPHER_CTX_set_iv -_libre_EVP_CIPHER_CTX_copy -_libre_EVP_CIPHER_CTX_get_app_data -_libre_EVP_CIPHER_CTX_set_app_data -_libre_EVP_CIPHER_CTX_get_cipher_data -_libre_EVP_CIPHER_CTX_set_cipher_data -_libre_EVP_CIPHER_CTX_buf_noconst -_libre_EVP_CIPHER_CTX_flags -_libre_EVP_CIPHER_meth_new -_libre_EVP_CIPHER_meth_dup -_libre_EVP_CIPHER_meth_free -_libre_EVP_CIPHER_meth_set_iv_length -_libre_EVP_CIPHER_meth_set_flags -_libre_EVP_CIPHER_meth_set_impl_ctx_size -_libre_EVP_CIPHER_meth_set_init -_libre_EVP_CIPHER_meth_set_do_cipher -_libre_EVP_CIPHER_meth_set_cleanup -_libre_EVP_CIPHER_meth_set_set_asn1_params -_libre_EVP_CIPHER_meth_set_get_asn1_params -_libre_EVP_CIPHER_meth_set_ctrl -_libre_EVP_PKEY_new_raw_private_key -_libre_EVP_PKEY_new_raw_public_key -_libre_EVP_PKEY_get_raw_private_key -_libre_EVP_PKEY_get_raw_public_key -_libre_EVP_Cipher -_libre_EVP_MD_CTX_new -_libre_EVP_MD_CTX_free -_libre_EVP_MD_CTX_reset -_libre_EVP_MD_CTX_create -_libre_EVP_MD_CTX_destroy -_libre_EVP_MD_CTX_cleanup -_libre_EVP_MD_CTX_copy_ex -_libre_EVP_MD_CTX_set_flags -_libre_EVP_MD_CTX_clear_flags -_libre_EVP_MD_CTX_ctrl -_libre_EVP_MD_CTX_test_flags -_libre_EVP_DigestInit_ex -_libre_EVP_DigestUpdate -_libre_EVP_DigestFinal_ex -_libre_EVP_Digest -_libre_EVP_MD_CTX_copy -_libre_EVP_DigestInit -_libre_EVP_DigestFinal -_libre_EVP_read_pw_string -_libre_EVP_read_pw_string_min -_libre_EVP_set_pw_prompt -_libre_EVP_get_pw_prompt -_libre_EVP_BytesToKey -_libre_EVP_CIPHER_CTX_set_flags -_libre_EVP_CIPHER_CTX_clear_flags -_libre_EVP_CIPHER_CTX_test_flags -_libre_EVP_EncryptInit -_libre_EVP_EncryptInit_ex -_libre_EVP_EncryptUpdate -_libre_EVP_EncryptFinal_ex -_libre_EVP_DecryptInit -_libre_EVP_DecryptInit_ex -_libre_EVP_DecryptUpdate -_libre_EVP_DecryptFinal_ex -_libre_EVP_CipherInit -_libre_EVP_CipherInit_ex -_libre_EVP_CipherUpdate -_libre_EVP_CipherFinal_ex -_libre_EVP_SignFinal -_libre_EVP_VerifyFinal -_libre_EVP_DigestSignInit -_libre_EVP_DigestSignFinal -_libre_EVP_DigestSign -_libre_EVP_DigestVerifyInit -_libre_EVP_DigestVerifyFinal -_libre_EVP_DigestVerify -_libre_EVP_OpenInit -_libre_EVP_OpenFinal -_libre_EVP_SealInit -_libre_EVP_SealFinal -_libre_EVP_ENCODE_CTX_new -_libre_EVP_ENCODE_CTX_free -_libre_EVP_EncodeInit -_libre_EVP_EncodeUpdate -_libre_EVP_EncodeFinal -_libre_EVP_EncodeBlock -_libre_EVP_DecodeInit -_libre_EVP_DecodeUpdate -_libre_EVP_DecodeFinal -_libre_EVP_DecodeBlock -_libre_EVP_CIPHER_CTX_cleanup -_libre_EVP_CIPHER_CTX_new -_libre_EVP_CIPHER_CTX_free -_libre_EVP_CIPHER_CTX_reset -_libre_EVP_CIPHER_CTX_set_key_length -_libre_EVP_CIPHER_CTX_set_padding -_libre_EVP_CIPHER_CTX_ctrl -_libre_EVP_CIPHER_CTX_rand_key -_libre_BIO_f_md -_libre_BIO_f_base64 -_libre_BIO_f_cipher -_libre_BIO_set_cipher -_libre_EVP_md_null -_libre_EVP_md4 -_libre_EVP_md5 -_libre_EVP_md5_sha1 -_libre_EVP_sha1 -_libre_EVP_sha224 -_libre_EVP_sha256 -_libre_EVP_sha384 -_libre_EVP_sha512 -_libre_EVP_sha512_224 -_libre_EVP_sha512_256 -_libre_EVP_sha3_224 -_libre_EVP_sha3_256 -_libre_EVP_sha3_384 -_libre_EVP_sha3_512 -_libre_EVP_sm3 -_libre_EVP_ripemd160 -_libre_EVP_whirlpool -_libre_EVP_enc_null -_libre_EVP_des_ecb -_libre_EVP_des_ede -_libre_EVP_des_ede3 -_libre_EVP_des_ede_ecb -_libre_EVP_des_ede3_ecb -_libre_EVP_des_cfb64 -_libre_EVP_des_cfb1 -_libre_EVP_des_cfb8 -_libre_EVP_des_ede_cfb64 -_libre_EVP_des_ede3_cfb64 -_libre_EVP_des_ede3_cfb1 -_libre_EVP_des_ede3_cfb8 -_libre_EVP_des_ofb -_libre_EVP_des_ede_ofb -_libre_EVP_des_ede3_ofb -_libre_EVP_des_cbc -_libre_EVP_des_ede_cbc -_libre_EVP_des_ede3_cbc -_libre_EVP_desx_cbc -_libre_EVP_rc4 -_libre_EVP_rc4_40 -_libre_EVP_idea_ecb -_libre_EVP_idea_cfb64 -_libre_EVP_idea_ofb -_libre_EVP_idea_cbc -_libre_EVP_rc2_ecb -_libre_EVP_rc2_cbc -_libre_EVP_rc2_40_cbc -_libre_EVP_rc2_64_cbc -_libre_EVP_rc2_cfb64 -_libre_EVP_rc2_ofb -_libre_EVP_bf_ecb -_libre_EVP_bf_cbc -_libre_EVP_bf_cfb64 -_libre_EVP_bf_ofb -_libre_EVP_cast5_ecb -_libre_EVP_cast5_cbc -_libre_EVP_cast5_cfb64 -_libre_EVP_cast5_ofb -_libre_EVP_aes_128_ecb -_libre_EVP_aes_128_cbc -_libre_EVP_aes_128_cfb1 -_libre_EVP_aes_128_cfb8 -_libre_EVP_aes_128_cfb128 -_libre_EVP_aes_128_ofb -_libre_EVP_aes_128_ctr -_libre_EVP_aes_128_ccm -_libre_EVP_aes_128_gcm -_libre_EVP_aes_128_wrap -_libre_EVP_aes_128_xts -_libre_EVP_aes_192_ecb -_libre_EVP_aes_192_cbc -_libre_EVP_aes_192_cfb1 -_libre_EVP_aes_192_cfb8 -_libre_EVP_aes_192_cfb128 -_libre_EVP_aes_192_ofb -_libre_EVP_aes_192_ctr -_libre_EVP_aes_192_ccm -_libre_EVP_aes_192_gcm -_libre_EVP_aes_192_wrap -_libre_EVP_aes_256_ecb -_libre_EVP_aes_256_cbc -_libre_EVP_aes_256_cfb1 -_libre_EVP_aes_256_cfb8 -_libre_EVP_aes_256_cfb128 -_libre_EVP_aes_256_ofb -_libre_EVP_aes_256_ctr -_libre_EVP_aes_256_ccm -_libre_EVP_aes_256_gcm -_libre_EVP_aes_256_wrap -_libre_EVP_aes_256_xts -_libre_EVP_chacha20_poly1305 -_libre_EVP_camellia_128_ecb -_libre_EVP_camellia_128_cbc -_libre_EVP_camellia_128_cfb1 -_libre_EVP_camellia_128_cfb8 -_libre_EVP_camellia_128_cfb128 -_libre_EVP_camellia_128_ofb -_libre_EVP_camellia_192_ecb -_libre_EVP_camellia_192_cbc -_libre_EVP_camellia_192_cfb1 -_libre_EVP_camellia_192_cfb8 -_libre_EVP_camellia_192_cfb128 -_libre_EVP_camellia_192_ofb -_libre_EVP_camellia_256_ecb -_libre_EVP_camellia_256_cbc -_libre_EVP_camellia_256_cfb1 -_libre_EVP_camellia_256_cfb8 -_libre_EVP_camellia_256_cfb128 -_libre_EVP_camellia_256_ofb -_libre_EVP_chacha20 -_libre_EVP_sm4_ecb -_libre_EVP_sm4_cbc -_libre_EVP_sm4_cfb128 -_libre_EVP_sm4_ofb -_libre_EVP_sm4_ctr -_libre_OPENSSL_add_all_algorithms_noconf -_libre_OPENSSL_add_all_algorithms_conf -_libre_OpenSSL_add_all_ciphers -_libre_OpenSSL_add_all_digests -_libre_EVP_get_cipherbyname -_libre_EVP_get_digestbyname -_libre_EVP_cleanup -_libre_EVP_CIPHER_do_all -_libre_EVP_CIPHER_do_all_sorted -_libre_EVP_MD_do_all -_libre_EVP_MD_do_all_sorted -_libre_EVP_PKEY_decrypt_old -_libre_EVP_PKEY_encrypt_old -_libre_EVP_PKEY_type -_libre_EVP_PKEY_id -_libre_EVP_PKEY_base_id -_libre_EVP_PKEY_bits -_libre_EVP_PKEY_security_bits -_libre_EVP_PKEY_size -_libre_EVP_PKEY_set_type -_libre_EVP_PKEY_set_type_str -_libre_EVP_PKEY_assign -_libre_EVP_PKEY_get0 -_libre_EVP_PKEY_get0_hmac -_libre_EVP_PKEY_get0_RSA -_libre_EVP_PKEY_get1_RSA -_libre_EVP_PKEY_set1_RSA -_libre_EVP_PKEY_get0_DSA -_libre_EVP_PKEY_get1_DSA -_libre_EVP_PKEY_set1_DSA -_libre_EVP_PKEY_get0_DH -_libre_EVP_PKEY_get1_DH -_libre_EVP_PKEY_set1_DH -_libre_EVP_PKEY_get0_EC_KEY -_libre_EVP_PKEY_get1_EC_KEY -_libre_EVP_PKEY_set1_EC_KEY -_libre_EVP_PKEY_new -_libre_EVP_PKEY_free -_libre_EVP_PKEY_up_ref -_libre_d2i_PublicKey -_libre_i2d_PublicKey -_libre_d2i_PrivateKey -_libre_d2i_AutoPrivateKey -_libre_i2d_PrivateKey -_libre_EVP_PKEY_copy_parameters -_libre_EVP_PKEY_missing_parameters -_libre_EVP_PKEY_save_parameters -_libre_EVP_PKEY_cmp_parameters -_libre_EVP_PKEY_cmp -_libre_EVP_PKEY_print_public -_libre_EVP_PKEY_print_private -_libre_EVP_PKEY_print_params -_libre_EVP_PKEY_get_default_digest_nid -_libre_EVP_CIPHER_type -_libre_PKCS5_PBKDF2_HMAC_SHA1 -_libre_PKCS5_PBKDF2_HMAC -_libre_EVP_PKEY_asn1_get_count -_libre_EVP_PKEY_asn1_get0 -_libre_EVP_PKEY_asn1_find -_libre_EVP_PKEY_asn1_find_str -_libre_EVP_PKEY_asn1_get0_info -_libre_EVP_PKEY_get0_asn1 -_libre_EVP_PKEY_CTX_new -_libre_EVP_PKEY_CTX_new_id -_libre_EVP_PKEY_CTX_dup -_libre_EVP_PKEY_CTX_free -_libre_EVP_PKEY_CTX_ctrl -_libre_EVP_PKEY_CTX_ctrl_str -_libre_EVP_PKEY_CTX_get_operation -_libre_EVP_PKEY_CTX_set0_keygen_info -_libre_EVP_PKEY_new_mac_key -_libre_EVP_PKEY_new_CMAC_key -_libre_EVP_PKEY_CTX_set_data -_libre_EVP_PKEY_CTX_get_data -_libre_EVP_PKEY_CTX_get0_pkey -_libre_EVP_PKEY_CTX_get0_peerkey -_libre_EVP_PKEY_CTX_set_app_data -_libre_EVP_PKEY_CTX_get_app_data -_libre_EVP_PKEY_sign_init -_libre_EVP_PKEY_sign -_libre_EVP_PKEY_verify_init -_libre_EVP_PKEY_verify -_libre_EVP_PKEY_verify_recover_init -_libre_EVP_PKEY_verify_recover -_libre_EVP_PKEY_encrypt_init -_libre_EVP_PKEY_encrypt -_libre_EVP_PKEY_decrypt_init -_libre_EVP_PKEY_decrypt -_libre_EVP_PKEY_derive_init -_libre_EVP_PKEY_derive_set_peer -_libre_EVP_PKEY_derive -_libre_EVP_PKEY_paramgen_init -_libre_EVP_PKEY_paramgen -_libre_EVP_PKEY_keygen_init -_libre_EVP_PKEY_keygen -_libre_EVP_PKEY_check -_libre_EVP_PKEY_public_check -_libre_EVP_PKEY_param_check -_libre_EVP_PKEY_CTX_set_cb -_libre_EVP_PKEY_CTX_get_cb -_libre_EVP_PKEY_CTX_get_keygen_info -_libre_EVP_aead_aes_128_gcm -_libre_EVP_aead_aes_256_gcm -_libre_EVP_aead_chacha20_poly1305 -_libre_EVP_aead_xchacha20_poly1305 -_libre_EVP_AEAD_key_length -_libre_EVP_AEAD_nonce_length -_libre_EVP_AEAD_max_overhead -_libre_EVP_AEAD_max_tag_len -_libre_EVP_AEAD_CTX_new -_libre_EVP_AEAD_CTX_free -_libre_EVP_AEAD_CTX_init -_libre_EVP_AEAD_CTX_cleanup -_libre_EVP_AEAD_CTX_seal -_libre_EVP_AEAD_CTX_open -_libre_ERR_load_EVP_strings -_libre_X509_CRL_get_signature_nid -_libre_X509_CRL_get0_extensions -_libre_X509_CRL_get_version -_libre_X509_CRL_get0_lastUpdate -_libre_X509_CRL_get0_nextUpdate -_libre_X509_CRL_get_lastUpdate -_libre_X509_CRL_get_nextUpdate -_libre_X509_CRL_get_issuer -_libre_X509_CRL_get_REVOKED -_libre_X509_CRL_get0_signature -_libre_X509_CRL_get0_tbs_sigalg -_libre_X509_REQ_get_signature_nid -_libre_X509_REQ_get0_signature -_libre_X509_CRL_verify -_libre_NETSCAPE_SPKI_print -_libre_X509_signature_dump -_libre_X509_signature_print -_libre_d2i_RSA_PUBKEY_fp -_libre_i2d_RSA_PUBKEY_fp -_libre_d2i_DSA_PUBKEY_fp -_libre_i2d_DSA_PUBKEY_fp -_libre_d2i_EC_PUBKEY_fp -_libre_i2d_EC_PUBKEY_fp -_libre_i2d_PUBKEY_fp -_libre_d2i_PUBKEY_fp -_libre_d2i_RSA_PUBKEY_bio -_libre_i2d_RSA_PUBKEY_bio -_libre_d2i_DSA_PUBKEY_bio -_libre_i2d_DSA_PUBKEY_bio -_libre_d2i_EC_PUBKEY_bio -_libre_i2d_EC_PUBKEY_bio -_libre_i2d_PUBKEY_bio -_libre_d2i_PUBKEY_bio -_libre_X509_dup -_libre_X509_ATTRIBUTE_dup -_libre_X509_EXTENSION_dup -_libre_X509_CRL_dup -_libre_X509_REQ_dup -_libre_X509_ALGOR_dup -_libre_X509_ALGOR_set0 -_libre_X509_ALGOR_get0 -_libre_X509_ALGOR_cmp -_libre_X509_NAME_dup -_libre_X509_NAME_get0_der -_libre_X509_NAME_ENTRY_dup -_libre_X509_ALGOR_new -_libre_X509_ALGOR_free -_libre_d2i_X509_ALGOR -_libre_i2d_X509_ALGOR -_libre_d2i_X509_ALGORS -_libre_i2d_X509_ALGORS -_libre_X509_VAL_new -_libre_X509_VAL_free -_libre_d2i_X509_VAL -_libre_i2d_X509_VAL -_libre_X509_PUBKEY_new -_libre_X509_PUBKEY_free -_libre_d2i_X509_PUBKEY -_libre_i2d_X509_PUBKEY -_libre_X509_PUBKEY_set -_libre_X509_PUBKEY_get -_libre_X509_PUBKEY_get0 -_libre_i2d_PUBKEY -_libre_d2i_PUBKEY -_libre_i2d_RSA_PUBKEY -_libre_d2i_RSA_PUBKEY -_libre_i2d_DSA_PUBKEY -_libre_d2i_DSA_PUBKEY -_libre_i2d_EC_PUBKEY -_libre_d2i_EC_PUBKEY -_libre_X509_SIG_new -_libre_X509_SIG_free -_libre_d2i_X509_SIG -_libre_i2d_X509_SIG -_libre_X509_SIG_get0 -_libre_X509_SIG_getm -_libre_X509_REQ_INFO_new -_libre_X509_REQ_INFO_free -_libre_d2i_X509_REQ_INFO -_libre_i2d_X509_REQ_INFO -_libre_X509_REQ_new -_libre_X509_REQ_free -_libre_d2i_X509_REQ -_libre_i2d_X509_REQ -_libre_X509_ATTRIBUTE_new -_libre_X509_ATTRIBUTE_free -_libre_d2i_X509_ATTRIBUTE -_libre_i2d_X509_ATTRIBUTE -_libre_X509_ATTRIBUTE_create -_libre_X509_EXTENSION_new -_libre_X509_EXTENSION_free -_libre_d2i_X509_EXTENSION -_libre_i2d_X509_EXTENSION -_libre_d2i_X509_EXTENSIONS -_libre_i2d_X509_EXTENSIONS -_libre_X509_NAME_ENTRY_new -_libre_X509_NAME_ENTRY_free -_libre_d2i_X509_NAME_ENTRY -_libre_i2d_X509_NAME_ENTRY -_libre_X509_NAME_new -_libre_X509_NAME_free -_libre_d2i_X509_NAME -_libre_i2d_X509_NAME -_libre_X509_NAME_set -_libre_X509_CINF_new -_libre_X509_CINF_free -_libre_d2i_X509_CINF -_libre_i2d_X509_CINF -_libre_X509_new -_libre_X509_free -_libre_d2i_X509 -_libre_i2d_X509 -_libre_X509_get_ex_new_index -_libre_X509_set_ex_data -_libre_X509_get_ex_data -_libre_i2d_X509_AUX -_libre_d2i_X509_AUX -_libre_i2d_re_X509_tbs -_libre_X509_get0_signature -_libre_X509_get_signature_nid -_libre_X509_alias_set1 -_libre_X509_keyid_set1 -_libre_X509_alias_get0 -_libre_X509_keyid_get0 -_libre_X509_add1_trust_object -_libre_X509_add1_reject_object -_libre_X509_trust_clear -_libre_X509_reject_clear -_libre_X509_REVOKED_new -_libre_X509_REVOKED_free -_libre_X509_REVOKED_dup -_libre_d2i_X509_REVOKED -_libre_i2d_X509_REVOKED -_libre_X509_CRL_INFO_new -_libre_X509_CRL_INFO_free -_libre_d2i_X509_CRL_INFO -_libre_i2d_X509_CRL_INFO -_libre_X509_CRL_new -_libre_X509_CRL_free -_libre_d2i_X509_CRL -_libre_i2d_X509_CRL -_libre_X509_CRL_add0_revoked -_libre_X509_CRL_get0_by_serial -_libre_X509_CRL_get0_by_cert -_libre_X509_PKEY_new -_libre_X509_PKEY_free -_libre_NETSCAPE_SPKI_new -_libre_NETSCAPE_SPKI_free -_libre_d2i_NETSCAPE_SPKI -_libre_i2d_NETSCAPE_SPKI -_libre_NETSCAPE_SPKAC_new -_libre_NETSCAPE_SPKAC_free -_libre_d2i_NETSCAPE_SPKAC -_libre_i2d_NETSCAPE_SPKAC -_libre_X509_INFO_new -_libre_X509_INFO_free -_libre_ASN1_item_digest -_libre_ASN1_item_verify -_libre_ASN1_item_sign -_libre_ASN1_item_sign_ctx -_libre_X509_print_ex_fp -_libre_X509_print_fp -_libre_X509_CRL_print_fp -_libre_X509_REQ_print_fp -_libre_X509_NAME_print_ex_fp -_libre_X509_NAME_print -_libre_X509_NAME_print_ex -_libre_X509_print_ex -_libre_X509_print -_libre_X509_ocspid_print -_libre_X509_CRL_print -_libre_X509_REQ_print_ex -_libre_X509_REQ_print -_libre_EVP_PKEY_get_attr_count -_libre_EVP_PKEY_get_attr_by_NID -_libre_EVP_PKEY_get_attr_by_OBJ -_libre_EVP_PKEY_get_attr -_libre_EVP_PKEY_delete_attr -_libre_EVP_PKEY_add1_attr -_libre_EVP_PKEY_add1_attr_by_OBJ -_libre_EVP_PKEY_add1_attr_by_NID -_libre_EVP_PKEY_add1_attr_by_txt -_libre_PKCS8_PRIV_KEY_INFO_new -_libre_PKCS8_PRIV_KEY_INFO_free -_libre_d2i_PKCS8_PRIV_KEY_INFO -_libre_i2d_PKCS8_PRIV_KEY_INFO -_libre_EVP_PKCS82PKEY -_libre_EVP_PKEY2PKCS8 -_libre_PKCS8_pkey_set0 -_libre_PKCS8_pkey_get0 -_libre_PKCS8_pkey_get0_attrs -_libre_PKCS8_pkey_add1_attr_by_NID -_libre_X509_PUBKEY_set0_param -_libre_X509_PUBKEY_get0_param -_libre_CONF_set_default_method -_libre_CONF_set_nconf -_libre_CONF_load -_libre_CONF_load_fp -_libre_CONF_load_bio -_libre_CONF_get_section -_libre_CONF_get_string -_libre_CONF_get_number -_libre_CONF_free -_libre_CONF_dump_fp -_libre_CONF_dump_bio -_libre_OPENSSL_config -_libre_OPENSSL_no_config -_libre_NCONF_new -_libre_NCONF_default -_libre_NCONF_WIN32 -_libre_NCONF_free -_libre_NCONF_free_data -_libre_NCONF_load -_libre_NCONF_load_fp -_libre_NCONF_load_bio -_libre_NCONF_get_section -_libre_NCONF_get_string -_libre_NCONF_get_number_e -_libre_NCONF_dump_fp -_libre_NCONF_dump_bio -_libre_CONF_modules_load -_libre_CONF_modules_load_file -_libre_CONF_modules_unload -_libre_CONF_modules_finish -_libre_CONF_modules_free -_libre_CONF_module_add -_libre_CONF_imodule_get_name -_libre_CONF_imodule_get_value -_libre_CONF_imodule_get_usr_data -_libre_CONF_imodule_set_usr_data -_libre_CONF_imodule_get_module -_libre_CONF_imodule_get_flags -_libre_CONF_imodule_set_flags -_libre_CONF_module_get_usr_data -_libre_CONF_module_set_usr_data -_libre_CONF_get1_default_config_file -_libre_CONF_parse_list -_libre_OPENSSL_load_builtin_modules -_libre_ERR_load_CONF_strings -_libre_CRYPTO_mem_ctrl -_libre_CRYPTO_set_id_callback -_libre_CRYPTO_get_id_callback -_libre_CRYPTO_thread_id -_libre_CRYPTO_get_new_lockid -_libre_CRYPTO_get_lock_name -_libre_CRYPTO_num_locks -_libre_CRYPTO_set_locking_callback -_libre_CRYPTO_get_locking_callback -_libre_CRYPTO_set_add_lock_callback -_libre_CRYPTO_get_add_lock_callback -_libre_CRYPTO_THREADID_set_numeric -_libre_CRYPTO_THREADID_set_pointer -_libre_CRYPTO_THREADID_set_callback -_libre_CRYPTO_THREADID_get_callback -_libre_CRYPTO_get_new_dynlockid -_libre_CRYPTO_destroy_dynlockid -_libre_CRYPTO_get_dynlock_value -_libre_CRYPTO_set_dynlock_create_callback -_libre_CRYPTO_set_dynlock_lock_callback -_libre_CRYPTO_set_dynlock_destroy_callback -_libre_CRYPTO_get_dynlock_lock_callback -_libre_CRYPTO_get_dynlock_destroy_callback -_libre_CRYPTO_malloc -_libre_CRYPTO_strdup -_libre_CRYPTO_free -_libre_OPENSSL_cleanse -_libre_FIPS_mode -_libre_FIPS_mode_set -_libre_OPENSSL_init -_libre_CRYPTO_memcmp -_libre_RAND_cleanup -_libre_RAND_bytes -_libre_RAND_pseudo_bytes -_libre_RAND_seed -_libre_RAND_add -_libre_RAND_load_file -_libre_RAND_write_file -_libre_RAND_file_name -_libre_RAND_status -_libre_RAND_poll -_libre_RC2_set_key -_libre_RC2_ecb_encrypt -_libre_RC2_encrypt -_libre_RC2_decrypt -_libre_RC2_cbc_encrypt -_libre_RC2_cfb64_encrypt -_libre_RC2_ofb64_encrypt -_libre_BN_div -_libre_BN_mod_exp -_libre_BN_mod_exp_mont -_libre_BN_gcd -_libre_BN_mod_inverse -_libre_HMAC_Init -_libre_HMAC_CTX_reset -_libre_EVP_MD_CTX_init -_libre_EVP_EncryptFinal -_libre_EVP_DecryptFinal -_libre_EVP_CipherFinal -_libre_EVP_CIPHER_CTX_init -_libre_EC_GROUP_clear_free -_libre_EC_GROUP_set_curve_GFp -_libre_EC_GROUP_get_curve_GFp -_libre_EC_POINT_clear_free -_libre_EC_POINT_set_Jprojective_coordinates_GFp -_libre_EC_POINT_get_Jprojective_coordinates_GFp -_libre_EC_POINT_set_affine_coordinates_GFp -_libre_EC_POINT_get_affine_coordinates_GFp -_libre_EC_POINT_set_compressed_coordinates_GFp -_libre_BASIC_CONSTRAINTS_it -_libre_AUTHORITY_KEYID_it -_libre_PKEY_USAGE_PERIOD_it -_libre_GENERAL_NAME_it -_libre_GENERAL_NAMES_it -_libre_OTHERNAME_it -_libre_EDIPARTYNAME_it -_libre_EXTENDED_KEY_USAGE_it -_libre_CERTIFICATEPOLICIES_it -_libre_POLICYINFO_it -_libre_POLICYQUALINFO_it -_libre_USERNOTICE_it -_libre_NOTICEREF_it -_libre_CRL_DIST_POINTS_it -_libre_DIST_POINT_NAME_it -_libre_DIST_POINT_it -_libre_ISSUING_DIST_POINT_it -_libre_ACCESS_DESCRIPTION_it -_libre_AUTHORITY_INFO_ACCESS_it -_libre_POLICY_MAPPING_it -_libre_POLICY_MAPPINGS_it -_libre_GENERAL_SUBTREE_it -_libre_NAME_CONSTRAINTS_it -_libre_POLICY_CONSTRAINTS_it -_libre_ASRange_it -_libre_ASIdOrRange_it -_libre_ASIdentifierChoice_it -_libre_ASIdentifiers_it -_libre_IPAddressRange_it -_libre_IPAddressOrRange_it -_libre_IPAddressChoice_it -_libre_IPAddressFamily_it -_libre_X509_ALGOR_it -_libre_X509_ALGORS_it -_libre_X509_VAL_it -_libre_X509_PUBKEY_it -_libre_X509_SIG_it -_libre_X509_REQ_INFO_it -_libre_X509_REQ_it -_libre_X509_ATTRIBUTE_it -_libre_X509_EXTENSION_it -_libre_X509_EXTENSIONS_it -_libre_X509_NAME_ENTRY_it -_libre_X509_NAME_it -_libre_X509_CINF_it -_libre_X509_it -_libre_X509_REVOKED_it -_libre_X509_CRL_INFO_it -_libre_X509_CRL_it -_libre_NETSCAPE_SPKI_it -_libre_NETSCAPE_SPKAC_it -_libre_PBEPARAM_it -_libre_PKCS8_PRIV_KEY_INFO_it -_libre_ASN1_SEQUENCE_ANY_it -_libre_ASN1_SET_ANY_it -_libre_ASN1_ANY_it -_libre_ASN1_OBJECT_it -_libre_ASN1_BIT_STRING_it -_libre_ASN1_INTEGER_it -_libre_ASN1_ENUMERATED_it -_libre_ASN1_OCTET_STRING_it -_libre_ASN1_VISIBLESTRING_it -_libre_ASN1_UNIVERSALSTRING_it -_libre_ASN1_UTF8STRING_it -_libre_ASN1_NULL_it -_libre_ASN1_BMPSTRING_it -_libre_ASN1_PRINTABLE_it -_libre_DIRECTORYSTRING_it -_libre_DISPLAYTEXT_it -_libre_ASN1_PRINTABLESTRING_it -_libre_ASN1_T61STRING_it -_libre_ASN1_IA5STRING_it -_libre_ASN1_GENERALSTRING_it -_libre_ASN1_UTCTIME_it -_libre_ASN1_GENERALIZEDTIME_it -_libre_ASN1_TIME_it -_libre_OCSP_SINGLERESP_it -_libre_OCSP_CERTSTATUS_it -_libre_OCSP_REVOKEDINFO_it -_libre_OCSP_BASICRESP_it -_libre_OCSP_RESPDATA_it -_libre_OCSP_RESPID_it -_libre_OCSP_RESPONSE_it -_libre_OCSP_RESPBYTES_it -_libre_OCSP_ONEREQ_it -_libre_OCSP_CERTID_it -_libre_OCSP_REQUEST_it -_libre_OCSP_SIGNATURE_it -_libre_OCSP_REQINFO_it -_libre_OCSP_CRLID_it -_libre_OCSP_SERVICELOC_it -_libre_PKCS7_ISSUER_AND_SERIAL_it -_libre_PKCS7_SIGNER_INFO_it -_libre_PKCS7_RECIP_INFO_it -_libre_PKCS7_SIGNED_it -_libre_PKCS7_ENC_CONTENT_it -_libre_PKCS7_ENVELOPE_it -_libre_PKCS7_SIGN_ENVELOPE_it -_libre_PKCS7_DIGEST_it -_libre_PKCS7_ENCRYPT_it -_libre_PKCS7_it -_libre_PKCS7_ATTR_SIGN_it -_libre_PKCS7_ATTR_VERIFY_it -_libre_ASN1_SEQUENCE_it -_libre_CBIGNUM_it -_libre_BIGNUM_it -_libre_LONG_it -_libre_ZLONG_it -_libre_RSAPublicKey_it -_libre_RSAPrivateKey_it -_libre_RSA_PSS_PARAMS_it -_libre_RSA_OAEP_PARAMS_it -_libre_DSAPublicKey_it -_libre_DSAPrivateKey_it -_libre_DSAparams_it -_libre_CMS_ContentInfo_it -_libre_CMS_ReceiptRequest_it -_libre_PKCS12_it -_libre_PKCS12_SAFEBAG_it -_libre_BIO_get_ex_new_index -_libre_BIO_new_bio_pair -_libre_ASN1_UTCTIME_cmp_time_t -_libre_ASN1_dup -_libre_CMS_get0_content -_libre_PKCS7_add_attribute -_libre_UI_method_get_prompt_constructor -_libre_UI_null -_libre_X509_STORE_CTX_get_check_issued -_libre_X509_STORE_get_check_issued -_libre_X509_STORE_set_check_issued -_libre_lh_error -_libre_DES_check_key -_libre_DES_rw_mode -_libre_CRYPTO_get_dynlock_create_callback -_libre_ERR_add_error_data -_libre_ERR_add_error_vdata -_libre_RSAPublicKey_it -_libre_RSAPrivateKey_it -_libre_RSA_PSS_PARAMS_it -_libre_RSA_OAEP_PARAMS_it diff --git a/lib/libcrypto/kdf/tls1_prf.c b/lib/libcrypto/kdf/tls1_prf.c index 9d2f77719..7d6231e3c 100644 --- a/lib/libcrypto/kdf/tls1_prf.c +++ b/lib/libcrypto/kdf/tls1_prf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls1_prf.c,v 1.39 2024/07/09 17:58:36 tb Exp $ */ +/* $OpenBSD: tls1_prf.c,v 1.40 2024/07/10 06:53:27 tb Exp $ */ /* * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project * 2016. @@ -146,8 +146,7 @@ pkey_tls1_prf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) } static int -pkey_tls1_prf_ctrl_str(EVP_PKEY_CTX *ctx, - const char *type, const char *value) +pkey_tls1_prf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) { if (value == NULL) { KDFerror(KDF_R_VALUE_MISSING); @@ -178,10 +177,8 @@ pkey_tls1_prf_ctrl_str(EVP_PKEY_CTX *ctx, } static int -tls1_prf_P_hash(const EVP_MD *md, - const unsigned char *secret, size_t secret_len, - const unsigned char *seed, size_t seed_len, - unsigned char *out, size_t out_len) +tls1_prf_P_hash(const EVP_MD *md, const unsigned char *secret, size_t secret_len, + const unsigned char *seed, size_t seed_len, unsigned char *out, size_t out_len) { int chunk; EVP_MD_CTX *ctx = NULL, *ctx_tmp = NULL, *ctx_init = NULL; diff --git a/lib/libcrypto/man/EVP_PKEY_CTX_set_hkdf_md.3 b/lib/libcrypto/man/EVP_PKEY_CTX_set_hkdf_md.3 index 86286fab5..973ae9597 100644 --- a/lib/libcrypto/man/EVP_PKEY_CTX_set_hkdf_md.3 +++ b/lib/libcrypto/man/EVP_PKEY_CTX_set_hkdf_md.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: EVP_PKEY_CTX_set_hkdf_md.3,v 1.3 2023/09/13 13:46:52 schwarze Exp $ +.\" $OpenBSD: EVP_PKEY_CTX_set_hkdf_md.3,v 1.4 2024/07/10 07:57:37 tb Exp $ .\" full merge up to: OpenSSL 1cb7eff4 Sep 10 13:56:40 2019 +0100 .\" .\" This file was written by Alessandro Ghedini , @@ -49,7 +49,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED .\" OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: September 13 2023 $ +.Dd $Mdocdate: July 10 2024 $ .Dt EVP_PKEY_CTX_SET_HKDF_MD 3 .Os .Sh NAME @@ -60,6 +60,7 @@ .Nm EVP_PKEY_CTX_hkdf_mode .Nd HMAC-based Extract-and-Expand key derivation algorithm .Sh SYNOPSIS +.In openssl/evp.h .In openssl/kdf.h .Ft int .Fo EVP_PKEY_CTX_hkdf_mode diff --git a/lib/libcrypto/man/EVP_PKEY_CTX_set_tls1_prf_md.3 b/lib/libcrypto/man/EVP_PKEY_CTX_set_tls1_prf_md.3 new file mode 100644 index 000000000..1b95bbaa9 --- /dev/null +++ b/lib/libcrypto/man/EVP_PKEY_CTX_set_tls1_prf_md.3 @@ -0,0 +1,171 @@ +.\" $OpenBSD: EVP_PKEY_CTX_set_tls1_prf_md.3,v 1.2 2024/07/10 10:22:03 tb Exp $ +.\" full merge up to: OpenSSL 1cb7eff4 Sep 10 13:56:40 2019 +0100 +.\" +.\" This file was written by Dr Stephen Henson , +.\" Copyright (c) 2016 The OpenSSL 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. All advertising materials mentioning features or use of this +.\" software must display the following acknowledgment: +.\" "This product includes software developed by the OpenSSL Project +.\" for use in the OpenSSL Toolkit. (http://www.openssl.org/)" +.\" +.\" 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to +.\" endorse or promote products derived from this software without +.\" prior written permission. For written permission, please contact +.\" openssl-core@openssl.org. +.\" +.\" 5. Products derived from this software may not be called "OpenSSL" +.\" nor may "OpenSSL" appear in their names without prior written +.\" permission of the OpenSSL Project. +.\" +.\" 6. Redistributions of any form whatsoever must retain the following +.\" acknowledgment: +.\" "This product includes software developed by the OpenSSL Project +.\" for use in the OpenSSL Toolkit (http://www.openssl.org/)" +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY +.\" EXPRESSED 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 OpenSSL PROJECT OR +.\" ITS 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 $Mdocdate: July 10 2024 $ +.Dt EVP_PKEY_CTX_SET_TLS1_PRF_MD 3 +.Os +.Sh NAME +.Nm EVP_PKEY_CTX_set_tls1_prf_md , +.Nm EVP_PKEY_CTX_set1_tls1_prf_secret , +.Nm EVP_PKEY_CTX_add1_tls1_prf_seed +.Nd TLS PRF key derivation algorithm +.Sh SYNOPSIS +.In openssl/evp.h +.In openssl/kdf.h +.Ft int +.Fo EVP_PKEY_CTX_set_tls1_prf_md +.Fa "EVP_PKEY_CTX *pctx" +.Fa "const EVP_MD *md" +.Fc +.Ft int +.Fo EVP_PKEY_CTX_set1_tls1_prf_secret +.Fa "EVP_PKEY_CTX *pctx" +.Fa "unsigned char *sec" +.Fa "int seclen" +.Fc +.Ft int +.Fo EVP_PKEY_CTX_add1_tls1_prf_seed +.Fa "EVP_PKEY_CTX *pctx" +.Fa "unsigned char *seed" +.Fa "int seedlen" +.Fc +.Sh DESCRIPTION +The +.Dv EVP_PKEY_TLS1_PRF +algorithm implements the PRF key derivation function for TLS. +It has no associated private key and only implements key derivation using +.Xr EVP_PKEY_derive 3 . +.Pp +.Fn EVP_PKEY_set_tls1_prf_md +sets the message digest associated with the TLS PRF. +.Xr EVP_md5_sha1 3 +is treated as a special case which uses the PRF algorithm using both +MD5 and SHA1 as used in TLS 1.0 and 1.1. +.Pp +.Fn EVP_PKEY_CTX_set_tls1_prf_secret +sets the secret value of the TLS PRF to +.Fa seclen +bytes of the buffer +.Fa sec . +Any existing secret value is replaced and any seed is reset. +.Pp +.Fn EVP_PKEY_CTX_add1_tls1_prf_seed +sets the seed to +.Fa seedlen +bytes of +.Fa seed . +If a seed is already set it is appended to the existing value. +.Sh STRING CTRLS +The TLS PRF also supports string based control operations using +.Xr EVP_PKEY_CTX_ctrl_str 3 . +The +.Fa type +parameter "md" uses the supplied +.Fa value +as the name of the digest algorithm to use. +The +.Fa type +parameters "secret" and "seed" use the supplied +.Fa value +parameter as a secret or seed value. +The names "hexsecret" and "hexseed" are similar except they take a hex +string which is converted to binary. +.Sh NOTES +All these functions are implemented as macros. +.Pp +A context for the TLS PRF can be obtained by calling: +.Bd -literal + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL); +.Ed +.Pp +The digest, secret value and seed must be set before a key is derived or +an error occurs. +.Pp +The total length of all seeds cannot exceed 1024 bytes in length: this +should be more than enough for any normal use of the TLS PRF. +.Pp +The output length of the PRF is specified by the length parameter in the +.Xr EVP_PKEY_derive 3 +function. +Since the output length is variable, setting the buffer to +.Dv NULL +is not meaningful for the TLS PRF. +.Sh RETURN VALUES +All these functions return 1 for success and 0 or a negative value for +failure. +In particular a return value of -2 indicates the operation is not +supported by the public key algorithm. +.Sh EXAMPLES +This example derives 10 bytes using SHA-256 with the secret key "secret" +and seed value "seed": +.Bd -literal + EVP_PKEY_CTX *pctx; + unsigned char out[10]; + size_t outlen = sizeof(out); + + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL); + if (EVP_PKEY_derive_init(pctx) <= 0) + /* Error */ + if (EVP_PKEY_CTX_set_tls1_prf_md(pctx, EVP_sha256()) <= 0) + /* Error */ + if (EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, "secret", 6) <= 0) + /* Error */ + if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, "seed", 4) <= 0) + /* Error */ + if (EVP_PKEY_derive(pctx, out, &outlen) <= 0) + /* Error */ +.Ed +.Sh SEE ALSO +.Xr EVP_PKEY_CTX_ctrl_str 3 , +.Xr EVP_PKEY_CTX_new 3 , +.Xr EVP_PKEY_derive 3 +.Sh HISTORY +These functions first appeared in OpenSSL 1.1.0 and have been available since +.Ox 7.6 . diff --git a/lib/libcrypto/man/Makefile b/lib/libcrypto/man/Makefile index a406bc560..3bb9348af 100644 --- a/lib/libcrypto/man/Makefile +++ b/lib/libcrypto/man/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.287 2024/05/12 11:50:36 tb Exp $ +# $OpenBSD: Makefile,v 1.288 2024/07/10 08:51:28 tb Exp $ .include @@ -176,6 +176,7 @@ MAN= \ EVP_PKEY_CTX_get_operation.3 \ EVP_PKEY_CTX_new.3 \ EVP_PKEY_CTX_set_hkdf_md.3 \ + EVP_PKEY_CTX_set_tls1_prf_md.3 \ EVP_PKEY_add1_attr.3 \ EVP_PKEY_asn1_get_count.3 \ EVP_PKEY_asn1_new.3 \ diff --git a/lib/libssl/man/SSL_CTX_set_alpn_select_cb.3 b/lib/libssl/man/SSL_CTX_set_alpn_select_cb.3 index 5f8da325b..42f68e0a3 100644 --- a/lib/libssl/man/SSL_CTX_set_alpn_select_cb.3 +++ b/lib/libssl/man/SSL_CTX_set_alpn_select_cb.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: SSL_CTX_set_alpn_select_cb.3,v 1.9 2024/06/28 14:48:43 tb Exp $ +.\" $OpenBSD: SSL_CTX_set_alpn_select_cb.3,v 1.10 2024/07/11 13:50:44 tb Exp $ .\" OpenSSL 87b81496 Apr 19 12:38:27 2017 -0400 .\" OpenSSL b97fdb57 Nov 11 09:33:09 2016 +0100 .\" @@ -49,7 +49,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED .\" OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: June 28 2024 $ +.Dd $Mdocdate: July 11 2024 $ .Dt SSL_CTX_SET_ALPN_SELECT_CB 3 .Os .Sh NAME @@ -85,10 +85,10 @@ .Fo SSL_select_next_proto .Fa "unsigned char **out" .Fa "unsigned char *outlen" -.Fa "const unsigned char *server" -.Fa "unsigned int server_len" -.Fa "const unsigned char *client" -.Fa "unsigned int client_len" +.Fa "const unsigned char *peer_list" +.Fa "unsigned int peer_list_len" +.Fa "const unsigned char *supported_list" +.Fa "unsigned int supported_list_len" .Fc .Ft void .Fo SSL_get0_alpn_selected @@ -149,7 +149,6 @@ parameter is the pointer set via .Pp .Fn SSL_select_next_proto is a helper function used to select protocols. -It implements the standard protocol selection. It is expected that this function is called from the application callback .Fa cb . @@ -163,32 +162,30 @@ should ignore and fail by returning .Dv SSL_TLSEXT_ERR_ALERT_FATAL . The protocol data in -.Fa server , -.Fa server_len +.Fa peer_list , +.Fa peer_list_len and -.Fa client , -.Fa client_len -must be in the protocol-list format described below. +.Fa supported_list , +.Fa supported_list_len +must be two non-empty lists, validly encoded +in the protocol-list format described below. The first item in the -.Fa server , -.Fa server_len -list that matches an item in the -.Fa client , -.Fa client_len -list is selected, and returned in +.Fa peer_list +that matches an item in the +.Fa supported_list +is selected, and returned in .Fa out , .Fa outlen . The .Fa out value will point into either -.Fa server +.Fa peer_list or -.Fa client , +.Fa supported_list , so it must not be modified and should be copied immediately. If no match is found, the first item in -.Fa client , -.Fa client_len +.Fa supported_list is returned in .Fa out , .Fa outlen . @@ -213,17 +210,13 @@ of non-empty, 8-bit length-prefixed byte strings. The length-prefix byte is not included in the length. Each string is limited to 255 bytes. A byte-string length of 0 is invalid. -A truncated byte-string is invalid. The length of the vector is not in the vector itself, but in a separate variable. .Pp For example: .Bd -literal -unsigned char vector[] = { - 6, 's', 'p', 'd', 'y', '/', '1', - 8, 'h', 't', 't', 'p', '/', '1', '.', '1' -}; -unsigned int length = sizeof(vector); +const unsigned char *vector = "\e6" "spdy/1" "\e8" "http/1.1"; +unsigned int length = strlen(vector); .Ed .Pp The ALPN callback is executed after the servername callback; as that @@ -249,8 +242,8 @@ A match was found and is returned in .It OPENSSL_NPN_NO_OVERLAP No match was found. The first item in -.Fa client , -.Fa client_len +.Fa supported_list , +.Fa supported_list_len is returned in .Fa out , .Fa outlen . @@ -273,6 +266,16 @@ configured for this connection. .Xr ssl 3 , .Xr SSL_CTX_set_tlsext_servername_arg 3 , .Xr SSL_CTX_set_tlsext_servername_callback 3 +.Sh STANDARDS +.Rs +.%T TLS Application-Layer Protocol Negotiation Extension +.%R RFC 7301 +.Re +.Pp +.Rs +.%T TLS Next Protocol Negotiation Extension +.%U https://datatracker.ietf.org/doc/html/draft-agl-tls-nextprotoneg +.Re .Sh HISTORY .Fn SSL_select_next_proto first appeared in OpenSSL 1.0.1 and has been available since @@ -285,3 +288,18 @@ and .Fn SSL_get0_alpn_selected first appeared in OpenSSL 1.0.2 and have been available since .Ox 5.7 . +.Sh CAVEATS +The fallback to the first supported protocol in +.Fn SSL_select_next_proto +comes from the opportunistic fallback mechanism in the NPN extension. +This behavior does not make sense for ALPN, +where missing protocol overlap should result in a handshake failure. +To avoid accidental selection of a protocol that the server does not +support, it is recommended to pass the locally configured protocols +as second pair of protocols in the ALPN callback. +.Sh BUGS +The +.Fa out +argument of +.Fn SSL_select_next_proto +should have been const. diff --git a/lib/libssl/ssl_lib.c b/lib/libssl/ssl_lib.c index f5d477e86..d78cb2ac3 100644 --- a/lib/libssl/ssl_lib.c +++ b/lib/libssl/ssl_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_lib.c,v 1.325 2024/06/29 07:34:12 tb Exp $ */ +/* $OpenBSD: ssl_lib.c,v 1.326 2024/07/11 13:48:52 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1791,56 +1791,58 @@ LSSL_ALIAS(SSL_get_servername_type); */ int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, - const unsigned char *server_list, unsigned int server_list_len, - const unsigned char *client_list, unsigned int client_list_len) + const unsigned char *peer_list, unsigned int peer_list_len, + const unsigned char *supported_list, unsigned int supported_list_len) { - CBS client, client_proto, server, server_proto; + CBS peer, peer_proto, supported, supported_proto; *out = NULL; *outlen = 0; - /* First check that the client list is well-formed. */ - CBS_init(&client, client_list, client_list_len); - if (!tlsext_alpn_check_format(&client)) + /* First check that the supported list is well-formed. */ + CBS_init(&supported, supported_list, supported_list_len); + if (!tlsext_alpn_check_format(&supported)) goto err; /* - * Use first client protocol as fallback. This is one way of doing NPN's - * "opportunistic" protocol selection (see security considerations in - * draft-agl-tls-nextprotoneg-04), and it is the documented behavior of - * this API. For ALPN it's the callback's responsibility to fail on + * Use first supported protocol as fallback. This is one way of doing + * NPN's "opportunistic" protocol selection (see security considerations + * in draft-agl-tls-nextprotoneg-04), and it is the documented behavior + * of this API. For ALPN it's the callback's responsibility to fail on * OPENSSL_NPN_NO_OVERLAP. */ - if (!CBS_get_u8_length_prefixed(&client, &client_proto)) + if (!CBS_get_u8_length_prefixed(&supported, &supported_proto)) goto err; - *out = (unsigned char *)CBS_data(&client_proto); - *outlen = CBS_len(&client_proto); + *out = (unsigned char *)CBS_data(&supported_proto); + *outlen = CBS_len(&supported_proto); - /* Now check that the server list is well-formed. */ - CBS_init(&server, server_list, server_list_len); - if (!tlsext_alpn_check_format(&server)) + /* Now check that the peer list is well-formed. */ + CBS_init(&peer, peer_list, peer_list_len); + if (!tlsext_alpn_check_format(&peer)) goto err; /* - * Walk the server list and select the first protocol that appears in - * the client list. + * Walk the peer list and select the first protocol that appears in + * the supported list. Thus we honor peer preference rather than local + * preference contrary to a SHOULD in RFC 7301, section 3.2. */ - while (CBS_len(&server) > 0) { - if (!CBS_get_u8_length_prefixed(&server, &server_proto)) + while (CBS_len(&peer) > 0) { + if (!CBS_get_u8_length_prefixed(&peer, &peer_proto)) goto err; - CBS_init(&client, client_list, client_list_len); + CBS_init(&supported, supported_list, supported_list_len); - while (CBS_len(&client) > 0) { - if (!CBS_get_u8_length_prefixed(&client, &client_proto)) + while (CBS_len(&supported) > 0) { + if (!CBS_get_u8_length_prefixed(&supported, + &supported_proto)) goto err; - if (CBS_mem_equal(&client_proto, - CBS_data(&server_proto), CBS_len(&server_proto))) { - *out = (unsigned char *)CBS_data(&server_proto); - *outlen = CBS_len(&server_proto); + if (CBS_mem_equal(&supported_proto, + CBS_data(&peer_proto), CBS_len(&peer_proto))) { + *out = (unsigned char *)CBS_data(&peer_proto); + *outlen = CBS_len(&peer_proto); return OPENSSL_NPN_NEGOTIATED; } diff --git a/libexec/snmpd/snmpd_metrics/pf.c b/libexec/snmpd/snmpd_metrics/pf.c index fd9cff092..1ec239f03 100644 --- a/libexec/snmpd/snmpd_metrics/pf.c +++ b/libexec/snmpd/snmpd_metrics/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.1.1.1 2022/09/01 14:20:33 martijn Exp $ */ +/* $OpenBSD: pf.c,v 1.2 2024/07/10 20:33:31 martijn Exp $ */ /* * Copyright (c) 2012 Joel Knight @@ -210,11 +210,11 @@ pfi_get(struct pfr_buffer *b, const char *filter) bzero(b, sizeof(struct pfr_buffer)); b->pfrb_type = PFRB_IFACES; for (;;) { - pfr_buf_grow(b, b->pfrb_size); + pfr_buf_grow(b, 0); b->pfrb_size = b->pfrb_msize; if (pfi_get_ifaces(filter, b->pfrb_caddr, &(b->pfrb_size))) return (1); - if (b->pfrb_size <= b->pfrb_msize) + if (b->pfrb_size < b->pfrb_msize) break; } diff --git a/regress/lib/libcrypto/symbols/Makefile b/regress/lib/libcrypto/symbols/Makefile index 7b703bbf9..07cce7e90 100644 --- a/regress/lib/libcrypto/symbols/Makefile +++ b/regress/lib/libcrypto/symbols/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.4 2023/06/22 19:23:27 tb Exp $ +# $OpenBSD: Makefile,v 1.5 2024/07/10 13:11:22 tb Exp $ TESTS = \ symbols @@ -22,7 +22,7 @@ LDADD= -lcrypto DPADD= ${LIBCRYPTO} LDFLAGS+= -lcrypto LDFLAGS+= -Wl,--no-allow-shlib-undefined -CFLAGS+= -Wno-deprecated-declarations +CFLAGS+= -Wno-deprecated-declarations -DUSE_LIBRESSL_NAMESPACE CLEANFILES+= include_headers.c symbols.c symbols.c.tmp diff --git a/regress/lib/libcrypto/symbols/symbols.awk b/regress/lib/libcrypto/symbols/symbols.awk index dec111b0b..c9a726600 100644 --- a/regress/lib/libcrypto/symbols/symbols.awk +++ b/regress/lib/libcrypto/symbols/symbols.awk @@ -1,4 +1,4 @@ -# $OpenBSD: symbols.awk,v 1.11 2024/04/15 16:49:13 tb Exp $ +# $OpenBSD: symbols.awk,v 1.12 2024/07/10 13:11:22 tb Exp $ # Copyright (c) 2018,2020 Theo Buehler # @@ -32,6 +32,8 @@ BEGIN { # Undefine aliases, so we don't accidentally leave them in Symbols.list. printf("#ifdef %s\n#undef %s\n#endif\n", $0, $0) + + printf("static typeof(%s) *_libre_%s;\n", $0, $0); } END { @@ -41,12 +43,16 @@ END { printf("\tstruct {\n") printf("\t\tconst char *const name;\n") printf("\t\tconst void *addr;\n") + printf("\t\tconst void *libre_addr;\n") printf("\t} symbols[] = {\n") for (symbol in symbols) { printf("\t\t{\n") printf("\t\t\t.name = \"%s\",\n", symbol) printf("\t\t\t.addr = &%s,\n", symbol) + printf("#if defined(USE_LIBRESSL_NAMESPACE)\n") + printf("\t\t\t.libre_addr = &_libre_%s,\n", symbol) + printf("#endif\n") printf("\t\t},\n") } diff --git a/regress/lib/libssl/unit/ssl_set_alpn_protos.c b/regress/lib/libssl/unit/ssl_set_alpn_protos.c index 6f3fcfbc2..d8447c899 100644 --- a/regress/lib/libssl/unit/ssl_set_alpn_protos.c +++ b/regress/lib/libssl/unit/ssl_set_alpn_protos.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_set_alpn_protos.c,v 1.3 2024/06/28 14:50:37 tb Exp $ */ +/* $OpenBSD: ssl_set_alpn_protos.c,v 1.4 2024/07/11 13:51:47 tb Exp $ */ /* * Copyright (c) 2022 Theo Buehler * @@ -202,162 +202,138 @@ test_ssl_set_alpn_protos_edge_cases(void) } static const struct select_next_proto_test { - const unsigned char *server_list; - size_t server_list_len; - const unsigned char *client_list; - size_t client_list_len; + const unsigned char *peer_list; + size_t peer_list_len; + const unsigned char *supported_list; + size_t supported_list_len; int want_ret; const unsigned char *want_out; unsigned char want_out_len; /* yes, unsigned char */ } select_next_proto_tests[] = { { - .server_list = "\x01" "a" "\x01" "b" "\x01" "c", - .server_list_len = 6, - .client_list = "\x01" "a", - .client_list_len = 2, + .peer_list = "\x01" "a" "\x01" "b" "\x01" "c", + .peer_list_len = 6, + .supported_list = "\x01" "a", + .supported_list_len = 2, .want_ret = OPENSSL_NPN_NEGOTIATED, .want_out = "a", .want_out_len = 1, }, { - .server_list = "\x01" "a" "\x01" "b" "\x01" "c", - .server_list_len = 6, - .client_list = "\x02" "aa" "\x01" "b" "\x01" "c", - .client_list_len = 7, + .peer_list = "\x01" "a" "\x01" "b" "\x01" "c", + .peer_list_len = 6, + .supported_list = "\x02" "aa" "\x01" "b" "\x01" "c", + .supported_list_len = 7, .want_ret = OPENSSL_NPN_NEGOTIATED, .want_out = "b", .want_out_len = 1, }, { - /* Use server preference. */ - .server_list = "\x01" "a" "\x01" "b" "\x01" "c", - .server_list_len = 6, - .client_list = "\x01" "c" "\x01" "b" "\x01" "a", - .client_list_len = 6, + /* Use peer preference. */ + .peer_list = "\x01" "a" "\x01" "b" "\x01" "c", + .peer_list_len = 6, + .supported_list = "\x01" "c" "\x01" "b" "\x01" "a", + .supported_list_len = 6, .want_ret = OPENSSL_NPN_NEGOTIATED, .want_out = "a", .want_out_len = 1, }, { - /* Again server preference wins. */ - .server_list = "\x01" "a" "\x03" "bbb" "\x02" "cc", - .server_list_len = 9, - .client_list = "\x01" "z" "\x02" "cc" "\x03" "bbb", - .client_list_len = 9, + /* Again peer preference wins. */ + .peer_list = "\x01" "a" "\x03" "bbb" "\x02" "cc", + .peer_list_len = 9, + .supported_list = "\x01" "z" "\x02" "cc" "\x03" "bbb", + .supported_list_len = 9, .want_ret = OPENSSL_NPN_NEGOTIATED, .want_out = "bbb", .want_out_len = 3, }, { - /* No overlap fails with first client protocol. */ - .server_list = "\x01" "a" "\x01" "b" "\x01" "c", - .server_list_len = 6, - .client_list = "\x01" "z" "\x01" "y", - .client_list_len = 4, + /* No overlap fails with first supported protocol. */ + .peer_list = "\x01" "a" "\x01" "b" "\x01" "c", + .peer_list_len = 6, + .supported_list = "\x01" "z" "\x01" "y", + .supported_list_len = 4, .want_ret = OPENSSL_NPN_NO_OVERLAP, .want_out = "z", .want_out_len = 1, }, { - /* - * No server protocols is a misconfiguration, but should fail - * cleanly. - */ - .server_list = "", - .server_list_len = 0, - .client_list = "\x01" "a" "\x01" "b" "\x01" "c", - .client_list_len = 6, + /* No peer protocols fails cleanly. */ + .peer_list = "", + .peer_list_len = 0, + .supported_list = "\x01" "a" "\x01" "b" "\x01" "c", + .supported_list_len = 6, .want_out = "a", .want_out_len = 1, .want_ret = OPENSSL_NPN_NO_OVERLAP, }, { - /* - * NULL server protocols is a programming error that fails - * cleanly. - */ - .server_list = NULL, - .server_list_len = 0, - .client_list = "\x01" "a" "\x01" "b" "\x01" "c", - .client_list_len = 6, + /* NULL peer protocols fails cleanly. */ + .peer_list = NULL, + .peer_list_len = 0, + .supported_list = "\x01" "a" "\x01" "b" "\x01" "c", + .supported_list_len = 6, .want_out = "a", .want_out_len = 1, .want_ret = OPENSSL_NPN_NO_OVERLAP, }, { - /* - * Malformed server protocols is a misconfiguration, but it - * should fail cleanly. - */ - .server_list = "\x00", - .server_list_len = 1, - .client_list = "\x01" "a" "\x01" "b" "\x01" "c", - .client_list_len = 6, + /* Malformed peer protocols fails cleanly. */ + .peer_list = "\x00", + .peer_list_len = 1, + .supported_list = "\x01" "a" "\x01" "b" "\x01" "c", + .supported_list_len = 6, .want_out = "a", .want_out_len = 1, .want_ret = OPENSSL_NPN_NO_OVERLAP, }, { - /* - * Malformed server protocols is a misconfiguration, but it - * should fail cleanly. - */ - .server_list = "\x01" "a" "\x03" "bb", - .server_list_len = 5, - .client_list = "\x01" "a" "\x01" "b" "\x01" "c", - .client_list_len = 6, + /* Malformed peer protocols fails cleanly. */ + .peer_list = "\x01" "a" "\x03" "bb", + .peer_list_len = 5, + .supported_list = "\x01" "a" "\x01" "b" "\x01" "c", + .supported_list_len = 6, .want_out = "a", .want_out_len = 1, .want_ret = OPENSSL_NPN_NO_OVERLAP, }, { - /* - * Empty client protocols is not reachable from the ALPN - * callback. It fails cleanly with NULL protocol and 0 length. - */ - .server_list = "\x01" "a", - .server_list_len = 2, - .client_list = "", - .client_list_len = 0, + /* Empty supported list fails cleanly. */ + .peer_list = "\x01" "a", + .peer_list_len = 2, + .supported_list = "", + .supported_list_len = 0, .want_out = NULL, .want_out_len = 0, .want_ret = OPENSSL_NPN_NO_OVERLAP, }, { - /* - * NULL client protocols is not reachable from the ALPN - * callback. It fails cleanly with NULL protocol and 0 length. - */ - .server_list = "\x01" "a", - .server_list_len = 2, - .client_list = NULL, - .client_list_len = 0, + /* NULL supported list fails cleanly. */ + .peer_list = "\x01" "a", + .peer_list_len = 2, + .supported_list = NULL, + .supported_list_len = 0, .want_out = NULL, .want_out_len = 0, .want_ret = OPENSSL_NPN_NO_OVERLAP, }, { - /* - * Malformed client list fails cleanly with NULL protocol and - * 0 length. - */ - .server_list = "\x01" "a", - .server_list_len = 2, - .client_list = "\x01" "a" "\x02" "bb" "\x03" "cc" "\x04" "ddd", - .client_list_len = 12, + /* Malformed supported list fails cleanly. */ + .peer_list = "\x01" "a", + .peer_list_len = 2, + .supported_list = "\x01" "a" "\x02" "bb" "\x03" "cc" "\x04" "ddd", + .supported_list_len = 12, .want_out = NULL, .want_out_len = 0, .want_ret = OPENSSL_NPN_NO_OVERLAP, }, { - /* - * Malformed client list fails cleanly with NULL protocol and - * 0 length. - */ - .server_list = "\x01" "a", - .server_list_len = 2, - .client_list = "\x01" "a" "\x02" "bb" "\x00" "\x03" "ddd", - .client_list_len = 10, + /* Malformed client list fails cleanly. */ + .peer_list = "\x01" "a", + .peer_list_len = 2, + .supported_list = "\x01" "a" "\x02" "bb" "\x00" "\x03" "ddd", + .supported_list_len = 10, .want_out = NULL, .want_out_len = 0, .want_ret = OPENSSL_NPN_NO_OVERLAP, @@ -368,58 +344,58 @@ static const struct select_next_proto_test { */ { - .server_list = "\x08" "http/1.1" "\x06" "spdy/1", - .server_list_len = 16, - .client_list = "\x08" "http/2.0" "\x08" "http/1.1", - .client_list_len = 18, + .peer_list = "\x08" "http/1.1" "\x06" "spdy/1", + .peer_list_len = 16, + .supported_list = "\x08" "http/2.0" "\x08" "http/1.1", + .supported_list_len = 18, .want_out = "http/1.1", .want_out_len = 8, .want_ret = OPENSSL_NPN_NEGOTIATED, }, { - .server_list = "\x08" "http/2.0" "\x06" "spdy/1", - .server_list_len = 16, - .client_list = "\x08" "http/1.0" "\x08" "http/1.1", - .client_list_len = 18, + .peer_list = "\x08" "http/2.0" "\x06" "spdy/1", + .peer_list_len = 16, + .supported_list = "\x08" "http/1.0" "\x08" "http/1.1", + .supported_list_len = 18, .want_out = "http/1.0", .want_out_len = 8, .want_ret = OPENSSL_NPN_NO_OVERLAP, }, { - .server_list = "\x08" "http/1.1" "\x08" "http/1.0", - .server_list_len = 18, - .client_list = "\x08" "http/1.0" "\x08" "http/1.1", - .client_list_len = 18, + .peer_list = "\x08" "http/1.1" "\x08" "http/1.0", + .peer_list_len = 18, + .supported_list = "\x08" "http/1.0" "\x08" "http/1.1", + .supported_list_len = 18, .want_out = "http/1.1", .want_out_len = 8, .want_ret = OPENSSL_NPN_NEGOTIATED, }, { - /* Server malformed. */ - .server_list = "\x08" "http/1.1" "\x07" "http/1.0", - .server_list_len = 18, - .client_list = "\x08" "http/1.0" "\x08" "http/1.1", - .client_list_len = 18, + /* Peer list malformed. */ + .peer_list = "\x08" "http/1.1" "\x07" "http/1.0", + .peer_list_len = 18, + .supported_list = "\x08" "http/1.0" "\x08" "http/1.1", + .supported_list_len = 18, .want_out = "http/1.0", .want_out_len = 8, .want_ret = OPENSSL_NPN_NO_OVERLAP, }, { - /* Server malformed. */ - .server_list = "\x07" "http/1.1" "\x08" "http/1.0", - .server_list_len = 18, - .client_list = "\x08" "http/1.0" "\x08" "http/1.1", - .client_list_len = 18, + /* Peer list malformed. */ + .peer_list = "\x07" "http/1.1" "\x08" "http/1.0", + .peer_list_len = 18, + .supported_list = "\x08" "http/1.0" "\x08" "http/1.1", + .supported_list_len = 18, .want_out = "http/1.0", .want_out_len = 8, .want_ret = OPENSSL_NPN_NO_OVERLAP, }, { - /* Client has trailing bytes. */ - .server_list = "\x08" "http/1.1" "\x08" "http/1.0", - .server_list_len = 18, - .client_list = "\x08" "http/1.0" "\x07" "http/1.1", - .client_list_len = 18, + /* Supported list has trailing bytes. */ + .peer_list = "\x08" "http/1.1" "\x08" "http/1.0", + .peer_list_len = 18, + .supported_list = "\x08" "http/1.0" "\x07" "http/1.1", + .supported_list_len = 18, .want_out = NULL, .want_out_len = 0, .want_ret = OPENSSL_NPN_NO_OVERLAP, @@ -437,8 +413,8 @@ select_next_proto_testcase(const struct select_next_proto_test *test) int ret; int failed = 0; - ret = SSL_select_next_proto(&out, &out_len, test->server_list, - test->server_list_len, test->client_list, test->client_list_len); + ret = SSL_select_next_proto(&out, &out_len, test->peer_list, + test->peer_list_len, test->supported_list, test->supported_list_len); if (ret != test->want_ret || out_len != test->want_out_len || (out == NULL && test->want_out != NULL) || @@ -452,9 +428,9 @@ select_next_proto_testcase(const struct select_next_proto_test *test) fprintf(stderr, "\nwant:\n"); hexdump(test->want_out, test->want_out_len); fprintf(stderr, "\nserver:\n"); - hexdump(test->server_list, test->server_list_len); + hexdump(test->peer_list, test->peer_list_len); fprintf(stderr, "\nclient:\n"); - hexdump(test->client_list, test->client_list_len); + hexdump(test->supported_list, test->supported_list_len); fprintf(stderr, "\n"); failed = 1; } diff --git a/regress/usr.bin/diff/t8.2 b/regress/usr.bin/diff/t8.2 index f84ad5c34..f060fd1a5 100644 --- a/regress/usr.bin/diff/t8.2 +++ b/regress/usr.bin/diff/t8.2 @@ -1,4 +1,4 @@ -/* $OpenBSD: t8.2,v 1.1 2003/07/17 21:04:04 otto Exp $ */ +/* $OpenBSD: t8.2,v 1.2 2024/07/10 09:20:33 krw Exp $ */ /* $NetBSD: kern_malloc.c,v 1.15.4.2 1996/06/13 17:10:56 cgd Exp $ */ /* @@ -76,7 +76,7 @@ struct kmemusage *kmemusage; char *kmembase, *kmemlimit; char buckstring[16 * sizeof("123456,")]; int buckstring_init = 0; -#if defined(KMEMSTATS) || defined(DIAGNOSTIC) || defined(FFS_SOFTUPDATES) +#if defined(KMEMSTATS) || defined(DIAGNOSTIC) char *memname[] = INITKMEMNAMES; char *memall = NULL; extern struct lock sysctl_kmemlock; @@ -561,7 +561,7 @@ sysctl_malloc(name, namelen, oldp, oldlenp, newp, newlen, p) return (EOPNOTSUPP); #endif case KERN_MALLOC_KMEMNAMES: -#if defined(KMEMSTATS) || defined(DIAGNOSTIC) || defined(FFS_SOFTUPDATES) +#if defined(KMEMSTATS) || defined(DIAGNOSTIC) if (memall == NULL) { int totlen; diff --git a/regress/usr.bin/diff/t9.2 b/regress/usr.bin/diff/t9.2 index 0a2273c4f..7ef3b3aa6 100644 --- a/regress/usr.bin/diff/t9.2 +++ b/regress/usr.bin/diff/t9.2 @@ -1,4 +1,4 @@ -/* $OpenBSD: t9.2,v 1.2 2013/12/01 16:40:56 krw Exp $ */ +/* $OpenBSD: t9.2,v 1.4 2024/07/10 09:24:03 krw Exp $ */ /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ /* @@ -591,10 +591,6 @@ sys_statfs(p, v, retval) if ((error = VFS_STATFS(mp, sp, p)) != 0) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; -#if notyet - if (mp->mnt_flag & MNT_SOFTDEP) - sp->f_eflags = STATFS_SOFTUPD; -#endif /* Don't let non-root see filesystem id (for NFS security) */ if (suser(p->p_ucred, &p->p_acflag)) { bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); @@ -633,10 +629,6 @@ sys_fstatfs(p, v, retval) if (error) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; -#if notyet - if (mp->mnt_flag & MNT_SOFTDEP) - sp->f_eflags = STATFS_SOFTUPD; -#endif /* Don't let non-root see filesystem id (for NFS security) */ if (suser(p->p_ucred, &p->p_acflag)) { bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); @@ -689,10 +681,6 @@ sys_getfsstat(p, v, retval) } sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; -#if notyet - if (mp->mnt_flag & MNT_SOFTDEP) - sp->f_eflags = STATFS_SOFTUPD; -#endif if (suser(p->p_ucred, &p->p_acflag)) { bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; @@ -2292,10 +2280,6 @@ sys_fsync(p, v, retval) vp = (struct vnode *)fp->f_data; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p); -#ifdef FFS_SOFTUPDATES - if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP)) - error = softdep_fsync(vp); -#endif VOP_UNLOCK(vp, 0, p); FRELE(fp); diff --git a/sbin/dhcp6leased/dhcp6leased.c b/sbin/dhcp6leased/dhcp6leased.c index 61fbd182a..8c2fb7e55 100644 --- a/sbin/dhcp6leased/dhcp6leased.c +++ b/sbin/dhcp6leased/dhcp6leased.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dhcp6leased.c,v 1.11 2024/06/05 16:15:47 florian Exp $ */ +/* $OpenBSD: dhcp6leased.c,v 1.12 2024/07/11 10:38:57 florian Exp $ */ /* * Copyright (c) 2017, 2021, 2024 Florian Obser @@ -913,6 +913,9 @@ write_lease_file(struct imsg_lease_info *imsg_lease_info) rem = sizeof(lease_buf); for (i = 0; i < iface_conf->ia_count; i++) { + if (imsg_lease_info->pds[i].prefix_len == 0) + continue; + len = snprintf(p, rem, "%s%d %s %d\n", LEASE_IA_PD_PREFIX, i, inet_ntop(AF_INET6, &imsg_lease_info->pds[i].prefix, ntopbuf, INET6_ADDRSTRLEN), diff --git a/sbin/dhcp6leased/dhcp6leased.h b/sbin/dhcp6leased/dhcp6leased.h index f2855759d..977a4cbfa 100644 --- a/sbin/dhcp6leased/dhcp6leased.h +++ b/sbin/dhcp6leased/dhcp6leased.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dhcp6leased.h,v 1.8 2024/06/06 15:15:44 florian Exp $ */ +/* $OpenBSD: dhcp6leased.h,v 1.9 2024/07/10 12:44:46 florian Exp $ */ /* * Copyright (c) 2017, 2021 Florian Obser @@ -260,7 +260,7 @@ void merge_config(struct dhcp6leased_conf *, struct const char *sin6_to_str(struct sockaddr_in6 *); /* engine.c */ -const char *dhcp_message_type2str(uint8_t); +const char *dhcp_message_type2str(int); /* frontend.c */ struct iface_conf *find_iface_conf(struct iface_conf_head *, char *); diff --git a/sbin/dhcp6leased/engine.c b/sbin/dhcp6leased/engine.c index 5ab075416..e410a5a46 100644 --- a/sbin/dhcp6leased/engine.c +++ b/sbin/dhcp6leased/engine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: engine.c,v 1.17 2024/07/09 16:24:57 florian Exp $ */ +/* $OpenBSD: engine.c,v 1.24 2024/07/11 10:48:51 florian Exp $ */ /* * Copyright (c) 2017, 2021, 2024 Florian Obser @@ -127,7 +127,7 @@ struct dhcp6leased_iface *get_dhcp6leased_iface_by_id(uint32_t); void remove_dhcp6leased_iface(uint32_t); void parse_dhcp(struct dhcp6leased_iface *, struct imsg_dhcp *); -void parse_ia_pd_options(uint8_t *, size_t, struct prefix *); +int parse_ia_pd_options(uint8_t *, size_t, struct prefix *); void state_transition(struct dhcp6leased_iface *, enum if_state); void iface_timeout(int, short, void *); @@ -139,10 +139,9 @@ int prefixcmp(struct prefix *, struct prefix *, int); void send_reconfigure_interface(struct iface_pd_conf *, struct prefix *, enum reconfigure_action); int engine_imsg_compose_main(int, pid_t, void *, uint16_t); -const char *dhcp_message_type2str(uint8_t); -const char *dhcp_option_type2str(uint16_t); +const char *dhcp_option_type2str(int); const char *dhcp_duid2str(int, uint8_t *); -const char *dhcp_status2str(uint8_t); +const char *dhcp_status2str(int); void in6_prefixlen2mask(struct in6_addr *, int len); struct dhcp6leased_conf *engine_conf; @@ -813,11 +812,19 @@ parse_dhcp(struct dhcp6leased_iface *iface, struct imsg_dhcp *dhcp) log_debug("%s: IA_PD, IAID: %08x, T1: %u, T2: %u", __func__, ntohl(iapd.iaid), ntohl(iapd.t1), ntohl(iapd.t2)); - if (ntohl(iapd.iaid) < iface_conf->ia_count) - parse_ia_pd_options(p + + if (ntohl(iapd.iaid) < iface_conf->ia_count) { + int status_code; + status_code = parse_ia_pd_options(p + sizeof(struct dhcp_iapd), opt_hdr.len - sizeof(struct dhcp_iapd), &iface->new_pds[ntohl(iapd.iaid)]); + + if (status_code != DHCP_STATUS_SUCCESS && + iface->state == IF_RENEWING) { + state_transition(iface, IF_REBINDING); + goto out; + } + } break; case DHO_RAPID_COMMIT: if (opt_hdr.len != 0) { @@ -933,14 +940,14 @@ parse_dhcp(struct dhcp6leased_iface *iface, struct imsg_dhcp *dhcp) return; } -void +int parse_ia_pd_options(uint8_t *p, size_t len, struct prefix *prefix) { struct dhcp_option_hdr opt_hdr; struct dhcp_iaprefix iaprefix; struct in6_addr mask; int i; - uint16_t status_code; + uint16_t status_code = DHCP_STATUS_SUCCESS; char ntopbuf[INET6_ADDRSTRLEN], *visbuf; while (len >= sizeof(struct dhcp_option_hdr)) { @@ -954,7 +961,7 @@ parse_ia_pd_options(uint8_t *p, size_t len, struct prefix *prefix) dhcp_option_type2str(opt_hdr.code), opt_hdr.len); if (len < opt_hdr.len) { log_warnx("%s: malformed packet, ignoring", __func__); - return; + return DHCP_STATUS_UNSPECFAIL; } switch (opt_hdr.code) { @@ -962,7 +969,7 @@ parse_ia_pd_options(uint8_t *p, size_t len, struct prefix *prefix) if (len < sizeof(struct dhcp_iaprefix)) { log_warnx("%s: malformed packet, ignoring", __func__); - return; + return DHCP_STATUS_UNSPECFAIL; } memcpy(&iaprefix, p, sizeof(struct dhcp_iaprefix)); @@ -997,20 +1004,21 @@ parse_ia_pd_options(uint8_t *p, size_t len, struct prefix *prefix) break; case DHO_STATUS_CODE: - /* - * XXX handle STATUS_CODE if not success - * STATUS_CODE can also appear in other parts of - * the packet. - */ + /* XXX STATUS_CODE can also appear outside of options */ if (len < 2) { log_warnx("%s: malformed packet, ignoring", __func__); - return; + return DHCP_STATUS_UNSPECFAIL; } memcpy(&status_code, p, sizeof(uint16_t)); status_code = ntohs(status_code); - visbuf = calloc(4, len - 2); - strvisx(visbuf, p + 2, len - 2, VIS_SAFE); + /* must be at least 4 * srclen + 1 long */ + visbuf = calloc(4, opt_hdr.len - 2 + 1); + if (visbuf == NULL) { + log_warn("%s", __func__); + break; + } + strvisx(visbuf, p + 2, opt_hdr.len - 2, VIS_SAFE); log_debug("%s: %s - %s", __func__, dhcp_status2str(status_code), visbuf); break; @@ -1020,6 +1028,7 @@ parse_ia_pd_options(uint8_t *p, size_t len, struct prefix *prefix) p += opt_hdr.len; len -= opt_hdr.len; } + return status_code; } /* XXX check valid transitions */ @@ -1270,9 +1279,10 @@ configure_interfaces(struct dhcp6leased_iface *iface) struct iface_ia_conf *ia_conf; struct iface_pd_conf *pd_conf; struct imsg_lease_info imsg_lease_info; + uint32_t i; + char ntopbuf[INET6_ADDRSTRLEN]; char ifnamebuf[IF_NAMESIZE], *if_name; - if ((if_name = if_indextoname(iface->if_index, ifnamebuf)) == NULL) { log_debug("%s: unknown interface %d", __func__, iface->if_index); @@ -1285,11 +1295,14 @@ configure_interfaces(struct dhcp6leased_iface *iface) return; } - memset(&imsg_lease_info, 0, sizeof(imsg_lease_info)); - imsg_lease_info.if_index = iface->if_index; - memcpy(imsg_lease_info.pds, iface->new_pds, sizeof(iface->new_pds)); - engine_imsg_compose_main(IMSG_WRITE_LEASE, 0, &imsg_lease_info, - sizeof(imsg_lease_info)); + for (i = 0; i < iface_conf->ia_count; i++) { + struct prefix *pd = &iface->new_pds[i]; + + log_info("prefix delegation #%d %s/%d received on %s from " + "server %s", i, inet_ntop(AF_INET6, &pd->prefix, ntopbuf, + INET6_ADDRSTRLEN), pd->prefix_len, if_name, + dhcp_duid2str(iface->serverid_len, iface->serverid)); + } SIMPLEQ_FOREACH(ia_conf, &iface_conf->iface_ia_list, entry) { struct prefix *pd = &iface->new_pds[ia_conf->id]; @@ -1300,10 +1313,9 @@ configure_interfaces(struct dhcp6leased_iface *iface) } if (prefixcmp(iface->pds, iface->new_pds, iface_conf->ia_count) != 0) { - uint32_t i; - char ntopbuf[INET6_ADDRSTRLEN]; - - log_warnx("IA_PDs changed"); + log_info("Prefix delegations on %s from server %s changed", + if_name, dhcp_duid2str(iface->serverid_len, + iface->serverid)); for (i = 0; i < iface_conf->ia_count; i++) { log_debug("%s: iface->pds [%d]: %s/%d", __func__, i, inet_ntop(AF_INET6, &iface->pds[i].prefix, ntopbuf, @@ -1318,6 +1330,12 @@ configure_interfaces(struct dhcp6leased_iface *iface) memcpy(iface->pds, iface->new_pds, sizeof(iface->pds)); memset(iface->new_pds, 0, sizeof(iface->new_pds)); + + memset(&imsg_lease_info, 0, sizeof(imsg_lease_info)); + imsg_lease_info.if_index = iface->if_index; + memcpy(imsg_lease_info.pds, iface->pds, sizeof(iface->pds)); + engine_imsg_compose_main(IMSG_WRITE_LEASE, 0, &imsg_lease_info, + sizeof(imsg_lease_info)); } void @@ -1326,6 +1344,8 @@ deconfigure_interfaces(struct dhcp6leased_iface *iface) struct iface_conf *iface_conf; struct iface_ia_conf *ia_conf; struct iface_pd_conf *pd_conf; + uint32_t i; + char ntopbuf[INET6_ADDRSTRLEN]; char ifnamebuf[IF_NAMESIZE], *if_name; @@ -1341,6 +1361,15 @@ deconfigure_interfaces(struct dhcp6leased_iface *iface) return; } + for (i = 0; i < iface_conf->ia_count; i++) { + struct prefix *pd = &iface->pds[i]; + + log_info("Prefix delegation #%d %s/%d expired on %s from " + "server %s", i, inet_ntop(AF_INET6, &pd->prefix, ntopbuf, + INET6_ADDRSTRLEN), pd->prefix_len, if_name, + dhcp_duid2str(iface->serverid_len, iface->serverid)); + } + SIMPLEQ_FOREACH(ia_conf, &iface_conf->iface_ia_list, entry) { struct prefix *pd = &iface->pds[ia_conf->id]; @@ -1348,6 +1377,7 @@ deconfigure_interfaces(struct dhcp6leased_iface *iface) send_reconfigure_interface(pd_conf, pd, DECONFIGURE); } } + memset(iface->pds, 0, sizeof(iface->pds)); } int @@ -1416,7 +1446,7 @@ send_reconfigure_interface(struct iface_pd_conf *pd_conf, struct prefix *pd, } const char * -dhcp_message_type2str(uint8_t type) +dhcp_message_type2str(int type) { static char buf[sizeof("Unknown [255]")]; @@ -1448,13 +1478,13 @@ dhcp_message_type2str(uint8_t type) case DHCPRELAYREPL: return "DHCPRELAYREPL"; default: - snprintf(buf, sizeof(buf), "Unknown [%u]", type); + snprintf(buf, sizeof(buf), "Unknown [%u]", type & 0xff); return buf; } } const char * -dhcp_option_type2str(uint16_t code) +dhcp_option_type2str(int code) { static char buf[sizeof("Unknown [65535]")]; switch (code) { @@ -1481,7 +1511,7 @@ dhcp_option_type2str(uint16_t code) case DHO_INF_MAX_RT: return "DHO_INF_MAX_RT"; default: - snprintf(buf, sizeof(buf), "Unknown [%u]", code); + snprintf(buf, sizeof(buf), "Unknown [%u]", code &0xffff); return buf; } } @@ -1505,7 +1535,7 @@ dhcp_duid2str(int len, uint8_t *p) } const char* -dhcp_status2str(uint8_t status) +dhcp_status2str(int status) { static char buf[sizeof("Unknown [255]")]; @@ -1525,7 +1555,7 @@ dhcp_status2str(uint8_t status) case DHCP_STATUS_NOPREFIXAVAIL: return "NoPrefixAvail"; default: - snprintf(buf, sizeof(buf), "Unknown [%u]", status); + snprintf(buf, sizeof(buf), "Unknown [%u]", status & 0xff); return buf; } } diff --git a/sbin/dhcp6leased/frontend.c b/sbin/dhcp6leased/frontend.c index 716ccfdb0..06c343fc6 100644 --- a/sbin/dhcp6leased/frontend.c +++ b/sbin/dhcp6leased/frontend.c @@ -1,4 +1,4 @@ -/* $OpenBSD: frontend.c,v 1.12 2024/06/19 07:42:44 florian Exp $ */ +/* $OpenBSD: frontend.c,v 1.14 2024/07/11 13:38:03 florian Exp $ */ /* * Copyright (c) 2017, 2021, 2024 Florian Obser @@ -551,6 +551,9 @@ update_iface(uint32_t if_index) if ((flags = get_flags(if_name)) == -1) return; + if (find_iface_conf(&frontend_conf->iface_list, if_name) == NULL) + return; + memset(&ifinfo, 0, sizeof(ifinfo)); ifinfo.if_index = if_index; ifinfo.link_state = -1; @@ -873,8 +876,8 @@ build_packet(uint8_t message_type, struct iface *iface, char *if_name) void send_packet(uint8_t message_type, struct iface *iface) { - ssize_t pkt_len; - char ifnamebuf[IF_NAMESIZE], *if_name; + ssize_t pkt_len; + char ifnamebuf[IF_NAMESIZE], *if_name, *message_name; if (!event_initialized(&iface->udpev)) { iface->send_solicit = 1; @@ -887,7 +890,26 @@ send_packet(uint8_t message_type, struct iface *iface) == NULL) return; /* iface went away, nothing to do */ - log_debug("%s on %s", dhcp_message_type2str(message_type), if_name); + switch (message_type) { + case DHCPSOLICIT: + message_name = "Soliciting"; + break; + case DHCPREQUEST: + message_name = "Requesting"; + break; + case DHCPRENEW: + message_name = "Renewing"; + break; + case DHCPREBIND: + message_name = "Rebinding"; + break; + default: + message_name = NULL; + break; + } + + if (message_name) + log_info("%s lease on %s", message_name, if_name); pkt_len = build_packet(message_type, iface, if_name); diff --git a/share/man/man4/bnxt.4 b/share/man/man4/bnxt.4 index acad31108..20d1e9ba9 100644 --- a/share/man/man4/bnxt.4 +++ b/share/man/man4/bnxt.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bnxt.4,v 1.3 2021/09/08 20:29:21 jmc Exp $ +.\" $OpenBSD: bnxt.4,v 1.4 2024/07/10 07:56:21 jmatthew Exp $ .\" .\" Copyright (c) 2018 Jonathan Matthew .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: September 8 2021 $ +.Dd $Mdocdate: July 10 2024 $ .Dt BNXT 4 .Os .Sh NAME @@ -41,9 +41,9 @@ Broadcom P210p Adapter (10Gb SFP+) .It Broadcom P210tp Adapter (10GBASE-T) .It -Broadcom P255c Adapter (10/25Gb QSFP28) +Broadcom P225c Adapter (10/25Gb QSFP28) .It -Broadcom P255p Adapter (10/25Gb SFP28) +Broadcom P225p Adapter (10/25Gb SFP28) .El .Pp Adapters based on these chipsets are also available as LOM/Mezzanine diff --git a/share/man/man5/port-modules.5 b/share/man/man5/port-modules.5 index eab225998..052e681d9 100644 --- a/share/man/man5/port-modules.5 +++ b/share/man/man5/port-modules.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: port-modules.5,v 1.269 2024/07/09 13:05:15 bentley Exp $ +.\" $OpenBSD: port-modules.5,v 1.270 2024/07/11 12:55:33 bentley Exp $ .\" .\" Copyright (c) 2008 Marc Espie .\" @@ -24,7 +24,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 $Mdocdate: July 9 2024 $ +.Dd $Mdocdate: July 11 2024 $ .Dt PORT-MODULES 5 .Os .Sh NAME @@ -697,7 +697,7 @@ it sets .Ev MODFONT_FAMILY should be set to the name of the font family. This sets -.Ev MODFONT_DIR +.Ev MODFONT_FONTDIR and .Ev MODFONT_DOCDIR using said family name. @@ -707,10 +707,15 @@ target is provided if the port itself does not provide it. This installs fonts from .Ev WRKSRC in the distribution. -If one or more file extensions are listed in -.Ev MODFONT_TYPES , -files of those types will be used. -Otherwise, otf files are preferred, with a fallback to ttf. +If one or more filenames (relative to +.Ev WRKSRC ) +are listed in +.Ev MODFONT_FONTFILES , +they will be installed to +.Ev MODFONT_FONTDIR . +Otherwise, otf files in +.Ev WRKSRC +will be installed, with a fallback to ttf. If filenames (relative to .Ev WRKSRC ) are listed in diff --git a/sys/arch/amd64/amd64/locore0.S b/sys/arch/amd64/amd64/locore0.S index b0f4f553e..bbfed3aa9 100644 --- a/sys/arch/amd64/amd64/locore0.S +++ b/sys/arch/amd64/amd64/locore0.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore0.S,v 1.23 2024/05/12 16:49:38 guenther Exp $ */ +/* $OpenBSD: locore0.S,v 1.24 2024/07/10 12:36:13 bluhm Exp $ */ /* $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $ */ /* @@ -314,17 +314,21 @@ cont: NDML3_ENTRIES + NDML2_ENTRIES + 3) * NBPG) #define fillkpt \ -1: movl %eax,(%ebx) ; /* store phys addr */ \ - movl $0,4(%ebx) ; /* upper 32 bits 0 */ \ - addl $8,%ebx ; /* next pte/pde */ \ - addl $NBPG,%eax ; /* next phys page */ \ - loop 1b ; /* till finished */ + pushl %ebp ; /* save */ \ + movl RELOC((pg_crypt + 4)), %ebp ; /* C bit? */ \ +1: movl %eax,(%ebx) ; /* store phys addr */ \ + movl %ebp,4(%ebx) ; /* upper 32 bits */ \ + addl $8,%ebx ; /* next pte/pde */ \ + addl $NBPG,%eax ; /* next phys page */ \ + loop 1b ; /* till finished */ \ + popl %ebp ; /* restore */ #define fillkpt_nx \ pushl %ebp ; /* save */ \ -1: movl %eax,(%ebx) ; /* store phys addr */ \ movl RELOC((pg_nx + 4)), %ebp ; /* NX bit? */ \ + orl RELOC((pg_crypt + 4)), %ebp ; /* C bit? */ \ +1: movl %eax,(%ebx) ; /* store phys addr */ \ movl %ebp,4(%ebx) ; /* upper 32 bits */ \ addl $8,%ebx ; /* next pte/pde */ \ addl $NBPG,%eax ; /* next phys page */ \ @@ -510,6 +514,7 @@ store_pte: movl %eax, (%ebx) pushl %ebp movl RELOC((pg_nx + 4)), %ebp + orl RELOC((pg_crypt + 4)), %ebp movl %ebp, 4(%ebx) popl %ebp addl $8, %ebx @@ -535,6 +540,7 @@ store_pte: movl %eax,(%ebx) pushl %ebp movl RELOC((pg_nx + 4)), %ebp + orl RELOC((pg_crypt + 4)), %ebp movl %ebp, 4(%ebx) popl %ebp diff --git a/sys/arch/amd64/include/vmmvar.h b/sys/arch/amd64/include/vmmvar.h index 50c1f15b0..b67d3f0a7 100644 --- a/sys/arch/amd64/include/vmmvar.h +++ b/sys/arch/amd64/include/vmmvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmmvar.h,v 1.102 2024/07/09 09:31:37 dv Exp $ */ +/* $OpenBSD: vmmvar.h,v 1.103 2024/07/10 09:27:32 dv Exp $ */ /* * Copyright (c) 2014 Mike Larkin * @@ -88,15 +88,15 @@ #define VMX_EXIT_XSAVES 63 #define VMX_EXIT_XRSTORS 64 +#define VM_EXIT_TERMINATED 0xFFFE +#define VM_EXIT_NONE 0xFFFF + /* * VMX: Misc defines */ #define VMX_MAX_CR3_TARGETS 256 #define VMX_VMCS_PA_CLEAR 0xFFFFFFFFFFFFFFFFUL -#define VM_EXIT_TERMINATED 0xFFFE -#define VM_EXIT_NONE 0xFFFF - /* * SVM: Intercept codes (exit reasons) */ @@ -473,20 +473,6 @@ struct vm_intr_params { uint16_t vip_intr; }; -#define VM_RWVMPARAMS_PVCLOCK_SYSTEM_GPA 0x1 /* read/write pvclock gpa */ -#define VM_RWVMPARAMS_PVCLOCK_VERSION 0x2 /* read/write pvclock version */ -#define VM_RWVMPARAMS_ALL (VM_RWVMPARAMS_PVCLOCK_SYSTEM_GPA | \ - VM_RWVMPARAMS_PVCLOCK_VERSION) - -struct vm_rwvmparams_params { - /* Input parameters to VMM_IOC_READVMPARAMS/VMM_IOC_WRITEVMPARAMS */ - uint32_t vpp_vm_id; - uint32_t vpp_vcpu_id; - uint32_t vpp_mask; - paddr_t vpp_pvclock_system_gpa; - uint32_t vpp_pvclock_version; -}; - #define VM_RWREGS_GPRS 0x1 /* read/write GPRs */ #define VM_RWREGS_SREGS 0x2 /* read/write segment registers */ #define VM_RWREGS_CRS 0x4 /* read/write CRs */ @@ -936,7 +922,6 @@ int vm_impl_init(struct vm *, struct proc *); void vm_impl_deinit(struct vm *); int vcpu_init(struct vcpu *); void vcpu_deinit(struct vcpu *); -int vm_rwvmparams(struct vm_rwvmparams_params *, int); int vm_rwregs(struct vm_rwregs_params *, int); int vcpu_reset_regs(struct vcpu *, struct vcpu_reg_state *); diff --git a/sys/arch/arm64/arm64/cpu.c b/sys/arch/arm64/arm64/cpu.c index 2cfef9992..7438390c0 100644 --- a/sys/arch/arm64/arm64/cpu.c +++ b/sys/arch/arm64/arm64/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.123 2024/07/02 19:59:54 kettenis Exp $ */ +/* $OpenBSD: cpu.c,v 1.125 2024/07/11 12:07:39 kettenis Exp $ */ /* * Copyright (c) 2016 Dale Rahn @@ -245,6 +245,7 @@ uint64_t cpu_id_aa64pfr0; uint64_t cpu_id_aa64pfr1; int arm64_has_lse; +int arm64_has_rng; #ifdef CRYPTO int arm64_has_aes; #endif @@ -273,8 +274,12 @@ struct cfdriver cpu_cd = { NULL, "cpu", DV_DULL }; +struct timeout cpu_rng_to; +void cpu_rng(void *); + void cpu_opp_init(struct cpu_info *, uint32_t); void cpu_psci_init(struct cpu_info *); +void cpu_psci_idle_cycle(void); void cpu_flush_bp_noop(void); void cpu_flush_bp_psci(void); @@ -285,6 +290,25 @@ void cpu_kstat_attach(struct cpu_info *ci); void cpu_opp_kstat_attach(struct cpu_info *ci); #endif +void +cpu_rng(void *arg) +{ + struct timeout *to = arg; + uint64_t rndr; + int ret; + + ret = __builtin_arm_rndrrs(&rndr); + if (ret) + ret = __builtin_arm_rndr(&rndr); + if (ret == 0) { + enqueue_randomness(rndr & 0xffffffff); + enqueue_randomness(rndr >> 32); + } + + if (to) + timeout_add_msec(to, 1000); +} + /* * Enable mitigation for Spectre-V2 branch target injection * vulnerabilities (CVE-2017-5715). @@ -666,6 +690,7 @@ cpu_identify(struct cpu_info *ci) if (ID_AA64ISAR0_RNDR(id) >= ID_AA64ISAR0_RNDR_IMPL) { printf("%sRNDR", sep); sep = ","; + arm64_has_rng = 1; } if (ID_AA64ISAR0_TLB(id) >= ID_AA64ISAR0_TLB_IOS) { @@ -1138,6 +1163,11 @@ cpu_attach(struct device *parent, struct device *dev, void *aux) } cpu_init(); + + if (arm64_has_rng) { + timeout_set(&cpu_rng_to, cpu_rng, &cpu_rng_to); + cpu_rng(&cpu_rng_to); + } #ifdef MULTIPROCESSOR } #endif @@ -1955,6 +1985,51 @@ cpu_psci_init(struct cpu_info *ci) uint32_t cluster; int idx, len, node; + /* + * Find the shallowest (for now) idle state for this CPU. + * This should be the first one that is listed. We'll use it + * in the idle loop. + */ + + len = OF_getproplen(ci->ci_node, "cpu-idle-states"); + if (len < (int)sizeof(uint32_t)) + return; + + states = malloc(len, M_TEMP, M_WAITOK); + OF_getpropintarray(ci->ci_node, "cpu-idle-states", states, len); + node = OF_getnodebyphandle(states[0]); + free(states, M_TEMP, len); + if (node) { + uint32_t entry, exit, residency, param; + int32_t features; + + param = OF_getpropint(node, "arm,psci-suspend-param", 0); + entry = OF_getpropint(node, "entry-latency-us", 0); + exit = OF_getpropint(node, "exit-latency-us", 0); + residency = OF_getpropint(node, "min-residency-us", 0); + ci->ci_psci_idle_latency += entry + exit + 2 * residency; + + /* Skip states that stop the local timer. */ + if (OF_getpropbool(node, "local-timer-stop")) + ci->ci_psci_idle_param = 0; + + /* Skip powerdown states. */ + features = psci_features(CPU_SUSPEND); + if (features == PSCI_NOT_SUPPORTED || + (features & PSCI_FEATURE_POWER_STATE_EXT) == 0) { + if (param & PSCI_POWER_STATE_POWERDOWN) + param = 0; + } else { + if (param & PSCI_POWER_STATE_EXT_POWERDOWN) + param = 0; + } + + if (param) { + ci->ci_psci_idle_param = param; + cpu_idle_cycle_fcn = cpu_psci_idle_cycle; + } + } + /* * Hunt for the deepest idle state for this CPU. This is * fairly complicated as it requires traversing quite a few @@ -2052,6 +2127,30 @@ cpu_psci_init(struct cpu_info *ci) OF_getpropint(node, "arm,psci-suspend-param", 0); } +void +cpu_psci_idle_cycle(void) +{ + struct cpu_info *ci = curcpu(); + struct timeval start, stop; + u_long itime; + + microuptime(&start); + + if (ci->ci_prev_sleep > ci->ci_psci_idle_latency) + psci_cpu_suspend(ci->ci_psci_idle_param, 0, 0); + else + cpu_wfi(); + + microuptime(&stop); + timersub(&stop, &start, &stop); + itime = stop.tv_sec * 1000000 + stop.tv_usec; + + ci->ci_last_itime = itime; + itime >>= 1; + ci->ci_prev_sleep = (ci->ci_prev_sleep + (ci->ci_prev_sleep >> 1) + + itime) >> 1; +} + #if NKSTAT > 0 struct cpu_kstats { diff --git a/sys/arch/arm64/conf/Makefile.arm64 b/sys/arch/arm64/conf/Makefile.arm64 index 837b1fe65..371e1f99a 100644 --- a/sys/arch/arm64/conf/Makefile.arm64 +++ b/sys/arch/arm64/conf/Makefile.arm64 @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.arm64,v 1.48 2024/07/02 10:25:16 kettenis Exp $ +# $OpenBSD: Makefile.arm64,v 1.49 2024/07/11 12:07:40 kettenis Exp $ # For instructions on building kernels consult the config(8) and options(4) # manual pages. @@ -56,7 +56,7 @@ CWARNFLAGS= -Werror -Wall -Wimplicit-function-declaration \ -Wno-unused-but-set-variable -Wno-gnu-folding-constant \ -Wframe-larger-than=2047 -CMACHFLAGS= -march=armv8-a+nofp+nosimd \ +CMACHFLAGS= -march=armv8-a+nofp+nosimd+rng \ -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer \ -ffixed-x18 CMACHFLAGS+= -ffreestanding ${NOPIE_FLAGS} diff --git a/sys/arch/arm64/include/cpu.h b/sys/arch/arm64/include/cpu.h index c4073465a..c9b0e1091 100644 --- a/sys/arch/arm64/include/cpu.h +++ b/sys/arch/arm64/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.47 2024/05/01 12:54:27 mpi Exp $ */ +/* $OpenBSD: cpu.h,v 1.48 2024/07/10 11:01:24 kettenis Exp $ */ /* * Copyright (c) 2016 Dale Rahn * @@ -146,6 +146,8 @@ struct cpu_info { uint64_t ci_ttbr1; vaddr_t ci_el1_stkend; + uint32_t ci_psci_idle_latency; + uint32_t ci_psci_idle_param; uint32_t ci_psci_suspend_param; struct opp_table *ci_opp_table; diff --git a/sys/arch/arm64/include/efivar.h b/sys/arch/arm64/include/efivar.h index 190549a4a..3bc3a8644 100644 --- a/sys/arch/arm64/include/efivar.h +++ b/sys/arch/arm64/include/efivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: efivar.h,v 1.1 2023/01/14 12:11:11 kettenis Exp $ */ +/* $OpenBSD: efivar.h,v 1.2 2024/07/10 10:53:55 kettenis Exp $ */ /* * Copyright (c) 2022 Mark Kettenis * @@ -30,6 +30,11 @@ struct efi_softc { struct todr_chip_handle sc_todr; }; + +extern EFI_GET_VARIABLE efi_get_variable; +extern EFI_SET_VARIABLE efi_set_variable; +extern EFI_GET_NEXT_VARIABLE_NAME efi_get_next_variable_name; + void efi_enter(struct efi_softc *); void efi_leave(struct efi_softc *); diff --git a/sys/arch/arm64/include/vmmvar.h b/sys/arch/arm64/include/vmmvar.h new file mode 100644 index 000000000..76afc5cd8 --- /dev/null +++ b/sys/arch/arm64/include/vmmvar.h @@ -0,0 +1,91 @@ +/* $OpenBSD: vmmvar.h,v 1.1 2024/07/10 10:41:19 dv Exp $ */ +/* + * Copyright (c) 2014 Mike Larkin + * + * 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. + */ + +/* + * CPU capabilities for VMM operation + */ +#ifndef _MACHINE_VMMVAR_H_ +#define _MACHINE_VMMVAR_H_ + +#define VMM_HV_SIGNATURE "OpenBSDVMM58" + +#define VMM_PCI_MMIO_BAR_BASE 0xF0000000ULL +#define VMM_PCI_MMIO_BAR_END 0xFFDFFFFFULL /* 2 MiB below 4 GiB */ + +/* Exit Reasons */ +#define VM_EXIT_TERMINATED 0xFFFE +#define VM_EXIT_NONE 0xFFFF + +struct vmm_softc_md { + /* Capabilities */ + uint32_t nr_cpus; /* [I] */ +}; + +/* + * struct vcpu_inject_event : describes an exception or interrupt to inject. + */ +struct vcpu_inject_event { + uint8_t vie_vector; /* Exception or interrupt vector. */ + uint32_t vie_errorcode; /* Optional error code. */ + uint8_t vie_type; +#define VCPU_INJECT_NONE 0 +#define VCPU_INJECT_INTR 1 /* External hardware interrupt. */ +#define VCPU_INJECT_EX 2 /* HW or SW Exception */ +#define VCPU_INJECT_NMI 3 /* Non-maskable Interrupt */ +}; + +#define VCPU_REGS_NGPRS 31 + +struct vcpu_reg_state { + uint64_t vrs_gprs[VCPU_REGS_NGPRS]; +}; + +/* + * struct vm_exit + * + * Contains VM exit information communicated to vmd(8). This information is + * gathered by vmm(4) from the CPU on each exit that requires help from vmd. + */ +struct vm_exit { + struct vcpu_reg_state vrs; +}; + +struct vm_intr_params { + /* Input parameters to VMM_IOC_INTR */ + uint32_t vip_vm_id; + uint32_t vip_vcpu_id; + uint16_t vip_intr; +}; + +#define VM_RWREGS_GPRS 0x1 /* read/write GPRs */ +#define VM_RWREGS_ALL (VM_RWREGS_GPRS) + +struct vm_rwregs_params { + /* + * Input/output parameters to VMM_IOC_READREGS / + * VMM_IOC_WRITEREGS + */ + uint32_t vrwp_vm_id; + uint32_t vrwp_vcpu_id; + uint64_t vrwp_mask; + struct vcpu_reg_state vrwp_regs; +}; + +/* IOCTL definitions */ +#define VMM_IOC_INTR _IOW('V', 6, struct vm_intr_params) /* Intr pending */ + +#endif /* ! _MACHINE_VMMVAR_H_ */ diff --git a/sys/arch/arm64/stand/efiboot/efiboot.c b/sys/arch/arm64/stand/efiboot/efiboot.c index b52fb2289..044bf6e52 100644 --- a/sys/arch/arm64/stand/efiboot/efiboot.c +++ b/sys/arch/arm64/stand/efiboot/efiboot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: efiboot.c,v 1.56 2024/07/07 09:38:44 patrick Exp $ */ +/* $OpenBSD: efiboot.c,v 1.57 2024/07/10 18:46:42 patrick Exp $ */ /* * Copyright (c) 2015 YASUOKA Masahiko @@ -588,7 +588,8 @@ efi_dma_constraint(void) fdt_node_is_compatible(node, "rockchip,rk3588") || fdt_node_is_compatible(node, "rockchip,rk3588s")) dma_constraint[1] = htobe64(0xffffffff); - if (fdt_node_is_compatible(node, "lenovo,thinkpad-x13s")) + if (fdt_node_is_compatible(node, "qcom,sc8280xp") || + fdt_node_is_compatible(node, "qcom,x1e80100")) dma_constraint[1] = htobe64(0xffffffff); /* Pass DMA constraint. */ diff --git a/sys/dev/efi/efi.c b/sys/dev/efi/efi.c index 6f8b37bb0..6be687645 100644 --- a/sys/dev/efi/efi.c +++ b/sys/dev/efi/efi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: efi.c,v 1.1 2023/01/14 12:11:11 kettenis Exp $ */ +/* $OpenBSD: efi.c,v 1.2 2024/07/10 10:53:55 kettenis Exp $ */ /* * Copyright (c) 2022 3mdeb * @@ -33,6 +33,10 @@ int efiioc_var_next(struct efi_softc *sc, void *); int efiioc_var_set(struct efi_softc *sc, void *); int efi_adapt_error(EFI_STATUS); +EFI_GET_VARIABLE efi_get_variable; +EFI_SET_VARIABLE efi_set_variable; +EFI_GET_NEXT_VARIABLE_NAME efi_get_next_variable_name; + int efiopen(dev_t dev, int flag, int mode, struct proc *p) { @@ -142,13 +146,18 @@ efiioc_var_get(struct efi_softc *sc, void *data) goto leave; } - if (efi_enter_check(sc)) { - error = ENOSYS; - goto leave; + if (efi_get_variable) { + status = efi_get_variable(name, (EFI_GUID *)&ioc->vendor, + &ioc->attrib, &ioc->datasize, value); + } else { + if (efi_enter_check(sc)) { + error = ENOSYS; + goto leave; + } + status = sc->sc_rs->GetVariable(name, (EFI_GUID *)&ioc->vendor, + &ioc->attrib, &ioc->datasize, value); + efi_leave(sc); } - status = sc->sc_rs->GetVariable(name, (EFI_GUID *)&ioc->vendor, - &ioc->attrib, &ioc->datasize, value); - efi_leave(sc); if (status == EFI_BUFFER_TOO_SMALL) { /* @@ -183,13 +192,18 @@ efiioc_var_next(struct efi_softc *sc, void *data) if (error) goto leave; - if (efi_enter_check(sc)) { - error = ENOSYS; - goto leave; + if (efi_get_next_variable_name) { + status = efi_get_next_variable_name(&ioc->namesize, + name, (EFI_GUID *)&ioc->vendor); + } else { + if (efi_enter_check(sc)) { + error = ENOSYS; + goto leave; + } + status = sc->sc_rs->GetNextVariableName(&ioc->namesize, + name, (EFI_GUID *)&ioc->vendor); + efi_leave(sc); } - status = sc->sc_rs->GetNextVariableName(&ioc->namesize, - name, (EFI_GUID *)&ioc->vendor); - efi_leave(sc); if (status == EFI_BUFFER_TOO_SMALL) { /* @@ -242,13 +256,18 @@ efiioc_var_set(struct efi_softc *sc, void *data) goto leave; } - if (efi_enter_check(sc)) { - error = ENOSYS; - goto leave; + if (efi_set_variable) { + status = efi_set_variable(name, (EFI_GUID *)&ioc->vendor, + ioc->attrib, ioc->datasize, value); + } else { + if (efi_enter_check(sc)) { + error = ENOSYS; + goto leave; + } + status = sc->sc_rs->SetVariable(name, (EFI_GUID *)&ioc->vendor, + ioc->attrib, ioc->datasize, value); + efi_leave(sc); } - status = sc->sc_rs->SetVariable(name, (EFI_GUID *)&ioc->vendor, - ioc->attrib, ioc->datasize, value); - efi_leave(sc); error = efi_adapt_error(status); diff --git a/sys/dev/fdt/psci.c b/sys/dev/fdt/psci.c index 14bcd8786..72fea23cf 100644 --- a/sys/dev/fdt/psci.c +++ b/sys/dev/fdt/psci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: psci.c,v 1.16 2024/04/13 14:20:48 kettenis Exp $ */ +/* $OpenBSD: psci.c,v 1.17 2024/07/10 11:01:24 kettenis Exp $ */ /* * Copyright (c) 2016 Jonathan Gray @@ -37,27 +37,6 @@ extern void (*powerdownfn)(void); #define SMCCC_ARCH_WORKAROUND_2 0x80007fff #define SMCCC_ARCH_WORKAROUND_3 0x80003fff -#define PSCI_VERSION 0x84000000 -#ifdef __LP64__ -#define CPU_SUSPEND 0xc4000001 -#else -#define CPU_SUSPEND 0x84000001 -#endif -#define CPU_OFF 0x84000002 -#ifdef __LP64__ -#define CPU_ON 0xc4000003 -#else -#define CPU_ON 0x84000003 -#endif -#define SYSTEM_OFF 0x84000008 -#define SYSTEM_RESET 0x84000009 -#define PSCI_FEATURES 0x8400000a -#ifdef __LP64__ -#define SYSTEM_SUSPEND 0xc400000e -#else -#define SYSTEM_SUSPEND 0x8400000e -#endif - struct psci_softc { struct device sc_dev; register_t (*sc_callfn)(register_t, register_t, register_t, diff --git a/sys/dev/fdt/pscivar.h b/sys/dev/fdt/pscivar.h index ba8942b03..f11666a61 100644 --- a/sys/dev/fdt/pscivar.h +++ b/sys/dev/fdt/pscivar.h @@ -10,12 +10,38 @@ #define PSCI_METHOD_HVC 1 #define PSCI_METHOD_SMC 2 +#define PSCI_VERSION 0x84000000 +#ifdef __LP64__ +#define CPU_SUSPEND 0xc4000001 +#else +#define CPU_SUSPEND 0x84000001 +#endif +#define CPU_OFF 0x84000002 +#ifdef __LP64__ +#define CPU_ON 0xc4000003 +#else +#define CPU_ON 0x84000003 +#endif +#define SYSTEM_OFF 0x84000008 +#define SYSTEM_RESET 0x84000009 +#define PSCI_FEATURES 0x8400000a +#ifdef __LP64__ +#define SYSTEM_SUSPEND 0xc400000e +#else +#define SYSTEM_SUSPEND 0x8400000e +#endif + +#define PSCI_FEATURE_POWER_STATE_EXT (1 << 1) +#define PSCI_POWER_STATE_POWERDOWN (1 << 16) +#define PSCI_POWER_STATE_EXT_POWERDOWN (1 << 30) + int psci_can_suspend(void); int32_t psci_system_suspend(register_t, register_t); int32_t psci_cpu_on(register_t, register_t, register_t); int32_t psci_cpu_off(void); int32_t psci_cpu_suspend(register_t, register_t, register_t); +int32_t psci_features(uint32_t); void psci_flush_bp(void); int psci_method(void); diff --git a/sys/dev/fdt/qcscm.c b/sys/dev/fdt/qcscm.c index 50b9f9e0b..cb7d9d466 100644 --- a/sys/dev/fdt/qcscm.c +++ b/sys/dev/fdt/qcscm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: qcscm.c,v 1.7 2024/07/04 20:11:46 kettenis Exp $ */ +/* $OpenBSD: qcscm.c,v 1.8 2024/07/10 10:53:55 kettenis Exp $ */ /* * Copyright (c) 2022 Patrick Wildt * @@ -33,11 +33,14 @@ #include #include +#include #include #include #include +#include "efi.h" + /* #define QCSCM_DEBUG */ #define ARM_SMCCC_STD_CALL (0U << 31) @@ -142,6 +145,12 @@ EFI_STATUS qcscm_uefi_set_variable(struct qcscm_softc *, CHAR16 *, EFI_STATUS qcscm_uefi_get_next_variable(struct qcscm_softc *, CHAR16 *, int *, EFI_GUID *); +EFI_STATUS qcscm_efi_get_variable(CHAR16 *, EFI_GUID *, UINT32 *, + UINTN *, VOID *); +EFI_STATUS qcscm_efi_set_variable(CHAR16 *, EFI_GUID *, UINT32, + UINTN, VOID *); +EFI_STATUS qcscm_efi_get_next_variable_name(UINTN *, CHAR16 *, EFI_GUID *); + #ifdef QCSCM_DEBUG void qcscm_uefi_dump_variables(struct qcscm_softc *); void qcscm_uefi_dump_variable(struct qcscm_softc *, CHAR16 *, int, @@ -188,6 +197,12 @@ qcscm_attach(struct device *parent, struct device *self, void *aux) printf("\n"); qcscm_sc = sc; +#if NEFI > 0 + efi_get_variable = qcscm_efi_get_variable; + efi_set_variable = qcscm_efi_set_variable; + efi_get_next_variable_name = qcscm_efi_get_next_variable_name; +#endif + #ifdef QCSCM_DEBUG qcscm_uefi_dump_variables(sc); qcscm_uefi_dump_variable(sc, u"RTCInfo", sizeof(u"RTCInfo"), @@ -418,7 +433,7 @@ qcscm_uefi_get_variable(struct qcscm_softc *sc, resp = QCSCM_DMA_KVA(qdm) + respoff; if (resp->command_id != QCTEE_UEFI_GET_VARIABLE || - resp->length < sizeof(*resp) || resp->length > respsize) { + resp->length < sizeof(*resp)) { qcscm_dmamem_free(sc, qdm); return QCTEE_UEFI_DEVICE_ERROR; } @@ -433,7 +448,8 @@ qcscm_uefi_get_variable(struct qcscm_softc *sc, return ret; } - if (resp->data_offset + resp->data_size > resp->length) { + if (resp->length > respsize || + resp->data_offset + resp->data_size > resp->length) { qcscm_dmamem_free(sc, qdm); return QCTEE_UEFI_DEVICE_ERROR; } @@ -641,7 +657,71 @@ qcscm_uefi_get_next_variable(struct qcscm_softc *sc, return QCTEE_UEFI_SUCCESS; } +#if NEFI > 0 + +EFI_STATUS +qcscm_efi_get_variable(CHAR16 *name, EFI_GUID *guid, UINT32 *attributes, + UINTN *data_size, VOID *data) +{ + struct qcscm_softc *sc = qcscm_sc; + EFI_STATUS status; + int name_size; + int size; + + name_size = 0; + while (name[name_size]) + name_size++; + name_size++; + + size = *data_size; + status = qcscm_uefi_get_variable(sc, name, name_size * 2, guid, + attributes, data, &size); + *data_size = size; + + /* Convert 32-bit status code to 64-bit. */ + return ((status & 0xf0000000) << 32 | (status & 0x0fffffff)); +} + +EFI_STATUS +qcscm_efi_set_variable(CHAR16 *name, EFI_GUID *guid, UINT32 attributes, + UINTN data_size, VOID *data) +{ + struct qcscm_softc *sc = qcscm_sc; + EFI_STATUS status; + int name_size; + + name_size = 0; + while (name[name_size]) + name_size++; + name_size++; + + status = qcscm_uefi_set_variable(sc, name, name_size * 2, guid, + attributes, data, data_size); + + /* Convert 32-bit status code to 64-bit. */ + return ((status & 0xf0000000) << 32 | (status & 0x0fffffff)); +} + +EFI_STATUS +qcscm_efi_get_next_variable_name(UINTN *name_size, CHAR16 *name, + EFI_GUID *guid) +{ + struct qcscm_softc *sc = qcscm_sc; + EFI_STATUS status; + int size; + + size = *name_size; + status = qcscm_uefi_get_next_variable(sc, name, &size, guid); + *name_size = size; + + /* Convert 32-bit status code to 64-bit. */ + return ((status & 0xf0000000) << 32 | (status & 0x0fffffff)); +} + +#endif + #ifdef QCSCM_DEBUG + void qcscm_uefi_dump_variables(struct qcscm_softc *sc) { @@ -699,6 +779,7 @@ qcscm_uefi_dump_variable(struct qcscm_softc *sc, CHAR16 *name, int namesize, printf("%02x", data[i]); printf("\n"); } + #endif int diff --git a/sys/dev/pci/drm/include/linux/fb.h b/sys/dev/pci/drm/include/linux/fb.h index fa1035d8b..ed622af72 100644 --- a/sys/dev/pci/drm/include/linux/fb.h +++ b/sys/dev/pci/drm/include/linux/fb.h @@ -60,11 +60,9 @@ struct fb_info { #define FBINFO_STATE_RUNNING 0 #define FBINFO_STATE_SUSPENDED 1 -#define FBINFO_DEFAULT 0 -#define FBINFO_VIRTFB 1 -#define FBINFO_READS_FAST 2 - -#define FBINFO_HIDE_SMEM_START 0 +#define FBINFO_VIRTFB 0x0001 +#define FBINFO_READS_FAST 0x0002 +#define FBINFO_HIDE_SMEM_START 0x0004 #define FB_ROTATE_UR 0 #define FB_ROTATE_CW 1 diff --git a/sys/dev/pci/if_iavf.c b/sys/dev/pci/if_iavf.c index afd6b09da..e8b17cee3 100644 --- a/sys/dev/pci/if_iavf.c +++ b/sys/dev/pci/if_iavf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iavf.c,v 1.14 2024/07/09 16:04:15 jmatthew Exp $ */ +/* $OpenBSD: if_iavf.c,v 1.17 2024/07/10 09:50:28 jmatthew Exp $ */ /* * Copyright (c) 2013-2015, Intel Corporation @@ -1115,7 +1115,7 @@ iavf_config_hena(struct iavf_softc *sc) iaq.iaq_flags = htole16(IAVF_AQ_BUF | IAVF_AQ_RD); iaq.iaq_opcode = htole16(IAVF_AQ_OP_SEND_TO_PF); iaq.iaq_vc_opcode = htole32(IAVF_VC_OP_SET_RSS_HENA); - iaq.iaq_datalen = htole32(sizeof(*caps)); + iaq.iaq_datalen = htole16(sizeof(*caps)); iavf_aq_dva(&iaq, IAVF_DMA_DVA(&sc->sc_scratch)); caps = IAVF_DMA_KVA(&sc->sc_scratch); @@ -2393,11 +2393,15 @@ iavf_atq_done(struct iavf_softc *sc) unsigned int cons; unsigned int prod; + mtx_enter(&sc->sc_atq_mtx); + prod = sc->sc_atq_prod; cons = sc->sc_atq_cons; - if (prod == cons) + if (prod == cons) { + mtx_leave(&sc->sc_atq_mtx); return; + } atq = IAVF_DMA_KVA(&sc->sc_atq); @@ -2421,6 +2425,8 @@ iavf_atq_done(struct iavf_softc *sc) BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); sc->sc_atq_cons = cons; + + mtx_leave(&sc->sc_atq_mtx); } static int @@ -2429,6 +2435,8 @@ iavf_atq_post(struct iavf_softc *sc, struct iavf_aq_desc *iaq) struct iavf_aq_desc *atq, *slot; unsigned int prod; + mtx_enter(&sc->sc_atq_mtx); + atq = IAVF_DMA_KVA(&sc->sc_atq); prod = sc->sc_atq_prod; slot = atq + prod; @@ -2446,6 +2454,9 @@ iavf_atq_post(struct iavf_softc *sc, struct iavf_aq_desc *iaq) prod &= IAVF_AQ_MASK; sc->sc_atq_prod = prod; iavf_wr(sc, sc->sc_aq_regs->atq_tail, prod); + + mtx_leave(&sc->sc_atq_mtx); + return (prod); } @@ -2554,15 +2565,15 @@ iavf_config_irq_map(struct iavf_softc *sc) iavf_aq_dva(&iaq, IAVF_DMA_DVA(&sc->sc_scratch)); map = IAVF_DMA_KVA(&sc->sc_scratch); - map->num_vectors = letoh16(1); + map->num_vectors = htole16(1); vec = map->vecmap; - vec[0].vsi_id = letoh16(sc->sc_vsi_id); + vec[0].vsi_id = htole16(sc->sc_vsi_id); vec[0].vector_id = 0; - vec[0].rxq_map = letoh16(iavf_allqueues(sc)); - vec[0].txq_map = letoh16(iavf_allqueues(sc)); - vec[0].rxitr_idx = IAVF_NOITR; - vec[0].txitr_idx = IAVF_NOITR; + vec[0].rxq_map = htole16(iavf_allqueues(sc)); + vec[0].txq_map = htole16(iavf_allqueues(sc)); + vec[0].rxitr_idx = htole16(IAVF_NOITR); + vec[0].txitr_idx = htole16(IAVF_NOITR); bus_dmamap_sync(sc->sc_dmat, IAVF_DMA_MAP(&sc->sc_scratch), 0, IAVF_DMA_LEN(&sc->sc_scratch), BUS_DMASYNC_PREREAD); diff --git a/sys/dev/vmm/vmm.h b/sys/dev/vmm/vmm.h index 3ec2d20fe..ac682bc2c 100644 --- a/sys/dev/vmm/vmm.h +++ b/sys/dev/vmm/vmm.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmm.h,v 1.5 2024/07/09 09:31:37 dv Exp $ */ +/* $OpenBSD: vmm.h,v 1.6 2024/07/10 10:41:19 dv Exp $ */ /* * Copyright (c) 2014-2023 Mike Larkin * @@ -108,6 +108,20 @@ struct vm_run_params { uint8_t vrp_irqready; /* ready for IRQ on entry */ }; +#define VM_RWVMPARAMS_PVCLOCK_SYSTEM_GPA 0x1 /* read/write pvclock gpa */ +#define VM_RWVMPARAMS_PVCLOCK_VERSION 0x2 /* read/write pvclock version */ +#define VM_RWVMPARAMS_ALL (VM_RWVMPARAMS_PVCLOCK_SYSTEM_GPA | \ + VM_RWVMPARAMS_PVCLOCK_VERSION) + +struct vm_rwvmparams_params { + /* Input parameters to VMM_IOC_READVMPARAMS/VMM_IOC_WRITEVMPARAMS */ + uint32_t vpp_vm_id; + uint32_t vpp_vcpu_id; + uint32_t vpp_mask; + paddr_t vpp_pvclock_system_gpa; + uint32_t vpp_pvclock_version; +}; + /* IOCTL definitions */ #define VMM_IOC_CREATE _IOWR('V', 1, struct vm_create_params) /* Create VM */ #define VMM_IOC_RUN _IOWR('V', 2, struct vm_run_params) /* Run VCPU */ @@ -225,6 +239,7 @@ void vm_teardown(struct vm **); int vm_get_info(struct vm_info_params *); int vm_terminate(struct vm_terminate_params *); int vm_resetcpu(struct vm_resetcpu_params *); +int vm_rwvmparams(struct vm_rwvmparams_params *, int); int vcpu_must_stop(struct vcpu *); int vm_share_mem(struct vm_sharemem_params *, struct proc *); int vm_run(struct vm_run_params *); diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 422afa832..23331f7d1 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sig.c,v 1.331 2024/07/09 09:22:50 claudio Exp $ */ +/* $OpenBSD: kern_sig.c,v 1.332 2024/07/10 12:28:46 claudio Exp $ */ /* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */ /* @@ -1078,7 +1078,12 @@ ptsignal(struct proc *p, int signum, enum signal_type type) */ if (signum == SIGKILL) { atomic_clearbits_int(&p->p_flag, P_SUSPSIG); - goto runfast; + /* Raise priority to at least PUSER. */ + if (p->p_usrpri > PUSER) + p->p_usrpri = PUSER; + unsleep(p); + setrunnable(p); + goto out; } if (prop & SA_CONT) { @@ -1097,10 +1102,19 @@ ptsignal(struct proc *p, int signum, enum signal_type type) wakeparent = 1; if (action == SIG_DFL) mask = 0; - if (action == SIG_CATCH) - goto runfast; - if (p->p_wchan == NULL) - goto run; + if (action == SIG_CATCH) { + /* Raise priority to at least PUSER. */ + if (p->p_usrpri > PUSER) + p->p_usrpri = PUSER; + unsleep(p); + setrunnable(p); + goto out; + } + if (p->p_wchan == NULL) { + unsleep(p); + setrunnable(p); + goto out; + } atomic_clearbits_int(&p->p_flag, P_WSLEEP); p->p_stat = SSLEEP; goto out; @@ -1146,8 +1160,11 @@ ptsignal(struct proc *p, int signum, enum signal_type type) * so it can discover the signal in cursig() and stop * for the parent. */ - if (pr->ps_flags & PS_TRACED) - goto run; + if (pr->ps_flags & PS_TRACED) { + unsleep(p); + setrunnable(p); + goto out; + } /* * Recheck sigmask before waking up the process, @@ -1206,8 +1223,13 @@ ptsignal(struct proc *p, int signum, enum signal_type type) /* * All other (caught or default) signals * cause the process to run. + * Raise priority to at least PUSER. */ - goto runfast; + if (p->p_usrpri > PUSER) + p->p_usrpri = PUSER; + unsleep(p); + setrunnable(p); + goto out; /* NOTREACHED */ case SONPROC: @@ -1229,15 +1251,6 @@ ptsignal(struct proc *p, int signum, enum signal_type type) } /* NOTREACHED */ -runfast: - /* - * Raise priority to at least PUSER. - */ - if (p->p_usrpri > PUSER) - p->p_usrpri = PUSER; -run: - unsleep(p); - setrunnable(p); out: /* finally adjust siglist */ if (mask) diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 709b99a76..dfe80510c 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sysctl.c,v 1.428 2024/07/08 13:17:12 claudio Exp $ */ +/* $OpenBSD: kern_sysctl.c,v 1.429 2024/07/11 14:11:55 bluhm Exp $ */ /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ /*- @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -1005,19 +1006,39 @@ int sysctl_int_bounded(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp, int minimum, int maximum) { - int val = *valp; + int oldval, newval; int error; /* read only */ - if (newp == NULL || minimum > maximum) - return (sysctl_rdint(oldp, oldlenp, newp, val)); + if (newp != NULL && minimum > maximum) + return (EPERM); - if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &val))) - return (error); - /* outside limits */ - if (val < minimum || maximum < val) + if (oldp != NULL && *oldlenp < sizeof(int)) + return (ENOMEM); + if (newp != NULL && newlen != sizeof(int)) return (EINVAL); - *valp = val; + *oldlenp = sizeof(int); + + /* copyin() may sleep, call it first */ + if (newp != NULL) { + if ((error = copyin(newp, &newval, sizeof(int)))) + return (error); + /* outside limits */ + if (newval < minimum || maximum < newval) + return (EINVAL); + } + if (oldp != NULL) { + if (newp != NULL) + oldval = atomic_swap_uint(valp, newval); + else + oldval = atomic_load_int(valp); + if ((error = copyout(&oldval, oldp, sizeof(int)))) { + /* new value has been set although user gets error */ + return (error); + } + } else if (newp != NULL) + atomic_store_int(valp, newval); + return (0); } diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index abd4395bc..e131165b9 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_syscalls.c,v 1.365 2024/05/18 05:20:22 guenther Exp $ */ +/* $OpenBSD: vfs_syscalls.c,v 1.366 2024/07/10 09:12:11 krw Exp $ */ /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ /* @@ -697,10 +697,6 @@ sys_getfsstat(struct proc *p, void *v, register_t *retval) } sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; -#if notyet - if (mp->mnt_flag & MNT_SOFTDEP) - sp->f_eflags = STATFS_SOFTUPD; -#endif error = (copyout_statfs(sp, sfsp, p)); if (error) { vfs_unbusy(mp); diff --git a/usr.bin/mg/mg.1 b/usr.bin/mg/mg.1 index 7afbd733b..ab42a8f2e 100644 --- a/usr.bin/mg/mg.1 +++ b/usr.bin/mg/mg.1 @@ -1,7 +1,7 @@ -.\" $OpenBSD: mg.1,v 1.138 2024/07/09 14:51:37 op Exp $ +.\" $OpenBSD: mg.1,v 1.139 2024/07/10 05:19:02 jmc Exp $ .\" This file is in the public domain. .\" -.Dd $Mdocdate: July 9 2024 $ +.Dd $Mdocdate: July 10 2024 $ .Dt MG 1 .Os .Sh NAME @@ -938,11 +938,11 @@ Set the tab width for the current buffer, or the default for new buffers if called with a prefix argument or from the startup file. .It Ic shell-command Execute external command from mini-buffer. -With an universal argument it inserts the command output into the current +With a universal argument it inserts the command output into the current buffer. .It Ic shell-command-on-region Provide the text in region to the shell command as input. -With an universal argument it replaces the region with the command +With a universal argument it replaces the region with the command output. .It Ic shrink-window Shrink current window by one line. diff --git a/usr.bin/ssh/sshd_config.5 b/usr.bin/ssh/sshd_config.5 index b76386513..3b4b178da 100644 --- a/usr.bin/ssh/sshd_config.5 +++ b/usr.bin/ssh/sshd_config.5 @@ -33,8 +33,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd_config.5,v 1.366 2024/07/04 22:53:59 djm Exp $ -.Dd $Mdocdate: July 4 2024 $ +.\" $OpenBSD: sshd_config.5,v 1.367 2024/07/10 21:58:34 djm Exp $ +.Dd $Mdocdate: July 10 2024 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -1579,7 +1579,7 @@ accumulated. .Pp Penalties are enabled by default with the default settings listed below but may disabled using the -.Cm off +.Cm no keyword. The defaults may be overridden by specifying one or more of the keywords below, separated by whitespace. diff --git a/usr.sbin/npppd/npppd/npppd.c b/usr.sbin/npppd/npppd/npppd.c index 185fed0a7..556f6dcf8 100644 --- a/usr.sbin/npppd/npppd/npppd.c +++ b/usr.sbin/npppd/npppd/npppd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: npppd.c,v 1.53 2022/07/01 09:57:24 mvs Exp $ */ +/* $OpenBSD: npppd.c,v 1.54 2024/07/11 14:05:59 yasuoka Exp $ */ /*- * Copyright (c) 2005-2008,2009 Internet Initiative Japan Inc. @@ -29,7 +29,7 @@ * Next pppd(nppd). This file provides a npppd daemon process and operations * for npppd instance. * @author Yasuoka Masahiko - * $Id: npppd.c,v 1.53 2022/07/01 09:57:24 mvs Exp $ + * $Id: npppd.c,v 1.54 2024/07/11 14:05:59 yasuoka Exp $ */ #include "version.h" #include /* ALIGNED_POINTER */ @@ -101,7 +101,6 @@ static void npppd_timer(int, short, void *); static void npppd_auth_finalizer_periodic(npppd *); static int rd2slist_walk (struct radish *, void *); static int rd2slist (struct radish_head *, slist *); -static slist *npppd_get_ppp_by_user (npppd *, const char *); static int npppd_get_all_users (npppd *, slist *); static struct ipcpstat *npppd_get_ipcp_stat(struct ipcpstat_head *, const char *); @@ -255,6 +254,7 @@ npppd_init(npppd *_this, const char *config_file) _this->pid = getpid(); slist_init(&_this->realms); npppd_conf_init(&_this->conf); + TAILQ_INIT(&_this->raddae_listens); log_printf(LOG_NOTICE, "Starting npppd pid=%u version=%s", _this->pid, VERSION); @@ -444,6 +444,10 @@ npppd_stop(npppd *_this) _this->finalizing = 1; npppd_reset_timer(_this); + +#ifdef USE_NPPPD_RADIUS + npppd_radius_dae_fini(_this); +#endif } static void @@ -763,7 +767,7 @@ npppd_get_ppp_by_ip(npppd *_this, struct in_addr ipaddr) * @return {@link slist} that contains the {@link npppd_ppp} instances. * NULL may be returned if no instance has been found. */ -static slist * +slist * npppd_get_ppp_by_user(npppd *_this, const char *username) { hash_link *hl; diff --git a/usr.sbin/npppd/npppd/npppd.conf.5 b/usr.sbin/npppd/npppd/npppd.conf.5 index ab2ed0b5d..559ce22f9 100644 --- a/usr.sbin/npppd/npppd/npppd.conf.5 +++ b/usr.sbin/npppd/npppd/npppd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: npppd.conf.5,v 1.34 2024/07/01 14:56:19 jmc Exp $ +.\" $OpenBSD: npppd.conf.5,v 1.35 2024/07/11 14:05:59 yasuoka Exp $ .\" .\" Copyright (c) 2012 YASUOKA Masahiko .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: July 1 2024 $ +.Dd $Mdocdate: July 11 2024 $ .Dt NPPPD.CONF 5 .Os .Sh NAME @@ -41,6 +41,8 @@ Interface settings. Authentication settings. .It Sy Bind Bind settings. +.It Sy RADIUS +RADIUS settings. .El .Sh GLOBAL The global options are as follows: @@ -664,6 +666,32 @@ settings so that they are used together. .Pp .Ic bind tunnel from Ar tunnel Ic authenticated by Ar authentication .Ic to Ar ifname +.Sh RADIUS +.Ic radius +configures the RADIUS features. +The supported options are as follows: +.Bl -tag -width Ds +.It Ic radius nas-id Ar identifier +Specify the +.Ar identifier +that is noticed to the RADIUS peers in the NAS-Identifier attribute. +.It Ic radius dae listen on Ar address Oo port Ar number Oc +Enable the Dynamic Authorization Extensions for RADIUS +.Po DAE, RFC 5176 Pc +server. +Specify the local +.Ar address +.Xr npppd 8 +should listen on for the DAE requests. +Optionally specify a port +.Ar number , +the default port number is 3799. +.It Ic radius dae client Ar address Ic secret Ar secret +Specify +.Ar address +for a DAE client and +.Ar secret . +.El .Sh EXAMPLES A very simple configuration example is below: .Bd -literal -offset indent diff --git a/usr.sbin/npppd/npppd/npppd.h b/usr.sbin/npppd/npppd/npppd.h index 3cf9b2bcb..1d33ce4bd 100644 --- a/usr.sbin/npppd/npppd/npppd.h +++ b/usr.sbin/npppd/npppd/npppd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: npppd.h,v 1.20 2024/07/01 07:09:07 yasuoka Exp $ */ +/* $OpenBSD: npppd.h,v 1.21 2024/07/11 14:05:59 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -43,6 +43,7 @@ #include "l2tp_conf.h" #include "pptp_conf.h" #include "pppoe_conf.h" +#include "slist.h" #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) @@ -170,6 +171,25 @@ struct authconf { } data; }; +struct radclientconf { + union { + struct sockaddr_in sin4; + struct sockaddr_in6 sin6; + } addr; + TAILQ_ENTRY(radclientconf) entry; + char secret[]; +}; +TAILQ_HEAD(radclientconfs,radclientconf); + +struct radlistenconf { + union { + struct sockaddr_in sin4; + struct sockaddr_in6 sin6; + } addr; + TAILQ_ENTRY(radlistenconf) entry; +}; +TAILQ_HEAD(radlistenconfs,radlistenconf); + struct ipcpconf { TAILQ_ENTRY(ipcpconf) entry; char name[NPPPD_GENERIC_NAME_LEN]; @@ -207,6 +227,9 @@ struct npppd_conf { TAILQ_HEAD(ipcpconfs, ipcpconf) ipcpconfs; TAILQ_HEAD(ifaces, iface) ifaces; TAILQ_HEAD(confbinds, confbind) confbinds; + struct radclientconfs raddaeclientconfs; + struct radlistenconfs raddaelistenconfs; + char nas_id[NPPPD_GENERIC_NAME_LEN]; struct l2tp_confs l2tp_confs; struct pptp_confs pptp_confs; struct pppoe_confs pppoe_confs; @@ -266,65 +289,70 @@ TAILQ_HEAD(ctl_conn_list, ctl_conn); extern struct ctl_conn_list ctl_conns; __BEGIN_DECLS -npppd *npppd_get_npppd (void); -int npppd_init (npppd *, const char *); -void npppd_start (npppd *); -void npppd_stop (npppd *); -void npppd_fini (npppd *); -int npppd_reset_routing_table (npppd *, int); -int npppd_get_user_password (npppd *, npppd_ppp *, const char *, char *, int *); -struct in_addr *npppd_get_user_framed_ip_address (npppd *, npppd_ppp *, const char *); -int npppd_check_calling_number (npppd *, npppd_ppp *); -npppd_ppp *npppd_get_ppp_by_ip (npppd *, struct in_addr); -npppd_ppp *npppd_get_ppp_by_id (npppd *, u_int); -int npppd_check_user_max_session (npppd *, npppd_ppp *); -void npppd_network_output (npppd *, npppd_ppp *, int, u_char *, int); -int npppd_ppp_pipex_enable (npppd *, npppd_ppp *); -int npppd_ppp_pipex_disable (npppd *, npppd_ppp *); -int npppd_prepare_ip (npppd *, npppd_ppp *); -void npppd_release_ip (npppd *, npppd_ppp *); -void npppd_set_ip_enabled (npppd *, npppd_ppp *, int); -int npppd_assign_ip_addr (npppd *, npppd_ppp *, uint32_t); -int npppd_set_radish (npppd *, void *); -int npppd_ppp_bind_realm (npppd *, npppd_ppp *, const char *, int); -int npppd_ppp_is_realm_local (npppd *, npppd_ppp *); -int npppd_ppp_is_realm_radius (npppd *, npppd_ppp *); -int npppd_ppp_is_realm_ready (npppd *, npppd_ppp *); -const char *npppd_ppp_get_realm_name (npppd *, npppd_ppp *); -const char *npppd_ppp_get_iface_name (npppd *, npppd_ppp *); -int npppd_ppp_iface_is_ready (npppd *, npppd_ppp *); -int npppd_ppp_bind_iface (npppd *, npppd_ppp *); -void npppd_ppp_unbind_iface (npppd *, npppd_ppp *); -void *npppd_get_radius_auth_setting (npppd *, npppd_ppp *); -int sockaddr_npppd_match (void *, void *); -const char *npppd_ppp_get_username_for_auth (npppd *, npppd_ppp *, const char *, char *); -const char *npppd_ppp_tunnel_protocol_name (npppd *, npppd_ppp *); -const char *npppd_tunnel_protocol_name (int); -struct tunnconf *npppd_get_tunnconf (npppd *, const char *); -int npppd_reload_config (npppd *); -int npppd_modules_reload (npppd *); -int npppd_ifaces_load_config (npppd *); +npppd *npppd_get_npppd(void); +int npppd_init(npppd *, const char *); +void npppd_start(npppd *); +void npppd_stop(npppd *); +void npppd_fini(npppd *); +int npppd_reset_routing_table(npppd *, int); +int npppd_get_user_password(npppd *, npppd_ppp *, const char *, + char *, int *); +struct in_addr *npppd_get_user_framed_ip_address(npppd *, npppd_ppp *, + const char *); +int npppd_check_calling_number(npppd *, npppd_ppp *); +npppd_ppp *npppd_get_ppp_by_ip(npppd *, struct in_addr); +npppd_ppp *npppd_get_ppp_by_id(npppd *, u_int); +slist *npppd_get_ppp_by_user(npppd *, const char *); +int npppd_check_user_max_session(npppd *, npppd_ppp *); +void npppd_network_output(npppd *, npppd_ppp *, int, u_char *, int); +int npppd_ppp_pipex_enable(npppd *, npppd_ppp *); +int npppd_ppp_pipex_disable(npppd *, npppd_ppp *); +int npppd_prepare_ip(npppd *, npppd_ppp *); +void npppd_release_ip(npppd *, npppd_ppp *); +void npppd_set_ip_enabled(npppd *, npppd_ppp *, int); +int npppd_assign_ip_addr(npppd *, npppd_ppp *, uint32_t); +int npppd_set_radish(npppd *, void *); +int npppd_ppp_bind_realm(npppd *, npppd_ppp *, const char *, int); +int npppd_ppp_is_realm_local(npppd *, npppd_ppp *); +int npppd_ppp_is_realm_radius(npppd *, npppd_ppp *); +int npppd_ppp_is_realm_ready(npppd *, npppd_ppp *); +const char *npppd_ppp_get_realm_name(npppd *, npppd_ppp *); +const char *npppd_ppp_get_iface_name(npppd *, npppd_ppp *); +int npppd_ppp_iface_is_ready(npppd *, npppd_ppp *); +int npppd_ppp_bind_iface(npppd *, npppd_ppp *); +void npppd_ppp_unbind_iface(npppd *, npppd_ppp *); +void *npppd_get_radius_auth_setting(npppd *, npppd_ppp *); +int sockaddr_npppd_match(void *, void *); +const char *npppd_ppp_get_username_for_auth(npppd *, npppd_ppp *, + const char *, char *); +const char *npppd_ppp_tunnel_protocol_name(npppd *, npppd_ppp *); +const char *npppd_tunnel_protocol_name(int); +struct tunnconf *npppd_get_tunnconf(npppd *, const char *); +int npppd_reload_config(npppd *); +int npppd_modules_reload(npppd *); +int npppd_ifaces_load_config(npppd *); -int npppd_conf_parse (struct npppd_conf *, const char *); -void npppd_conf_init (struct npppd_conf *); -void npppd_conf_fini (struct npppd_conf *); -int npppd_config_check (const char *); -void npppd_on_ppp_start (npppd *, npppd_ppp *); -void npppd_on_ppp_stop (npppd *, npppd_ppp *); -void imsg_event_add(struct imsgev *); +int npppd_conf_parse(struct npppd_conf *, const char *); +void npppd_conf_init(struct npppd_conf *); +void npppd_conf_fini(struct npppd_conf *); +int npppd_config_check(const char *); +void npppd_on_ppp_start(npppd *, npppd_ppp *); +void npppd_on_ppp_stop(npppd *, npppd_ppp *); +void imsg_event_add(struct imsgev *); -int control_init (struct control_sock *); -int control_listen (struct control_sock *); -void control_cleanup (struct control_sock *); -struct npppd_ctl *npppd_ctl_create (npppd *); -void npppd_ctl_destroy (struct npppd_ctl *); -int npppd_ctl_who (struct npppd_ctl *); -int npppd_ctl_monitor (struct npppd_ctl *); -int npppd_ctl_who_and_monitor (struct npppd_ctl *); -int npppd_ctl_add_started_ppp_id (struct npppd_ctl *, uint32_t); -int npppd_ctl_add_stopped_ppp (struct npppd_ctl *, npppd_ppp *); -int npppd_ctl_imsg_compose (struct npppd_ctl *, struct imsgbuf *); -int npppd_ctl_disconnect (struct npppd_ctl *, u_int *, int); +int control_init(struct control_sock *); +int control_listen(struct control_sock *); +void control_cleanup(struct control_sock *); +struct npppd_ctl + *npppd_ctl_create(npppd *); +void npppd_ctl_destroy(struct npppd_ctl *); +int npppd_ctl_who(struct npppd_ctl *); +int npppd_ctl_monitor(struct npppd_ctl *); +int npppd_ctl_who_and_monitor(struct npppd_ctl *); +int npppd_ctl_add_started_ppp_id(struct npppd_ctl *, uint32_t); +int npppd_ctl_add_stopped_ppp(struct npppd_ctl *, npppd_ppp *); +int npppd_ctl_imsg_compose(struct npppd_ctl *, struct imsgbuf *); +int npppd_ctl_disconnect(struct npppd_ctl *, u_int *, int); __END_DECLS diff --git a/usr.sbin/npppd/npppd/npppd_config.c b/usr.sbin/npppd/npppd/npppd_config.c index d5a93fbcc..614ac71db 100644 --- a/usr.sbin/npppd/npppd/npppd_config.c +++ b/usr.sbin/npppd/npppd/npppd_config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: npppd_config.c,v 1.14 2015/01/19 01:48:59 deraadt Exp $ */ +/* $OpenBSD: npppd_config.c,v 1.15 2024/07/11 14:05:59 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -/* $Id: npppd_config.c,v 1.14 2015/01/19 01:48:59 deraadt Exp $ */ +/* $Id: npppd_config.c,v 1.15 2024/07/11 14:05:59 yasuoka Exp $ */ /*@file * This file provides functions which operates configuration and so on. */ @@ -131,6 +131,9 @@ npppd_modules_reload(npppd *_this) #ifdef USE_NPPPD_PPPOE rval |= pppoed_reload(&_this->pppoed, &_this->conf.pppoe_confs); #endif +#ifdef USE_NPPPD_RADIUS + npppd_radius_dae_init(_this); +#endif return rval; } diff --git a/usr.sbin/npppd/npppd/npppd_local.h b/usr.sbin/npppd/npppd/npppd_local.h index 37205b65f..d3e692f51 100644 --- a/usr.sbin/npppd/npppd/npppd_local.h +++ b/usr.sbin/npppd/npppd/npppd_local.h @@ -1,4 +1,4 @@ -/* $OpenBSD: npppd_local.h,v 1.18 2024/02/26 08:29:37 yasuoka Exp $ */ +/* $OpenBSD: npppd_local.h,v 1.19 2024/07/11 14:05:59 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -73,6 +73,10 @@ #include "npppd_pool.h" #include "npppd_ctl.h" +#ifdef USE_NPPPD_RADIUS +#include "npppd_radius.h" +#endif + /** structure of pool */ struct _npppd_pool { /** base of npppd structure */ @@ -169,6 +173,10 @@ struct _npppd { struct control_sock ctl_sock; +#ifdef USE_NPPPD_RADIUS + struct npppd_radius_dae_listens raddae_listens; +#endif + u_int /** whether finalizing or not */ finalizing:1, /** whether finalize completed or not */ diff --git a/usr.sbin/npppd/npppd/npppd_radius.c b/usr.sbin/npppd/npppd/npppd_radius.c index 2d3ef6f9d..edc4c371d 100644 --- a/usr.sbin/npppd/npppd/npppd_radius.c +++ b/usr.sbin/npppd/npppd/npppd_radius.c @@ -1,4 +1,4 @@ -/* $Id: npppd_radius.c,v 1.11 2024/07/01 07:09:07 yasuoka Exp $ */ +/* $Id: npppd_radius.c,v 1.12 2024/07/11 14:05:59 yasuoka Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. * All rights reserved. @@ -45,12 +45,16 @@ #include #include #include +#include +#include +#include #include #include "radius_req.h" #include "npppd_local.h" #include "npppd_radius.h" +#include "net_utils.h" #ifdef NPPPD_RADIUS_DEBUG #define NPPPD_RADIUS_DBG(x) ppp_log x @@ -268,7 +272,7 @@ radius_acct_request(npppd *pppd, npppd_ppp *ppp, int stop) /* npppd has no physical / virtual ports in design. */ /* RFC 2865 5.32. NAS-Identifier */ - ATTR_STR(RADIUS_TYPE_NAS_IDENTIFIER, "npppd"); + ATTR_STR(RADIUS_TYPE_NAS_IDENTIFIER, pppd->conf.nas_id); /* RFC 2865 5.31. Calling-Station-Id */ if (ppp->calling_number[0] != '\0') @@ -397,7 +401,7 @@ radius_acct_on(npppd *pppd, radius_req_setting *rad_setting) /* RFC 2866 5.1. Acct-Status-Type */ ATTR_INT32(RADIUS_TYPE_ACCT_STATUS_TYPE, RADIUS_ACCT_STATUS_TYPE_ACCT_ON); /* RFC 2865 5.32. NAS-Identifier */ - ATTR_STR(RADIUS_TYPE_NAS_IDENTIFIER, "npppd"); + ATTR_STR(RADIUS_TYPE_NAS_IDENTIFIER, pppd->conf.nas_id); /* Send the request */ radius_request(radctx, radpkt); @@ -561,3 +565,305 @@ ppp_set_radius_attrs_for_authreq(npppd_ppp *_this, fail: return 1; } + +/*********************************************************************** + * Dynamic Authorization Extensions for RADIUS + ***********************************************************************/ +static int npppd_radius_dae_listen_start(struct npppd_radius_dae_listen *); +static void npppd_radius_dae_on_event(int, short, void *); +static void npppd_radius_dae_listen_stop(struct npppd_radius_dae_listen *); + +void +npppd_radius_dae_init(npppd *_this) +{ + struct npppd_radius_dae_listens listens; + struct npppd_radius_dae_listen *listen, *listent; + struct radlistenconf *listenconf; + + TAILQ_INIT(&listens); + + TAILQ_FOREACH(listenconf, &_this->conf.raddaelistenconfs, entry) { + TAILQ_FOREACH_SAFE(listen, &_this->raddae_listens, entry, + listent) { + if ((listen->addr.sin4.sin_family == AF_INET && + listenconf->addr.sin4.sin_family == AF_INET && + memcmp(&listen->addr.sin4, &listenconf->addr.sin4, + sizeof(struct sockaddr_in)) == 0) || + (listen->addr.sin6.sin6_family == AF_INET6 && + listenconf->addr.sin6.sin6_family == AF_INET6 && + memcmp(&listen->addr.sin6, &listenconf->addr.sin6, + sizeof(struct sockaddr_in6)) == 0)) + break; + } + if (listen != NULL) + /* keep using this */ + TAILQ_REMOVE(&_this->raddae_listens, listen, entry); + else { + if ((listen = calloc(1, sizeof(*listen))) == NULL) { + log_printf(LOG_ERR, "%s: calloc failed: %m", + __func__); + goto fail; + } + listen->pppd = _this; + listen->sock = -1; + if (listenconf->addr.sin4.sin_family == AF_INET) + listen->addr.sin4 = listenconf->addr.sin4; + else + listen->addr.sin6 = listenconf->addr.sin6; + } + TAILQ_INSERT_TAIL(&listens, listen, entry); + } + + /* listen on the new addresses */ + TAILQ_FOREACH(listen, &listens, entry) { + if (listen->sock == -1) + npppd_radius_dae_listen_start(listen); + } + + /* stop listening on the old addresses */ + TAILQ_FOREACH_SAFE(listen, &_this->raddae_listens, entry, listent) { + TAILQ_REMOVE(&_this->raddae_listens, listen, entry); + npppd_radius_dae_listen_stop(listen); + free(listen); + } + fail: + TAILQ_CONCAT(&_this->raddae_listens, &listens, entry); + + return; +} + +void +npppd_radius_dae_fini(npppd *_this) +{ + struct npppd_radius_dae_listen *listen, *listent; + + TAILQ_FOREACH_SAFE(listen, &_this->raddae_listens, entry, listent) { + TAILQ_REMOVE(&_this->raddae_listens, listen, entry); + npppd_radius_dae_listen_stop(listen); + free(listen); + } +} + +int +npppd_radius_dae_listen_start(struct npppd_radius_dae_listen *listen) +{ + char buf[80]; + int sock = -1, on = 1; + + if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { + log_printf(LOG_ERR, "%s: socket(): %m", __func__); + goto on_error; + } + on = 1; + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { + log_printf(LOG_WARNING, "%s: setsockopt(,,SO_REUSEADDR): %m", + __func__); + goto on_error; + } + if (bind(sock, (struct sockaddr *)&listen->addr, + listen->addr.sin4.sin_len) == -1) { + log_printf(LOG_ERR, "%s: bind(): %m", __func__); + goto on_error; + } + + listen->sock = sock; + event_set(&listen->evsock, listen->sock, EV_READ | EV_PERSIST, + npppd_radius_dae_on_event, listen); + event_add(&listen->evsock, NULL); + log_printf(LOG_INFO, "radius Listening %s/udp (DAE)", + addrport_tostring((struct sockaddr *)&listen->addr, + listen->addr.sin4.sin_len, buf, sizeof(buf))); + + return (0); + on_error: + if (sock >= 0) + close(sock); + + return (-1); +} + +void +npppd_radius_dae_on_event(int fd, short ev, void *ctx) +{ + char buf[80], attr[256], username[256]; + char *endp; + const char *reason, *nakcause = NULL; + struct npppd_radius_dae_listen *listen = ctx; + struct radclientconf *client; + npppd *_this = listen->pppd; + RADIUS_PACKET *req = NULL, *res = NULL; + struct sockaddr_storage ss; + socklen_t sslen; + unsigned long long ppp_id; + int code, n = 0; + uint32_t cause = 0; + struct in_addr ina; + slist *users; + npppd_ppp *ppp; + + reason = "disconnect requested"; + sslen = sizeof(ss); + req = radius_recvfrom(listen->sock, 0, (struct sockaddr *)&ss, &sslen); + if (req == NULL) { + log_printf(LOG_WARNING, "%s: receiving a RADIUS message " + "failed: %m", __func__); + return; + } + TAILQ_FOREACH(client, &_this->conf.raddaeclientconfs, entry) { + if (ss.ss_family == AF_INET && + ((struct sockaddr_in *)&ss)->sin_addr.s_addr == + client->addr.sin4.sin_addr.s_addr) + break; + else if (ss.ss_family == AF_INET6 && + IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)&ss)->sin6_addr, + &client->addr.sin6.sin6_addr)) + break; + } + + if (client == NULL) { + log_printf(LOG_WARNING, "radius received a RADIUS message from " + "%s: unknown client", addrport_tostring( + (struct sockaddr *)&ss, ss.ss_len, buf, sizeof(buf))); + goto out; + } + + if (radius_check_accounting_request_authenticator(req, + client->secret) != 0) { + log_printf(LOG_WARNING, "radius received an invalid RADIUS " + "message from %s: bad response authenticator", + addrport_tostring( + (struct sockaddr *)&ss, ss.ss_len, buf, sizeof(buf))); + goto out; + } + if ((code = radius_get_code(req)) != RADIUS_CODE_DISCONNECT_REQUEST) { + /* Code other than Disconnect-Request is not supported */ + if (code == RADIUS_CODE_COA_REQUEST) { + log_printf(LOG_INFO, "received CoA-Request from %s", + addrport_tostring( + (struct sockaddr *)&ss, ss.ss_len, buf, + sizeof(buf))); + code = RADIUS_CODE_COA_NAK; + cause = RADIUS_ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED; + goto send; + } + log_printf(LOG_WARNING, "radius received an invalid RADIUS " + "message from %s: unknown code %d", + addrport_tostring((struct sockaddr *)&ss, ss.ss_len, buf, + sizeof(buf)), code); + goto out; + } + + log_printf(LOG_INFO, "radius received Disconnect-Request from %s", + addrport_tostring((struct sockaddr *)&ss, ss.ss_len, buf, + sizeof(buf))); + + if (radius_get_string_attr(req, RADIUS_TYPE_NAS_IDENTIFIER, attr, + sizeof(attr)) == 0 && strcmp(attr, _this->conf.nas_id) != 0) { + cause = RADIUS_ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH; + nakcause = "NAS Identification is mimatch"; + goto search_done; + } + + /* prepare User-Name attribute */ + memset(&username, 0, sizeof(username)); + radius_get_string_attr(req, RADIUS_TYPE_USER_NAME, username, + sizeof(username)); + + cause = RADIUS_ERROR_CAUSE_SESSION_NOT_FOUND; + /* Our Session-Id is represented in "%08X%08x" (boot_id, ppp_id) */ + snprintf(buf, sizeof(buf), "%08X", _this->boot_id); + if (radius_get_string_attr(req, RADIUS_TYPE_ACCT_SESSION_ID, attr, + sizeof(attr)) == 0) { + ppp = NULL; + /* the client is to disconnect a session */ + if (strlen(attr) != 16 || strncmp(buf, attr, 8) != 0) { + cause = RADIUS_ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE; + nakcause = "Session-Id is wrong"; + goto search_done; + } + ppp_id = strtoull(attr + 8, &endp, 16); + if (*endp != '\0' || errno == ERANGE || ppp_id == ULLONG_MAX) { + cause = RADIUS_ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE; + nakcause = "Session-Id is invalid"; + goto search_done; + } + if ((ppp = npppd_get_ppp_by_id(_this, ppp_id)) == NULL) + goto search_done; + if (username[0] != '\0' && + strcmp(username, ppp->username) != 0) { + /* specified User-Name attribute is mismatched */ + cause = RADIUS_ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE; + nakcause = "User-Name is mismatched"; + goto search_done; + } + ppp_stop(ppp, reason); + n++; + } else if (username[0] != '\0') { + users = npppd_get_ppp_by_user(_this, username); + if (users == NULL) + goto search_done; + memset(&ina, 0, sizeof(ina)); + radius_get_uint32_attr(req, RADIUS_TYPE_FRAMED_IP_ADDRESS, + &ina.s_addr); + slist_itr_first(users); + while ((ppp = slist_itr_next(users)) != NULL) { + if (ntohl(ina.s_addr) != 0 && + ina.s_addr != ppp->ppp_framed_ip_address.s_addr) + continue; + ppp_stop(ppp, reason); + n++; + } + } else if (radius_get_uint32_attr(req, RADIUS_TYPE_FRAMED_IP_ADDRESS, + &ina.s_addr) == 0) { + ppp = npppd_get_ppp_by_ip(_this, ina); + if (ppp != NULL) { + ppp_stop(ppp, reason); + n++; + } + } + search_done: + if (n > 0) + code = RADIUS_CODE_DISCONNECT_ACK; + else { + if (nakcause == NULL) + nakcause = "session not found"; + code = RADIUS_CODE_DISCONNECT_NAK; + } + send: + res = radius_new_response_packet(code, req); + if (res == NULL) { + log_printf(LOG_WARNING, "%s: radius_new_response_packet: %m", + __func__); + goto out; + } + if (cause != 0) + radius_put_uint32_attr(res, RADIUS_TYPE_ERROR_CAUSE, cause); + radius_set_response_authenticator(res, client->secret); + if (radius_sendto(listen->sock, res, 0, (struct sockaddr *)&ss, sslen) + == -1) + log_printf(LOG_WARNING, "%s: sendto(): %m", __func__); + log_printf(LOG_INFO, "radius send %s to %s%s%s", + (code == RADIUS_CODE_DISCONNECT_ACK)? "Disconnect-ACK" : + (code == RADIUS_CODE_DISCONNECT_NAK)? "Disconnect-NAK" : "CoA-NAK", + addrport_tostring((struct sockaddr *)&ss, ss.ss_len, buf, + sizeof(buf)), (nakcause)? ": " : "", (nakcause)? nakcause : ""); + out: + radius_delete_packet(req); + if (res != NULL) + radius_delete_packet(res); +} + +void +npppd_radius_dae_listen_stop(struct npppd_radius_dae_listen *listen) +{ + char buf[80]; + + if (listen->sock >= 0) { + log_printf(LOG_INFO, "radius Shutdown %s/udp (DAE)", + addrport_tostring((struct sockaddr *)&listen->addr, + listen->addr.sin4.sin_len, buf, sizeof(buf))); + event_del(&listen->evsock); + close(listen->sock); + listen->sock = -1; + } +} diff --git a/usr.sbin/npppd/npppd/npppd_radius.h b/usr.sbin/npppd/npppd/npppd_radius.h index a1334545e..a7c309bd4 100644 --- a/usr.sbin/npppd/npppd/npppd_radius.h +++ b/usr.sbin/npppd/npppd/npppd_radius.h @@ -1,15 +1,35 @@ #ifndef NPPPD_RADIUS_H #define NPPPD_RADIUS_H 1 +#include +#include +#include + +struct npppd_radius_dae_listen { + int sock; + struct event evsock; + union { + struct sockaddr_in sin4; + struct sockaddr_in6 sin6; + } addr; + npppd *pppd; + TAILQ_ENTRY(npppd_radius_dae_listen) entry; +}; + +TAILQ_HEAD(npppd_radius_dae_listens, npppd_radius_dae_listen); + #ifdef __cplusplus extern "C" { #endif -void ppp_proccess_radius_framed_ip (npppd_ppp *, RADIUS_PACKET *); -int ppp_set_radius_attrs_for_authreq (npppd_ppp *, radius_req_setting *, RADIUS_PACKET *); -void npppd_ppp_radius_acct_start (npppd *, npppd_ppp *); -void npppd_ppp_radius_acct_stop (npppd *, npppd_ppp *); -void radius_acct_on(npppd *, radius_req_setting *); +void ppp_proccess_radius_framed_ip(npppd_ppp *, RADIUS_PACKET *); +int ppp_set_radius_attrs_for_authreq(npppd_ppp *, radius_req_setting *, + RADIUS_PACKET *); +void npppd_ppp_radius_acct_start(npppd *, npppd_ppp *); +void npppd_ppp_radius_acct_stop(npppd *, npppd_ppp *); +void radius_acct_on(npppd *, radius_req_setting *); +void npppd_radius_dae_init(npppd *); +void npppd_radius_dae_fini(npppd *); #ifdef __cplusplus } diff --git a/usr.sbin/npppd/npppd/parse.y b/usr.sbin/npppd/npppd/parse.y index a589c5a70..2017fe9a7 100644 --- a/usr.sbin/npppd/npppd/parse.y +++ b/usr.sbin/npppd/npppd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.28 2024/07/01 07:09:07 yasuoka Exp $ */ +/* $OpenBSD: parse.y,v 1.29 2024/07/11 14:05:59 yasuoka Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -134,6 +135,7 @@ typedef struct { %token INTERFACE ADDRESS IPCP %token BIND FROM AUTHENTICATED BY TO %token ERROR +%token DAE CLIENT NAS_ID %token STRING %token NUMBER %type yesno @@ -164,6 +166,7 @@ grammar : /* empty */ | grammar ipcp '\n' | grammar interface '\n' | grammar bind '\n' + | grammar radius '\n' | grammar error '\n' { file->errors++; } ; @@ -513,6 +516,80 @@ tunnopt : LISTEN ON addressport { curr_tunnconf->debug_dump_pktout = $2; } ; +radius : RADIUS NAS_ID STRING { + if (strlcpy(conf->nas_id, $3, sizeof(conf->nas_id)) + >= sizeof(conf->nas_id)) { + yyerror("`radius nas-id' is too long. use " + "less than %u chars.", + (unsigned)sizeof(conf->nas_id) - 1); + free($3); + YYERROR; + } + free($3); + } + | RADIUS DAE CLIENT address SECRET STRING { + struct radclientconf *client; + int secretsiz; + + secretsiz = strlen($6) + 1; + if ((client = calloc(1, offsetof(struct radclientconf, + secret[secretsiz]))) == NULL) { + yyerror("%s", strerror(errno)); + free($6); + YYERROR; + } + strlcpy(client->secret, $6, secretsiz); + + switch ($4.ss_family) { + case AF_INET: + memcpy(&client->addr, &$4, + sizeof(struct sockaddr_in)); + break; + case AF_INET6: + memcpy(&client->addr, &$4, + sizeof(struct sockaddr_in6)); + break; + default: + yyerror("address family %d not supported", + $4.ss_family); + free($6); + YYERROR; + break; + } + TAILQ_INSERT_TAIL(&conf->raddaeclientconfs, client, + entry); + free($6); + } + | RADIUS DAE LISTEN ON addressport { + struct radlistenconf *listen; + + if (ntohs(((struct sockaddr_in *)&$5)->sin_port) == 0) + ((struct sockaddr_in *)&$5)->sin_port = htons( + RADIUS_DAE_DEFAULT_PORT); + + if ((listen = calloc(1, sizeof(*listen))) == NULL) { + yyerror("%s", strerror(errno)); + YYERROR; + } + switch ($5.ss_family) { + case AF_INET: + memcpy(&listen->addr, &$5, + sizeof(struct sockaddr_in)); + break; + case AF_INET6: + memcpy(&listen->addr, &$5, + sizeof(struct sockaddr_in6)); + break; + default: + yyerror("address family %d not supported", + $5.ss_family); + YYERROR; + break; + } + TAILQ_INSERT_TAIL(&conf->raddaelistenconfs, listen, + entry); + } + ; tunnelproto : L2TP { $$ = NPPPD_TUNNEL_L2TP; } | PPTP { $$ = NPPPD_TUNNEL_PPTP; } @@ -1011,6 +1088,8 @@ lookup(char *s) { "ccp-timeout", CCP_TIMEOUT}, { "chap", CHAP}, { "chap-name", CHAP_NAME}, + { "client", CLIENT}, + { "dae", DAE}, { "debug-dump-pktin", DEBUG_DUMP_PKTIN}, { "debug-dump-pktout", DEBUG_DUMP_PKTOUT}, { "dns-servers", DNS_SERVERS}, @@ -1061,6 +1140,7 @@ lookup(char *s) { "mppe-key-state", MPPE_KEY_STATE}, { "mru", MRU}, { "mschapv2", MSCHAPV2}, + { "nas-id", NAS_ID}, { "nbns-servers", NBNS_SERVERS}, { "no", NO}, { "on", ON}, @@ -1429,6 +1509,9 @@ npppd_conf_init(struct npppd_conf *xconf) TAILQ_INIT(&xconf->l2tp_confs); TAILQ_INIT(&xconf->pptp_confs); TAILQ_INIT(&xconf->pppoe_confs); + TAILQ_INIT(&xconf->raddaeclientconfs); + TAILQ_INIT(&xconf->raddaelistenconfs); + strlcpy(xconf->nas_id, "npppd", sizeof(xconf->nas_id)); } void @@ -1439,6 +1522,8 @@ npppd_conf_fini(struct npppd_conf *xconf) struct ipcpconf *ipcp, *ipcp0; struct iface *iface, *iface0; struct confbind *confbind, *confbind0; + struct radclientconf *radc, *radct; + struct radlistenconf *radl, *radlt; TAILQ_FOREACH_SAFE(tunn, &xconf->tunnconfs, entry, tunn0) { tunnconf_fini(tunn); @@ -1455,6 +1540,10 @@ npppd_conf_fini(struct npppd_conf *xconf) TAILQ_FOREACH_SAFE(confbind, &xconf->confbinds, entry, confbind0) { free(confbind); } + TAILQ_FOREACH_SAFE(radc, &xconf->raddaeclientconfs, entry, radct) + free(radc); + TAILQ_FOREACH_SAFE(radl, &xconf->raddaelistenconfs, entry, radlt) + free(radl); TAILQ_INIT(&xconf->l2tp_confs); TAILQ_INIT(&xconf->pptp_confs); TAILQ_INIT(&xconf->pppoe_confs); diff --git a/usr.sbin/pstat/pstat.c b/usr.sbin/pstat/pstat.c index f62c96c8a..96b38ef8a 100644 --- a/usr.sbin/pstat/pstat.c +++ b/usr.sbin/pstat/pstat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pstat.c,v 1.129 2022/02/22 17:35:01 deraadt Exp $ */ +/* $OpenBSD: pstat.c,v 1.130 2024/07/10 13:29:23 krw Exp $ */ /* $NetBSD: pstat.c,v 1.27 1996/10/23 22:50:06 cgd Exp $ */ /*- @@ -739,6 +739,11 @@ mount_print(struct mount *mp) flags &= ~MNT_NODEV; comma = ","; } + if (flags & MNT_NOPERM) { + (void)printf("%snoperm", comma); + flags &= ~MNT_NOPERM; + comma = ","; + } if (flags & MNT_ASYNC) { (void)printf("%sasync", comma); flags &= ~MNT_ASYNC; @@ -810,6 +815,16 @@ mount_print(struct mount *mp) flags &= ~MNT_FORCE; comma = ","; } + if (flags & MNT_STALLED) { + (void)printf("%sstalled", comma); + flags &= ~MNT_STALLED; + comma = ","; + } + if (flags & MNT_SWAPPABLE) { + (void)printf("%sswappable", comma); + flags &= ~MNT_SWAPPABLE; + comma = ","; + } if (flags & MNT_WANTRDWR) { (void)printf("%swantrdwr", comma); flags &= ~MNT_WANTRDWR; @@ -820,6 +835,11 @@ mount_print(struct mount *mp) flags &= ~MNT_SOFTDEP; comma = ","; } + if (flags & MNT_DOOMED) { + (void)printf("%sdoomed", comma); + flags &= ~MNT_DOOMED; + comma = ","; + } if (flags) (void)printf("%sunknown_flags:%x", comma, flags); (void)printf(")"); diff --git a/usr.sbin/radiusctl/radiusctl.8 b/usr.sbin/radiusctl/radiusctl.8 index c9970aa6d..0074700e7 100644 --- a/usr.sbin/radiusctl/radiusctl.8 +++ b/usr.sbin/radiusctl/radiusctl.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: radiusctl.8,v 1.6 2024/07/09 17:26:14 yasuoka Exp $ +.\" $OpenBSD: radiusctl.8,v 1.7 2024/07/10 05:41:34 jmc Exp $ .\" .\" Copyright (c) YASUOKA Masahiko .\" @@ -15,7 +15,7 @@ .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .\" -.Dd $Mdocdate: July 9 2024 $ +.Dd $Mdocdate: July 10 2024 $ .Dt RADIUSCTL 8 .Os .Sh NAME @@ -111,7 +111,6 @@ shows the sessions in JSON format. .It Cm ipcp disconnect Ar sequence Request to disconnect the session specfied by the .Ar sequence . -.Xc .El .Sh EXAMPLES .Bd -literal -offset indent diff --git a/usr.sbin/radiusd/parse.y b/usr.sbin/radiusd/parse.y index 435482ca1..c43cd506d 100644 --- a/usr.sbin/radiusd/parse.y +++ b/usr.sbin/radiusd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.21 2024/07/09 17:26:14 yasuoka Exp $ */ +/* $OpenBSD: parse.y,v 1.22 2024/07/10 16:30:43 yasuoka Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer @@ -394,7 +394,6 @@ authenticate : AUTHENTICATE str_l BY STRING optdeco { yyerror("Out of memory: %s", strerror(errno)); goto authenticate_error; } - modref = create_module_ref($4); if ((auth->auth = create_module_ref($4)) == NULL) goto authenticate_error; auth->username = $2.v; @@ -495,7 +494,7 @@ account : ACCOUNT optquick str_l TO STRING optdeco { struct radiusd_module_ref *modref, *modreft; if ((acct = calloc(1, - sizeof(struct radiusd_authentication))) == NULL) { + sizeof(struct radiusd_accounting))) == NULL) { yyerror("Out of memory: %s", strerror(errno)); goto account_error; } diff --git a/usr.sbin/radiusd/radiusd.c b/usr.sbin/radiusd/radiusd.c index ec1cf51fa..6825f8978 100644 --- a/usr.sbin/radiusd/radiusd.c +++ b/usr.sbin/radiusd/radiusd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: radiusd.c,v 1.45 2024/07/09 17:26:14 yasuoka Exp $ */ +/* $OpenBSD: radiusd.c,v 1.46 2024/07/10 16:30:43 yasuoka Exp $ */ /* * Copyright (c) 2013, 2023 Internet Initiative Japan Inc. @@ -118,7 +118,7 @@ main(int argc, char *argv[]) { extern char *__progname; const char *conffile = CONFFILE; - int ch; + int ch, error; struct radiusd *radiusd; bool noaction = false; struct passwd *pw; @@ -213,10 +213,11 @@ main(int argc, char *argv[]) event_loop(0); + error = radiusd->error; radiusd_free(radiusd); event_base_free(NULL); - if (radiusd->error != 0) + if (error != 0) exit(EXIT_FAILURE); else exit(EXIT_SUCCESS); @@ -339,6 +340,7 @@ radiusd_free(struct radiusd *radiusd) struct radiusd_module *module, *modulet; struct radiusd_module_ref *modref, *modreft; struct radiusd_authentication *authen, *authent; + struct radiusd_accounting *acct, *acctt; TAILQ_FOREACH_SAFE(authen, &radiusd->authen, next, authent) { TAILQ_REMOVE(&radiusd->authen, authen, next); @@ -352,6 +354,19 @@ radiusd_free(struct radiusd *radiusd) free(authen->username); free(authen); } + TAILQ_FOREACH_SAFE(acct, &radiusd->account, next, acctt) { + TAILQ_REMOVE(&radiusd->account, acct, next); + free(acct->secret); + free(acct->acct); + TAILQ_FOREACH_SAFE(modref, &acct->deco, next, modreft) { + TAILQ_REMOVE(&acct->deco, modref, next); + free(modref); + } + for (i = 0; acct->username[i] != NULL; i++) + free(acct->username[i]); + free(acct->username); + free(acct); + } TAILQ_FOREACH_SAFE(module, &radiusd->module, next, modulet) { TAILQ_REMOVE(&radiusd->module, module, next); radiusd_module_unload(module); diff --git a/usr.sbin/radiusd/radiusd.conf.5 b/usr.sbin/radiusd/radiusd.conf.5 index b5068fee9..605132fbb 100644 --- a/usr.sbin/radiusd/radiusd.conf.5 +++ b/usr.sbin/radiusd/radiusd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: radiusd.conf.5,v 1.28 2024/07/09 17:26:14 yasuoka Exp $ +.\" $OpenBSD: radiusd.conf.5,v 1.29 2024/07/10 05:40:08 jmc Exp $ .\" .\" Copyright (c) 2014 Esdenera Networks GmbH .\" Copyright (c) 2014, 2023 Internet Initiative Japan Inc. @@ -15,7 +15,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: July 9 2024 $ +.Dd $Mdocdate: July 10 2024 $ .Dt RADIUSD.CONF 5 .Os .Sh NAME @@ -86,8 +86,8 @@ See .It Do ipcp Dc module The .Dq ipcp -module provides IP configuration and manages IP address pool. -Also provides session-timeout and disconnection feature. +module provides IP configuration and manages the IP address pool. +It also provides session-timeout and disconnection feature. See .Xr radiusd_ipcp 8 . .It Do radius Dc module diff --git a/usr.sbin/radiusd/radiusd_ipcp.8 b/usr.sbin/radiusd/radiusd_ipcp.8 index 80cb6ba88..28d9a8317 100644 --- a/usr.sbin/radiusd/radiusd_ipcp.8 +++ b/usr.sbin/radiusd/radiusd_ipcp.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: radiusd_ipcp.8,v 1.2 2024/07/09 17:34:10 yasuoka Exp $ +.\" $OpenBSD: radiusd_ipcp.8,v 1.4 2024/07/11 14:14:56 yasuoka Exp $ .\" .\" Copyright (c) 2024 Internet Initiative Japan Inc. .\" @@ -16,7 +16,7 @@ .\" .\" The following requests are required for all man pages. .\" -.Dd $Mdocdate: July 9 2024 $ +.Dd $Mdocdate: July 11 2024 $ .Dt RADIUSD_IPCP 8 .Os .Sh NAME @@ -30,21 +30,20 @@ The module is executed by .Xr radiusd 8 as a module to provide IP configuration through RADIUS Access-Accept messages -and manages IP address pool through RADIUS accounting messages. +and manages the IP address pool through RADIUS accounting messages. The internal sessions can be shown or monitored by .Xr radiusctl 8 . -Also .Nm -provides session timeouts and disconnects requested by +also provides session timeouts and disconnects requested by .Xr radiusctl 8 through the Dynamic Authorization Extension -.Po DAE, RFC 5176 Pc . +.Pq DAE, RFC 5176 . .Sh CONFIGURATIONS To use the .Nm module, -it should be configure as a decoration module of the authentication -and as an accouting module. +it should be configured as a decoration module of the authentication +and as an accounting module. .Bd -literal -offset indent authenticate * by (any auth module) decorate-by ipcp account * to ipcp @@ -52,27 +51,24 @@ account * to ipcp .Pp The .Nm -module supports the following configuration key and value: -.Pp +module supports the following configuration keys and values: .Bl -tag -width Ds .It Ic address pool Ar address-space ... Specify the IP address spaces that is pooled. The .Ar address-space -can be specified by a address range +can be specified by an address range .Pq e.g. 192.168.1.1-192.168.1.199 -or a address mask +or an address mask .Pq e.g. 192.168.1.0/24 . The pooled addresses are used for dynamic assignment. .It Ic address static Ar address-space ... Specify the IP address spaces that is pooled for static assignment. The .Ar address-space -is the same syntax of +is the same syntax as .Ic address pool , -see the description for -.Ic address pool -for detail. +above. .It Ic name-server Ar primary-address Op Ar secondary-address Specify the DNS servers' IP addresses. .It Ic netbios-server Ar primary-address Op Ar secondary-address @@ -109,12 +105,12 @@ the server is selected only for the session which NAS-Identifier is matched the specified value. The default port number is 3799. .It Ic max-sessions Ar number -Specify the maxinum number of sessions. +Specify the maximum number of sessions. .Sq 0 means no limit. The default value is 0. .It Ic user-max-sessions Ar number -Specify the maxinum number of sessions per a user. +Specify the maximum number of sessions per a user. .Sq 0 means no limit. The default value is 0. @@ -125,13 +121,19 @@ session after Access-Accept. preserves the assigned IP address for that period. The default value is 60 seconds. .El +.Sh FILES +.Bl -tag -width "/usr/libexec/radiusd/radiusd_ipcp" -compact +.It Pa /usr/libexec/radiusd/radiusd_ipcp +.Dq ipcp +module executable. +.El .Sh EXAMPLES -An example which +An example with .Nm -works with -.Xr npppd 8 . +working with +.Xr npppd 8 : .Pp -.Pa /etc/radiusd.conf: +.Pa /etc/radiusd.conf : .Bd -literal -offset indent listen on 127.0.0.1 listen on 127.0.0.1 accounting @@ -150,14 +152,15 @@ module ipcp { set name-server 192.168.0.4 set max-sessions 128 set user-max-sessions 2 - #set dae server 127.0.0.1 "SECRET3" + set dae server 127.0.0.1 "SECRET3" + set session-timeout radius } authenticate * by radius decorate-by ipcp account * to ipcp .Ed .Pp -.Pa /etc/npppd/npppd.conf: +.Pa /etc/npppd/npppd.conf : .Bd -literal -offset indent tunnel L2TP protocol l2tp { listen on 192.0.2.51 @@ -175,19 +178,16 @@ authentication RADIUS type radius { } } bind tunnel from L2TP authenticated by RADIUS to pppac0 + +radius dae listen on 127.0.0.1 +radius dae client 127.0.0.1 secret "SECRET3" .Ed -.Sh FILES -.Bl -tag -width "/usr/libexec/radiusd/radiusd_ipcp" -compact -.It Pa /usr/libexec/radiusd/radiusd_ipcp -.Dq ipcp -module executable. -.El .Sh SEE ALSO -.Xr radiusctl 8 , .Xr authenticate 3 , -.Xr radiusd 8 , .Xr radiusd.conf 5 , -.Xr npppd 8 +.Xr npppd 8 , +.Xr radiusctl 8 , +.Xr radiusd 8 .Sh HISTORY The .Nm diff --git a/usr.sbin/radiusd/radiusd_ipcp.c b/usr.sbin/radiusd/radiusd_ipcp.c index bc73ee652..581214590 100644 --- a/usr.sbin/radiusd/radiusd_ipcp.c +++ b/usr.sbin/radiusd/radiusd_ipcp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: radiusd_ipcp.c,v 1.1 2024/07/09 17:26:14 yasuoka Exp $ */ +/* $OpenBSD: radiusd_ipcp.c,v 1.3 2024/07/11 13:29:08 yasuoka Exp $ */ /* * Copyright (c) 2024 Internet Initiative Japan Inc. @@ -190,6 +190,7 @@ static void ipcp_schedule_timer(struct module_ipcp *); static void ipcp_dae_send_disconnect_request(struct assigned_ipv4 *); static void ipcp_dae_request_on_timeout(int, short, void *); static void ipcp_dae_on_event(int, short, void *); +static void ipcp_dae_reset_request(struct assigned_ipv4 *); static struct ipcp_address *parse_address_range(const char *); static const char @@ -625,7 +626,9 @@ ipcp_dispatch_control(void *ctx, struct imsg *imsg) else { log_info("Disconnect id=%u requested", assign->seq); - ipcp_dae_send_disconnect_request(assign); + if (assign->dae_ntry == 0) + ipcp_dae_send_disconnect_request( + assign); } } break; @@ -1057,7 +1060,7 @@ ipcp_accounting_request(void *ctx, u_int q_id, const u_char *pkt, assign->session_timeout; } assign->nas_ipv4 = nas_ipv4; - assign->nas_ipv4 = nas_ipv4; + assign->nas_ipv6 = nas_ipv6; strlcpy(assign->nas_id, nas_id, sizeof(assign->nas_id)); if (radius_get_string_attr(radpkt, RADIUS_TYPE_ACCT_SESSION_ID, @@ -1222,18 +1225,7 @@ ipcp_ipv4_release(struct module_ipcp *self, struct assigned_ipv4 *assign) TAILQ_REMOVE(&assign->user->ipv4s, assign, next); RB_REMOVE(assigned_ipv4_tree, &self->ipv4s, assign); self->nsessions--; - if (assign->dae != NULL) { - if (assign->dae_ntry > 0) { - TAILQ_REMOVE(&assign->dae->reqs, assign, - dae_next); - if (evtimer_pending(&assign->dae_evtimer, NULL)) - evtimer_del(&assign->dae_evtimer); - } - } - if (assign->dae_reqpkt != NULL) - radius_delete_packet(assign->dae_reqpkt); - if (evtimer_pending(&assign->dae_evtimer, NULL)) - evtimer_del(&assign->dae_evtimer); + ipcp_dae_reset_request(assign); free(assign); } } @@ -1505,37 +1497,50 @@ ipcp_dae_send_disconnect_request(struct assigned_ipv4 *assign) if (assign->dae == NULL) return; /* DAE is not configured */ - if (assign->dae_ntry == 0) - - if (assign->dae_reqpkt != NULL) { - radius_delete_packet(assign->dae_reqpkt); - assign->dae_reqpkt = NULL; + if (assign->dae_reqpkt == NULL) { + if ((reqpkt = radius_new_request_packet( + RADIUS_CODE_DISCONNECT_REQUEST)) == NULL) { + log_warn("%s: radius_new_request_packet(): %m", + __func__); + return; + } + radius_put_string_attr(reqpkt, RADIUS_TYPE_ACCT_SESSION_ID, + assign->session_id); + /* + * RFC 5176 Section 3, "either the User-Name or + * Chargeable-User-Identity attribute SHOULD be present in + * Disconnect-Request and CoA-Request packets." + */ + radius_put_string_attr(reqpkt, RADIUS_TYPE_USER_NAME, + assign->user->name); + if (assign->nas_id[0] != '\0') + radius_put_string_attr(reqpkt, + RADIUS_TYPE_NAS_IDENTIFIER, assign->nas_id); + if (ntohl(assign->nas_ipv4.s_addr) != 0) + radius_put_ipv4_attr(reqpkt, + RADIUS_TYPE_NAS_IP_ADDRESS, assign->nas_ipv4); + if (!IN6_IS_ADDR_UNSPECIFIED(&assign->nas_ipv6)) + radius_put_ipv6_attr(reqpkt, + RADIUS_TYPE_NAS_IPV6_ADDRESS, &assign->nas_ipv6); + radius_set_accounting_request_authenticator(reqpkt, + assign->dae->secret); + assign->dae_reqpkt = reqpkt; } - reqpkt = radius_new_request_packet(RADIUS_CODE_DISCONNECT_REQUEST); - - radius_put_string_attr(reqpkt, RADIUS_TYPE_ACCT_SESSION_ID, - assign->session_id); - - radius_set_accounting_request_authenticator(reqpkt, - assign->dae->secret); - - if (radius_send(assign->dae->sock, reqpkt, 0) < 0) - log_warn("%s: sendto: %m", __func__); - - if (assign->dae_ntry == 0) + if (assign->dae_ntry == 0) { log_info("Sending Disconnect-Request seq=%u to %s", assign->seq, print_addr((struct sockaddr *) &assign->dae->nas_addr, buf, sizeof(buf))); + TAILQ_INSERT_TAIL(&assign->dae->reqs, assign, dae_next); + } - assign->dae_reqpkt = reqpkt; - tv.tv_sec = dae_request_timeouts[assign->dae_ntry]; + if (radius_send(assign->dae->sock, assign->dae_reqpkt, 0) < 0) + log_warn("%s: sendto: %m", __func__); + + tv.tv_sec = dae_request_timeouts[assign->dae_ntry++]; tv.tv_usec = 0; evtimer_set(&assign->dae_evtimer, ipcp_dae_request_on_timeout, assign); evtimer_add(&assign->dae_evtimer, &tv); - - if (assign->dae_ntry++ == 0) - TAILQ_INSERT_TAIL(&assign->dae->reqs, assign, dae_next); } void @@ -1544,11 +1549,12 @@ ipcp_dae_request_on_timeout(int fd, short ev, void *ctx) struct assigned_ipv4 *assign = ctx; char buf[80]; - if (assign->dae_ntry >= (int)nitems(dae_request_timeouts)) + if (assign->dae_ntry >= (int)nitems(dae_request_timeouts)) { log_warnx("No answer for Disconnect-Request seq=%u from %s", assign->seq, print_addr((struct sockaddr *) &assign->dae->nas_addr, buf, sizeof(buf))); - else + ipcp_dae_reset_request(assign); + } else ipcp_dae_send_disconnect_request(assign); } @@ -1561,7 +1567,7 @@ ipcp_dae_on_event(int fd, short ev, void *ctx) uint32_t u32; struct assigned_ipv4 *assign; char buf[80], causestr[80]; - const char *cause; + const char *cause = ""; if ((ev & EV_READ) == 0) return; @@ -1581,7 +1587,7 @@ ipcp_dae_on_event(int fd, short ev, void *ctx) log_warnx("Received RADIUS packet from %s has unknown id=%d", print_addr((struct sockaddr *)&dae->nas_addr, buf, sizeof(buf)), radius_get_id(radres)); - return; + goto out; } radius_set_request_packet(radres, assign->dae_reqpkt); @@ -1590,7 +1596,7 @@ ipcp_dae_on_event(int fd, short ev, void *ctx) "authenticator", assign->seq, print_addr( (struct sockaddr *)&dae->nas_addr, buf, sizeof(buf))); - return; + goto out; } causestr[0] = '\0'; if (radius_get_uint32_attr(radres, RADIUS_TYPE_ERROR_CAUSE, &u32) == 0){ @@ -1600,6 +1606,7 @@ ipcp_dae_on_event(int fd, short ev, void *ctx) u32, cause); else snprintf(causestr, sizeof(causestr), " cause=%u", u32); + cause = causestr; } code = radius_get_code(radres); @@ -1608,13 +1615,11 @@ ipcp_dae_on_event(int fd, short ev, void *ctx) log_info("Received Disconnect-ACK for seq=%u from %s%s", assign->seq, print_addr((struct sockaddr *) &dae->nas_addr, buf, sizeof(buf)), cause); - evtimer_del(&assign->dae_evtimer); break; case RADIUS_CODE_DISCONNECT_NAK: log_warnx("Received Disconnect-NAK for seq=%u from %s%s", assign->seq, print_addr((struct sockaddr *) &dae->nas_addr, buf, sizeof(buf)), cause); - evtimer_del(&assign->dae_evtimer); break; default: log_warn("Received unknown code=%d for id=%u from %s", @@ -1622,6 +1627,25 @@ ipcp_dae_on_event(int fd, short ev, void *ctx) &dae->nas_addr, buf, sizeof(buf))); break; } + ipcp_dae_reset_request(assign); + out: + if (radres != NULL) + radius_delete_packet(radres); +} + +void +ipcp_dae_reset_request(struct assigned_ipv4 *assign) +{ + if (assign->dae != NULL) { + if (assign->dae_ntry > 0) + TAILQ_REMOVE(&assign->dae->reqs, assign, dae_next); + } + if (assign->dae_reqpkt != NULL) + radius_delete_packet(assign->dae_reqpkt); + assign->dae_reqpkt = NULL; + if (evtimer_pending(&assign->dae_evtimer, NULL)) + evtimer_del(&assign->dae_evtimer); + assign->dae_ntry = 0; } /*********************************************************************** diff --git a/usr.sbin/vmctl/Makefile b/usr.sbin/vmctl/Makefile index 4dab88fba..05359639a 100644 --- a/usr.sbin/vmctl/Makefile +++ b/usr.sbin/vmctl/Makefile @@ -1,6 +1,6 @@ -# $OpenBSD: Makefile,v 1.6 2019/01/18 01:24:07 pd Exp $ +# $OpenBSD: Makefile,v 1.7 2024/07/10 09:27:33 dv Exp $ -.if ${MACHINE} == "amd64" +.if ${MACHINE} == "amd64" || ${MACHINE} == "arm64" .PATH: ${.CURDIR}/../vmd diff --git a/usr.sbin/vmd/Makefile b/usr.sbin/vmd/Makefile index 3fbb9d086..22c1e8878 100644 --- a/usr.sbin/vmd/Makefile +++ b/usr.sbin/vmd/Makefile @@ -1,13 +1,20 @@ -# $OpenBSD: Makefile,v 1.29 2023/04/27 22:47:27 dv Exp $ +# $OpenBSD: Makefile,v 1.30 2024/07/10 09:27:33 dv Exp $ -.if ${MACHINE} == "amd64" +.if ${MACHINE} == "amd64" || ${MACHINE} == "arm64" PROG= vmd -SRCS= vmd.c control.c log.c priv.c proc.c config.c vmm.c -SRCS+= vm.c loadfile_elf.c pci.c virtio.c i8259.c mc146818.c -SRCS+= ns8250.c i8253.c dhcp.c packet.c mmio.c -SRCS+= parse.y atomicio.c vioscsi.c vioraw.c vioqcow2.c fw_cfg.c -SRCS+= vm_agentx.c vioblk.c vionet.c +SRCS= vmd.c control.c log.c priv.c proc.c config.c vmm.c vm.c +SRCS+= pci.c virtio.c dhcp.c packet.c parse.y atomicio.c +SRCS+= vioscsi.c vioraw.c vioqcow2.c vm_agentx.c vioblk.c +SRCS+= vionet.c + +.if ${MACHINE} == "amd64" +SRCS+= i8253.c i8259.c fw_cfg.c loadfile_elf.c mc146818.c ns8250.c +SRCS+= x86_vm.c x86_mmio.c +.endif # amd64 +.if ${MACHINE} == "arm64" +SRCS+= arm64_vm.c +.endif # arm64 CFLAGS+= -Wall -I${.CURDIR} CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes @@ -24,7 +31,7 @@ YFLAGS= NOPROG= yes -.endif +.endif # amd64 or arm64 MAN= vmd.8 vm.conf.5 diff --git a/usr.sbin/vmd/arm64_vm.c b/usr.sbin/vmd/arm64_vm.c new file mode 100644 index 000000000..282dbcb49 --- /dev/null +++ b/usr.sbin/vmd/arm64_vm.c @@ -0,0 +1,162 @@ +/* $OpenBSD: arm64_vm.c,v 1.1 2024/07/10 10:41:19 dv Exp $ */ +/* + * Copyright (c) 2024 Dave Voutila + * + * 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 + +#include "vmd.h" + +void +create_memory_map(struct vm_create_params *vcp) +{ + fatalx("%s: unimplemented", __func__); + /* NOTREACHED */ +} + +int +load_firmware(struct vmd_vm *vm, struct vcpu_reg_state *vrs) +{ + fatalx("%s: unimplemented", __func__); + /* NOTREACHED */ + return (-1); +} + +void +init_emulated_hw(struct vmop_create_params *vcp, int child_cdrom, + int child_disks[][VM_MAX_BASE_PER_DISK], int *child_taps) +{ + fatalx("%s: unimplemented", __func__); + /* NOTREACHED */ +} + +void +restore_emulated_hw(struct vm_create_params *vcp, int fd, int *child_taps, + int child_disks[][VM_MAX_BASE_PER_DISK], int child_cdrom) +{ + fatalx("%s: unimplemented", __func__); + /* NOTREACHED */ +} + +void +pause_vm_md(struct vmd_vm *vm) +{ + fatalx("%s: unimplemented", __func__); + /* NOTREACHED */ +} + +void +unpause_vm_md(struct vmd_vm *vm) +{ + fatalx("%s: unimplemented", __func__); + /* NOTREACHED */ +} + +int +dump_devs(int fd) +{ + fatalx("%s: unimplemented", __func__); + /* NOTREACHED */ + return (-1); +} + +int +dump_send_header(int fd) +{ + fatalx("%s: unimplemented", __func__); + /* NOTREACHED */ + return (-1); +} + +void * +hvaddr_mem(paddr_t gpa, size_t len) +{ fatalx("%s: unimplemented", __func__); + /* NOTREACHED */ + return (NULL); +} + +int +write_mem(paddr_t dst, const void *buf, size_t len) +{ + fatalx("%s: unimplemented", __func__); + /* NOTREACHED */ + return (-1); +} + +int +read_mem(paddr_t src, void *buf, size_t len) +{ + fatalx("%s: unimplemented", __func__); + /* NOTREACHED */ + return (-1); +} + +int +intr_pending(struct vmd_vm *vm) +{ + fatalx("%s: unimplemented", __func__); + /* NOTREACHED */ + return (-1); +} + +void +intr_toggle_el(struct vmd_vm *vm, int irq, int val) +{ + fatalx("%s: unimplemented", __func__); + /* NOTREACHED */ +} + +int +intr_ack(struct vmd_vm *vm) +{ + fatalx("%s: unimplemented", __func__); + /* NOTREACHED */ + return (-1); +} + +void +vcpu_assert_irq(uint32_t vm_id, uint32_t vcpu_id, int irq) +{ + fatalx("%s: unimplemented", __func__); +} + +void +vcpu_deassert_irq(uint32_t vm_id, uint32_t vcpu_id, int irq) +{ + fatalx("%s: unimplemented", __func__); +} + +int +vmd_check_vmh(struct vm_dump_header *vmh) +{ + fatalx("%s: unimplemented", __func__); + /* NOTREACHED */ + return (-1); +} + +int +vcpu_exit(struct vm_run_params *vrp) +{ + fatalx("%s: unimplemented", __func__); + /* NOTREACHED */ + return (-1); +} + +uint8_t +vcpu_exit_pci(struct vm_run_params *vrp) +{ + fatalx("%s: unimplemented", __func__); + /* NOTREACHED */ + return (0xff); +} diff --git a/usr.sbin/vmd/i8253.c b/usr.sbin/vmd/i8253.c index ac9855e38..7cea3fa38 100644 --- a/usr.sbin/vmd/i8253.c +++ b/usr.sbin/vmd/i8253.c @@ -1,4 +1,4 @@ -/* $OpenBSD: i8253.c,v 1.40 2024/07/09 09:31:37 dv Exp $ */ +/* $OpenBSD: i8253.c,v 1.41 2024/07/10 09:27:33 dv Exp $ */ /* * Copyright (c) 2016 Mike Larkin * @@ -29,7 +29,6 @@ #include "i8253.h" #include "vmd.h" -#include "vmm.h" #include "atomicio.h" extern char *__progname; @@ -369,7 +368,7 @@ i8253_fire(int fd, short type, void *arg) struct timeval tv; struct i8253_channel *ctr = (struct i8253_channel *)arg; - vcpu_assert_pic_irq(ctr->vm_id, 0, 0); + vcpu_assert_irq(ctr->vm_id, 0, 0); if (ctr->mode != TIMER_INTTC) { timerclear(&tv); diff --git a/usr.sbin/vmd/mc146818.c b/usr.sbin/vmd/mc146818.c index 660c625eb..62fc6459a 100644 --- a/usr.sbin/vmd/mc146818.c +++ b/usr.sbin/vmd/mc146818.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mc146818.c,v 1.28 2024/07/09 09:31:37 dv Exp $ */ +/* $OpenBSD: mc146818.c,v 1.29 2024/07/10 09:27:33 dv Exp $ */ /* * Copyright (c) 2016 Mike Larkin * @@ -31,7 +31,6 @@ #include "mc146818.h" #include "virtio.h" #include "vmd.h" -#include "vmm.h" #define MC_RATE_MASK 0xf @@ -148,7 +147,7 @@ rtc_fireper(int fd, short type, void *arg) { rtc.regs[MC_REGC] |= MC_REGC_PF; - vcpu_assert_pic_irq((ptrdiff_t)arg, 0, 8); + vcpu_assert_irq((ptrdiff_t)arg, 0, 8); evtimer_add(&rtc.per, &rtc.per_tv); } diff --git a/usr.sbin/vmd/mmio.c b/usr.sbin/vmd/mmio.c index c5a189d5b..e69de29bb 100644 --- a/usr.sbin/vmd/mmio.c +++ b/usr.sbin/vmd/mmio.c @@ -1,1046 +0,0 @@ -/* $OpenBSD: mmio.c,v 1.3 2024/02/10 12:31:16 dv Exp $ */ - -/* - * Copyright (c) 2022 Dave Voutila - * - * 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 -#include - -#include -#include - -#include "vmd.h" -#include "mmio.h" - -#define MMIO_DEBUG 0 - -extern char* __progname; - -struct x86_decode_state { - uint8_t s_bytes[15]; - size_t s_len; - size_t s_idx; -}; - -enum decode_result { - DECODE_ERROR = 0, /* Something went wrong. */ - DECODE_DONE, /* Decode success and no more work needed. */ - DECODE_MORE, /* Decode success and more work required. */ -}; - -static const char *str_cpu_mode(int); -static const char *str_decode_res(enum decode_result); -static const char *str_opcode(struct x86_opcode *); -static const char *str_operand_enc(struct x86_opcode *); -static const char *str_reg(int); -static const char *str_sreg(int); -static int detect_cpu_mode(struct vcpu_reg_state *); - -static enum decode_result decode_prefix(struct x86_decode_state *, - struct x86_insn *); -static enum decode_result decode_opcode(struct x86_decode_state *, - struct x86_insn *); -static enum decode_result decode_modrm(struct x86_decode_state *, - struct x86_insn *); -static int get_modrm_reg(struct x86_insn *); -static int get_modrm_addr(struct x86_insn *, struct vcpu_reg_state *vrs); -static enum decode_result decode_disp(struct x86_decode_state *, - struct x86_insn *); -static enum decode_result decode_sib(struct x86_decode_state *, - struct x86_insn *); -static enum decode_result decode_imm(struct x86_decode_state *, - struct x86_insn *); - -static enum decode_result peek_byte(struct x86_decode_state *, uint8_t *); -static enum decode_result next_byte(struct x86_decode_state *, uint8_t *); -static enum decode_result next_value(struct x86_decode_state *, size_t, - uint64_t *); -static int is_valid_state(struct x86_decode_state *, const char *); - -static int emulate_mov(struct x86_insn *, struct vm_exit *); -static int emulate_movzx(struct x86_insn *, struct vm_exit *); - -/* Lookup table for 1-byte opcodes, in opcode alphabetical order. */ -const enum x86_opcode_type x86_1byte_opcode_tbl[255] = { - /* MOV */ - [0x88] = OP_MOV, - [0x89] = OP_MOV, - [0x8A] = OP_MOV, - [0x8B] = OP_MOV, - [0x8C] = OP_MOV, - [0xA0] = OP_MOV, - [0xA1] = OP_MOV, - [0xA2] = OP_MOV, - [0xA3] = OP_MOV, - - /* MOVS */ - [0xA4] = OP_UNSUPPORTED, - [0xA5] = OP_UNSUPPORTED, - - [ESCAPE] = OP_TWO_BYTE, -}; - -/* Lookup table for 1-byte operand encodings, in opcode alphabetical order. */ -const enum x86_operand_enc x86_1byte_operand_enc_tbl[255] = { - /* MOV */ - [0x88] = OP_ENC_MR, - [0x89] = OP_ENC_MR, - [0x8A] = OP_ENC_RM, - [0x8B] = OP_ENC_RM, - [0x8C] = OP_ENC_MR, - [0xA0] = OP_ENC_FD, - [0xA1] = OP_ENC_FD, - [0xA2] = OP_ENC_TD, - [0xA3] = OP_ENC_TD, - - /* MOVS */ - [0xA4] = OP_ENC_ZO, - [0xA5] = OP_ENC_ZO, -}; - -const enum x86_opcode_type x86_2byte_opcode_tbl[255] = { - /* MOVZX */ - [0xB6] = OP_MOVZX, - [0xB7] = OP_MOVZX, -}; - -const enum x86_operand_enc x86_2byte_operand_enc_table[255] = { - /* MOVZX */ - [0xB6] = OP_ENC_RM, - [0xB7] = OP_ENC_RM, -}; - -/* - * peek_byte - * - * Fetch the next byte fron the instruction bytes without advancing the - * position in the stream. - * - * Return values: - * DECODE_DONE: byte was found and is the last in the stream - * DECODE_MORE: byte was found and there are more remaining to be read - * DECODE_ERROR: state is invalid and not byte was found, *byte left unchanged - */ -static enum decode_result -peek_byte(struct x86_decode_state *state, uint8_t *byte) -{ - enum decode_result res; - - if (state == NULL) - return (DECODE_ERROR); - - if (state->s_idx == state->s_len) - return (DECODE_ERROR); - - if (state->s_idx + 1 == state->s_len) - res = DECODE_DONE; - else - res = DECODE_MORE; - - if (byte != NULL) - *byte = state->s_bytes[state->s_idx]; - return (res); -} - -/* - * next_byte - * - * Fetch the next byte fron the instruction bytes, advancing the position in the - * stream and mutating decode state. - * - * Return values: - * DECODE_DONE: byte was found and is the last in the stream - * DECODE_MORE: byte was found and there are more remaining to be read - * DECODE_ERROR: state is invalid and not byte was found, *byte left unchanged - */ -static enum decode_result -next_byte(struct x86_decode_state *state, uint8_t *byte) -{ - uint8_t next; - - /* Cheat and see if we're going to fail. */ - if (peek_byte(state, &next) == DECODE_ERROR) - return (DECODE_ERROR); - - if (byte != NULL) - *byte = next; - state->s_idx++; - - return (state->s_idx < state->s_len ? DECODE_MORE : DECODE_DONE); -} - -/* - * Fetch the next `n' bytes as a single uint64_t value. - */ -static enum decode_result -next_value(struct x86_decode_state *state, size_t n, uint64_t *value) -{ - uint8_t bytes[8]; - size_t i; - enum decode_result res; - - if (value == NULL) - return (DECODE_ERROR); - - if (n == 0 || n > sizeof(bytes)) - return (DECODE_ERROR); - - memset(bytes, 0, sizeof(bytes)); - for (i = 0; i < n; i++) - if ((res = next_byte(state, &bytes[i])) == DECODE_ERROR) - return (DECODE_ERROR); - - *value = *((uint64_t*)bytes); - - return (res); -} - -/* - * is_valid_state - * - * Validate the decode state looks viable. - * - * Returns: - * 1: if state is valid - * 0: if an invariant is detected - */ -static int -is_valid_state(struct x86_decode_state *state, const char *fn_name) -{ - const char *s = (fn_name != NULL) ? fn_name : __func__; - - if (state == NULL) { - log_warnx("%s: null state", s); - return (0); - } - if (state->s_len > sizeof(state->s_bytes)) { - log_warnx("%s: invalid length", s); - return (0); - } - if (state->s_idx + 1 > state->s_len) { - log_warnx("%s: invalid index", s); - return (0); - } - - return (1); -} - -#ifdef MMIO_DEBUG -static void -dump_regs(struct vcpu_reg_state *vrs) -{ - size_t i; - struct vcpu_segment_info *vsi; - - for (i = 0; i < VCPU_REGS_NGPRS; i++) - log_info("%s: %s 0x%llx", __progname, str_reg(i), - vrs->vrs_gprs[i]); - - for (i = 0; i < VCPU_REGS_NSREGS; i++) { - vsi = &vrs->vrs_sregs[i]; - log_info("%s: %s { sel: 0x%04x, lim: 0x%08x, ar: 0x%08x, " - "base: 0x%llx }", __progname, str_sreg(i), - vsi->vsi_sel, vsi->vsi_limit, vsi->vsi_ar, vsi->vsi_base); - } -} - -static void -dump_insn(struct x86_insn *insn) -{ - log_info("instruction { %s, enc=%s, len=%d, mod=0x%02x, (" - "reg=%s, addr=0x%lx) sib=0x%02x }", - str_opcode(&insn->insn_opcode), - str_operand_enc(&insn->insn_opcode), insn->insn_bytes_len, - insn->insn_modrm, str_reg(insn->insn_reg), - insn->insn_gva, insn->insn_sib); -} -#endif /* MMIO_DEBUG */ - -static const char * -str_cpu_mode(int mode) -{ - switch (mode) { - case VMM_CPU_MODE_REAL: return "REAL"; - case VMM_CPU_MODE_PROT: return "PROT"; - case VMM_CPU_MODE_PROT32: return "PROT32"; - case VMM_CPU_MODE_COMPAT: return "COMPAT"; - case VMM_CPU_MODE_LONG: return "LONG"; - default: return "UKNOWN"; - } -} - -__unused static const char * -str_decode_res(enum decode_result res) { - switch (res) { - case DECODE_DONE: return "DONE"; - case DECODE_MORE: return "MORE"; - case DECODE_ERROR: return "ERROR"; - default: return "UNKNOWN"; - } -} - -static const char * -str_opcode(struct x86_opcode *opcode) -{ - switch (opcode->op_type) { - case OP_IN: return "IN"; - case OP_INS: return "INS"; - case OP_MOV: return "MOV"; - case OP_MOVZX: return "MOVZX"; - case OP_OUT: return "OUT"; - case OP_OUTS: return "OUTS"; - case OP_UNSUPPORTED: return "UNSUPPORTED"; - default: return "UNKNOWN"; - } -} - -static const char * -str_operand_enc(struct x86_opcode *opcode) -{ - switch (opcode->op_encoding) { - case OP_ENC_I: return "I"; - case OP_ENC_MI: return "MI"; - case OP_ENC_MR: return "MR"; - case OP_ENC_RM: return "RM"; - case OP_ENC_FD: return "FD"; - case OP_ENC_TD: return "TD"; - case OP_ENC_OI: return "OI"; - case OP_ENC_ZO: return "ZO"; - default: return "UNKNOWN"; - } -} - -static const char * -str_reg(int reg) { - switch (reg) { - case VCPU_REGS_RAX: return "RAX"; - case VCPU_REGS_RCX: return "RCX"; - case VCPU_REGS_RDX: return "RDX"; - case VCPU_REGS_RBX: return "RBX"; - case VCPU_REGS_RSI: return "RSI"; - case VCPU_REGS_RDI: return "RDI"; - case VCPU_REGS_R8: return " R8"; - case VCPU_REGS_R9: return " R9"; - case VCPU_REGS_R10: return "R10"; - case VCPU_REGS_R11: return "R11"; - case VCPU_REGS_R12: return "R12"; - case VCPU_REGS_R13: return "R13"; - case VCPU_REGS_R14: return "R14"; - case VCPU_REGS_R15: return "R15"; - case VCPU_REGS_RSP: return "RSP"; - case VCPU_REGS_RBP: return "RBP"; - case VCPU_REGS_RIP: return "RIP"; - case VCPU_REGS_RFLAGS: return "RFLAGS"; - default: return "UNKNOWN"; - } -} - -static const char * -str_sreg(int sreg) { - switch (sreg) { - case VCPU_REGS_CS: return "CS"; - case VCPU_REGS_DS: return "DS"; - case VCPU_REGS_ES: return "ES"; - case VCPU_REGS_FS: return "FS"; - case VCPU_REGS_GS: return "GS"; - case VCPU_REGS_SS: return "GS"; - case VCPU_REGS_LDTR: return "LDTR"; - case VCPU_REGS_TR: return "TR"; - default: return "UKNOWN"; - } -} - -static int -detect_cpu_mode(struct vcpu_reg_state *vrs) -{ - uint64_t cr0, cr4, cs, efer, rflags; - - /* Is protected mode enabled? */ - cr0 = vrs->vrs_crs[VCPU_REGS_CR0]; - if (!(cr0 & CR0_PE)) - return (VMM_CPU_MODE_REAL); - - cr4 = vrs->vrs_crs[VCPU_REGS_CR4]; - cs = vrs->vrs_sregs[VCPU_REGS_CS].vsi_ar; - efer = vrs->vrs_msrs[VCPU_REGS_EFER]; - rflags = vrs->vrs_gprs[VCPU_REGS_RFLAGS]; - - /* Check for Long modes. */ - if ((efer & EFER_LME) && (cr4 & CR4_PAE) && (cr0 & CR0_PG)) { - if (cs & CS_L) { - /* Long Modes */ - if (!(cs & CS_D)) - return (VMM_CPU_MODE_LONG); - log_warnx("%s: invalid cpu mode", __progname); - return (VMM_CPU_MODE_UNKNOWN); - } else { - /* Compatibility Modes */ - if (cs & CS_D) /* XXX Add Compat32 mode */ - return (VMM_CPU_MODE_UNKNOWN); - return (VMM_CPU_MODE_COMPAT); - } - } - - /* Check for 32-bit Protected Mode. */ - if (cs & CS_D) - return (VMM_CPU_MODE_PROT32); - - /* Check for virtual 8086 mode. */ - if (rflags & EFLAGS_VM) { - /* XXX add Virtual8086 mode */ - log_warnx("%s: Virtual 8086 mode", __progname); - return (VMM_CPU_MODE_UNKNOWN); - } - - /* Can't determine mode. */ - log_warnx("%s: invalid cpu mode", __progname); - return (VMM_CPU_MODE_UNKNOWN); -} - -static enum decode_result -decode_prefix(struct x86_decode_state *state, struct x86_insn *insn) -{ - enum decode_result res = DECODE_ERROR; - struct x86_prefix *prefix; - uint8_t byte; - - if (!is_valid_state(state, __func__) || insn == NULL) - return (-1); - - prefix = &insn->insn_prefix; - memset(prefix, 0, sizeof(*prefix)); - - /* - * Decode prefixes. The last of its kind wins. The behavior is undefined - * in the Intel SDM (see Vol 2, 2.1.1 Instruction Prefixes.) - */ - while ((res = peek_byte(state, &byte)) != DECODE_ERROR) { - switch (byte) { - case LEG_1_LOCK: - case LEG_1_REPNE: - case LEG_1_REP: - prefix->pfx_group1 = byte; - break; - case LEG_2_CS: - case LEG_2_SS: - case LEG_2_DS: - case LEG_2_ES: - case LEG_2_FS: - case LEG_2_GS: - prefix->pfx_group2 = byte; - break; - case LEG_3_OPSZ: - prefix->pfx_group3 = byte; - break; - case LEG_4_ADDRSZ: - prefix->pfx_group4 = byte; - break; - case REX_BASE...REX_BASE + 0x0F: - if (insn->insn_cpu_mode == VMM_CPU_MODE_LONG) - prefix->pfx_rex = byte; - else /* INC encountered */ - return (DECODE_ERROR); - break; - case VEX_2_BYTE: - case VEX_3_BYTE: - log_warnx("%s: VEX not supported", __func__); - return (DECODE_ERROR); - default: - /* Something other than a valid prefix. */ - return (DECODE_MORE); - } - /* Advance our position. */ - next_byte(state, NULL); - } - - return (res); -} - -static enum decode_result -decode_modrm(struct x86_decode_state *state, struct x86_insn *insn) -{ - enum decode_result res; - uint8_t byte = 0; - - if (!is_valid_state(state, __func__) || insn == NULL) - return (DECODE_ERROR); - - insn->insn_modrm_valid = 0; - - /* Check the operand encoding to see if we fetch a byte or abort. */ - switch (insn->insn_opcode.op_encoding) { - case OP_ENC_MR: - case OP_ENC_RM: - case OP_ENC_MI: - res = next_byte(state, &byte); - if (res == DECODE_ERROR) { - log_warnx("%s: failed to get modrm byte", __func__); - break; - } - insn->insn_modrm = byte; - insn->insn_modrm_valid = 1; - break; - - case OP_ENC_I: - case OP_ENC_OI: - log_warnx("%s: instruction does not need memory assist", - __func__); - res = DECODE_ERROR; - break; - - default: - /* Peek to see if we're done decode. */ - res = peek_byte(state, NULL); - } - - return (res); -} - -static int -get_modrm_reg(struct x86_insn *insn) -{ - if (insn == NULL) - return (-1); - - if (insn->insn_modrm_valid) { - switch (MODRM_REGOP(insn->insn_modrm)) { - case 0: - insn->insn_reg = VCPU_REGS_RAX; - break; - case 1: - insn->insn_reg = VCPU_REGS_RCX; - break; - case 2: - insn->insn_reg = VCPU_REGS_RDX; - break; - case 3: - insn->insn_reg = VCPU_REGS_RBX; - break; - case 4: - insn->insn_reg = VCPU_REGS_RSP; - break; - case 5: - insn->insn_reg = VCPU_REGS_RBP; - break; - case 6: - insn->insn_reg = VCPU_REGS_RSI; - break; - case 7: - insn->insn_reg = VCPU_REGS_RDI; - break; - } - } - - /* REX R bit selects extended registers in LONG mode. */ - if (insn->insn_prefix.pfx_rex & REX_R) - insn->insn_reg += 8; - - return (0); -} - -static int -get_modrm_addr(struct x86_insn *insn, struct vcpu_reg_state *vrs) -{ - uint8_t mod, rm; - vaddr_t addr = 0x0UL; - - if (insn == NULL || vrs == NULL) - return (-1); - - if (insn->insn_modrm_valid) { - rm = MODRM_RM(insn->insn_modrm); - mod = MODRM_MOD(insn->insn_modrm); - - switch (rm) { - case 0b000: - addr = vrs->vrs_gprs[VCPU_REGS_RAX]; - break; - case 0b001: - addr = vrs->vrs_gprs[VCPU_REGS_RCX]; - break; - case 0b010: - addr = vrs->vrs_gprs[VCPU_REGS_RDX]; - break; - case 0b011: - addr = vrs->vrs_gprs[VCPU_REGS_RBX]; - break; - case 0b100: - if (mod == 0b11) - addr = vrs->vrs_gprs[VCPU_REGS_RSP]; - break; - case 0b101: - if (mod != 0b00) - addr = vrs->vrs_gprs[VCPU_REGS_RBP]; - break; - case 0b110: - addr = vrs->vrs_gprs[VCPU_REGS_RSI]; - break; - case 0b111: - addr = vrs->vrs_gprs[VCPU_REGS_RDI]; - break; - } - - insn->insn_gva = addr; - } - - return (0); -} - -static enum decode_result -decode_disp(struct x86_decode_state *state, struct x86_insn *insn) -{ - enum decode_result res = DECODE_ERROR; - uint64_t disp = 0; - - if (!is_valid_state(state, __func__) || insn == NULL) - return (DECODE_ERROR); - - if (!insn->insn_modrm_valid) - return (DECODE_ERROR); - - switch (MODRM_MOD(insn->insn_modrm)) { - case 0x00: - insn->insn_disp_type = DISP_0; - res = DECODE_MORE; - break; - case 0x01: - insn->insn_disp_type = DISP_1; - res = next_value(state, 1, &disp); - if (res == DECODE_ERROR) - return (res); - insn->insn_disp = disp; - break; - case 0x02: - if (insn->insn_prefix.pfx_group4 == LEG_4_ADDRSZ) { - insn->insn_disp_type = DISP_2; - res = next_value(state, 2, &disp); - } else { - insn->insn_disp_type = DISP_4; - res = next_value(state, 4, &disp); - } - if (res == DECODE_ERROR) - return (res); - insn->insn_disp = disp; - break; - default: - insn->insn_disp_type = DISP_NONE; - res = DECODE_MORE; - } - - return (res); -} - -static enum decode_result -decode_opcode(struct x86_decode_state *state, struct x86_insn *insn) -{ - enum decode_result res; - enum x86_opcode_type type; - enum x86_operand_enc enc; - struct x86_opcode *opcode = &insn->insn_opcode; - uint8_t byte, byte2; - - if (!is_valid_state(state, __func__) || insn == NULL) - return (-1); - - memset(opcode, 0, sizeof(*opcode)); - - res = next_byte(state, &byte); - if (res == DECODE_ERROR) - return (res); - - type = x86_1byte_opcode_tbl[byte]; - switch(type) { - case OP_UNKNOWN: - case OP_UNSUPPORTED: - log_warnx("%s: unsupported opcode", __func__); - return (DECODE_ERROR); - - case OP_TWO_BYTE: - res = next_byte(state, &byte2); - if (res == DECODE_ERROR) - return (res); - - type = x86_2byte_opcode_tbl[byte2]; - if (type == OP_UNKNOWN || type == OP_UNSUPPORTED) { - log_warnx("%s: unsupported 2-byte opcode", __func__); - return (DECODE_ERROR); - } - - opcode->op_bytes[0] = byte; - opcode->op_bytes[1] = byte2; - opcode->op_bytes_len = 2; - enc = x86_2byte_operand_enc_table[byte2]; - break; - - default: - /* We've potentially got a known 1-byte opcode. */ - opcode->op_bytes[0] = byte; - opcode->op_bytes_len = 1; - enc = x86_1byte_operand_enc_tbl[byte]; - } - - if (enc == OP_ENC_UNKNOWN) - return (DECODE_ERROR); - - opcode->op_type = type; - opcode->op_encoding = enc; - - return (res); -} - -static enum decode_result -decode_sib(struct x86_decode_state *state, struct x86_insn *insn) -{ - enum decode_result res; - uint8_t byte; - - if (!is_valid_state(state, __func__) || insn == NULL) - return (-1); - - /* SIB is optional, so assume we will be continuing. */ - res = DECODE_MORE; - - insn->insn_sib_valid = 0; - if (!insn->insn_modrm_valid) - return (res); - - /* XXX is SIB valid in all cpu modes? */ - if (MODRM_RM(insn->insn_modrm) == 0b100) { - res = next_byte(state, &byte); - if (res != DECODE_ERROR) { - insn->insn_sib_valid = 1; - insn->insn_sib = byte; - } - } - - return (res); -} - -static enum decode_result -decode_imm(struct x86_decode_state *state, struct x86_insn *insn) -{ - enum decode_result res; - size_t num_bytes; - uint64_t value; - - if (!is_valid_state(state, __func__) || insn == NULL) - return (DECODE_ERROR); - - /* Only handle MI encoded instructions. Others shouldn't need assist. */ - if (insn->insn_opcode.op_encoding != OP_ENC_MI) - return (DECODE_DONE); - - /* Exceptions related to MOV instructions. */ - if (insn->insn_opcode.op_type == OP_MOV) { - switch (insn->insn_opcode.op_bytes[0]) { - case 0xC6: - num_bytes = 1; - break; - case 0xC7: - if (insn->insn_cpu_mode == VMM_CPU_MODE_REAL) - num_bytes = 2; - else - num_bytes = 4; - break; - default: - log_warnx("%s: cannot decode immediate bytes for MOV", - __func__); - return (DECODE_ERROR); - } - } else { - /* Fallback to interpreting based on cpu mode and REX. */ - if (insn->insn_cpu_mode == VMM_CPU_MODE_REAL) - num_bytes = 2; - else if (insn->insn_prefix.pfx_rex == REX_NONE) - num_bytes = 4; - else - num_bytes = 8; - } - - res = next_value(state, num_bytes, &value); - if (res != DECODE_ERROR) { - insn->insn_immediate = value; - insn->insn_immediate_len = num_bytes; - } - - return (res); -} - - -/* - * insn_decode - * - * Decode an x86 instruction from the provided instruction bytes. - * - * Return values: - * 0: successful decode - * Non-zero: an exception occurred during decode - */ -int -insn_decode(struct vm_exit *exit, struct x86_insn *insn) -{ - enum decode_result res; - struct vcpu_reg_state *vrs = &exit->vrs; - struct x86_decode_state state; - uint8_t *bytes, len; - int mode; - - if (exit == NULL || insn == NULL) { - log_warnx("%s: invalid input", __func__); - return (DECODE_ERROR); - } - - bytes = exit->vee.vee_insn_bytes; - len = exit->vee.vee_insn_len; - - /* 0. Initialize state and instruction objects. */ - memset(insn, 0, sizeof(*insn)); - memset(&state, 0, sizeof(state)); - state.s_len = len; - memcpy(&state.s_bytes, bytes, len); - - /* 1. Detect CPU mode. */ - mode = detect_cpu_mode(vrs); - if (mode == VMM_CPU_MODE_UNKNOWN) { - log_warnx("%s: failed to identify cpu mode", __func__); -#ifdef MMIO_DEBUG - dump_regs(vrs); -#endif - return (-1); - } - insn->insn_cpu_mode = mode; - -#ifdef MMIO_DEBUG - log_info("%s: cpu mode %s detected", __progname, str_cpu_mode(mode)); - printf("%s: got bytes: [ ", __progname); - for (int i = 0; i < len; i++) { - printf("%02x ", bytes[i]); - } - printf("]\n"); -#endif - /* 2. Decode prefixes. */ - res = decode_prefix(&state, insn); - if (res == DECODE_ERROR) { - log_warnx("%s: error decoding prefixes", __func__); - goto err; - } else if (res == DECODE_DONE) - goto done; - -#ifdef MMIO_DEBUG - log_info("%s: prefixes {g1: 0x%02x, g2: 0x%02x, g3: 0x%02x, g4: 0x%02x," - " rex: 0x%02x }", __progname, insn->insn_prefix.pfx_group1, - insn->insn_prefix.pfx_group2, insn->insn_prefix.pfx_group3, - insn->insn_prefix.pfx_group4, insn->insn_prefix.pfx_rex); -#endif - - /* 3. Pick apart opcode. Here we can start short-circuiting. */ - res = decode_opcode(&state, insn); - if (res == DECODE_ERROR) { - log_warnx("%s: error decoding opcode", __func__); - goto err; - } else if (res == DECODE_DONE) - goto done; - -#ifdef MMIO_DEBUG - log_info("%s: found opcode %s (operand encoding %s) (%s)", __progname, - str_opcode(&insn->insn_opcode), str_operand_enc(&insn->insn_opcode), - str_decode_res(res)); -#endif - - /* Process optional ModR/M byte. */ - res = decode_modrm(&state, insn); - if (res == DECODE_ERROR) { - log_warnx("%s: error decoding modrm", __func__); - goto err; - } - if (get_modrm_addr(insn, vrs) != 0) - goto err; - if (get_modrm_reg(insn) != 0) - goto err; - if (res == DECODE_DONE) - goto done; - -#ifdef MMIO_DEBUG - if (insn->insn_modrm_valid) - log_info("%s: found ModRM 0x%02x (%s)", __progname, - insn->insn_modrm, str_decode_res(res)); -#endif - - /* Process optional SIB byte. */ - res = decode_sib(&state, insn); - if (res == DECODE_ERROR) { - log_warnx("%s: error decoding sib", __func__); - goto err; - } else if (res == DECODE_DONE) - goto done; - -#ifdef MMIO_DEBUG - if (insn->insn_sib_valid) - log_info("%s: found SIB 0x%02x (%s)", __progname, - insn->insn_sib, str_decode_res(res)); -#endif - - /* Process any Displacement bytes. */ - res = decode_disp(&state, insn); - if (res == DECODE_ERROR) { - log_warnx("%s: error decoding displacement", __func__); - goto err; - } else if (res == DECODE_DONE) - goto done; - - /* Process any Immediate data bytes. */ - res = decode_imm(&state, insn); - if (res == DECODE_ERROR) { - log_warnx("%s: error decoding immediate bytes", __func__); - goto err; - } - -done: - insn->insn_bytes_len = state.s_idx; - -#ifdef MMIO_DEBUG - log_info("%s: final instruction length is %u", __func__, - insn->insn_bytes_len); - dump_insn(insn); - log_info("%s: modrm: {mod: %d, regop: %d, rm: %d}", __func__, - MODRM_MOD(insn->insn_modrm), MODRM_REGOP(insn->insn_modrm), - MODRM_RM(insn->insn_modrm)); - dump_regs(vrs); -#endif /* MMIO_DEBUG */ - return (0); - -err: -#ifdef MMIO_DEBUG - dump_insn(insn); - log_info("%s: modrm: {mod: %d, regop: %d, rm: %d}", __func__, - MODRM_MOD(insn->insn_modrm), MODRM_REGOP(insn->insn_modrm), - MODRM_RM(insn->insn_modrm)); - dump_regs(vrs); -#endif /* MMIO_DEBUG */ - return (-1); -} - -static int -emulate_mov(struct x86_insn *insn, struct vm_exit *exit) -{ - /* XXX Only supports read to register for now */ - if (insn->insn_opcode.op_encoding != OP_ENC_RM) - return (-1); - - /* XXX No device emulation yet. Fill with 0xFFs. */ - exit->vrs.vrs_gprs[insn->insn_reg] = 0xFFFFFFFFFFFFFFFF; - - return (0); -} - -static int -emulate_movzx(struct x86_insn *insn, struct vm_exit *exit) -{ - uint8_t byte, len, src = 1, dst = 2; - uint64_t value = 0; - - /* Only RM is valid for MOVZX. */ - if (insn->insn_opcode.op_encoding != OP_ENC_RM) { - log_warnx("invalid op encoding for MOVZX: %d", - insn->insn_opcode.op_encoding); - return (-1); - } - - len = insn->insn_opcode.op_bytes_len; - if (len < 1 || len > sizeof(insn->insn_opcode.op_bytes)) { - log_warnx("invalid opcode byte length: %d", len); - return (-1); - } - - byte = insn->insn_opcode.op_bytes[len - 1]; - switch (byte) { - case 0xB6: - src = 1; - if (insn->insn_cpu_mode == VMM_CPU_MODE_PROT - || insn->insn_cpu_mode == VMM_CPU_MODE_REAL) - dst = 2; - else if (insn->insn_prefix.pfx_rex == REX_NONE) - dst = 4; - else // XXX validate CPU mode - dst = 8; - break; - case 0xB7: - src = 2; - if (insn->insn_prefix.pfx_rex == REX_NONE) - dst = 4; - else // XXX validate CPU mode - dst = 8; - break; - default: - log_warnx("invalid byte in MOVZX opcode: %x", byte); - return (-1); - } - - if (dst == 4) - exit->vrs.vrs_gprs[insn->insn_reg] &= 0xFFFFFFFF00000000; - else - exit->vrs.vrs_gprs[insn->insn_reg] = 0x0UL; - - /* XXX No device emulation yet. Fill with 0xFFs. */ - switch (src) { - case 1: value = 0xFF; break; - case 2: value = 0xFFFF; break; - case 4: value = 0xFFFFFFFF; break; - case 8: value = 0xFFFFFFFFFFFFFFFF; break; - default: - log_warnx("invalid source size: %d", src); - return (-1); - } - - exit->vrs.vrs_gprs[insn->insn_reg] |= value; - - return (0); -} - -/* - * insn_emulate - * - * Returns: - * 0: success - * EINVAL: exception occurred - * EFAULT: page fault occurred, requires retry - * ENOTSUP: an unsupported instruction was provided - */ -int -insn_emulate(struct vm_exit *exit, struct x86_insn *insn) -{ - int res; - - switch (insn->insn_opcode.op_type) { - case OP_MOV: - res = emulate_mov(insn, exit); - break; - - case OP_MOVZX: - res = emulate_movzx(insn, exit); - break; - - default: - log_warnx("%s: emulation not defined for %s", __func__, - str_opcode(&insn->insn_opcode)); - res = ENOTSUP; - } - - if (res == 0) - exit->vrs.vrs_gprs[VCPU_REGS_RIP] += insn->insn_bytes_len; - - return (res); -} diff --git a/usr.sbin/vmd/ns8250.c b/usr.sbin/vmd/ns8250.c index bcb48ef95..17cc8bfe5 100644 --- a/usr.sbin/vmd/ns8250.c +++ b/usr.sbin/vmd/ns8250.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ns8250.c,v 1.39 2024/07/09 09:31:37 dv Exp $ */ +/* $OpenBSD: ns8250.c,v 1.40 2024/07/10 09:27:33 dv Exp $ */ /* * Copyright (c) 2016 Mike Larkin * @@ -30,7 +30,6 @@ #include "atomicio.h" #include "ns8250.h" #include "vmd.h" -#include "vmm.h" extern char *__progname; struct ns8250_dev com1_dev; @@ -80,7 +79,7 @@ ratelimit(int fd, short type, void *arg) com1_dev.regs.iir |= IIR_TXRDY; com1_dev.regs.iir &= ~IIR_NOPEND; - vcpu_assert_pic_irq(com1_dev.vmid, 0, com1_dev.irq); + vcpu_assert_irq(com1_dev.vmid, 0, com1_dev.irq); mutex_unlock(&com1_dev.mutex); } @@ -157,7 +156,7 @@ com_rcv_event(int fd, short kind, void *arg) /* If pending interrupt, inject */ if ((com1_dev.regs.iir & IIR_NOPEND) == 0) { /* XXX: vcpu_id */ - vcpu_assert_pic_irq((uintptr_t)arg, 0, com1_dev.irq); + vcpu_assert_irq((uintptr_t)arg, 0, com1_dev.irq); } mutex_unlock(&com1_dev.mutex); diff --git a/usr.sbin/vmd/pci.c b/usr.sbin/vmd/pci.c index 1722baa9e..0dbe846fd 100644 --- a/usr.sbin/vmd/pci.c +++ b/usr.sbin/vmd/pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pci.c,v 1.32 2024/07/09 09:31:37 dv Exp $ */ +/* $OpenBSD: pci.c,v 1.33 2024/07/10 09:27:33 dv Exp $ */ /* * Copyright (c) 2015 Mike Larkin @@ -28,12 +28,12 @@ #include "vmd.h" #include "pci.h" -#include "vmm.h" #include "i8259.h" #include "atomicio.h" struct pci pci; +extern struct vmd_vm current_vm; extern char *__progname; /* PIC IRQs, assigned to devices in order */ @@ -86,7 +86,9 @@ pci_add_bar(uint8_t id, uint32_t type, void *barfn, void *cookie) pci.pci_devices[id].pd_bartype[bar_ct] = PCI_BAR_TYPE_MMIO; pci.pci_devices[id].pd_barsize[bar_ct] = VM_PCI_MMIO_BAR_SIZE; pci.pci_devices[id].pd_bar_ct++; - } else if (type == PCI_MAPREG_TYPE_IO) { + } +#ifdef __amd64__ + else if (type == PCI_MAPREG_TYPE_IO) { if (pci.pci_next_io_bar >= VM_PCI_IO_BAR_END) return (1); @@ -102,6 +104,7 @@ pci_add_bar(uint8_t id, uint32_t type, void *barfn, void *cookie) pci.pci_devices[id].pd_barsize[bar_ct] = VM_PCI_IO_BAR_SIZE; pci.pci_devices[id].pd_bar_ct++; } +#endif /* __amd64__ */ return (0); } @@ -195,7 +198,7 @@ pci_add_device(uint8_t *id, uint16_t vid, uint16_t pid, uint8_t class, pci.pci_next_pic_irq++; DPRINTF("assigned irq %d to pci dev %d", pci.pci_devices[*id].pd_irq, *id); - pic_set_elcr(pci.pci_devices[*id].pd_irq, 1); + intr_toggle_el(¤t_vm, pci.pci_devices[*id].pd_irq, 1); } pci.pci_dev_ct ++; @@ -216,7 +219,10 @@ pci_init(void) memset(&pci, 0, sizeof(pci)); pci.pci_next_mmio_bar = VMM_PCI_MMIO_BAR_BASE; + +#ifdef __amd64__ pci.pci_next_io_bar = VM_PCI_IO_BAR_BASE; +#endif /* __amd64__ */ if (pci_add_device(&id, PCI_VENDOR_OPENBSD, PCI_PRODUCT_OPENBSD_PCHB, PCI_CLASS_BRIDGE, PCI_SUBCLASS_BRIDGE_HOST, @@ -226,6 +232,7 @@ pci_init(void) } } +#ifdef __amd64__ void pci_handle_address_reg(struct vm_run_params *vrp) { @@ -415,6 +422,7 @@ pci_handle_data_reg(struct vm_run_params *vrp) } } } +#endif /* __amd64__ */ int pci_dump(int fd) diff --git a/usr.sbin/vmd/pci.h b/usr.sbin/vmd/pci.h index 73b54437b..0b05a9298 100644 --- a/usr.sbin/vmd/pci.h +++ b/usr.sbin/vmd/pci.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pci.h,v 1.10 2023/02/06 20:33:34 dv Exp $ */ +/* $OpenBSD: pci.h,v 1.11 2024/07/10 09:27:33 dv Exp $ */ /* * Copyright (c) 2015 Mike Larkin @@ -93,9 +93,6 @@ struct pci { }; int pci_find_first_device(uint16_t); -void pci_handle_address_reg(struct vm_run_params *); -void pci_handle_data_reg(struct vm_run_params *); -uint8_t pci_handle_io(struct vm_run_params *); void pci_init(void); int pci_add_device(uint8_t *, uint16_t, uint16_t, uint8_t, uint8_t, uint16_t, uint16_t, uint8_t, pci_cs_fn_t); @@ -105,4 +102,10 @@ uint8_t pci_get_dev_irq(uint8_t); int pci_dump(int); int pci_restore(int); +#ifdef __amd64__ +void pci_handle_address_reg(struct vm_run_params *); +void pci_handle_data_reg(struct vm_run_params *); +uint8_t pci_handle_io(struct vm_run_params *); +#endif /* __amd64__ */ + #endif /* _PCI_H_ */ diff --git a/usr.sbin/vmd/vioblk.c b/usr.sbin/vmd/vioblk.c index 6e3e31475..cef10e32c 100644 --- a/usr.sbin/vmd/vioblk.c +++ b/usr.sbin/vmd/vioblk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vioblk.c,v 1.13 2024/02/20 21:40:37 dv Exp $ */ +/* $OpenBSD: vioblk.c,v 1.14 2024/07/10 09:27:33 dv Exp $ */ /* * Copyright (c) 2023 Dave Voutila @@ -555,7 +555,7 @@ handle_sync_io(int fd, short event, void *arg) case VIODEV_MSG_IO_WRITE: /* Write IO: no reply needed */ if (handle_io_write(&msg, dev) == 1) - virtio_assert_pic_irq(dev, 0); + virtio_assert_irq(dev, 0); break; case VIODEV_MSG_SHUTDOWN: event_del(&dev->sync_iev.ev); @@ -614,7 +614,7 @@ handle_io_write(struct viodev_msg *msg, struct virtio_dev *dev) vioblk->cfg.isr_status = 0; vioblk->vq[0].last_avail = 0; vioblk->vq[0].notified_avail = 0; - virtio_deassert_pic_irq(dev, msg->vcpu); + virtio_deassert_irq(dev, msg->vcpu); } break; default: diff --git a/usr.sbin/vmd/virtio.c b/usr.sbin/vmd/virtio.c index 80d035ef6..f203f822a 100644 --- a/usr.sbin/vmd/virtio.c +++ b/usr.sbin/vmd/virtio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: virtio.c,v 1.114 2024/07/09 09:31:37 dv Exp $ */ +/* $OpenBSD: virtio.c,v 1.115 2024/07/10 09:27:33 dv Exp $ */ /* * Copyright (c) 2015 Mike Larkin @@ -47,7 +47,6 @@ #include "vioscsi.h" #include "virtio.h" #include "vmd.h" -#include "vmm.h" extern struct vmd *env; extern char *__progname; @@ -274,7 +273,7 @@ virtio_rnd_io(int dir, uint16_t reg, uint32_t *data, uint8_t *intr, case VIRTIO_CONFIG_ISR_STATUS: *data = viornd.cfg.isr_status; viornd.cfg.isr_status = 0; - vcpu_deassert_pic_irq(viornd.vm_id, 0, viornd.irq); + vcpu_deassert_irq(viornd.vm_id, 0, viornd.irq); break; } } @@ -310,7 +309,7 @@ vmmci_ctl(unsigned int cmd) /* Trigger interrupt */ vmmci.cfg.isr_status = VIRTIO_CONFIG_ISR_CONFIG_CHANGE; - vcpu_assert_pic_irq(vmmci.vm_id, 0, vmmci.irq); + vcpu_assert_irq(vmmci.vm_id, 0, vmmci.irq); /* Add ACK timeout */ tv.tv_sec = VMMCI_TIMEOUT; @@ -322,7 +321,7 @@ vmmci_ctl(unsigned int cmd) vmmci.cmd = cmd; vmmci.cfg.isr_status = VIRTIO_CONFIG_ISR_CONFIG_CHANGE; - vcpu_assert_pic_irq(vmmci.vm_id, 0, vmmci.irq); + vcpu_assert_irq(vmmci.vm_id, 0, vmmci.irq); } else { log_debug("%s: RTC sync skipped (guest does not " "support RTC sync)\n", __func__); @@ -468,7 +467,7 @@ vmmci_io(int dir, uint16_t reg, uint32_t *data, uint8_t *intr, case VIRTIO_CONFIG_ISR_STATUS: *data = vmmci.cfg.isr_status; vmmci.cfg.isr_status = 0; - vcpu_deassert_pic_irq(vmmci.vm_id, 0, vmmci.irq); + vcpu_deassert_irq(vmmci.vm_id, 0, vmmci.irq); break; } } @@ -1586,9 +1585,9 @@ handle_dev_msg(struct viodev_msg *msg, struct virtio_dev *gdev) switch (msg->type) { case VIODEV_MSG_KICK: if (msg->state == INTR_STATE_ASSERT) - vcpu_assert_pic_irq(vm_id, msg->vcpu, irq); + vcpu_assert_irq(vm_id, msg->vcpu, irq); else if (msg->state == INTR_STATE_DEASSERT) - vcpu_deassert_pic_irq(vm_id, msg->vcpu, irq); + vcpu_deassert_irq(vm_id, msg->vcpu, irq); break; case VIODEV_MSG_READY: log_debug("%s: device reports ready", __func__); @@ -1702,9 +1701,9 @@ virtio_pci_io(int dir, uint16_t reg, uint32_t *data, uint8_t *intr, * device performs a register read. */ if (msg.state == INTR_STATE_ASSERT) - vcpu_assert_pic_irq(dev->vm_id, msg.vcpu, msg.irq); + vcpu_assert_irq(dev->vm_id, msg.vcpu, msg.irq); else if (msg.state == INTR_STATE_DEASSERT) - vcpu_deassert_pic_irq(dev->vm_id, msg.vcpu, msg.irq); + vcpu_deassert_irq(dev->vm_id, msg.vcpu, msg.irq); } else { log_warnx("%s: expected IO_READ, got %d", __func__, msg.type); @@ -1716,7 +1715,7 @@ virtio_pci_io(int dir, uint16_t reg, uint32_t *data, uint8_t *intr, } void -virtio_assert_pic_irq(struct virtio_dev *dev, int vcpu) +virtio_assert_irq(struct virtio_dev *dev, int vcpu) { struct viodev_msg msg; int ret; @@ -1734,7 +1733,7 @@ virtio_assert_pic_irq(struct virtio_dev *dev, int vcpu) } void -virtio_deassert_pic_irq(struct virtio_dev *dev, int vcpu) +virtio_deassert_irq(struct virtio_dev *dev, int vcpu) { struct viodev_msg msg; int ret; diff --git a/usr.sbin/vmd/virtio.h b/usr.sbin/vmd/virtio.h index 58f2c2168..c29374305 100644 --- a/usr.sbin/vmd/virtio.h +++ b/usr.sbin/vmd/virtio.h @@ -1,4 +1,4 @@ -/* $OpenBSD: virtio.h,v 1.51 2024/02/20 21:40:37 dv Exp $ */ +/* $OpenBSD: virtio.h,v 1.52 2024/07/10 09:27:33 dv Exp $ */ /* * Copyright (c) 2015 Mike Larkin @@ -346,8 +346,8 @@ uint32_t vring_size(uint32_t); int vm_device_pipe(struct virtio_dev *, void (*)(int, short, void *), struct event_base *); int virtio_pci_io(int, uint16_t, uint32_t *, uint8_t *, void *, uint8_t); -void virtio_assert_pic_irq(struct virtio_dev *, int); -void virtio_deassert_pic_irq(struct virtio_dev *, int); +void virtio_assert_irq(struct virtio_dev *, int); +void virtio_deassert_irq(struct virtio_dev *, int); int virtio_rnd_io(int, uint16_t, uint32_t *, uint8_t *, void *, uint8_t); int viornd_dump(int); diff --git a/usr.sbin/vmd/vm.c b/usr.sbin/vmd/vm.c index 078e9b517..e8c73b0e0 100644 --- a/usr.sbin/vmd/vm.c +++ b/usr.sbin/vmd/vm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm.c,v 1.103 2024/07/09 09:31:37 dv Exp $ */ +/* $OpenBSD: vm.c,v 1.104 2024/07/10 09:27:33 dv Exp $ */ /* * Copyright (c) 2015 Mike Larkin @@ -22,21 +22,14 @@ #include #include #include -#include #include #include #include #include -#include -#include #include #include -#include -#include -#include - #include #include @@ -55,57 +48,28 @@ #include #include "atomicio.h" -#include "fw_cfg.h" -#include "i8253.h" -#include "i8259.h" -#include "loadfile.h" -#include "mc146818.h" #include "mmio.h" -#include "ns8250.h" #include "pci.h" #include "virtio.h" #include "vmd.h" -#include "vmm.h" - -#define MB(x) (x * 1024UL * 1024UL) -#define GB(x) (x * 1024UL * 1024UL * 1024UL) #define MMIO_NOTYET 0 -io_fn_t ioports_map[MAX_PORTS]; - static int run_vm(struct vmop_create_params *, struct vcpu_reg_state *); -void vm_dispatch_vmm(int, short, void *); -void *event_thread(void *); -void *vcpu_run_loop(void *); -int vcpu_exit(struct vm_run_params *); -int vcpu_reset(uint32_t, uint32_t, struct vcpu_reg_state *); -void create_memory_map(struct vm_create_params *); +static void vm_dispatch_vmm(int, short, void *); +static void *event_thread(void *); +static void *vcpu_run_loop(void *); static int vmm_create_vm(struct vmd_vm *); -int alloc_guest_mem(struct vmd_vm *); -void init_emulated_hw(struct vmop_create_params *, int, - int[][VM_MAX_BASE_PER_DISK], int *); -void restore_emulated_hw(struct vm_create_params *, int, int *, - int[][VM_MAX_BASE_PER_DISK],int); -void vcpu_exit_inout(struct vm_run_params *); -int vcpu_exit_eptviolation(struct vm_run_params *); -uint8_t vcpu_exit_pci(struct vm_run_params *); -int vcpu_pic_intr(uint32_t, uint32_t, uint8_t); -int loadfile_bios(gzFile, off_t, struct vcpu_reg_state *); +static int alloc_guest_mem(struct vmd_vm *); static int send_vm(int, struct vmd_vm *); -int dump_send_header(int); static int dump_vmr(int , struct vm_mem_range *); static int dump_mem(int, struct vmd_vm *); -void restore_vmr(int, struct vm_mem_range *); -void restore_mem(int, struct vm_create_params *); -int restore_vm_params(int, struct vm_create_params *); +static void restore_vmr(int, struct vm_mem_range *); +static void restore_mem(int, struct vm_create_params *); +static int restore_vm_params(int, struct vm_create_params *); static void pause_vm(struct vmd_vm *); static void unpause_vm(struct vmd_vm *); - -int translate_gva(struct vm_exit*, uint64_t, uint64_t *, int); - -static struct vm_mem_range *find_gpa_range(struct vm_create_params *, paddr_t, - size_t); +static int start_vm(struct vmd_vm *, int); int con_fd; struct vmd_vm *current_vm; @@ -127,93 +91,6 @@ pthread_mutex_t vm_mtx; uint8_t vcpu_hlt[VMM_MAX_VCPUS_PER_VM]; uint8_t vcpu_done[VMM_MAX_VCPUS_PER_VM]; -/* - * Represents a standard register set for an OS to be booted - * as a flat 64 bit address space. - * - * NOT set here are: - * RIP - * RSP - * GDTR BASE - * - * Specific bootloaders should clone this structure and override - * those fields as needed. - * - * Note - CR3 and various bits in CR0 may be overridden by vmm(4) based on - * features of the CPU in use. - */ -static const struct vcpu_reg_state vcpu_init_flat64 = { - .vrs_gprs[VCPU_REGS_RFLAGS] = 0x2, - .vrs_gprs[VCPU_REGS_RIP] = 0x0, - .vrs_gprs[VCPU_REGS_RSP] = 0x0, - .vrs_crs[VCPU_REGS_CR0] = CR0_ET | CR0_PE | CR0_PG, - .vrs_crs[VCPU_REGS_CR3] = PML4_PAGE, - .vrs_crs[VCPU_REGS_CR4] = CR4_PAE | CR4_PSE, - .vrs_crs[VCPU_REGS_PDPTE0] = 0ULL, - .vrs_crs[VCPU_REGS_PDPTE1] = 0ULL, - .vrs_crs[VCPU_REGS_PDPTE2] = 0ULL, - .vrs_crs[VCPU_REGS_PDPTE3] = 0ULL, - .vrs_sregs[VCPU_REGS_CS] = { 0x8, 0xFFFFFFFF, 0xC09F, 0x0}, - .vrs_sregs[VCPU_REGS_DS] = { 0x10, 0xFFFFFFFF, 0xC093, 0x0}, - .vrs_sregs[VCPU_REGS_ES] = { 0x10, 0xFFFFFFFF, 0xC093, 0x0}, - .vrs_sregs[VCPU_REGS_FS] = { 0x10, 0xFFFFFFFF, 0xC093, 0x0}, - .vrs_sregs[VCPU_REGS_GS] = { 0x10, 0xFFFFFFFF, 0xC093, 0x0}, - .vrs_sregs[VCPU_REGS_SS] = { 0x10, 0xFFFFFFFF, 0xC093, 0x0}, - .vrs_gdtr = { 0x0, 0xFFFF, 0x0, 0x0}, - .vrs_idtr = { 0x0, 0xFFFF, 0x0, 0x0}, - .vrs_sregs[VCPU_REGS_LDTR] = { 0x0, 0xFFFF, 0x0082, 0x0}, - .vrs_sregs[VCPU_REGS_TR] = { 0x0, 0xFFFF, 0x008B, 0x0}, - .vrs_msrs[VCPU_REGS_EFER] = EFER_LME | EFER_LMA, - .vrs_drs[VCPU_REGS_DR0] = 0x0, - .vrs_drs[VCPU_REGS_DR1] = 0x0, - .vrs_drs[VCPU_REGS_DR2] = 0x0, - .vrs_drs[VCPU_REGS_DR3] = 0x0, - .vrs_drs[VCPU_REGS_DR6] = 0xFFFF0FF0, - .vrs_drs[VCPU_REGS_DR7] = 0x400, - .vrs_msrs[VCPU_REGS_STAR] = 0ULL, - .vrs_msrs[VCPU_REGS_LSTAR] = 0ULL, - .vrs_msrs[VCPU_REGS_CSTAR] = 0ULL, - .vrs_msrs[VCPU_REGS_SFMASK] = 0ULL, - .vrs_msrs[VCPU_REGS_KGSBASE] = 0ULL, - .vrs_msrs[VCPU_REGS_MISC_ENABLE] = 0ULL, - .vrs_crs[VCPU_REGS_XCR0] = XFEATURE_X87 -}; - -/* - * Represents a standard register set for an BIOS to be booted - * as a flat 16 bit address space. - */ -static const struct vcpu_reg_state vcpu_init_flat16 = { - .vrs_gprs[VCPU_REGS_RFLAGS] = 0x2, - .vrs_gprs[VCPU_REGS_RIP] = 0xFFF0, - .vrs_gprs[VCPU_REGS_RSP] = 0x0, - .vrs_crs[VCPU_REGS_CR0] = 0x60000010, - .vrs_crs[VCPU_REGS_CR3] = 0, - .vrs_sregs[VCPU_REGS_CS] = { 0xF000, 0xFFFF, 0x809F, 0xF0000}, - .vrs_sregs[VCPU_REGS_DS] = { 0x0, 0xFFFF, 0x8093, 0x0}, - .vrs_sregs[VCPU_REGS_ES] = { 0x0, 0xFFFF, 0x8093, 0x0}, - .vrs_sregs[VCPU_REGS_FS] = { 0x0, 0xFFFF, 0x8093, 0x0}, - .vrs_sregs[VCPU_REGS_GS] = { 0x0, 0xFFFF, 0x8093, 0x0}, - .vrs_sregs[VCPU_REGS_SS] = { 0x0, 0xFFFF, 0x8093, 0x0}, - .vrs_gdtr = { 0x0, 0xFFFF, 0x0, 0x0}, - .vrs_idtr = { 0x0, 0xFFFF, 0x0, 0x0}, - .vrs_sregs[VCPU_REGS_LDTR] = { 0x0, 0xFFFF, 0x0082, 0x0}, - .vrs_sregs[VCPU_REGS_TR] = { 0x0, 0xFFFF, 0x008B, 0x0}, - .vrs_msrs[VCPU_REGS_EFER] = 0ULL, - .vrs_drs[VCPU_REGS_DR0] = 0x0, - .vrs_drs[VCPU_REGS_DR1] = 0x0, - .vrs_drs[VCPU_REGS_DR2] = 0x0, - .vrs_drs[VCPU_REGS_DR3] = 0x0, - .vrs_drs[VCPU_REGS_DR6] = 0xFFFF0FF0, - .vrs_drs[VCPU_REGS_DR7] = 0x400, - .vrs_msrs[VCPU_REGS_STAR] = 0ULL, - .vrs_msrs[VCPU_REGS_LSTAR] = 0ULL, - .vrs_msrs[VCPU_REGS_CSTAR] = 0ULL, - .vrs_msrs[VCPU_REGS_SFMASK] = 0ULL, - .vrs_msrs[VCPU_REGS_KGSBASE] = 0ULL, - .vrs_crs[VCPU_REGS_XCR0] = XFEATURE_X87 -}; - /* * vm_main * @@ -290,58 +167,6 @@ vm_main(int fd, int fd_vmm) _exit(ret); } -/* - * loadfile_bios - * - * Alternatively to loadfile_elf, this function loads a non-ELF BIOS image - * directly into memory. - * - * Parameters: - * fp: file of a kernel file to load - * size: uncompressed size of the image - * (out) vrs: register state to set on init for this kernel - * - * Return values: - * 0 if successful - * various error codes returned from read(2) or loadelf functions - */ -int -loadfile_bios(gzFile fp, off_t size, struct vcpu_reg_state *vrs) -{ - off_t off; - - /* Set up a "flat 16 bit" register state for BIOS */ - memcpy(vrs, &vcpu_init_flat16, sizeof(*vrs)); - - /* Seek to the beginning of the BIOS image */ - if (gzseek(fp, 0, SEEK_SET) == -1) - return (-1); - - /* The BIOS image must end at 1MB */ - if ((off = MB(1) - size) < 0) - return (-1); - - /* Read BIOS image into memory */ - if (mread(fp, off, size) != (size_t)size) { - errno = EIO; - return (-1); - } - - if (gzseek(fp, 0, SEEK_SET) == -1) - return (-1); - - /* Read a second BIOS copy into memory ending at 4GB */ - off = GB(4) - size; - if (mread(fp, off, size) != (size_t)size) { - errno = EIO; - return (-1); - } - - log_debug("%s: loaded BIOS image", __func__); - - return (0); -} - /* * start_vm * @@ -372,10 +197,8 @@ start_vm(struct vmd_vm *vm, int fd) struct vcpu_reg_state vrs; int nicfds[VM_MAX_NICS_PER_VM]; int ret; - gzFile fp; size_t i; struct vm_rwregs_params vrp; - struct stat sb; /* * We first try to initialize and allocate memory before bothering @@ -433,33 +256,8 @@ start_vm(struct vmd_vm *vm, int fd) if (ret != sizeof(vrp)) fatal("received incomplete vrp - exiting"); vrs = vrp.vrwp_regs; - } else { - /* - * Set up default "flat 64 bit" register state - RIP, - * RSP, and GDT info will be set in bootloader - */ - memcpy(&vrs, &vcpu_init_flat64, sizeof(vrs)); - - /* Find and open kernel image */ - if ((fp = gzdopen(vm->vm_kernel, "r")) == NULL) - fatalx("failed to open kernel - exiting"); - - /* Load kernel image */ - ret = loadfile_elf(fp, vm, &vrs, vmc->vmc_bootdevice); - - /* - * Try BIOS as a fallback (only if it was provided as an image - * with vm->vm_kernel and the file is not compressed) - */ - if (ret && errno == ENOEXEC && vm->vm_kernel != -1 && - gzdirect(fp) && (ret = fstat(vm->vm_kernel, &sb)) == 0) - ret = loadfile_bios(fp, sb.st_size, &vrs); - - if (ret) - fatal("failed to load kernel or BIOS - exiting"); - - gzclose(fp); - } + } else if (load_firmware(vm, &vrs)) + fatalx("failed to load kernel or firmware image"); if (vm->vm_kernel != -1) close_fd(vm->vm_kernel); @@ -721,15 +519,7 @@ send_vm(int fd, struct vmd_vm *vm) /* Dump memory before devices to aid in restoration. */ if ((ret = dump_mem(fd, vm))) goto err; - if ((ret = i8253_dump(fd))) - goto err; - if ((ret = i8259_dump(fd))) - goto err; - if ((ret = ns8250_dump(fd))) - goto err; - if ((ret = mc146818_dump(fd))) - goto err; - if ((ret = fw_cfg_dump(fd))) + if ((ret = dump_devs(fd))) goto err; if ((ret = pci_dump(fd))) goto err; @@ -764,46 +554,6 @@ err: return ret; } -int -dump_send_header(int fd) { - struct vm_dump_header vmh; - int i; - - memcpy(&vmh.vmh_signature, VM_DUMP_SIGNATURE, - sizeof(vmh.vmh_signature)); - - vmh.vmh_cpuids[0].code = 0x00; - vmh.vmh_cpuids[0].leaf = 0x00; - - vmh.vmh_cpuids[1].code = 0x01; - vmh.vmh_cpuids[1].leaf = 0x00; - - vmh.vmh_cpuids[2].code = 0x07; - vmh.vmh_cpuids[2].leaf = 0x00; - - vmh.vmh_cpuids[3].code = 0x0d; - vmh.vmh_cpuids[3].leaf = 0x00; - - vmh.vmh_cpuids[4].code = 0x80000001; - vmh.vmh_cpuids[4].leaf = 0x00; - - vmh.vmh_version = VM_DUMP_VERSION; - - for (i=0; i < VM_DUMP_HEADER_CPUID_COUNT; i++) { - CPUID_LEAF(vmh.vmh_cpuids[i].code, - vmh.vmh_cpuids[i].leaf, - vmh.vmh_cpuids[i].a, - vmh.vmh_cpuids[i].b, - vmh.vmh_cpuids[i].c, - vmh.vmh_cpuids[i].d); - } - - if (atomicio(vwrite, fd, &vmh, sizeof(vmh)) != sizeof(vmh)) - return (-1); - - return (0); -} - int dump_mem(int fd, struct vmd_vm *vm) { @@ -933,10 +683,7 @@ pause_vm(struct vmd_vm *vm) return; } - i8253_stop(); - mc146818_stop(); - ns8250_stop(); - virtio_stop(vm); + pause_vm_md(vm); } static void @@ -962,10 +709,7 @@ unpause_vm(struct vmd_vm *vm) } } - i8253_start(); - mc146818_start(); - ns8250_start(); - virtio_start(vm); + unpause_vm_md(vm); } /* @@ -1002,99 +746,6 @@ vcpu_reset(uint32_t vmid, uint32_t vcpu_id, struct vcpu_reg_state *vrs) return (0); } -/* - * create_memory_map - * - * Sets up the guest physical memory ranges that the VM can access. - * - * Parameters: - * vcp: VM create parameters describing the VM whose memory map - * is being created - * - * Return values: - * nothing - */ -void -create_memory_map(struct vm_create_params *vcp) -{ - size_t len, mem_bytes; - size_t above_1m = 0, above_4g = 0; - - mem_bytes = vcp->vcp_memranges[0].vmr_size; - vcp->vcp_nmemranges = 0; - if (mem_bytes == 0 || mem_bytes > VMM_MAX_VM_MEM_SIZE) - return; - - /* First memory region: 0 - LOWMEM_KB (DOS low mem) */ - len = LOWMEM_KB * 1024; - vcp->vcp_memranges[0].vmr_gpa = 0x0; - vcp->vcp_memranges[0].vmr_size = len; - vcp->vcp_memranges[0].vmr_type = VM_MEM_RAM; - mem_bytes -= len; - - /* - * Second memory region: LOWMEM_KB - 1MB. - * - * N.B. - Normally ROMs or parts of video RAM are mapped here. - * We have to add this region, because some systems - * unconditionally write to 0xb8000 (VGA RAM), and - * we need to make sure that vmm(4) permits accesses - * to it. So allocate guest memory for it. - */ - len = MB(1) - (LOWMEM_KB * 1024); - vcp->vcp_memranges[1].vmr_gpa = LOWMEM_KB * 1024; - vcp->vcp_memranges[1].vmr_size = len; - vcp->vcp_memranges[1].vmr_type = VM_MEM_RESERVED; - mem_bytes -= len; - - /* If we have less than 2MB remaining, still create a 2nd BIOS area. */ - if (mem_bytes <= MB(2)) { - vcp->vcp_memranges[2].vmr_gpa = VMM_PCI_MMIO_BAR_END; - vcp->vcp_memranges[2].vmr_size = MB(2); - vcp->vcp_memranges[2].vmr_type = VM_MEM_RESERVED; - vcp->vcp_nmemranges = 3; - return; - } - - /* - * Calculate the how to split any remaining memory across the 4GB - * boundary while making sure we do not place physical memory into - * MMIO ranges. - */ - if (mem_bytes > VMM_PCI_MMIO_BAR_BASE - MB(1)) { - above_1m = VMM_PCI_MMIO_BAR_BASE - MB(1); - above_4g = mem_bytes - above_1m; - } else { - above_1m = mem_bytes; - above_4g = 0; - } - - /* Third memory region: area above 1MB to MMIO region */ - vcp->vcp_memranges[2].vmr_gpa = MB(1); - vcp->vcp_memranges[2].vmr_size = above_1m; - vcp->vcp_memranges[2].vmr_type = VM_MEM_RAM; - - /* Fourth region: PCI MMIO range */ - vcp->vcp_memranges[3].vmr_gpa = VMM_PCI_MMIO_BAR_BASE; - vcp->vcp_memranges[3].vmr_size = VMM_PCI_MMIO_BAR_END - - VMM_PCI_MMIO_BAR_BASE + 1; - vcp->vcp_memranges[3].vmr_type = VM_MEM_MMIO; - - /* Fifth region: 2nd copy of BIOS above MMIO ending at 4GB */ - vcp->vcp_memranges[4].vmr_gpa = VMM_PCI_MMIO_BAR_END + 1; - vcp->vcp_memranges[4].vmr_size = MB(2); - vcp->vcp_memranges[4].vmr_type = VM_MEM_RESERVED; - - /* Sixth region: any remainder above 4GB */ - if (above_4g > 0) { - vcp->vcp_memranges[5].vmr_gpa = GB(4); - vcp->vcp_memranges[5].vmr_size = above_4g; - vcp->vcp_memranges[5].vmr_type = VM_MEM_RAM; - vcp->vcp_nmemranges = 6; - } else - vcp->vcp_nmemranges = 5; -} - /* * alloc_guest_mem * @@ -1190,142 +841,8 @@ vmm_create_vm(struct vmd_vm *vm) return (0); } -/* - * init_emulated_hw - * - * Initializes the userspace hardware emulation - */ -void -init_emulated_hw(struct vmop_create_params *vmc, int child_cdrom, - int child_disks[][VM_MAX_BASE_PER_DISK], int *child_taps) -{ - struct vm_create_params *vcp = &vmc->vmc_params; - size_t i; - uint64_t memlo, memhi; - - /* Calculate memory size for NVRAM registers */ - memlo = memhi = 0; - for (i = 0; i < vcp->vcp_nmemranges; i++) { - if (vcp->vcp_memranges[i].vmr_gpa == MB(1) && - vcp->vcp_memranges[i].vmr_size > (15 * MB(1))) - memlo = vcp->vcp_memranges[i].vmr_size - (15 * MB(1)); - else if (vcp->vcp_memranges[i].vmr_gpa == GB(4)) - memhi = vcp->vcp_memranges[i].vmr_size; - } - - /* Reset the IO port map */ - memset(&ioports_map, 0, sizeof(io_fn_t) * MAX_PORTS); - - /* Init i8253 PIT */ - i8253_init(vcp->vcp_id); - ioports_map[TIMER_CTRL] = vcpu_exit_i8253; - ioports_map[TIMER_BASE + TIMER_CNTR0] = vcpu_exit_i8253; - ioports_map[TIMER_BASE + TIMER_CNTR1] = vcpu_exit_i8253; - ioports_map[TIMER_BASE + TIMER_CNTR2] = vcpu_exit_i8253; - ioports_map[PCKBC_AUX] = vcpu_exit_i8253_misc; - - /* Init mc146818 RTC */ - mc146818_init(vcp->vcp_id, memlo, memhi); - ioports_map[IO_RTC] = vcpu_exit_mc146818; - ioports_map[IO_RTC + 1] = vcpu_exit_mc146818; - - /* Init master and slave PICs */ - i8259_init(); - ioports_map[IO_ICU1] = vcpu_exit_i8259; - ioports_map[IO_ICU1 + 1] = vcpu_exit_i8259; - ioports_map[IO_ICU2] = vcpu_exit_i8259; - ioports_map[IO_ICU2 + 1] = vcpu_exit_i8259; - ioports_map[ELCR0] = vcpu_exit_elcr; - ioports_map[ELCR1] = vcpu_exit_elcr; - - /* Init ns8250 UART */ - ns8250_init(con_fd, vcp->vcp_id); - for (i = COM1_DATA; i <= COM1_SCR; i++) - ioports_map[i] = vcpu_exit_com; - - /* Initialize PCI */ - for (i = VM_PCI_IO_BAR_BASE; i <= VM_PCI_IO_BAR_END; i++) - ioports_map[i] = vcpu_exit_pci; - - ioports_map[PCI_MODE1_ADDRESS_REG] = vcpu_exit_pci; - ioports_map[PCI_MODE1_DATA_REG] = vcpu_exit_pci; - ioports_map[PCI_MODE1_DATA_REG + 1] = vcpu_exit_pci; - ioports_map[PCI_MODE1_DATA_REG + 2] = vcpu_exit_pci; - ioports_map[PCI_MODE1_DATA_REG + 3] = vcpu_exit_pci; - pci_init(); - - /* Initialize virtio devices */ - virtio_init(current_vm, child_cdrom, child_disks, child_taps); /* - * Init QEMU fw_cfg interface. Must be done last for pci hardware - * detection. - */ - fw_cfg_init(vmc); - ioports_map[FW_CFG_IO_SELECT] = vcpu_exit_fw_cfg; - ioports_map[FW_CFG_IO_DATA] = vcpu_exit_fw_cfg; - ioports_map[FW_CFG_IO_DMA_ADDR_HIGH] = vcpu_exit_fw_cfg_dma; - ioports_map[FW_CFG_IO_DMA_ADDR_LOW] = vcpu_exit_fw_cfg_dma; -} - -/* - * restore_emulated_hw - * - * Restores the userspace hardware emulation from fd - */ -void -restore_emulated_hw(struct vm_create_params *vcp, int fd, - int *child_taps, int child_disks[][VM_MAX_BASE_PER_DISK], int child_cdrom) -{ - /* struct vm_create_params *vcp = &vmc->vmc_params; */ - int i; - memset(&ioports_map, 0, sizeof(io_fn_t) * MAX_PORTS); - - /* Init i8253 PIT */ - i8253_restore(fd, vcp->vcp_id); - ioports_map[TIMER_CTRL] = vcpu_exit_i8253; - ioports_map[TIMER_BASE + TIMER_CNTR0] = vcpu_exit_i8253; - ioports_map[TIMER_BASE + TIMER_CNTR1] = vcpu_exit_i8253; - ioports_map[TIMER_BASE + TIMER_CNTR2] = vcpu_exit_i8253; - - /* Init master and slave PICs */ - i8259_restore(fd); - ioports_map[IO_ICU1] = vcpu_exit_i8259; - ioports_map[IO_ICU1 + 1] = vcpu_exit_i8259; - ioports_map[IO_ICU2] = vcpu_exit_i8259; - ioports_map[IO_ICU2 + 1] = vcpu_exit_i8259; - - /* Init ns8250 UART */ - ns8250_restore(fd, con_fd, vcp->vcp_id); - for (i = COM1_DATA; i <= COM1_SCR; i++) - ioports_map[i] = vcpu_exit_com; - - /* Init mc146818 RTC */ - mc146818_restore(fd, vcp->vcp_id); - ioports_map[IO_RTC] = vcpu_exit_mc146818; - ioports_map[IO_RTC + 1] = vcpu_exit_mc146818; - - /* Init QEMU fw_cfg interface */ - fw_cfg_restore(fd); - ioports_map[FW_CFG_IO_SELECT] = vcpu_exit_fw_cfg; - ioports_map[FW_CFG_IO_DATA] = vcpu_exit_fw_cfg; - ioports_map[FW_CFG_IO_DMA_ADDR_HIGH] = vcpu_exit_fw_cfg_dma; - ioports_map[FW_CFG_IO_DMA_ADDR_LOW] = vcpu_exit_fw_cfg_dma; - - /* Initialize PCI */ - for (i = VM_PCI_IO_BAR_BASE; i <= VM_PCI_IO_BAR_END; i++) - ioports_map[i] = vcpu_exit_pci; - - ioports_map[PCI_MODE1_ADDRESS_REG] = vcpu_exit_pci; - ioports_map[PCI_MODE1_DATA_REG] = vcpu_exit_pci; - ioports_map[PCI_MODE1_DATA_REG + 1] = vcpu_exit_pci; - ioports_map[PCI_MODE1_DATA_REG + 2] = vcpu_exit_pci; - ioports_map[PCI_MODE1_DATA_REG + 3] = vcpu_exit_pci; - pci_restore(fd); - virtio_restore(fd, current_vm, child_cdrom, child_disks, child_taps); -} - -/* * run_vm * * Runs the VM whose creation parameters are specified in vcp @@ -1525,7 +1042,7 @@ run_vm(struct vmop_create_params *vmc, struct vcpu_reg_state *vrs) return (ret); } -void * +static void * event_thread(void *arg) { uint8_t *donep = arg; @@ -1555,7 +1072,7 @@ event_thread(void *arg) * NULL: the VCPU shutdown properly * !NULL: error processing VCPU run, or the VCPU shutdown abnormally */ -void * +static void * vcpu_run_loop(void *arg) { struct vm_run_params *vrp = (struct vm_run_params *)arg; @@ -1593,7 +1110,7 @@ vcpu_run_loop(void *arg) return ((void *)ret); } - /* i8259 may be firing as we pause, release run mtx. */ + /* Interrupt may be firing, release run mtx. */ mutex_unlock(&vcpu_run_mtx[n]); ret = pthread_cond_wait(&vcpu_unpause_cond[n], &vcpu_unpause_mtx[n]); @@ -1636,14 +1153,14 @@ vcpu_run_loop(void *arg) break; } - if (vrp->vrp_irqready && i8259_is_pending()) { - vrp->vrp_inject.vie_vector = i8259_ack(); + if (vrp->vrp_irqready && intr_pending(current_vm)) { + vrp->vrp_inject.vie_vector = intr_ack(current_vm); vrp->vrp_inject.vie_type = VCPU_INJECT_INTR; } else vrp->vrp_inject.vie_type = VCPU_INJECT_NONE; /* Still more interrupts pending? */ - vrp->vrp_intr_pending = i8259_is_pending(); + vrp->vrp_intr_pending = intr_pending(current_vm); if (ioctl(env->vmd_fd, VMM_IOC_RUN, vrp) == -1) { /* If run ioctl failed, exit */ @@ -1682,7 +1199,7 @@ vcpu_run_loop(void *arg) } int -vcpu_pic_intr(uint32_t vm_id, uint32_t vcpu_id, uint8_t intr) +vcpu_intr(uint32_t vm_id, uint32_t vcpu_id, uint8_t intr) { struct vm_intr_params vip; @@ -1698,503 +1215,6 @@ vcpu_pic_intr(uint32_t vm_id, uint32_t vcpu_id, uint8_t intr) return (0); } -/* - * vcpu_exit_pci - * - * Handle all I/O to the emulated PCI subsystem. - * - * Parameters: - * vrp: vcpu run parameters containing guest state for this exit - * - * Return value: - * Interrupt to inject to the guest VM, or 0xFF if no interrupt should - * be injected. - */ -uint8_t -vcpu_exit_pci(struct vm_run_params *vrp) -{ - struct vm_exit *vei = vrp->vrp_exit; - uint8_t intr; - - intr = 0xFF; - - switch (vei->vei.vei_port) { - case PCI_MODE1_ADDRESS_REG: - pci_handle_address_reg(vrp); - break; - case PCI_MODE1_DATA_REG: - case PCI_MODE1_DATA_REG + 1: - case PCI_MODE1_DATA_REG + 2: - case PCI_MODE1_DATA_REG + 3: - pci_handle_data_reg(vrp); - break; - case VM_PCI_IO_BAR_BASE ... VM_PCI_IO_BAR_END: - intr = pci_handle_io(vrp); - break; - default: - log_warnx("%s: unknown PCI register 0x%llx", - __progname, (uint64_t)vei->vei.vei_port); - break; - } - - return (intr); -} - -/* - * vcpu_exit_inout - * - * Handle all I/O exits that need to be emulated in vmd. This includes the - * i8253 PIT, the com1 ns8250 UART, and the MC146818 RTC/NVRAM device. - * - * Parameters: - * vrp: vcpu run parameters containing guest state for this exit - */ -void -vcpu_exit_inout(struct vm_run_params *vrp) -{ - struct vm_exit *vei = vrp->vrp_exit; - uint8_t intr = 0xFF; - - if (vei->vei.vei_rep || vei->vei.vei_string) { -#ifdef MMIO_DEBUG - log_info("%s: %s%s%s %d-byte, enc=%d, data=0x%08x, port=0x%04x", - __func__, - vei->vei.vei_rep == 0 ? "" : "REP ", - vei->vei.vei_dir == VEI_DIR_IN ? "IN" : "OUT", - vei->vei.vei_string == 0 ? "" : "S", - vei->vei.vei_size, vei->vei.vei_encoding, - vei->vei.vei_data, vei->vei.vei_port); - log_info("%s: ECX = 0x%llx, RDX = 0x%llx, RSI = 0x%llx", - __func__, - vei->vrs.vrs_gprs[VCPU_REGS_RCX], - vei->vrs.vrs_gprs[VCPU_REGS_RDX], - vei->vrs.vrs_gprs[VCPU_REGS_RSI]); -#endif /* MMIO_DEBUG */ - fatalx("%s: can't emulate REP prefixed IN(S)/OUT(S)", - __func__); - } - - if (ioports_map[vei->vei.vei_port] != NULL) - intr = ioports_map[vei->vei.vei_port](vrp); - else if (vei->vei.vei_dir == VEI_DIR_IN) - set_return_data(vei, 0xFFFFFFFF); - - vei->vrs.vrs_gprs[VCPU_REGS_RIP] += vei->vei.vei_insn_len; - - if (intr != 0xFF) - vcpu_assert_pic_irq(vrp->vrp_vm_id, vrp->vrp_vcpu_id, intr); -} - -/* - * vcpu_exit_eptviolation - * - * handle an EPT Violation - * - * Parameters: - * vrp: vcpu run parameters containing guest state for this exit - * - * Return values: - * 0: no action required - * EFAULT: a protection fault occured, kill the vm. - */ -int -vcpu_exit_eptviolation(struct vm_run_params *vrp) -{ - struct vm_exit *ve = vrp->vrp_exit; - int ret = 0; -#if MMIO_NOTYET - struct x86_insn insn; - uint64_t va, pa; - size_t len = 15; /* Max instruction length in x86. */ -#endif /* MMIO_NOTYET */ - switch (ve->vee.vee_fault_type) { - case VEE_FAULT_HANDLED: - break; - -#if MMIO_NOTYET - case VEE_FAULT_MMIO_ASSIST: - /* Intel VMX might give us the length of the instruction. */ - if (ve->vee.vee_insn_info & VEE_LEN_VALID) - len = ve->vee.vee_insn_len; - - if (len > 15) - fatalx("%s: invalid instruction length %lu", __func__, - len); - - /* If we weren't given instruction bytes, we need to fetch. */ - if (!(ve->vee.vee_insn_info & VEE_BYTES_VALID)) { - memset(ve->vee.vee_insn_bytes, 0, - sizeof(ve->vee.vee_insn_bytes)); - va = ve->vrs.vrs_gprs[VCPU_REGS_RIP]; - - /* XXX Only support instructions that fit on 1 page. */ - if ((va & PAGE_MASK) + len > PAGE_SIZE) { - log_warnx("%s: instruction might cross page " - "boundary", __func__); - ret = EINVAL; - break; - } - - ret = translate_gva(ve, va, &pa, PROT_EXEC); - if (ret != 0) { - log_warnx("%s: failed gva translation", - __func__); - break; - } - - ret = read_mem(pa, ve->vee.vee_insn_bytes, len); - if (ret != 0) { - log_warnx("%s: failed to fetch instruction " - "bytes from 0x%llx", __func__, pa); - break; - } - } - - ret = insn_decode(ve, &insn); - if (ret == 0) - ret = insn_emulate(ve, &insn); - break; -#endif /* MMIO_NOTYET */ - - case VEE_FAULT_PROTECT: - log_debug("%s: EPT Violation: rip=0x%llx", __progname, - ve->vrs.vrs_gprs[VCPU_REGS_RIP]); - ret = EFAULT; - break; - - default: - fatalx("%s: invalid fault_type %d", __progname, - ve->vee.vee_fault_type); - /* UNREACHED */ - } - - return (ret); -} - -/* - * vcpu_exit - * - * Handle a vcpu exit. This function is called when it is determined that - * vmm(4) requires the assistance of vmd to support a particular guest - * exit type (eg, accessing an I/O port or device). Guest state is contained - * in 'vrp', and will be resent to vmm(4) on exit completion. - * - * Upon conclusion of handling the exit, the function determines if any - * interrupts should be injected into the guest, and asserts the proper - * IRQ line whose interrupt should be vectored. - * - * Parameters: - * vrp: vcpu run parameters containing guest state for this exit - * - * Return values: - * 0: the exit was handled successfully - * 1: an error occurred (eg, unknown exit reason passed in 'vrp') - */ -int -vcpu_exit(struct vm_run_params *vrp) -{ - int ret; - - switch (vrp->vrp_exit_reason) { - case VMX_EXIT_INT_WINDOW: - case SVM_VMEXIT_VINTR: - case VMX_EXIT_CPUID: - case VMX_EXIT_EXTINT: - case SVM_VMEXIT_INTR: - case SVM_VMEXIT_MSR: - case SVM_VMEXIT_CPUID: - /* - * We may be exiting to vmd to handle a pending interrupt but - * at the same time the last exit type may have been one of - * these. In this case, there's nothing extra to be done - * here (and falling through to the default case below results - * in more vmd log spam). - */ - break; - case SVM_VMEXIT_NPF: - case VMX_EXIT_EPT_VIOLATION: - ret = vcpu_exit_eptviolation(vrp); - if (ret) - return (ret); - break; - case VMX_EXIT_IO: - case SVM_VMEXIT_IOIO: - vcpu_exit_inout(vrp); - break; - case VMX_EXIT_HLT: - case SVM_VMEXIT_HLT: - mutex_lock(&vm_mtx); - vcpu_hlt[vrp->vrp_vcpu_id] = 1; - mutex_unlock(&vm_mtx); - break; - case VMX_EXIT_TRIPLE_FAULT: - case SVM_VMEXIT_SHUTDOWN: - /* reset VM */ - return (EAGAIN); - default: - log_debug("%s: unknown exit reason 0x%x", - __progname, vrp->vrp_exit_reason); - } - - return (0); -} - -/* - * find_gpa_range - * - * Search for a contiguous guest physical mem range. - * - * Parameters: - * vcp: VM create parameters that contain the memory map to search in - * gpa: the starting guest physical address - * len: the length of the memory range - * - * Return values: - * NULL: on failure if there is no memory range as described by the parameters - * Pointer to vm_mem_range that contains the start of the range otherwise. - */ -static struct vm_mem_range * -find_gpa_range(struct vm_create_params *vcp, paddr_t gpa, size_t len) -{ - size_t i, n; - struct vm_mem_range *vmr; - - /* Find the first vm_mem_range that contains gpa */ - for (i = 0; i < vcp->vcp_nmemranges; i++) { - vmr = &vcp->vcp_memranges[i]; - if (gpa < vmr->vmr_gpa + vmr->vmr_size) - break; - } - - /* No range found. */ - if (i == vcp->vcp_nmemranges) - return (NULL); - - /* - * vmr may cover the range [gpa, gpa + len) only partly. Make - * sure that the following vm_mem_ranges are contiguous and - * cover the rest. - */ - n = vmr->vmr_size - (gpa - vmr->vmr_gpa); - if (len < n) - len = 0; - else - len -= n; - gpa = vmr->vmr_gpa + vmr->vmr_size; - for (i = i + 1; len != 0 && i < vcp->vcp_nmemranges; i++) { - vmr = &vcp->vcp_memranges[i]; - if (gpa != vmr->vmr_gpa) - return (NULL); - if (len <= vmr->vmr_size) - len = 0; - else - len -= vmr->vmr_size; - - gpa = vmr->vmr_gpa + vmr->vmr_size; - } - - if (len != 0) - return (NULL); - - return (vmr); -} - -/* - * write_mem - * - * Copies data from 'buf' into the guest VM's memory at paddr 'dst'. - * - * Parameters: - * dst: the destination paddr_t in the guest VM - * buf: data to copy (or NULL to zero the data) - * len: number of bytes to copy - * - * Return values: - * 0: success - * EINVAL: if the guest physical memory range [dst, dst + len) does not - * exist in the guest. - */ -int -write_mem(paddr_t dst, const void *buf, size_t len) -{ - const char *from = buf; - char *to; - size_t n, off; - struct vm_mem_range *vmr; - - vmr = find_gpa_range(¤t_vm->vm_params.vmc_params, dst, len); - if (vmr == NULL) { - errno = EINVAL; - log_warn("%s: failed - invalid memory range dst = 0x%lx, " - "len = 0x%zx", __func__, dst, len); - return (EINVAL); - } - - off = dst - vmr->vmr_gpa; - while (len != 0) { - n = vmr->vmr_size - off; - if (len < n) - n = len; - - to = (char *)vmr->vmr_va + off; - if (buf == NULL) - memset(to, 0, n); - else { - memcpy(to, from, n); - from += n; - } - len -= n; - off = 0; - vmr++; - } - - return (0); -} - -/* - * read_mem - * - * Reads memory at guest paddr 'src' into 'buf'. - * - * Parameters: - * src: the source paddr_t in the guest VM to read from. - * buf: destination (local) buffer - * len: number of bytes to read - * - * Return values: - * 0: success - * EINVAL: if the guest physical memory range [dst, dst + len) does not - * exist in the guest. - */ -int -read_mem(paddr_t src, void *buf, size_t len) -{ - char *from, *to = buf; - size_t n, off; - struct vm_mem_range *vmr; - - vmr = find_gpa_range(¤t_vm->vm_params.vmc_params, src, len); - if (vmr == NULL) { - errno = EINVAL; - log_warn("%s: failed - invalid memory range src = 0x%lx, " - "len = 0x%zx", __func__, src, len); - return (EINVAL); - } - - off = src - vmr->vmr_gpa; - while (len != 0) { - n = vmr->vmr_size - off; - if (len < n) - n = len; - - from = (char *)vmr->vmr_va + off; - memcpy(to, from, n); - - to += n; - len -= n; - off = 0; - vmr++; - } - - return (0); -} - -/* - * hvaddr_mem - * - * Translate a guest physical address to a host virtual address, checking the - * provided memory range length to confirm it's contiguous within the same - * guest memory range (vm_mem_range). - * - * Parameters: - * gpa: guest physical address to translate - * len: number of bytes in the intended range - * - * Return values: - * void* to host virtual memory on success - * NULL on error, setting errno to: - * EFAULT: gpa falls outside guest memory ranges - * EINVAL: requested len extends beyond memory range - */ -void * -hvaddr_mem(paddr_t gpa, size_t len) -{ - struct vm_mem_range *vmr; - size_t off; - - vmr = find_gpa_range(¤t_vm->vm_params.vmc_params, gpa, len); - if (vmr == NULL) { - log_warnx("%s: failed - invalid gpa: 0x%lx\n", __func__, gpa); - errno = EFAULT; - return (NULL); - } - - off = gpa - vmr->vmr_gpa; - if (len > (vmr->vmr_size - off)) { - log_warnx("%s: failed - invalid memory range: gpa=0x%lx, " - "len=%zu", __func__, gpa, len); - errno = EINVAL; - return (NULL); - } - - return ((char *)vmr->vmr_va + off); -} - -/* - * vcpu_assert_pic_irq - * - * Injects the specified IRQ on the supplied vcpu/vm - * - * Parameters: - * vm_id: VM ID to inject to - * vcpu_id: VCPU ID to inject to - * irq: IRQ to inject - */ -void -vcpu_assert_pic_irq(uint32_t vm_id, uint32_t vcpu_id, int irq) -{ - int ret; - - i8259_assert_irq(irq); - - if (i8259_is_pending()) { - if (vcpu_pic_intr(vm_id, vcpu_id, 1)) - fatalx("%s: can't assert INTR", __func__); - - mutex_lock(&vm_mtx); - vcpu_hlt[vcpu_id] = 0; - mutex_unlock(&vm_mtx); - - mutex_lock(&vcpu_run_mtx[vcpu_id]); - ret = pthread_cond_signal(&vcpu_run_cond[vcpu_id]); - if (ret) - fatalx("%s: can't signal (%d)", __func__, ret); - mutex_unlock(&vcpu_run_mtx[vcpu_id]); - } -} - -/* - * vcpu_deassert_pic_irq - * - * Clears the specified IRQ on the supplied vcpu/vm - * - * Parameters: - * vm_id: VM ID to clear in - * vcpu_id: VCPU ID to clear in - * irq: IRQ to clear - */ -void -vcpu_deassert_pic_irq(uint32_t vm_id, uint32_t vcpu_id, int irq) -{ - i8259_deassert_irq(irq); - - if (!i8259_is_pending()) { - if (vcpu_pic_intr(vm_id, vcpu_id, 0)) - fatalx("%s: can't deassert INTR for vm_id %d, " - "vcpu_id %d", __func__, vm_id, vcpu_id); - } -} - /* * fd_hasdata * @@ -2258,203 +1278,6 @@ mutex_unlock(pthread_mutex_t *m) } } -/* - * set_return_data - * - * Utility function for manipulating register data in vm exit info structs. This - * function ensures that the data is copied to the vei->vei.vei_data field with - * the proper size for the operation being performed. - * - * Parameters: - * vei: exit information - * data: return data - */ -void -set_return_data(struct vm_exit *vei, uint32_t data) -{ - switch (vei->vei.vei_size) { - case 1: - vei->vei.vei_data &= ~0xFF; - vei->vei.vei_data |= (uint8_t)data; - break; - case 2: - vei->vei.vei_data &= ~0xFFFF; - vei->vei.vei_data |= (uint16_t)data; - break; - case 4: - vei->vei.vei_data = data; - break; - } -} - -/* - * get_input_data - * - * Utility function for manipulating register data in vm exit info - * structs. This function ensures that the data is copied from the - * vei->vei.vei_data field with the proper size for the operation being - * performed. - * - * Parameters: - * vei: exit information - * data: location to store the result - */ -void -get_input_data(struct vm_exit *vei, uint32_t *data) -{ - switch (vei->vei.vei_size) { - case 1: - *data &= 0xFFFFFF00; - *data |= (uint8_t)vei->vei.vei_data; - break; - case 2: - *data &= 0xFFFF0000; - *data |= (uint16_t)vei->vei.vei_data; - break; - case 4: - *data = vei->vei.vei_data; - break; - default: - log_warnx("%s: invalid i/o size %d", __func__, - vei->vei.vei_size); - } - -} - -/* - * translate_gva - * - * Translates a guest virtual address to a guest physical address by walking - * the currently active page table (if needed). - * - * XXX ensure translate_gva updates the A bit in the PTE - * XXX ensure translate_gva respects segment base and limits in i386 mode - * XXX ensure translate_gva respects segment wraparound in i8086 mode - * XXX ensure translate_gva updates the A bit in the segment selector - * XXX ensure translate_gva respects CR4.LMSLE if available - * - * Parameters: - * exit: The VCPU this translation should be performed for (guest MMU settings - * are gathered from this VCPU) - * va: virtual address to translate - * pa: pointer to paddr_t variable that will receive the translated physical - * address. 'pa' is unchanged on error. - * mode: one of PROT_READ, PROT_WRITE, PROT_EXEC indicating the mode in which - * the address should be translated - * - * Return values: - * 0: the address was successfully translated - 'pa' contains the physical - * address currently mapped by 'va'. - * EFAULT: the PTE for 'VA' is unmapped. A #PF will be injected in this case - * and %cr2 set in the vcpu structure. - * EINVAL: an error occurred reading paging table structures - */ -int -translate_gva(struct vm_exit* exit, uint64_t va, uint64_t* pa, int mode) -{ - int level, shift, pdidx; - uint64_t pte, pt_paddr, pte_paddr, mask, low_mask, high_mask; - uint64_t shift_width, pte_size; - struct vcpu_reg_state *vrs; - - vrs = &exit->vrs; - - if (!pa) - return (EINVAL); - - if (!(vrs->vrs_crs[VCPU_REGS_CR0] & CR0_PG)) { - log_debug("%s: unpaged, va=pa=0x%llx", __func__, va); - *pa = va; - return (0); - } - - pt_paddr = vrs->vrs_crs[VCPU_REGS_CR3]; - - log_debug("%s: guest %%cr0=0x%llx, %%cr3=0x%llx", __func__, - vrs->vrs_crs[VCPU_REGS_CR0], vrs->vrs_crs[VCPU_REGS_CR3]); - - if (vrs->vrs_crs[VCPU_REGS_CR0] & CR0_PE) { - if (vrs->vrs_crs[VCPU_REGS_CR4] & CR4_PAE) { - pte_size = sizeof(uint64_t); - shift_width = 9; - - if (vrs->vrs_msrs[VCPU_REGS_EFER] & EFER_LMA) { - /* 4 level paging */ - level = 4; - mask = L4_MASK; - shift = L4_SHIFT; - } else { - /* 32 bit with PAE paging */ - level = 3; - mask = L3_MASK; - shift = L3_SHIFT; - } - } else { - /* 32 bit paging */ - level = 2; - shift_width = 10; - mask = 0xFFC00000; - shift = 22; - pte_size = sizeof(uint32_t); - } - } else - return (EINVAL); - - /* XXX: Check for R bit in segment selector and set A bit */ - - for (;level > 0; level--) { - pdidx = (va & mask) >> shift; - pte_paddr = (pt_paddr) + (pdidx * pte_size); - - log_debug("%s: read pte level %d @ GPA 0x%llx", __func__, - level, pte_paddr); - if (read_mem(pte_paddr, &pte, pte_size)) { - log_warn("%s: failed to read pte", __func__); - return (EFAULT); - } - - log_debug("%s: PTE @ 0x%llx = 0x%llx", __func__, pte_paddr, - pte); - - /* XXX: Set CR2 */ - if (!(pte & PG_V)) - return (EFAULT); - - /* XXX: Check for SMAP */ - if ((mode == PROT_WRITE) && !(pte & PG_RW)) - return (EPERM); - - if ((exit->cpl > 0) && !(pte & PG_u)) - return (EPERM); - - pte = pte | PG_U; - if (mode == PROT_WRITE) - pte = pte | PG_M; - if (write_mem(pte_paddr, &pte, pte_size)) { - log_warn("%s: failed to write back flags to pte", - __func__); - return (EIO); - } - - /* XXX: EINVAL if in 32bit and PG_PS is 1 but CR4.PSE is 0 */ - if (pte & PG_PS) - break; - - if (level > 1) { - pt_paddr = pte & PG_FRAME; - shift -= shift_width; - mask = mask >> shift_width; - } - } - - low_mask = (1 << shift) - 1; - high_mask = (((uint64_t)1ULL << ((pte_size * 8) - 1)) - 1) ^ low_mask; - *pa = (pte & high_mask) | (va & low_mask); - - log_debug("%s: final GPA for GVA 0x%llx = 0x%llx\n", __func__, va, *pa); - - return (0); -} void vm_pipe_init(struct vm_dev_pipe *p, void (*cb)(int, short, void *)) @@ -2619,3 +1442,31 @@ remap_guest_mem(struct vmd_vm *vm, int vmm_fd) return (0); } + +void +vcpu_halt(uint32_t vcpu_id) +{ + mutex_lock(&vm_mtx); + vcpu_hlt[vcpu_id] = 1; + mutex_unlock(&vm_mtx); +} + +void +vcpu_unhalt(uint32_t vcpu_id) + { + mutex_lock(&vm_mtx); + vcpu_hlt[vcpu_id] = 0; + mutex_unlock(&vm_mtx); +} + +void +vcpu_signal_run(uint32_t vcpu_id) +{ + int ret; + + mutex_lock(&vcpu_run_mtx[vcpu_id]); + ret = pthread_cond_signal(&vcpu_run_cond[vcpu_id]); + if (ret) + fatalx("%s: can't signal (%d)", __func__, ret); + mutex_unlock(&vcpu_run_mtx[vcpu_id]); +} diff --git a/usr.sbin/vmd/vmd.c b/usr.sbin/vmd/vmd.c index 3c053ae08..232bc82d8 100644 --- a/usr.sbin/vmd/vmd.c +++ b/usr.sbin/vmd/vmd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmd.c,v 1.158 2024/07/09 09:31:37 dv Exp $ */ +/* $OpenBSD: vmd.c,v 1.159 2024/07/10 09:27:33 dv Exp $ */ /* * Copyright (c) 2015 Reyk Floeter @@ -41,7 +41,6 @@ #include #include -#include #include "proc.h" #include "atomicio.h" @@ -613,134 +612,6 @@ vmd_dispatch_priv(int fd, struct privsep_proc *p, struct imsg *imsg) return (0); } -int -vmd_check_vmh(struct vm_dump_header *vmh) -{ - int i; - unsigned int code, leaf; - unsigned int a, b, c, d; - - if (strncmp(vmh->vmh_signature, VM_DUMP_SIGNATURE, strlen(VM_DUMP_SIGNATURE)) != 0) { - log_warnx("%s: incompatible dump signature", __func__); - return (-1); - } - - if (vmh->vmh_version != VM_DUMP_VERSION) { - log_warnx("%s: incompatible dump version", __func__); - return (-1); - } - - for (i = 0; i < VM_DUMP_HEADER_CPUID_COUNT; i++) { - code = vmh->vmh_cpuids[i].code; - leaf = vmh->vmh_cpuids[i].leaf; - if (leaf != 0x00) { - log_debug("%s: invalid leaf 0x%x for code 0x%x", - __func__, leaf, code); - return (-1); - } - - switch (code) { - case 0x00: - CPUID_LEAF(code, leaf, a, b, c, d); - if (vmh->vmh_cpuids[i].a > a) { - log_debug("%s: incompatible cpuid level", - __func__); - return (-1); - } - if (!(vmh->vmh_cpuids[i].b == b && - vmh->vmh_cpuids[i].c == c && - vmh->vmh_cpuids[i].d == d)) { - log_debug("%s: incompatible cpu brand", - __func__); - return (-1); - } - break; - - case 0x01: - CPUID_LEAF(code, leaf, a, b, c, d); - if ((vmh->vmh_cpuids[i].c & c & VMM_CPUIDECX_MASK) != - (vmh->vmh_cpuids[i].c & VMM_CPUIDECX_MASK)) { - log_debug("%s: incompatible cpu features " - "code: 0x%x leaf: 0x%x reg: c", __func__, - code, leaf); - return (-1); - } - if ((vmh->vmh_cpuids[i].d & d & VMM_CPUIDEDX_MASK) != - (vmh->vmh_cpuids[i].d & VMM_CPUIDEDX_MASK)) { - log_debug("%s: incompatible cpu features " - "code: 0x%x leaf: 0x%x reg: d", __func__, - code, leaf); - return (-1); - } - break; - - case 0x07: - CPUID_LEAF(code, leaf, a, b, c, d); - if ((vmh->vmh_cpuids[i].b & b & VMM_SEFF0EBX_MASK) != - (vmh->vmh_cpuids[i].b & VMM_SEFF0EBX_MASK)) { - log_debug("%s: incompatible cpu features " - "code: 0x%x leaf: 0x%x reg: c", __func__, - code, leaf); - return (-1); - } - if ((vmh->vmh_cpuids[i].c & c & VMM_SEFF0ECX_MASK) != - (vmh->vmh_cpuids[i].c & VMM_SEFF0ECX_MASK)) { - log_debug("%s: incompatible cpu features " - "code: 0x%x leaf: 0x%x reg: d", __func__, - code, leaf); - return (-1); - } - break; - - case 0x0d: - CPUID_LEAF(code, leaf, a, b, c, d); - if (vmh->vmh_cpuids[i].b > b) { - log_debug("%s: incompatible cpu: insufficient " - "max save area for enabled XCR0 features", - __func__); - return (-1); - } - if (vmh->vmh_cpuids[i].c > c) { - log_debug("%s: incompatible cpu: insufficient " - "max save area for supported XCR0 features", - __func__); - return (-1); - } - break; - - case 0x80000001: - CPUID_LEAF(code, leaf, a, b, c, d); - if ((vmh->vmh_cpuids[i].a & a) != - vmh->vmh_cpuids[i].a) { - log_debug("%s: incompatible cpu features " - "code: 0x%x leaf: 0x%x reg: a", __func__, - code, leaf); - return (-1); - } - if ((vmh->vmh_cpuids[i].c & c) != - vmh->vmh_cpuids[i].c) { - log_debug("%s: incompatible cpu features " - "code: 0x%x leaf: 0x%x reg: c", __func__, - code, leaf); - return (-1); - } - if ((vmh->vmh_cpuids[i].d & d) != - vmh->vmh_cpuids[i].d) { - log_debug("%s: incompatible cpu features " - "code: 0x%x leaf: 0x%x reg: d", __func__, - code, leaf); - return (-1); - } - break; - - default: - log_debug("%s: unknown code 0x%x", __func__, code); - return (-1); - } - } - - return (0); -} void vmd_sighdlr(int sig, short event, void *arg) diff --git a/usr.sbin/vmd/vmd.h b/usr.sbin/vmd/vmd.h index 4f1b05e70..2f2056541 100644 --- a/usr.sbin/vmd/vmd.h +++ b/usr.sbin/vmd/vmd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmd.h,v 1.126 2024/07/09 09:31:37 dv Exp $ */ +/* $OpenBSD: vmd.h,v 1.127 2024/07/10 09:27:33 dv Exp $ */ /* * Copyright (c) 2015 Mike Larkin @@ -43,6 +43,9 @@ #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) +#define MB(x) (x * 1024UL * 1024UL) +#define GB(x) (x * 1024UL * 1024UL * 1024UL) + #define VMD_USER "_vmd" #define VMD_CONF "/etc/vm.conf" #define SOCKET_NAME "/var/run/vmd.sock" @@ -492,21 +495,51 @@ int opentap(char *); int fd_hasdata(int); int vmm_pipe(struct vmd_vm *, int, void (*)(int, short, void *)); -/* vm.c */ +/* {mach}_vm.c (md interface) */ +void create_memory_map(struct vm_create_params *); +int load_firmware(struct vmd_vm *, struct vcpu_reg_state *); +void init_emulated_hw(struct vmop_create_params *, int, + int[][VM_MAX_BASE_PER_DISK], int *); +void restore_emulated_hw(struct vm_create_params *vcp, int, int *, + int[][VM_MAX_BASE_PER_DISK], int); +int vcpu_reset(uint32_t, uint32_t, struct vcpu_reg_state *); +void pause_vm_md(struct vmd_vm *); +void unpause_vm_md(struct vmd_vm *); +int dump_devs(int); +int dump_send_header(int); +void *hvaddr_mem(paddr_t, size_t); +int write_mem(paddr_t, const void *, size_t); +int read_mem(paddr_t, void *, size_t); +int intr_ack(struct vmd_vm *); +int intr_pending(struct vmd_vm *); +void intr_toggle_el(struct vmd_vm *, int, int); +void vcpu_assert_irq(uint32_t, uint32_t, int); +void vcpu_deassert_irq(uint32_t, uint32_t, int); +int vcpu_exit(struct vm_run_params *); +uint8_t vcpu_exit_pci(struct vm_run_params *); + +#ifdef __amd64__ +/* x86 io functions in x86_vm.c */ +void set_return_data(struct vm_exit *, uint32_t); +void get_input_data(struct vm_exit *, uint32_t *); +#endif /* __amd64 __ */ + +/* vm.c (mi functions) */ +void vcpu_halt(uint32_t); +void vcpu_unhalt(uint32_t); +void vcpu_signal_run(uint32_t); +int vcpu_intr(uint32_t, uint32_t, uint8_t); void vm_main(int, int); void mutex_lock(pthread_mutex_t *); void mutex_unlock(pthread_mutex_t *); -int read_mem(paddr_t, void *buf, size_t); -int start_vm(struct vmd_vm *, int); -__dead void vm_shutdown(unsigned int); +int vmd_check_vmh(struct vm_dump_header *); void vm_pipe_init(struct vm_dev_pipe *, void (*)(int, short, void *)); void vm_pipe_init2(struct vm_dev_pipe *, void (*)(int, short, void *), void *); void vm_pipe_send(struct vm_dev_pipe *, enum pipe_msg_type); enum pipe_msg_type vm_pipe_recv(struct vm_dev_pipe *); -int write_mem(paddr_t, const void *buf, size_t); -void* hvaddr_mem(paddr_t, size_t); int remap_guest_mem(struct vmd_vm *, int); +__dead void vm_shutdown(unsigned int); /* config.c */ int config_init(struct vmd *); diff --git a/usr.sbin/vmd/vmm.c b/usr.sbin/vmd/vmm.c index 70c94c0df..6a98e43f7 100644 --- a/usr.sbin/vmd/vmm.c +++ b/usr.sbin/vmd/vmm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmm.c,v 1.120 2024/07/09 09:31:37 dv Exp $ */ +/* $OpenBSD: vmm.c,v 1.121 2024/07/10 09:27:33 dv Exp $ */ /* * Copyright (c) 2015 Mike Larkin @@ -30,9 +30,6 @@ #include #include -#include -#include - #include #include @@ -50,7 +47,6 @@ #include #include "vmd.h" -#include "vmm.h" #include "atomicio.h" #include "proc.h" diff --git a/usr.sbin/vmd/x86_mmio.c b/usr.sbin/vmd/x86_mmio.c new file mode 100644 index 000000000..381df30e4 --- /dev/null +++ b/usr.sbin/vmd/x86_mmio.c @@ -0,0 +1,1045 @@ +/* $OpenBSD: x86_mmio.c,v 1.1 2024/07/10 10:41:19 dv Exp $ */ +/* + * Copyright (c) 2022 Dave Voutila + * + * 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 +#include + +#include +#include + +#include "vmd.h" +#include "mmio.h" + +#define MMIO_DEBUG 0 + +extern char* __progname; + +struct x86_decode_state { + uint8_t s_bytes[15]; + size_t s_len; + size_t s_idx; +}; + +enum decode_result { + DECODE_ERROR = 0, /* Something went wrong. */ + DECODE_DONE, /* Decode success and no more work needed. */ + DECODE_MORE, /* Decode success and more work required. */ +}; + +static const char *str_cpu_mode(int); +static const char *str_decode_res(enum decode_result); +static const char *str_opcode(struct x86_opcode *); +static const char *str_operand_enc(struct x86_opcode *); +static const char *str_reg(int); +static const char *str_sreg(int); +static int detect_cpu_mode(struct vcpu_reg_state *); + +static enum decode_result decode_prefix(struct x86_decode_state *, + struct x86_insn *); +static enum decode_result decode_opcode(struct x86_decode_state *, + struct x86_insn *); +static enum decode_result decode_modrm(struct x86_decode_state *, + struct x86_insn *); +static int get_modrm_reg(struct x86_insn *); +static int get_modrm_addr(struct x86_insn *, struct vcpu_reg_state *vrs); +static enum decode_result decode_disp(struct x86_decode_state *, + struct x86_insn *); +static enum decode_result decode_sib(struct x86_decode_state *, + struct x86_insn *); +static enum decode_result decode_imm(struct x86_decode_state *, + struct x86_insn *); + +static enum decode_result peek_byte(struct x86_decode_state *, uint8_t *); +static enum decode_result next_byte(struct x86_decode_state *, uint8_t *); +static enum decode_result next_value(struct x86_decode_state *, size_t, + uint64_t *); +static int is_valid_state(struct x86_decode_state *, const char *); + +static int emulate_mov(struct x86_insn *, struct vm_exit *); +static int emulate_movzx(struct x86_insn *, struct vm_exit *); + +/* Lookup table for 1-byte opcodes, in opcode alphabetical order. */ +const enum x86_opcode_type x86_1byte_opcode_tbl[255] = { + /* MOV */ + [0x88] = OP_MOV, + [0x89] = OP_MOV, + [0x8A] = OP_MOV, + [0x8B] = OP_MOV, + [0x8C] = OP_MOV, + [0xA0] = OP_MOV, + [0xA1] = OP_MOV, + [0xA2] = OP_MOV, + [0xA3] = OP_MOV, + + /* MOVS */ + [0xA4] = OP_UNSUPPORTED, + [0xA5] = OP_UNSUPPORTED, + + [ESCAPE] = OP_TWO_BYTE, +}; + +/* Lookup table for 1-byte operand encodings, in opcode alphabetical order. */ +const enum x86_operand_enc x86_1byte_operand_enc_tbl[255] = { + /* MOV */ + [0x88] = OP_ENC_MR, + [0x89] = OP_ENC_MR, + [0x8A] = OP_ENC_RM, + [0x8B] = OP_ENC_RM, + [0x8C] = OP_ENC_MR, + [0xA0] = OP_ENC_FD, + [0xA1] = OP_ENC_FD, + [0xA2] = OP_ENC_TD, + [0xA3] = OP_ENC_TD, + + /* MOVS */ + [0xA4] = OP_ENC_ZO, + [0xA5] = OP_ENC_ZO, +}; + +const enum x86_opcode_type x86_2byte_opcode_tbl[255] = { + /* MOVZX */ + [0xB6] = OP_MOVZX, + [0xB7] = OP_MOVZX, +}; + +const enum x86_operand_enc x86_2byte_operand_enc_table[255] = { + /* MOVZX */ + [0xB6] = OP_ENC_RM, + [0xB7] = OP_ENC_RM, +}; + +/* + * peek_byte + * + * Fetch the next byte fron the instruction bytes without advancing the + * position in the stream. + * + * Return values: + * DECODE_DONE: byte was found and is the last in the stream + * DECODE_MORE: byte was found and there are more remaining to be read + * DECODE_ERROR: state is invalid and not byte was found, *byte left unchanged + */ +static enum decode_result +peek_byte(struct x86_decode_state *state, uint8_t *byte) +{ + enum decode_result res; + + if (state == NULL) + return (DECODE_ERROR); + + if (state->s_idx == state->s_len) + return (DECODE_ERROR); + + if (state->s_idx + 1 == state->s_len) + res = DECODE_DONE; + else + res = DECODE_MORE; + + if (byte != NULL) + *byte = state->s_bytes[state->s_idx]; + return (res); +} + +/* + * next_byte + * + * Fetch the next byte fron the instruction bytes, advancing the position in the + * stream and mutating decode state. + * + * Return values: + * DECODE_DONE: byte was found and is the last in the stream + * DECODE_MORE: byte was found and there are more remaining to be read + * DECODE_ERROR: state is invalid and not byte was found, *byte left unchanged + */ +static enum decode_result +next_byte(struct x86_decode_state *state, uint8_t *byte) +{ + uint8_t next; + + /* Cheat and see if we're going to fail. */ + if (peek_byte(state, &next) == DECODE_ERROR) + return (DECODE_ERROR); + + if (byte != NULL) + *byte = next; + state->s_idx++; + + return (state->s_idx < state->s_len ? DECODE_MORE : DECODE_DONE); +} + +/* + * Fetch the next `n' bytes as a single uint64_t value. + */ +static enum decode_result +next_value(struct x86_decode_state *state, size_t n, uint64_t *value) +{ + uint8_t bytes[8]; + size_t i; + enum decode_result res; + + if (value == NULL) + return (DECODE_ERROR); + + if (n == 0 || n > sizeof(bytes)) + return (DECODE_ERROR); + + memset(bytes, 0, sizeof(bytes)); + for (i = 0; i < n; i++) + if ((res = next_byte(state, &bytes[i])) == DECODE_ERROR) + return (DECODE_ERROR); + + *value = *((uint64_t*)bytes); + + return (res); +} + +/* + * is_valid_state + * + * Validate the decode state looks viable. + * + * Returns: + * 1: if state is valid + * 0: if an invariant is detected + */ +static int +is_valid_state(struct x86_decode_state *state, const char *fn_name) +{ + const char *s = (fn_name != NULL) ? fn_name : __func__; + + if (state == NULL) { + log_warnx("%s: null state", s); + return (0); + } + if (state->s_len > sizeof(state->s_bytes)) { + log_warnx("%s: invalid length", s); + return (0); + } + if (state->s_idx + 1 > state->s_len) { + log_warnx("%s: invalid index", s); + return (0); + } + + return (1); +} + +#ifdef MMIO_DEBUG +static void +dump_regs(struct vcpu_reg_state *vrs) +{ + size_t i; + struct vcpu_segment_info *vsi; + + for (i = 0; i < VCPU_REGS_NGPRS; i++) + log_info("%s: %s 0x%llx", __progname, str_reg(i), + vrs->vrs_gprs[i]); + + for (i = 0; i < VCPU_REGS_NSREGS; i++) { + vsi = &vrs->vrs_sregs[i]; + log_info("%s: %s { sel: 0x%04x, lim: 0x%08x, ar: 0x%08x, " + "base: 0x%llx }", __progname, str_sreg(i), + vsi->vsi_sel, vsi->vsi_limit, vsi->vsi_ar, vsi->vsi_base); + } +} + +static void +dump_insn(struct x86_insn *insn) +{ + log_info("instruction { %s, enc=%s, len=%d, mod=0x%02x, (" + "reg=%s, addr=0x%lx) sib=0x%02x }", + str_opcode(&insn->insn_opcode), + str_operand_enc(&insn->insn_opcode), insn->insn_bytes_len, + insn->insn_modrm, str_reg(insn->insn_reg), + insn->insn_gva, insn->insn_sib); +} +#endif /* MMIO_DEBUG */ + +static const char * +str_cpu_mode(int mode) +{ + switch (mode) { + case VMM_CPU_MODE_REAL: return "REAL"; + case VMM_CPU_MODE_PROT: return "PROT"; + case VMM_CPU_MODE_PROT32: return "PROT32"; + case VMM_CPU_MODE_COMPAT: return "COMPAT"; + case VMM_CPU_MODE_LONG: return "LONG"; + default: return "UKNOWN"; + } +} + +__unused static const char * +str_decode_res(enum decode_result res) { + switch (res) { + case DECODE_DONE: return "DONE"; + case DECODE_MORE: return "MORE"; + case DECODE_ERROR: return "ERROR"; + default: return "UNKNOWN"; + } +} + +static const char * +str_opcode(struct x86_opcode *opcode) +{ + switch (opcode->op_type) { + case OP_IN: return "IN"; + case OP_INS: return "INS"; + case OP_MOV: return "MOV"; + case OP_MOVZX: return "MOVZX"; + case OP_OUT: return "OUT"; + case OP_OUTS: return "OUTS"; + case OP_UNSUPPORTED: return "UNSUPPORTED"; + default: return "UNKNOWN"; + } +} + +static const char * +str_operand_enc(struct x86_opcode *opcode) +{ + switch (opcode->op_encoding) { + case OP_ENC_I: return "I"; + case OP_ENC_MI: return "MI"; + case OP_ENC_MR: return "MR"; + case OP_ENC_RM: return "RM"; + case OP_ENC_FD: return "FD"; + case OP_ENC_TD: return "TD"; + case OP_ENC_OI: return "OI"; + case OP_ENC_ZO: return "ZO"; + default: return "UNKNOWN"; + } +} + +static const char * +str_reg(int reg) { + switch (reg) { + case VCPU_REGS_RAX: return "RAX"; + case VCPU_REGS_RCX: return "RCX"; + case VCPU_REGS_RDX: return "RDX"; + case VCPU_REGS_RBX: return "RBX"; + case VCPU_REGS_RSI: return "RSI"; + case VCPU_REGS_RDI: return "RDI"; + case VCPU_REGS_R8: return " R8"; + case VCPU_REGS_R9: return " R9"; + case VCPU_REGS_R10: return "R10"; + case VCPU_REGS_R11: return "R11"; + case VCPU_REGS_R12: return "R12"; + case VCPU_REGS_R13: return "R13"; + case VCPU_REGS_R14: return "R14"; + case VCPU_REGS_R15: return "R15"; + case VCPU_REGS_RSP: return "RSP"; + case VCPU_REGS_RBP: return "RBP"; + case VCPU_REGS_RIP: return "RIP"; + case VCPU_REGS_RFLAGS: return "RFLAGS"; + default: return "UNKNOWN"; + } +} + +static const char * +str_sreg(int sreg) { + switch (sreg) { + case VCPU_REGS_CS: return "CS"; + case VCPU_REGS_DS: return "DS"; + case VCPU_REGS_ES: return "ES"; + case VCPU_REGS_FS: return "FS"; + case VCPU_REGS_GS: return "GS"; + case VCPU_REGS_SS: return "GS"; + case VCPU_REGS_LDTR: return "LDTR"; + case VCPU_REGS_TR: return "TR"; + default: return "UKNOWN"; + } +} + +static int +detect_cpu_mode(struct vcpu_reg_state *vrs) +{ + uint64_t cr0, cr4, cs, efer, rflags; + + /* Is protected mode enabled? */ + cr0 = vrs->vrs_crs[VCPU_REGS_CR0]; + if (!(cr0 & CR0_PE)) + return (VMM_CPU_MODE_REAL); + + cr4 = vrs->vrs_crs[VCPU_REGS_CR4]; + cs = vrs->vrs_sregs[VCPU_REGS_CS].vsi_ar; + efer = vrs->vrs_msrs[VCPU_REGS_EFER]; + rflags = vrs->vrs_gprs[VCPU_REGS_RFLAGS]; + + /* Check for Long modes. */ + if ((efer & EFER_LME) && (cr4 & CR4_PAE) && (cr0 & CR0_PG)) { + if (cs & CS_L) { + /* Long Modes */ + if (!(cs & CS_D)) + return (VMM_CPU_MODE_LONG); + log_warnx("%s: invalid cpu mode", __progname); + return (VMM_CPU_MODE_UNKNOWN); + } else { + /* Compatibility Modes */ + if (cs & CS_D) /* XXX Add Compat32 mode */ + return (VMM_CPU_MODE_UNKNOWN); + return (VMM_CPU_MODE_COMPAT); + } + } + + /* Check for 32-bit Protected Mode. */ + if (cs & CS_D) + return (VMM_CPU_MODE_PROT32); + + /* Check for virtual 8086 mode. */ + if (rflags & EFLAGS_VM) { + /* XXX add Virtual8086 mode */ + log_warnx("%s: Virtual 8086 mode", __progname); + return (VMM_CPU_MODE_UNKNOWN); + } + + /* Can't determine mode. */ + log_warnx("%s: invalid cpu mode", __progname); + return (VMM_CPU_MODE_UNKNOWN); +} + +static enum decode_result +decode_prefix(struct x86_decode_state *state, struct x86_insn *insn) +{ + enum decode_result res = DECODE_ERROR; + struct x86_prefix *prefix; + uint8_t byte; + + if (!is_valid_state(state, __func__) || insn == NULL) + return (-1); + + prefix = &insn->insn_prefix; + memset(prefix, 0, sizeof(*prefix)); + + /* + * Decode prefixes. The last of its kind wins. The behavior is undefined + * in the Intel SDM (see Vol 2, 2.1.1 Instruction Prefixes.) + */ + while ((res = peek_byte(state, &byte)) != DECODE_ERROR) { + switch (byte) { + case LEG_1_LOCK: + case LEG_1_REPNE: + case LEG_1_REP: + prefix->pfx_group1 = byte; + break; + case LEG_2_CS: + case LEG_2_SS: + case LEG_2_DS: + case LEG_2_ES: + case LEG_2_FS: + case LEG_2_GS: + prefix->pfx_group2 = byte; + break; + case LEG_3_OPSZ: + prefix->pfx_group3 = byte; + break; + case LEG_4_ADDRSZ: + prefix->pfx_group4 = byte; + break; + case REX_BASE...REX_BASE + 0x0F: + if (insn->insn_cpu_mode == VMM_CPU_MODE_LONG) + prefix->pfx_rex = byte; + else /* INC encountered */ + return (DECODE_ERROR); + break; + case VEX_2_BYTE: + case VEX_3_BYTE: + log_warnx("%s: VEX not supported", __func__); + return (DECODE_ERROR); + default: + /* Something other than a valid prefix. */ + return (DECODE_MORE); + } + /* Advance our position. */ + next_byte(state, NULL); + } + + return (res); +} + +static enum decode_result +decode_modrm(struct x86_decode_state *state, struct x86_insn *insn) +{ + enum decode_result res; + uint8_t byte = 0; + + if (!is_valid_state(state, __func__) || insn == NULL) + return (DECODE_ERROR); + + insn->insn_modrm_valid = 0; + + /* Check the operand encoding to see if we fetch a byte or abort. */ + switch (insn->insn_opcode.op_encoding) { + case OP_ENC_MR: + case OP_ENC_RM: + case OP_ENC_MI: + res = next_byte(state, &byte); + if (res == DECODE_ERROR) { + log_warnx("%s: failed to get modrm byte", __func__); + break; + } + insn->insn_modrm = byte; + insn->insn_modrm_valid = 1; + break; + + case OP_ENC_I: + case OP_ENC_OI: + log_warnx("%s: instruction does not need memory assist", + __func__); + res = DECODE_ERROR; + break; + + default: + /* Peek to see if we're done decode. */ + res = peek_byte(state, NULL); + } + + return (res); +} + +static int +get_modrm_reg(struct x86_insn *insn) +{ + if (insn == NULL) + return (-1); + + if (insn->insn_modrm_valid) { + switch (MODRM_REGOP(insn->insn_modrm)) { + case 0: + insn->insn_reg = VCPU_REGS_RAX; + break; + case 1: + insn->insn_reg = VCPU_REGS_RCX; + break; + case 2: + insn->insn_reg = VCPU_REGS_RDX; + break; + case 3: + insn->insn_reg = VCPU_REGS_RBX; + break; + case 4: + insn->insn_reg = VCPU_REGS_RSP; + break; + case 5: + insn->insn_reg = VCPU_REGS_RBP; + break; + case 6: + insn->insn_reg = VCPU_REGS_RSI; + break; + case 7: + insn->insn_reg = VCPU_REGS_RDI; + break; + } + } + + /* REX R bit selects extended registers in LONG mode. */ + if (insn->insn_prefix.pfx_rex & REX_R) + insn->insn_reg += 8; + + return (0); +} + +static int +get_modrm_addr(struct x86_insn *insn, struct vcpu_reg_state *vrs) +{ + uint8_t mod, rm; + vaddr_t addr = 0x0UL; + + if (insn == NULL || vrs == NULL) + return (-1); + + if (insn->insn_modrm_valid) { + rm = MODRM_RM(insn->insn_modrm); + mod = MODRM_MOD(insn->insn_modrm); + + switch (rm) { + case 0b000: + addr = vrs->vrs_gprs[VCPU_REGS_RAX]; + break; + case 0b001: + addr = vrs->vrs_gprs[VCPU_REGS_RCX]; + break; + case 0b010: + addr = vrs->vrs_gprs[VCPU_REGS_RDX]; + break; + case 0b011: + addr = vrs->vrs_gprs[VCPU_REGS_RBX]; + break; + case 0b100: + if (mod == 0b11) + addr = vrs->vrs_gprs[VCPU_REGS_RSP]; + break; + case 0b101: + if (mod != 0b00) + addr = vrs->vrs_gprs[VCPU_REGS_RBP]; + break; + case 0b110: + addr = vrs->vrs_gprs[VCPU_REGS_RSI]; + break; + case 0b111: + addr = vrs->vrs_gprs[VCPU_REGS_RDI]; + break; + } + + insn->insn_gva = addr; + } + + return (0); +} + +static enum decode_result +decode_disp(struct x86_decode_state *state, struct x86_insn *insn) +{ + enum decode_result res = DECODE_ERROR; + uint64_t disp = 0; + + if (!is_valid_state(state, __func__) || insn == NULL) + return (DECODE_ERROR); + + if (!insn->insn_modrm_valid) + return (DECODE_ERROR); + + switch (MODRM_MOD(insn->insn_modrm)) { + case 0x00: + insn->insn_disp_type = DISP_0; + res = DECODE_MORE; + break; + case 0x01: + insn->insn_disp_type = DISP_1; + res = next_value(state, 1, &disp); + if (res == DECODE_ERROR) + return (res); + insn->insn_disp = disp; + break; + case 0x02: + if (insn->insn_prefix.pfx_group4 == LEG_4_ADDRSZ) { + insn->insn_disp_type = DISP_2; + res = next_value(state, 2, &disp); + } else { + insn->insn_disp_type = DISP_4; + res = next_value(state, 4, &disp); + } + if (res == DECODE_ERROR) + return (res); + insn->insn_disp = disp; + break; + default: + insn->insn_disp_type = DISP_NONE; + res = DECODE_MORE; + } + + return (res); +} + +static enum decode_result +decode_opcode(struct x86_decode_state *state, struct x86_insn *insn) +{ + enum decode_result res; + enum x86_opcode_type type; + enum x86_operand_enc enc; + struct x86_opcode *opcode = &insn->insn_opcode; + uint8_t byte, byte2; + + if (!is_valid_state(state, __func__) || insn == NULL) + return (-1); + + memset(opcode, 0, sizeof(*opcode)); + + res = next_byte(state, &byte); + if (res == DECODE_ERROR) + return (res); + + type = x86_1byte_opcode_tbl[byte]; + switch(type) { + case OP_UNKNOWN: + case OP_UNSUPPORTED: + log_warnx("%s: unsupported opcode", __func__); + return (DECODE_ERROR); + + case OP_TWO_BYTE: + res = next_byte(state, &byte2); + if (res == DECODE_ERROR) + return (res); + + type = x86_2byte_opcode_tbl[byte2]; + if (type == OP_UNKNOWN || type == OP_UNSUPPORTED) { + log_warnx("%s: unsupported 2-byte opcode", __func__); + return (DECODE_ERROR); + } + + opcode->op_bytes[0] = byte; + opcode->op_bytes[1] = byte2; + opcode->op_bytes_len = 2; + enc = x86_2byte_operand_enc_table[byte2]; + break; + + default: + /* We've potentially got a known 1-byte opcode. */ + opcode->op_bytes[0] = byte; + opcode->op_bytes_len = 1; + enc = x86_1byte_operand_enc_tbl[byte]; + } + + if (enc == OP_ENC_UNKNOWN) + return (DECODE_ERROR); + + opcode->op_type = type; + opcode->op_encoding = enc; + + return (res); +} + +static enum decode_result +decode_sib(struct x86_decode_state *state, struct x86_insn *insn) +{ + enum decode_result res; + uint8_t byte; + + if (!is_valid_state(state, __func__) || insn == NULL) + return (-1); + + /* SIB is optional, so assume we will be continuing. */ + res = DECODE_MORE; + + insn->insn_sib_valid = 0; + if (!insn->insn_modrm_valid) + return (res); + + /* XXX is SIB valid in all cpu modes? */ + if (MODRM_RM(insn->insn_modrm) == 0b100) { + res = next_byte(state, &byte); + if (res != DECODE_ERROR) { + insn->insn_sib_valid = 1; + insn->insn_sib = byte; + } + } + + return (res); +} + +static enum decode_result +decode_imm(struct x86_decode_state *state, struct x86_insn *insn) +{ + enum decode_result res; + size_t num_bytes; + uint64_t value; + + if (!is_valid_state(state, __func__) || insn == NULL) + return (DECODE_ERROR); + + /* Only handle MI encoded instructions. Others shouldn't need assist. */ + if (insn->insn_opcode.op_encoding != OP_ENC_MI) + return (DECODE_DONE); + + /* Exceptions related to MOV instructions. */ + if (insn->insn_opcode.op_type == OP_MOV) { + switch (insn->insn_opcode.op_bytes[0]) { + case 0xC6: + num_bytes = 1; + break; + case 0xC7: + if (insn->insn_cpu_mode == VMM_CPU_MODE_REAL) + num_bytes = 2; + else + num_bytes = 4; + break; + default: + log_warnx("%s: cannot decode immediate bytes for MOV", + __func__); + return (DECODE_ERROR); + } + } else { + /* Fallback to interpreting based on cpu mode and REX. */ + if (insn->insn_cpu_mode == VMM_CPU_MODE_REAL) + num_bytes = 2; + else if (insn->insn_prefix.pfx_rex == REX_NONE) + num_bytes = 4; + else + num_bytes = 8; + } + + res = next_value(state, num_bytes, &value); + if (res != DECODE_ERROR) { + insn->insn_immediate = value; + insn->insn_immediate_len = num_bytes; + } + + return (res); +} + + +/* + * insn_decode + * + * Decode an x86 instruction from the provided instruction bytes. + * + * Return values: + * 0: successful decode + * Non-zero: an exception occurred during decode + */ +int +insn_decode(struct vm_exit *exit, struct x86_insn *insn) +{ + enum decode_result res; + struct vcpu_reg_state *vrs = &exit->vrs; + struct x86_decode_state state; + uint8_t *bytes, len; + int mode; + + if (exit == NULL || insn == NULL) { + log_warnx("%s: invalid input", __func__); + return (DECODE_ERROR); + } + + bytes = exit->vee.vee_insn_bytes; + len = exit->vee.vee_insn_len; + + /* 0. Initialize state and instruction objects. */ + memset(insn, 0, sizeof(*insn)); + memset(&state, 0, sizeof(state)); + state.s_len = len; + memcpy(&state.s_bytes, bytes, len); + + /* 1. Detect CPU mode. */ + mode = detect_cpu_mode(vrs); + if (mode == VMM_CPU_MODE_UNKNOWN) { + log_warnx("%s: failed to identify cpu mode", __func__); +#ifdef MMIO_DEBUG + dump_regs(vrs); +#endif + return (-1); + } + insn->insn_cpu_mode = mode; + +#ifdef MMIO_DEBUG + log_info("%s: cpu mode %s detected", __progname, str_cpu_mode(mode)); + printf("%s: got bytes: [ ", __progname); + for (int i = 0; i < len; i++) { + printf("%02x ", bytes[i]); + } + printf("]\n"); +#endif + /* 2. Decode prefixes. */ + res = decode_prefix(&state, insn); + if (res == DECODE_ERROR) { + log_warnx("%s: error decoding prefixes", __func__); + goto err; + } else if (res == DECODE_DONE) + goto done; + +#ifdef MMIO_DEBUG + log_info("%s: prefixes {g1: 0x%02x, g2: 0x%02x, g3: 0x%02x, g4: 0x%02x," + " rex: 0x%02x }", __progname, insn->insn_prefix.pfx_group1, + insn->insn_prefix.pfx_group2, insn->insn_prefix.pfx_group3, + insn->insn_prefix.pfx_group4, insn->insn_prefix.pfx_rex); +#endif + + /* 3. Pick apart opcode. Here we can start short-circuiting. */ + res = decode_opcode(&state, insn); + if (res == DECODE_ERROR) { + log_warnx("%s: error decoding opcode", __func__); + goto err; + } else if (res == DECODE_DONE) + goto done; + +#ifdef MMIO_DEBUG + log_info("%s: found opcode %s (operand encoding %s) (%s)", __progname, + str_opcode(&insn->insn_opcode), str_operand_enc(&insn->insn_opcode), + str_decode_res(res)); +#endif + + /* Process optional ModR/M byte. */ + res = decode_modrm(&state, insn); + if (res == DECODE_ERROR) { + log_warnx("%s: error decoding modrm", __func__); + goto err; + } + if (get_modrm_addr(insn, vrs) != 0) + goto err; + if (get_modrm_reg(insn) != 0) + goto err; + if (res == DECODE_DONE) + goto done; + +#ifdef MMIO_DEBUG + if (insn->insn_modrm_valid) + log_info("%s: found ModRM 0x%02x (%s)", __progname, + insn->insn_modrm, str_decode_res(res)); +#endif + + /* Process optional SIB byte. */ + res = decode_sib(&state, insn); + if (res == DECODE_ERROR) { + log_warnx("%s: error decoding sib", __func__); + goto err; + } else if (res == DECODE_DONE) + goto done; + +#ifdef MMIO_DEBUG + if (insn->insn_sib_valid) + log_info("%s: found SIB 0x%02x (%s)", __progname, + insn->insn_sib, str_decode_res(res)); +#endif + + /* Process any Displacement bytes. */ + res = decode_disp(&state, insn); + if (res == DECODE_ERROR) { + log_warnx("%s: error decoding displacement", __func__); + goto err; + } else if (res == DECODE_DONE) + goto done; + + /* Process any Immediate data bytes. */ + res = decode_imm(&state, insn); + if (res == DECODE_ERROR) { + log_warnx("%s: error decoding immediate bytes", __func__); + goto err; + } + +done: + insn->insn_bytes_len = state.s_idx; + +#ifdef MMIO_DEBUG + log_info("%s: final instruction length is %u", __func__, + insn->insn_bytes_len); + dump_insn(insn); + log_info("%s: modrm: {mod: %d, regop: %d, rm: %d}", __func__, + MODRM_MOD(insn->insn_modrm), MODRM_REGOP(insn->insn_modrm), + MODRM_RM(insn->insn_modrm)); + dump_regs(vrs); +#endif /* MMIO_DEBUG */ + return (0); + +err: +#ifdef MMIO_DEBUG + dump_insn(insn); + log_info("%s: modrm: {mod: %d, regop: %d, rm: %d}", __func__, + MODRM_MOD(insn->insn_modrm), MODRM_REGOP(insn->insn_modrm), + MODRM_RM(insn->insn_modrm)); + dump_regs(vrs); +#endif /* MMIO_DEBUG */ + return (-1); +} + +static int +emulate_mov(struct x86_insn *insn, struct vm_exit *exit) +{ + /* XXX Only supports read to register for now */ + if (insn->insn_opcode.op_encoding != OP_ENC_RM) + return (-1); + + /* XXX No device emulation yet. Fill with 0xFFs. */ + exit->vrs.vrs_gprs[insn->insn_reg] = 0xFFFFFFFFFFFFFFFF; + + return (0); +} + +static int +emulate_movzx(struct x86_insn *insn, struct vm_exit *exit) +{ + uint8_t byte, len, src = 1, dst = 2; + uint64_t value = 0; + + /* Only RM is valid for MOVZX. */ + if (insn->insn_opcode.op_encoding != OP_ENC_RM) { + log_warnx("invalid op encoding for MOVZX: %d", + insn->insn_opcode.op_encoding); + return (-1); + } + + len = insn->insn_opcode.op_bytes_len; + if (len < 1 || len > sizeof(insn->insn_opcode.op_bytes)) { + log_warnx("invalid opcode byte length: %d", len); + return (-1); + } + + byte = insn->insn_opcode.op_bytes[len - 1]; + switch (byte) { + case 0xB6: + src = 1; + if (insn->insn_cpu_mode == VMM_CPU_MODE_PROT + || insn->insn_cpu_mode == VMM_CPU_MODE_REAL) + dst = 2; + else if (insn->insn_prefix.pfx_rex == REX_NONE) + dst = 4; + else // XXX validate CPU mode + dst = 8; + break; + case 0xB7: + src = 2; + if (insn->insn_prefix.pfx_rex == REX_NONE) + dst = 4; + else // XXX validate CPU mode + dst = 8; + break; + default: + log_warnx("invalid byte in MOVZX opcode: %x", byte); + return (-1); + } + + if (dst == 4) + exit->vrs.vrs_gprs[insn->insn_reg] &= 0xFFFFFFFF00000000; + else + exit->vrs.vrs_gprs[insn->insn_reg] = 0x0UL; + + /* XXX No device emulation yet. Fill with 0xFFs. */ + switch (src) { + case 1: value = 0xFF; break; + case 2: value = 0xFFFF; break; + case 4: value = 0xFFFFFFFF; break; + case 8: value = 0xFFFFFFFFFFFFFFFF; break; + default: + log_warnx("invalid source size: %d", src); + return (-1); + } + + exit->vrs.vrs_gprs[insn->insn_reg] |= value; + + return (0); +} + +/* + * insn_emulate + * + * Returns: + * 0: success + * EINVAL: exception occurred + * EFAULT: page fault occurred, requires retry + * ENOTSUP: an unsupported instruction was provided + */ +int +insn_emulate(struct vm_exit *exit, struct x86_insn *insn) +{ + int res; + + switch (insn->insn_opcode.op_type) { + case OP_MOV: + res = emulate_mov(insn, exit); + break; + + case OP_MOVZX: + res = emulate_movzx(insn, exit); + break; + + default: + log_warnx("%s: emulation not defined for %s", __func__, + str_opcode(&insn->insn_opcode)); + res = ENOTSUP; + } + + if (res == 0) + exit->vrs.vrs_gprs[VCPU_REGS_RIP] += insn->insn_bytes_len; + + return (res); +} diff --git a/usr.sbin/vmd/x86_vm.c b/usr.sbin/vmd/x86_vm.c new file mode 100644 index 000000000..c6c4b2a9e --- /dev/null +++ b/usr.sbin/vmd/x86_vm.c @@ -0,0 +1,1373 @@ +/* $OpenBSD: x86_vm.c,v 1.1 2024/07/10 10:41:19 dv Exp $ */ +/* + * Copyright (c) 2015 Mike Larkin + * + * 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 +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "atomicio.h" +#include "fw_cfg.h" +#include "i8253.h" +#include "i8259.h" +#include "loadfile.h" +#include "mc146818.h" +#include "ns8250.h" +#include "pci.h" +#include "virtio.h" + +typedef uint8_t (*io_fn_t)(struct vm_run_params *); + +#define MAX_PORTS 65536 + +io_fn_t ioports_map[MAX_PORTS]; +extern char *__progname; + +void create_memory_map(struct vm_create_params *); +int translate_gva(struct vm_exit*, uint64_t, uint64_t *, int); + +static struct vm_mem_range *find_gpa_range(struct vm_create_params *, paddr_t, + size_t); +static int loadfile_bios(gzFile, off_t, struct vcpu_reg_state *); +static int vcpu_exit_eptviolation(struct vm_run_params *); +static void vcpu_exit_inout(struct vm_run_params *); + +extern struct vmd_vm *current_vm; +extern int con_fd; + +/* + * Represents a standard register set for an OS to be booted + * as a flat 64 bit address space. + * + * NOT set here are: + * RIP + * RSP + * GDTR BASE + * + * Specific bootloaders should clone this structure and override + * those fields as needed. + * + * Note - CR3 and various bits in CR0 may be overridden by vmm(4) based on + * features of the CPU in use. + */ +static const struct vcpu_reg_state vcpu_init_flat64 = { + .vrs_gprs[VCPU_REGS_RFLAGS] = 0x2, + .vrs_gprs[VCPU_REGS_RIP] = 0x0, + .vrs_gprs[VCPU_REGS_RSP] = 0x0, + .vrs_crs[VCPU_REGS_CR0] = CR0_ET | CR0_PE | CR0_PG, + .vrs_crs[VCPU_REGS_CR3] = PML4_PAGE, + .vrs_crs[VCPU_REGS_CR4] = CR4_PAE | CR4_PSE, + .vrs_crs[VCPU_REGS_PDPTE0] = 0ULL, + .vrs_crs[VCPU_REGS_PDPTE1] = 0ULL, + .vrs_crs[VCPU_REGS_PDPTE2] = 0ULL, + .vrs_crs[VCPU_REGS_PDPTE3] = 0ULL, + .vrs_sregs[VCPU_REGS_CS] = { 0x8, 0xFFFFFFFF, 0xC09F, 0x0}, + .vrs_sregs[VCPU_REGS_DS] = { 0x10, 0xFFFFFFFF, 0xC093, 0x0}, + .vrs_sregs[VCPU_REGS_ES] = { 0x10, 0xFFFFFFFF, 0xC093, 0x0}, + .vrs_sregs[VCPU_REGS_FS] = { 0x10, 0xFFFFFFFF, 0xC093, 0x0}, + .vrs_sregs[VCPU_REGS_GS] = { 0x10, 0xFFFFFFFF, 0xC093, 0x0}, + .vrs_sregs[VCPU_REGS_SS] = { 0x10, 0xFFFFFFFF, 0xC093, 0x0}, + .vrs_gdtr = { 0x0, 0xFFFF, 0x0, 0x0}, + .vrs_idtr = { 0x0, 0xFFFF, 0x0, 0x0}, + .vrs_sregs[VCPU_REGS_LDTR] = { 0x0, 0xFFFF, 0x0082, 0x0}, + .vrs_sregs[VCPU_REGS_TR] = { 0x0, 0xFFFF, 0x008B, 0x0}, + .vrs_msrs[VCPU_REGS_EFER] = EFER_LME | EFER_LMA, + .vrs_drs[VCPU_REGS_DR0] = 0x0, + .vrs_drs[VCPU_REGS_DR1] = 0x0, + .vrs_drs[VCPU_REGS_DR2] = 0x0, + .vrs_drs[VCPU_REGS_DR3] = 0x0, + .vrs_drs[VCPU_REGS_DR6] = 0xFFFF0FF0, + .vrs_drs[VCPU_REGS_DR7] = 0x400, + .vrs_msrs[VCPU_REGS_STAR] = 0ULL, + .vrs_msrs[VCPU_REGS_LSTAR] = 0ULL, + .vrs_msrs[VCPU_REGS_CSTAR] = 0ULL, + .vrs_msrs[VCPU_REGS_SFMASK] = 0ULL, + .vrs_msrs[VCPU_REGS_KGSBASE] = 0ULL, + .vrs_msrs[VCPU_REGS_MISC_ENABLE] = 0ULL, + .vrs_crs[VCPU_REGS_XCR0] = XFEATURE_X87 +}; + +/* + * Represents a standard register set for an BIOS to be booted + * as a flat 16 bit address space. + */ +static const struct vcpu_reg_state vcpu_init_flat16 = { + .vrs_gprs[VCPU_REGS_RFLAGS] = 0x2, + .vrs_gprs[VCPU_REGS_RIP] = 0xFFF0, + .vrs_gprs[VCPU_REGS_RSP] = 0x0, + .vrs_crs[VCPU_REGS_CR0] = 0x60000010, + .vrs_crs[VCPU_REGS_CR3] = 0, + .vrs_sregs[VCPU_REGS_CS] = { 0xF000, 0xFFFF, 0x809F, 0xF0000}, + .vrs_sregs[VCPU_REGS_DS] = { 0x0, 0xFFFF, 0x8093, 0x0}, + .vrs_sregs[VCPU_REGS_ES] = { 0x0, 0xFFFF, 0x8093, 0x0}, + .vrs_sregs[VCPU_REGS_FS] = { 0x0, 0xFFFF, 0x8093, 0x0}, + .vrs_sregs[VCPU_REGS_GS] = { 0x0, 0xFFFF, 0x8093, 0x0}, + .vrs_sregs[VCPU_REGS_SS] = { 0x0, 0xFFFF, 0x8093, 0x0}, + .vrs_gdtr = { 0x0, 0xFFFF, 0x0, 0x0}, + .vrs_idtr = { 0x0, 0xFFFF, 0x0, 0x0}, + .vrs_sregs[VCPU_REGS_LDTR] = { 0x0, 0xFFFF, 0x0082, 0x0}, + .vrs_sregs[VCPU_REGS_TR] = { 0x0, 0xFFFF, 0x008B, 0x0}, + .vrs_msrs[VCPU_REGS_EFER] = 0ULL, + .vrs_drs[VCPU_REGS_DR0] = 0x0, + .vrs_drs[VCPU_REGS_DR1] = 0x0, + .vrs_drs[VCPU_REGS_DR2] = 0x0, + .vrs_drs[VCPU_REGS_DR3] = 0x0, + .vrs_drs[VCPU_REGS_DR6] = 0xFFFF0FF0, + .vrs_drs[VCPU_REGS_DR7] = 0x400, + .vrs_msrs[VCPU_REGS_STAR] = 0ULL, + .vrs_msrs[VCPU_REGS_LSTAR] = 0ULL, + .vrs_msrs[VCPU_REGS_CSTAR] = 0ULL, + .vrs_msrs[VCPU_REGS_SFMASK] = 0ULL, + .vrs_msrs[VCPU_REGS_KGSBASE] = 0ULL, + .vrs_crs[VCPU_REGS_XCR0] = XFEATURE_X87 +}; + +/* + * create_memory_map + * + * Sets up the guest physical memory ranges that the VM can access. + * + * Parameters: + * vcp: VM create parameters describing the VM whose memory map + * is being created + * + * Return values: + * nothing + */ +void +create_memory_map(struct vm_create_params *vcp) +{ + size_t len, mem_bytes; + size_t above_1m = 0, above_4g = 0; + + mem_bytes = vcp->vcp_memranges[0].vmr_size; + vcp->vcp_nmemranges = 0; + if (mem_bytes == 0 || mem_bytes > VMM_MAX_VM_MEM_SIZE) + return; + + /* First memory region: 0 - LOWMEM_KB (DOS low mem) */ + len = LOWMEM_KB * 1024; + vcp->vcp_memranges[0].vmr_gpa = 0x0; + vcp->vcp_memranges[0].vmr_size = len; + vcp->vcp_memranges[0].vmr_type = VM_MEM_RAM; + mem_bytes -= len; + + /* + * Second memory region: LOWMEM_KB - 1MB. + * + * N.B. - Normally ROMs or parts of video RAM are mapped here. + * We have to add this region, because some systems + * unconditionally write to 0xb8000 (VGA RAM), and + * we need to make sure that vmm(4) permits accesses + * to it. So allocate guest memory for it. + */ + len = MB(1) - (LOWMEM_KB * 1024); + vcp->vcp_memranges[1].vmr_gpa = LOWMEM_KB * 1024; + vcp->vcp_memranges[1].vmr_size = len; + vcp->vcp_memranges[1].vmr_type = VM_MEM_RESERVED; + mem_bytes -= len; + + /* If we have less than 2MB remaining, still create a 2nd BIOS area. */ + if (mem_bytes <= MB(2)) { + vcp->vcp_memranges[2].vmr_gpa = VMM_PCI_MMIO_BAR_END; + vcp->vcp_memranges[2].vmr_size = MB(2); + vcp->vcp_memranges[2].vmr_type = VM_MEM_RESERVED; + vcp->vcp_nmemranges = 3; + return; + } + + /* + * Calculate the how to split any remaining memory across the 4GB + * boundary while making sure we do not place physical memory into + * MMIO ranges. + */ + if (mem_bytes > VMM_PCI_MMIO_BAR_BASE - MB(1)) { + above_1m = VMM_PCI_MMIO_BAR_BASE - MB(1); + above_4g = mem_bytes - above_1m; + } else { + above_1m = mem_bytes; + above_4g = 0; + } + + /* Third memory region: area above 1MB to MMIO region */ + vcp->vcp_memranges[2].vmr_gpa = MB(1); + vcp->vcp_memranges[2].vmr_size = above_1m; + vcp->vcp_memranges[2].vmr_type = VM_MEM_RAM; + + /* Fourth region: PCI MMIO range */ + vcp->vcp_memranges[3].vmr_gpa = VMM_PCI_MMIO_BAR_BASE; + vcp->vcp_memranges[3].vmr_size = VMM_PCI_MMIO_BAR_END - + VMM_PCI_MMIO_BAR_BASE + 1; + vcp->vcp_memranges[3].vmr_type = VM_MEM_MMIO; + + /* Fifth region: 2nd copy of BIOS above MMIO ending at 4GB */ + vcp->vcp_memranges[4].vmr_gpa = VMM_PCI_MMIO_BAR_END + 1; + vcp->vcp_memranges[4].vmr_size = MB(2); + vcp->vcp_memranges[4].vmr_type = VM_MEM_RESERVED; + + /* Sixth region: any remainder above 4GB */ + if (above_4g > 0) { + vcp->vcp_memranges[5].vmr_gpa = GB(4); + vcp->vcp_memranges[5].vmr_size = above_4g; + vcp->vcp_memranges[5].vmr_type = VM_MEM_RAM; + vcp->vcp_nmemranges = 6; + } else + vcp->vcp_nmemranges = 5; +} + +int +load_firmware(struct vmd_vm *vm, struct vcpu_reg_state *vrs) +{ + int ret; + gzFile fp; + struct stat sb; + + /* + * Set up default "flat 64 bit" register state - RIP, RSP, and + * GDT info will be set in bootloader + */ + memcpy(vrs, &vcpu_init_flat64, sizeof(*vrs)); + + /* Find and open kernel image */ + if ((fp = gzdopen(vm->vm_kernel, "r")) == NULL) + fatalx("failed to open kernel - exiting"); + + /* Load kernel image */ + ret = loadfile_elf(fp, vm, vrs, vm->vm_params.vmc_bootdevice); + + /* + * Try BIOS as a fallback (only if it was provided as an image + * with vm->vm_kernel and the file is not compressed) + */ + if (ret && errno == ENOEXEC && vm->vm_kernel != -1 && + gzdirect(fp) && (ret = fstat(vm->vm_kernel, &sb)) == 0) + ret = loadfile_bios(fp, sb.st_size, vrs); + + gzclose(fp); + + return (ret); +} + + +/* + * loadfile_bios + * + * Alternatively to loadfile_elf, this function loads a non-ELF BIOS image + * directly into memory. + * + * Parameters: + * fp: file of a kernel file to load + * size: uncompressed size of the image + * (out) vrs: register state to set on init for this kernel + * + * Return values: + * 0 if successful + * various error codes returned from read(2) or loadelf functions + */ +int +loadfile_bios(gzFile fp, off_t size, struct vcpu_reg_state *vrs) +{ + off_t off; + + /* Set up a "flat 16 bit" register state for BIOS */ + memcpy(vrs, &vcpu_init_flat16, sizeof(*vrs)); + + /* Seek to the beginning of the BIOS image */ + if (gzseek(fp, 0, SEEK_SET) == -1) + return (-1); + + /* The BIOS image must end at 1MB */ + if ((off = MB(1) - size) < 0) + return (-1); + + /* Read BIOS image into memory */ + if (mread(fp, off, size) != (size_t)size) { + errno = EIO; + return (-1); + } + + if (gzseek(fp, 0, SEEK_SET) == -1) + return (-1); + + /* Read a second BIOS copy into memory ending at 4GB */ + off = GB(4) - size; + if (mread(fp, off, size) != (size_t)size) { + errno = EIO; + return (-1); + } + + log_debug("%s: loaded BIOS image", __func__); + + return (0); +} + +/* + * init_emulated_hw + * + * Initializes the userspace hardware emulation + */ +void +init_emulated_hw(struct vmop_create_params *vmc, int child_cdrom, + int child_disks[][VM_MAX_BASE_PER_DISK], int *child_taps) +{ + struct vm_create_params *vcp = &vmc->vmc_params; + size_t i; + uint64_t memlo, memhi; + + /* Calculate memory size for NVRAM registers */ + memlo = memhi = 0; + for (i = 0; i < vcp->vcp_nmemranges; i++) { + if (vcp->vcp_memranges[i].vmr_gpa == MB(1) && + vcp->vcp_memranges[i].vmr_size > (15 * MB(1))) + memlo = vcp->vcp_memranges[i].vmr_size - (15 * MB(1)); + else if (vcp->vcp_memranges[i].vmr_gpa == GB(4)) + memhi = vcp->vcp_memranges[i].vmr_size; + } + + /* Reset the IO port map */ + memset(&ioports_map, 0, sizeof(io_fn_t) * MAX_PORTS); + + /* Init i8253 PIT */ + i8253_init(vcp->vcp_id); + ioports_map[TIMER_CTRL] = vcpu_exit_i8253; + ioports_map[TIMER_BASE + TIMER_CNTR0] = vcpu_exit_i8253; + ioports_map[TIMER_BASE + TIMER_CNTR1] = vcpu_exit_i8253; + ioports_map[TIMER_BASE + TIMER_CNTR2] = vcpu_exit_i8253; + ioports_map[PCKBC_AUX] = vcpu_exit_i8253_misc; + + /* Init mc146818 RTC */ + mc146818_init(vcp->vcp_id, memlo, memhi); + ioports_map[IO_RTC] = vcpu_exit_mc146818; + ioports_map[IO_RTC + 1] = vcpu_exit_mc146818; + + /* Init master and slave PICs */ + i8259_init(); + ioports_map[IO_ICU1] = vcpu_exit_i8259; + ioports_map[IO_ICU1 + 1] = vcpu_exit_i8259; + ioports_map[IO_ICU2] = vcpu_exit_i8259; + ioports_map[IO_ICU2 + 1] = vcpu_exit_i8259; + ioports_map[ELCR0] = vcpu_exit_elcr; + ioports_map[ELCR1] = vcpu_exit_elcr; + + /* Init ns8250 UART */ + ns8250_init(con_fd, vcp->vcp_id); + for (i = COM1_DATA; i <= COM1_SCR; i++) + ioports_map[i] = vcpu_exit_com; + + /* Initialize PCI */ + for (i = VM_PCI_IO_BAR_BASE; i <= VM_PCI_IO_BAR_END; i++) + ioports_map[i] = vcpu_exit_pci; + + ioports_map[PCI_MODE1_ADDRESS_REG] = vcpu_exit_pci; + ioports_map[PCI_MODE1_DATA_REG] = vcpu_exit_pci; + ioports_map[PCI_MODE1_DATA_REG + 1] = vcpu_exit_pci; + ioports_map[PCI_MODE1_DATA_REG + 2] = vcpu_exit_pci; + ioports_map[PCI_MODE1_DATA_REG + 3] = vcpu_exit_pci; + pci_init(); + + /* Initialize virtio devices */ + virtio_init(current_vm, child_cdrom, child_disks, child_taps); + + /* + * Init QEMU fw_cfg interface. Must be done last for pci hardware + * detection. + */ + fw_cfg_init(vmc); + ioports_map[FW_CFG_IO_SELECT] = vcpu_exit_fw_cfg; + ioports_map[FW_CFG_IO_DATA] = vcpu_exit_fw_cfg; + ioports_map[FW_CFG_IO_DMA_ADDR_HIGH] = vcpu_exit_fw_cfg_dma; + ioports_map[FW_CFG_IO_DMA_ADDR_LOW] = vcpu_exit_fw_cfg_dma; +} + +/* + * restore_emulated_hw + * + * Restores the userspace hardware emulation from fd + */ +void +restore_emulated_hw(struct vm_create_params *vcp, int fd, + int *child_taps, int child_disks[][VM_MAX_BASE_PER_DISK], int child_cdrom) +{ + /* struct vm_create_params *vcp = &vmc->vmc_params; */ + int i; + memset(&ioports_map, 0, sizeof(io_fn_t) * MAX_PORTS); + + /* Init i8253 PIT */ + i8253_restore(fd, vcp->vcp_id); + ioports_map[TIMER_CTRL] = vcpu_exit_i8253; + ioports_map[TIMER_BASE + TIMER_CNTR0] = vcpu_exit_i8253; + ioports_map[TIMER_BASE + TIMER_CNTR1] = vcpu_exit_i8253; + ioports_map[TIMER_BASE + TIMER_CNTR2] = vcpu_exit_i8253; + + /* Init master and slave PICs */ + i8259_restore(fd); + ioports_map[IO_ICU1] = vcpu_exit_i8259; + ioports_map[IO_ICU1 + 1] = vcpu_exit_i8259; + ioports_map[IO_ICU2] = vcpu_exit_i8259; + ioports_map[IO_ICU2 + 1] = vcpu_exit_i8259; + + /* Init ns8250 UART */ + ns8250_restore(fd, con_fd, vcp->vcp_id); + for (i = COM1_DATA; i <= COM1_SCR; i++) + ioports_map[i] = vcpu_exit_com; + + /* Init mc146818 RTC */ + mc146818_restore(fd, vcp->vcp_id); + ioports_map[IO_RTC] = vcpu_exit_mc146818; + ioports_map[IO_RTC + 1] = vcpu_exit_mc146818; + + /* Init QEMU fw_cfg interface */ + fw_cfg_restore(fd); + ioports_map[FW_CFG_IO_SELECT] = vcpu_exit_fw_cfg; + ioports_map[FW_CFG_IO_DATA] = vcpu_exit_fw_cfg; + ioports_map[FW_CFG_IO_DMA_ADDR_HIGH] = vcpu_exit_fw_cfg_dma; + ioports_map[FW_CFG_IO_DMA_ADDR_LOW] = vcpu_exit_fw_cfg_dma; + + /* Initialize PCI */ + for (i = VM_PCI_IO_BAR_BASE; i <= VM_PCI_IO_BAR_END; i++) + ioports_map[i] = vcpu_exit_pci; + + ioports_map[PCI_MODE1_ADDRESS_REG] = vcpu_exit_pci; + ioports_map[PCI_MODE1_DATA_REG] = vcpu_exit_pci; + ioports_map[PCI_MODE1_DATA_REG + 1] = vcpu_exit_pci; + ioports_map[PCI_MODE1_DATA_REG + 2] = vcpu_exit_pci; + ioports_map[PCI_MODE1_DATA_REG + 3] = vcpu_exit_pci; + pci_restore(fd); + virtio_restore(fd, current_vm, child_cdrom, child_disks, child_taps); +} + +void +pause_vm_md(struct vmd_vm *vm) +{ + i8253_stop(); + mc146818_stop(); + ns8250_stop(); + virtio_stop(vm); +} + +void +unpause_vm_md(struct vmd_vm *vm) +{ + i8253_start(); + mc146818_start(); + ns8250_start(); + virtio_start(vm); +} + +int +dump_devs(int fd) +{ + int ret = 0; + + if ((ret = i8253_dump(fd))) + return ret; + if ((ret = i8259_dump(fd))) + return ret; + if ((ret = ns8250_dump(fd))) + return ret; + if ((ret = mc146818_dump(fd))) + return ret; + ret = fw_cfg_dump(fd); + + return ret; +} + +int +dump_send_header(int fd) { + struct vm_dump_header vmh; + int i; + + memcpy(&vmh.vmh_signature, VM_DUMP_SIGNATURE, + sizeof(vmh.vmh_signature)); + + vmh.vmh_cpuids[0].code = 0x00; + vmh.vmh_cpuids[0].leaf = 0x00; + + vmh.vmh_cpuids[1].code = 0x01; + vmh.vmh_cpuids[1].leaf = 0x00; + + vmh.vmh_cpuids[2].code = 0x07; + vmh.vmh_cpuids[2].leaf = 0x00; + + vmh.vmh_cpuids[3].code = 0x0d; + vmh.vmh_cpuids[3].leaf = 0x00; + + vmh.vmh_cpuids[4].code = 0x80000001; + vmh.vmh_cpuids[4].leaf = 0x00; + + vmh.vmh_version = VM_DUMP_VERSION; + + for (i=0; i < VM_DUMP_HEADER_CPUID_COUNT; i++) { + CPUID_LEAF(vmh.vmh_cpuids[i].code, + vmh.vmh_cpuids[i].leaf, + vmh.vmh_cpuids[i].a, + vmh.vmh_cpuids[i].b, + vmh.vmh_cpuids[i].c, + vmh.vmh_cpuids[i].d); + } + + if (atomicio(vwrite, fd, &vmh, sizeof(vmh)) != sizeof(vmh)) + return (-1); + + return (0); +} + + +/* + * vcpu_exit_inout + * + * Handle all I/O exits that need to be emulated in vmd. This includes the + * i8253 PIT, the com1 ns8250 UART, and the MC146818 RTC/NVRAM device. + * + * Parameters: + * vrp: vcpu run parameters containing guest state for this exit + */ +void +vcpu_exit_inout(struct vm_run_params *vrp) +{ + struct vm_exit *vei = vrp->vrp_exit; + uint8_t intr = 0xFF; + + if (vei->vei.vei_rep || vei->vei.vei_string) { +#ifdef MMIO_DEBUG + log_info("%s: %s%s%s %d-byte, enc=%d, data=0x%08x, port=0x%04x", + __func__, + vei->vei.vei_rep == 0 ? "" : "REP ", + vei->vei.vei_dir == VEI_DIR_IN ? "IN" : "OUT", + vei->vei.vei_string == 0 ? "" : "S", + vei->vei.vei_size, vei->vei.vei_encoding, + vei->vei.vei_data, vei->vei.vei_port); + log_info("%s: ECX = 0x%llx, RDX = 0x%llx, RSI = 0x%llx", + __func__, + vei->vrs.vrs_gprs[VCPU_REGS_RCX], + vei->vrs.vrs_gprs[VCPU_REGS_RDX], + vei->vrs.vrs_gprs[VCPU_REGS_RSI]); +#endif /* MMIO_DEBUG */ + fatalx("%s: can't emulate REP prefixed IN(S)/OUT(S)", + __func__); + } + + if (ioports_map[vei->vei.vei_port] != NULL) + intr = ioports_map[vei->vei.vei_port](vrp); + else if (vei->vei.vei_dir == VEI_DIR_IN) + set_return_data(vei, 0xFFFFFFFF); + + vei->vrs.vrs_gprs[VCPU_REGS_RIP] += vei->vei.vei_insn_len; + + if (intr != 0xFF) + vcpu_assert_irq(vrp->vrp_vm_id, vrp->vrp_vcpu_id, intr); +} + +/* + * vcpu_exit + * + * Handle a vcpu exit. This function is called when it is determined that + * vmm(4) requires the assistance of vmd to support a particular guest + * exit type (eg, accessing an I/O port or device). Guest state is contained + * in 'vrp', and will be resent to vmm(4) on exit completion. + * + * Upon conclusion of handling the exit, the function determines if any + * interrupts should be injected into the guest, and asserts the proper + * IRQ line whose interrupt should be vectored. + * + * Parameters: + * vrp: vcpu run parameters containing guest state for this exit + * + * Return values: + * 0: the exit was handled successfully + * 1: an error occurred (eg, unknown exit reason passed in 'vrp') + */ +int +vcpu_exit(struct vm_run_params *vrp) +{ + int ret; + + switch (vrp->vrp_exit_reason) { + case VMX_EXIT_INT_WINDOW: + case SVM_VMEXIT_VINTR: + case VMX_EXIT_CPUID: + case VMX_EXIT_EXTINT: + case SVM_VMEXIT_INTR: + case SVM_VMEXIT_MSR: + case SVM_VMEXIT_CPUID: + /* + * We may be exiting to vmd to handle a pending interrupt but + * at the same time the last exit type may have been one of + * these. In this case, there's nothing extra to be done + * here (and falling through to the default case below results + * in more vmd log spam). + */ + break; + case SVM_VMEXIT_NPF: + case VMX_EXIT_EPT_VIOLATION: + ret = vcpu_exit_eptviolation(vrp); + if (ret) + return (ret); + break; + case VMX_EXIT_IO: + case SVM_VMEXIT_IOIO: + vcpu_exit_inout(vrp); + break; + case VMX_EXIT_HLT: + case SVM_VMEXIT_HLT: + vcpu_halt(vrp->vrp_vcpu_id); + break; + case VMX_EXIT_TRIPLE_FAULT: + case SVM_VMEXIT_SHUTDOWN: + /* reset VM */ + return (EAGAIN); + default: + log_debug("%s: unknown exit reason 0x%x", + __progname, vrp->vrp_exit_reason); + } + + return (0); +} + +/* + * vcpu_exit_eptviolation + * + * handle an EPT Violation + * + * Parameters: + * vrp: vcpu run parameters containing guest state for this exit + * + * Return values: + * 0: no action required + * EFAULT: a protection fault occured, kill the vm. + */ +static int +vcpu_exit_eptviolation(struct vm_run_params *vrp) +{ + struct vm_exit *ve = vrp->vrp_exit; + int ret = 0; +#if MMIO_NOTYET + struct x86_insn insn; + uint64_t va, pa; + size_t len = 15; /* Max instruction length in x86. */ +#endif /* MMIO_NOTYET */ + switch (ve->vee.vee_fault_type) { + case VEE_FAULT_HANDLED: + log_debug("%s: fault already handled", __func__); + break; + +#if MMIO_NOTYET + case VEE_FAULT_MMIO_ASSIST: + /* Intel VMX might give us the length of the instruction. */ + if (ve->vee.vee_insn_info & VEE_LEN_VALID) + len = ve->vee.vee_insn_len; + + if (len > 15) + fatalx("%s: invalid instruction length %lu", __func__, + len); + + /* If we weren't given instruction bytes, we need to fetch. */ + if (!(ve->vee.vee_insn_info & VEE_BYTES_VALID)) { + memset(ve->vee.vee_insn_bytes, 0, + sizeof(ve->vee.vee_insn_bytes)); + va = ve->vrs.vrs_gprs[VCPU_REGS_RIP]; + + /* XXX Only support instructions that fit on 1 page. */ + if ((va & PAGE_MASK) + len > PAGE_SIZE) { + log_warnx("%s: instruction might cross page " + "boundary", __func__); + ret = EINVAL; + break; + } + + ret = translate_gva(ve, va, &pa, PROT_EXEC); + if (ret != 0) { + log_warnx("%s: failed gva translation", + __func__); + break; + } + + ret = read_mem(pa, ve->vee.vee_insn_bytes, len); + if (ret != 0) { + log_warnx("%s: failed to fetch instruction " + "bytes from 0x%llx", __func__, pa); + break; + } + } + + ret = insn_decode(ve, &insn); + if (ret == 0) + ret = insn_emulate(ve, &insn); + break; +#endif /* MMIO_NOTYET */ + + case VEE_FAULT_PROTECT: + log_debug("%s: EPT Violation: rip=0x%llx", __progname, + ve->vrs.vrs_gprs[VCPU_REGS_RIP]); + ret = EFAULT; + break; + + default: + fatalx("%s: invalid fault_type %d", __progname, + ve->vee.vee_fault_type); + /* UNREACHED */ + } + + return (ret); +} + +/* + * vcpu_exit_pci + * + * Handle all I/O to the emulated PCI subsystem. + * + * Parameters: + * vrp: vcpu run parameters containing guest state for this exit + * + * Return value: + * Interrupt to inject to the guest VM, or 0xFF if no interrupt should + * be injected. + */ +uint8_t +vcpu_exit_pci(struct vm_run_params *vrp) +{ + struct vm_exit *vei = vrp->vrp_exit; + uint8_t intr; + + intr = 0xFF; + + switch (vei->vei.vei_port) { + case PCI_MODE1_ADDRESS_REG: + pci_handle_address_reg(vrp); + break; + case PCI_MODE1_DATA_REG: + case PCI_MODE1_DATA_REG + 1: + case PCI_MODE1_DATA_REG + 2: + case PCI_MODE1_DATA_REG + 3: + pci_handle_data_reg(vrp); + break; + case VM_PCI_IO_BAR_BASE ... VM_PCI_IO_BAR_END: + intr = pci_handle_io(vrp); + break; + default: + log_warnx("%s: unknown PCI register 0x%llx", + __progname, (uint64_t)vei->vei.vei_port); + break; + } + + return (intr); +} + +/* + * find_gpa_range + * + * Search for a contiguous guest physical mem range. + * + * Parameters: + * vcp: VM create parameters that contain the memory map to search in + * gpa: the starting guest physical address + * len: the length of the memory range + * + * Return values: + * NULL: on failure if there is no memory range as described by the parameters + * Pointer to vm_mem_range that contains the start of the range otherwise. + */ +static struct vm_mem_range * +find_gpa_range(struct vm_create_params *vcp, paddr_t gpa, size_t len) +{ + size_t i, n; + struct vm_mem_range *vmr; + + /* Find the first vm_mem_range that contains gpa */ + for (i = 0; i < vcp->vcp_nmemranges; i++) { + vmr = &vcp->vcp_memranges[i]; + if (gpa < vmr->vmr_gpa + vmr->vmr_size) + break; + } + + /* No range found. */ + if (i == vcp->vcp_nmemranges) + return (NULL); + + /* + * vmr may cover the range [gpa, gpa + len) only partly. Make + * sure that the following vm_mem_ranges are contiguous and + * cover the rest. + */ + n = vmr->vmr_size - (gpa - vmr->vmr_gpa); + if (len < n) + len = 0; + else + len -= n; + gpa = vmr->vmr_gpa + vmr->vmr_size; + for (i = i + 1; len != 0 && i < vcp->vcp_nmemranges; i++) { + vmr = &vcp->vcp_memranges[i]; + if (gpa != vmr->vmr_gpa) + return (NULL); + if (len <= vmr->vmr_size) + len = 0; + else + len -= vmr->vmr_size; + + gpa = vmr->vmr_gpa + vmr->vmr_size; + } + + if (len != 0) + return (NULL); + + return (vmr); +} +/* + * write_mem + * + * Copies data from 'buf' into the guest VM's memory at paddr 'dst'. + * + * Parameters: + * dst: the destination paddr_t in the guest VM + * buf: data to copy (or NULL to zero the data) + * len: number of bytes to copy + * + * Return values: + * 0: success + * EINVAL: if the guest physical memory range [dst, dst + len) does not + * exist in the guest. + */ +int +write_mem(paddr_t dst, const void *buf, size_t len) +{ + const char *from = buf; + char *to; + size_t n, off; + struct vm_mem_range *vmr; + + vmr = find_gpa_range(¤t_vm->vm_params.vmc_params, dst, len); + if (vmr == NULL) { + errno = EINVAL; + log_warn("%s: failed - invalid memory range dst = 0x%lx, " + "len = 0x%zx", __func__, dst, len); + return (EINVAL); + } + + off = dst - vmr->vmr_gpa; + while (len != 0) { + n = vmr->vmr_size - off; + if (len < n) + n = len; + + to = (char *)vmr->vmr_va + off; + if (buf == NULL) + memset(to, 0, n); + else { + memcpy(to, from, n); + from += n; + } + len -= n; + off = 0; + vmr++; + } + + return (0); +} + +/* + * read_mem + * + * Reads memory at guest paddr 'src' into 'buf'. + * + * Parameters: + * src: the source paddr_t in the guest VM to read from. + * buf: destination (local) buffer + * len: number of bytes to read + * + * Return values: + * 0: success + * EINVAL: if the guest physical memory range [dst, dst + len) does not + * exist in the guest. + */ +int +read_mem(paddr_t src, void *buf, size_t len) +{ + char *from, *to = buf; + size_t n, off; + struct vm_mem_range *vmr; + + vmr = find_gpa_range(¤t_vm->vm_params.vmc_params, src, len); + if (vmr == NULL) { + errno = EINVAL; + log_warn("%s: failed - invalid memory range src = 0x%lx, " + "len = 0x%zx", __func__, src, len); + return (EINVAL); + } + + off = src - vmr->vmr_gpa; + while (len != 0) { + n = vmr->vmr_size - off; + if (len < n) + n = len; + + from = (char *)vmr->vmr_va + off; + memcpy(to, from, n); + + to += n; + len -= n; + off = 0; + vmr++; + } + + return (0); +} + +/* + * hvaddr_mem + * + * Translate a guest physical address to a host virtual address, checking the + * provided memory range length to confirm it's contiguous within the same + * guest memory range (vm_mem_range). + * + * Parameters: + * gpa: guest physical address to translate + * len: number of bytes in the intended range + * + * Return values: + * void* to host virtual memory on success + * NULL on error, setting errno to: + * EFAULT: gpa falls outside guest memory ranges + * EINVAL: requested len extends beyond memory range + */ +void * +hvaddr_mem(paddr_t gpa, size_t len) +{ + struct vm_mem_range *vmr; + size_t off; + + vmr = find_gpa_range(¤t_vm->vm_params.vmc_params, gpa, len); + if (vmr == NULL) { + log_warnx("%s: failed - invalid gpa: 0x%lx\n", __func__, gpa); + errno = EFAULT; + return (NULL); + } + + off = gpa - vmr->vmr_gpa; + if (len > (vmr->vmr_size - off)) { + log_warnx("%s: failed - invalid memory range: gpa=0x%lx, " + "len=%zu", __func__, gpa, len); + errno = EINVAL; + return (NULL); + } + + return ((char *)vmr->vmr_va + off); +} + +/* + * vcpu_assert_irq + * + * Injects the specified IRQ on the supplied vcpu/vm + * + * Parameters: + * vm_id: VM ID to inject to + * vcpu_id: VCPU ID to inject to + * irq: IRQ to inject + */ +void +vcpu_assert_irq(uint32_t vm_id, uint32_t vcpu_id, int irq) +{ + i8259_assert_irq(irq); + + if (i8259_is_pending()) { + if (vcpu_intr(vm_id, vcpu_id, 1)) + fatalx("%s: can't assert INTR", __func__); + + vcpu_unhalt(vcpu_id); + vcpu_signal_run(vcpu_id); + } +} + +/* + * vcpu_deassert_pic_irq + * + * Clears the specified IRQ on the supplied vcpu/vm + * + * Parameters: + * vm_id: VM ID to clear in + * vcpu_id: VCPU ID to clear in + * irq: IRQ to clear + */ +void +vcpu_deassert_irq(uint32_t vm_id, uint32_t vcpu_id, int irq) +{ + i8259_deassert_irq(irq); + + if (!i8259_is_pending()) { + if (vcpu_intr(vm_id, vcpu_id, 0)) + fatalx("%s: can't deassert INTR for vm_id %d, " + "vcpu_id %d", __func__, vm_id, vcpu_id); + } +} +/* + * set_return_data + * + * Utility function for manipulating register data in vm exit info structs. This + * function ensures that the data is copied to the vei->vei.vei_data field with + * the proper size for the operation being performed. + * + * Parameters: + * vei: exit information + * data: return data + */ +void +set_return_data(struct vm_exit *vei, uint32_t data) +{ + switch (vei->vei.vei_size) { + case 1: + vei->vei.vei_data &= ~0xFF; + vei->vei.vei_data |= (uint8_t)data; + break; + case 2: + vei->vei.vei_data &= ~0xFFFF; + vei->vei.vei_data |= (uint16_t)data; + break; + case 4: + vei->vei.vei_data = data; + break; + } +} + +/* + * get_input_data + * + * Utility function for manipulating register data in vm exit info + * structs. This function ensures that the data is copied from the + * vei->vei.vei_data field with the proper size for the operation being + * performed. + * + * Parameters: + * vei: exit information + * data: location to store the result + */ +void +get_input_data(struct vm_exit *vei, uint32_t *data) +{ + switch (vei->vei.vei_size) { + case 1: + *data &= 0xFFFFFF00; + *data |= (uint8_t)vei->vei.vei_data; + break; + case 2: + *data &= 0xFFFF0000; + *data |= (uint16_t)vei->vei.vei_data; + break; + case 4: + *data = vei->vei.vei_data; + break; + default: + log_warnx("%s: invalid i/o size %d", __func__, + vei->vei.vei_size); + } + +} + +/* + * translate_gva + * + * Translates a guest virtual address to a guest physical address by walking + * the currently active page table (if needed). + * + * XXX ensure translate_gva updates the A bit in the PTE + * XXX ensure translate_gva respects segment base and limits in i386 mode + * XXX ensure translate_gva respects segment wraparound in i8086 mode + * XXX ensure translate_gva updates the A bit in the segment selector + * XXX ensure translate_gva respects CR4.LMSLE if available + * + * Parameters: + * exit: The VCPU this translation should be performed for (guest MMU settings + * are gathered from this VCPU) + * va: virtual address to translate + * pa: pointer to paddr_t variable that will receive the translated physical + * address. 'pa' is unchanged on error. + * mode: one of PROT_READ, PROT_WRITE, PROT_EXEC indicating the mode in which + * the address should be translated + * + * Return values: + * 0: the address was successfully translated - 'pa' contains the physical + * address currently mapped by 'va'. + * EFAULT: the PTE for 'VA' is unmapped. A #PF will be injected in this case + * and %cr2 set in the vcpu structure. + * EINVAL: an error occurred reading paging table structures + */ +int +translate_gva(struct vm_exit* exit, uint64_t va, uint64_t* pa, int mode) +{ + int level, shift, pdidx; + uint64_t pte, pt_paddr, pte_paddr, mask, low_mask, high_mask; + uint64_t shift_width, pte_size; + struct vcpu_reg_state *vrs; + + vrs = &exit->vrs; + + if (!pa) + return (EINVAL); + + if (!(vrs->vrs_crs[VCPU_REGS_CR0] & CR0_PG)) { + log_debug("%s: unpaged, va=pa=0x%llx", __func__, va); + *pa = va; + return (0); + } + + pt_paddr = vrs->vrs_crs[VCPU_REGS_CR3]; + + log_debug("%s: guest %%cr0=0x%llx, %%cr3=0x%llx", __func__, + vrs->vrs_crs[VCPU_REGS_CR0], vrs->vrs_crs[VCPU_REGS_CR3]); + + if (vrs->vrs_crs[VCPU_REGS_CR0] & CR0_PE) { + if (vrs->vrs_crs[VCPU_REGS_CR4] & CR4_PAE) { + pte_size = sizeof(uint64_t); + shift_width = 9; + + if (vrs->vrs_msrs[VCPU_REGS_EFER] & EFER_LMA) { + /* 4 level paging */ + level = 4; + mask = L4_MASK; + shift = L4_SHIFT; + } else { + /* 32 bit with PAE paging */ + level = 3; + mask = L3_MASK; + shift = L3_SHIFT; + } + } else { + /* 32 bit paging */ + level = 2; + shift_width = 10; + mask = 0xFFC00000; + shift = 22; + pte_size = sizeof(uint32_t); + } + } else + return (EINVAL); + + /* XXX: Check for R bit in segment selector and set A bit */ + + for (;level > 0; level--) { + pdidx = (va & mask) >> shift; + pte_paddr = (pt_paddr) + (pdidx * pte_size); + + log_debug("%s: read pte level %d @ GPA 0x%llx", __func__, + level, pte_paddr); + if (read_mem(pte_paddr, &pte, pte_size)) { + log_warn("%s: failed to read pte", __func__); + return (EFAULT); + } + + log_debug("%s: PTE @ 0x%llx = 0x%llx", __func__, pte_paddr, + pte); + + /* XXX: Set CR2 */ + if (!(pte & PG_V)) + return (EFAULT); + + /* XXX: Check for SMAP */ + if ((mode == PROT_WRITE) && !(pte & PG_RW)) + return (EPERM); + + if ((exit->cpl > 0) && !(pte & PG_u)) + return (EPERM); + + pte = pte | PG_U; + if (mode == PROT_WRITE) + pte = pte | PG_M; + if (write_mem(pte_paddr, &pte, pte_size)) { + log_warn("%s: failed to write back flags to pte", + __func__); + return (EIO); + } + + /* XXX: EINVAL if in 32bit and PG_PS is 1 but CR4.PSE is 0 */ + if (pte & PG_PS) + break; + + if (level > 1) { + pt_paddr = pte & PG_FRAME; + shift -= shift_width; + mask = mask >> shift_width; + } + } + + low_mask = (1 << shift) - 1; + high_mask = (((uint64_t)1ULL << ((pte_size * 8) - 1)) - 1) ^ low_mask; + *pa = (pte & high_mask) | (va & low_mask); + + log_debug("%s: final GPA for GVA 0x%llx = 0x%llx\n", __func__, va, *pa); + + return (0); +} + +int +intr_pending(struct vmd_vm *vm) +{ + /* XXX select active interrupt controller */ + return i8259_is_pending(); +} + +int +intr_ack(struct vmd_vm *vm) +{ + /* XXX select active interrupt controller */ + return i8259_ack(); +} + +void +intr_toggle_el(struct vmd_vm *vm, int irq, int val) +{ + /* XXX select active interrupt controller */ + pic_set_elcr(irq, val); +} + +int +vmd_check_vmh(struct vm_dump_header *vmh) +{ + int i; + unsigned int code, leaf; + unsigned int a, b, c, d; + + if (strncmp(vmh->vmh_signature, VM_DUMP_SIGNATURE, strlen(VM_DUMP_SIGNATURE)) != 0) { + log_warnx("%s: incompatible dump signature", __func__); + return (-1); + } + + if (vmh->vmh_version != VM_DUMP_VERSION) { + log_warnx("%s: incompatible dump version", __func__); + return (-1); + } + + for (i = 0; i < VM_DUMP_HEADER_CPUID_COUNT; i++) { + code = vmh->vmh_cpuids[i].code; + leaf = vmh->vmh_cpuids[i].leaf; + if (leaf != 0x00) { + log_debug("%s: invalid leaf 0x%x for code 0x%x", + __func__, leaf, code); + return (-1); + } + + switch (code) { + case 0x00: + CPUID_LEAF(code, leaf, a, b, c, d); + if (vmh->vmh_cpuids[i].a > a) { + log_debug("%s: incompatible cpuid level", + __func__); + return (-1); + } + if (!(vmh->vmh_cpuids[i].b == b && + vmh->vmh_cpuids[i].c == c && + vmh->vmh_cpuids[i].d == d)) { + log_debug("%s: incompatible cpu brand", + __func__); + return (-1); + } + break; + + case 0x01: + CPUID_LEAF(code, leaf, a, b, c, d); + if ((vmh->vmh_cpuids[i].c & c & VMM_CPUIDECX_MASK) != + (vmh->vmh_cpuids[i].c & VMM_CPUIDECX_MASK)) { + log_debug("%s: incompatible cpu features " + "code: 0x%x leaf: 0x%x reg: c", __func__, + code, leaf); + return (-1); + } + if ((vmh->vmh_cpuids[i].d & d & VMM_CPUIDEDX_MASK) != + (vmh->vmh_cpuids[i].d & VMM_CPUIDEDX_MASK)) { + log_debug("%s: incompatible cpu features " + "code: 0x%x leaf: 0x%x reg: d", __func__, + code, leaf); + return (-1); + } + break; + + case 0x07: + CPUID_LEAF(code, leaf, a, b, c, d); + if ((vmh->vmh_cpuids[i].b & b & VMM_SEFF0EBX_MASK) != + (vmh->vmh_cpuids[i].b & VMM_SEFF0EBX_MASK)) { + log_debug("%s: incompatible cpu features " + "code: 0x%x leaf: 0x%x reg: c", __func__, + code, leaf); + return (-1); + } + if ((vmh->vmh_cpuids[i].c & c & VMM_SEFF0ECX_MASK) != + (vmh->vmh_cpuids[i].c & VMM_SEFF0ECX_MASK)) { + log_debug("%s: incompatible cpu features " + "code: 0x%x leaf: 0x%x reg: d", __func__, + code, leaf); + return (-1); + } + break; + + case 0x0d: + CPUID_LEAF(code, leaf, a, b, c, d); + if (vmh->vmh_cpuids[i].b > b) { + log_debug("%s: incompatible cpu: insufficient " + "max save area for enabled XCR0 features", + __func__); + return (-1); + } + if (vmh->vmh_cpuids[i].c > c) { + log_debug("%s: incompatible cpu: insufficient " + "max save area for supported XCR0 features", + __func__); + return (-1); + } + break; + + case 0x80000001: + CPUID_LEAF(code, leaf, a, b, c, d); + if ((vmh->vmh_cpuids[i].a & a) != + vmh->vmh_cpuids[i].a) { + log_debug("%s: incompatible cpu features " + "code: 0x%x leaf: 0x%x reg: a", __func__, + code, leaf); + return (-1); + } + if ((vmh->vmh_cpuids[i].c & c) != + vmh->vmh_cpuids[i].c) { + log_debug("%s: incompatible cpu features " + "code: 0x%x leaf: 0x%x reg: c", __func__, + code, leaf); + return (-1); + } + if ((vmh->vmh_cpuids[i].d & d) != + vmh->vmh_cpuids[i].d) { + log_debug("%s: incompatible cpu features " + "code: 0x%x leaf: 0x%x reg: d", __func__, + code, leaf); + return (-1); + } + break; + + default: + log_debug("%s: unknown code 0x%x", __func__, code); + return (-1); + } + } + + return (0); +}