Skip to content

Commit e56d1f3

Browse files
committed
Use prctl() call before IPC handle creation
Use the prctl() call to let the parent process and its children open IPC handle. This is a more secure way than setting the ptrace_scope to 0 globally for all processes in the system. Co-authored-by: [email protected]
1 parent 820fd05 commit e56d1f3

File tree

12 files changed

+41
-83
lines changed

12 files changed

+41
-83
lines changed

.github/workflows/reusable_basic.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,6 @@ jobs:
145145
- name: Install libhwloc
146146
run: .github/scripts/install_hwloc.sh
147147

148-
- name: Set ptrace value for IPC test
149-
run: sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"
150-
151148
- name: Get UMF version
152149
run: |
153150
VERSION=$(git describe --tags --abbrev=0 | grep -oP '\d+\.\d+\.\d+')

.github/workflows/reusable_fast.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,6 @@ jobs:
8888
sudo apt-get install -y cmake libnuma-dev libtbb-dev
8989
.github/scripts/install_hwloc.sh # install hwloc-2.3.0 instead of hwloc-2.1.0 present in the OS package
9090
91-
- name: Set ptrace value for IPC test (on Linux only)
92-
if: ${{ matrix.os == 'ubuntu-latest' || matrix.os == 'ubuntu-20.04' }}
93-
run: sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"
94-
9591
- name: Configure CMake
9692
if: matrix.simple_cmake == 'OFF'
9793
run: >

.github/workflows/reusable_proxy_lib.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@ jobs:
3434
sudo apt-get update
3535
sudo apt-get install -y cmake libhwloc-dev libtbb-dev lcov
3636
37-
- name: Set ptrace value for IPC test
38-
run: sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"
39-
4037
- name: Configure build
4138
run: >
4239
cmake

.github/workflows/reusable_sanitizers.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,6 @@ jobs:
4040
sudo apt-get update
4141
sudo apt-get install -y intel-oneapi-ippcp-devel intel-oneapi-ipp-devel intel-oneapi-common-oneapi-vars intel-oneapi-compiler-dpcpp-cpp
4242
43-
44-
- name: Set ptrace value for IPC test
45-
run: sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"
46-
4743
- name: Configure build
4844
run: >
4945
${{ matrix.compiler.cxx == 'icpx' && '. /opt/intel/oneapi/setvars.sh &&' || ''}}

