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

Add info about ptrace permissions #1040

Merged
merged 1 commit into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/workflows/reusable_basic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,6 @@ jobs:
- name: Install libhwloc
run: .github/scripts/install_hwloc.sh

- name: Set ptrace value for IPC test
run: sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"

- name: Get UMF version
run: |
VERSION=$(git describe --tags --abbrev=0 | grep -oP '\d+\.\d+\.\d+')
Expand Down
4 changes: 0 additions & 4 deletions .github/workflows/reusable_fast.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,6 @@ jobs:
sudo apt-get install -y cmake libnuma-dev libtbb-dev
.github/scripts/install_hwloc.sh # install hwloc-2.3.0 instead of hwloc-2.1.0 present in the OS package

- name: Set ptrace value for IPC test (on Linux only)
if: ${{ matrix.os == 'ubuntu-latest' || matrix.os == 'ubuntu-20.04' }}
run: sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"

- name: Configure CMake
if: matrix.simple_cmake == 'OFF'
run: >
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/reusable_proxy_lib.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ jobs:
sudo apt-get update
sudo apt-get install -y cmake libhwloc-dev libtbb-dev lcov

- name: Set ptrace value for IPC test
run: sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"

- name: Configure build
run: >
cmake
Expand Down
4 changes: 0 additions & 4 deletions .github/workflows/reusable_sanitizers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ jobs:
sudo apt-get update
sudo apt-get install -y intel-oneapi-ippcp-devel intel-oneapi-ipp-devel intel-oneapi-common-oneapi-vars intel-oneapi-compiler-dpcpp-cpp


- name: Set ptrace value for IPC test
run: sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"

- name: Configure build
run: >
${{ matrix.compiler.cxx == 'icpx' && '. /opt/intel/oneapi/setvars.sh &&' || ''}}
Expand Down
25 changes: 13 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,12 @@ OS memory provider supports two types of memory mappings (set by the `visibility
IPC API requires the `UMF_MEM_MAP_SHARED` memory `visibility` mode
(`UMF_RESULT_ERROR_INVALID_ARGUMENT` is returned otherwise).

IPC API uses the file descriptor duplication. It requires using `pidfd_getfd(2)` to obtain
a duplicate of another process's file descriptor (`pidfd_getfd(2)` is supported since Linux 5.6).
Permission to duplicate another process's file descriptor is governed by a ptrace access mode
`PTRACE_MODE_ATTACH_REALCREDS` check (see `ptrace(2)`) that can be changed using
the `/proc/sys/kernel/yama/ptrace_scope` interface in the following way:
IPC API uses file descriptor duplication, which requires the `pidfd_getfd(2)` system call to obtain
a duplicate of another process's file descriptor. This system call is supported since Linux 5.6.
Required permission ("restricted ptrace") is governed by the `PTRACE_MODE_ATTACH_REALCREDS` check
(see `ptrace(2)`). To allow file descriptor duplication in a binary that opens IPC handle, you can call
`prctl(PR_SET_PTRACER, ...)` in the producer binary that gets the IPC handle.
Alternatively you can change the `ptrace_scope` globally in the system, e.g.:

```sh
sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"
Expand Down Expand Up @@ -194,16 +195,16 @@ Packages required for tests (Linux-only yet):

A memory provider that provides memory from L0 device.

IPC API uses the file descriptor duplication. It requires using `pidfd_getfd(2)` to obtain
a duplicate of another process's file descriptor (`pidfd_getfd(2)` is supported since Linux 5.6).
Permission to duplicate another process's file descriptor is governed by a ptrace access mode
`PTRACE_MODE_ATTACH_REALCREDS` check (see `ptrace(2)`) that can be changed using
the `/proc/sys/kernel/yama/ptrace_scope` interface in the following way:
IPC API uses file descriptor duplication, which requires the `pidfd_getfd(2)` system call to obtain
lplewa marked this conversation as resolved.
Show resolved Hide resolved
a duplicate of another process's file descriptor. This system call is supported since Linux 5.6.
Required permission ("restricted ptrace") is governed by the `PTRACE_MODE_ATTACH_REALCREDS` check
(see `ptrace(2)`). To allow file descriptor duplication in a binary that opens IPC handle, you can call
`prctl(PR_SET_PTRACER, ...)` in the producer binary that gets the IPC handle.
Alternatively you can change the `ptrace_scope` globally in the system, e.g.:

```sh
sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"
```

##### Requirements

1) Linux or Windows OS
Expand Down Expand Up @@ -359,7 +360,7 @@ The memory used by the proxy memory allocator is mmap'ed:
1) with the `MAP_PRIVATE` flag by default or
2) with the `MAP_SHARED` flag if the `UMF_PROXY` environment variable contains one of two following strings: `page.disposition=shared-shm` or `page.disposition=shared-fd`. These two options differ in a mechanism used during IPC:
- `page.disposition=shared-shm` - IPC uses the named shared memory. An SHM name is generated using the `umf_proxy_lib_shm_pid_$PID` pattern, where `$PID` is the PID of the process. It creates the `/dev/shm/umf_proxy_lib_shm_pid_$PID` file.
- `page.disposition=shared-fd` - IPC uses the file descriptor duplication. It requires using `pidfd_getfd(2)` to obtain a duplicate of another process's file descriptor. Permission to duplicate another process's file descriptor is governed by a ptrace access mode `PTRACE_MODE_ATTACH_REALCREDS` check (see `ptrace(2)`) that can be changed using the `/proc/sys/kernel/yama/ptrace_scope` interface. `pidfd_getfd(2)` is supported since Linux 5.6.
- `page.disposition=shared-fd` - IPC API uses file descriptor duplication, which requires the `pidfd_getfd(2)` system call to obtain a duplicate of another process's file descriptor. This system call is supported since Linux 5.6. Required permission ("restricted ptrace") is governed by the `PTRACE_MODE_ATTACH_REALCREDS` check (see `ptrace(2)`). To allow file descriptor duplication in a binary that opens IPC handle, you can call `prctl(PR_SET_PTRACER, ...)` in the producer binary that gets the IPC handle. Alternatively you can change the `ptrace_scope` globally in the system, e.g.: `sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"`.

