Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ODR issues with openssl/boringssl and other bazel libraries #306

Open
RajivKurian opened this issue Dec 6, 2022 · 8 comments
Open

ODR issues with openssl/boringssl and other bazel libraries #306

RajivKurian opened this issue Dec 6, 2022 · 8 comments

Comments

@RajivKurian
Copy link

It looks like for the asio-ssl target, boost brings in boringssl but calls it openssl.
When we use other libraries in our project (like GRPC) that also depend on boringssl, it leads to ODR issues.
It also seems that the maybe bazel helper doesn't work here, because rules_boost brings in boringssl but calls it openssl.
So we cannot just define boringssl outside and have a single version that both rules_boost and grpc pick up.

Here is a sample error in an ASAN build when using GRPC and rules_boost:

==12==ERROR: AddressSanitizer: odr-violation (0x155553494000):
  [1] size=2980 'kOpenSSLReasonValues' external/boringssl/err_data.c:57:16
  [2] size=2960 'kOpenSSLReasonValues' external/openssl/err_data.c:57:16

Is there any suggestion (besides possibly building openssl just for rules_boost), where we could work around this? Would it be possible to call the project boringssl instead, so we can easily supply a single version?

@reltuk
Copy link
Collaborator

reltuk commented Dec 6, 2022

It's certainly not beautiful, but I think you can work around this by creating your own openssl repository with an alias target from :ssl to @boringssl//:ssl. Something like:

workspace(name = "boost_openssl_override")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
  name = "boringssl",
  url = "https://github.com/hedronvision/boringssl/archive/0f5d9c12d1291b0f29eba5c5dc7f9750bfab0032.tar.gz",
  sha256 = "0c39e858689c7f3b3cfc0d88af9ec4aa615158a470ebf459dff06bd096a3ac9b",
  strip_prefix = "boringssl-0f5d9c12d1291b0f29eba5c5dc7f9750bfab0032",
)

new_local_repository(
  name = "openssl",
  path = ".",
  build_file_content = """
alias(
  name = "ssl",
  actual = "@boringssl//:ssl",
  visibility = ["//visibility:public"],
)
""",
)

http_archive(
    name = "com_github_nelhage_rules_boost",
    url = "https://github.com/nelhage/rules_boost/archive/2abec7db70327bc0b4bbdb33c90ff096d0c95872.tar.gz",
    strip_prefix = "rules_boost-2abec7db70327bc0b4bbdb33c90ff096d0c95872",
    sha256 = "37a2568bbda4a61dc2467ad226a1dae93ee9496646217e141003ce9ec5aeb9ce",
)
load("@com_github_nelhage_rules_boost//:boost/boost.bzl", "boost_deps")
boost_deps()

That will keep boost_deps() from installing its own @openssl repo and it will make it build against @openssl//:ssl.

I would recommend replacing path = "." with a relative path to an empty directory.

@wijagels
Copy link
Contributor

wijagels commented Dec 6, 2022

Use repo_mapping = {"@boringssl": "@openssl"} in your http_archive directive for grpc

@RajivKurian
Copy link
Author

RajivKurian commented Dec 6, 2022

Thanks, I tried the repo_mapping solution for both grpc repo_mapping = {"@boringssl": "@openssl"} (created my own openssl project in workspace first) and repo_mapping = {"@openssl": "@boringssl"} (created by own boringssl project in workspace first) for boost and neither seemed to do the job. I am talking to the Bazel folks on slack to see why that did not work.
Here was what I tried when I tried boost to use boringssl:

http_archive(
    name = "boringssl",
    # Use github mirror instead of https://boringssl.googlesource.com/boringssl
    # to obtain a boringssl archive with consistent sha256
    sha256 = "534fa658bd845fd974b50b10f444d392dfd0d93768c4a51b61263fd37d851c40",
    strip_prefix = "boringssl-b9232f9e27e5668bc0414879dcdedb2a59ea75f2",
    urls = [
        "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/boringssl/archive/b9232f9e27e5668bc0414879dcdedb2a59ea75f2.tar.gz",
        "https://github.com/google/boringssl/archive/b9232f9e27e5668bc0414879dcdedb2a59ea75f2.tar.gz",
    ],
)

# Boost
http_archive(
    name = "com_github_nelhage_rules_boost",
    url = "https://github.com/nelhage/rules_boost/archive/2abec7db70327bc0b4bbdb33c90ff096d0c95872.tar.gz",
    strip_prefix = "rules_boost-2abec7db70327bc0b4bbdb33c90ff096d0c95872",
    sha256 = "37a2568bbda4a61dc2467ad226a1dae93ee9496646217e141003ce9ec5aeb9ce",
    # Boost asio-ssl uses boringssl but calls it openssl.
    # This leads to ODR issues since boringssl is used in GRPC too.
    repo_mapping = {"@openssl": "@boringssl"}
)
load("@com_github_nelhage_rules_boost//:boost/boost.bzl", "boost_deps")
boost_deps()

But then it looked like boost was still downloading its own openssl and I couldn't get rid of the ODR issue.
In the mean time I just created a patch on top of rules_boost (when importing it via http_archive) to use boringssl as the name of the ssl project instead of openssl and that seems to do the trick.

@cpsauer
Copy link
Collaborator

cpsauer commented Dec 6, 2022

Please do report back what you learn! I'd have recommended those solutions, too.

@cpsauer
Copy link
Collaborator

cpsauer commented Dec 6, 2022

Thinking more about it, one other thing worth checking is the ordering in WORKSPACE, since I think that'll affect whether or not it'll work.

I'd propose an ordering like:

  1. Manually pull in boringssl, probably as "boringssl", just to be explicit.
  2. Grab rules_boost with a repo_mapping = {"@openssl": "@boringssl"}, which should make it use the boringssl already pulled in as openssl.
  3. Grab grpc, which should then not import boringssl since it already exists.

But the last two could be switched--or you could use the version of boringssl pulled in by one of the two libraries. The important part is that the http_archive with the repo_mapping be listed later than the other.

@RajivKurian
Copy link
Author

RajivKurian commented Dec 6, 2022

I had the exact ordering that you suggested i.e. bring in boringssl explicitly, then grab rules_boost with a repo_mapping, then grab grpc as is without any repo_mapping. What I see is that boringssl is bought in through my explicit import. Then grpc ends up reusing that boringssl, but rules_boost still got its own boringssl named openssl. Almost like the repo_mapping did nothing.

@cpsauer
Copy link
Collaborator

cpsauer commented Dec 7, 2022

👍🏻 Figured I'd raise it just in case; delighted to hear you were ahead of me. Curious!

@cpsauer
Copy link
Collaborator

cpsauer commented Dec 23, 2022

@RajivKurian, any updates? I know I'm curious what you learned solving this :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants