Compare commits
	
		
			51 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 54ea7d6cfd | |||
| cfed7004a5 | |||
| 529332dc94 | |||
| b5f6d5f9b9 | |||
| 
						 | 
					ffe6a750b0 | ||
| 
						 | 
					f8e8d400d3 | ||
| 
						 | 
					060d2ec1b3 | ||
| 
						 | 
					3b90df67dc | ||
| 
						 | 
					d3e84d2269 | ||
| 
						 | 
					501abda5ca | ||
| 
						 | 
					5b704984e3 | ||
| 
						 | 
					4027258ec5 | ||
| 
						 | 
					0c1c0621e6 | ||
| 
						 | 
					f58652da96 | ||
| 
						 | 
					ded96d761d | ||
| 
						 | 
					49cc99418e | ||
| 
						 | 
					ca930d19b2 | ||
| 
						 | 
					6930e606ef | ||
| 
						 | 
					d7131a1a5b | ||
| 
						 | 
					32b94f1dd9 | ||
| 
						 | 
					addb5c61f4 | ||
| 
						 | 
					d416c8b1d1 | ||
| 
						 | 
					a99c63e21d | ||
| 
						 | 
					1e8c5a6d0a | ||
| 
						 | 
					879cfa58a5 | ||
| 
						 | 
					c2db186854 | ||
| 
						 | 
					32c7cc44f1 | ||
| 
						 | 
					91a0f126bf | ||
| 
						 | 
					9b6cb4d27f | ||
| 
						 | 
					d4de8f59e6 | ||
| 
						 | 
					11d0746f96 | ||
| 
						 | 
					4c7274efbe | ||
| 
						 | 
					37ce7b5432 | ||
| 
						 | 
					1de75ad218 | ||
| 
						 | 
					75b5f84ec6 | ||
| 
						 | 
					5d3799fcb8 | ||
| 
						 | 
					e96a1348e5 | ||
| 
						 | 
					219fdd4e26 | ||
| 
						 | 
					d6741c0096 | ||
| 
						 | 
					d27f0d5cd0 | ||
| 
						 | 
					976135b79c | ||
| 
						 | 
					1bee38f50a | ||
| 
						 | 
					9ed1778866 | ||
| 
						 | 
					707c4669d5 | ||
| 
						 | 
					b1039a6054 | ||
| 
						 | 
					45bf6902f5 | ||
| 
						 | 
					775b3e127c | ||
| 
						 | 
					95eac28425 | ||
| 
						 | 
					b93b8412dc | ||
| 
						 | 
					a320a77f36 | ||
| 
						 | 
					b749b7db3b | 
							
								
								
									
										3
									
								
								.github/workflows/demo_test.yml
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										3
									
								
								.github/workflows/demo_test.yml
									
									
									
									
										vendored
									
									
								
							@ -82,7 +82,8 @@ jobs:
 | 
			
		||||
      run: docker exec ${{ github.job }} bash -c "cd /root/occlum/tools/toolchains/golang && ./build.sh go1.18.4_for_occlum && cd /root/occlum/demos/golang/go_sqlite/ && SGX_MODE=SIM ./run_go_sqlite_demo.sh"
 | 
			
		||||
 | 
			
		||||
    - name: Go Server set up and run
 | 
			
		||||
      run: docker exec ${{ github.job }} bash -c "cd /root/occlum/demos/golang/web_server && ./build.sh;
 | 
			
		||||
      run: docker exec ${{ github.job }} bash -c "cd /root/occlum/demos/golang/web_server && occlum-go mod init web_server && occlum-go get -u -v github.com/gin-gonic/gin;
 | 
			
		||||
            occlum-go build -o web_server ./web_server.go;
 | 
			
		||||
            SGX_MODE=SIM ./run_golang_on_occlum.sh" &
 | 
			
		||||
 | 
			
		||||
    - name: Set up Golang grpc pingpong test
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								.github/workflows/hw_mode_test.yml
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										3
									
								
								.github/workflows/hw_mode_test.yml
									
									
									
									
										vendored
									
									
								
							@ -142,7 +142,8 @@ jobs:
 | 
			
		||||
 | 
			
		||||
    - name: Go server set up and run
 | 
			
		||||
      run: docker exec ${{ env.CONTAINER_NAME }} bash -c "export GO111MODULE=on;
 | 
			
		||||
            cd /root/occlum/demos/golang/web_server && ./build.sh;
 | 
			
		||||
            cd /root/occlum/demos/golang/web_server && occlum-go mod init web_server && occlum-go get -u -v github.com/gin-gonic/gin;
 | 
			
		||||
            occlum-go build -o web_server ./web_server.go;
 | 
			
		||||
            ./run_golang_on_occlum.sh" &
 | 
			
		||||
 | 
			
		||||
    - name: Set up Golang grpc pingpong test
 | 
			
		||||
 | 
			
		||||
