162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * This test covers the anonymous VMA naming functionality through prctl calls 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <errno.h> 762306a36Sopenharmony_ci#include <sys/prctl.h> 862306a36Sopenharmony_ci#include <stdio.h> 962306a36Sopenharmony_ci#include <stdlib.h> 1062306a36Sopenharmony_ci#include <sys/mman.h> 1162306a36Sopenharmony_ci#include <string.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include "../kselftest_harness.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define AREA_SIZE 1024 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define GOOD_NAME "goodname" 1862306a36Sopenharmony_ci#define BAD_NAME "badname\1" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#ifndef PR_SET_VMA 2162306a36Sopenharmony_ci#define PR_SET_VMA 0x53564d41 2262306a36Sopenharmony_ci#define PR_SET_VMA_ANON_NAME 0 2362306a36Sopenharmony_ci#endif 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ciint rename_vma(unsigned long addr, unsigned long size, char *name) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci int res; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci res = prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, addr, size, name); 3162306a36Sopenharmony_ci if (res < 0) 3262306a36Sopenharmony_ci return -errno; 3362306a36Sopenharmony_ci return res; 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ciint was_renaming_successful(char *target_name, unsigned long ptr) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci FILE *maps_file; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci char line_buf[512], name[128], mode[8]; 4162306a36Sopenharmony_ci unsigned long start_addr, end_addr, offset; 4262306a36Sopenharmony_ci unsigned int major_id, minor_id, node_id; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci char target_buf[128]; 4562306a36Sopenharmony_ci int res = 0, sscanf_res; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci // The entry name in maps will be in format [anon:<target_name>] 4862306a36Sopenharmony_ci sprintf(target_buf, "[anon:%s]", target_name); 4962306a36Sopenharmony_ci maps_file = fopen("/proc/self/maps", "r"); 5062306a36Sopenharmony_ci if (!maps_file) { 5162306a36Sopenharmony_ci printf("## /proc/self/maps file opening error\n"); 5262306a36Sopenharmony_ci return 0; 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci // Parse the maps file to find the entry we renamed 5662306a36Sopenharmony_ci while (fgets(line_buf, sizeof(line_buf), maps_file)) { 5762306a36Sopenharmony_ci sscanf_res = sscanf(line_buf, "%lx-%lx %7s %lx %u:%u %u %s", &start_addr, 5862306a36Sopenharmony_ci &end_addr, mode, &offset, &major_id, 5962306a36Sopenharmony_ci &minor_id, &node_id, name); 6062306a36Sopenharmony_ci if (sscanf_res == EOF) { 6162306a36Sopenharmony_ci res = 0; 6262306a36Sopenharmony_ci printf("## EOF while parsing the maps file\n"); 6362306a36Sopenharmony_ci break; 6462306a36Sopenharmony_ci } 6562306a36Sopenharmony_ci if (!strcmp(name, target_buf) && start_addr == ptr) { 6662306a36Sopenharmony_ci res = 1; 6762306a36Sopenharmony_ci break; 6862306a36Sopenharmony_ci } 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci fclose(maps_file); 7162306a36Sopenharmony_ci return res; 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ciFIXTURE(vma) { 7562306a36Sopenharmony_ci void *ptr_anon, *ptr_not_anon; 7662306a36Sopenharmony_ci}; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ciFIXTURE_SETUP(vma) { 7962306a36Sopenharmony_ci self->ptr_anon = mmap(NULL, AREA_SIZE, PROT_READ | PROT_WRITE, 8062306a36Sopenharmony_ci MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 8162306a36Sopenharmony_ci ASSERT_NE(self->ptr_anon, NULL); 8262306a36Sopenharmony_ci self->ptr_not_anon = mmap(NULL, AREA_SIZE, PROT_READ | PROT_WRITE, 8362306a36Sopenharmony_ci MAP_PRIVATE, 0, 0); 8462306a36Sopenharmony_ci ASSERT_NE(self->ptr_not_anon, NULL); 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ciFIXTURE_TEARDOWN(vma) { 8862306a36Sopenharmony_ci munmap(self->ptr_anon, AREA_SIZE); 8962306a36Sopenharmony_ci munmap(self->ptr_not_anon, AREA_SIZE); 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ciTEST_F(vma, renaming) { 9362306a36Sopenharmony_ci TH_LOG("Try to rename the VMA with correct parameters"); 9462306a36Sopenharmony_ci EXPECT_GE(rename_vma((unsigned long)self->ptr_anon, AREA_SIZE, GOOD_NAME), 0); 9562306a36Sopenharmony_ci EXPECT_TRUE(was_renaming_successful(GOOD_NAME, (unsigned long)self->ptr_anon)); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci TH_LOG("Try to pass invalid name (with non-printable character \\1) to rename the VMA"); 9862306a36Sopenharmony_ci EXPECT_EQ(rename_vma((unsigned long)self->ptr_anon, AREA_SIZE, BAD_NAME), -EINVAL); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci TH_LOG("Try to rename non-anonymous VMA"); 10162306a36Sopenharmony_ci EXPECT_EQ(rename_vma((unsigned long) self->ptr_not_anon, AREA_SIZE, GOOD_NAME), -EINVAL); 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ciTEST_HARNESS_MAIN 105