1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
#!/usr/bin/bats -t
# SPDX-License-Identifier: MPL-2.0
#
# libpathrs: safe path resolution on Linux
# Copyright (C) 2019-2025 Aleksa Sarai <cyphar@cyphar.com>
# Copyright (C) 2019-2025 SUSE LLC
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
load helpers
function setup() {
setup_tmpdirs
}
function teardown() {
teardown_tmpdirs
}
@test "procfs --base root readlink" {
pathrs-cmd procfs readlink net
[ "$status" -eq 0 ]
grep -Fx 'LINK-TARGET self/net' <<<"$output"
pathrs-cmd procfs --base root readlink mounts
[ "$status" -eq 0 ]
grep -Fx 'LINK-TARGET self/mounts' <<<"$output"
pathrs-cmd procfs --base root readlink self
[ "$status" -eq 0 ]
grep -Ex 'LINK-TARGET [0-9]+' <<<"$output"
pathrs-cmd procfs --base root readlink thread-self
if [ -e /proc/thread-self ]; then
[ "$status" -eq 0 ]
grep -Ex 'LINK-TARGET [0-9]+/task/[0-9]+' <<<"$output"
else
check-errno ENOENT
fi
}
@test "procfs --base root readlink [symlink parent component]" {
realpwd="$(readlink -f "$PWD")"
pathrs-cmd procfs --base root readlink self/cwd
[ "$status" -eq 0 ]
grep -Fx "LINK-TARGET $realpwd" <<<"$output"
}
@test "procfs --base pid=\$\$ readlink" {
realpwd="$(readlink -f "$PWD")"
pathrs-cmd procfs --base pid=$$ readlink cwd
[ "$status" -eq 0 ]
grep -Fx "LINK-TARGET $realpwd" <<<"$output"
}
@test "procfs --base self readlink" {
exepath="$(readlink -f "$PATHRS_CMD")"
pathrs-cmd procfs --base self readlink exe
[ "$status" -eq 0 ]
! grep -E '^FILE-PATH (/proc)?/[0-9]+/.*$' <<<"$output"
# We can only guess /proc/self/exe for compiled pathrs-cmd binaries.
if is-compiled "$PATHRS_CMD"; then
grep -Fx "LINK-TARGET $exepath" <<<"$output"
fi
dummyfile="$(setup_tmpdir)/dummyfile"
touch "$dummyfile"
pathrs-cmd procfs --base self readlink fd/100 100>"$dummyfile"
[ "$status" -eq 0 ]
grep -Fx "LINK-TARGET $dummyfile" <<<"$output"
}
@test "procfs --base thread-self readlink" {
exepath="$(readlink -f "$PATHRS_CMD")"
pathrs-cmd procfs --base thread-self readlink exe
[ "$status" -eq 0 ]
! grep -E '^FILE-PATH (/proc)?/[0-9]+/.*$' <<<"$output"
# We can only guess /proc/self/exe for compiled pathrs-cmd binaries.
if is-compiled "$PATHRS_CMD"; then
grep -Fx "LINK-TARGET $exepath" <<<"$output"
fi
dummyfile="$(setup_tmpdir)/dummyfile"
touch "$dummyfile"
pathrs-cmd procfs --base thread-self readlink fd/100 100>"$dummyfile"
[ "$status" -eq 0 ]
grep -Fx "LINK-TARGET $dummyfile" <<<"$output"
}
# Make sure that thread-self and self are actually handled differently.
@test "procfs readlink [self != thread-self]" {
# This is a little ugly, but if we get ENOENT from trying to *resolve*
# $base/task then we know we are in thread-self. Unfortunately, readlinkat
# also returns ENOENT if the target is not a symlink so we need to check
# whether the error is coming from readlinkat as well.
pathrs-cmd procfs --base self readlink task
check-errno ENOENT
[[ "$output" == *"error:"*"readlinkat"* ]] # Make sure the error is from readlinkat(2).
pathrs-cmd procfs --base thread-self readlink task
check-errno ENOENT
[[ "$output" != *"error:"*"readlinkat"* ]] # Make sure the error is NOT from readlinkat(2).
}
@test "procfs readlink [non-symlink]" {
pathrs-cmd procfs readlink uptime
check-errno ENOENT
[[ "$output" == *"error:"*"readlinkat"* ]] # Make sure the error is from readlinkat(2).
pathrs-cmd procfs --base root readlink sys/fs/overflowuid
check-errno ENOENT
[[ "$output" == *"error:"*"readlinkat"* ]] # Make sure the error is from readlinkat(2).
pathrs-cmd procfs --base pid=1 readlink stat
check-errno ENOENT
[[ "$output" == *"error:"*"readlinkat"* ]] # Make sure the error is from readlinkat(2).
pathrs-cmd procfs --base self readlink status
check-errno ENOENT
[[ "$output" == *"error:"*"readlinkat"* ]] # Make sure the error is from readlinkat(2).
pathrs-cmd procfs --base thread-self readlink stack
check-errno ENOENT
[[ "$output" == *"error:"*"readlinkat"* ]] # Make sure the error is from readlinkat(2).
}
|