• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 
16 #include "volume/process.h"
17 
18 #include <csignal>
19 #include <dirent.h>
20 #include <unistd.h>
21 
22 #include "storage_service_errno.h"
23 #include "storage_service_log.h"
24 #include "utils/string_utils.h"
25 
26 using namespace std;
27 
28 namespace OHOS {
29 namespace StorageDaemon {
Process(std::string path)30 Process::Process(std::string path)
31 {
32     path_ = path;
33 }
34 
GetPids()35 std::unordered_set<pid_t> Process::GetPids()
36 {
37     return pids_;
38 }
39 
GetPath()40 std::string Process::GetPath()
41 {
42     return path_;
43 }
44 
Readlink(std::string path)45 std::string Process::Readlink(std::string path)
46 {
47     int len = 0;
48     int size = 0;
49     int growlen = 64;
50     std::string buf;
51 
52     do {
53         size += growlen;
54         buf.assign(std::string(size, '\0'));
55         len = readlink(path.c_str(), buf.data(), size);
56         if (len == -1) {
57             return "";
58         }
59     } while (size <= len);
60 
61     return buf;
62 }
63 
CheckSubDir(std::string subdir)64 bool Process::CheckSubDir(std::string subdir)
65 {
66     const char *p = path_.c_str();
67     const char *q = subdir.c_str();
68 
69     while (*p != '\0' && *q != '\0') {
70         if (*p != *q) {
71             return false;
72         }
73         p++;
74         q++;
75     }
76 
77     if (*p == '\0' && *q == '\0') {
78         return true;
79     }
80 
81     if (*p == '\0' && *q == '/') {
82         return true;
83     }
84 
85     return false;
86 }
87 
CheckMaps(std::string pidPath)88 bool Process::CheckMaps(std::string pidPath)
89 {
90     char *buf = nullptr;
91     size_t lineLen = 0;
92     std::string line;
93     auto path = StringPrintf("%s/maps", pidPath.c_str());
94     FILE *file = fopen(path.c_str(), "r");
95     if (file == nullptr) {
96         return false;
97     }
98 
99     while (getline(&buf, &lineLen, file) > 0) {
100         line = buf;
101         std::string::size_type pos = line.find('/');
102         if (pos != line.npos) {
103             line = line.substr(pos);
104             if (CheckSubDir(line)) {
105                 LOGI("Found map in %{public}s", pidPath.c_str());
106                 (void)fclose(file);
107                 free(buf);
108                 buf = nullptr;
109                 return true;
110             }
111         }
112     }
113 
114     (void)fclose(file);
115     free(buf);
116     buf = nullptr;
117     return false;
118 }
119 
CheckSymlink(std::string path)120 bool Process::CheckSymlink(std::string path)
121 {
122     std::string link = Readlink(path);
123     if (!link.empty() && CheckSubDir(link)) {
124         return true;
125     }
126     return false;
127 }
128 
CheckFds(std::string pidPath)129 bool Process::CheckFds(std::string pidPath)
130 {
131     struct dirent *dirEntry;
132     auto path = StringPrintf("%s/fd", pidPath.c_str());
133     DIR *dir = opendir(path.c_str());
134     if (dir == nullptr) {
135         return E_ERR;
136     }
137 
138     while ((dirEntry = readdir(dir)) != nullptr) {
139         if (dirEntry->d_type != DT_LNK) continue;
140         if (CheckSymlink(path + "/" + dirEntry->d_name)) {
141             (void)closedir(dir);
142             return true;
143         }
144     }
145 
146     (void)closedir(dir);
147     return false;
148 }
149 
UpdatePidByPath()150 int32_t Process::UpdatePidByPath()
151 {
152     struct dirent *dirEntry;
153     DIR *dir = opendir("/proc");
154     if (dir == nullptr) {
155         return E_ERR;
156     }
157 
158     while ((dirEntry = readdir(dir)) != nullptr) {
159         if (dirEntry->d_type != DT_DIR) continue;
160         pid_t pid = atoi(dirEntry->d_name);
161         if (pid > 0 && pid != getprocpid()) {
162             std::string pidPath = StringPrintf("/proc/%d", pid);
163             if (CheckMaps(pidPath)
164                 || CheckSymlink(pidPath + "/cwd")
165                 || CheckSymlink(pidPath + "/root")
166                 || CheckSymlink(pidPath + "/exe")) {
167                 pids_.insert(pid);
168             }
169         }
170     }
171 
172     (void)closedir(dir);
173     return E_OK;
174 }
175 
KillProcess(int signal)176 void Process::KillProcess(int signal)
177 {
178     if (signal == 0) {
179         return;
180     }
181 
182     for (const auto& pid : pids_) {
183         LOGI("KILL PID %{public}d", pid);
184         kill(pid, signal);
185     }
186     pids_.clear();
187 }
188 } // StorageDaemon
189 } // OHOS
190