README.md

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -159,15 +159,7 @@ OS memory provider supports two types of memory mappings (set by the `visibility
159159
IPC API requires the `UMF_MEM_MAP_SHARED` memory `visibility` mode
160160
(`UMF_RESULT_ERROR_INVALID_ARGUMENT` is returned otherwise).
161161

162-
IPC API uses the file descriptor duplication. It requires using `pidfd_getfd(2)` to obtain
163-
a duplicate of another process's file descriptor (`pidfd_getfd(2)` is supported since Linux 5.6).
164-
Permission to duplicate another process's file descriptor is governed by a ptrace access mode
165-
`PTRACE_MODE_ATTACH_REALCREDS` check (see `ptrace(2)`) that can be changed using
166-
the `/proc/sys/kernel/yama/ptrace_scope` interface in the following way:
167-
168-
```sh
169-
sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"
170-
```
162+
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.
171163

172164
There are available two mechanisms for the shared memory mapping:
173165

@@ -194,15 +186,7 @@ Packages required for tests (Linux-only yet):
194186

195187
A memory provider that provides memory from L0 device.
196188

197-
IPC API uses the file descriptor duplication. It requires using `pidfd_getfd(2)` to obtain
198-
a duplicate of another process's file descriptor (`pidfd_getfd(2)` is supported since Linux 5.6).
199-
Permission to duplicate another process's file descriptor is governed by a ptrace access mode
200-
`PTRACE_MODE_ATTACH_REALCREDS` check (see `ptrace(2)`) that can be changed using
201-
the `/proc/sys/kernel/yama/ptrace_scope` interface in the following way:
202-
203-
```sh
204-
sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"
205-
```
189+
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.
206190

207191
##### Requirements
208192

@@ -359,7 +343,7 @@ The memory used by the proxy memory allocator is mmap'ed:
359343
1) with the `MAP_PRIVATE` flag by default or
360344
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:
361345
- `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.
362-
- `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.
346+
- `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.
363347

364348
**Size threshold**
365349

examples/ipc_ipcapi/ipc_ipcapi_anon_fd.sh

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

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

examples/ipc_ipcapi/ipc_ipcapi_producer.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
*/
77

88
#include <arpa/inet.h>
9+
#include <errno.h>
910
#include <stdio.h>
1011
#include <stdlib.h>
1112
#include <string.h>
13+
#include <sys/prctl.h>
1214
#include <sys/socket.h>
1315
#include <unistd.h>
1416

@@ -69,6 +71,23 @@ int main(int argc, char *argv[]) {
6971

7072
int port = atoi(argv[1]);
7173

74+
// The prctl() function with PR_SET_PTRACER is used here to allow parent process and its children
75+
// to ptrace the current process. This is necessary because UMF's memory providers on Linux (except CUDA)
76+
// use the pidfd_getfd(2) system call to duplicate another process's file descriptor, which is
77+
// governed by ptrace permissions. By default on Ubuntu /proc/sys/kernel/yama/ptrace_scope is
78+
// set to 1 ("restricted ptrace"), which prevents pidfd_getfd from working unless ptrace_scope
79+
// is set to 0.
80+
// To overcome this limitation without requiring users to change the ptrace_scope
81+
// setting (which requires root privileges), we use prctl() to allow the consumer process
82+
// to copy producer's file descriptor, even when ptrace_scope is set to 1.
83+
ret = prctl(PR_SET_PTRACER, getppid());
84+
if (ret == -1) {
85+
printf("prctl() call failed with errno %d (%s). This may indicate that "
86+
"PR_SET_PTRACER"
87+
" is not supported on this system.\n",
88+
errno, strerror(errno));
89+
}
90+
7291
umf_memory_provider_handle_t OS_memory_provider = NULL;
7392
umf_os_memory_provider_params_handle_t os_params = NULL;
7493
enum umf_result_t umf_result;

scripts/qemu/run-tests.sh

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/bin/bash
2-
# Copyright (C) 2024 Intel Corporation
2+
# Copyright (C) 2024-2025 Intel Corporation
33
# Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
44
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
55

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

2927
numactl -H
3028

src/utils/utils_posix_common.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright (C) 2024 Intel Corporation
3+
* Copyright (C) 2024-2025 Intel Corporation
44
*
55
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
66
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -91,9 +91,8 @@ umf_result_t utils_duplicate_fd(int pid, int fd_in, int *fd_out) {
9191
return UMF_RESULT_ERROR_NOT_SUPPORTED;
9292
#else
9393
// pidfd_getfd(2) is used to obtain a duplicate of another process's file descriptor.
94-
// Permission to duplicate another process's file descriptor
95-
// is governed by a ptrace access mode PTRACE_MODE_ATTACH_REALCREDS check (see ptrace(2))
96-
// that can be changed using the /proc/sys/kernel/yama/ptrace_scope interface.
94+
// Calling prctl(PR_SET_PTRACER, getppid()) in a producer binary that creates IPC handle
95+
// allow file descriptor duplication for parent process and its children
9796
// pidfd_getfd(2) is supported since Linux 5.6
9897
// pidfd_open(2) is supported since Linux 5.3
9998
errno = 0;

test/common/ipc_common.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
*/
77

88
#include <arpa/inet.h>
9+
#include <errno.h>
910
#include <stdio.h>
1011
#include <stdlib.h>
1112
#include <string.h>
13+
#include <sys/prctl.h>
1214
#include <sys/socket.h>
1315
#include <unistd.h>
1416

@@ -336,6 +338,14 @@ int run_producer(int port, umf_memory_pool_ops_t *pool_ops, void *pool_params,
336338
int producer_socket = -1;
337339
char consumer_message[MSG_SIZE];
338340

341+
ret = prctl(PR_SET_PTRACER, getppid());
342+
if (ret == -1) {
343+
printf("prctl() call failed with errno %d (%s). This may indicate that "
344+
"PR_SET_PTRACER"
345+
" is not supported on this system.\n",
346+
errno, strerror(errno));
347+
}
348+
339349
// create OS memory provider
340350
umf_result =
341351
umfMemoryProviderCreate(provider_ops, provider_params, &provider);

test/ipc_os_prov_anon_fd.sh

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (C) 2024 Intel Corporation
2+
# Copyright (C) 2024-2025 Intel Corporation
33
#
44
# Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
55
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -12,21 +12,6 @@ set -e
1212
# port should be a number from the range <1024, 65535>
1313
PORT=$(( 1024 + ( $$ % ( 65535 - 1024 ))))
1414

15-
# The ipc_os_prov_anon_fd example requires using pidfd_getfd(2)
16-
# to obtain a duplicate of another process's file descriptor.
17-
# Permission to duplicate another process's file descriptor
18-
# is governed by a ptrace access mode PTRACE_MODE_ATTACH_REALCREDS check (see ptrace(2))
19-
# that can be changed using the /proc/sys/kernel/yama/ptrace_scope interface.
20-
PTRACE_SCOPE_FILE="/proc/sys/kernel/yama/ptrace_scope"
21-
VAL=0
22-
if [ -f $PTRACE_SCOPE_FILE ]; then
23-
PTRACE_SCOPE_VAL=$(cat $PTRACE_SCOPE_FILE)
24-
if [ $PTRACE_SCOPE_VAL -ne $VAL ]; then
25-
echo "SKIP: ptrace_scope is not set to 0 (classic ptrace permissions) - skipping the test"
26-
exit 125 # skip code defined in CMakeLists.txt
27-
fi
28-
fi
29-
3015
UMF_LOG_VAL="level:debug;flush:debug;output:stderr;pid:yes"
3116

3217
echo "Starting ipc_os_prov_anon_fd CONSUMER on port $PORT ..."

test/providers/ipc_level_zero_prov.sh

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (C) 2024 Intel Corporation
2+
# Copyright (C) 2024-2025 Intel Corporation
33
#
44
# Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
55
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -12,21 +12,6 @@ set -e
1212
# port should be a number from the range <1024, 65535>
1313
PORT=$(( 1024 + ( $$ % ( 65535 - 1024 ))))
1414

15-
# The ipc_level_zero_prov test requires using pidfd_getfd(2)
16-
# to obtain a duplicate of another process's file descriptor.
17-
# Permission to duplicate another process's file descriptor
18-
# is governed by a ptrace access mode PTRACE_MODE_ATTACH_REALCREDS check (see ptrace(2))
19-
# that can be changed using the /proc/sys/kernel/yama/ptrace_scope interface.
20-
PTRACE_SCOPE_FILE="/proc/sys/kernel/yama/ptrace_scope"
21-
VAL=0
22-
if [ -f $PTRACE_SCOPE_FILE ]; then
23-
PTRACE_SCOPE_VAL=$(cat $PTRACE_SCOPE_FILE)
24-
if [ $PTRACE_SCOPE_VAL -ne $VAL ]; then
25-
echo "SKIP: ptrace_scope is not set to 0 (classic ptrace permissions) - skipping the test"
26-
exit 125 # skip code defined in CMakeLists.txt
27-
fi
28-
fi
29-
3015
UMF_LOG_VAL="level:debug;flush:debug;output:stderr;pid:yes"
3116

3217
echo "Starting ipc_level_zero_prov CONSUMER on port $PORT ..."

0 commit comments

Comments
 (0)