sync with OpenBSD -current

This commit is contained in:
purplerain 2024-06-29 09:21:17 +00:00
parent caabca1cee
commit aaa686b79e
Signed by: purplerain
GPG Key ID: F42C07F07E2E35B7
15 changed files with 537 additions and 267 deletions

View File

@ -1,4 +1,4 @@
/* $OpenBSD: radius.h,v 1.4 2024/02/25 06:22:45 yasuoka Exp $ */ /* $OpenBSD: radius.h,v 1.6 2024/06/29 07:19:18 yasuoka Exp $ */
/*- /*-
* Copyright (c) 2009 Internet Initiative Japan Inc. * Copyright (c) 2009 Internet Initiative Japan Inc.
@ -31,6 +31,7 @@
#define RADIUS_DEFAULT_PORT 1812 #define RADIUS_DEFAULT_PORT 1812
#define RADIUS_ACCT_DEFAULT_PORT 1813 #define RADIUS_ACCT_DEFAULT_PORT 1813
#define RADIUS_DAE_DEFAULT_PORT 3799
/* RADIUS codes */ /* RADIUS codes */
#define RADIUS_CODE_ACCESS_REQUEST 1 #define RADIUS_CODE_ACCESS_REQUEST 1
@ -42,6 +43,12 @@
#define RADIUS_CODE_STATUS_SERVER 12 #define RADIUS_CODE_STATUS_SERVER 12
#define RADIUS_CODE_STATUS_CLIENT 13 #define RADIUS_CODE_STATUS_CLIENT 13
#define RADIUS_CODE_DISCONNECT_REQUEST 40
#define RADIUS_CODE_DISCONNECT_ACK 41
#define RADIUS_CODE_DISCONNECT_NACK 42
#define RADIUS_CODE_COA_REQUEST 43
#define RADIUS_CODE_COA_ACK 44
#define RADIUS_CODE_COA_NACK 45
/* RADIUS attributes */ /* RADIUS attributes */
#define RADIUS_TYPE_USER_NAME 1 #define RADIUS_TYPE_USER_NAME 1
@ -143,6 +150,9 @@
#define RADIUS_TYPE_FRAMED_IPV6_ROUTE 99 #define RADIUS_TYPE_FRAMED_IPV6_ROUTE 99
#define RADIUS_TYPE_FRAMED_IPV6_POOL 100 #define RADIUS_TYPE_FRAMED_IPV6_POOL 100
/* RFC 5176 3.5. Error-Cause */
#define RADIUS_TYPE_ERROR_CAUSE 101
/* RFC 6911 3. Attributes */ /* RFC 6911 3. Attributes */
#define RADIUS_TYPE_FRAMED_IPV6_ADDRESS 168 #define RADIUS_TYPE_FRAMED_IPV6_ADDRESS 168
#define RADIUS_TYPE_DNS_SERVER_IPV6_ADDRESS 169 #define RADIUS_TYPE_DNS_SERVER_IPV6_ADDRESS 169
@ -320,6 +330,42 @@
#define RADIUS_TUNNEL_MEDIUM_TYPE_E163 7 /* E.163 (POTS) */ #define RADIUS_TUNNEL_MEDIUM_TYPE_E163 7 /* E.163 (POTS) */
#define RADIUS_TUNNEL_MEDIUM_TYPE_E164 8 /* E.164 (SMDS, Frame #define RADIUS_TUNNEL_MEDIUM_TYPE_E164 8 /* E.164 (SMDS, Frame
* Relay, ATM) */ * Relay, ATM) */
/* RFC 5167 3.5. Error-Cause */
/* Residual Session Context Removed */
#define RADIUS_ERROR_CAUSE_RESIDUAL_SESSION_REMOVED 201
/* Invalid EAP Packet (Ignored) */
#define RADIUS_ERROR_CAUSE_INVALID_EAP_PACKET 202
/* Unsupported Attribute */
#define RADIUS_ERROR_CAUSE_UNSUPPORTED_ATTRIBUTE 401
/* Missing Attribute */
#define RADIUS_ERROR_CAUSE_MISSING_ATTRIBUTE 402
/* NAS Identification Mismatch */
#define RADIUS_ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH 403
/* Invalid Request */
#define RADIUS_ERROR_CAUSE_INVALID_REQUEST 404
/* Unsupported Service */
#define RADIUS_ERROR_CAUSE_UNSUPPORTED_SERVICE 405
/* Unsupported Extension */
#define RADIUS_ERROR_CAUSE_UNSUPPORTED_EXTENSION 406
/* Invalid Attribute Valu */
#define RADIUS_ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE 407
/* Administratively Prohibited */
#define RADIUS_ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED 501
/* Request Not Routable (Proxy) */
#define RADIUS_ERROR_CAUSE_REQUEST_NOT_ROUTABLE 502
/* Session Context Not Found */
#define RADIUS_ERROR_CAUSE_SESSION_NOT_FOUND 503
/* Session Context Not Removable */
#define RADIUS_ERROR_CAUSE_SESSION_NOT_REMOVABLE 504
/* Other Proxy Processing Error */
#define RADIUS_ERROR_CAUSE_OTHER_PROXY_PROCESSING_ERROR 505
/* Resources Unavailable */
#define RADIUS_ERROR_CAUSE_RESOURCES_UNAVAILABLE 506
/* Request Initiated */
#define RADIUS_ERROR_CAUSE_REQUEST_INITIATED 507
/* Multiple Session Selection Unsupported */
#define RADIUS_ERROR_CAUSE_MULTI_SELECTION_UNSUPPORTED 508
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/cdefs.h> #include <sys/cdefs.h>

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: SSL_CTX_set_alpn_select_cb.3,v 1.8 2021/09/10 09:25:29 tb Exp $ .\" $OpenBSD: SSL_CTX_set_alpn_select_cb.3,v 1.9 2024/06/28 14:48:43 tb Exp $
.\" OpenSSL 87b81496 Apr 19 12:38:27 2017 -0400 .\" OpenSSL 87b81496 Apr 19 12:38:27 2017 -0400
.\" OpenSSL b97fdb57 Nov 11 09:33:09 2016 +0100 .\" 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 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
.\" OF THE POSSIBILITY OF SUCH DAMAGE. .\" OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.Dd $Mdocdate: September 10 2021 $ .Dd $Mdocdate: June 28 2024 $
.Dt SSL_CTX_SET_ALPN_SELECT_CB 3 .Dt SSL_CTX_SET_ALPN_SELECT_CB 3
.Os .Os
.Sh NAME .Sh NAME
@ -153,6 +153,15 @@ It implements the standard protocol selection.
It is expected that this function is called from the application It is expected that this function is called from the application
callback callback
.Fa cb . .Fa cb .
If
.Fn SSL_select_next_proto
returns
.Dv OPENSSL_NPN_NO_OVERLAP ,
.Fa cb
should ignore
.Fa out
and fail by returning
.Dv SSL_TLSEXT_ERR_ALERT_FATAL .
The protocol data in The protocol data in
.Fa server , .Fa server ,
.Fa server_len .Fa server_len
@ -175,7 +184,8 @@ value will point into either
.Fa server .Fa server
or or
.Fa client , .Fa client ,
so it should be copied immediately. so it must not be modified and
should be copied immediately.
If no match is found, the first item in If no match is found, the first item in
.Fa client , .Fa client ,
.Fa client_len .Fa client_len

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssl_lib.c,v 1.323 2024/04/15 16:00:05 tb Exp $ */ /* $OpenBSD: ssl_lib.c,v 1.325 2024/06/29 07:34:12 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved. * All rights reserved.
* *
@ -1785,45 +1785,70 @@ LSSL_ALIAS(SSL_get_servername_type);
* It returns either: * It returns either:
* OPENSSL_NPN_NEGOTIATED if a common protocol was found, or * OPENSSL_NPN_NEGOTIATED if a common protocol was found, or
* OPENSSL_NPN_NO_OVERLAP if the fallback case was reached. * OPENSSL_NPN_NO_OVERLAP if the fallback case was reached.
*
* XXX - the out argument points into server_list or client_list and should
* therefore really be const. We can't fix that without breaking the callers.
*/ */
int int
SSL_select_next_proto(unsigned char **out, unsigned char *outlen, SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
const unsigned char *server, unsigned int server_len, const unsigned char *server_list, unsigned int server_list_len,
const unsigned char *client, unsigned int client_len) const unsigned char *client_list, unsigned int client_list_len)
{ {
unsigned int i, j; CBS client, client_proto, server, server_proto;
const unsigned char *result;
int status = OPENSSL_NPN_UNSUPPORTED; *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))
goto err;
/* /*
* For each protocol in server preference order, * Use first client protocol as fallback. This is one way of doing NPN's
* see if we support it. * "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.
*/ */
for (i = 0; i < server_len; ) {
for (j = 0; j < client_len; ) { if (!CBS_get_u8_length_prefixed(&client, &client_proto))
if (server[i] == client[j] && goto err;
memcmp(&server[i + 1],
&client[j + 1], server[i]) == 0) { *out = (unsigned char *)CBS_data(&client_proto);
/* We found a match */ *outlen = CBS_len(&client_proto);
result = &server[i];
status = OPENSSL_NPN_NEGOTIATED; /* Now check that the server list is well-formed. */
goto found; CBS_init(&server, server_list, server_list_len);
if (!tlsext_alpn_check_format(&server))
goto err;
/*
* Walk the server list and select the first protocol that appears in
* the client list.
*/
while (CBS_len(&server) > 0) {
if (!CBS_get_u8_length_prefixed(&server, &server_proto))
goto err;
CBS_init(&client, client_list, client_list_len);
while (CBS_len(&client) > 0) {
if (!CBS_get_u8_length_prefixed(&client, &client_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);
return OPENSSL_NPN_NEGOTIATED;
} }
j += client[j];
j++;
} }
i += server[i];
i++;
} }
/* There's no overlap between our protocols and the server's list. */ err:
result = client; return OPENSSL_NPN_NO_OVERLAP;
status = OPENSSL_NPN_NO_OVERLAP;
found:
*out = (unsigned char *) result + 1;
*outlen = result[0];
return (status);
} }
LSSL_ALIAS(SSL_select_next_proto); LSSL_ALIAS(SSL_select_next_proto);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssl_packet.c,v 1.15 2022/11/26 16:08:56 tb Exp $ */ /* $OpenBSD: ssl_packet.c,v 1.16 2024/06/28 13:37:49 jsing Exp $ */
/* /*
* Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org> * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org>
* *
@ -18,34 +18,6 @@
#include "bytestring.h" #include "bytestring.h"
#include "ssl_local.h" #include "ssl_local.h"
static int
ssl_is_sslv2_client_hello(CBS *header)
{
uint16_t record_length;
uint8_t message_type;
CBS cbs;
CBS_dup(header, &cbs);
if (!CBS_get_u16(&cbs, &record_length) ||
!CBS_get_u8(&cbs, &message_type))
return 0;
/*
* The SSLv2 record length field uses variable length (2 or 3 byte)
* encoding. Given the size of a client hello, we expect/require the
* 2-byte form which is indicated by a one in the most significant bit.
*/
if ((record_length & 0x8000) == 0)
return 0;
if ((record_length & ~0x8000) < 3)
return 0;
if (message_type != SSL2_MT_CLIENT_HELLO)
return 0;
return 1;
}
static int static int
ssl_is_sslv3_handshake(CBS *header) ssl_is_sslv3_handshake(CBS *header)
{ {
@ -67,164 +39,6 @@ ssl_is_sslv3_handshake(CBS *header)
return 1; return 1;
} }
static int
ssl_convert_sslv2_client_hello(SSL *s)
{
CBB cbb, handshake, client_hello, cipher_suites, compression, session_id;
CBS cbs, challenge, cipher_specs, session;
uint16_t record_length, client_version, cipher_specs_length;
uint16_t session_id_length, challenge_length;
unsigned char *client_random = NULL, *data = NULL;
size_t data_len, pad_len, len;
uint32_t cipher_spec;
uint8_t message_type;
unsigned char *pad;
int ret = -1;
int n;
memset(&cbb, 0, sizeof(cbb));
CBS_init(&cbs, s->packet, SSL3_RT_HEADER_LENGTH);
if (!CBS_get_u16(&cbs, &record_length) ||
!CBS_get_u8(&cbs, &message_type) ||
!CBS_get_u16(&cbs, &client_version))
return -1;
/*
* The SSLv2 record length field uses variable length (2 or 3 byte)
* encoding. Given the size of a client hello, we expect/require the
* 2-byte form which is indicated by a one in the most significant bit.
* Also note that the record length value does not include the bytes
* used for the record length field.
*/
if ((record_length & 0x8000) == 0)
return -1;
record_length &= ~0x8000;
if (record_length < SSL3_RT_HEADER_LENGTH - 2)
return -1;
if (message_type != SSL2_MT_CLIENT_HELLO)
return -1;
if (record_length < 9) {
SSLerror(s, SSL_R_RECORD_LENGTH_MISMATCH);
return -1;
}
if (record_length > 4096) {
SSLerror(s, SSL_R_RECORD_TOO_LARGE);
return -1;
}
n = ssl3_packet_extend(s, record_length + 2);
if (n != record_length + 2)
return n;
tls1_transcript_record(s, s->packet + 2,
s->packet_length - 2);
s->mac_packet = 0;
if (s->msg_callback)
s->msg_callback(0, SSL2_VERSION, 0,
s->packet + 2, s->packet_length - 2, s,
s->msg_callback_arg);
/* Decode the SSLv2 record containing the client hello. */
CBS_init(&cbs, s->packet, s->packet_length);
if (!CBS_get_u16(&cbs, &record_length))
return -1;
if (!CBS_get_u8(&cbs, &message_type))
return -1;
if (!CBS_get_u16(&cbs, &client_version))
return -1;
if (!CBS_get_u16(&cbs, &cipher_specs_length))
return -1;
if (!CBS_get_u16(&cbs, &session_id_length))
return -1;
if (!CBS_get_u16(&cbs, &challenge_length))
return -1;
if (!CBS_get_bytes(&cbs, &cipher_specs, cipher_specs_length))
return -1;
if (!CBS_get_bytes(&cbs, &session, session_id_length))
return -1;
if (!CBS_get_bytes(&cbs, &challenge, challenge_length))
return -1;
if (CBS_len(&cbs) != 0) {
SSLerror(s, SSL_R_RECORD_LENGTH_MISMATCH);
return -1;
}
/*
* Convert SSLv2 challenge to SSLv3/TLS client random, by truncating or
* left-padding with zero bytes.
*/
if ((client_random = malloc(SSL3_RANDOM_SIZE)) == NULL)
goto err;
if (!CBB_init_fixed(&cbb, client_random, SSL3_RANDOM_SIZE))
goto err;
if ((len = CBS_len(&challenge)) > SSL3_RANDOM_SIZE)
len = SSL3_RANDOM_SIZE;
pad_len = SSL3_RANDOM_SIZE - len;
if (!CBB_add_space(&cbb, &pad, pad_len))
goto err;
memset(pad, 0, pad_len);
if (!CBB_add_bytes(&cbb, CBS_data(&challenge), len))
goto err;
if (!CBB_finish(&cbb, NULL, NULL))
goto err;
/* Build SSLv3/TLS record with client hello. */
if (!CBB_init(&cbb, SSL3_RT_MAX_PLAIN_LENGTH))
goto err;
if (!CBB_add_u8(&cbb, SSL3_RT_HANDSHAKE))
goto err;
if (!CBB_add_u16(&cbb, 0x0301))
goto err;
if (!CBB_add_u16_length_prefixed(&cbb, &handshake))
goto err;
if (!CBB_add_u8(&handshake, SSL3_MT_CLIENT_HELLO))
goto err;
if (!CBB_add_u24_length_prefixed(&handshake, &client_hello))
goto err;
if (!CBB_add_u16(&client_hello, client_version))
goto err;
if (!CBB_add_bytes(&client_hello, client_random, SSL3_RANDOM_SIZE))
goto err;
if (!CBB_add_u8_length_prefixed(&client_hello, &session_id))
goto err;
if (!CBB_add_u16_length_prefixed(&client_hello, &cipher_suites))
goto err;
while (CBS_len(&cipher_specs) > 0) {
if (!CBS_get_u24(&cipher_specs, &cipher_spec))
goto err;
if ((cipher_spec & 0xff0000) != 0)
continue;
if (!CBB_add_u16(&cipher_suites, cipher_spec & 0xffff))
goto err;
}
if (!CBB_add_u8_length_prefixed(&client_hello, &compression))
goto err;
if (!CBB_add_u8(&compression, 0))
goto err;
if (!CBB_finish(&cbb, &data, &data_len))
goto err;
if (data_len > s->s3->rbuf.len)
goto err;
s->packet = s->s3->rbuf.buf;
s->packet_length = data_len;
memcpy(s->packet, data, data_len);
ret = 1;
err:
CBB_cleanup(&cbb);
free(client_random);
free(data);
return (ret);
}
/* /*
* Potentially do legacy processing on the first packet received by a TLS * Potentially do legacy processing on the first packet received by a TLS
* server. We return 1 if we want SSLv3/TLS record processing to continue * server. We return 1 if we want SSLv3/TLS record processing to continue
@ -233,7 +47,6 @@ ssl_convert_sslv2_client_hello(SSL *s)
int int
ssl_server_legacy_first_packet(SSL *s) ssl_server_legacy_first_packet(SSL *s)
{ {
uint16_t min_version;
const char *data; const char *data;
CBS header; CBS header;
@ -249,23 +62,6 @@ ssl_server_legacy_first_packet(SSL *s)
if (s->method->min_tls_version == s->method->max_tls_version) if (s->method->min_tls_version == s->method->max_tls_version)
return 1; return 1;
if (ssl_is_sslv2_client_hello(&header) == 1) {
/* Only permit SSLv2 client hellos if TLSv1.0 is enabled. */
if (ssl_enabled_tls_version_range(s, &min_version, NULL) != 1) {
SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE);
return -1;
}
if (min_version > TLS1_VERSION)
return 1;
if (ssl_convert_sslv2_client_hello(s) != 1) {
SSLerror(s, SSL_R_BAD_PACKET_LENGTH);
return -1;
}
return 1;
}
/* Ensure that we have SSL3_RT_HEADER_LENGTH (5 bytes) of the packet. */ /* Ensure that we have SSL3_RT_HEADER_LENGTH (5 bytes) of the packet. */
if (CBS_len(&header) != SSL3_RT_HEADER_LENGTH) { if (CBS_len(&header) != SSL3_RT_HEADER_LENGTH) {
SSLerror(s, ERR_R_INTERNAL_ERROR); SSLerror(s, ERR_R_INTERNAL_ERROR);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssl_set_alpn_protos.c,v 1.2 2022/07/21 03:59:04 tb Exp $ */ /* $OpenBSD: ssl_set_alpn_protos.c,v 1.3 2024/06/28 14:50:37 tb Exp $ */
/* /*
* Copyright (c) 2022 Theo Buehler <tb@openbsd.org> * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
* *
@ -20,6 +20,21 @@
#include <openssl/ssl.h> #include <openssl/ssl.h>
static void
hexdump(const unsigned char *buf, size_t len)
{
size_t i;
if (buf == NULL) {
fprintf(stderr, "(null), len %zu\n", len);
return;
}
for (i = 1; i <= len; i++)
fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
if (len % 8)
fprintf(stderr, "\n");
}
struct alpn_test { struct alpn_test {
const char *description; const char *description;
const uint8_t protocols[24]; const uint8_t protocols[24];
@ -186,6 +201,279 @@ test_ssl_set_alpn_protos_edge_cases(void)
return failed; return failed;
} }
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;
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,
.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,
.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,
.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,
.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,
.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,
.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,
.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,
.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,
.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,
.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,
.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,
.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,
.want_out = NULL,
.want_out_len = 0,
.want_ret = OPENSSL_NPN_NO_OVERLAP,
},
/*
* Some non-toy examples.
*/
{
.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,
.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,
.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,
.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,
.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,
.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,
.want_out = NULL,
.want_out_len = 0,
.want_ret = OPENSSL_NPN_NO_OVERLAP,
},
};
#define N_SELECT_NEXT_PROTO_TESTS \
(sizeof(select_next_proto_tests) / sizeof(select_next_proto_tests[0]))
static int
select_next_proto_testcase(const struct select_next_proto_test *test)
{
unsigned char *out;
unsigned char out_len;
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);
if (ret != test->want_ret || out_len != test->want_out_len ||
(out == NULL && test->want_out != NULL) ||
(out != NULL && test->want_out == NULL) ||
(out != NULL && test->want_out != NULL &&
memcmp(out, test->want_out, out_len) != 0)) {
fprintf(stderr, "FAIL: ret: %u (want %u), out_len: %u (want %u)\n",
ret, test->want_ret, out_len, test->want_out_len);
fprintf(stderr, "\ngot:\n");
hexdump(out, out_len);
fprintf(stderr, "\nwant:\n");
hexdump(test->want_out, test->want_out_len);
fprintf(stderr, "\nserver:\n");
hexdump(test->server_list, test->server_list_len);
fprintf(stderr, "\nclient:\n");
hexdump(test->client_list, test->client_list_len);
fprintf(stderr, "\n");
failed = 1;
}
return failed;
}
static int
test_ssl_select_next_proto(void)
{
size_t i;
int failed = 0;
for (i = 0; i < N_SELECT_NEXT_PROTO_TESTS; i++)
failed |= select_next_proto_testcase(&select_next_proto_tests[i]);
return failed;
}
int int
main(void) main(void)
{ {
@ -197,6 +485,8 @@ main(void)
failed |= test_ssl_set_alpn_protos_edge_cases(); failed |= test_ssl_set_alpn_protos_edge_cases();
failed |= test_ssl_select_next_proto();
if (!failed) if (!failed)
printf("PASS %s\n", __FILE__); printf("PASS %s\n", __FILE__);

View File

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.105 2023/07/06 07:45:56 deraadt Exp $ # $OpenBSD: Makefile,v 1.106 2024/06/28 21:36:05 bluhm Exp $
SUBDIR+= accept access SUBDIR+= accept access
SUBDIR+= bind SUBDIR+= bind
@ -22,7 +22,7 @@ SUBDIR+= setuid
.endif .endif
SUBDIR+= signal sosplice stackjmp stackpivot syscall_segment SUBDIR+= signal sosplice stackjmp stackpivot syscall_segment
SUBDIR+= sysvmsg sysvsem sysvshm SUBDIR+= sysvmsg sysvsem sysvshm
SUBDIR+= unalign unfdpass unixsockets unveil unveil-unmount SUBDIR+= unalign unfdpass unixsockets unp-write-closed unveil unveil-unmount
SUBDIR+= wait SUBDIR+= wait
SUBDIR+= xonly SUBDIR+= xonly

View File

@ -0,0 +1,5 @@
# $OpenBSD: Makefile,v 1.1.1.1 2024/06/28 21:07:27 bluhm Exp $
PROG= unp-write-closed
.include <bsd.regress.mk>

View File

@ -0,0 +1,83 @@
/* $OpenBSD: unp-write-closed.c,v 1.1.1.1 2024/06/28 21:07:27 bluhm Exp $ */
/*
* Copyright (c) 2024 Vitaliy Makkoveev <mvs@openbsd.org>
* Copyright (c) 2024 Alenander Bluhm <bluhm@openbsd.org>
*
* 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 <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <err.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
sig_atomic_t done = 0;
void
handler(int sigraised)
{
done = 1;
}
int
main(int argc, char *argv[])
{
int i, s[2], status;
pid_t pid;
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
err(1, "signal pipe");
if (signal(SIGALRM, handler) == SIG_ERR)
err(1, "signal alrm");
alarm(30);
while (!done) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) < 0)
err(1, "socketpair");
switch ((pid = fork())) {
case -1:
err(1, "fork");
case 0:
if (close(s[0]) < 0)
err(1, "child close 0");
if (close(s[1]) < 0)
err(1, "child close 1");
return 0;
default:
if (close(s[1]) < 0)
err(1, "parent close 1");
for (i = 1000000; i > 0; i--) {
if (write(s[0], "1", 1) < 0)
break;
}
if (i <= 0)
errx(1, "write did not fail");
if (errno != EPIPE)
err(1, "write");
if (close(s[0]) < 0)
err(1, "parent close 1");
if (waitpid(pid, &status, 0) < 0)
err(1, "waitpid");
if (status != 0)
errx(1, "child status %d", status);
break;
}
}
return 0;
}

View File

@ -164,6 +164,8 @@ static void sumo_construct_vid_mapping_table(struct amdgpu_device *adev,
for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) { for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) {
if (table[i].ulSupportedSCLK != 0) { if (table[i].ulSupportedSCLK != 0) {
if (table[i].usVoltageIndex >= SUMO_MAX_NUMBER_VOLTAGES)
continue;
vid_mapping_table->entries[table[i].usVoltageIndex].vid_7bit = vid_mapping_table->entries[table[i].usVoltageIndex].vid_7bit =
table[i].usVoltageID; table[i].usVoltageID;
vid_mapping_table->entries[table[i].usVoltageIndex].vid_2bit = vid_mapping_table->entries[table[i].usVoltageIndex].vid_2bit =

View File

@ -393,6 +393,10 @@ bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp)
struct intel_encoder *encoder = &intel_dig_port->base; struct intel_encoder *encoder = &intel_dig_port->base;
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
/* eDP MSO is not compatible with joiner */
if (intel_dp->mso_link_count)
return false;
return DISPLAY_VER(dev_priv) >= 12 || return DISPLAY_VER(dev_priv) >= 12 ||
(DISPLAY_VER(dev_priv) == 11 && (DISPLAY_VER(dev_priv) == 11 &&
encoder->port != PORT_A); encoder->port != PORT_A);

View File

@ -1621,6 +1621,8 @@ void sumo_construct_vid_mapping_table(struct radeon_device *rdev,
for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) { for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) {
if (table[i].ulSupportedSCLK != 0) { if (table[i].ulSupportedSCLK != 0) {
if (table[i].usVoltageIndex >= SUMO_MAX_NUMBER_VOLTAGES)
continue;
vid_mapping_table->entries[table[i].usVoltageIndex].vid_7bit = vid_mapping_table->entries[table[i].usVoltageIndex].vid_7bit =
table[i].usVoltageID; table[i].usVoltageID;
vid_mapping_table->entries[table[i].usVoltageIndex].vid_2bit = vid_mapping_table->entries[table[i].usVoltageIndex].vid_2bit =

View File

@ -1,4 +1,4 @@
/* $OpenBSD: if_vio.c,v 1.41 2024/06/26 01:40:49 jsg Exp $ */ /* $OpenBSD: if_vio.c,v 1.42 2024/06/28 14:46:31 jan Exp $ */
/* /*
* Copyright (c) 2012 Stefan Fritsch, Alexander Fiveg. * Copyright (c) 2012 Stefan Fritsch, Alexander Fiveg.
@ -419,7 +419,7 @@ vio_alloc_mem(struct vio_softc *sc)
*/ */
allocsize = sizeof(struct virtio_net_hdr) * txqsize; allocsize = sizeof(struct virtio_net_hdr) * txqsize;
if (vsc->sc_nvqs == 3) { if (virtio_has_feature(vsc, VIRTIO_NET_F_CTRL_VQ)) {
allocsize += sizeof(struct virtio_net_ctrl_cmd) * 1; allocsize += sizeof(struct virtio_net_ctrl_cmd) * 1;
allocsize += sizeof(struct virtio_net_ctrl_status) * 1; allocsize += sizeof(struct virtio_net_ctrl_status) * 1;
allocsize += sizeof(struct virtio_net_ctrl_rx) * 1; allocsize += sizeof(struct virtio_net_ctrl_rx) * 1;
@ -436,7 +436,7 @@ vio_alloc_mem(struct vio_softc *sc)
kva = sc->sc_dma_kva; kva = sc->sc_dma_kva;
sc->sc_tx_hdrs = (struct virtio_net_hdr*)(kva + offset); sc->sc_tx_hdrs = (struct virtio_net_hdr*)(kva + offset);
offset += sizeof(struct virtio_net_hdr) * txqsize; offset += sizeof(struct virtio_net_hdr) * txqsize;
if (vsc->sc_nvqs == 3) { if (virtio_has_feature(vsc, VIRTIO_NET_F_CTRL_VQ)) {
sc->sc_ctrl_cmd = (void*)(kva + offset); sc->sc_ctrl_cmd = (void*)(kva + offset);
offset += sizeof(*sc->sc_ctrl_cmd); offset += sizeof(*sc->sc_ctrl_cmd);
sc->sc_ctrl_status = (void*)(kva + offset); sc->sc_ctrl_status = (void*)(kva + offset);
@ -529,7 +529,7 @@ vio_needs_reset(struct vio_softc *sc)
{ {
if (virtio_get_status(sc->sc_virtio) & if (virtio_get_status(sc->sc_virtio) &
VIRTIO_CONFIG_DEVICE_STATUS_DEVICE_NEEDS_RESET) { VIRTIO_CONFIG_DEVICE_STATUS_DEVICE_NEEDS_RESET) {
printf("%s: device needs reset", sc->sc_dev.dv_xname); printf("%s: device needs reset\n", sc->sc_dev.dv_xname);
vio_ctrl_wakeup(sc, RESET); vio_ctrl_wakeup(sc, RESET);
return 1; return 1;
} }
@ -604,8 +604,7 @@ vio_attach(struct device *parent, struct device *self, void *aux)
virtio_postpone_intr_far(&sc->sc_vq[VQTX]); virtio_postpone_intr_far(&sc->sc_vq[VQTX]);
else else
virtio_stop_vq_intr(vsc, &sc->sc_vq[VQTX]); virtio_stop_vq_intr(vsc, &sc->sc_vq[VQTX]);
if (virtio_has_feature(vsc, VIRTIO_NET_F_CTRL_VQ) && if (virtio_has_feature(vsc, VIRTIO_NET_F_CTRL_VQ)) {
virtio_has_feature(vsc, VIRTIO_NET_F_CTRL_RX)) {
if (virtio_alloc_vq(vsc, &sc->sc_vq[VQCTL], 2, NBPG, 1, if (virtio_alloc_vq(vsc, &sc->sc_vq[VQCTL], 2, NBPG, 1,
"control") == 0) { "control") == 0) {
sc->sc_vq[VQCTL].vq_done = vio_ctrleof; sc->sc_vq[VQCTL].vq_done = vio_ctrleof;
@ -760,7 +759,7 @@ vio_stop(struct ifnet *ifp, int disable)
/* only way to stop I/O and DMA is resetting... */ /* only way to stop I/O and DMA is resetting... */
virtio_reset(vsc); virtio_reset(vsc);
vio_rxeof(sc); vio_rxeof(sc);
if (vsc->sc_nvqs >= 3) if (virtio_has_feature(vsc, VIRTIO_NET_F_CTRL_VQ))
vio_ctrl_wakeup(sc, RESET); vio_ctrl_wakeup(sc, RESET);
vio_tx_drain(sc); vio_tx_drain(sc);
if (disable) if (disable)
@ -769,10 +768,10 @@ vio_stop(struct ifnet *ifp, int disable)
virtio_reinit_start(vsc); virtio_reinit_start(vsc);
virtio_start_vq_intr(vsc, &sc->sc_vq[VQRX]); virtio_start_vq_intr(vsc, &sc->sc_vq[VQRX]);
virtio_stop_vq_intr(vsc, &sc->sc_vq[VQTX]); virtio_stop_vq_intr(vsc, &sc->sc_vq[VQTX]);
if (vsc->sc_nvqs >= 3) if (virtio_has_feature(vsc, VIRTIO_NET_F_CTRL_VQ))
virtio_start_vq_intr(vsc, &sc->sc_vq[VQCTL]); virtio_start_vq_intr(vsc, &sc->sc_vq[VQCTL]);
virtio_reinit_end(vsc); virtio_reinit_end(vsc);
if (vsc->sc_nvqs >= 3) if (virtio_has_feature(vsc, VIRTIO_NET_F_CTRL_VQ))
vio_ctrl_wakeup(sc, FREE); vio_ctrl_wakeup(sc, FREE);
} }
@ -959,7 +958,7 @@ vio_dump(struct vio_softc *sc)
printf("rx tick active: %d\n", !timeout_triggered(&sc->sc_rxtick)); printf("rx tick active: %d\n", !timeout_triggered(&sc->sc_rxtick));
printf("RX virtqueue:\n"); printf("RX virtqueue:\n");
virtio_vq_dump(&vsc->sc_vqs[VQRX]); virtio_vq_dump(&vsc->sc_vqs[VQRX]);
if (vsc->sc_nvqs == 3) { if (virtio_has_feature(vsc, VIRTIO_NET_F_CTRL_VQ)) {
printf("CTL virtqueue:\n"); printf("CTL virtqueue:\n");
virtio_vq_dump(&vsc->sc_vqs[VQCTL]); virtio_vq_dump(&vsc->sc_vqs[VQCTL]);
printf("ctrl_inuse: %d\n", sc->sc_ctrl_inuse); printf("ctrl_inuse: %d\n", sc->sc_ctrl_inuse);
@ -1530,7 +1529,7 @@ vio_wait_ctrl_done(struct vio_softc *sc)
r = tsleep_nsec(&sc->sc_ctrl_inuse, PRIBIO, "viodone", r = tsleep_nsec(&sc->sc_ctrl_inuse, PRIBIO, "viodone",
VIRTIO_NET_CTRL_TIMEOUT); VIRTIO_NET_CTRL_TIMEOUT);
if (r == EWOULDBLOCK) { if (r == EWOULDBLOCK) {
printf("%s: ctrl queue timeout", sc->sc_dev.dv_xname); printf("%s: ctrl queue timeout\n", sc->sc_dev.dv_xname);
vio_ctrl_wakeup(sc, RESET); vio_ctrl_wakeup(sc, RESET);
return ENXIO; return ENXIO;
} }
@ -1648,7 +1647,7 @@ vio_iff(struct vio_softc *sc)
ifp->if_flags &= ~IFF_ALLMULTI; ifp->if_flags &= ~IFF_ALLMULTI;
if (vsc->sc_nvqs < 3) { if (!virtio_has_feature(vsc, VIRTIO_NET_F_CTRL_RX)) {
/* no ctrl vq; always promisc */ /* no ctrl vq; always promisc */
ifp->if_flags |= IFF_ALLMULTI | IFF_PROMISC; ifp->if_flags |= IFF_ALLMULTI | IFF_PROMISC;
return; return;
@ -1682,9 +1681,6 @@ vio_iff(struct vio_softc *sc)
sc->sc_ctrl_mac_tbl_mc->nentries = rxfilter ? nentries : 0; sc->sc_ctrl_mac_tbl_mc->nentries = rxfilter ? nentries : 0;
if (vsc->sc_nvqs < 3)
return;
r = vio_set_rx_filter(sc); r = vio_set_rx_filter(sc);
if (r == EIO) if (r == EIO)
allmulti = 1; /* fallback */ allmulti = 1; /* fallback */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: uipc_socket2.c,v 1.155 2024/05/17 19:11:14 mvs Exp $ */ /* $OpenBSD: uipc_socket2.c,v 1.156 2024/06/28 21:30:24 mvs Exp $ */
/* $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $ */ /* $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $ */
/* /*
@ -160,8 +160,6 @@ void
soisdisconnected(struct socket *so) soisdisconnected(struct socket *so)
{ {
soassertlocked(so); soassertlocked(so);
so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
so->so_state |= SS_ISDISCONNECTED;
mtx_enter(&so->so_rcv.sb_mtx); mtx_enter(&so->so_rcv.sb_mtx);
so->so_rcv.sb_state |= SS_CANTRCVMORE; so->so_rcv.sb_state |= SS_CANTRCVMORE;
@ -171,6 +169,9 @@ soisdisconnected(struct socket *so)
so->so_snd.sb_state |= SS_CANTSENDMORE; so->so_snd.sb_state |= SS_CANTSENDMORE;
mtx_leave(&so->so_snd.sb_mtx); mtx_leave(&so->so_snd.sb_mtx);
so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
so->so_state |= SS_ISDISCONNECTED;
wakeup(&so->so_timeo); wakeup(&so->so_timeo);
sowwakeup(so); sowwakeup(so);
sorwakeup(so); sorwakeup(so);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: uipc_usrreq.c,v 1.207 2024/06/26 12:23:36 mvs Exp $ */ /* $OpenBSD: uipc_usrreq.c,v 1.208 2024/06/28 21:30:24 mvs Exp $ */
/* $NetBSD: uipc_usrreq.c,v 1.18 1996/02/09 19:00:50 christos Exp $ */ /* $NetBSD: uipc_usrreq.c,v 1.18 1996/02/09 19:00:50 christos Exp $ */
/* /*
@ -513,6 +513,14 @@ uipc_send(struct socket *so, struct mbuf *m, struct mbuf *nam,
goto out; goto out;
} }
/*
* We hold both solock() and `sb_mtx' mutex while modifying
* SS_CANTSENDMORE flag. solock() is enough to check it.
*/
if (so->so_snd.sb_state & SS_CANTSENDMORE) {
error = EPIPE;
goto dispose;
}
if (unp->unp_conn == NULL) { if (unp->unp_conn == NULL) {
error = ENOTCONN; error = ENOTCONN;
goto dispose; goto dispose;
@ -531,12 +539,6 @@ uipc_send(struct socket *so, struct mbuf *m, struct mbuf *nam,
*/ */
mtx_enter(&so2->so_rcv.sb_mtx); mtx_enter(&so2->so_rcv.sb_mtx);
mtx_enter(&so->so_snd.sb_mtx); mtx_enter(&so->so_snd.sb_mtx);
if (so->so_snd.sb_state & SS_CANTSENDMORE) {
mtx_leave(&so->so_snd.sb_mtx);
mtx_leave(&so2->so_rcv.sb_mtx);
error = EPIPE;
goto dispose;
}
if (control) { if (control) {
if (sbappendcontrol(so2, &so2->so_rcv, m, control)) { if (sbappendcontrol(so2, &so2->so_rcv, m, control)) {
control = NULL; control = NULL;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: fifo_vnops.c,v 1.105 2024/05/03 17:43:09 mvs Exp $ */ /* $OpenBSD: fifo_vnops.c,v 1.106 2024/06/28 21:30:24 mvs Exp $ */
/* $NetBSD: fifo_vnops.c,v 1.18 1996/03/16 23:52:42 christos Exp $ */ /* $NetBSD: fifo_vnops.c,v 1.18 1996/03/16 23:52:42 christos Exp $ */
/* /*
@ -174,10 +174,16 @@ fifo_open(void *v)
return (error); return (error);
} }
fip->fi_readers = fip->fi_writers = 0; fip->fi_readers = fip->fi_writers = 0;
/*
* Should take both solock() and `sb_mtx' mutex for
* SS_CANTSENDMORE flag modifications.
*/
solock(wso);
mtx_enter(&wso->so_snd.sb_mtx); mtx_enter(&wso->so_snd.sb_mtx);
wso->so_snd.sb_state |= SS_CANTSENDMORE; wso->so_snd.sb_state |= SS_CANTSENDMORE;
wso->so_snd.sb_lowat = PIPE_BUF; wso->so_snd.sb_lowat = PIPE_BUF;
mtx_leave(&wso->so_snd.sb_mtx); mtx_leave(&wso->so_snd.sb_mtx);
sounlock(wso);
} else { } else {
rso = fip->fi_readsock; rso = fip->fi_readsock;
wso = fip->fi_writesock; wso = fip->fi_writesock;
@ -185,9 +191,11 @@ fifo_open(void *v)
if (ap->a_mode & FREAD) { if (ap->a_mode & FREAD) {
fip->fi_readers++; fip->fi_readers++;
if (fip->fi_readers == 1) { if (fip->fi_readers == 1) {
solock(wso);
mtx_enter(&wso->so_snd.sb_mtx); mtx_enter(&wso->so_snd.sb_mtx);
wso->so_snd.sb_state &= ~SS_CANTSENDMORE; wso->so_snd.sb_state &= ~SS_CANTSENDMORE;
mtx_leave(&wso->so_snd.sb_mtx); mtx_leave(&wso->so_snd.sb_mtx);
sounlock(wso);
if (fip->fi_writers > 0) if (fip->fi_writers > 0)
wakeup(&fip->fi_writers); wakeup(&fip->fi_writers);
} }