From b50a267d2abc2278e526ef464634dee49e1d9346 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 25 2022 08:13:38 +0000 Subject: import golang-1.19.2-4.module+el8.8.0+17327+0baa7998 --- diff --git a/SOURCES/enable-big-endian-fips-mode.patch b/SOURCES/enable-big-endian-fips-mode.patch new file mode 100644 index 0000000..f9756e1 --- /dev/null +++ b/SOURCES/enable-big-endian-fips-mode.patch @@ -0,0 +1,348 @@ +diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/ecdsa.go b/src/vendor/github.com/golang-fips/openssl-fips/openssl/ecdsa.go +index b3501400e0..5e1e789da0 100644 +--- a/src/vendor/github.com/golang-fips/openssl-fips/openssl/ecdsa.go ++++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/ecdsa.go +@@ -131,7 +131,7 @@ func NewPrivateKeyECDSA(curve string, X, Y BigInt, D BigInt) (*PrivateKeyECDSA, + func HashSignECDSA(priv *PrivateKeyECDSA, hash []byte, h crypto.Hash) (*big.Int, *big.Int, error) { + size := C._goboringcrypto_ECDSA_size(priv.key) + sig := make([]byte, size) +- var sigLen C.uint ++ var sigLen C.size_t + md := cryptoHashToMD(h) + if md == nil { + panic("boring: invalid hash") +diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/goopenssl.h b/src/vendor/github.com/golang-fips/openssl-fips/openssl/goopenssl.h +index 411fefdf78..217b320e4a 100644 +--- a/src/vendor/github.com/golang-fips/openssl-fips/openssl/goopenssl.h ++++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/goopenssl.h +@@ -218,10 +218,16 @@ DEFINEFUNC(const GO_EVP_MD *, EVP_sha512, (void), ()) + DEFINEFUNC(const GO_EVP_MD *, EVP_md_null, (void), ()) + #if OPENSSL_VERSION_NUMBER < 0x30000000L + DEFINEFUNCINTERNAL(int, EVP_MD_type, (const GO_EVP_MD *arg0), (arg0)) ++DEFINEFUNCINTERNAL(size_t, EVP_MD_size, (const GO_EVP_MD *arg0), (arg0)) ++static inline int ++_goboringcrypto_EVP_MD_get_size(const GO_EVP_MD *arg0) ++{ ++ return _goboringcrypto_internal_EVP_MD_size(arg0); ++} + #else + DEFINEFUNCINTERNAL(int, EVP_MD_get_type, (const GO_EVP_MD *arg0), (arg0)) ++DEFINEFUNC(size_t, EVP_MD_get_size, (const GO_EVP_MD *arg0), (arg0)) + #endif +-DEFINEFUNCINTERNAL(size_t, EVP_MD_size, (const GO_EVP_MD *arg0), (arg0)) + DEFINEFUNCINTERNAL(const GO_EVP_MD*, EVP_md5_sha1, (void), ()) + + # include +@@ -275,26 +281,16 @@ DEFINEFUNC(void, HMAC_CTX_free, (GO_HMAC_CTX * arg0), (arg0)) + #if OPENSSL_VERSION_NUMBER < 0x10100000L + static inline size_t + _goboringcrypto_HMAC_size(const GO_HMAC_CTX* arg0) { +- return _goboringcrypto_internal_EVP_MD_size(arg0->md); ++ return _goboringcrypto_EVP_MD_get_size(arg0->md); + } + #else + DEFINEFUNCINTERNAL(const EVP_MD*, HMAC_CTX_get_md, (const GO_HMAC_CTX* ctx), (ctx)) +-# if OPENSSL_VERSION_NUMBER < 0x30000000L +-static inline size_t +-_goboringcrypto_HMAC_size(const GO_HMAC_CTX* arg0) { +- const EVP_MD* md; +- md = _goboringcrypto_internal_HMAC_CTX_get_md(arg0); +- return _goboringcrypto_internal_EVP_MD_size(md); +-} +-# else +-DEFINEFUNCINTERNAL(size_t, EVP_MD_get_size, (const GO_EVP_MD *arg0), (arg0)) + static inline size_t + _goboringcrypto_HMAC_size(const GO_HMAC_CTX* arg0) { + const EVP_MD* md; + md = _goboringcrypto_internal_HMAC_CTX_get_md(arg0); +- return _goboringcrypto_internal_EVP_MD_get_size(md); ++ return _goboringcrypto_EVP_MD_get_size(md); + } +-# endif + #endif + + #if OPENSSL_VERSION_NUMBER < 0x10100000L +@@ -370,6 +366,7 @@ DEFINEFUNC(unsigned int, BN_num_bits, (const GO_BIGNUM *arg0), (arg0)) + DEFINEFUNC(int, BN_is_negative, (const GO_BIGNUM *arg0), (arg0)) + DEFINEFUNC(GO_BIGNUM *, BN_bin2bn, (const uint8_t *arg0, size_t arg1, GO_BIGNUM *arg2), (arg0, arg1, arg2)) + DEFINEFUNC(GO_BIGNUM *, BN_lebin2bn, (const unsigned char *s, size_t len, BIGNUM *ret), (s, len, ret)) ++DEFINEFUNC(int, BN_bn2binpad, (const BIGNUM *a, unsigned char *to, size_t tolen), (a, to, tolen)) + DEFINEFUNC(int, BN_bn2lebinpad, (const BIGNUM *a, unsigned char *to, size_t tolen), (a, to, tolen)) + + static inline unsigned int +@@ -418,7 +415,7 @@ typedef ECDSA_SIG GO_ECDSA_SIG; + DEFINEFUNC(GO_ECDSA_SIG *, ECDSA_SIG_new, (void), ()) + DEFINEFUNC(void, ECDSA_SIG_free, (GO_ECDSA_SIG * arg0), (arg0)) + DEFINEFUNC(GO_ECDSA_SIG *, ECDSA_do_sign, (const uint8_t *arg0, size_t arg1, const GO_EC_KEY *arg2), (arg0, arg1, arg2)) +-DEFINEFUNC(int, ECDSA_do_verify, (const uint8_t *arg0, size_t arg1, const GO_ECDSA_SIG *arg2, const GO_EC_KEY *arg3), (arg0, arg1, arg2, arg3)) ++DEFINEFUNC(int, ECDSA_do_verify, (const uint8_t *arg0, size_t arg1, const GO_ECDSA_SIG *arg2, GO_EC_KEY *arg3), (arg0, arg1, arg2, arg3)) + DEFINEFUNC(size_t, ECDSA_size, (const GO_EC_KEY *arg0), (arg0)) + + DEFINEFUNCINTERNAL(int, ECDSA_sign, +@@ -453,25 +450,25 @@ _goboringcrypto_EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *rsa) { + } + + DEFINEFUNC(int, EVP_DigestSignInit, +- (EVP_MD_CTX* ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, const EVP_PKEY *pkey), ++ (EVP_MD_CTX* ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey), + (ctx, pctx, type, e, pkey)) + + DEFINEFUNC(int, EVP_DigestUpdate, + (EVP_MD_CTX* ctx, const void *d, size_t cnt), + (ctx, d, cnt)) + DEFINEFUNC(int, EVP_DigestSignFinal, +- (EVP_MD_CTX* ctx, unsigned char *sig, unsigned int *siglen), ++ (EVP_MD_CTX* ctx, unsigned char *sig, size_t *siglen), + (ctx, sig, siglen)) + + DEFINEFUNC(int, EVP_DigestVerifyInit, +- (EVP_MD_CTX* ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, const EVP_PKEY *pkey), ++ (EVP_MD_CTX* ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey), + (ctx, pctx, type, e, pkey)) + DEFINEFUNC(int, EVP_DigestVerifyFinal, + (EVP_MD_CTX* ctx, const uint8_t *sig, unsigned int siglen), + (ctx, sig, siglen)) + + typedef RSA GO_RSA; +-int _goboringcrypto_EVP_sign(EVP_MD* md, EVP_PKEY_CTX *ctx, const uint8_t *msg, size_t msgLen, uint8_t *sig, unsigned int *slen, EVP_PKEY *eckey); ++int _goboringcrypto_EVP_sign(EVP_MD* md, EVP_PKEY_CTX *ctx, const uint8_t *msg, size_t msgLen, uint8_t *sig, size_t *slen, EVP_PKEY *eckey); + int _goboringcrypto_EVP_sign_raw(EVP_MD *md, EVP_PKEY_CTX *ctx, const uint8_t *msg, + size_t msgLen, uint8_t *sig, size_t *slen, + GO_RSA *key); +@@ -490,7 +487,7 @@ static inline void _goboringcrypto_EVP_MD_CTX_free(EVP_MD_CTX *ctx) { + DEFINEFUNC(void, EVP_MD_CTX_free, (EVP_MD_CTX *ctx), (ctx)) + #endif + +-int _goboringcrypto_ECDSA_sign(EVP_MD *md, const uint8_t *arg1, size_t arg2, uint8_t *arg3, unsigned int *arg4, GO_EC_KEY *arg5); ++int _goboringcrypto_ECDSA_sign(EVP_MD *md, const uint8_t *arg1, size_t arg2, uint8_t *arg3, size_t *arg4, GO_EC_KEY *arg5); + int _goboringcrypto_ECDSA_verify(EVP_MD *md, const uint8_t *arg1, size_t arg2, const uint8_t *arg3, unsigned int arg4, GO_EC_KEY *arg5); + + #include +@@ -498,7 +495,7 @@ int _goboringcrypto_ECDSA_verify(EVP_MD *md, const uint8_t *arg1, size_t arg2, c + // Note: order of struct fields here is unchecked. + typedef BN_GENCB GO_BN_GENCB; + +-int _goboringcrypto_EVP_RSA_sign(EVP_MD* md, const uint8_t *msg, unsigned int msgLen, uint8_t *sig, unsigned int *slen, RSA *rsa); ++int _goboringcrypto_EVP_RSA_sign(EVP_MD* md, const uint8_t *msg, unsigned int msgLen, uint8_t *sig, size_t *slen, RSA *rsa); + int _goboringcrypto_EVP_RSA_verify(EVP_MD* md, const uint8_t *msg, unsigned int msgLen, const uint8_t *sig, unsigned int slen, GO_RSA *rsa); + + DEFINEFUNC(GO_RSA *, RSA_new, (void), ()) +@@ -800,10 +797,10 @@ _goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(GO_EVP_PKEY_CTX * ctx, const GO_EVP + } + + DEFINEFUNC(int, EVP_PKEY_decrypt, +- (GO_EVP_PKEY_CTX * arg0, uint8_t *arg1, unsigned int *arg2, const uint8_t *arg3, unsigned int arg4), ++ (GO_EVP_PKEY_CTX * arg0, uint8_t *arg1, size_t *arg2, const uint8_t *arg3, size_t arg4), + (arg0, arg1, arg2, arg3, arg4)) + DEFINEFUNC(int, EVP_PKEY_encrypt, +- (GO_EVP_PKEY_CTX * arg0, uint8_t *arg1, unsigned int *arg2, const uint8_t *arg3, unsigned int arg4), ++ (GO_EVP_PKEY_CTX * arg0, uint8_t *arg1, size_t *arg2, const uint8_t *arg3, size_t arg4), + (arg0, arg1, arg2, arg3, arg4)) + DEFINEFUNC(int, EVP_PKEY_decrypt_init, (GO_EVP_PKEY_CTX * arg0), (arg0)) + DEFINEFUNC(int, EVP_PKEY_encrypt_init, (GO_EVP_PKEY_CTX * arg0), (arg0)) +diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl.go b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl.go +index 86d7c6c212..2f45dabca2 100644 +--- a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl.go ++++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl.go +@@ -14,6 +14,7 @@ package openssl + */ + import "C" + import ( ++ "encoding/binary" + "errors" + "fmt" + "math/bits" +@@ -184,25 +185,73 @@ type fail string + + func (e fail) Error() string { return "boringcrypto: " + string(e) + " failed" } + +-func wbase(b BigInt) *C.uint8_t { +- if len(b) == 0 { +- return nil ++const wordBytes = bits.UintSize / 8 ++ ++// These two functions were copied from `math/big` package, which ++// defines `big.Int` with a similar representation. ++func (z BigInt) writeBytes(buf []byte) (i int) { ++ i = len(buf) ++ for _, d := range z { ++ for j := 0; j < wordBytes; j++ { ++ i-- ++ if i >= 0 { ++ buf[i] = byte(d) ++ } else if byte(d) != 0 { ++ panic("boringcrypto: buffer too small to fit value") ++ } ++ d >>= 8 ++ } ++ } ++ ++ if i < 0 { ++ i = 0 ++ } ++ for i < len(buf) && buf[i] == 0 { ++ i++ + } +- return (*C.uint8_t)(unsafe.Pointer(&b[0])) ++ ++ return + } + +-const wordBytes = bits.UintSize / 8 ++func bytesToBig(buf []byte) BigInt { ++ z := make(BigInt, (len(buf) + wordBytes - 1) / wordBytes) ++ i := len(buf) ++ for k := 0; i >= wordBytes; k++ { ++ if bits.UintSize == 64 { ++ z[k] = uint(binary.BigEndian.Uint64(buf[i-wordBytes : i])) ++ } else { ++ z[k] = uint(binary.BigEndian.Uint32(buf[i-wordBytes : i])) ++ } ++ i -= wordBytes ++ } ++ if i > 0 { ++ var d uint ++ for s := uint(0); i > 0; s += 8 { ++ d |= uint(buf[i-1]) << s ++ i-- ++ } ++ z[len(z)-1] = d ++ } ++ ++ i = len(z) ++ for i > 0 && z[i-1] == 0 { ++ i-- ++ } ++ return z[0:i] ++} + + func bigToBN(x BigInt) *C.GO_BIGNUM { +- return C._goboringcrypto_BN_lebin2bn(wbase(x), C.size_t(len(x)*wordBytes), nil) ++ buf := make([]byte, len(x)*wordBytes) ++ buf = buf[x.writeBytes(buf):] ++ return C._goboringcrypto_BN_bin2bn(base(buf), C.size_t(len(buf)), nil) + } + + func bnToBig(bn *C.GO_BIGNUM) BigInt { +- x := make(BigInt, (C._goboringcrypto_BN_num_bytes(bn)+wordBytes-1)/wordBytes) +- if C._goboringcrypto_BN_bn2lebinpad(bn, wbase(x), C.size_t(len(x)*wordBytes)) == 0 { ++ buf := make([]byte, C._goboringcrypto_BN_num_bytes(bn)) ++ if C._goboringcrypto_BN_bn2binpad(bn, base(buf), C.size_t(len(buf))) == 0 { + panic("boringcrypto: bignum conversion failed") + } +- return x ++ return bytesToBig(buf) + } + + func bigToBn(bnp **C.GO_BIGNUM, b BigInt) bool { +diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_ecdsa_signature.c b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_ecdsa_signature.c +index 2349db1fd9..714d18f1e8 100644 +--- a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_ecdsa_signature.c ++++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_ecdsa_signature.c +@@ -7,7 +7,7 @@ + #include "goopenssl.h" + + int _goboringcrypto_ECDSA_sign(EVP_MD *md, const uint8_t *msg, size_t msgLen, +- uint8_t *sig, unsigned int *slen, ++ uint8_t *sig, size_t *slen, + GO_EC_KEY *eckey) { + int result; + EVP_PKEY *key = _goboringcrypto_EVP_PKEY_new(); +diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_evp.c b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_evp.c +index 43790198c6..76bac5bc01 100644 +--- a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_evp.c ++++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_evp.c +@@ -7,7 +7,7 @@ + #include "goopenssl.h" + + int _goboringcrypto_EVP_sign(EVP_MD *md, EVP_PKEY_CTX *ctx, const uint8_t *msg, +- size_t msgLen, uint8_t *sig, unsigned int *slen, ++ size_t msgLen, uint8_t *sig, size_t *slen, + EVP_PKEY *key) { + EVP_MD_CTX *mdctx = NULL; + int ret = 0; +diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_rsa.c b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_rsa.c +index 28241470f5..bf39656b45 100644 +--- a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_rsa.c ++++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_rsa.c +@@ -21,7 +21,7 @@ int _goboringcrypto_RSA_generate_key_fips(GO_RSA *rsa, int size, + } + + int _goboringcrypto_RSA_digest_and_sign_pss_mgf1( +- GO_RSA *rsa, unsigned int *out_len, uint8_t *out, size_t max_out, ++ GO_RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, + const uint8_t *in, size_t in_len, EVP_MD *md, const EVP_MD *mgf1_md, + int salt_len) { + EVP_PKEY_CTX *ctx; +@@ -184,7 +184,7 @@ err: + + int _goboringcrypto_EVP_RSA_sign(EVP_MD *md, const uint8_t *msg, + unsigned int msgLen, uint8_t *sig, +- unsigned int *slen, RSA *rsa) { ++ size_t *slen, RSA *rsa) { + int result; + EVP_PKEY *key = _goboringcrypto_EVP_PKEY_new(); + if (!key) { +@@ -216,4 +216,4 @@ int _goboringcrypto_EVP_RSA_verify(EVP_MD *md, const uint8_t *msg, + err: + _goboringcrypto_EVP_PKEY_free(key); + return result; +-} +\ No newline at end of file ++} +diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/rsa.go b/src/vendor/github.com/golang-fips/openssl-fips/openssl/rsa.go +index 915c840834..f48c57adff 100644 +--- a/src/vendor/github.com/golang-fips/openssl-fips/openssl/rsa.go ++++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/rsa.go +@@ -199,7 +199,7 @@ func setupRSA(withKey func(func(*C.GO_RSA) C.int) C.int, + func cryptRSA(withKey func(func(*C.GO_RSA) C.int) C.int, + padding C.int, h hash.Hash, label []byte, saltLen int, ch crypto.Hash, + init func(*C.GO_EVP_PKEY_CTX) C.int, +- crypt func(*C.GO_EVP_PKEY_CTX, *C.uint8_t, *C.uint, *C.uint8_t, C.uint) C.int, ++ crypt func(*C.GO_EVP_PKEY_CTX, *C.uint8_t, *C.size_t, *C.uint8_t, C.size_t) C.int, + in []byte) ([]byte, error) { + + pkey, ctx, err := setupRSA(withKey, padding, h, label, saltLen, ch, init) +@@ -209,12 +209,12 @@ func cryptRSA(withKey func(func(*C.GO_RSA) C.int) C.int, + defer C._goboringcrypto_EVP_PKEY_free(pkey) + defer C._goboringcrypto_EVP_PKEY_CTX_free(ctx) + +- var outLen C.uint +- if crypt(ctx, nil, &outLen, base(in), C.uint(len(in))) == 0 { ++ var outLen C.size_t ++ if crypt(ctx, nil, &outLen, base(in), C.size_t(len(in))) == 0 { + return nil, NewOpenSSLError("EVP_PKEY_decrypt/encrypt failed") + } + out := make([]byte, outLen) +- if crypt(ctx, base(out), &outLen, base(in), C.uint(len(in))) <= 0 { ++ if crypt(ctx, base(out), &outLen, base(in), C.size_t(len(in))) <= 0 { + return nil, NewOpenSSLError("EVP_PKEY_decrypt/encrypt failed") + } + return out[:outLen], nil +@@ -250,7 +250,7 @@ func decryptInit(ctx *C.GO_EVP_PKEY_CTX) C.int { + return C._goboringcrypto_EVP_PKEY_decrypt_init(ctx) + } + +-func decrypt(ctx *C.GO_EVP_PKEY_CTX, out *C.uint8_t, outLen *C.uint, in *C.uint8_t, inLen C.uint) C.int { ++func decrypt(ctx *C.GO_EVP_PKEY_CTX, out *C.uint8_t, outLen *C.size_t, in *C.uint8_t, inLen C.size_t) C.int { + return C._goboringcrypto_EVP_PKEY_decrypt(ctx, out, outLen, in, inLen) + } + +@@ -258,7 +258,7 @@ func encryptInit(ctx *C.GO_EVP_PKEY_CTX) C.int { + return C._goboringcrypto_EVP_PKEY_encrypt_init(ctx) + } + +-func encrypt(ctx *C.GO_EVP_PKEY_CTX, out *C.uint8_t, outLen *C.uint, in *C.uint8_t, inLen C.uint) C.int { ++func encrypt(ctx *C.GO_EVP_PKEY_CTX, out *C.uint8_t, outLen *C.size_t, in *C.uint8_t, inLen C.size_t) C.int { + return C._goboringcrypto_EVP_PKEY_encrypt(ctx, out, outLen, in, inLen) + } + +@@ -326,7 +326,7 @@ func SignRSAPKCS1v15(priv *PrivateKeyRSA, h crypto.Hash, msg []byte, msgIsHashed + } + + var out []byte +- var outLen C.uint ++ var outLen C.size_t + + if priv.withKey(func(key *C.GO_RSA) C.int { + return C._goboringcrypto_EVP_RSA_sign(md, base(msg), C.uint(len(msg)), base(out), &outLen, key) diff --git a/SPECS/golang.spec b/SPECS/golang.spec index 1c834b7..c7be79d 100644 --- a/SPECS/golang.spec +++ b/SPECS/golang.spec @@ -56,7 +56,7 @@ %endif # Controls what ever we fail on failed tests -%ifarch x86_64 %{arm} aarch64 ppc64le +%ifarch x86_64 %{arm} aarch64 ppc64le s390x %global fail_on_tests 1 %else %global fail_on_tests 0 @@ -101,7 +101,7 @@ Name: golang Version: %{version} -Release: 3%{?dist} +Release: 4%{?dist} Summary: The Go Programming Language # source tree includes several copies of Mark.Twain-Tom.Sawyer.txt under Public Domain License: BSD and Public Domain @@ -143,6 +143,7 @@ Patch0: 000-initial-setup.patch Patch1: 001-initial-openssl-for-fips.patch Patch2: disable_static_tests_part1.patch Patch3: disable_static_tests_part2.patch +Patch4: enable-big-endian-fips-mode.patch Patch227: cmd-link-use-correct-path-for-dynamic-loader-on-ppc6.patch @@ -239,6 +240,7 @@ Requires: %{name} = %{version}-%{release} %patch1 -p1 %patch2 -p1 %patch3 -p1 +%patch4 -p1 %patch221 -p1 @@ -517,6 +519,10 @@ cd .. %endif %changelog +* Mon Oct 17 2022 David Benoit - 1.19.2-4 +- Enable big endian support in FIPS mode +- Resolves: rhbz#1969844 + * Mon Oct 17 2022 David Benoit - 1.19.2-3 - Restore old HashSign/HashVerify API - Resolves: rhbz#2132730