Skip to content

Set ptracer permissions for IPC handle creation #1018

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

Closed
wants to merge 1 commit into from
Closed
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
22 changes: 3 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,7 @@ 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:

```sh
sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"
```
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. Permission to duplicate another process's file descriptor 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, getppid())` in the producer binary that gets the IPC handle.

There are available two mechanisms for the shared memory mapping:

Expand All @@ -194,15 +186,7 @@ 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:

```sh
sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"
```
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. Permission to duplicate another process's file descriptor 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, getppid())` in the producer binary that gets the IPC handle.

##### Requirements

Expand Down Expand Up @@ -359,7 +343,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. Permission to duplicate another process's file descriptor 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, getppid())` in the producer binary that gets the IPC handle.

**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: 19 additions & 0 deletions examples/ipc_ipcapi/ipc_ipcapi_producer.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
*/

#include <arpa/inet.h>
#include <errno.h>
#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 +71,23 @@ 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) {
printf("prctl() call failed with errno %d (%s). This may indicate that "
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perror?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

"PR_SET_PTRACER"
" is not supported on this system.\n",
errno, strerror(errno));
}

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
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
// allow 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: 10 additions & 0 deletions test/common/ipc_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
*/

#include <arpa/inet.h>
#include <errno.h>
#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 +338,14 @@ 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) {
printf("prctl() call failed with errno %d (%s). This may indicate that "
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perror

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

"PR_SET_PTRACER"
" is not supported on this system.\n",
errno, strerror(errno));
}

// create OS memory provider
umf_result =
umfMemoryProviderCreate(provider_ops, provider_params, &provider);
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