**Size threshold**

Expand Down
14 changes: 3 additions & 11 deletions examples/ipc_ipcapi/ipc_ipcapi_anon_fd.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (C) 2024 Intel Corporation
# Copyright (C) 2024-2025 Intel Corporation
#
# Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Expand All @@ -16,16 +16,8 @@ PORT=$(( 1024 + ( $$ % ( 65535 - 1024 ))))
# to obtain a duplicate of another process's file descriptor.
# Permission to duplicate another process's file descriptor
# is governed by a ptrace access mode PTRACE_MODE_ATTACH_REALCREDS check (see ptrace(2))
# that can be changed using the /proc/sys/kernel/yama/ptrace_scope interface.
PTRACE_SCOPE_FILE="/proc/sys/kernel/yama/ptrace_scope"
VAL=0
if [ -f $PTRACE_SCOPE_FILE ]; then
PTRACE_SCOPE_VAL=$(cat $PTRACE_SCOPE_FILE)
if [ $PTRACE_SCOPE_VAL -ne $VAL ]; then
echo "SKIP: ptrace_scope is not set to 0 (classic ptrace permissions) - skipping the test"
exit 125 # skip code defined in CMakeLists.txt
fi
fi
# In the producer binary used in this example prctl(PR_SET_PTRACER, getppid()) is used
# to allow consumer to duplicate file descriptor of producer.

UMF_LOG_VAL="level:debug;flush:debug;output:stderr;pid:yes"

Expand Down
19 changes: 18 additions & 1 deletion examples/ipc_ipcapi/ipc_ipcapi_producer.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2024 Intel Corporation
* Copyright (C) 2024-2025 Intel Corporation
*
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Expand All @@ -9,6 +9,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/socket.h>
#include <unistd.h>

