162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#define _GNU_SOURCE 462306a36Sopenharmony_ci#include <errno.h> 562306a36Sopenharmony_ci#include <fcntl.h> 662306a36Sopenharmony_ci#include <inttypes.h> 762306a36Sopenharmony_ci#include <limits.h> 862306a36Sopenharmony_ci#include <linux/types.h> 962306a36Sopenharmony_ci#include <sched.h> 1062306a36Sopenharmony_ci#include <signal.h> 1162306a36Sopenharmony_ci#include <stdbool.h> 1262306a36Sopenharmony_ci#include <stdio.h> 1362306a36Sopenharmony_ci#include <stdlib.h> 1462306a36Sopenharmony_ci#include <string.h> 1562306a36Sopenharmony_ci#include <syscall.h> 1662306a36Sopenharmony_ci#include <sys/mount.h> 1762306a36Sopenharmony_ci#include <sys/prctl.h> 1862306a36Sopenharmony_ci#include <sys/wait.h> 1962306a36Sopenharmony_ci#include <unistd.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include "pidfd.h" 2262306a36Sopenharmony_ci#include "../kselftest.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic int safe_int(const char *numstr, int *converted) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci char *err = NULL; 2762306a36Sopenharmony_ci long sli; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci errno = 0; 3062306a36Sopenharmony_ci sli = strtol(numstr, &err, 0); 3162306a36Sopenharmony_ci if (errno == ERANGE && (sli == LONG_MAX || sli == LONG_MIN)) 3262306a36Sopenharmony_ci return -ERANGE; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci if (errno != 0 && sli == 0) 3562306a36Sopenharmony_ci return -EINVAL; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci if (err == numstr || *err != '\0') 3862306a36Sopenharmony_ci return -EINVAL; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci if (sli > INT_MAX || sli < INT_MIN) 4162306a36Sopenharmony_ci return -ERANGE; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci *converted = (int)sli; 4462306a36Sopenharmony_ci return 0; 4562306a36Sopenharmony_ci} 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistatic int char_left_gc(const char *buffer, size_t len) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci size_t i; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci for (i = 0; i < len; i++) { 5262306a36Sopenharmony_ci if (buffer[i] == ' ' || 5362306a36Sopenharmony_ci buffer[i] == '\t') 5462306a36Sopenharmony_ci continue; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci return i; 5762306a36Sopenharmony_ci } 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci return 0; 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic int char_right_gc(const char *buffer, size_t len) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci int i; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci for (i = len - 1; i >= 0; i--) { 6762306a36Sopenharmony_ci if (buffer[i] == ' ' || 6862306a36Sopenharmony_ci buffer[i] == '\t' || 6962306a36Sopenharmony_ci buffer[i] == '\n' || 7062306a36Sopenharmony_ci buffer[i] == '\0') 7162306a36Sopenharmony_ci continue; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci return i + 1; 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci return 0; 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic char *trim_whitespace_in_place(char *buffer) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci buffer += char_left_gc(buffer, strlen(buffer)); 8262306a36Sopenharmony_ci buffer[char_right_gc(buffer, strlen(buffer))] = '\0'; 8362306a36Sopenharmony_ci return buffer; 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic pid_t get_pid_from_fdinfo_file(int pidfd, const char *key, size_t keylen) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci int ret; 8962306a36Sopenharmony_ci char path[512]; 9062306a36Sopenharmony_ci FILE *f; 9162306a36Sopenharmony_ci size_t n = 0; 9262306a36Sopenharmony_ci pid_t result = -1; 9362306a36Sopenharmony_ci char *line = NULL; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", pidfd); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci f = fopen(path, "re"); 9862306a36Sopenharmony_ci if (!f) 9962306a36Sopenharmony_ci return -1; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci while (getline(&line, &n, f) != -1) { 10262306a36Sopenharmony_ci char *numstr; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci if (strncmp(line, key, keylen)) 10562306a36Sopenharmony_ci continue; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci numstr = trim_whitespace_in_place(line + 4); 10862306a36Sopenharmony_ci ret = safe_int(numstr, &result); 10962306a36Sopenharmony_ci if (ret < 0) 11062306a36Sopenharmony_ci goto out; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci break; 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ciout: 11662306a36Sopenharmony_ci free(line); 11762306a36Sopenharmony_ci fclose(f); 11862306a36Sopenharmony_ci return result; 11962306a36Sopenharmony_ci} 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ciint main(int argc, char **argv) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci int pidfd = -1, ret = 1; 12462306a36Sopenharmony_ci pid_t pid; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci ksft_set_plan(3); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci pidfd = sys_pidfd_open(-1, 0); 12962306a36Sopenharmony_ci if (pidfd >= 0) { 13062306a36Sopenharmony_ci ksft_print_msg( 13162306a36Sopenharmony_ci "%s - succeeded to open pidfd for invalid pid -1\n", 13262306a36Sopenharmony_ci strerror(errno)); 13362306a36Sopenharmony_ci goto on_error; 13462306a36Sopenharmony_ci } 13562306a36Sopenharmony_ci ksft_test_result_pass("do not allow invalid pid test: passed\n"); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci pidfd = sys_pidfd_open(getpid(), 1); 13862306a36Sopenharmony_ci if (pidfd >= 0) { 13962306a36Sopenharmony_ci ksft_print_msg( 14062306a36Sopenharmony_ci "%s - succeeded to open pidfd with invalid flag value specified\n", 14162306a36Sopenharmony_ci strerror(errno)); 14262306a36Sopenharmony_ci goto on_error; 14362306a36Sopenharmony_ci } 14462306a36Sopenharmony_ci ksft_test_result_pass("do not allow invalid flag test: passed\n"); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci pidfd = sys_pidfd_open(getpid(), 0); 14762306a36Sopenharmony_ci if (pidfd < 0) { 14862306a36Sopenharmony_ci ksft_print_msg("%s - failed to open pidfd\n", strerror(errno)); 14962306a36Sopenharmony_ci goto on_error; 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci ksft_test_result_pass("open a new pidfd test: passed\n"); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci pid = get_pid_from_fdinfo_file(pidfd, "Pid:", sizeof("Pid:") - 1); 15462306a36Sopenharmony_ci ksft_print_msg("pidfd %d refers to process with pid %d\n", pidfd, pid); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci ret = 0; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cion_error: 15962306a36Sopenharmony_ci if (pidfd >= 0) 16062306a36Sopenharmony_ci close(pidfd); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci return !ret ? ksft_exit_pass() : ksft_exit_fail(); 16362306a36Sopenharmony_ci} 164