Skip to content

Commit 66b79ca

Browse files
dvyukovcopybara-github
authored andcommitted
Make cc_sandboxed_library a cc_library replacement
PiperOrigin-RevId: 890283751 Change-Id: Ie77eea7aa00e5263ba3b34aa0f11e78d9f09c2d0
1 parent 9f31652 commit 66b79ca

File tree

3 files changed

+155
-37
lines changed

3 files changed

+155
-37
lines changed

sandboxed_api/bazel/BUILD

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
# limitations under the License.
1414

1515
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
16+
load(
17+
"@bazel_skylib//rules:common_settings.bzl",
18+
"string_list_setting",
19+
)
1620

1721
licenses(["notice"])
1822

@@ -60,6 +64,7 @@ bzl_library(
6064
":build_defs_bzl",
6165
":embed_data_bzl",
6266
":proto_bzl",
67+
"@bazel_skylib//rules:common_settings",
6368
"@bazel_tools//tools/cpp:toolchain_utils.bzl",
6469
"@rules_cc//cc:core_rules",
6570
"@rules_cc//cc/common",
@@ -71,3 +76,13 @@ bzl_library(
7176
srcs = ["llvm_config.bzl"],
7277
visibility = ["//visibility:private"],
7378
)
79+
80+
string_list_setting(
81+
name = "lib_sandboxing_enable",
82+
build_setting_default = [],
83+
)
84+
85+
string_list_setting(
86+
name = "lib_sandboxing_disable",
87+
build_setting_default = [],
88+
)

sandboxed_api/bazel/sapi.bzl

Lines changed: 126 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ load("@rules_cc//cc:cc_library.bzl", "cc_library")
1919
load("@rules_cc//cc:cc_test.bzl", "cc_test")
2020
load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
2121
load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
22+
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
2223
load("//sandboxed_api/bazel:build_defs.bzl", "sapi_platform_copts")
2324
load("//sandboxed_api/bazel:embed_data.bzl", "sapi_cc_embed_data")
2425
load(
@@ -506,17 +507,20 @@ def sapi_library(
506507

507508
def cc_sandboxed_library(
508509
name,
509-
lib,
510-
srcs = [],
510+
annotations = [],
511+
default_sandboxed = True,
511512
tags = [],
512513
host_deps = [],
513514
sandboxee_deps = [],
514515
visibility = None,
515-
compatible_with = None):
516-
"""Creates a sandboxed drop-in replacement cc_library.
516+
compatible_with = None,
517+
**kwargs):
518+
"""Creates a drop-in replacement cc_library that may be sandboxed.
517519
518520
NOTE: this functionality is experimental and may change in the future.
519521
522+
The resulting library may or may not be sandboxed depending on the default_sandboxed attribute.
523+
520524
The resulting library can be used instead of the original cc_library
521525
as dependency for other targets. The behavior is supposed to be identical
522526
to the original library, except that the library is sandboxed with a single
@@ -529,16 +533,18 @@ def cc_sandboxed_library(
529533
530534
Args:
531535
name: Name of the target
532-
lib: Label of the cc_library target to sandbox
533-
srcs: List of source files to tune syscall policy, and interface bridging.
536+
annotations: List of source files to tune syscall policy, and interface bridging.
537+
default_sandboxed: Whether the library is sandboxed by default.
534538
tags: Same as cc_library.tags
535539
host_deps: Additional dependencies for the host code.
536540
sandboxee_deps: Additional dependencies for the sandboxee code.
537541
visibility: Same as cc_library.visibility
538542
compatible_with: Same as cc_library.compatible_with
543+
**kwargs: Same as for cc_library.
539544
"""
540545

541546
# Implementation outline:
547+
# 0. Create unsandboxed cc_library with an internal name.
542548
# 1. Run clang generator tool in sandboxed library mode.
543549
# In this mode it takes all functions declared in the library public headers,
544550
# and generates 3 files:
@@ -565,16 +571,23 @@ def cc_sandboxed_library(
565571
# Using the compilation context of the original library ensures that during
566572
# compilation the replacement library "looks" exactly as the original library
567573
# (this includes any use of defines/includes and any other cc_library attributes).
574+
# 7. Finally, the rule that actually uses the name as name selects between
575+
# the original library and the sandboxed library using the default_sandboxed attribute.
568576

569577
# Unique prefix for things generated by sapi_library (e.g. FooSandbox class name).
570578
# TODO(dvyukov): add hash/flattening of the full library /path:name, just the name is not
571579
# necessarily globally unique.
572580
wrapper_name = "Sapi" + name
573581
common = _common_kwargs(tags, visibility, compatible_with)
574582

583+
cc_library(
584+
name = "_unsandboxed_" + name,
585+
**(common | kwargs)
586+
)
587+
575588
_sandboxed_library_gen(
576589
name = "_sandboxed_library_gen_" + name,
577-
lib = lib,
590+
lib = "_unsandboxed_" + name,
578591
lib_name = wrapper_name,
579592
sandboxee_hdr_out = name + ".sapi.sandboxee.h.unformatted",
580593
sandboxee_src_out = name + ".sapi.sandboxee.cc.unformatted",
@@ -583,7 +596,7 @@ def cc_sandboxed_library(
583596
sandboxee_deps = sandboxee_deps,
584597
host_src_out = name + ".sapi.host.cc.unformatted",
585598
sapi_hdr = native.package_name() + "/_sapi_" + name + ".sapi.h",
586-
srcs = srcs,
599+
srcs = annotations,
587600
**common
588601
)
589602

@@ -601,7 +614,7 @@ def cc_sandboxed_library(
601614
# that force linking of the sandboxee library. In global mode, it won't be linked.
602615
alwayslink = 1,
603616
deps = [
604-
lib,
617+
"_unsandboxed_" + name,
605618
"//sandboxed_api:lenval_core",
606619
] + sandboxee_deps,
607620
**common
@@ -624,12 +637,20 @@ def cc_sandboxed_library(
624637
)
625638

626639
_sandboxed_library(
627-
name = name,
628-
lib = lib,
640+
name = "_sandboxed_" + name,
641+
lib = "_unsandboxed_" + name,
629642
sapi = ":_sapi_" + name,
630643
**common
631644
)
632645

646+
_sandboxed_library_selector(
647+
name = name,
648+
unsandboxed_lib = "_unsandboxed_" + name,
649+
sandboxed_lib = "_sandboxed_" + name,
650+
default_sandboxed = default_sandboxed,
651+
**common
652+
)
653+
633654
_sandboxed_library = rule(
634655
provides = [CcInfo],
635656
attrs = {
@@ -642,38 +663,68 @@ _sandboxed_library = rule(
642663
)],
643664
)
644665

666+
def _sandboxed_library_selector_impl(ctx):
667+
# TODO: disable sandboxing in non //tools/cc_target_os:linux-google[-arm] builds,
668+
# host builds, and other non-interesting cases.
669+
enabled = ctx.attr.default_sandboxed
670+
if str(ctx.label) in ctx.attr._bin_sandboxing_enable[BuildSettingInfo].value:
671+
enabled = True
672+
if str(ctx.label) in ctx.attr._bin_sandboxing_disable[BuildSettingInfo].value:
673+
enabled = False
674+
if enabled:
675+
return ctx.attr.sandboxed_lib[CcInfo]
676+
return ctx.attr.unsandboxed_lib[CcInfo]
677+
678+
_sandboxed_library_selector = rule(
679+
implementation = _sandboxed_library_selector_impl,
680+
provides = [CcInfo],
681+
attrs = {
682+
"unsandboxed_lib": attr.label(providers = [CcInfo]),
683+
"sandboxed_lib": attr.label(providers = [CcInfo]),
684+
"default_sandboxed": attr.bool(),
685+
"_bin_sandboxing_enable": attr.label(default = "//sandboxed_api/bazel:lib_sandboxing_enable"),
686+
"_bin_sandboxing_disable": attr.label(default = "//sandboxed_api/bazel:lib_sandboxing_disable"),
687+
},
688+
)
689+
645690
def cc_sandboxed_library_test(
646691
name,
647692
lib,
648-
sandboxed_lib,
649693
deps = [],
650694
**kwargs):
651695
"""Creates a pair of sandboxed/unsandboxed cc_test's for cc_sandboxed_library.
652696
653697
NOTE: this functionality is experimental and may change in the future.
654698
655699
This rule is supposed to be a replacement for any cc_test's for a library
656-
that is used with cc_sandboxed_library. It creates a pair of cc_test's
700+
that is converted to cc_sandboxed_library. It creates a pair of cc_test's
657701
that test both sandboxed and unsandboxed versions of the library.
658702
659703
Args:
660704
name: Name of the target
661-
lib: Label of the normal unsandboxed cc_library target
662-
sandboxed_lib: Label of the cc_sandboxed_library target for the lib
663-
deps: Same as cc_library.deps, must not include lib/sandboxed_lib
705+
lib: Label of the cc_sandboxed_library target
706+
deps: Same as cc_library.deps, must not include the lib
664707
**kwargs: Passed to resulting cc_test's
665708
"""
666709

667710
cc_test(
668-
name = name + "_unsandboxed",
711+
name = "_internal_" + name,
669712
deps = deps + [lib],
670713
**kwargs
671714
)
672715

673-
cc_test(
716+
_transitioned_test(
717+
name = name + "_unsandboxed",
718+
binary = ":_internal_" + name,
719+
lib_sandboxing_enable = [],
720+
lib_sandboxing_disable = [str(native.package_relative_label(lib))],
721+
)
722+
723+
_transitioned_test(
674724
name = name + "_sandboxed",
675-
deps = deps + [sandboxed_lib],
676-
**kwargs
725+
binary = ":_internal_" + name,
726+
lib_sandboxing_enable = [str(native.package_relative_label(lib))],
727+
lib_sandboxing_disable = [],
677728
)
678729

679730
native.test_suite(
@@ -777,3 +828,58 @@ sandboxed_library_gen_errors = rule(
777828
"errors": attr.output(),
778829
},
779830
)
831+
832+
def _binary_transition_impl(_, attr):
833+
return {
834+
"//sandboxed_api/bazel:lib_sandboxing_enable": attr.lib_sandboxing_enable,
835+
"//sandboxed_api/bazel:lib_sandboxing_disable": attr.lib_sandboxing_disable,
836+
}
837+
838+
_binary_transition = transition(
839+
implementation = _binary_transition_impl,
840+
inputs = [],
841+
outputs = [
842+
"//sandboxed_api/bazel:lib_sandboxing_enable",
843+
"//sandboxed_api/bazel:lib_sandboxing_disable",
844+
],
845+
)
846+
847+
def _transitioned_binary_impl(ctx):
848+
default_info = ctx.attr.binary[0][DefaultInfo]
849+
files = default_info.files.to_list()
850+
orig_executable = files[0]
851+
outfile = ctx.actions.declare_file(ctx.label.name)
852+
ctx.actions.run_shell(
853+
inputs = [orig_executable],
854+
outputs = [outfile],
855+
command = "cp %s %s" % (orig_executable.path, outfile.path),
856+
mnemonic = "CcSandboxedLibraryCopyBinary",
857+
)
858+
data_runfiles = []
859+
for file in default_info.data_runfiles.files.to_list():
860+
if file == orig_executable:
861+
file = outfile
862+
data_runfiles = data_runfiles + [file]
863+
default_runfiles = []
864+
for file in default_info.default_runfiles.files.to_list():
865+
if file == orig_executable:
866+
file = outfile
867+
default_runfiles = default_runfiles + [file]
868+
return [
869+
DefaultInfo(
870+
executable = outfile,
871+
data_runfiles = ctx.runfiles(files = data_runfiles),
872+
default_runfiles = ctx.runfiles(files = default_runfiles),
873+
),
874+
]
875+
876+
_transitioned_test = rule(
877+
implementation = _transitioned_binary_impl,
878+
attrs = {
879+
"lib_sandboxing_enable": attr.string_list(),
880+
"lib_sandboxing_disable": attr.string_list(),
881+
"binary": attr.label(cfg = _binary_transition),
882+
},
883+
test = True,
884+
executable = True,
885+
)

sandboxed_api/tests/testcases/BUILD

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,47 +12,44 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
load("@rules_cc//cc:cc_library.bzl", "cc_library")
1615
load("//sandboxed_api/bazel:sapi.bzl", "cc_sandboxed_library", "cc_sandboxed_library_test")
1716

1817
package(default_visibility = ["//visibility:private"])
1918

2019
licenses(["notice"])
2120

22-
cc_library(
23-
name = "replaced_library",
21+
cc_sandboxed_library(
22+
name = "replacement_library",
2423
srcs = ["replaced_library.cc"],
2524
hdrs = ["replaced_library.h"],
25+
annotations = ["lwbox_sandbox.cc"],
2626
deps = [
2727
"//sandboxed_api:annotations",
2828
"@abseil-cpp//absl/strings:string_view",
2929
],
3030
)
3131

32-
cc_sandboxed_library(
33-
name = "replacement_library",
34-
srcs = ["lwbox_sandbox.cc"],
35-
lib = ":replaced_library",
36-
)
37-
3832
cc_sandboxed_library(
3933
name = "replacement_library2",
40-
srcs = ["lwbox_ignore.cc"],
41-
lib = ":replaced_library",
34+
srcs = ["replaced_library.cc"],
35+
hdrs = ["replaced_library.h"],
36+
annotations = ["lwbox_ignore.cc"],
37+
deps = [
38+
"//sandboxed_api:annotations",
39+
"@abseil-cpp//absl/strings:string_view",
40+
],
4241
)
4342

4443
cc_sandboxed_library_test(
45-
name = "replaced_test",
44+
name = "replacement_test",
4645
srcs = ["replaced_library_test.cc"],
47-
lib = ":replaced_library",
48-
sandboxed_lib = ":replacement_library",
46+
lib = ":replacement_library",
4947
deps = ["@googletest//:gtest_main"],
5048
)
5149

5250
cc_sandboxed_library_test(
53-
name = "replaced2_test",
51+
name = "replacement2_test",
5452
srcs = ["replaced_library_test.cc"],
55-
lib = ":replaced_library",
56-
sandboxed_lib = ":replacement_library2",
53+
lib = ":replacement_library2",
5754
deps = ["@googletest//:gtest_main"],
5855
)

0 commit comments

Comments
 (0)