support controlling trait methods

This commit is contained in:
Jianfeng Jiang 2023-03-03 10:14:27 +08:00 committed by Tate, Hongliang Tian
parent cd2d516be1
commit 99e6ffb7f8
10 changed files with 190 additions and 39 deletions

45
src/Cargo.lock generated
View File

@ -60,21 +60,6 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bootloader"
version = "0.10.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24e13520aa8580a2850fc9f5390dc6753f1062fb66f90e5a61bd5c72b55df731"
[[package]]
name = "bootloader-locator"
version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aaaa9db3339d32c2622f2e5d0731eb82a468d3439797c9d4fe426744fe2bd551"
dependencies = [
"json",
]
[[package]]
name = "buddy_system_allocator"
version = "0.6.0"
@ -213,10 +198,10 @@ dependencies = [
name = "jinux"
version = "0.1.0"
dependencies = [
"bootloader",
"component",
"jinux-frame",
"jinux-std",
"limine",
]
[[package]]
@ -240,8 +225,6 @@ name = "jinux-boot"
version = "0.1.0"
dependencies = [
"anyhow",
"bootloader-locator",
"locate-cargo-manifest",
"runner-utils",
]
@ -251,11 +234,11 @@ version = "0.1.0"
dependencies = [
"acpi",
"bitflags",
"bootloader",
"buddy_system_allocator",
"font8x8",
"intrusive-collections",
"lazy_static",
"limine",
"linked_list_allocator",
"log",
"pod",
@ -375,6 +358,15 @@ version = "0.2.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
[[package]]
name = "limine"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e9d0c951056ac044f0e6b09448b9d702f8fb1001db89cffd2bc467bd1c25307"
dependencies = [
"uuid",
]
[[package]]
name = "linked_list_allocator"
version = "0.9.1"
@ -384,15 +376,6 @@ dependencies = [
"spinning_top",
]
[[package]]
name = "locate-cargo-manifest"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db985b63431fe09e8d71f50aeceffcc31e720cb86be8dad2f38d084c5a328466"
dependencies = [
"json",
]
[[package]]
name = "lock_api"
version = "0.4.9"
@ -660,6 +643,12 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372"
[[package]]
name = "uuid"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
[[package]]
name = "version_check"
version = "0.9.4"

View File

@ -20,7 +20,8 @@ use rustc_middle::mir::{
Constant, InlineAsmOperand, LocalDecl, Operand, Rvalue, Statement, StatementKind, Terminator,
TerminatorKind,
};
use rustc_middle::ty::{InstanceDef, TyCtxt, TyKind, WithOptConstParam};
use rustc_middle::query::Key;
use rustc_middle::ty::{ImplSubject, InstanceDef, TyCtxt, TyKind, WithOptConstParam};
use rustc_span::def_id::{DefId, LocalDefId, LOCAL_CRATE};
use rustc_span::Span;
@ -221,7 +222,7 @@ fn def_path_if_invalid_access(def_id: DefId, tcx: TyCtxt<'_>) -> Option<String>
fn def_path_if_not_in_whitelist(def_id: DefId, tcx: TyCtxt<'_>) -> Option<String> {
let crate_symbol = tcx.crate_name(LOCAL_CRATE);
let crate_name = crate_symbol.as_str();
let def_path_str = def_path_str(def_id, tcx);
let def_path_str = def_path_for_def_id(tcx, def_id);
if conf::CONFIG
.get()
.unwrap()
@ -233,15 +234,6 @@ fn def_path_if_not_in_whitelist(def_id: DefId, tcx: TyCtxt<'_>) -> Option<String
}
}
fn def_path_str(def_id: DefId, tcx: TyCtxt<'_>) -> String {
// The def_path_str of TyCtxt will panic the compiler,
// while the def_path_debug_str contains noisy info.
// This function is like def_path_debug_str.
let def_path = tcx.def_path(def_id);
let crate_name = tcx.crate_name(def_path.krate);
format!("{}{}", crate_name, def_path.to_string_no_crate_verbose())
}
/// if the def_id has attribute component_access_control::controlled, return true, else return false
fn contains_controlled_attr(def_id: DefId, tcx: TyCtxt<'_>) -> bool {
for attr in tcx.get_attrs_unchecked(def_id) {
@ -262,6 +254,34 @@ fn contains_controlled_attr(def_id: DefId, tcx: TyCtxt<'_>) -> bool {
false
}
fn def_path_for_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> String {
match tcx.impl_of_method(def_id) {
None => common_def_path_str(tcx, def_id),
Some(impl_def_id) => def_path_str_for_impl(tcx, def_id, impl_def_id),
}
}
/// def path for function, type, static variables and trait methods
fn common_def_path_str(tcx: TyCtxt<'_>, def_id: DefId) -> String {
// This function is like def_path_debug_str without noisy info
let def_path = tcx.def_path(def_id);
let crate_name = tcx.crate_name(def_path.krate);
format!("{}{}", crate_name, def_path.to_string_no_crate_verbose())
}
/// def path for impl, if the impl is not for trait.
fn def_path_str_for_impl(tcx: TyCtxt<'_>, def_id: DefId, impl_def_id: DefId) -> String {
let item_name = tcx.item_name(def_id).to_string();
let impl_subject = tcx.impl_subject(impl_def_id);
if let ImplSubject::Inherent(impl_ty) = impl_subject {
let impl_ty_def_id = impl_ty.ty_adt_id().expect("Method should impl an adt type");
let impl_ty_name = common_def_path_str(tcx, impl_ty_def_id);
return format!("{impl_ty_name}::{item_name}");
}
// impl trait goes here, which is impossible
unreachable!()
}
fn emit_note(tcx: TyCtxt<'_>, span: Span, crate_name: &str, def_paths: Vec<String>) {
if def_paths.len() > 0 {
let sess = tcx.sess;

View File

@ -1,2 +1,3 @@
[toolchain]
channel = "nightly-2023-02-05"
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]

View File

@ -0,0 +1,28 @@
//! This test checks that if cargo-component can control method and trait method
#![feature(once_cell)]
use std::path::PathBuf;
use test_utils::{cargo_clean, cargo_component, clean_after_test};
mod test_utils;
#[test]
fn trait_method() {
let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let target_dir = root_dir.join("target").join("trait_method_test");
let cwd = root_dir.join("tests").join("trait_method_test");
let output = cargo_clean(&cwd, &target_dir);
assert!(output.status.success());
let output = cargo_component(&cwd, &target_dir);
let stderr = String::from_utf8_lossy(&output.stderr);
println!("stderr: {stderr}");
assert!(output.status.success());
assert!(stderr.contains("access controlled entry point is disallowed"));
assert!(stderr.contains("access foo::Foo::method in bar"));
assert!(stderr.contains("access foo::FooTrait::trait_associate_fn in bar"));
assert!(stderr.contains("access foo::FooTrait::trait_method in bar"));
clean_after_test(&cwd);
}

View File

@ -0,0 +1,2 @@
[workspace]
members = ["foo", "bar"]

View File

@ -0,0 +1,19 @@
[components]
foo = { name = "foo" }
bar = { name = "bar" }
[whitelist]
[whitelist.foo.FooTrait.trait_method]
bar = false
[whitelist.foo.FooTrait.trait_associate_fn]
bar = false
[whitelist.foo.Foo.method]
bar = false
[whitelist.foo.ObjectSafeTrait.get]
bar = true
[whitelist.foo.Foo.associate_fn]
bar = true

View File

@ -0,0 +1,9 @@
[package]
name = "bar"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
foo = {path = "../foo"}

View File

@ -0,0 +1,26 @@
use foo::{ObjectSafeTrait, Foo, FooTrait};
pub fn method() {
let foo_struct = Foo::associate_fn();
let val = foo_struct.method();
println!("val = {}", val);
}
pub fn trait_method() {
Foo::trait_associate_fn();
let foo_struct = Foo::associate_fn();
foo_struct.trait_method();
}
pub fn dyn_trait() {
let foo_as_dyn = Box::new(Foo::associate_fn()) as Box<dyn ObjectSafeTrait>;
foo_as_dyn.get();
}
pub fn opaque_type(object: impl ObjectSafeTrait) {
object.get();
}
pub fn generic<T: ObjectSafeTrait>(object: T) {
object.get();
}

View File

@ -0,0 +1,9 @@
[package]
name = "foo"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
controlled = {path = "../../../../controlled"}

View File

@ -0,0 +1,48 @@
#![feature(register_tool)]
#![register_tool(component_access_control)]
#[macro_use]
extern crate controlled;
pub struct Foo;
impl Foo {
#[controlled]
pub fn associate_fn() -> Self {
todo!()
}
#[controlled]
pub fn method(&self) -> usize {
todo!()
}
}
pub trait FooTrait {
#[controlled]
fn trait_associate_fn();
#[controlled]
fn trait_method(&self) -> usize;
}
impl FooTrait for Foo {
fn trait_associate_fn() {
todo!()
}
fn trait_method(&self) -> usize {
todo!()
}
}
pub trait ObjectSafeTrait {
#[controlled]
fn get(&self) -> usize;
}
impl ObjectSafeTrait for Foo {
fn get(&self) -> usize {
todo!()
}
}