@ -54,9 +54,9 @@ fi
 | 
			
		||||
if ! type "protoc-gen-go-grpc" > /dev/null 2>&1; then
 | 
			
		||||
	if [[ $GOVERSION != 'go1.16.3' ]];then
 | 
			
		||||
	occlum-go get google.golang.org/grpc/cmd/protoc-gen-go-grpc
 | 
			
		||||
	occlum-go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3.0
 | 
			
		||||
	occlum-go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
 | 
			
		||||
	else
 | 
			
		||||
	occlum-go get google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3.0
 | 
			
		||||
	occlum-go get google.golang.org/grpc/cmd/protoc-gen-go-grpc
 | 
			
		||||
	fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,10 @@ occlum init
 | 
			
		||||
new_json="$(jq '.resource_limits.user_space_size = "1MB" |
 | 
			
		||||
	.resource_limits.user_space_max_size = "800MB" |
 | 
			
		||||
	.resource_limits.kernel_space_heap_size="1MB" |
 | 
			
		||||
	.resource_limits.kernel_space_heap_max_size="80MB"  ' Occlum.json)" && \
 | 
			
		||||
	.resource_limits.kernel_space_heap_max_size="40MB" |
 | 
			
		||||
	.resource_limits.kernel_space_stack_size="1MB" |
 | 
			
		||||
	.process.default_stack_size = "1MB" |
 | 
			
		||||
	.process.default_heap_size = "20MB" ' Occlum.json)" && \
 | 
			
		||||
echo "${new_json}" > Occlum.json
 | 
			
		||||
 | 
			
		||||
# 2. Copy program into Occlum Workspace and build
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,10 @@ occlum init
 | 
			
		||||
new_json="$(jq '.resource_limits.user_space_size = "1MB" |
 | 
			
		||||
	.resource_limits.user_space_max_size = "800MB" |
 | 
			
		||||
	.resource_limits.kernel_space_heap_size="1MB" |
 | 
			
		||||
	.resource_limits.kernel_space_heap_max_size="80MB" ' Occlum.json)" && \
 | 
			
		||||
	.resource_limits.kernel_space_heap_max_size="40MB" |
 | 
			
		||||
	.resource_limits.kernel_space_stack_size="1MB" |
 | 
			
		||||
	.process.default_stack_size = "1MB" |
 | 
			
		||||
	.process.default_heap_size = "20MB" ' Occlum.json)" && \
 | 
			
		||||
echo "${new_json}" > Occlum.json
 | 
			
		||||
 | 
			
		||||
# 2. Copy program into Occlum Workspace and build
 | 
			
		||||
 | 
			
		||||
@ -2,18 +2,24 @@
 | 
			
		||||
 | 
			
		||||
