* Copyright (C) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <pthread.h>
#include <fcntl.h>
#include <stdint.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include <musl_log.h>
#include <atomic.h>
#include <dirent.h>
#include <sys/types.h>
#include <errno.h>
#include "functionalext.h"
#define DEV_NULL_PATH "/dev/null"
#define DEBUG_SIGNAL (42)
#define ONE (1)
#define ZERO (0)
#define TWO (2)
#define THREE (3)
#define DIRECTORY_PATH "/data/log/faultlog/temp"
#define FDSAN_SEARCH_STRING "DEBUG SIGNAL(FDSAN)"
#define BADFD_SEARCH_STRING "EBADF:"
#define TEMP_FD_0 (0)
#define TEMP_FD_1 (1)
#define TEMP_FD_2 (2)
#define TEMP_FD_3 (3)
#define TEMP_FD_4 (4)
#define TEMP_FD_5 (5)
#define TEMP_FD_6 (6)
#define INVALID_TAG_999 (999)
#define INVALID_TAG_998 (998)
#define TEMP_TAG_99 (99)
void* thread_func(void* arg)
{
for (int i = ZERO; i < THREE; i++) {
fdsan_exchange_owner_tag((int)arg, INVALID_TAG_999, INVALID_TAG_998);
}
return NULL;
}
#define MAX_PATH_LENGTH (1024)
#define NOT_FOUND (0)
#define FOUND (1)
int contains_string(FILE *file, const char *search_string)
{
char line[1024];
while (fgets(line, sizeof(line), file) != NULL) {
if (strstr(line, search_string) != NULL) {
return FOUND;
}
}
return NOT_FOUND;
}
int count_string_in_directory(const char *dir_path, const char *search_string1, const char *search_string2)
{
DIR *dir = opendir(dir_path);
if (dir == NULL) {
t_error("can not open dir");
return -1;
}
struct dirent *entry;
int count = ZERO;
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == ZERO || strcmp(entry->d_name, "..") == 0) {
continue;
}
char file_path[MAX_PATH_LENGTH];
(void)snprintf(file_path, sizeof(file_path), "%s/%s", dir_path, entry->d_name);
FILE *file = fopen(file_path, "r");
if (file != NULL) {
if (contains_string(file, search_string1) && contains_string(file, search_string2)) {
count++;
}
fclose(file);
}
}
closedir(dir);
return count;
}
void wait_until_signal(void)
{
sigset_t set;
sigemptyset(&set);
sigaddset(&set, DEBUG_SIGNAL);
struct timespec timeout;
timeout.tv_sec = 0;
timeout.tv_nsec = 500000000;
(void)sigtimedwait(&set, NULL, &timeout);
}
#define TEMP_LENGTH (256)
#define RIGHT_RESULT (1)
void check_same_fd_same_time_fdsan_signal_once(void)
{
(void)system("rm -rf /data/log/faultlog/temp/*");
pthread_t thread1, thread2;
int result = pthread_create(&thread1, NULL, thread_func, (void *)TEMP_FD_0);
if (result != 0) {
t_error("check_fdsan_signal_once pthread_create1 failed result=%d\n", result);
return;
}
result = pthread_create(&thread2, NULL, thread_func, (void *)TEMP_FD_0);
if (result != 0) {
t_error("check_fdsan_signal_once pthread_create2 failed result=%d\n", result);
return;
}
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pid_t pid = getpid();
char search_string[TEMP_LENGTH];
(void)sprintf(search_string, "Pid:%d", pid);
wait_until_signal();
result = count_string_in_directory(DIRECTORY_PATH, search_string, FDSAN_SEARCH_STRING);
if (result != RIGHT_RESULT) {
t_error("The target string '%s' appears in %d files\n", search_string, result);
}
}
void check_same_fd_diff_time_fdsan_signal_once(void)
{
(void)system("rm -rf /data/log/faultlog/temp/*");
fdsan_exchange_owner_tag(TEMP_FD_1, INVALID_TAG_999, INVALID_TAG_998);
fdsan_exchange_owner_tag(TEMP_FD_1, INVALID_TAG_999, INVALID_TAG_998);
pid_t pid = getpid();
char search_string[TEMP_LENGTH];
(void)sprintf(search_string, "Pid:%d", pid);
wait_until_signal();
int result = count_string_in_directory(DIRECTORY_PATH, search_string, FDSAN_SEARCH_STRING);
if (result != RIGHT_RESULT) {
t_error("The target string '%s' appears in %d files\n", search_string, result);
}
}
void check_diff_fd_same_time_fdsan_signal_twice(void)
{
(void)system("rm -rf /data/log/faultlog/temp/*");
pthread_t thread1, thread2;
int result = pthread_create(&thread1, NULL, thread_func, (void *)TEMP_FD_2);
if (result != 0) {
t_error("check_fdsan_signal_once pthread_create1 failed result=%d\n", result);
return;
}
result = pthread_create(&thread2, NULL, thread_func, (void *)TEMP_FD_3);
if (result != 0) {
t_error("check_fdsan_signal_once pthread_create2 failed result=%d\n", result);
return;
}
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pid_t pid = getpid();
char search_string[TEMP_LENGTH];
(void)sprintf(search_string, "Pid:%d", pid);
wait_until_signal();
result = count_string_in_directory(DIRECTORY_PATH, search_string, FDSAN_SEARCH_STRING);
if (result != TWO) {
t_error("The target string '%s' appears in %d files\n", search_string, result);
}
}
void check_diff_fd_diff_time_fdsan_signal_twice(void)
{
(void)system("rm -rf /data/log/faultlog/temp/*");
fdsan_exchange_owner_tag(TEMP_FD_4, INVALID_TAG_999, INVALID_TAG_998);
fdsan_exchange_owner_tag(TEMP_FD_5, INVALID_TAG_999, INVALID_TAG_998);
pid_t pid = getpid();
char search_string[TEMP_LENGTH];
(void)sprintf(search_string, "Pid:%d", pid);
wait_until_signal();
int result = count_string_in_directory(DIRECTORY_PATH, search_string, FDSAN_SEARCH_STRING);
if (result != TWO) {
t_error("The target string '%s' appears in %d files\n", search_string, result);
}
}
void check_bad_fd(void)
{
(void)system("rm -rf /data/log/faultlog/temp/*");
int fd = open("/data/local/tmp/newfile.txt", O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);
if (fd == -1) {
t_error("check_bad_fd open failed errno=%d\n", errno);
return;
}
fdsan_exchange_owner_tag(fd, ZERO, TEMP_TAG_99);
fdsan_close_with_tag(fd, TEMP_TAG_99);
fdsan_close_with_tag(fd, TEMP_TAG_99);
fdsan_close_with_tag(fd, TEMP_TAG_99);
pid_t pid = getpid();
char search_string[TEMP_LENGTH];
(void)sprintf(search_string, "Pid:%d", pid);
wait_until_signal();
int result = count_string_in_directory(DIRECTORY_PATH, search_string, BADFD_SEARCH_STRING);
if (result == ZERO) {
t_error("The target string '%s' appears in %d files\n", search_string, result);
}
}
int main(void)
{
FILE *fp = popen("uname", "r");
char buffer[128];
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
printf("uname result %s", buffer);
if (strstr(buffer, "Linux")) {
return ZERO;
}
}
check_same_fd_same_time_fdsan_signal_once();
check_same_fd_diff_time_fdsan_signal_once();
check_diff_fd_same_time_fdsan_signal_twice();
check_diff_fd_diff_time_fdsan_signal_twice();
check_bad_fd();
return t_status;
}