@@ -19,6 +19,7 @@ load("@rules_cc//cc:cc_library.bzl", "cc_library")
1919load ("@rules_cc//cc:cc_test.bzl" , "cc_test" )
2020load ("@rules_cc//cc/common:cc_common.bzl" , "cc_common" )
2121load ("@rules_cc//cc/common:cc_info.bzl" , "CcInfo" )
22+ load ("@bazel_skylib//rules:common_settings.bzl" , "BuildSettingInfo" )
2223load ("//sandboxed_api/bazel:build_defs.bzl" , "sapi_platform_copts" )
2324load ("//sandboxed_api/bazel:embed_data.bzl" , "sapi_cc_embed_data" )
2425load (
@@ -506,17 +507,20 @@ def sapi_library(
506507
507508def 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+
645690def 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+ )
0 commit comments