This project demonstrates how Occlum enables [Golang](https://golang.org) programs running in SGX enclaves, the demo program is a HTTP web server based on a widely used web framework([Gin](https://gin-gonic.com)) for Go.
 | 
			
		||||
 | 
			
		||||
Step 1: Install Gin and build Golang web server with `occlum-go`
 | 
			
		||||
Step 1: Install Gin with `occlum-go`, it may take a few minutes
 | 
			
		||||
```
 | 
			
		||||
./build.sh
 | 
			
		||||
occlum-go mod init web_server && \
 | 
			
		||||
occlum-go get -u -v github.com/gin-gonic/gin
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Step 2: You can run the web server demo on Occlum via
 | 
			
		||||
Step 2: Build the Golang web server using the Occlum Golang toolchain(i.e., `occlum-go`)
 | 
			
		||||
```
 | 
			
		||||
occlum-go build -o web_server ./web_server.go
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Step 3: You can run the web server demo on Occlum via
 | 
			
		||||
```
 | 
			
		||||
./run_golang_on_occlum.sh
 | 
			
		||||
```
 | 
			
		||||
The HTTP web server should now start to listen on port 8090 and serve HTTP requests.
 | 
			
		||||
 | 
			
		||||
Step 3: To check whether the HTTP server works, run
 | 
			
		||||
Step 4: To check whether the HTTP server works, run
 | 
			
		||||
```
 | 
			
		||||
curl http://127.0.0.1:8090/ping
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
@ -1,10 +0,0 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
rm -f go.mod
 | 
			
		||||
occlum-go mod init web_server
 | 
			
		||||
occlum-go mod tidy
 | 
			
		||||
occlum-go get -u -v github.com/gin-gonic/gin
 | 
			
		||||
occlum-go get -u -v golang.org/x/crypto@v0.23.0
 | 
			
		||||
 | 
			
		||||
occlum-go build -o web_server ./web_server.go
 | 
			
		||||
@ -21,7 +21,19 @@ sed -i "186 i \    elif sysstr == 'occlum':\n        return True" $CORE_PY
 | 
			
		||||
sed -ie "37,64d" $IMAGE_PY
 | 
			
		||||
sed -i "37 i \try:\n    import cv2\nexcept ImportError:\n     cv2 = None" $IMAGE_PY
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Download the dataset
 | 
			
		||||
git clone https://github.com/fgnt/mnist.git
 | 
			
		||||
DATASET=$script_dir/mnist
 | 
			
		||||
 | 
			
		||||
[ -d $DATASET ] && exit 0
 | 
			
		||||
 | 
			
		||||
TRAIN_IMAGE=train-images-idx3-ubyte.gz
 | 
			
		||||
TRAIN_LABEL=train-labels-idx1-ubyte.gz
 | 
			
		||||
TEST_IMAGE=t10k-images-idx3-ubyte.gz
 | 
			
		||||
TEST_LABEL=t10k-labels-idx1-ubyte.gz
 | 
			
		||||
URL=http://yann.lecun.com/exdb/mnist
 | 
			
		||||
 | 
			
		||||
mkdir $DATASET
 | 
			
		||||
wget $URL/$TRAIN_IMAGE -P $DATASET
 | 
			
		||||
wget $URL/$TRAIN_LABEL -P $DATASET
 | 
			
		||||
wget $URL/$TEST_IMAGE  -P $DATASET
 | 
			
		||||
wget $URL/$TEST_LABEL  -P $DATASET
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}"  )" >/dev/null 2>&1 && pwd )"
 | 
			
		||||
# 2. Install python and dependencies to specified position
 | 
			
		||||
[ -f Miniconda3-latest-Linux-x86_64.sh ] || wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
 | 
			
		||||
[ -d miniconda ] || bash ./Miniconda3-latest-Linux-x86_64.sh -b -p $script_dir/miniconda
 | 
			
		||||
$script_dir/miniconda/bin/conda create --prefix $script_dir/python-occlum -y python=3.9.11 flask=2.2.2 flask-restful=0.3.9 jinja2=3.1.2  werkzeug=2.3
 | 
			
		||||
$script_dir/miniconda/bin/conda create --prefix $script_dir/python-occlum -y python=3.9.11 flask=2.2.2 flask-restful=0.3.9 jinja2=3.1.2  werkzeug
 | 
			
		||||
 | 
			
		||||
# 3. Remove miniconda and installation scripts
 | 
			
		||||
rm -rf ./Miniconda3-latest-Linux-x86_64.sh $script_dir/miniconda
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								src/libos/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										26
									
								
								src/libos/Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -12,7 +12,6 @@ dependencies = [
 | 
			
		||||
 "bitvec 1.0.1",
 | 
			
		||||
 "ctor",
 | 
			
		||||
 "derive_builder",
 | 
			
		||||
 "errno",
 | 
			
		||||
 "goblin",
 | 
			
		||||
 "intrusive-collections",
 | 
			
		||||
 "itertools",
 | 
			
		||||
@ -39,7 +38,6 @@ dependencies = [
 | 
			
		||||
 "sgx_tstd",
 | 
			
		||||
 "sgx_types",
 | 
			
		||||
 "spin 0.7.1",
 | 
			
		||||
 "vdso-time",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
@ -209,16 +207,6 @@ version = "1.8.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "errno"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "log",
 | 
			
		||||
 "rcore-fs",
 | 
			
		||||
 "serde_json",
 | 
			
		||||
 "sgx_tstd",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "fnv"
 | 
			
		||||
version = "1.0.7"
 | 
			
		||||
@ -821,20 +809,6 @@ dependencies = [
 | 
			
		||||
 "rand",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "vdso-time"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "cfg-if",
 | 
			
		||||
 "errno",
 | 
			
		||||
 "lazy_static",
 | 
			
		||||
 "log",
 | 
			
		||||
 "sgx_libc",
 | 
			
		||||
 "sgx_trts",
 | 
			
		||||
 "sgx_tstd",
 | 
			
		||||
 "sgx_types",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "winapi"
 | 
			
		||||
version = "0.3.9"
 | 
			
		||||
 | 
			
		||||
@ -41,7 +41,7 @@ modular-bitfield = "0.11.2"
 | 
			
		||||
sgx_tstd = { path = "../../deps/rust-sgx-sdk/sgx_tstd" }
 | 
			
		||||
 | 
			
		||||
[features]
 | 
			
		||||
default = ["integrity_only_opt", "sgx_file_cache", "sgx1_exception_sim", "kernel_heap_monitor"]
 | 
			
		||||
default = ["integrity_only_opt", "sgx_file_cache", "sgx1_exception_sim"]
 | 
			
		||||
syscall_timing = []     # Timing for each syscall. But it has cost from more ocall.
 | 
			
		||||
integrity_only_opt = [] # Clear bss only. It should be disabled if checking memory reads.
 | 
			
		||||
sgx_file_cache = []     # Cache SgxFile objects. Invalidation is unimplemented.
 | 
			
		||||
 | 
			
		||||
@ -7,19 +7,12 @@ bitflags! {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn do_fchownat(fs_path: &FsPath, uid: i32, gid: i32, flags: ChownFlags) -> Result<()> {
 | 
			
		||||
pub fn do_fchownat(fs_path: &FsPath, uid: u32, gid: u32, flags: ChownFlags) -> Result<()> {
 | 
			
		||||
    debug!(
 | 
			
		||||
        "fchownat: fs_path: {:?}, uid: {}, gid: {}, flags: {:?}",
 | 
			
		||||
        fs_path, uid, gid, flags
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let uid = to_opt(uid)?;
 | 
			
		||||
    let gid = to_opt(gid)?;
 | 
			
		||||
    // Return early if owner and group are -1
 | 
			
		||||
    if uid.is_none() && gid.is_none() {
 | 
			
		||||
        return Ok(());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let inode = {
 | 
			
		||||
        let path = fs_path.to_abs_path()?;
 | 
			
		||||
        let current = current!();
 | 
			
		||||
@ -31,47 +24,19 @@ pub fn do_fchownat(fs_path: &FsPath, uid: i32, gid: i32, flags: ChownFlags) -> R
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    let mut info = inode.metadata()?;
 | 
			
		||||
    if let Some(uid) = uid {
 | 
			
		||||
        info.uid = uid as usize;
 | 
			
		||||
    }
 | 
			
		||||
    if let Some(gid) = gid {
 | 
			
		||||
        info.gid = gid as usize;
 | 
			
		||||
    }
 | 
			
		||||
    info.uid = uid as usize;
 | 
			
		||||
    info.gid = gid as usize;
 | 
			
		||||
    inode.set_metadata(&info)?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn do_fchown(fd: FileDesc, uid: i32, gid: i32) -> Result<()> {
 | 
			
		||||
pub fn do_fchown(fd: FileDesc, uid: u32, gid: u32) -> Result<()> {
 | 
			
		||||
    debug!("fchown: fd: {}, uid: {}, gid: {}", fd, uid, gid);
 | 
			
		||||
 | 
			
		||||
    let uid = to_opt(uid)?;
 | 
			
		||||
    let gid = to_opt(gid)?;
 | 
			
		||||
    // Return early if owner and group are -1
 | 
			
		||||
    if uid.is_none() && gid.is_none() {
 | 
			
		||||
        return Ok(());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let file_ref = current!().file(fd)?;
 | 
			
		||||
    let mut info = file_ref.metadata()?;
 | 
			
		||||
    if let Some(uid) = uid {
 | 
			
		||||
        info.uid = uid as usize;
 | 
			
		||||
    }
 | 
			
		||||
    if let Some(gid) = gid {
 | 
			
		||||
        info.gid = gid as usize;
 | 
			
		||||
    }
 | 
			
		||||
    info.uid = uid as usize;
 | 
			
		||||
    info.gid = gid as usize;
 | 
			
		||||
    file_ref.set_metadata(&info)?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn to_opt(id: i32) -> Result<Option<u32>> {
 | 
			
		||||
    let id = if id >= 0 {
 | 
			
		||||
        Some(id as u32)
 | 
			
		||||
    } else if id == -1 {
 | 
			
		||||
        // If the ID is specified as -1, then that ID is not changed
 | 
			
		||||
        None
 | 
			
		||||
    } else {
 | 
			
		||||
        return_errno!(EINVAL, "invalid id");
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Ok(id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -36,9 +36,8 @@ impl ProcINode for ProcStatINode {
 | 
			
		||||
        let stime = 0;
 | 
			
		||||
        let cutime = 0;
 | 
			
		||||
        let cstime = 0;
 | 
			
		||||
        // Convert [19,-20] to [39,0].
 | 
			
		||||
        let priority = main_thread.nice().read().unwrap().to_raw_val() + 20;
 | 
			
		||||
        let nice = main_thread.nice().read().unwrap().to_raw_val();
 | 
			
		||||
        let priority = main_thread.nice().read().unwrap().to_priority_val();
 | 
			
		||||
        let nice = main_thread.nice().read().unwrap().raw_val();
 | 
			
		||||
        let num_threads = self.0.threads().len();
 | 
			
		||||
        let itrealvalue = 0;
 | 
			
		||||
        let starttime = self.0.start_time();
 | 
			
		||||
 | 
			
		||||
@ -606,16 +606,16 @@ pub fn do_fchmodat(dirfd: i32, path: *const i8, mode: u16) -> Result<isize> {
 | 
			
		||||
    Ok(0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn do_chown(path: *const i8, uid: i32, gid: i32) -> Result<isize> {
 | 
			
		||||
pub fn do_chown(path: *const i8, uid: u32, gid: u32) -> Result<isize> {
 | 
			
		||||
    self::do_fchownat(AT_FDCWD, path, uid, gid, 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn do_fchown(fd: FileDesc, uid: i32, gid: i32) -> Result<isize> {
 | 
			
		||||
pub fn do_fchown(fd: FileDesc, uid: u32, gid: u32) -> Result<isize> {
 | 
			
		||||
    file_ops::do_fchown(fd, uid, gid)?;
 | 
			
		||||
    Ok(0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn do_fchownat(dirfd: i32, path: *const i8, uid: i32, gid: i32, flags: i32) -> Result<isize> {
 | 
			
		||||
pub fn do_fchownat(dirfd: i32, path: *const i8, uid: u32, gid: u32, flags: i32) -> Result<isize> {
 | 
			
		||||
    let path = from_user::clone_cstring_safely(path)?
 | 
			
		||||
        .to_string_lossy()
 | 
			
		||||
        .into_owned();
 | 
			
		||||
@ -631,7 +631,7 @@ pub fn do_fchownat(dirfd: i32, path: *const i8, uid: i32, gid: i32, flags: i32)
 | 
			
		||||
    Ok(0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn do_lchown(path: *const i8, uid: i32, gid: i32) -> Result<isize> {
 | 
			
		||||
pub fn do_lchown(path: *const i8, uid: u32, gid: u32) -> Result<isize> {
 | 
			
		||||
    self::do_fchownat(
 | 
			
		||||
        AT_FDCWD,
 | 
			
		||||
        path,
 | 
			
		||||
 | 
			
		||||
@ -42,9 +42,6 @@ pub struct Thread {
 | 
			
		||||
    fs: FsViewRef,
 | 
			
		||||
    files: FileTableRef,
 | 
			
		||||
    sched: SchedAgentRef,
 | 
			
		||||
    // According to POSIX, the nice value is a per-process setting.
 | 
			
		||||
    // In our implementation, the threads belong to same process
 | 
			
		||||
    // share the same nice value.
 | 
			
		||||
    nice: NiceValueRef,
 | 
			
		||||
    rlimits: ResourceLimitsRef,
 | 
			
		||||
    // Signal
 | 
			
		||||
 | 
			
		||||
@ -2,17 +2,18 @@ use super::priority::{NiceValue, PrioWhich};
 | 
			
		||||
use crate::prelude::*;
 | 
			
		||||
use crate::process::table::{get_all_processes, get_pgrp, get_process};
 | 
			
		||||
 | 
			
		||||
pub fn do_set_priority(which: PrioWhich, who: i32, nice: NiceValue) -> Result<()> {
 | 
			
		||||
pub fn do_set_priority(which: PrioWhich, who: i32, prio: NiceValue) -> Result<()> {
 | 
			
		||||
    debug!(
 | 
			
		||||
        "set_priority: which: {:?}, who: {}, nice: {:?}",
 | 
			
		||||
        which, who, nice
 | 
			
		||||
        "set_priority: which: {:?}, who: {}, prio: {:?}",
 | 
			
		||||
        which, who, prio
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let processes = get_processes(which, who)?;
 | 
			
		||||
    for process in processes.iter() {
 | 
			
		||||
        for thread in process.threads().iter() {
 | 
			
		||||
            *thread.nice().write().unwrap() = nice;
 | 
			
		||||
        }
 | 
			
		||||
        let main_thread = process
 | 
			
		||||
            .main_thread()
 | 
			
		||||
            .ok_or_else(|| errno!(ESRCH, "invalid pid"))?;
 | 
			
		||||
        *main_thread.nice().write().unwrap() = prio;
 | 
			
		||||
    }
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
@ -21,25 +22,27 @@ pub fn do_get_priority(which: PrioWhich, who: i32) -> Result<NiceValue> {
 | 
			
		||||
    debug!("get_priority: which: {:?}, who: {}", which, who);
 | 
			
		||||
 | 
			
		||||
    let processes = get_processes(which, who)?;
 | 
			
		||||
    let nice = {
 | 
			
		||||
        let mut nice = NiceValue::MAX;
 | 
			
		||||
    let prio = {
 | 
			
		||||
        let mut prio = NiceValue::max_value();
 | 
			
		||||
        for process in processes.iter() {
 | 
			
		||||
            let main_thread = process
 | 
			
		||||
                .main_thread()
 | 
			
		||||
                .ok_or_else(|| errno!(ESRCH, "invalid pid"))?;
 | 
			
		||||
            let current_nice = main_thread.nice().read().unwrap();
 | 
			
		||||
            let nice_value = main_thread.nice().read().unwrap();
 | 
			
		||||
            // Returns the highest priority enjoyed by the processes
 | 
			
		||||
            if *current_nice < nice {
 | 
			
		||||
                nice = *current_nice;
 | 
			
		||||
            if *nice_value < prio {
 | 
			
		||||
                prio = *nice_value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        nice
 | 
			
		||||
        prio
 | 
			
		||||
    };
 | 
			
		||||
    Ok(nice)
 | 
			
		||||
    Ok(prio)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// According to POSIX, the nice value is a per-process setting.
 | 
			
		||||
// In our implementation, the threads belong to same process share the same nice value.
 | 
			
		||||
fn get_processes(which: PrioWhich, who: i32) -> Result<Vec<crate::process::ProcessRef>> {
 | 
			
		||||
    let processes = match which {
 | 
			
		||||
    Ok(match which {
 | 
			
		||||
        PrioWhich::PRIO_PROCESS => {
 | 
			
		||||
            let process = if who == 0 {
 | 
			
		||||
                current!().process().clone()
 | 
			
		||||
@ -64,10 +67,5 @@ fn get_processes(which: PrioWhich, who: i32) -> Result<Vec<crate::process::Proce
 | 
			
		||||
                return_errno!(ESRCH, "no such user");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    if processes.is_empty() {
 | 
			
		||||
        return_errno!(ESRCH, "no such process");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ok(processes)
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -21,48 +21,55 @@ impl TryFrom<i32> for PrioWhich {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Process scheduling nice value.
 | 
			
		||||
/// Process priority value
 | 
			
		||||
///
 | 
			
		||||
/// Lower values give a process a higher scheduling priority.
 | 
			
		||||
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
 | 
			
		||||
pub struct NiceValue {
 | 
			
		||||
    value: i8,
 | 
			
		||||
    value: i32,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl NiceValue {
 | 
			
		||||
    pub const MAX: Self = Self { value: 19 };
 | 
			
		||||
    const MAX_PRIO: i32 = 19;
 | 
			
		||||
 | 
			
		||||
    pub const MIN: Self = Self { value: -20 };
 | 
			
		||||
    const MIN_PRIO: i32 = -20;
 | 
			
		||||
 | 
			
		||||
    /// Create a nice value from a raw value.
 | 
			
		||||
    ///
 | 
			
		||||
    /// The raw value given beyond the range are automatically adjusted
 | 
			
		||||
    /// to the nearest boundary value.
 | 
			
		||||
    pub fn new(raw: i8) -> Self {
 | 
			
		||||
        if raw < Self::MIN.value {
 | 
			
		||||
            Self::MIN
 | 
			
		||||
        } else if raw > Self::MAX.value {
 | 
			
		||||
            Self::MAX
 | 
			
		||||
        } else {
 | 
			
		||||
            Self { value: raw }
 | 
			
		||||
    pub fn max_value() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            value: Self::MAX_PRIO,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Convert to the raw value with range [19, -20].
 | 
			
		||||
    pub fn to_raw_val(self) -> i8 {
 | 
			
		||||
    pub fn min_value() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            value: Self::MIN_PRIO,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn raw_val(&self) -> i32 {
 | 
			
		||||
        self.value
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Convert [19,-20] to priority value [39,0].
 | 
			
		||||
    pub fn to_priority_val(&self) -> i32 {
 | 
			
		||||
        self.value - Self::MIN_PRIO
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Convert [19,-20] to rlimit style value [1,40].
 | 
			
		||||
    pub fn to_rlimit_val(&self) -> i32 {
 | 
			
		||||
        Self::MAX_PRIO - self.value + 1
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<i32> for NiceValue {
 | 
			
		||||
    fn from(raw: i32) -> Self {
 | 
			
		||||
        let adj_raw = if raw > i8::MAX as i32 {
 | 
			
		||||
            i8::MAX
 | 
			
		||||
        } else if raw < i8::MIN as i32 {
 | 
			
		||||
            i8::MIN
 | 
			
		||||
        let value = if raw < Self::MIN_PRIO {
 | 
			
		||||
            Self::MIN_PRIO
 | 
			
		||||
        } else if raw > Self::MAX_PRIO {
 | 
			
		||||
            Self::MAX_PRIO
 | 
			
		||||
        } else {
 | 
			
		||||
            raw as i8
 | 
			
		||||
            raw
 | 
			
		||||
        };
 | 
			
		||||
        Self::new(adj_raw)
 | 
			
		||||
        Self { value }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -83,16 +83,16 @@ pub fn do_getcpu(cpu_ptr: *mut u32, node_ptr: *mut u32) -> Result<isize> {
 | 
			
		||||
 | 
			
		||||
pub fn do_set_priority(which: i32, who: i32, prio: i32) -> Result<isize> {
 | 
			
		||||
    let which = PrioWhich::try_from(which)?;
 | 
			
		||||
    let nice = NiceValue::from(prio);
 | 
			
		||||
    super::do_priority::do_set_priority(which, who, nice)?;
 | 
			
		||||
    let prio = NiceValue::from(prio);
 | 
			
		||||
    super::do_priority::do_set_priority(which, who, prio)?;
 | 
			
		||||
    Ok(0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn do_get_priority(which: i32, who: i32) -> Result<isize> {
 | 
			
		||||
    let which = PrioWhich::try_from(which)?;
 | 
			
		||||
    let nice = super::do_priority::do_get_priority(which, who)?;
 | 
			
		||||
    let prio = super::do_priority::do_get_priority(which, who)?;
 | 
			
		||||
    // To avoid negative return values, "getpriority()" will
 | 
			
		||||
    // not return the normal nice-value, but a negated value that
 | 
			
		||||
    // has been offset by 20 (ie it returns 40..1 instead of -20..19)
 | 
			
		||||
    Ok((20 - nice.to_raw_val()) as _)
 | 
			
		||||
    Ok(prio.to_rlimit_val() as isize)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -189,9 +189,9 @@ macro_rules! process_syscall_table_with_callback {
 | 
			
		||||
            (Readlink = 89) => do_readlink(path: *const i8, buf: *mut u8, size: usize),
 | 
			
		||||
            (Chmod = 90) => do_chmod(path: *const i8, mode: u16),
 | 
			
		||||
            (Fchmod = 91) => do_fchmod(fd: FileDesc, mode: u16),
 | 
			
		||||
            (Chown = 92) => do_chown(path: *const i8, uid: i32, gid: i32),
 | 
			
		||||
            (Fchown = 93) => do_fchown(fd: FileDesc, uid: i32, gid: i32),
 | 
			
		||||
            (Lchown = 94) => do_lchown(path: *const i8, uid: i32, gid: i32),
 | 
			
		||||
            (Chown = 92) => do_chown(path: *const i8, uid: u32, gid: u32),
 | 
			
		||||
            (Fchown = 93) => do_fchown(fd: FileDesc, uid: u32, gid: u32),
 | 
			
		||||
            (Lchown = 94) => do_lchown(path: *const i8, uid: u32, gid: u32),
 | 
			
		||||
            (Umask = 95) => do_umask(mask: u16),
 | 
			
		||||
            (Gettimeofday = 96) => do_gettimeofday(tv_u: *mut timeval_t),
 | 
			
		||||
            (Getrlimit = 97) => do_gettrlimit(resource: u32, rlim: *mut rlimit_t),
 | 
			
		||||
@ -357,7 +357,7 @@ macro_rules! process_syscall_table_with_callback {
 | 
			
		||||
            (Openat = 257) => do_openat(dirfd: i32, path: *const i8, flags: u32, mode: u16),
 | 
			
		||||
            (Mkdirat = 258) => do_mkdirat(dirfd: i32, path: *const i8, mode: u16),
 | 
			
		||||
            (Mknodat = 259) => handle_unsupported(),
 | 
			
		||||
            (Fchownat = 260) => do_fchownat(dirfd: i32, path: *const i8, uid: i32, gid: i32, flags: i32),
 | 
			
		||||
            (Fchownat = 260) => do_fchownat(dirfd: i32, path: *const i8, uid: u32, gid: u32, flags: i32),
 | 
			
		||||
            (Futimesat = 261) => do_futimesat(dirfd: i32, path: *const i8, times: *const timeval_t),
 | 
			
		||||
            (Fstatat = 262) => do_fstatat(dirfd: i32, path: *const i8, stat_buf: *mut Stat, flags: u32),
 | 
			
		||||
            (Unlinkat = 263) => do_unlinkat(dirfd: i32, path: *const i8, flags: i32),
 | 
			
		||||
 | 
			
		||||
@ -55,57 +55,6 @@ static int __test_chown(const char *file_path) {
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int __test_chown_with_negative_id(const char *file_path) {
 | 
			
		||||
    struct stat old_stat_buf;
 | 
			
		||||
    struct stat new_stat_buf;
 | 
			
		||||
    uid_t uid = -100;
 | 
			
		||||
    gid_t gid = -100;
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    ret = chown(file_path, uid, gid);
 | 
			
		||||
    if (!(ret < 0 && errno == EINVAL)) {
 | 
			
		||||
        THROW_ERROR("chown should return EINVAL");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = stat(file_path, &old_stat_buf);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        THROW_ERROR("failed to stat file");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uid = 100;
 | 
			
		||||
    gid = -1;
 | 
			
		||||
    ret = chown(file_path, uid, gid);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        THROW_ERROR("failed to chown file");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = stat(file_path, &new_stat_buf);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        THROW_ERROR("failed to stat file");
 | 
			
		||||
    }
 | 
			
		||||
    if (new_stat_buf.st_uid != uid || new_stat_buf.st_gid != old_stat_buf.st_gid) {
 | 
			
		||||
        THROW_ERROR("check chown result failed");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    old_stat_buf.st_uid = new_stat_buf.st_uid;
 | 
			
		||||
    uid = -1;
 | 
			
		||||
    gid = 100;
 | 
			
		||||
    ret = chown(file_path, uid, gid);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        THROW_ERROR("failed to chown file");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = stat(file_path, &new_stat_buf);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        THROW_ERROR("failed to stat file");
 | 
			
		||||
    }
 | 
			
		||||
    if (new_stat_buf.st_uid != old_stat_buf.st_uid || new_stat_buf.st_gid != gid) {
 | 
			
		||||
        THROW_ERROR("check chown result failed");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int __test_lchown(const char *file_path) {
 | 
			
		||||
    struct stat stat_buf;
 | 
			
		||||
    uid_t uid = 100;
 | 
			
		||||
@ -239,10 +188,6 @@ static int test_chown() {
 | 
			
		||||
    return test_chown_framework(__test_chown);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int test_chown_with_negative_id() {
 | 
			
		||||
    return test_chown_framework(__test_chown_with_negative_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int test_lchown() {
 | 
			
		||||
    return test_chown_framework(__test_lchown);
 | 
			
		||||
}
 | 
			
		||||
@ -265,7 +210,6 @@ static int test_fchownat_with_empty_path() {
 | 
			
		||||
 | 
			
		||||
static test_case_t test_cases[] = {
 | 
			
		||||
    TEST_CASE(test_chown),
 | 
			
		||||
    TEST_CASE(test_chown_with_negative_id),
 | 
			
		||||
    TEST_CASE(test_lchown),
 | 
			
		||||
    TEST_CASE(test_fchown),
 | 
			
		||||
    TEST_CASE(test_fchownat),
 | 
			
		||||
 | 
			
		||||
@ -125,7 +125,7 @@ RUN wget http://www.etallen.com/cpuid/cpuid-20200211.x86_64.tar.gz && \
 | 
			
		||||
# Download the Occlum source
 | 
			
		||||
ARG OCCLUM_BRANCH
 | 
			
		||||
WORKDIR /root
 | 
			
		||||
RUN git clone -b $OCCLUM_BRANCH https://github.com/occlum/occlum && \
 | 
			
		||||
RUN git clone -b $OCCLUM_BRANCH https://gitea.detee.cloud/general/occlum && \
 | 
			
		||||
    cp -r /root/occlum/tools/toolchains/* /tmp/ && mkdir -p /opt/occlum/ && \
 | 
			
		||||
    cp /root/occlum/tools/docker/start_aesm.sh /opt/occlum/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -129,7 +129,7 @@ RUN wget http://www.etallen.com/cpuid/cpuid-20200211.x86_64.tar.gz && \
 | 
			
		||||
# Download the Occlum source
 | 
			
		||||
ARG OCCLUM_BRANCH
 | 
			
		||||
WORKDIR /root
 | 
			
		||||
RUN git clone -b $OCCLUM_BRANCH https://github.com/occlum/occlum && \
 | 
			
		||||
RUN git clone -b $OCCLUM_BRANCH https://gitea.detee.cloud/general/occlum && \
 | 
			
		||||
    cd /root/occlum && git submodule update --init && \
 | 
			
		||||
    mkdir -p /opt/occlum/ && \
 | 
			
		||||
    cp /root/occlum/tools/docker/start_aesm.sh /opt/occlum/
 | 
			
		||||
 | 
			
		||||
@ -136,7 +136,7 @@ RUN git clone -b sgx_2.20_for_occlum https://github.com/occlum/linux-sgx && \
 | 
			
		||||
# Download the Occlum source
 | 
			
		||||
ARG OCCLUM_BRANCH
 | 
			
		||||
WORKDIR /root
 | 
			
		||||
RUN git clone -b $OCCLUM_BRANCH https://github.com/occlum/occlum && \
 | 
			
		||||
RUN git clone -b $OCCLUM_BRANCH https://gitea.detee.cloud/general/occlum && \
 | 
			
		||||
    cd /root/occlum && git submodule update --init && \
 | 
			
		||||
    mkdir -p /opt/occlum/ && \
 | 
			
		||||
    cp /root/occlum/tools/docker/start_aesm.sh /opt/occlum/
 | 
			
		||||
@ -184,9 +184,9 @@ COPY --from=alpine /usr/lib/jvm/java-1.8-openjdk $JDK8_PATH
 | 
			
		||||
RUN rm $JDK8_PATH/jre/lib/security/cacerts
 | 
			
		||||
COPY --from=alpine /etc/ssl/certs/java/cacerts $JDK8_PATH/jre/lib/security/cacerts
 | 
			
		||||
 | 
			
		||||
# Install DCAP library
 | 
			
		||||
# Install DCAP and Utilities libraries
 | 
			
		||||
WORKDIR /root/occlum/tools/toolchains
 | 
			
		||||
RUN cd dcap_lib && ./build.sh && cd .. && rm -rf dcap_lib
 | 
			
		||||
RUN cd dcap_lib && ./build.sh && cd ../utils_lib && ./build.sh && cd .. && rm -rf utils_lib dcap_lib
 | 
			
		||||
 | 
			
		||||
# Install AECS Client library
 | 
			
		||||
WORKDIR /root/occlum/tools/toolchains
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user