Expand Down Expand Up @@ -69,6 +70,21 @@ int main(int argc, char *argv[]) {

int port = atoi(argv[1]);

// The prctl() function with PR_SET_PTRACER is used here to allow parent process and its children
// to ptrace the current process. This is necessary because UMF's memory providers on Linux (except CUDA)
// use the pidfd_getfd(2) system call to duplicate another process's file descriptor, which is
// governed by ptrace permissions. By default on Ubuntu /proc/sys/kernel/yama/ptrace_scope is
// set to 1 ("restricted ptrace"), which prevents pidfd_getfd from working unless ptrace_scope
// is set to 0.
// To overcome this limitation without requiring users to change the ptrace_scope
// setting (which requires root privileges), we use prctl() to allow the consumer process
// to copy producer's file descriptor, even when ptrace_scope is set to 1.
ret = prctl(PR_SET_PTRACER, getppid());
if (ret == -1) {
perror("PR_SET_PTRACER may be not supported. prctl() call failed");
goto err_end;
}

umf_memory_provider_handle_t OS_memory_provider = NULL;
umf_os_memory_provider_params_handle_t os_params = NULL;
enum umf_result_t umf_result;
Expand Down Expand Up @@ -259,6 +275,7 @@ int main(int argc, char *argv[]) {
err_destroy_OS_params:
umfOsMemoryProviderParamsDestroy(os_params);

err_end:
if (ret == 0) {
fprintf(stderr, "[producer] Shutting down (status OK) ...\n");
} else if (ret == 1) {
Expand Down
4 changes: 1 addition & 3 deletions scripts/qemu/run-tests.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
# Copyright (C) 2024 Intel Corporation
# Copyright (C) 2024-2025 Intel Corporation
# Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

Expand All @@ -23,8 +23,6 @@ UMF_DIR=$(pwd)
# Drop caches, restores free memory on NUMA nodes
echo password | sudo sync;
echo password | sudo sh -c "/usr/bin/echo 3 > /proc/sys/vm/drop_caches"
# Set ptrace value for IPC test
echo password | sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"

numactl -H

Expand Down
7 changes: 3 additions & 4 deletions src/utils/utils_posix_common.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
*
* Copyright (C) 2024 Intel Corporation
* Copyright (C) 2024-2025 Intel Corporation
*
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Expand Down Expand Up @@ -91,9 +91,8 @@ umf_result_t utils_duplicate_fd(int pid, int fd_in, int *fd_out) {
return UMF_RESULT_ERROR_NOT_SUPPORTED;
#else
// pidfd_getfd(2) is used to obtain a duplicate of another process's file descriptor.
// Permission to duplicate another process's file descriptor
// is governed by a ptrace access mode PTRACE_MODE_ATTACH_REALCREDS check (see ptrace(2))
// that can be changed using the /proc/sys/kernel/yama/ptrace_scope interface.
// Calling prctl(PR_SET_PTRACER, getppid()) in a producer binary that creates IPC handle
// allows file descriptor duplication for parent process and its children.
// pidfd_getfd(2) is supported since Linux 5.6
// pidfd_open(2) is supported since Linux 5.3
errno = 0;
Expand Down
10 changes: 9 additions & 1 deletion test/common/ipc_common.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2024 Intel Corporation
* Copyright (C) 2024-2025 Intel Corporation
*
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Expand All @@ -9,6 +9,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/socket.h>
#include <unistd.h>

Expand Down Expand Up @@ -336,6 +337,12 @@ int run_producer(int port, umf_memory_pool_ops_t *pool_ops, void *pool_params,
int producer_socket = -1;
char consumer_message[MSG_SIZE];

ret = prctl(PR_SET_PTRACER, getppid());
if (ret == -1) {
perror("PR_SET_PTRACER may be not supported. prctl() call failed");
goto err_end;
}

// create OS memory provider
umf_result =
umfMemoryProviderCreate(provider_ops, provider_params, &provider);
Expand Down Expand Up @@ -528,6 +535,7 @@ int run_producer(int port, umf_memory_pool_ops_t *pool_ops, void *pool_params,
err_umfMemoryProviderDestroy:
umfMemoryProviderDestroy(provider);

err_end:
if (ret == 0) {
fprintf(stderr, "[producer] Shutting down (status OK) ...\n");
} else if (ret == 1) {
Expand Down
17 changes: 1 addition & 16 deletions test/ipc_os_prov_anon_fd.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (C) 2024 Intel Corporation
# Copyright (C) 2024-2025 Intel Corporation
#
# Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Expand All @@ -12,21 +12,6 @@ set -e
# port should be a number from the range <1024, 65535>
PORT=$(( 1024 + ( $$ % ( 65535 - 1024 ))))

# The ipc_os_prov_anon_fd example requires using pidfd_getfd(2)
# to obtain a duplicate of another process's file descriptor.
# Permission to duplicate another process's file descriptor
# is governed by a ptrace access mode PTRACE_MODE_ATTACH_REALCREDS check (see ptrace(2))
# that can be changed using the /proc/sys/kernel/yama/ptrace_scope interface.
PTRACE_SCOPE_FILE="/proc/sys/kernel/yama/ptrace_scope"
VAL=0
if [ -f $PTRACE_SCOPE_FILE ]; then
PTRACE_SCOPE_VAL=$(cat $PTRACE_SCOPE_FILE)
if [ $PTRACE_SCOPE_VAL -ne $VAL ]; then
echo "SKIP: ptrace_scope is not set to 0 (classic ptrace permissions) - skipping the test"
exit 125 # skip code defined in CMakeLists.txt
fi
fi

UMF_LOG_VAL="level:debug;flush:debug;output:stderr;pid:yes"

echo "Starting ipc_os_prov_anon_fd CONSUMER on port $PORT ..."
Expand Down
17 changes: 1 addition & 16 deletions test/providers/ipc_level_zero_prov.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (C) 2024 Intel Corporation
# Copyright (C) 2024-2025 Intel Corporation
#
# Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Expand All @@ -12,21 +12,6 @@ set -e
# port should be a number from the range <1024, 65535>
PORT=$(( 1024 + ( $$ % ( 65535 - 1024 ))))

# The ipc_level_zero_prov test requires using pidfd_getfd(2)
# to obtain a duplicate of another process's file descriptor.
# Permission to duplicate another process's file descriptor
# is governed by a ptrace access mode PTRACE_MODE_ATTACH_REALCREDS check (see ptrace(2))
# that can be changed using the /proc/sys/kernel/yama/ptrace_scope interface.
PTRACE_SCOPE_FILE="/proc/sys/kernel/yama/ptrace_scope"
VAL=0
if [ -f $PTRACE_SCOPE_FILE ]; then
PTRACE_SCOPE_VAL=$(cat $PTRACE_SCOPE_FILE)
if [ $PTRACE_SCOPE_VAL -ne $VAL ]; then
echo "SKIP: ptrace_scope is not set to 0 (classic ptrace permissions) - skipping the test"
exit 125 # skip code defined in CMakeLists.txt
fi
fi

UMF_LOG_VAL="level:debug;flush:debug;output:stderr;pid:yes"

echo "Starting ipc_level_zero_prov CONSUMER on port $PORT ..."
Expand Down
Loading