From c170139b8d6adc17c9e446b9f7a98e45fc3fb794 Mon Sep 17 00:00:00 2001 From: purplerain Date: Wed, 22 Jan 2025 18:06:03 +0000 Subject: [PATCH] sync with OpenBSD -current --- lib/libcrypto/bn/bn_exp.c | 31 +-- lib/libcrypto/bn/bn_local.h | 25 +- lib/libcrypto/bn/bn_recp.c | 114 ++++----- lib/libcrypto/crypto.h | 4 +- lib/libcrypto/ec/ec_lib.c | 13 +- lib/libcrypto/ec/ec_local.h | 4 +- lib/libcrypto/ec/ecp_methods.c | 21 +- lib/libcrypto/sm4/sm4.c | 238 ++++++++++-------- regress/lib/libcrypto/bn/bn_test.c | 14 +- regress/lib/libcrypto/ec/Makefile | 18 +- regress/lib/libcrypto/ec/ectest.c | 132 ++++------ .../libexec/ld.so/constructor/prog1/Makefile | 4 +- .../libexec/ld.so/constructor/prog2/Makefile | 4 +- regress/libexec/ld.so/dlopen/prog1/Makefile | 4 +- regress/libexec/ld.so/dlopen/prog2/Makefile | 4 +- regress/libexec/ld.so/dlopen/prog3/Makefile | 4 +- regress/libexec/ld.so/dlopen/prog4/Makefile | 4 +- regress/libexec/ld.so/init-env/prog/Makefile | 4 +- .../ld.so/initfirst/test2/prog1/Makefile | 4 +- .../ld.so/initfirst/test2/prog2/Makefile | 4 +- sys/arch/arm/arm/cpufunc.c | 3 +- sys/dev/wscons/wsevent.c | 167 +++++++++--- sys/dev/wscons/wseventvar.h | 68 +++-- sys/dev/wscons/wskbd.c | 18 +- sys/dev/wscons/wsmux.c | 17 +- sys/kern/kern_sig.c | 28 ++- sys/kern/kern_synch.c | 52 ++-- sys/kern/uipc_socket.c | 124 +++------ sys/kern/uipc_socket2.c | 48 ++-- sys/net/if.c | 26 +- sys/net/if_var.h | 84 ++++--- sys/netinet/tcp_subr.c | 14 +- sys/sys/socketvar.h | 32 +-- sys/uvm/uvm_fault.c | 20 +- usr.sbin/bgpd/session.c | 8 +- usr.sbin/iscsid/connection.c | 41 ++- usr.sbin/iscsid/initiator.c | 92 +++++-- usr.sbin/iscsid/iscsid.8 | 26 +- usr.sbin/iscsid/iscsid.c | 58 +++-- usr.sbin/iscsid/iscsid.h | 31 ++- usr.sbin/iscsid/pdu.c | 43 +++- usr.sbin/iscsid/session.c | 64 +---- 42 files changed, 899 insertions(+), 815 deletions(-) diff --git a/lib/libcrypto/bn/bn_exp.c b/lib/libcrypto/bn/bn_exp.c index c51296c3c..2aa41f865 100644 --- a/lib/libcrypto/bn/bn_exp.c +++ b/lib/libcrypto/bn/bn_exp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_exp.c,v 1.53 2024/04/10 14:58:06 beck Exp $ */ +/* $OpenBSD: bn_exp.c,v 1.56 2025/01/22 12:53:16 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -972,7 +972,7 @@ BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BIGNUM *aa, *q; /* Table of variables obtained from 'ctx' */ BIGNUM *val[TABLE_SIZE]; - BN_RECP_CTX recp; + BN_RECP_CTX *recp = NULL; int ret = 0; if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) { @@ -992,8 +992,6 @@ BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, return ret; } - BN_RECP_CTX_init(&recp); - BN_CTX_start(ctx); if ((aa = BN_CTX_get(ctx)) == NULL) goto err; @@ -1002,17 +1000,8 @@ BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, if ((val[0] = BN_CTX_get(ctx)) == NULL) goto err; - if (m->neg) { - /* ignore sign of 'm' */ - if (!bn_copy(aa, m)) - goto err; - aa->neg = 0; - if (BN_RECP_CTX_set(&recp, aa, ctx) <= 0) - goto err; - } else { - if (BN_RECP_CTX_set(&recp, m, ctx) <= 0) - goto err; - } + if ((recp = BN_RECP_CTX_create(m)) == NULL) + goto err; if (!BN_nnmod(val[0], a, m, ctx)) goto err; @@ -1025,13 +1014,13 @@ BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, window = BN_window_bits_for_exponent_size(bits); if (window > 1) { - if (!BN_mod_mul_reciprocal(aa, val[0], val[0], &recp, ctx)) + if (!BN_mod_sqr_reciprocal(aa, val[0], recp, ctx)) goto err; j = 1 << (window - 1); for (i = 1; i < j; i++) { if (((val[i] = BN_CTX_get(ctx)) == NULL) || !BN_mod_mul_reciprocal(val[i], val[i - 1], - aa, &recp, ctx)) + aa, recp, ctx)) goto err; } } @@ -1049,7 +1038,7 @@ BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, for (;;) { if (BN_is_bit_set(q, wstart) == 0) { if (!start) - if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx)) + if (!BN_mod_sqr_reciprocal(r, r, recp, ctx)) goto err; if (wstart == 0) break; @@ -1078,12 +1067,12 @@ BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, /* add the 'bytes above' */ if (!start) for (i = 0; i < j; i++) { - if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx)) + if (!BN_mod_sqr_reciprocal(r, r, recp, ctx)) goto err; } /* wvalue will be an odd number < 2^window */ - if (!BN_mod_mul_reciprocal(r, r, val[wvalue >> 1], &recp, ctx)) + if (!BN_mod_mul_reciprocal(r, r, val[wvalue >> 1], recp, ctx)) goto err; /* move the 'window' down further */ @@ -1099,7 +1088,7 @@ BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, err: BN_CTX_end(ctx); - BN_RECP_CTX_free(&recp); + BN_RECP_CTX_free(recp); return ret; } diff --git a/lib/libcrypto/bn/bn_local.h b/lib/libcrypto/bn/bn_local.h index 310cce2a0..fe3abeeb9 100644 --- a/lib/libcrypto/bn/bn_local.h +++ b/lib/libcrypto/bn/bn_local.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_local.h,v 1.45 2025/01/06 13:47:37 tb Exp $ */ +/* $OpenBSD: bn_local.h,v 1.48 2025/01/22 10:12:01 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -138,16 +138,7 @@ struct bn_mont_ctx_st { int flags; }; -/* Used for reciprocal division/mod functions - * It cannot be shared between threads - */ -typedef struct bn_recp_ctx_st { - BIGNUM N; /* the divisor */ - BIGNUM Nr; /* the reciprocal */ - int num_bits; - int shift; - int flags; -} BN_RECP_CTX; +typedef struct bn_recp_ctx_st BN_RECP_CTX; /* Used for slow "generation" functions. */ struct bn_gencb_st { @@ -280,14 +271,14 @@ int bn_rand_interval(BIGNUM *rnd, BN_ULONG lower_word, const BIGNUM *upper_exc); void BN_init(BIGNUM *); -void BN_RECP_CTX_init(BN_RECP_CTX *recp); -BN_RECP_CTX *BN_RECP_CTX_new(void); -void BN_RECP_CTX_free(BN_RECP_CTX *recp); -int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *rdiv, BN_CTX *ctx); -int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, BN_RECP_CTX *recp, - BN_CTX *ctx); +BN_RECP_CTX *BN_RECP_CTX_create(const BIGNUM *N); +void BN_RECP_CTX_free(BN_RECP_CTX *recp); +int BN_div_reciprocal(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, + BN_RECP_CTX *recp, BN_CTX *ctx); int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y, BN_RECP_CTX *recp, BN_CTX *ctx); +int BN_mod_sqr_reciprocal(BIGNUM *r, const BIGNUM *x, BN_RECP_CTX *recp, + BN_CTX *ctx); int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx); diff --git a/lib/libcrypto/bn/bn_recp.c b/lib/libcrypto/bn/bn_recp.c index 44c5b05e4..8f917e95d 100644 --- a/lib/libcrypto/bn/bn_recp.c +++ b/lib/libcrypto/bn/bn_recp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_recp.c,v 1.25 2025/01/08 20:21:28 tb Exp $ */ +/* $OpenBSD: bn_recp.c,v 1.30 2025/01/22 12:53:16 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -62,26 +62,35 @@ #include "bn_local.h" -void -BN_RECP_CTX_init(BN_RECP_CTX *recp) -{ - BN_init(&recp->N); - BN_init(&recp->Nr); - recp->num_bits = 0; - recp->flags = 0; -} +struct bn_recp_ctx_st { + BIGNUM *N; /* the divisor */ + BIGNUM *Nr; /* the reciprocal 2^shift / N */ + int num_bits; /* number of bits in N */ + int shift; +} /* BN_RECP_CTX */; BN_RECP_CTX * -BN_RECP_CTX_new(void) +BN_RECP_CTX_create(const BIGNUM *N) { - BN_RECP_CTX *ret; + BN_RECP_CTX *recp; - if ((ret = malloc(sizeof(BN_RECP_CTX))) == NULL) - return NULL; + if ((recp = calloc(1, sizeof(*recp))) == NULL) + goto err; - BN_RECP_CTX_init(ret); - ret->flags = BN_FLG_MALLOCED; - return ret; + if ((recp->N = BN_dup(N)) == NULL) + goto err; + BN_set_negative(recp->N, 0); + recp->num_bits = BN_num_bits(recp->N); + + if ((recp->Nr = BN_new()) == NULL) + goto err; + + return recp; + + err: + BN_RECP_CTX_free(recp); + + return NULL; } void @@ -90,23 +99,9 @@ BN_RECP_CTX_free(BN_RECP_CTX *recp) if (recp == NULL) return; - BN_free(&recp->N); - BN_free(&recp->Nr); - if (recp->flags & BN_FLG_MALLOCED) - free(recp); -} - -int -BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *d, BN_CTX *ctx) -{ - if (!bn_copy(&recp->N, d)) - return 0; - recp->num_bits = BN_num_bits(&recp->N); - - BN_zero(&recp->Nr); - recp->shift = 0; - - return 1; + BN_free(recp->N); + BN_free(recp->Nr); + freezero(recp, sizeof(*recp)); } /* len is the expected size of the result @@ -138,7 +133,7 @@ err: } int -BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, BN_RECP_CTX *recp, +BN_div_reciprocal(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, BN_RECP_CTX *recp, BN_CTX *ctx) { int i, j, ret = 0; @@ -158,7 +153,7 @@ BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, BN_RECP_CTX *recp, if (a == NULL || b == NULL || d == NULL || r == NULL) goto err; - if (BN_ucmp(m, &recp->N) < 0) { + if (BN_ucmp(m, recp->N) < 0) { BN_zero(d); if (!bn_copy(r, m)) { BN_CTX_end(ctx); @@ -182,7 +177,7 @@ BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, BN_RECP_CTX *recp, /* Nr := round(2^i / N) */ if (i != recp->shift) - recp->shift = BN_reciprocal(&recp->Nr, &recp->N, i, ctx); + recp->shift = BN_reciprocal(recp->Nr, recp->N, i, ctx); /* BN_reciprocal returns i, or -1 for an error */ if (recp->shift == -1) @@ -195,13 +190,13 @@ BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, BN_RECP_CTX *recp, */ if (!BN_rshift(a, m, recp->num_bits)) goto err; - if (!BN_mul(b, a, &recp->Nr, ctx)) + if (!BN_mul(b, a, recp->Nr, ctx)) goto err; if (!BN_rshift(d, b, i - recp->num_bits)) goto err; d->neg = 0; - if (!BN_mul(b, &recp->N, d, ctx)) + if (!BN_mul(b, recp->N, d, ctx)) goto err; if (!BN_usub(r, m, b)) goto err; @@ -209,12 +204,12 @@ BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, BN_RECP_CTX *recp, #if 1 j = 0; - while (BN_ucmp(r, &recp->N) >= 0) { + while (BN_ucmp(r, recp->N) >= 0) { if (j++ > 2) { BNerror(BN_R_BAD_RECIPROCAL); goto err; } - if (!BN_usub(r, r, &recp->N)) + if (!BN_usub(r, r, recp->N)) goto err; if (!BN_add_word(d, 1)) goto err; @@ -222,7 +217,7 @@ BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, BN_RECP_CTX *recp, #endif BN_set_negative(r, m->neg); - BN_set_negative(d, m->neg ^ recp->N.neg); + BN_set_negative(d, m->neg ^ recp->N->neg); ret = 1; @@ -231,32 +226,23 @@ err: return ret; } +/* Compute r = (x * y) % m. */ int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y, BN_RECP_CTX *recp, BN_CTX *ctx) { - int ret = 0; - BIGNUM *a; - const BIGNUM *ca; + if (!BN_mul(r, x, y, ctx)) + return 0; - BN_CTX_start(ctx); - if ((a = BN_CTX_get(ctx)) == NULL) - goto err; - if (y != NULL) { - if (x == y) { - if (!BN_sqr(a, x, ctx)) - goto err; - } else { - if (!BN_mul(a, x, y, ctx)) - goto err; - } - ca = a; - } else - ca = x; /* Just do the mod */ - - ret = BN_div_recp(NULL, r, ca, recp, ctx); - -err: - BN_CTX_end(ctx); - return ret; + return BN_div_reciprocal(NULL, r, r, recp, ctx); +} + +/* Compute r = x^2 % m. */ +int +BN_mod_sqr_reciprocal(BIGNUM *r, const BIGNUM *x, BN_RECP_CTX *recp, BN_CTX *ctx) +{ + if (!BN_sqr(r, x, ctx)) + return 0; + + return BN_div_reciprocal(NULL, r, r, recp, ctx); } diff --git a/lib/libcrypto/crypto.h b/lib/libcrypto/crypto.h index 33b6fe419..56e69cd35 100644 --- a/lib/libcrypto/crypto.h +++ b/lib/libcrypto/crypto.h @@ -1,4 +1,4 @@ -/* $OpenBSD: crypto.h,v 1.76 2024/10/03 03:47:40 tb Exp $ */ +/* $OpenBSD: crypto.h,v 1.77 2025/01/20 17:50:12 tb Exp $ */ /* ==================================================================== * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. * @@ -182,7 +182,7 @@ extern "C" { #define CRYPTO_LOCK_ECDSA 32 #define CRYPTO_LOCK_EC 33 #define CRYPTO_LOCK_ECDH 34 -#define CRYPTO_LOCK_BN 35 +#define CRYPTO_LOCK_BN 35 #define CRYPTO_LOCK_EC_PRE_COMP 36 #define CRYPTO_LOCK_STORE 37 #define CRYPTO_LOCK_COMP 38 diff --git a/lib/libcrypto/ec/ec_lib.c b/lib/libcrypto/ec/ec_lib.c index 5bfa16df3..a60543ab9 100644 --- a/lib/libcrypto/ec/ec_lib.c +++ b/lib/libcrypto/ec/ec_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ec_lib.c,v 1.111 2025/01/11 15:26:07 tb Exp $ */ +/* $OpenBSD: ec_lib.c,v 1.113 2025/01/22 09:56:58 jsing Exp $ */ /* * Originally written by Bodo Moeller for the OpenSSL project. */ @@ -667,6 +667,7 @@ EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx_in) { BN_CTX *ctx; EC_POINT *point = NULL; + const EC_POINT *generator; const BIGNUM *order; int ret = 0; @@ -680,11 +681,11 @@ EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx_in) goto err; } - if (group->generator == NULL) { + if ((generator = EC_GROUP_get0_generator(group)) == NULL) { ECerror(EC_R_UNDEFINED_GENERATOR); goto err; } - if (EC_POINT_is_on_curve(group, group->generator, ctx) <= 0) { + if (EC_POINT_is_on_curve(group, generator, ctx) <= 0) { ECerror(EC_R_POINT_IS_NOT_ON_CURVE); goto err; } @@ -1346,8 +1347,7 @@ EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, if (ctx == NULL) goto err; - if (group->meth->mul_generator_ct == NULL || - group->meth->mul_single_ct == NULL || + if (group->meth->mul_single_ct == NULL || group->meth->mul_double_nonct == NULL) { ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); goto err; @@ -1362,7 +1362,8 @@ EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, * secret. This is why we ignore if BN_FLG_CONSTTIME is actually * set and we always call the constant time version. */ - ret = group->meth->mul_generator_ct(group, r, g_scalar, ctx); + ret = group->meth->mul_single_ct(group, r, g_scalar, + group->generator, ctx); } else if (g_scalar == NULL && point != NULL && p_scalar != NULL) { /* * In this case we want to compute p_scalar * GenericPoint: diff --git a/lib/libcrypto/ec/ec_local.h b/lib/libcrypto/ec/ec_local.h index afa8b0307..84c1552c8 100644 --- a/lib/libcrypto/ec/ec_local.h +++ b/lib/libcrypto/ec/ec_local.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ec_local.h,v 1.62 2025/01/11 20:57:03 tb Exp $ */ +/* $OpenBSD: ec_local.h,v 1.63 2025/01/22 09:56:58 jsing Exp $ */ /* * Originally written by Bodo Moeller for the OpenSSL project. */ @@ -105,8 +105,6 @@ struct ec_method_st { int (*dbl)(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *); int (*invert)(const EC_GROUP *, EC_POINT *, BN_CTX *); - int (*mul_generator_ct)(const EC_GROUP *, EC_POINT *r, - const BIGNUM *scalar, BN_CTX *); int (*mul_single_ct)(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, const EC_POINT *point, BN_CTX *); int (*mul_double_nonct)(const EC_GROUP *group, EC_POINT *r, diff --git a/lib/libcrypto/ec/ecp_methods.c b/lib/libcrypto/ec/ecp_methods.c index 718bd4565..8bcff77d0 100644 --- a/lib/libcrypto/ec/ecp_methods.c +++ b/lib/libcrypto/ec/ecp_methods.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ecp_methods.c,v 1.39 2025/01/17 11:11:27 tb Exp $ */ +/* $OpenBSD: ecp_methods.c,v 1.41 2025/01/22 12:54:40 tb Exp $ */ /* Includes code written by Lenka Fibikova * for the OpenSSL project. * Includes code written by Bodo Moeller for the OpenSSL project. @@ -1020,17 +1020,9 @@ ec_mul_ct(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, BN_CTX_start(ctx); - if ((s = EC_POINT_new(group)) == NULL) + if ((s = EC_POINT_dup(point, group)) == NULL) goto err; - if (point == NULL) { - if (!EC_POINT_copy(s, group->generator)) - goto err; - } else { - if (!EC_POINT_copy(s, point)) - goto err; - } - EC_POINT_BN_set_flags(s, BN_FLG_CONSTTIME); if ((cardinality = BN_CTX_get(ctx)) == NULL) @@ -1194,13 +1186,6 @@ ec_mul_ct(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, #undef EC_POINT_BN_set_flags #undef EC_POINT_CSWAP -static int -ec_mul_generator_ct(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, - BN_CTX *ctx) -{ - return ec_mul_ct(group, r, scalar, NULL, ctx); -} - static int ec_mul_single_ct(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, const EC_POINT *point, BN_CTX *ctx) @@ -1317,7 +1302,6 @@ static const EC_METHOD ec_GFp_simple_method = { .add = ec_add, .dbl = ec_dbl, .invert = ec_invert, - .mul_generator_ct = ec_mul_generator_ct, .mul_single_ct = ec_mul_single_ct, .mul_double_nonct = ec_mul_double_nonct, .field_mul = ec_simple_field_mul, @@ -1343,7 +1327,6 @@ static const EC_METHOD ec_GFp_mont_method = { .add = ec_add, .dbl = ec_dbl, .invert = ec_invert, - .mul_generator_ct = ec_mul_generator_ct, .mul_single_ct = ec_mul_single_ct, .mul_double_nonct = ec_mul_double_nonct, .field_mul = ec_mont_field_mul, diff --git a/lib/libcrypto/sm4/sm4.c b/lib/libcrypto/sm4/sm4.c index bd1689987..6e90fa19d 100644 --- a/lib/libcrypto/sm4/sm4.c +++ b/lib/libcrypto/sm4/sm4.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sm4.c,v 1.2 2023/07/07 12:01:32 beck Exp $ */ +/* $OpenBSD: sm4.c,v 1.6 2025/01/22 09:53:16 jsing Exp $ */ /* * Copyright (c) 2017, 2019 Ribose Inc * @@ -20,6 +20,8 @@ #ifndef OPENSSL_NO_SM4 #include +#include "crypto_internal.h" + struct sm4_key { uint32_t rk[SM4_KEY_SCHEDULE]; }; @@ -98,30 +100,6 @@ static const uint32_t SM4_SBOX_T[256] = { 0x8BD45F5F, 0xE7C82F2F, 0xDD39E4E4, 0x68492121, }; -static inline uint32_t -rotl(uint32_t a, uint8_t n) -{ - return (a << n) | (a >> (32 - n)); -} - -static inline uint32_t -load_u32_be(const uint8_t *b, uint32_t n) -{ - return ((uint32_t)b[4 * n] << 24) | - ((uint32_t)b[4 * n + 1] << 16) | - ((uint32_t)b[4 * n + 2] << 8) | - ((uint32_t)b[4 * n + 3]); -} - -static inline void -store_u32_be(uint32_t v, uint8_t *b) -{ - b[0] = (uint8_t)(v >> 24); - b[1] = (uint8_t)(v >> 16); - b[2] = (uint8_t)(v >> 8); - b[3] = (uint8_t)(v); -} - static inline uint32_t SM4_T_slow(uint32_t X) { @@ -132,67 +110,65 @@ SM4_T_slow(uint32_t X) t |= ((uint32_t)SM4_S[(uint8_t)(X >> 8)]) << 8; t |= SM4_S[(uint8_t)X]; - /* - * L linear transform - */ - return t ^ rotl(t, 2) ^ rotl(t, 10) ^ rotl(t, 18) ^ rotl(t, 24); + /* L linear transform. */ + return t ^ crypto_rol_u32(t, 2) ^ crypto_rol_u32(t, 10) ^ + crypto_rol_u32(t, 18) ^ crypto_rol_u32(t, 24); } static inline uint32_t SM4_T(uint32_t X) { return SM4_SBOX_T[(uint8_t)(X >> 24)] ^ - rotl(SM4_SBOX_T[(uint8_t)(X >> 16)], 24) ^ - rotl(SM4_SBOX_T[(uint8_t)(X >> 8)], 16) ^ - rotl(SM4_SBOX_T[(uint8_t)X], 8); + crypto_rol_u32(SM4_SBOX_T[(uint8_t)(X >> 16)], 24) ^ + crypto_rol_u32(SM4_SBOX_T[(uint8_t)(X >> 8)], 16) ^ + crypto_rol_u32(SM4_SBOX_T[(uint8_t)X], 8); } +/* + * SM4 Family Key + */ +static const uint32_t SM4_FK[4] = { + 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc, +}; + +/* + * SM4 Constant Key + */ +static const uint32_t SM4_CK[32] = { + 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269, + 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9, + 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249, + 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9, + 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229, + 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299, + 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209, + 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279, +}; + int SM4_set_key(const uint8_t *key, SM4_KEY *k) { struct sm4_key *ks = (struct sm4_key *)k; - - /* - * Family Key - */ - static const uint32_t FK[4] = { - 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc, - }; - - /* - * Constant Key - */ - static const uint32_t CK[32] = { - 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269, - 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9, - 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249, - 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9, - 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229, - 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299, - 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209, - 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279, - }; - uint32_t K[4]; int i; - K[0] = load_u32_be(key, 0) ^ FK[0]; - K[1] = load_u32_be(key, 1) ^ FK[1]; - K[2] = load_u32_be(key, 2) ^ FK[2]; - K[3] = load_u32_be(key, 3) ^ FK[3]; + K[0] = crypto_load_be32toh(&key[0 * 4]) ^ SM4_FK[0]; + K[1] = crypto_load_be32toh(&key[1 * 4]) ^ SM4_FK[1]; + K[2] = crypto_load_be32toh(&key[2 * 4]) ^ SM4_FK[2]; + K[3] = crypto_load_be32toh(&key[3 * 4]) ^ SM4_FK[3]; for (i = 0; i < SM4_KEY_SCHEDULE; i++) { uint32_t X; uint32_t t = 0; - X = K[(i + 1) % 4] ^ K[(i + 2) % 4] ^ K[(i + 3) % 4] ^ CK[i]; + X = K[(i + 1) % 4] ^ K[(i + 2) % 4] ^ K[(i + 3) % 4] ^ SM4_CK[i]; t |= ((uint32_t)SM4_S[(uint8_t)(X >> 24)]) << 24; t |= ((uint32_t)SM4_S[(uint8_t)(X >> 16)]) << 16; t |= ((uint32_t)SM4_S[(uint8_t)(X >> 8)]) << 8; t |= SM4_S[(uint8_t)X]; - t = t ^ rotl(t, 13) ^ rotl(t, 23); + t = t ^ crypto_rol_u32(t, 13) ^ crypto_rol_u32(t, 23); K[i % 4] ^= t; ks->rk[i] = K[i % 4]; } @@ -201,40 +177,65 @@ SM4_set_key(const uint8_t *key, SM4_KEY *k) } LCRYPTO_ALIAS(SM4_set_key); -#define SM4_ROUNDS(k0, k1, k2, k3, F) \ - do { \ - B0 ^= F(B1 ^ B2 ^ B3 ^ ks->rk[k0]); \ - B1 ^= F(B0 ^ B2 ^ B3 ^ ks->rk[k1]); \ - B2 ^= F(B0 ^ B1 ^ B3 ^ ks->rk[k2]); \ - B3 ^= F(B0 ^ B1 ^ B2 ^ ks->rk[k3]); \ - } while(0) - void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *k) { struct sm4_key *ks = (struct sm4_key *)k; - uint32_t B0 = load_u32_be(in, 0); - uint32_t B1 = load_u32_be(in, 1); - uint32_t B2 = load_u32_be(in, 2); - uint32_t B3 = load_u32_be(in, 3); + uint32_t B0, B1, B2, B3; + + B0 = crypto_load_be32toh(&in[0 * 4]); + B1 = crypto_load_be32toh(&in[1 * 4]); + B2 = crypto_load_be32toh(&in[2 * 4]); + B3 = crypto_load_be32toh(&in[3 * 4]); /* * Uses byte-wise sbox in the first and last rounds to provide some * protection from cache based side channels. */ - SM4_ROUNDS( 0, 1, 2, 3, SM4_T_slow); - SM4_ROUNDS( 4, 5, 6, 7, SM4_T); - SM4_ROUNDS( 8, 9, 10, 11, SM4_T); - SM4_ROUNDS(12, 13, 14, 15, SM4_T); - SM4_ROUNDS(16, 17, 18, 19, SM4_T); - SM4_ROUNDS(20, 21, 22, 23, SM4_T); - SM4_ROUNDS(24, 25, 26, 27, SM4_T); - SM4_ROUNDS(28, 29, 30, 31, SM4_T_slow); + B0 ^= SM4_T_slow(B1 ^ B2 ^ B3 ^ ks->rk[0]); + B1 ^= SM4_T_slow(B0 ^ B2 ^ B3 ^ ks->rk[1]); + B2 ^= SM4_T_slow(B0 ^ B1 ^ B3 ^ ks->rk[2]); + B3 ^= SM4_T_slow(B0 ^ B1 ^ B2 ^ ks->rk[3]); - store_u32_be(B3, out); - store_u32_be(B2, out + 4); - store_u32_be(B1, out + 8); - store_u32_be(B0, out + 12); + B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[4]); + B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[5]); + B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[6]); + B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[7]); + + B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[8]); + B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[9]); + B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[10]); + B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[11]); + + B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[12]); + B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[13]); + B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[14]); + B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[15]); + + B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[16]); + B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[17]); + B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[18]); + B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[19]); + + B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[20]); + B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[21]); + B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[22]); + B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[23]); + + B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[24]); + B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[25]); + B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[26]); + B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[27]); + + B0 ^= SM4_T_slow(B1 ^ B2 ^ B3 ^ ks->rk[28]); + B1 ^= SM4_T_slow(B0 ^ B2 ^ B3 ^ ks->rk[29]); + B2 ^= SM4_T_slow(B0 ^ B1 ^ B3 ^ ks->rk[30]); + B3 ^= SM4_T_slow(B0 ^ B1 ^ B2 ^ ks->rk[31]); + + crypto_store_htobe32(&out[0 * 4], B3); + crypto_store_htobe32(&out[1 * 4], B2); + crypto_store_htobe32(&out[2 * 4], B1); + crypto_store_htobe32(&out[3 * 4], B0); } LCRYPTO_ALIAS(SM4_encrypt); @@ -242,24 +243,61 @@ void SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *k) { struct sm4_key *ks = (struct sm4_key *)k; - uint32_t B0 = load_u32_be(in, 0); - uint32_t B1 = load_u32_be(in, 1); - uint32_t B2 = load_u32_be(in, 2); - uint32_t B3 = load_u32_be(in, 3); + uint32_t B0, B1, B2, B3; - SM4_ROUNDS(31, 30, 29, 28, SM4_T_slow); - SM4_ROUNDS(27, 26, 25, 24, SM4_T); - SM4_ROUNDS(23, 22, 21, 20, SM4_T); - SM4_ROUNDS(19, 18, 17, 16, SM4_T); - SM4_ROUNDS(15, 14, 13, 12, SM4_T); - SM4_ROUNDS(11, 10, 9, 8, SM4_T); - SM4_ROUNDS( 7, 6, 5, 4, SM4_T); - SM4_ROUNDS( 3, 2, 1, 0, SM4_T_slow); + B0 = crypto_load_be32toh(&in[0 * 4]); + B1 = crypto_load_be32toh(&in[1 * 4]); + B2 = crypto_load_be32toh(&in[2 * 4]); + B3 = crypto_load_be32toh(&in[3 * 4]); - store_u32_be(B3, out); - store_u32_be(B2, out + 4); - store_u32_be(B1, out + 8); - store_u32_be(B0, out + 12); + /* + * Uses byte-wise sbox in the first and last rounds to provide some + * protection from cache based side channels. + */ + B0 ^= SM4_T_slow(B1 ^ B2 ^ B3 ^ ks->rk[31]); + B1 ^= SM4_T_slow(B0 ^ B2 ^ B3 ^ ks->rk[30]); + B2 ^= SM4_T_slow(B0 ^ B1 ^ B3 ^ ks->rk[29]); + B3 ^= SM4_T_slow(B0 ^ B1 ^ B2 ^ ks->rk[28]); + + B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[27]); + B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[26]); + B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[25]); + B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[24]); + + B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[23]); + B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[22]); + B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[21]); + B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[20]); + + B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[19]); + B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[18]); + B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[17]); + B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[16]); + + B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[15]); + B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[14]); + B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[13]); + B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[12]); + + B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[11]); + B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[10]); + B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[9]); + B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[8]); + + B0 ^= SM4_T(B1 ^ B2 ^ B3 ^ ks->rk[7]); + B1 ^= SM4_T(B0 ^ B2 ^ B3 ^ ks->rk[6]); + B2 ^= SM4_T(B0 ^ B1 ^ B3 ^ ks->rk[5]); + B3 ^= SM4_T(B0 ^ B1 ^ B2 ^ ks->rk[4]); + + B0 ^= SM4_T_slow(B1 ^ B2 ^ B3 ^ ks->rk[3]); + B1 ^= SM4_T_slow(B0 ^ B2 ^ B3 ^ ks->rk[2]); + B2 ^= SM4_T_slow(B0 ^ B1 ^ B3 ^ ks->rk[1]); + B3 ^= SM4_T_slow(B0 ^ B1 ^ B2 ^ ks->rk[0]); + + crypto_store_htobe32(&out[0 * 4], B3); + crypto_store_htobe32(&out[1 * 4], B2); + crypto_store_htobe32(&out[2 * 4], B1); + crypto_store_htobe32(&out[3 * 4], B0); } LCRYPTO_ALIAS(SM4_decrypt); diff --git a/regress/lib/libcrypto/bn/bn_test.c b/regress/lib/libcrypto/bn/bn_test.c index f73799b3a..4aeb3ee28 100644 --- a/regress/lib/libcrypto/bn/bn_test.c +++ b/regress/lib/libcrypto/bn/bn_test.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_test.c,v 1.19 2023/04/25 17:17:21 tb Exp $ */ +/* $OpenBSD: bn_test.c,v 1.22 2025/01/22 13:02:14 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -224,7 +224,7 @@ main(int argc, char *argv[]) goto err; (void)BIO_flush(out); - message(out, "BN_div_recp"); + message(out, "BN_div_reciprocal"); if (!test_div_recp(out, ctx)) goto err; (void)BIO_flush(out); @@ -581,9 +581,6 @@ test_div_recp(BIO *bp, BN_CTX *ctx) if ((e = BN_CTX_get(ctx)) == NULL) goto err; - if ((recp = BN_RECP_CTX_new()) == NULL) - goto err; - for (i = 0; i < num0 + num1; i++) { if (i < num1) { CHECK_GOTO(BN_bntest_rand(a, 400, 0, 0)); @@ -592,10 +589,9 @@ test_div_recp(BIO *bp, BN_CTX *ctx) CHECK_GOTO(BN_add_word(a, i)); } else CHECK_GOTO(BN_bntest_rand(b, 50 + 3 * (i - num1), 0, 0)); - BN_set_negative(a, rand_neg()); - BN_set_negative(b, rand_neg()); - CHECK_GOTO(BN_RECP_CTX_set(recp, b, ctx)); - CHECK_GOTO(BN_div_recp(d, c, a, recp, ctx)); + BN_RECP_CTX_free(recp); + CHECK_GOTO(recp = BN_RECP_CTX_create(b)); + CHECK_GOTO(BN_div_reciprocal(d, c, a, recp, ctx)); if (bp != NULL) { if (!results) { CHECK_GOTO(BN_print(bp, a)); diff --git a/regress/lib/libcrypto/ec/Makefile b/regress/lib/libcrypto/ec/Makefile index 20d2a9031..59311ef79 100644 --- a/regress/lib/libcrypto/ec/Makefile +++ b/regress/lib/libcrypto/ec/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.9 2024/11/04 09:51:51 tb Exp $ +# $OpenBSD: Makefile,v 1.10 2025/01/21 16:47:52 tb Exp $ .ifdef EOPENSSL33 LDADD += -Wl,-rpath,/usr/local/lib/eopenssl33 -L/usr/local/lib/eopenssl33 @@ -6,14 +6,14 @@ CFLAGS += -I/usr/local/include/eopenssl33/ CFLAGS += -DOPENSSL_SUPPRESS_DEPRECATED .endif -PROGS += ectest -PROGS += ec_asn1_test -PROGS += ec_point_conversion +PROGS += ectest +PROGS += ec_asn1_test +PROGS += ec_point_conversion -LDADD = -lcrypto -DPADD = ${LIBCRYPTO} -WARNINGS = Yes -CFLAGS += -DLIBRESSL_CRYPTO_INTERNAL -DLIBRESSL_INTERNAL -CFLAGS += -Wall -Wundef -Werror +LDADD = -lcrypto +DPADD = ${LIBCRYPTO} +WARNINGS = Yes +CFLAGS += -DLIBRESSL_CRYPTO_INTERNAL -DLIBRESSL_INTERNAL +CFLAGS += -Wall -Wundef -Werror .include diff --git a/regress/lib/libcrypto/ec/ectest.c b/regress/lib/libcrypto/ec/ectest.c index 48f05eeee..1aa6b1717 100644 --- a/regress/lib/libcrypto/ec/ectest.c +++ b/regress/lib/libcrypto/ec/ectest.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ectest.c,v 1.26 2025/01/06 10:43:26 tb Exp $ */ +/* $OpenBSD: ectest.c,v 1.34 2025/01/22 15:38:25 tb Exp $ */ /* * Originally written by Bodo Moeller for the OpenSSL project. */ @@ -88,27 +88,24 @@ exit(1); \ } while (0) -#define TIMING_BASE_PT 0 -#define TIMING_RAND_PT 1 -#define TIMING_SIMUL 2 - /* test multiplication with group order, long and negative scalars */ static void -group_order_tests(EC_GROUP *group) +group_order_tests(EC_GROUP *group, BN_CTX *ctx) { BIGNUM *n1, *n2, *order; EC_POINT *P = EC_POINT_new(group); EC_POINT *Q = EC_POINT_new(group); - BN_CTX *ctx; - if ((ctx = BN_CTX_new()) == NULL) + if (P == NULL || Q == NULL) ABORT; - if ((n1 = BN_new()) == NULL) + BN_CTX_start(ctx); + + if ((n1 = BN_CTX_get(ctx)) == NULL) ABORT; - if ((n2 = BN_new()) == NULL) + if ((n2 = BN_CTX_get(ctx)) == NULL) ABORT; - if ((order = BN_new()) == NULL) + if ((order = BN_CTX_get(ctx)) == NULL) ABORT; fprintf(stdout, "verify group order ..."); fflush(stdout); @@ -128,8 +125,7 @@ group_order_tests(EC_GROUP *group) ABORT; fprintf(stdout, " ok\n"); fprintf(stdout, "long/negative scalar tests ... "); - /* XXX - switch back to BN_one() after next bump. */ - if (!BN_set_word(n1, 1)) + if (!BN_one(n1)) ABORT; /* n1 = 1 - order */ if (!BN_sub(n1, n1, order)) @@ -155,10 +151,7 @@ group_order_tests(EC_GROUP *group) fprintf(stdout, "ok\n"); EC_POINT_free(P); EC_POINT_free(Q); - BN_free(n1); - BN_free(n2); - BN_free(order); - BN_CTX_free(ctx); + BN_CTX_end(ctx); } static void @@ -191,20 +184,13 @@ prime_field_tests(void) if (!BN_hex2bn(&b, "1")) ABORT; - group = EC_GROUP_new(EC_GFp_mont_method()); /* applications should use EC_GROUP_new_curve_GFp - * so that the library gets to choose the EC_METHOD */ - if (!group) - ABORT; - - if (!EC_GROUP_set_curve(group, p, a, b, ctx)) + if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) ABORT; { EC_GROUP *tmp; - tmp = EC_GROUP_new(EC_GROUP_method_of(group)); - if (!tmp) - ABORT; - if (!EC_GROUP_copy(tmp, group)) + + if ((tmp = EC_GROUP_dup(group)) == NULL) ABORT; EC_GROUP_free(group); group = tmp; @@ -263,18 +249,16 @@ prime_field_tests(void) } fprintf(stdout, "A cyclic subgroup:\n"); - k = 100; + k = 0; do { - if (k-- == 0) - ABORT; - + fprintf(stderr, " %d - ", k); if (EC_POINT_is_at_infinity(group, P)) - fprintf(stdout, " point at infinity\n"); + fprintf(stdout, "point at infinity\n"); else { if (!EC_POINT_get_affine_coordinates(group, P, x, y, ctx)) ABORT; - fprintf(stdout, " x = 0x"); + fprintf(stdout, "x = 0x"); BN_print_fp(stdout, x); fprintf(stdout, ", y = 0x"); BN_print_fp(stdout, y); @@ -285,8 +269,15 @@ prime_field_tests(void) ABORT; if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT; + if (k++ > 99) + ABORT; } while (!EC_POINT_is_at_infinity(group, P)); + if (k != 7) { + fprintf(stderr, "cycled in %d iterations, want 7\n", k); + ABORT; + } + if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT; if (!EC_POINT_is_at_infinity(group, P)) @@ -300,9 +291,10 @@ prime_field_tests(void) if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "Generator as octet string, compressed form:\n "); - for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); + for (i = 0; i < len; i++) + fprintf(stdout, "%02X", buf[i]); - len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx); + len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) @@ -310,9 +302,10 @@ prime_field_tests(void) if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n "); - for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); + for (i = 0; i < len; i++) + fprintf(stdout, "%02X", buf[i]); - len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx); + len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx); if (len == 0) ABORT; if (!EC_POINT_oct2point(group, P, buf, len, ctx)) @@ -322,8 +315,8 @@ prime_field_tests(void) fprintf(stdout, "\nGenerator as octet string, hybrid form:\n "); for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); - if (!EC_POINT_get_affine_coordinates(group, R, x, y, ctx)) - ABORT; + if (!EC_POINT_get_affine_coordinates(group, R, x, y, ctx)) + ABORT; fprintf(stdout, "\nThe inverse of that generator:\n X = 0x"); BN_print_fp(stdout, x); fprintf(stdout, ", Y = 0x"); @@ -381,13 +374,10 @@ prime_field_tests(void) ABORT; fprintf(stdout, " ok\n"); - group_order_tests(group); + group_order_tests(group, ctx); - if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) + if ((P_160 = EC_GROUP_dup(group)) == NULL) ABORT; - if (!EC_GROUP_copy(P_160, group)) - ABORT; - /* Curve P-192 (FIPS PUB 186-2, App. 6) */ @@ -431,13 +421,10 @@ prime_field_tests(void) ABORT; fprintf(stdout, " ok\n"); - group_order_tests(group); + group_order_tests(group, ctx); - if (!(P_192 = EC_GROUP_new(EC_GROUP_method_of(group)))) + if ((P_192 = EC_GROUP_dup(group)) == NULL) ABORT; - if (!EC_GROUP_copy(P_192, group)) - ABORT; - /* Curve P-224 (FIPS PUB 186-2, App. 6) */ @@ -481,13 +468,10 @@ prime_field_tests(void) ABORT; fprintf(stdout, " ok\n"); - group_order_tests(group); + group_order_tests(group, ctx); - if (!(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))) + if ((P_224 = EC_GROUP_dup(group)) == NULL) ABORT; - if (!EC_GROUP_copy(P_224, group)) - ABORT; - /* Curve P-256 (FIPS PUB 186-2, App. 6) */ @@ -531,13 +515,10 @@ prime_field_tests(void) ABORT; fprintf(stdout, " ok\n"); - group_order_tests(group); + group_order_tests(group, ctx); - if (!(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))) + if ((P_256 = EC_GROUP_dup(group)) == NULL) ABORT; - if (!EC_GROUP_copy(P_256, group)) - ABORT; - /* Curve P-384 (FIPS PUB 186-2, App. 6) */ @@ -581,13 +562,10 @@ prime_field_tests(void) ABORT; fprintf(stdout, " ok\n"); - group_order_tests(group); + group_order_tests(group, ctx); - if (!(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))) + if ((P_384 = EC_GROUP_dup(group)) == NULL) ABORT; - if (!EC_GROUP_copy(P_384, group)) - ABORT; - /* Curve P-521 (FIPS PUB 186-2, App. 6) */ @@ -637,13 +615,10 @@ prime_field_tests(void) ABORT; fprintf(stdout, " ok\n"); - group_order_tests(group); + group_order_tests(group, ctx); - if (!(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))) + if ((P_521 = EC_GROUP_dup(group)) == NULL) ABORT; - if (!EC_GROUP_copy(P_521, group)) - ABORT; - /* more tests using the last curve */ fprintf(stdout, "infinity tests ..."); @@ -683,19 +658,12 @@ prime_field_tests(void) BN_free(y); BN_free(z); - if (P_160) - EC_GROUP_free(P_160); - if (P_192) - EC_GROUP_free(P_192); - if (P_224) - EC_GROUP_free(P_224); - if (P_256) - EC_GROUP_free(P_256); - if (P_384) - EC_GROUP_free(P_384); - if (P_521) - EC_GROUP_free(P_521); - + EC_GROUP_free(P_160); + EC_GROUP_free(P_192); + EC_GROUP_free(P_224); + EC_GROUP_free(P_256); + EC_GROUP_free(P_384); + EC_GROUP_free(P_521); } int diff --git a/regress/libexec/ld.so/constructor/prog1/Makefile b/regress/libexec/ld.so/constructor/prog1/Makefile index 523fbb80d..c4d20bce9 100644 --- a/regress/libexec/ld.so/constructor/prog1/Makefile +++ b/regress/libexec/ld.so/constructor/prog1/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.2 2016/09/27 06:52:50 kettenis Exp $ +# $OpenBSD: Makefile,v 1.3 2025/01/21 19:14:27 anton Exp $ .include @@ -29,6 +29,6 @@ LDADD+=-laa LDFLAGS=-L$(AA_OBJDIR) -L$(AB_OBJDIR) LDFLAGS+= -Wl,-rpath,$(AA_OBJDIR) -Wl,-rpath,$(AB_OBJDIR) NOMAN= -CC=c++ +CC=${CXX} .include diff --git a/regress/libexec/ld.so/constructor/prog2/Makefile b/regress/libexec/ld.so/constructor/prog2/Makefile index fa3136aaf..6f5fba50e 100644 --- a/regress/libexec/ld.so/constructor/prog2/Makefile +++ b/regress/libexec/ld.so/constructor/prog2/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.2 2016/09/27 06:52:50 kettenis Exp $ +# $OpenBSD: Makefile,v 1.3 2025/01/21 19:14:28 anton Exp $ .include @@ -29,6 +29,6 @@ LDADD+=-lab LDFLAGS=-L$(AA_OBJDIR) -L$(AB_OBJDIR) LDFLAGS+= -Wl,-rpath,$(AA_OBJDIR) -Wl,-rpath,$(AB_OBJDIR) NOMAN= -CC=c++ +CC=${CXX} .include diff --git a/regress/libexec/ld.so/dlopen/prog1/Makefile b/regress/libexec/ld.so/dlopen/prog1/Makefile index dc569339d..80a7dbd1a 100644 --- a/regress/libexec/ld.so/dlopen/prog1/Makefile +++ b/regress/libexec/ld.so/dlopen/prog1/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.4 2015/06/15 01:10:19 deraadt Exp $ +# $OpenBSD: Makefile,v 1.5 2025/01/21 19:14:28 anton Exp $ .include @@ -29,7 +29,7 @@ LDADD= #LDFLAGS=-L$(AA_OBJDIR) -L$(AB_OBJDIR) LDFLAGS+= -Wl,-rpath,$(AA_OBJDIR) -Wl,-rpath,$(AB_OBJDIR) NOMAN= -CC=c++ +CC=${CXX} LD_LIBRARY_PATH=$(AA_OBJDIR):$(AB_OBJDIR) .include diff --git a/regress/libexec/ld.so/dlopen/prog2/Makefile b/regress/libexec/ld.so/dlopen/prog2/Makefile index 8a7484cf9..93f595390 100644 --- a/regress/libexec/ld.so/dlopen/prog2/Makefile +++ b/regress/libexec/ld.so/dlopen/prog2/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.2 2015/06/15 01:10:19 deraadt Exp $ +# $OpenBSD: Makefile,v 1.3 2025/01/21 19:14:28 anton Exp $ .include @@ -29,6 +29,6 @@ LDADD+=-lab LDFLAGS=-L$(AA_OBJDIR) -L$(AB_OBJDIR) LDFLAGS+= -Wl,-rpath,$(AA_OBJDIR) -Wl,-rpath,$(AB_OBJDIR) NOMAN= -CC=c++ +CC=${CXX} .include diff --git a/regress/libexec/ld.so/dlopen/prog3/Makefile b/regress/libexec/ld.so/dlopen/prog3/Makefile index a13c66676..629a2ce3d 100644 --- a/regress/libexec/ld.so/dlopen/prog3/Makefile +++ b/regress/libexec/ld.so/dlopen/prog3/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.4 2017/03/18 16:45:32 kettenis Exp $ +# $OpenBSD: Makefile,v 1.5 2025/01/21 19:14:28 anton Exp $ .include @@ -29,6 +29,6 @@ LDFLAGS=-L$(AA_OBJDIR) -L$(AC_OBJDIR) LDFLAGS+= -Wl,-disable-new-dtags LDFLAGS+= -Wl,-rpath,$(AA_OBJDIR) -Wl,-rpath,$(AC_OBJDIR) NOMAN= -CC=c++ +CC=${CXX} .include diff --git a/regress/libexec/ld.so/dlopen/prog4/Makefile b/regress/libexec/ld.so/dlopen/prog4/Makefile index 25f844c7d..9897dea9b 100644 --- a/regress/libexec/ld.so/dlopen/prog4/Makefile +++ b/regress/libexec/ld.so/dlopen/prog4/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.3 2015/06/15 01:10:19 deraadt Exp $ +# $OpenBSD: Makefile,v 1.4 2025/01/21 19:14:28 anton Exp $ .include @@ -30,6 +30,6 @@ LDFLAGS=-L$(AA_OBJDIR) -L$(AC_OBJDIR) # This intentionally leaves out AA_OBJDIR from -rpath LDFLAGS+= -Wl,-rpath,$(AC_OBJDIR) NOMAN= -CC=c++ +CC=${CXX} .include diff --git a/regress/libexec/ld.so/init-env/prog/Makefile b/regress/libexec/ld.so/init-env/prog/Makefile index 54464144c..f948fb784 100644 --- a/regress/libexec/ld.so/init-env/prog/Makefile +++ b/regress/libexec/ld.so/init-env/prog/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.1 2016/03/20 05:13:22 guenther Exp $ +# $OpenBSD: Makefile,v 1.2 2025/01/21 19:14:28 anton Exp $ .include @@ -18,6 +18,6 @@ LDADD+=-laa LDFLAGS=-L$(AA_OBJDIR) LDFLAGS+= -Wl,-rpath,$(AA_OBJDIR) NOMAN= -CC=c++ +CC=${CXX} .include diff --git a/regress/libexec/ld.so/initfirst/test2/prog1/Makefile b/regress/libexec/ld.so/initfirst/test2/prog1/Makefile index 56b9c640b..9514c75b0 100644 --- a/regress/libexec/ld.so/initfirst/test2/prog1/Makefile +++ b/regress/libexec/ld.so/initfirst/test2/prog1/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.2 2017/03/18 16:58:22 kettenis Exp $ +# $OpenBSD: Makefile,v 1.3 2025/01/21 19:14:28 anton Exp $ .include @@ -50,7 +50,7 @@ LDFLAGS+= -Wl,-rpath,$(AC_OBJDIR) LDFLAGS+= -Wl,-rpath,$(AD_OBJDIR) LDFLAGS+= -Wl,-rpath,$(AE_OBJDIR) NOMAN= -CC=c++ +CC=${CXX} run-regress-${PROG}: ${PROG} [ "`./${PROG}`" = "DBECAPpacebd" ] diff --git a/regress/libexec/ld.so/initfirst/test2/prog2/Makefile b/regress/libexec/ld.so/initfirst/test2/prog2/Makefile index df5e4889f..a66e0f0ae 100644 --- a/regress/libexec/ld.so/initfirst/test2/prog2/Makefile +++ b/regress/libexec/ld.so/initfirst/test2/prog2/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.2 2017/03/18 16:58:22 kettenis Exp $ +# $OpenBSD: Makefile,v 1.3 2025/01/21 19:14:28 anton Exp $ .include @@ -50,7 +50,7 @@ LDFLAGS+= -Wl,-rpath,$(AC_OBJDIR) LDFLAGS+= -Wl,-rpath,$(AD_OBJDIR) LDFLAGS+= -Wl,-rpath,$(AE_OBJDIR) NOMAN= -CC=c++ +CC=${CXX} run-regress-${PROG}: ${PROG} [ "`./${PROG}`" = "DBECAacebd" ] diff --git a/sys/arch/arm/arm/cpufunc.c b/sys/arch/arm/arm/cpufunc.c index c01b2ca4b..fbe205de7 100644 --- a/sys/arch/arm/arm/cpufunc.c +++ b/sys/arch/arm/arm/cpufunc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpufunc.c,v 1.57 2021/05/16 03:39:27 jsg Exp $ */ +/* $OpenBSD: cpufunc.c,v 1.58 2025/01/20 20:13:29 kettenis Exp $ */ /* $NetBSD: cpufunc.c,v 1.65 2003/11/05 12:53:15 scw Exp $ */ /* @@ -392,7 +392,6 @@ armv7_setup(void) | CPU_CONTROL_AFE; cpuctrl = CPU_CONTROL_MMU_ENABLE - | CPU_CONTROL_AFLT_ENABLE | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_IC_ENABLE diff --git a/sys/dev/wscons/wsevent.c b/sys/dev/wscons/wsevent.c index c28f89c37..a6e666f5a 100644 --- a/sys/dev/wscons/wsevent.c +++ b/sys/dev/wscons/wsevent.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wsevent.c,v 1.28 2024/03/25 13:01:49 mvs Exp $ */ +/* $OpenBSD: wsevent.c,v 1.29 2025/01/21 20:13:19 mvs Exp $ */ /* $NetBSD: wsevent.c,v 1.16 2003/08/07 16:31:29 agc Exp $ */ /* @@ -85,19 +85,61 @@ void filt_wseventdetach(struct knote *); int filt_wseventread(struct knote *, long); +int filt_wseventmodify(struct kevent *, struct knote *); +int filt_wseventprocess(struct knote *, struct kevent *); + +static void +wsevent_klist_assertlk(void *arg) +{ + struct wseventvar *ev = arg; + + if((ev->ws_flags & WSEVENT_MPSAFE) == 0) + KERNEL_ASSERT_LOCKED(); + MUTEX_ASSERT_LOCKED(&ev->ws_mtx); +} + +static int +wsevent_klist_lock(void *arg) +{ + struct wseventvar *ev = arg; + + if((ev->ws_flags & WSEVENT_MPSAFE) == 0) + KERNEL_LOCK(); + mtx_enter(&ev->ws_mtx); + + return (0); +} + +static void +wsevent_klist_unlock(void *arg, int s) +{ + struct wseventvar *ev = arg; + + mtx_leave(&ev->ws_mtx); + if ((ev->ws_flags & WSEVENT_MPSAFE) == 0) + KERNEL_UNLOCK(); +} + +static const struct klistops wsevent_klistops = { + .klo_assertlk = wsevent_klist_assertlk, + .klo_lock = wsevent_klist_lock, + .klo_unlock = wsevent_klist_unlock, +}; const struct filterops wsevent_filtops = { - .f_flags = FILTEROP_ISFD, + .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_wseventdetach, .f_event = filt_wseventread, + .f_modify = filt_wseventmodify, + .f_process = filt_wseventprocess, }; /* * Initialize a wscons_event queue. */ int -wsevent_init(struct wseventvar *ev) +wsevent_init_flags(struct wseventvar *ev, int flags) { struct wscons_event *queue; @@ -112,6 +154,10 @@ wsevent_init(struct wseventvar *ev) return (1); } + mtx_init_flags(&ev->ws_mtx, IPL_TTY, "wsmtx", 0); + klist_init(&ev->ws_klist, &wsevent_klistops, ev); + + ev->ws_flags = flags; ev->ws_q = queue; ev->ws_get = ev->ws_put = 0; @@ -135,7 +181,7 @@ wsevent_fini(struct wseventvar *ev) free(ev->ws_q, M_DEVBUF, WSEVENT_QSIZE * sizeof(struct wscons_event)); ev->ws_q = NULL; - klist_invalidate(&ev->ws_sel.si_note); + klist_invalidate(&ev->ws_klist); sigio_free(&ev->ws_sigio); } @@ -147,8 +193,8 @@ wsevent_fini(struct wseventvar *ev) int wsevent_read(struct wseventvar *ev, struct uio *uio, int flags) { - int s, error; - u_int cnt; + int error, wrap = 0; + u_int cnt, tcnt, get; size_t n; /* @@ -156,17 +202,20 @@ wsevent_read(struct wseventvar *ev, struct uio *uio, int flags) */ if (uio->uio_resid < sizeof(struct wscons_event)) return (EMSGSIZE); /* ??? */ - s = splwsevent(); + n = howmany(uio->uio_resid, sizeof(struct wscons_event)); + + mtx_enter(&ev->ws_mtx); + while (ev->ws_get == ev->ws_put) { if (flags & IO_NDELAY) { - splx(s); + mtx_leave(&ev->ws_mtx); return (EWOULDBLOCK); } ev->ws_wanted = 1; - error = tsleep_nsec(ev, PWSEVENT | PCATCH, + error = msleep_nsec(ev, &ev->ws_mtx, PWSEVENT | PCATCH, "wsevent_read", INFSLP); if (error) { - splx(s); + mtx_leave(&ev->ws_mtx); return (error); } } @@ -178,37 +227,43 @@ wsevent_read(struct wseventvar *ev, struct uio *uio, int flags) cnt = WSEVENT_QSIZE - ev->ws_get; /* events in [get..QSIZE) */ else cnt = ev->ws_put - ev->ws_get; /* events in [get..put) */ - splx(s); - n = howmany(uio->uio_resid, sizeof(struct wscons_event)); + if (cnt > n) cnt = n; - error = uiomove((caddr_t)&ev->ws_q[ev->ws_get], - cnt * sizeof(struct wscons_event), uio); + + get = ev->ws_get; + tcnt = ev->ws_put; n -= cnt; - /* - * If we do not wrap to 0, used up all our space, or had an error, - * stop. Otherwise move from front of queue to put index, if there - * is anything there to move. - */ - if ((ev->ws_get = (ev->ws_get + cnt) % WSEVENT_QSIZE) != 0 || - n == 0 || error || (cnt = ev->ws_put) == 0) - return (error); - if (cnt > n) - cnt = n; - error = uiomove((caddr_t)&ev->ws_q[0], + + ev->ws_get = (get + cnt) % WSEVENT_QSIZE; + if (!(ev->ws_get != 0 || n == 0 || tcnt == 0)) { + wrap = 1; + + if (tcnt > n) + tcnt = n; + ev->ws_get = tcnt; + } + + mtx_leave(&ev->ws_mtx); + + error = uiomove((caddr_t)&ev->ws_q[get], cnt * sizeof(struct wscons_event), uio); - ev->ws_get = cnt; + + /* + * If we do wrap to 0, move from front of queue to put index, if + * there is anything there to move. + */ + if (wrap && error == 0) { + error = uiomove((caddr_t)&ev->ws_q[0], + tcnt * sizeof(struct wscons_event), uio); + } + return (error); } int wsevent_kqfilter(struct wseventvar *ev, struct knote *kn) { - struct klist *klist; - int s; - - klist = &ev->ws_sel.si_note; - switch (kn->kn_filter) { case EVFILT_READ: kn->kn_fop = &wsevent_filtops; @@ -218,10 +273,7 @@ wsevent_kqfilter(struct wseventvar *ev, struct knote *kn) } kn->kn_hook = ev; - - s = splwsevent(); - klist_insert_locked(klist, kn); - splx(s); + klist_insert(&ev->ws_klist, kn); return (0); } @@ -230,12 +282,8 @@ void filt_wseventdetach(struct knote *kn) { struct wseventvar *ev = kn->kn_hook; - struct klist *klist = &ev->ws_sel.si_note; - int s; - s = splwsevent(); - klist_remove_locked(klist, kn); - splx(s); + klist_remove(&ev->ws_klist, kn); } int @@ -243,6 +291,10 @@ filt_wseventread(struct knote *kn, long hint) { struct wseventvar *ev = kn->kn_hook; + if((ev->ws_flags & WSEVENT_MPSAFE) == 0) + KERNEL_ASSERT_LOCKED(); + MUTEX_ASSERT_LOCKED(&ev->ws_mtx); + if (ev->ws_get == ev->ws_put) return (0); @@ -253,3 +305,38 @@ filt_wseventread(struct knote *kn, long hint) return (1); } + +int +filt_wseventmodify(struct kevent *kev, struct knote *kn) +{ + struct wseventvar *ev = kn->kn_hook; + int active, dolock = ((ev->ws_flags & WSEVENT_MPSAFE) == 0); + + if (dolock) + KERNEL_LOCK(); + mtx_enter(&ev->ws_mtx); + active = knote_modify(kev, kn); + mtx_leave(&ev->ws_mtx); + if (dolock) + KERNEL_UNLOCK(); + + return (active); +} + +int +filt_wseventprocess(struct knote *kn, struct kevent *kev) +{ + struct wseventvar *ev = kn->kn_hook; + int active, dolock = ((ev->ws_flags & WSEVENT_MPSAFE) == 0); + + if (dolock) + KERNEL_LOCK(); + mtx_enter(&ev->ws_mtx); + active = knote_process(kn, kev); + mtx_leave(&ev->ws_mtx); + if (dolock) + KERNEL_UNLOCK(); + + return (active); + +} diff --git a/sys/dev/wscons/wseventvar.h b/sys/dev/wscons/wseventvar.h index 657a30066..19b1a8fee 100644 --- a/sys/dev/wscons/wseventvar.h +++ b/sys/dev/wscons/wseventvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: wseventvar.h,v 1.13 2024/03/25 13:01:49 mvs Exp $ */ +/* $OpenBSD: wseventvar.h,v 1.14 2025/01/21 20:13:19 mvs Exp $ */ /* $NetBSD: wseventvar.h,v 1.1 1998/03/22 14:24:03 drochner Exp $ */ /* @@ -71,8 +71,9 @@ * @(#)event_var.h 8.1 (Berkeley) 6/11/93 */ -#include +#include #include +#include /* * Internal "wscons_event" queue interface for the keyboard and mouse drivers. @@ -80,38 +81,69 @@ * i.e., are expected to run off serial ports or similar devices. */ +/* + * Locks used to protect data + * I immutable + * m ws_mtx + */ + +/* + * XXXSMP: Non WSEVENT_MPSAFE wseventvar structures rely on kernel lock + */ + /* WSEVENT_QSIZE should be a power of two so that `%' is fast */ #define WSEVENT_QSIZE 256 /* may need tuning; this uses 2k */ struct wseventvar { - u_int ws_get; /* get (read) index (modified + u_int ws_get; /* [m] get (read) index (modified synchronously) */ - volatile u_int ws_put; /* put (write) index (modified by + volatile u_int ws_put; /* [m] put (write) index (modified by interrupt) */ - struct selinfo ws_sel; /* process selecting */ + int ws_flags; /* [I] flags, see below*/ + struct mutex ws_mtx; + struct klist ws_klist; /* [m] list of knotes */ struct sigio_ref ws_sigio; /* async I/O registration */ - int ws_wanted; /* wake up on input ready */ - int ws_async; /* send SIGIO on input ready */ - struct wscons_event *ws_q; /* circular buffer (queue) of events */ + int ws_wanted; /* [m] wake up on input ready */ + int ws_async; /* [m] send SIGIO on input ready */ + struct wscons_event *ws_q; /* [m] circular buffer (queue) of + events */ }; -#define splwsevent() spltty() +#define WSEVENT_MPSAFE 0x0001 -#define WSEVENT_WAKEUP(ev) { \ - selwakeup(&(ev)->ws_sel); \ - if ((ev)->ws_wanted) { \ - (ev)->ws_wanted = 0; \ - wakeup((caddr_t)(ev)); \ - } \ - if ((ev)->ws_async) \ - pgsigio(&(ev)->ws_sigio, SIGIO, 0); \ +static inline void +wsevent_wakeup(struct wseventvar *ev) +{ + int dosigio = 0; + + knote(&ev->ws_klist, 0); + + mtx_enter(&ev->ws_mtx); + if (ev->ws_wanted) { + ev->ws_wanted = 0; + wakeup(ev); + } + if (ev->ws_async) + dosigio = 1; + mtx_leave(&ev->ws_mtx); + + if (dosigio) + pgsigio(&ev->ws_sigio, SIGIO, 0); } -int wsevent_init(struct wseventvar *); +#define WSEVENT_WAKEUP(ev) do { wsevent_wakeup(ev); } while (0) + +int wsevent_init_flags(struct wseventvar *, int); void wsevent_fini(struct wseventvar *); int wsevent_read(struct wseventvar *, struct uio *, int); int wsevent_kqfilter(struct wseventvar *, struct knote *); +static inline int +wsevent_init(struct wseventvar *ev) +{ + return wsevent_init_flags(ev, 0); +} + /* * PWSEVENT is set just above PSOCK, which is just above TTIPRI, on the * theory that mouse and keyboard `user' input should be quick. diff --git a/sys/dev/wscons/wskbd.c b/sys/dev/wscons/wskbd.c index d926449ed..110dddae9 100644 --- a/sys/dev/wscons/wskbd.c +++ b/sys/dev/wscons/wskbd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wskbd.c,v 1.120 2024/12/30 02:46:00 guenther Exp $ */ +/* $OpenBSD: wskbd.c,v 1.121 2025/01/21 20:13:19 mvs Exp $ */ /* $NetBSD: wskbd.c,v 1.80 2005/05/04 01:52:16 augustss Exp $ */ /* @@ -625,7 +625,6 @@ wskbd_detach(struct device *self, int flags) struct wskbd_softc *sc = (struct wskbd_softc *)self; struct wseventvar *evar; int maj, mn; - int s; #if NWSMUX > 0 /* Tell parent mux we're leaving. */ @@ -647,18 +646,19 @@ wskbd_detach(struct device *self, int flags) evar = sc->sc_base.me_evp; if (evar != NULL) { - s = spltty(); if (--sc->sc_refcnt >= 0) { /* Wake everyone by generating a dummy event. */ + + mtx_enter(&evar->ws_mtx); if (++evar->ws_put >= WSEVENT_QSIZE) evar->ws_put = 0; - WSEVENT_WAKEUP(evar); + mtx_leave(&evar->ws_mtx); + wsevent_wakeup(evar); /* Wait for processes to go away. */ if (tsleep_nsec(sc, PZERO, "wskdet", SEC_TO_NSEC(60))) printf("wskbd_detach: %s didn't detach\n", sc->sc_base.me_dv.dv_xname); } - splx(s); } free(sc->sc_map, M_DEVBUF, @@ -763,6 +763,7 @@ wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value) } #endif + mtx_enter(&evar->ws_mtx); put = evar->ws_put; ev = &evar->ws_q[put]; put = (put + 1) % WSEVENT_QSIZE; @@ -775,7 +776,8 @@ wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value) ev->value = value; nanotime(&ev->time); evar->ws_put = put; - WSEVENT_WAKEUP(evar); + mtx_leave(&evar->ws_mtx); + wsevent_wakeup(evar); } #ifdef WSDISPLAY_COMPAT_RAWKBD @@ -862,7 +864,7 @@ wskbdopen(dev_t dev, int flags, int mode, struct proc *p) return (EBUSY); evar = &sc->sc_base.me_evar; - if (wsevent_init(evar)) + if (wsevent_init_flags(evar, WSEVENT_MPSAFE)) return (EBUSY); error = wskbd_do_open(sc, evar); @@ -1005,7 +1007,9 @@ wskbd_do_ioctl_sc(struct wskbd_softc *sc, u_long cmd, caddr_t data, int flag, case FIOASYNC: if (sc->sc_base.me_evp == NULL) return (EINVAL); + mtx_enter(&sc->sc_base.me_evp->ws_mtx); sc->sc_base.me_evp->ws_async = *(int *)data != 0; + mtx_leave(&sc->sc_base.me_evp->ws_mtx); return (0); case FIOGETOWN: diff --git a/sys/dev/wscons/wsmux.c b/sys/dev/wscons/wsmux.c index 43cd9cd8f..2e4819fd5 100644 --- a/sys/dev/wscons/wsmux.c +++ b/sys/dev/wscons/wsmux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wsmux.c,v 1.60 2024/12/30 02:46:00 guenther Exp $ */ +/* $OpenBSD: wsmux.c,v 1.61 2025/01/22 15:06:56 mvs Exp $ */ /* $NetBSD: wsmux.c,v 1.37 2005/04/30 03:47:12 augustss Exp $ */ /* @@ -208,7 +208,7 @@ wsmuxopen(dev_t dev, int flags, int mode, struct proc *p) return (EBUSY); evar = &sc->sc_base.me_evar; - if (wsevent_init(evar)) + if (wsevent_init_flags(evar, WSEVENT_MPSAFE)) return (EBUSY); #ifdef WSDISPLAY_COMPAT_RAWKBD sc->sc_rawkbd = 0; @@ -385,7 +385,7 @@ wsmux_do_ioctl(struct device *dv, u_long cmd, caddr_t data, int flag, struct wsmux_softc *sc = (struct wsmux_softc *)dv; struct wsevsrc *me; int error, ok; - int s, put, get, n; + int put, get, n; struct wseventvar *evar; struct wscons_event *ev; struct wsmux_device_list *l; @@ -415,13 +415,12 @@ wsmux_do_ioctl(struct device *dv, u_long cmd, caddr_t data, int flag, return (0); } - s = spltty(); + mtx_enter(&evar->ws_mtx); get = evar->ws_get; put = evar->ws_put; ev = &evar->ws_q[put]; if (++put % WSEVENT_QSIZE == get) { - put--; - splx(s); + mtx_leave(&evar->ws_mtx); return (ENOSPC); } if (put >= WSEVENT_QSIZE) @@ -429,8 +428,8 @@ wsmux_do_ioctl(struct device *dv, u_long cmd, caddr_t data, int flag, *ev = *(struct wscons_event *)data; nanotime(&ev->time); evar->ws_put = put; - WSEVENT_WAKEUP(evar); - splx(s); + mtx_leave(&evar->ws_mtx); + wsevent_wakeup(evar); return (0); case WSMUXIO_ADD_DEVICE: #define d ((struct wsmux_device *)data) @@ -496,7 +495,9 @@ wsmux_do_ioctl(struct device *dv, u_long cmd, caddr_t data, int flag, evar = sc->sc_base.me_evp; if (evar == NULL) return (EINVAL); + mtx_enter(&evar->ws_mtx); evar->ws_async = *(int *)data != 0; + mtx_leave(&evar->ws_mtx); return (0); case FIOGETOWN: case TIOCGPGRP: diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 9855771cc..9e3002a2b 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sig.c,v 1.355 2025/01/06 13:17:56 claudio Exp $ */ +/* $OpenBSD: kern_sig.c,v 1.357 2025/01/22 16:13:09 claudio Exp $ */ /* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */ /* @@ -1549,10 +1549,8 @@ process_continue(struct proc *p, int flag) SCHED_ASSERT_LOCKED(); if (q->p_wchan == NULL) setrunnable(q); - else { - atomic_clearbits_int(&q->p_flag, P_WSLEEP); + else q->p_stat = SSLEEP; - } /* XXX SCHED_UNLOCK(); */ } } @@ -2123,15 +2121,21 @@ single_thread_check_locked(struct proc *p, int deep) if (pr->ps_single == NULL || pr->ps_single == p) return (0); - do { - /* if we're in deep, we need to unwind to the edge */ - if (deep) { - if (pr->ps_flags & PS_SINGLEUNWIND) - return (ERESTART); - if (pr->ps_flags & PS_SINGLEEXIT) - return (EINTR); - } + /* if we're in deep, we need to unwind to the edge */ + if (deep) { + int err = 0; + if (pr->ps_flags & PS_SINGLEUNWIND || + pr->ps_flags & PS_SINGLEEXIT) + return (ERESTART); + SCHED_LOCK(); + if (p->p_stat != SSTOP) + err = EWOULDBLOCK; + SCHED_UNLOCK(); + return (err); + } + + do { if (pr->ps_flags & PS_SINGLEEXIT) { mtx_leave(&pr->ps_mtx); KERNEL_LOCK(); diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index 7f5e9cf2a..a6b3ffc7f 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_synch.c,v 1.215 2024/12/05 14:53:55 claudio Exp $ */ +/* $OpenBSD: kern_synch.c,v 1.218 2025/01/22 16:14:22 claudio Exp $ */ /* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */ /* @@ -376,15 +376,6 @@ sleep_finish(int timo, int do_sleep) } if (catch != 0) { - /* - * We put ourselves on the sleep queue and start our - * timeout before calling sleep_signal_check(), as we could - * stop there, and a wakeup or a SIGCONT (or both) could - * occur while we were stopped. A SIGCONT would cause - * us to be marked as SSLEEP without resuming us, thus - * we must be ready for sleep when sleep_signal_check() is - * called. - */ if ((error = sleep_signal_check(p, 0)) != 0) { catch = 0; do_sleep = 0; @@ -459,31 +450,48 @@ sleep_finish(int timo, int do_sleep) /* * Check and handle signals and suspensions around a sleep cycle. - * The 2nd call in sleep_finish() sets nostop = 1 and then stop - * signals can be ignored since the sleep is over and the process - * will stop in userret. + * The 2nd call in sleep_finish() sets after_sleep = 1. In this case + * any pending suspend event came in after the wakeup / unsleep and + * can therefor be ignored. Once the process hits userret the event + * will be picked up again. */ int -sleep_signal_check(struct proc *p, int nostop) +sleep_signal_check(struct proc *p, int after_sleep) { struct sigctx ctx; int err, sig; - if ((err = single_thread_check(p, 1)) != 0) - return err; + if ((err = single_thread_check(p, 1)) != 0) { + if (err != EWOULDBLOCK) + return err; + + /* requested to stop */ + if (!after_sleep) { + mtx_enter(&p->p_p->ps_mtx); + if (--p->p_p->ps_singlecnt == 0) + wakeup(&p->p_p->ps_singlecnt); + mtx_leave(&p->p_p->ps_mtx); + + SCHED_LOCK(); + p->p_stat = SSTOP; + SCHED_UNLOCK(); + } + } + if ((sig = cursig(p, &ctx, 1)) != 0) { if (ctx.sig_stop) { - if (nostop) - return 0; - p->p_p->ps_xsig = sig; - SCHED_LOCK(); - proc_stop(p, 0); - SCHED_UNLOCK(); + if (!after_sleep) { + p->p_p->ps_xsig = sig; + SCHED_LOCK(); + proc_stop(p, 0); + SCHED_UNLOCK(); + } } else if (ctx.sig_intr && !ctx.sig_ignore) return EINTR; else return ERESTART; } + return 0; } diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index d2bb20585..ee92f4f2d 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket.c,v 1.361 2025/01/20 16:34:48 bluhm Exp $ */ +/* $OpenBSD: uipc_socket.c,v 1.363 2025/01/22 15:05:49 mvs Exp $ */ /* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ /* @@ -166,9 +166,6 @@ soalloc(const struct protosw *prp, int wait) TAILQ_INIT(&so->so_q0); TAILQ_INIT(&so->so_q); - so->so_snd.sb_flags |= SB_MTXLOCK; - so->so_rcv.sb_flags |= SB_MTXLOCK; - return (so); } @@ -598,7 +595,6 @@ sosend(struct socket *so, struct mbuf *addr, struct uio *uio, struct mbuf *top, size_t resid; int error; int atomic = sosendallatonce(so) || top; - int dosolock = ((so->so_snd.sb_flags & SB_MTXLOCK) == 0); if (uio) resid = uio->uio_resid; @@ -634,9 +630,7 @@ sosend(struct socket *so, struct mbuf *addr, struct uio *uio, struct mbuf *top, restart: if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags))) != 0) goto out; - if (dosolock) - solock_shared(so); - sb_mtx_lock(&so->so_snd); + mtx_enter(&so->so_snd.sb_mtx); so->so_snd.sb_state |= SS_ISSENDING; do { if (so->so_snd.sb_state & SS_CANTSENDMORE) @@ -669,11 +663,9 @@ restart: if (flags & MSG_DONTWAIT) snderr(EWOULDBLOCK); sbunlock(&so->so_snd); - error = sbwait(so, &so->so_snd); + error = sbwait(&so->so_snd); so->so_snd.sb_state &= ~SS_ISSENDING; - sb_mtx_unlock(&so->so_snd); - if (dosolock) - sounlock_shared(so); + mtx_leave(&so->so_snd.sb_mtx); if (error) goto out; goto restart; @@ -688,13 +680,9 @@ restart: if (flags & MSG_EOR) top->m_flags |= M_EOR; } else { - sb_mtx_unlock(&so->so_snd); - if (dosolock) - sounlock_shared(so); + mtx_leave(&so->so_snd.sb_mtx); error = m_getuio(&top, atomic, space, uio); - if (dosolock) - solock_shared(so); - sb_mtx_lock(&so->so_snd); + mtx_enter(&so->so_snd.sb_mtx); if (error) goto release; space -= top->m_pkthdr.len; @@ -706,16 +694,14 @@ restart: so->so_snd.sb_state &= ~SS_ISSENDING; if (top && so->so_options & SO_ZEROIZE) top->m_flags |= M_ZEROIZE; - sb_mtx_unlock(&so->so_snd); - if (!dosolock) - solock_shared(so); + mtx_leave(&so->so_snd.sb_mtx); + solock_shared(so); if (flags & MSG_OOB) error = pru_sendoob(so, top, addr, control); else error = pru_send(so, top, addr, control); - if (!dosolock) - sounlock_shared(so); - sb_mtx_lock(&so->so_snd); + sounlock_shared(so); + mtx_enter(&so->so_snd.sb_mtx); clen = 0; control = NULL; top = NULL; @@ -726,9 +712,7 @@ restart: release: so->so_snd.sb_state &= ~SS_ISSENDING; - sb_mtx_unlock(&so->so_snd); - if (dosolock) - sounlock_shared(so); + mtx_leave(&so->so_snd.sb_mtx); sbunlock(&so->so_snd); out: m_freem(top); @@ -865,7 +849,6 @@ soreceive(struct socket *so, struct mbuf **paddr, struct uio *uio, const struct protosw *pr = so->so_proto; struct mbuf *nextrecord; size_t resid, orig_resid = uio->uio_resid; - int dosolock = ((so->so_rcv.sb_flags & SB_MTXLOCK) == 0); mp = mp0; if (paddr) @@ -898,9 +881,7 @@ bad: restart: if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0) return (error); - if (dosolock) - solock_shared(so); - sb_mtx_lock(&so->so_rcv); + mtx_enter(&so->so_rcv.sb_mtx); m = so->so_rcv.sb_mb; #ifdef SOCKET_SPLICE @@ -965,10 +946,8 @@ restart: SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 1"); sbunlock(&so->so_rcv); - error = sbwait(so, &so->so_rcv); - sb_mtx_unlock(&so->so_rcv); - if (dosolock) - sounlock_shared(so); + error = sbwait(&so->so_rcv); + mtx_leave(&so->so_rcv.sb_mtx); if (error) return (error); goto restart; @@ -1037,15 +1016,11 @@ dontblock: sbsync(&so->so_rcv, nextrecord); if (controlp) { if (pr->pr_domain->dom_externalize) { - sb_mtx_unlock(&so->so_rcv); - if (dosolock) - sounlock_shared(so); + mtx_leave(&so->so_rcv.sb_mtx); error = (*pr->pr_domain->dom_externalize) (cm, controllen, flags); - if (dosolock) - solock_shared(so); - sb_mtx_lock(&so->so_rcv); + mtx_enter(&so->so_rcv.sb_mtx); } *controlp = cm; } else { @@ -1054,9 +1029,9 @@ dontblock: * through the read path rather than recv. */ if (pr->pr_domain->dom_dispose) { - sb_mtx_unlock(&so->so_rcv); + mtx_leave(&so->so_rcv.sb_mtx); pr->pr_domain->dom_dispose(cm); - sb_mtx_lock(&so->so_rcv); + mtx_enter(&so->so_rcv.sb_mtx); } m_free(cm); } @@ -1122,13 +1097,9 @@ dontblock: SBLASTRECORDCHK(&so->so_rcv, "soreceive uiomove"); SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove"); resid = uio->uio_resid; - sb_mtx_unlock(&so->so_rcv); - if (dosolock) - sounlock_shared(so); + mtx_leave(&so->so_rcv.sb_mtx); uio_error = uiomove(mtod(m, caddr_t) + moff, len, uio); - if (dosolock) - solock_shared(so); - sb_mtx_lock(&so->so_rcv); + mtx_enter(&so->so_rcv.sb_mtx); if (uio_error) uio->uio_resid = resid - len; } else @@ -1210,10 +1181,8 @@ dontblock: break; SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 2"); SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 2"); - if (sbwait(so, &so->so_rcv)) { - sb_mtx_unlock(&so->so_rcv); - if (dosolock) - sounlock_shared(so); + if (sbwait(&so->so_rcv)) { + mtx_leave(&so->so_rcv.sb_mtx); sbunlock(&so->so_rcv); return (0); } @@ -1244,19 +1213,17 @@ dontblock: SBLASTRECORDCHK(&so->so_rcv, "soreceive 4"); SBLASTMBUFCHK(&so->so_rcv, "soreceive 4"); if (pr->pr_flags & PR_WANTRCVD) { - sb_mtx_unlock(&so->so_rcv); - if (!dosolock) - solock_shared(so); + mtx_leave(&so->so_rcv.sb_mtx); + solock_shared(so); pru_rcvd(so); - if (!dosolock) - sounlock_shared(so); - sb_mtx_lock(&so->so_rcv); + sounlock_shared(so); + mtx_enter(&so->so_rcv.sb_mtx); } } if (orig_resid == uio->uio_resid && orig_resid && (flags & MSG_EOR) == 0 && (so->so_rcv.sb_state & SS_CANTRCVMORE) == 0) { - sb_mtx_unlock(&so->so_rcv); + mtx_leave(&so->so_rcv.sb_mtx); sbunlock(&so->so_rcv); goto restart; } @@ -1267,9 +1234,7 @@ dontblock: if (flagsp) *flagsp |= flags; release: - sb_mtx_unlock(&so->so_rcv); - if (dosolock) - sounlock_shared(so); + mtx_leave(&so->so_rcv.sb_mtx); sbunlock(&so->so_rcv); return (error); } @@ -1937,19 +1902,16 @@ somove(struct socket *so, int wait) void sorwakeup(struct socket *so) { - if ((so->so_rcv.sb_flags & SB_MTXLOCK) == 0) - soassertlocked_readonly(so); - #ifdef SOCKET_SPLICE if (so->so_proto->pr_flags & PR_SPLICE) { - sb_mtx_lock(&so->so_rcv); + mtx_enter(&so->so_rcv.sb_mtx); if (so->so_rcv.sb_flags & SB_SPLICE) task_add(sosplice_taskq, &so->so_splicetask); if (isspliced(so)) { - sb_mtx_unlock(&so->so_rcv); + mtx_leave(&so->so_rcv.sb_mtx); return; } - sb_mtx_unlock(&so->so_rcv); + mtx_leave(&so->so_rcv.sb_mtx); } #endif sowakeup(so, &so->so_rcv); @@ -1960,20 +1922,17 @@ sorwakeup(struct socket *so) void sowwakeup(struct socket *so) { - if ((so->so_snd.sb_flags & SB_MTXLOCK) == 0) - soassertlocked_readonly(so); - #ifdef SOCKET_SPLICE if (so->so_proto->pr_flags & PR_SPLICE) { - sb_mtx_lock(&so->so_snd); + mtx_enter(&so->so_snd.sb_mtx); if (so->so_snd.sb_flags & SB_SPLICE) task_add(sosplice_taskq, &so->so_sp->ssp_soback->so_splicetask); if (issplicedback(so)) { - sb_mtx_unlock(&so->so_snd); + mtx_leave(&so->so_snd.sb_mtx); return; } - sb_mtx_unlock(&so->so_snd); + mtx_leave(&so->so_snd.sb_mtx); } #endif sowakeup(so, &so->so_snd); @@ -2059,10 +2018,7 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m) if ((long)cnt <= 0) cnt = 1; - if (((sb->sb_flags & SB_MTXLOCK) == 0)) - solock(so); mtx_enter(&sb->sb_mtx); - switch (optname) { case SO_SNDBUF: case SO_RCVBUF: @@ -2084,10 +2040,7 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m) sb->sb_hiwat : cnt; break; } - mtx_leave(&sb->sb_mtx); - if (((sb->sb_flags & SB_MTXLOCK) == 0)) - sounlock(so); break; } @@ -2403,14 +2356,11 @@ filt_soread(struct knote *kn, long hint) int rv = 0; MUTEX_ASSERT_LOCKED(&so->so_rcv.sb_mtx); - if ((so->so_rcv.sb_flags & SB_MTXLOCK) == 0) - soassertlocked_readonly(so); if (so->so_options & SO_ACCEPTCONN) { short qlen = READ_ONCE(so->so_qlen); - if (so->so_rcv.sb_flags & SB_MTXLOCK) - soassertlocked_readonly(so); + soassertlocked_readonly(so); kn->kn_data = qlen; rv = (kn->kn_data != 0); @@ -2469,8 +2419,6 @@ filt_sowrite(struct knote *kn, long hint) int rv; MUTEX_ASSERT_LOCKED(&so->so_snd.sb_mtx); - if ((so->so_snd.sb_flags & SB_MTXLOCK) == 0) - soassertlocked_readonly(so); kn->kn_data = sbspace_locked(so, &so->so_snd); if (so->so_snd.sb_state & SS_CANTSENDMORE) { @@ -2502,8 +2450,6 @@ filt_soexcept(struct knote *kn, long hint) int rv = 0; MUTEX_ASSERT_LOCKED(&so->so_rcv.sb_mtx); - if ((so->so_rcv.sb_flags & SB_MTXLOCK) == 0) - soassertlocked_readonly(so); #ifdef SOCKET_SPLICE if (isspliced(so)) { diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c index 550954f6f..b6572675a 100644 --- a/sys/kern/uipc_socket2.c +++ b/sys/kern/uipc_socket2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket2.c,v 1.167 2025/01/20 16:34:48 bluhm Exp $ */ +/* $OpenBSD: uipc_socket2.c,v 1.168 2025/01/22 15:05:49 mvs Exp $ */ /* $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $ */ /* @@ -316,9 +316,6 @@ socantsendmore(struct socket *so) void socantrcvmore(struct socket *so) { - if ((so->so_rcv.sb_flags & SB_MTXLOCK) == 0) - soassertlocked(so); - mtx_enter(&so->so_rcv.sb_mtx); so->so_rcv.sb_state |= SS_CANTRCVMORE; mtx_leave(&so->so_rcv.sb_mtx); @@ -482,40 +479,25 @@ sosleep_nsec(struct socket *so, void *ident, int prio, const char *wmesg, } void -sbmtxassertlocked(struct socket *so, struct sockbuf *sb) +sbmtxassertlocked(struct sockbuf *sb) { - if (sb->sb_flags & SB_MTXLOCK) { - if (splassert_ctl > 0 && mtx_owned(&sb->sb_mtx) == 0) - splassert_fail(0, RW_WRITE, __func__); - } else - soassertlocked(so); + if (splassert_ctl > 0 && mtx_owned(&sb->sb_mtx) == 0) + splassert_fail(0, RW_WRITE, __func__); } /* * Wait for data to arrive at/drain from a socket buffer. */ int -sbwait(struct socket *so, struct sockbuf *sb) +sbwait(struct sockbuf *sb) { - uint64_t timeo_nsecs; int prio = (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH; - if (sb->sb_flags & SB_MTXLOCK) { - MUTEX_ASSERT_LOCKED(&sb->sb_mtx); + MUTEX_ASSERT_LOCKED(&sb->sb_mtx); - sb->sb_flags |= SB_WAIT; - return msleep_nsec(&sb->sb_cc, &sb->sb_mtx, prio, "sbwait", - sb->sb_timeo_nsecs); - } - - soassertlocked(so); - - mtx_enter(&sb->sb_mtx); - timeo_nsecs = sb->sb_timeo_nsecs; sb->sb_flags |= SB_WAIT; - mtx_leave(&sb->sb_mtx); - - return sosleep_nsec(so, &sb->sb_cc, prio, "netio", timeo_nsecs); + return msleep_nsec(&sb->sb_cc, &sb->sb_mtx, prio, "sbwait", + sb->sb_timeo_nsecs); } int @@ -640,7 +622,7 @@ bad: int sbreserve(struct socket *so, struct sockbuf *sb, u_long cc) { - sbmtxassertlocked(so, sb); + sbmtxassertlocked(sb); if (cc == 0 || cc > sb_max) return (1); @@ -787,7 +769,7 @@ sbappend(struct socket *so, struct sockbuf *sb, struct mbuf *m) if (m == NULL) return; - sbmtxassertlocked(so, sb); + sbmtxassertlocked(sb); SBLASTRECORDCHK(sb, "sbappend 1"); if ((n = sb->sb_lastrecord) != NULL) { @@ -821,7 +803,7 @@ sbappend(struct socket *so, struct sockbuf *sb, struct mbuf *m) void sbappendstream(struct socket *so, struct sockbuf *sb, struct mbuf *m) { - sbmtxassertlocked(so, sb); + sbmtxassertlocked(sb); KDASSERT(m->m_nextpkt == NULL); KASSERT(sb->sb_mb == sb->sb_lastrecord); @@ -867,7 +849,7 @@ sbappendrecord(struct socket *so, struct sockbuf *sb, struct mbuf *m0) { struct mbuf *m; - sbmtxassertlocked(so, sb); + sbmtxassertlocked(sb); if (m0 == NULL) return; @@ -902,7 +884,7 @@ sbappendaddr(struct socket *so, struct sockbuf *sb, const struct sockaddr *asa, struct mbuf *m, *n, *nlast; int space = asa->sa_len; - sbmtxassertlocked(so, sb); + sbmtxassertlocked(sb); if (m0 && (m0->m_flags & M_PKTHDR) == 0) panic("sbappendaddr"); @@ -951,7 +933,7 @@ sbappendcontrol(struct socket *so, struct sockbuf *sb, struct mbuf *m0, struct mbuf *m, *mlast, *n; int eor = 0, space = 0; - sbmtxassertlocked(so, sb); + sbmtxassertlocked(sb); if (control == NULL) panic("sbappendcontrol"); @@ -1078,7 +1060,7 @@ sbdrop(struct socket *so, struct sockbuf *sb, int len) struct mbuf *m, *mn; struct mbuf *next; - sbmtxassertlocked(so, sb); + sbmtxassertlocked(sb); next = (m = sb->sb_mb) ? m->m_nextpkt : NULL; while (len > 0) { diff --git a/sys/net/if.c b/sys/net/if.c index 0e88a5542..de2e823c1 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.722 2025/01/16 17:20:23 mvs Exp $ */ +/* $OpenBSD: if.c,v 1.723 2025/01/21 17:40:57 mvs Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -2798,7 +2798,29 @@ if_getdata(struct ifnet *ifp, struct if_data *data) { unsigned int i; - *data = ifp->if_data; + data->ifi_type = ifp->if_type; + data->ifi_addrlen = ifp->if_addrlen; + data->ifi_hdrlen = ifp->if_hdrlen; + data->ifi_link_state = ifp->if_link_state; + data->ifi_mtu = ifp->if_mtu; + data->ifi_metric = ifp->if_metric; + data->ifi_baudrate = ifp->if_baudrate; + data->ifi_capabilities = ifp->if_capabilities; + data->ifi_rdomain = ifp->if_rdomain; + data->ifi_lastchange = ifp->if_lastchange; + + data->ifi_ipackets = ifp->if_data_counters[ifc_ipackets]; + data->ifi_ierrors = ifp->if_data_counters[ifc_ierrors]; + data->ifi_opackets = ifp->if_data_counters[ifc_opackets]; + data->ifi_oerrors = ifp->if_data_counters[ifc_oerrors]; + data->ifi_collisions = ifp->if_data_counters[ifc_collisions]; + data->ifi_ibytes = ifp->if_data_counters[ifc_ibytes]; + data->ifi_obytes = ifp->if_data_counters[ifc_obytes]; + data->ifi_imcasts = ifp->if_data_counters[ifc_imcasts]; + data->ifi_omcasts = ifp->if_data_counters[ifc_omcasts]; + data->ifi_iqdrops = ifp->if_data_counters[ifc_iqdrops]; + data->ifi_oqdrops = ifp->if_data_counters[ifc_oqdrops]; + data->ifi_noproto = ifp->if_data_counters[ifc_noproto]; if (ifp->if_counters != NULL) { uint64_t counters[ifc_ncounters]; diff --git a/sys/net/if_var.h b/sys/net/if_var.h index b850c8f7f..01b4e6e38 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_var.h,v 1.133 2024/10/12 23:18:10 jsg Exp $ */ +/* $OpenBSD: if_var.h,v 1.134 2025/01/21 17:40:57 mvs Exp $ */ /* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ /* @@ -110,6 +110,23 @@ struct if_clone { .ifc_destroy = destroy, \ } +enum if_counters { + ifc_ipackets, /* packets received on interface */ + ifc_ierrors, /* input errors on interface */ + ifc_opackets, /* packets sent on interface */ + ifc_oerrors, /* output errors on interface */ + ifc_collisions, /* collisions on csma interfaces */ + ifc_ibytes, /* total number of octets received */ + ifc_obytes, /* total number of octets sent */ + ifc_imcasts, /* packets received via multicast */ + ifc_omcasts, /* packets sent via multicast */ + ifc_iqdrops, /* dropped on input, this interface */ + ifc_oqdrops, /* dropped on output, this interface */ + ifc_noproto, /* destined for unsupported protocol */ + + ifc_ncounters +}; + /* * Structure defining a queue for a network interface. * @@ -147,7 +164,20 @@ struct ifnet { /* and the entries */ short if_timer; /* time 'til if_watchdog called */ unsigned short if_flags; /* [N] up/down, broadcast, etc. */ int if_xflags; /* [N] extra softnet flags */ - struct if_data if_data; /* stats and other data about if */ + + /* Stats and other data about if. Should be in sync with if_data. */ + u_char if_type; + u_char if_addrlen; + u_char if_hdrlen; + u_char if_link_state; + uint32_t if_mtu; + uint32_t if_metric; + uint64_t if_baudrate; + uint32_t if_capabilities; + uint32_t if_rdomain; + struct timeval if_lastchange; /* [c] last op. state change */ + uint64_t if_data_counters[ifc_ncounters]; + struct cpumem *if_counters; /* per cpu stats */ uint32_t if_hardmtu; /* [d] maximum MTU device supports */ char if_description[IFDESCRSIZE]; /* [c] interface description */ @@ -187,45 +217,19 @@ struct ifnet { /* and the entries */ struct nd_ifinfo *if_nd; /* [I] IPv6 Neighbor Discovery info */ }; -#define if_mtu if_data.ifi_mtu -#define if_type if_data.ifi_type -#define if_addrlen if_data.ifi_addrlen -#define if_hdrlen if_data.ifi_hdrlen -#define if_metric if_data.ifi_metric -#define if_link_state if_data.ifi_link_state -#define if_baudrate if_data.ifi_baudrate -#define if_ipackets if_data.ifi_ipackets -#define if_ierrors if_data.ifi_ierrors -#define if_opackets if_data.ifi_opackets -#define if_oerrors if_data.ifi_oerrors -#define if_collisions if_data.ifi_collisions -#define if_ibytes if_data.ifi_ibytes -#define if_obytes if_data.ifi_obytes -#define if_imcasts if_data.ifi_imcasts -#define if_omcasts if_data.ifi_omcasts -#define if_iqdrops if_data.ifi_iqdrops -#define if_oqdrops if_data.ifi_oqdrops -#define if_noproto if_data.ifi_noproto -#define if_lastchange if_data.ifi_lastchange /* [c] last op. state change */ -#define if_capabilities if_data.ifi_capabilities -#define if_rdomain if_data.ifi_rdomain -enum if_counters { - ifc_ipackets, /* packets received on interface */ - ifc_ierrors, /* input errors on interface */ - ifc_opackets, /* packets sent on interface */ - ifc_oerrors, /* output errors on interface */ - ifc_collisions, /* collisions on csma interfaces */ - ifc_ibytes, /* total number of octets received */ - ifc_obytes, /* total number of octets sent */ - ifc_imcasts, /* packets received via multicast */ - ifc_omcasts, /* packets sent via multicast */ - ifc_iqdrops, /* dropped on input, this interface */ - ifc_oqdrops, /* dropped on output, this interface */ - ifc_noproto, /* destined for unsupported protocol */ - - ifc_ncounters -}; +#define if_ipackets if_data_counters[ifc_ipackets] +#define if_ierrors if_data_counters[ifc_ierrors] +#define if_opackets if_data_counters[ifc_opackets] +#define if_oerrors if_data_counters[ifc_oerrors] +#define if_collisions if_data_counters[ifc_collisions] +#define if_ibytes if_data_counters[ifc_ibytes] +#define if_obytes if_data_counters[ifc_obytes] +#define if_imcasts if_data_counters[ifc_imcasts] +#define if_omcasts if_data_counters[ifc_omcasts] +#define if_iqdrops if_data_counters[ifc_iqdrops] +#define if_oqdrops if_data_counters[ifc_oqdrops] +#define if_noproto if_data_counters[ifc_noproto] /* * The ifaddr structure contains information about one address diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 471e513e3..70ea17a7f 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_subr.c,v 1.205 2025/01/16 11:59:20 bluhm Exp $ */ +/* $OpenBSD: tcp_subr.c,v 1.206 2025/01/22 09:37:06 bluhm Exp $ */ /* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */ /* @@ -331,11 +331,11 @@ tcp_respond(struct tcpcb *tp, caddr_t template, struct tcphdr *th0, th = (struct tcphdr *)(ip6 + 1); tlen = sizeof(*ip6) + sizeof(*th); if (th0) { - bcopy(template, ip6, sizeof(*ip6)); - bcopy(th0, th, sizeof(*th)); + memcpy(ip6, template, sizeof(*ip6)); + memcpy(th, th0, sizeof(*th)); xchg(ip6->ip6_dst, ip6->ip6_src, struct in6_addr); } else { - bcopy(template, ip6, tlen); + memcpy(ip6, template, tlen); } break; #endif /* INET6 */ @@ -344,11 +344,11 @@ tcp_respond(struct tcpcb *tp, caddr_t template, struct tcphdr *th0, th = (struct tcphdr *)(ip + 1); tlen = sizeof(*ip) + sizeof(*th); if (th0) { - bcopy(template, ip, sizeof(*ip)); - bcopy(th0, th, sizeof(*th)); + memcpy(ip, template, sizeof(*ip)); + memcpy(th, th0, sizeof(*th)); xchg(ip->ip_dst.s_addr, ip->ip_src.s_addr, u_int32_t); } else { - bcopy(template, ip, tlen); + memcpy(ip, template, tlen); } break; } diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index d04de6c43..402456ebd 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: socketvar.h,v 1.139 2025/01/16 16:35:01 bluhm Exp $ */ +/* $OpenBSD: socketvar.h,v 1.140 2025/01/22 15:05:49 mvs Exp $ */ /* $NetBSD: socketvar.h,v 1.18 1996/02/09 18:25:38 christos Exp $ */ /*- @@ -112,7 +112,6 @@ struct sockbuf { #define SB_ASYNC 0x0002 /* ASYNC I/O, need signals */ #define SB_SPLICE 0x0004 /* buffer is splice source or drain */ #define SB_NOINTR 0x0008 /* operations not interruptible */ -#define SB_MTXLOCK 0x0010 /* sblock() doesn't need solock() */ /* * Kernel structure per socket. @@ -225,21 +224,7 @@ soref(struct socket *so) #define isspliced(so) ((so)->so_sp && (so)->so_sp->ssp_socket) #define issplicedback(so) ((so)->so_sp && (so)->so_sp->ssp_soback) -static inline void -sb_mtx_lock(struct sockbuf *sb) -{ - if (sb->sb_flags & SB_MTXLOCK) - mtx_enter(&sb->sb_mtx); -} - -static inline void -sb_mtx_unlock(struct sockbuf *sb) -{ - if (sb->sb_flags & SB_MTXLOCK) - mtx_leave(&sb->sb_mtx); -} - -void sbmtxassertlocked(struct socket *so, struct sockbuf *); +void sbmtxassertlocked(struct sockbuf *); /* * Do we need to notify the other side when I/O is possible? @@ -249,8 +234,6 @@ sb_notify(struct socket *so, struct sockbuf *sb) { int rv; - soassertlocked(so); - mtx_enter(&sb->sb_mtx); rv = ((sb->sb_flags & (SB_WAIT|SB_ASYNC|SB_SPLICE)) != 0 || !klist_empty(&sb->sb_klist)); @@ -269,10 +252,7 @@ sb_notify(struct socket *so, struct sockbuf *sb) static inline long sbspace_locked(struct socket *so, struct sockbuf *sb) { - if (sb->sb_flags & SB_MTXLOCK) - sbmtxassertlocked(so, sb); - else - soassertlocked_readonly(so); + sbmtxassertlocked(sb); return lmin(sb->sb_hiwat - sb->sb_cc, sb->sb_mbmax - sb->sb_mbcnt); } @@ -282,9 +262,9 @@ sbspace(struct socket *so, struct sockbuf *sb) { long ret; - sb_mtx_lock(sb); + mtx_enter(&sb->sb_mtx); ret = sbspace_locked(so, sb); - sb_mtx_unlock(sb); + mtx_leave(&sb->sb_mtx); return ret; } @@ -411,7 +391,7 @@ void sbrelease(struct socket *, struct sockbuf *); int sbcheckreserve(u_long, u_long); int sbchecklowmem(void); int sbreserve(struct socket *, struct sockbuf *, u_long); -int sbwait(struct socket *, struct sockbuf *); +int sbwait(struct sockbuf *); void soinit(void); void soabort(struct socket *); int soaccept(struct socket *, struct mbuf *); diff --git a/sys/uvm/uvm_fault.c b/sys/uvm/uvm_fault.c index 7c2ed2461..a6f5f8ddb 100644 --- a/sys/uvm/uvm_fault.c +++ b/sys/uvm/uvm_fault.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_fault.c,v 1.160 2025/01/18 16:35:30 kettenis Exp $ */ +/* $OpenBSD: uvm_fault.c,v 1.162 2025/01/22 10:52:09 mpi Exp $ */ /* $NetBSD: uvm_fault.c,v 1.51 2000/08/06 00:22:53 thorpej Exp $ */ /* @@ -321,16 +321,9 @@ uvmfault_anonget(struct uvm_faultinfo *ufi, struct vm_amap *amap, * The last unlock must be an atomic unlock and wait * on the owner of page. */ - if (pg->uobject) { - /* Owner of page is UVM object. */ - uvmfault_unlockall(ufi, amap, NULL); - uvm_pagewait(pg, pg->uobject->vmobjlock, - "anonget1"); - } else { - /* Owner of page is anon. */ - uvmfault_unlockall(ufi, NULL, NULL); - uvm_pagewait(pg, anon->an_lock, "anonget2"); - } + KASSERT(pg->uobject == NULL); + uvmfault_unlockall(ufi, NULL, NULL); + uvm_pagewait(pg, anon->an_lock, "anonget"); } else { /* * No page, therefore allocate one. @@ -467,8 +460,7 @@ uvmfault_anonget(struct uvm_faultinfo *ufi, struct vm_amap *amap, * the anon on us. */ if (ufi != NULL && amap_lookup(&ufi->entry->aref, - ufi->orig_rvaddr - ufi->entry->start) != anon) { - + ufi->orig_rvaddr - ufi->entry->start) != anon) { uvmfault_unlockall(ufi, amap, NULL); return ERESTART; } @@ -1004,8 +996,6 @@ uvm_fault_upper(struct uvm_faultinfo *ufi, struct uvm_faultctx *flt, * if it fails (!OK) it will unlock everything for us. * if it succeeds, locks are still valid and locked. * also, if it is OK, then the anon's page is on the queues. - * if the page is on loan from a uvm_object, then anonget will - * lock that object for us if it does not fail. */ error = uvmfault_anonget(ufi, amap, anon); switch (error) { diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c index 47b590ae1..2ab0e28f4 100644 --- a/usr.sbin/bgpd/session.c +++ b/usr.sbin/bgpd/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.507 2025/01/13 13:50:34 claudio Exp $ */ +/* $OpenBSD: session.c,v 1.508 2025/01/22 12:19:47 claudio Exp $ */ /* * Copyright (c) 2003, 2004, 2005 Henning Brauer @@ -2572,7 +2572,7 @@ int parse_capabilities(struct peer *peer, struct ibuf *buf, uint32_t *as) { struct ibuf capabuf; - uint16_t afi, nhafi, tmp16, gr_header; + uint16_t afi, nhafi, gr_header; uint8_t capa_code, capa_len; uint8_t safi, aid, role, flags; @@ -2616,6 +2616,7 @@ parse_capabilities(struct peer *peer, struct ibuf *buf, uint32_t *as) break; case CAPA_EXT_NEXTHOP: while (ibuf_size(&capabuf) > 0) { + uint16_t tmp16; if (ibuf_get_n16(&capabuf, &afi) == -1 || ibuf_get_n16(&capabuf, &tmp16) == -1 || ibuf_get_n16(&capabuf, &nhafi) == -1) { @@ -2626,7 +2627,8 @@ parse_capabilities(struct peer *peer, struct ibuf *buf, uint32_t *as) sizeof(peer->capa.peer.ext_nh)); break; } - if (afi2aid(afi, tmp16, &aid) == -1 || + safi = tmp16; + if (afi2aid(afi, safi, &aid) == -1 || !(aid == AID_INET || aid == AID_VPN_IPv4)) { log_peer_warnx(&peer->conf, "Received %s capability: " diff --git a/usr.sbin/iscsid/connection.c b/usr.sbin/iscsid/connection.c index 3bfc71824..8c86c1dba 100644 --- a/usr.sbin/iscsid/connection.c +++ b/usr.sbin/iscsid/connection.c @@ -1,4 +1,4 @@ -/* $OpenBSD: connection.c,v 1.22 2025/01/16 16:19:39 claudio Exp $ */ +/* $OpenBSD: connection.c,v 1.24 2025/01/22 10:14:54 claudio Exp $ */ /* * Copyright (c) 2009 Claudio Jeker @@ -66,10 +66,15 @@ conn_new(struct session *s, struct connection_config *cc) c->cid = arc4random(); c->config = *cc; c->mine = initiator_conn_defaults; - c->mine.HeaderDigest = s->config.HeaderDigest; - c->mine.DataDigest = s->config.DataDigest; + if (s->config.HeaderDigest != 0) + c->mine.HeaderDigest = s->config.HeaderDigest; + if (s->config.DataDigest != 0) + c->mine.DataDigest = s->config.DataDigest; c->his = iscsi_conn_defaults; - c->active = iscsi_conn_defaults; + + c->sev.sess = s; + c->sev.conn = c; + evtimer_set(&c->sev.ev, session_fsm_callback, &c->sev); TAILQ_INIT(&c->pdu_w); TAILQ_INIT(&c->tasks); @@ -113,6 +118,7 @@ conn_free(struct connection *c) pdu_readbuf_free(&c->prbuf); pdu_free_queue(&c->pdu_w); + event_del(&c->sev.ev); event_del(&c->ev); event_del(&c->wev); if (c->fd != -1) @@ -262,7 +268,6 @@ do { \ (p)->key, (p)->value, err); \ errors++; \ } \ -log_debug("SET_NUM: %s = %llu", #v, (u_int64_t)(x)->his.v); \ } \ } while (0) @@ -275,7 +280,18 @@ do { \ (p)->key, (p)->value, err); \ errors++; \ } \ -log_debug("SET_BOOL: %s = %u", #v, (int)(x)->his.v); \ + } \ +} while (0) + +#define SET_DIGEST(p, x, v) \ +do { \ + if (!strcmp((p)->key, #v)) { \ + (x)->his.v = text_to_digest((p)->value, &err); \ + if (err) { \ + log_warnx("bad param %s=%s: %s", \ + (p)->key, (p)->value, err); \ + errors++; \ + } \ } \ } while (0) @@ -304,6 +320,8 @@ log_debug("conn_parse_kvp: %s = %s", k->key, k->value); SET_BOOL(k, s, DataSequenceInOrder); SET_NUM(k, s, ErrorRecoveryLevel, 0, 2); SET_NUM(k, c, MaxRecvDataSegmentLength, 512, 16777215); + SET_DIGEST(k, c, HeaderDigest); + SET_DIGEST(k, c, DataDigest); } if (errors) { @@ -315,6 +333,7 @@ log_debug("conn_parse_kvp: %s = %s", k->key, k->value); #undef SET_NUM #undef SET_BOOL +#undef SET_DIGEST int conn_gen_kvp(struct connection *c, struct kvp *kvp, size_t *nkvp) @@ -435,7 +454,7 @@ c_do_connect(struct connection *c, enum c_event ev) if (c->fd == -1) { log_warnx("connect(%s), lost socket", log_sockaddr(&c->config.TargetAddr)); - session_fsm(c->session, SESS_EV_CONN_FAIL, c, 0); + session_fsm(&c->sev, SESS_EV_CONN_FAIL, 0); return CONN_FREE; } if (c->config.LocalAddr.ss_len != 0) { @@ -443,7 +462,7 @@ c_do_connect(struct connection *c, enum c_event ev) c->config.LocalAddr.ss_len) == -1) { log_warn("bind(%s)", log_sockaddr(&c->config.LocalAddr)); - session_fsm(c->session, SESS_EV_CONN_FAIL, c, 0); + session_fsm(&c->sev, SESS_EV_CONN_FAIL, 0); return CONN_FREE; } } @@ -456,7 +475,7 @@ c_do_connect(struct connection *c, enum c_event ev) } else { log_warn("connect(%s)", log_sockaddr(&c->config.TargetAddr)); - session_fsm(c->session, SESS_EV_CONN_FAIL, c, 0); + session_fsm(&c->sev, SESS_EV_CONN_FAIL, 0); return CONN_FREE; } } @@ -477,7 +496,7 @@ int c_do_loggedin(struct connection *c, enum c_event ev) { iscsi_merge_conn_params(&c->active, &c->mine, &c->his); - session_fsm(c->session, SESS_EV_CONN_LOGGED_IN, c, 0); + session_fsm(&c->sev, SESS_EV_CONN_LOGGED_IN, 0); return CONN_LOGGED_IN; } @@ -525,7 +544,7 @@ c_do_fail(struct connection *c, enum c_event ev) taskq_cleanup(&c->tasks); /* session will take care of cleaning up the mess */ - session_fsm(c->session, SESS_EV_CONN_FAIL, c, 0); + session_fsm(&c->sev, SESS_EV_CONN_FAIL, 0); if (ev == CONN_EV_FREE || c->state & CONN_NEVER_LOGGED_IN) return CONN_FREE; diff --git a/usr.sbin/iscsid/initiator.c b/usr.sbin/iscsid/initiator.c index 76cce12b0..d873ac13d 100644 --- a/usr.sbin/iscsid/initiator.c +++ b/usr.sbin/iscsid/initiator.c @@ -1,4 +1,4 @@ -/* $OpenBSD: initiator.c,v 1.16 2025/01/16 16:19:39 claudio Exp $ */ +/* $OpenBSD: initiator.c,v 1.20 2025/01/22 16:06:36 claudio Exp $ */ /* * Copyright (c) 2009 Claudio Jeker @@ -33,7 +33,7 @@ #include "iscsid.h" #include "log.h" -struct initiator *initiator; +static struct initiator *initiator; struct task_login { struct task task; @@ -58,11 +58,10 @@ void initiator_login_cb(struct connection *, void *, struct pdu *); void initiator_discovery_cb(struct connection *, void *, struct pdu *); void initiator_logout_cb(struct connection *, void *, struct pdu *); - struct session_params initiator_sess_defaults; struct connection_params initiator_conn_defaults; -struct initiator * +void initiator_init(void) { if (!(initiator = calloc(1, sizeof(*initiator)))) @@ -78,24 +77,34 @@ initiator_init(void) initiator_conn_defaults = iscsi_conn_defaults; initiator_sess_defaults.MaxConnections = ISCSID_DEF_CONNS; initiator_conn_defaults.MaxRecvDataSegmentLength = 65536; - - return initiator; } void -initiator_cleanup(struct initiator *i) +initiator_cleanup(void) { struct session *s; - while ((s = TAILQ_FIRST(&i->sessions)) != NULL) { - TAILQ_REMOVE(&i->sessions, s, entry); + while ((s = TAILQ_FIRST(&initiator->sessions)) != NULL) { + TAILQ_REMOVE(&initiator->sessions, s, entry); session_cleanup(s); } free(initiator); } void -initiator_shutdown(struct initiator *i) +initiator_set_config(struct initiator_config *ic) +{ + initiator->config = *ic; +} + +struct initiator_config * +initiator_get_config(void) +{ + return &initiator->config; +} + +void +initiator_shutdown(void) { struct session *s; @@ -106,7 +115,7 @@ initiator_shutdown(struct initiator *i) } int -initiator_isdown(struct initiator *i) +initiator_isdown(void) { struct session *s; int inprogres = 0; @@ -118,6 +127,49 @@ initiator_isdown(struct initiator *i) return !inprogres; } +struct session * +initiator_new_session(u_int8_t st) +{ + struct session *s; + + if (!(s = calloc(1, sizeof(*s)))) + return NULL; + + /* use the same qualifier unless there is a conflict */ + s->isid_base = initiator->config.isid_base; + s->isid_qual = initiator->config.isid_qual; + s->cmdseqnum = arc4random(); + s->itt = arc4random(); + s->state = SESS_INIT; + + s->sev.sess = s; + evtimer_set(&s->sev.ev, session_fsm_callback, &s->sev); + + if (st == SESSION_TYPE_DISCOVERY) + s->target = 0; + else + s->target = initiator->target++; + + TAILQ_INIT(&s->connections); + TAILQ_INIT(&s->tasks); + + TAILQ_INSERT_HEAD(&initiator->sessions, s, entry); + + return s; +} + +struct session * +initiator_find_session(char *name) +{ + struct session *s; + + TAILQ_FOREACH(s, &initiator->sessions, entry) { + if (strcmp(s->config.SessionName, name) == 0) + return s; + } + return NULL; +} + struct session * initiator_t2s(u_int target) { @@ -130,6 +182,12 @@ initiator_t2s(u_int target) return NULL; } +struct session_head * +initiator_get_sessions(void) +{ + return &initiator->sessions; +} + void initiator_login(struct connection *c) { @@ -258,7 +316,7 @@ initiator_login_kvp(struct connection *c, u_int8_t stage) switch (stage) { case ISCSI_LOGIN_STG_SECNEG: - if (!(kvp = calloc(4, sizeof(*kvp)))) + if (!(kvp = calloc(5, sizeof(*kvp)))) return NULL; kvp[0].key = "AuthMethod"; kvp[0].value = "None"; @@ -269,8 +327,10 @@ initiator_login_kvp(struct connection *c, u_int8_t stage) kvp[2].key = "SessionType"; kvp[2].value = "Discovery"; } else { - kvp[2].key = "TargetName"; - kvp[2].value = c->session->config.TargetName; + kvp[2].key = "SessionType"; + kvp[2].value = "Normal"; + kvp[3].key = "TargetName"; + kvp[3].value = c->session->config.TargetName; } break; case ISCSI_LOGIN_STG_OPNEG: @@ -512,10 +572,10 @@ initiator_logout_cb(struct connection *c, void *arg, struct pdu *p) case ISCSI_LOGOUT_RESP_SUCCESS: if (tl->reason == ISCSI_LOGOUT_CLOSE_SESS) { conn_fsm(c, CONN_EV_LOGGED_OUT); - session_fsm(c->session, SESS_EV_CLOSED, NULL, 0); + session_fsm(&c->session->sev, SESS_EV_CLOSED, 0); } else { conn_fsm(tl->c, CONN_EV_LOGGED_OUT); - session_fsm(c->session, SESS_EV_CONN_CLOSED, tl->c, 0); + session_fsm(&tl->c->sev, SESS_EV_CONN_CLOSED, 0); } break; case ISCSI_LOGOUT_RESP_UNKN_CID: diff --git a/usr.sbin/iscsid/iscsid.8 b/usr.sbin/iscsid/iscsid.8 index f78f4b860..c49b3502c 100644 --- a/usr.sbin/iscsid/iscsid.8 +++ b/usr.sbin/iscsid/iscsid.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: iscsid.8,v 1.10 2015/07/27 17:28:39 sobrado Exp $ +.\" $OpenBSD: iscsid.8,v 1.11 2025/01/21 12:26:47 claudio Exp $ .\" .\" Copyright (c) 2010 David Gwynne .\" @@ -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 27 2015 $ +.Dd $Mdocdate: January 21 2025 $ .Dt ISCSID 8 .Os .Sh NAME @@ -74,26 +74,16 @@ socket used for communication with .Xr iscsictl 8 .Sh STANDARDS .Rs -.%A J. Satran -.%A K. Meth -.%A C. Sapuntzakis -.%A M. Chadalapaka -.%A E. Zeidner -.%D April 2004 -.%R RFC 3720 -.%T Internet Small Computer Systems Interface (iSCSI) -.Re -.Pp -.Rs -.%A M. Bakke -.%A J. Hafner -.%A J. Hufferd -.%A K. Voruganti -.%A M. Krueger .%D April 2004 .%R RFC 3721 .%T Internet Small Computer Systems Interface (iSCSI) Naming and Discovery .Re +.Pp +.Rs +.%D April 2014 +.%R RFC 7143 +.%T Internet Small Computer System Interface (iSCSI) Protocol (Consolidated) +.Re .Sh HISTORY The .Nm diff --git a/usr.sbin/iscsid/iscsid.c b/usr.sbin/iscsid/iscsid.c index 6815ad7a0..abf3c6fe0 100644 --- a/usr.sbin/iscsid/iscsid.c +++ b/usr.sbin/iscsid/iscsid.c @@ -1,4 +1,4 @@ -/* $OpenBSD: iscsid.c,v 1.22 2021/04/16 14:37:06 claudio Exp $ */ +/* $OpenBSD: iscsid.c,v 1.25 2025/01/22 16:06:36 claudio Exp $ */ /* * Copyright (c) 2009 Claudio Jeker @@ -38,7 +38,6 @@ void main_sig_handler(int, short, void *); __dead void usage(void); void shutdown_cb(int, short, void *); -extern struct initiator *initiator; struct event exit_ev; int exit_rounds; #define ISCSI_EXIT_WAIT 5 @@ -54,11 +53,13 @@ const struct session_params iscsi_sess_defaults = { .ImmediateData = 1, .DataPDUInOrder = 1, .DataSequenceInOrder = 1, - .ErrorRecoveryLevel = 0 + .ErrorRecoveryLevel = 0, }; const struct connection_params iscsi_conn_defaults = { - .MaxRecvDataSegmentLength = 8192 + .MaxRecvDataSegmentLength = 8192, + .HeaderDigest = DIGEST_NONE, + .DataDigest = DIGEST_NONE, }; int @@ -146,13 +147,13 @@ main(int argc, char *argv[]) signal(SIGPIPE, SIG_IGN); control_event_init(); - initiator = initiator_init(); + initiator_init(); event_dispatch(); /* do some cleanup on the way out */ control_cleanup(ctrlsock); - initiator_cleanup(initiator); + initiator_cleanup(); log_info("exiting."); return 0; } @@ -162,7 +163,7 @@ shutdown_cb(int fd, short event, void *arg) { struct timeval tv; - if (exit_rounds++ >= ISCSI_EXIT_WAIT || initiator_isdown(initiator)) + if (exit_rounds++ >= ISCSI_EXIT_WAIT || initiator_isdown()) event_loopexit(NULL); timerclear(&tv); @@ -182,7 +183,7 @@ main_sig_handler(int sig, short event, void *arg) case SIGTERM: case SIGINT: case SIGHUP: - initiator_shutdown(initiator); + initiator_shutdown(); evtimer_set(&exit_ev, shutdown_cb, NULL); timerclear(&tv); if (evtimer_add(&exit_ev, &tv) == -1) @@ -209,6 +210,7 @@ iscsid_ctrl_dispatch(void *ch, struct pdu *pdu) { struct ctrlmsghdr *cmh; struct initiator_config *ic; + struct session_head *sh; struct session_config *sc; struct session *s; struct session_poll p = { 0 }; @@ -226,7 +228,7 @@ iscsid_ctrl_dispatch(void *ch, struct pdu *pdu) break; } ic = pdu_getbuf(pdu, NULL, 1); - memcpy(&initiator->config, ic, sizeof(initiator->config)); + initiator_set_config(ic); control_compose(ch, CTRL_SUCCESS, NULL, 0); break; case CTRL_SESSION_CONFIG: @@ -248,9 +250,9 @@ iscsid_ctrl_dispatch(void *ch, struct pdu *pdu) else sc->InitiatorName = NULL; - s = session_find(initiator, sc->SessionName); + s = initiator_find_session(sc->SessionName); if (s == NULL) { - s = session_new(initiator, sc->SessionType); + s = initiator_new_session(sc->SessionType); if (s == NULL) { control_compose(ch, CTRL_FAILURE, NULL, 0); goto done; @@ -259,7 +261,7 @@ iscsid_ctrl_dispatch(void *ch, struct pdu *pdu) session_config(s, sc); if (s->state == SESS_INIT) - session_fsm(s, SESS_EV_START, NULL, 0); + session_fsm(&s->sev, SESS_EV_START, 0); control_compose(ch, CTRL_SUCCESS, NULL, 0); break; @@ -278,10 +280,11 @@ iscsid_ctrl_dispatch(void *ch, struct pdu *pdu) sizeof(struct vscsi_stats)); break; case CTRL_SHOW_SUM: - control_compose(ch, CTRL_INITIATOR_CONFIG, &initiator->config, - sizeof(initiator->config)); + ic = initiator_get_config(); + control_compose(ch, CTRL_INITIATOR_CONFIG, ic, sizeof(*ic)); - TAILQ_FOREACH(s, &initiator->sessions, entry) { + sh = initiator_get_sessions(); + TAILQ_FOREACH(s, sh, entry) { struct ctrldata cdv[3]; bzero(cdv, sizeof(cdv)); @@ -306,7 +309,8 @@ iscsid_ctrl_dispatch(void *ch, struct pdu *pdu) control_compose(ch, CTRL_SUCCESS, NULL, 0); break; case CTRL_SESS_POLL: - TAILQ_FOREACH(s, &initiator->sessions, entry) + sh = initiator_get_sessions(); + TAILQ_FOREACH(s, sh, entry) poll_session(&p, s); poll_finalize(&p); control_compose(ch, CTRL_SESS_POLL, &p, sizeof(p)); @@ -334,6 +338,8 @@ void iscsi_merge_sess_params(struct session_params *res, struct session_params *mine, struct session_params *his) { + memset(res, 0, sizeof(*res)); + MERGE_MIN(res, mine, his, MaxBurstLength); MERGE_MIN(res, mine, his, FirstBurstLength); MERGE_MAX(res, mine, his, DefaultTime2Wait); @@ -353,8 +359,26 @@ void iscsi_merge_conn_params(struct connection_params *res, struct connection_params *mine, struct connection_params *his) { + int mask; + + memset(res, 0, sizeof(*res)); + res->MaxRecvDataSegmentLength = his->MaxRecvDataSegmentLength; - /* XXX HeaderDigest and DataDigest */ + + /* for digest select first bit that is set in both his and mine */ + mask = mine->HeaderDigest & his->HeaderDigest; + mask = ffs(mask) - 1; + if (mask == -1) + res->HeaderDigest = 0; + else + res->HeaderDigest = 1 << mask; + + mask = mine->DataDigest & his->DataDigest; + mask = ffs(mask) - 1; + if (mask == -1) + res->DataDigest = 0; + else + res->DataDigest = 1 << mask; } #undef MERGE_MIN diff --git a/usr.sbin/iscsid/iscsid.h b/usr.sbin/iscsid/iscsid.h index 2eee9719b..aad1dc05b 100644 --- a/usr.sbin/iscsid/iscsid.h +++ b/usr.sbin/iscsid/iscsid.h @@ -1,4 +1,4 @@ -/* $OpenBSD: iscsid.h,v 1.20 2025/01/16 16:19:39 claudio Exp $ */ +/* $OpenBSD: iscsid.h,v 1.23 2025/01/22 16:06:36 claudio Exp $ */ /* * Copyright (c) 2009 Claudio Jeker @@ -181,6 +181,9 @@ struct session_config { u_int8_t disabled; }; +#define DIGEST_NONE 0x1 +#define DIGEST_CRC32C 0x2 + #define SESSION_TYPE_NORMAL 0 #define SESSION_TYPE_DISCOVERY 1 @@ -226,6 +229,7 @@ struct initiator { }; struct sessev { + struct event ev; struct session *sess; struct connection *conn; enum s_event event; @@ -233,13 +237,13 @@ struct sessev { struct session { TAILQ_ENTRY(session) entry; + struct sessev sev; struct connection_head connections; struct taskq tasks; struct session_config config; struct session_params mine; struct session_params his; struct session_params active; - struct initiator *initiator; u_int32_t cmdseqnum; u_int32_t itt; u_int32_t isid_base; /* only 24 bits */ @@ -264,6 +268,7 @@ struct session_poll { struct connection { struct event ev; struct event wev; + struct sessev sev; TAILQ_ENTRY(connection) entry; struct connection_params mine; struct connection_params his; @@ -323,11 +328,16 @@ void iscsi_merge_sess_params(struct session_params *, void iscsi_merge_conn_params(struct connection_params *, struct connection_params *, struct connection_params *); -struct initiator *initiator_init(void); -void initiator_cleanup(struct initiator *); -void initiator_shutdown(struct initiator *); -int initiator_isdown(struct initiator *); -struct session *initiator_t2s(u_int); +void initiator_init(void); +void initiator_cleanup(void); +void initiator_set_config(struct initiator_config *); +struct initiator_config *initiator_get_config(void); +void initiator_shutdown(void); +int initiator_isdown(void); +struct session *initiator_new_session(u_int8_t); +struct session *initiator_find_session(char *); +struct session *initiator_t2s(u_int); +struct session_head *initiator_get_sessions(void); void initiator_login(struct connection *); void initiator_discovery(struct session *); void initiator_logout(struct session *, struct connection *, u_int8_t); @@ -341,16 +351,14 @@ void control_queue(void *, struct pdu *); int control_compose(void *, u_int16_t, void *, size_t); int control_build(void *, u_int16_t, int, struct ctrldata *); -struct session *session_find(struct initiator *, char *); -struct session *session_new(struct initiator *, u_int8_t); void session_cleanup(struct session *); int session_shutdown(struct session *); void session_config(struct session *, struct session_config *); void session_task_issue(struct session *, struct task *); void session_logout_issue(struct session *, struct task *); void session_schedule(struct session *); -void session_fsm(struct session *, enum s_event, struct connection *, - unsigned int); +void session_fsm(struct sessev *, enum s_event, unsigned int); +void session_fsm_callback(int, short, void *); void conn_new(struct session *, struct connection_config *); void conn_free(struct connection *); @@ -369,6 +377,7 @@ int text_to_pdu(struct kvp *, struct pdu *); struct kvp *pdu_to_text(char *, size_t); u_int64_t text_to_num(const char *, u_int64_t, u_int64_t, const char **); int text_to_bool(const char *, const char **); +int text_to_digest(const char *, const char **); void pdu_free_queue(struct pduq *); ssize_t pdu_read(struct connection *); ssize_t pdu_write(struct connection *); diff --git a/usr.sbin/iscsid/pdu.c b/usr.sbin/iscsid/pdu.c index e694d45c6..7358a89be 100644 --- a/usr.sbin/iscsid/pdu.c +++ b/usr.sbin/iscsid/pdu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pdu.c,v 1.13 2021/04/12 10:03:33 claudio Exp $ */ +/* $OpenBSD: pdu.c,v 1.14 2025/01/22 10:14:54 claudio Exp $ */ /* * Copyright (c) 2009 Claudio Jeker @@ -193,23 +193,42 @@ text_to_bool(const char *buf, const char **errstrp) { int val = 0; - if (!strcmp(buf, "Yes")) { + if (strcmp(buf, "Yes") == 0) val = 1; - errno = 0; - } else if (!strcmp(buf, "No")) - errno = 0; - else - errno = EINVAL; - - if (errstrp != NULL) { - if (errno == 0) - *errstrp = NULL; - else + else if (strcmp(buf, "No") != 0) { + if (errstrp != NULL) *errstrp = "invalid"; } return val; } +int +text_to_digest(const char *buf, const char **errstrp) +{ + int val = 0; + size_t len; + const char *p; + + while (buf != NULL) { + p = strchr(buf, ','); + if (p == NULL) + len = strlen(buf); + else + len = p++ - buf; + + if (strncmp(buf, "None", len) == 0) + val |= DIGEST_NONE; + else if (strncmp(buf, "CRC32C", len) == 0) + val |= DIGEST_CRC32C; + else { + if (errstrp != NULL) + *errstrp = "invalid"; + return 0; + } + buf = p; + } + return val; +} /* * Internal functions to send/recv pdus. diff --git a/usr.sbin/iscsid/session.c b/usr.sbin/iscsid/session.c index f9820753b..28dcb930c 100644 --- a/usr.sbin/iscsid/session.c +++ b/usr.sbin/iscsid/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.10 2025/01/16 16:17:32 claudio Exp $ */ +/* $OpenBSD: session.c,v 1.13 2025/01/22 16:06:36 claudio Exp $ */ /* * Copyright (c) 2011 Claudio Jeker @@ -35,7 +35,6 @@ #include "iscsid.h" #include "log.h" -void session_fsm_callback(int, short, void *); int sess_do_start(struct session *, struct sessev *); int sess_do_conn_loggedin(struct session *, struct sessev *); int sess_do_conn_fail(struct session *, struct sessev *); @@ -47,46 +46,6 @@ int sess_do_reinstatement(struct session *, struct sessev *); const char *sess_state(int); const char *sess_event(enum s_event); -struct session * -session_find(struct initiator *i, char *name) -{ - struct session *s; - - TAILQ_FOREACH(s, &i->sessions, entry) { - if (strcmp(s->config.SessionName, name) == 0) - return s; - } - return NULL; -} - -struct session * -session_new(struct initiator *i, u_int8_t st) -{ - struct session *s; - - if (!(s = calloc(1, sizeof(*s)))) - return NULL; - - /* use the same qualifier unless there is a conflict */ - s->isid_base = i->config.isid_base; - s->isid_qual = i->config.isid_qual; - s->cmdseqnum = arc4random(); - s->itt = arc4random(); - s->initiator = i; - s->state = SESS_INIT; - - if (st == SESSION_TYPE_DISCOVERY) - s->target = 0; - else - s->target = s->initiator->target++; - - TAILQ_INSERT_HEAD(&i->sessions, s, entry); - TAILQ_INIT(&s->connections); - TAILQ_INIT(&s->tasks); - - return s; -} - void session_cleanup(struct session *s) { @@ -204,25 +163,20 @@ session_schedule(struct session *s) * The session FSM runs from a callback so that the connection FSM can finish. */ void -session_fsm(struct session *s, enum s_event ev, struct connection *c, - unsigned int timeout) +session_fsm(struct sessev *sev, enum s_event event, unsigned int timeout) { + struct session *s = sev->sess; struct timeval tv; - struct sessev *sev; log_debug("session_fsm[%s]: %s ev %s timeout %d", s->config.SessionName, sess_state(s->state), - sess_event(ev), timeout); + sess_event(event), timeout); - if ((sev = malloc(sizeof(*sev))) == NULL) - fatal("session_fsm"); - sev->conn = c; - sev->sess = s; - sev->event = ev; + sev->event = event; timerclear(&tv); tv.tv_sec = timeout; - if (event_once(-1, EV_TIMEOUT, session_fsm_callback, sev, &tv) == -1) + if (evtimer_add(&sev->ev, &tv) == -1) fatal("session_fsm"); } @@ -276,8 +230,6 @@ session_fsm_callback(int fd, short event, void *arg) sess_state(s->state), sess_event(sev->event)); fatalx("bjork bjork bjork"); } - free(sev); -log_debug("sess_fsm: done"); } int @@ -286,7 +238,7 @@ sess_do_start(struct session *s, struct sessev *sev) log_debug("new connection to %s", log_sockaddr(&s->config.connection.TargetAddr)); - /* initialize the session params */ + /* initialize the session params, and reset the active state */ s->mine = initiator_sess_defaults; s->his = iscsi_sess_defaults; s->active = iscsi_sess_defaults; @@ -360,7 +312,7 @@ sess_do_conn_fail(struct session *s, struct sessev *sev) state = SESS_LOGGED_IN; } - session_fsm(s, SESS_EV_START, NULL, s->holdTimer); + session_fsm(&s->sev, SESS_EV_START, s->holdTimer); /* exponential back-off on constant failure */ if (s->holdTimer < ISCSID_HOLD_TIME_MAX) s->holdTimer = s->holdTimer ? s->holdTimer * 2 : 1;