• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *	http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <dlfcn.h>
16 #include <link.h>
17 #include <pthread.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <sys/ioctl.h>
24 #include <sys/wait.h>
25 #include <sys/prctl.h>
26 #include <sys/mman.h>
27 #include <unistd.h>
28 
29 #include "test.h"
30 #define MAX_BUF 256
31 #define HEX_TERM 16
32 #define RELRO_INDEX 3
33 #define RELRO_NUM 1
34 #define BUFFER_SIZE 1024
35 #define PID_BUFFER_SIZE 128
36 
37 const char *g_libPath = "/system/lib64/libc++.so";
38 const char *g_keylog = "ro_seal report: provition_type: 1, reason: 2, filename: /system/lib64/libc++.so";
39 
dlclose_check(unsigned long start,unsigned long end,const char * so)40 int dlclose_check(unsigned long start, unsigned long end, const char *so)
41 {
42     if (mprotect((void *)start, end - start, PROT_READ | PROT_WRITE) == 0) {
43         t_error("the relro segment of %s should be readonly and cannot be changed\n", so);
44         return 0;
45     }
46     int fd = open(so, O_RDONLY);
47     if (fd < 0) {
48         t_error("open file %s should be success but failed, errno %d\n", so, errno);
49         return 0;
50     }
51     if (mmap((void *)start, end - start, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, 0) != MAP_FAILED) {
52         t_error("mmap to the fixed region of so %s, start: %zu, end: %zu should fail but success\n",
53             so, start, end);
54         close(fd);
55         munmap((void *)start, end - start);
56         return 0;
57     }
58     close(fd);
59     return 1;
60 }
61 
check_load_permission(const char * so,int is_dlclose)62 int check_load_permission(const char *so, int is_dlclose)
63 {
64     int pid = getpid();
65     const char *so_name = NULL;
66     char path[MAX_BUF] = { 0 };
67     if (sprintf(path, "/proc/%d/maps", pid) < 0) {
68        t_error("Failed in sprintf: %s\n", strerror(errno));
69     }
70     FILE* fp = fopen(path, "r");
71     if (fp == NULL) {
72         return 0;
73     }
74     if (strchr(so, '/')) {
75         so_name = strrchr(so, '/') + 1;
76     }
77     char buffer[MAX_BUF] = { 0 };
78     unsigned long start = 0;
79     unsigned long end = 0;
80     int seg_num = 0;
81     while (fgets(buffer, MAX_BUF, fp) != NULL) {
82         if (strstr(buffer, so_name) != NULL) {
83             char *end_ptr;
84             seg_num++;
85             if (is_dlclose && seg_num == RELRO_NUM) {
86                 start = strtoul(buffer, &end_ptr, HEX_TERM);
87                 end = strtoul(end_ptr + 1, &end_ptr, HEX_TERM);
88             }
89             if (!is_dlclose && seg_num == RELRO_INDEX) {
90                 start = strtoul(buffer, &end_ptr, HEX_TERM);
91                 end = strtoul(end_ptr + 1, &end_ptr, HEX_TERM);
92             }
93         }
94     }
95     fclose(fp);
96     if (start != 0 && end != 0 && is_dlclose && seg_num == RELRO_NUM) {
97         return dlclose_check(start, end, so);
98     } else if (start != 0 && end != 0 && !is_dlclose && seg_num >= RELRO_INDEX) {
99         mprotect((void*)start, end - start, PROT_READ | PROT_WRITE);
100         return 1;
101     }
102     return 0;
103 }
104 
test_lib(void)105 void test_lib(void)
106 {
107     void *handle = dlopen(g_libPath, RTLD_LAZY);
108     if (!handle) {
109         t_error("dlopen(name=%s, mode=%d) failed: %s\n", g_libPath, RTLD_LAZY, dlerror());
110     }
111 
112     if (!check_load_permission(g_libPath, 0)) {
113         t_error("check_load_permission failed for so %s\n", g_libPath);
114     }
115     dlclose(handle);
116 }
117 
main(int argc,char * argv[])118 int main(int argc, char* argv[])
119 {
120     int pipe_fd[2];
121     pid_t pid;
122     test_lib();
123 
124     if (pipe(pipe_fd) == -1) {
125         t_error("create pipe failed\n");
126         return t_status;
127     }
128     pid = fork();
129     if (pid == -1) {
130         close(pipe_fd[0]);
131         close(pipe_fd[1]);
132         t_error("fork failed\n");
133         return t_status;
134     }
135 
136     if (pid == 0) {
137         close(pipe_fd[0]);
138         dup2(pipe_fd[1], STDOUT_FILENO);
139         close(pipe_fd[1]);
140 
141         execlp("dmesg", "dmesg", NULL);
142         _exit(0);
143     } else {
144         close(pipe_fd[1]);
145         FILE *pipe_read = fdopen(pipe_fd[0], "r");
146         if (pipe_read == NULL) {
147             t_error("Failed to open read pipe fd, errno %d\n", errno);
148             close(pipe_fd[0]);
149             return t_status;
150         }
151         char buffer[BUFFER_SIZE];
152         char pid_buffer[PID_BUFFER_SIZE] = { 0 };
153         int check_success = 0;
154         if (sprintf(pid_buffer, "pid=%d", getpid()) < 0) {
155             t_error("Failed in sprintf: %s\n", strerror(errno));
156         }
157         while (fgets(buffer, BUFFER_SIZE, pipe_read) != NULL) {
158             if (strstr(buffer, g_keylog) && strstr(buffer, pid_buffer)) {
159                 check_success = 1;
160                 break;
161             }
162         }
163         if (!check_success) {
164             t_error("don't find correct log in dmesg: %s\n", g_keylog);
165         }
166         waitpid(pid, NULL, 0);
167         fclose(pipe_read);
168     }
169     return t_status;
170 }
171 
172