• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "js_process.h"
17 #include <sys/resource.h>
18 #include <sys/time.h>
19 #include <uv.h>
20 
21 #include "process_helper.h"
22 namespace OHOS::JsSysModule::Process {
23 
24     using namespace Commonlibrary::Platform;
25     namespace {
26         constexpr int NUM_OF_DATA = 4;
27         constexpr int PER_USER_RANGE = 100000;
28         constexpr int32_t NAPI_RETURN_ZERO = 0;
29         constexpr int32_t NAPI_RETURN_ONE = 1;
30     }
31     constexpr int FIRST_APPLICATION_UID = 10000; // 10000 : bundleId lower limit
32     constexpr int LAST_APPLICATION_UID = 65535; // 65535 : bundleId upper limit
33     thread_local std::multimap<std::string, napi_ref> eventMap;
34     static std::mutex g_sharedTimedMutex;
35     thread_local std::map<napi_ref, napi_ref> pendingUnHandledRejections;
36     // support g_events
37     thread_local std::string g_events = "UnHandleRejection";
38 
GetUid(napi_env env) const39     napi_value Process::GetUid(napi_env env) const
40     {
41         napi_value result = nullptr;
42         auto processGetuid = static_cast<uint32_t>(getuid());
43         NAPI_CALL(env, napi_create_uint32(env, processGetuid, &result));
44         return result;
45     }
46 
GetGid(napi_env env) const47     napi_value Process::GetGid(napi_env env) const
48     {
49         napi_value result = nullptr;
50         auto processGetgid = static_cast<uint32_t>(getgid());
51         NAPI_CALL(env, napi_create_uint32(env, processGetgid, &result));
52         return result;
53     }
54 
GetEUid(napi_env env) const55     napi_value Process::GetEUid(napi_env env) const
56     {
57         napi_value result = nullptr;
58         auto processGeteuid = static_cast<uint32_t>(geteuid());
59         NAPI_CALL(env, napi_create_uint32(env, processGeteuid, &result));
60         return result;
61     }
62 
GetEGid(napi_env env) const63     napi_value Process::GetEGid(napi_env env) const
64     {
65         napi_value result = nullptr;
66         auto processGetegid = static_cast<uint32_t>(getegid());
67         NAPI_CALL(env, napi_create_uint32(env, processGetegid, &result));
68         return result;
69     }
70 
GetGroups(napi_env env) const71     napi_value Process::GetGroups(napi_env env) const
72     {
73         napi_value result = nullptr;
74         int progroups = getgroups(0, nullptr);
75         if (progroups == -1) {
76             napi_throw_error(env, "-1", "getgroups initialize failed");
77             return nullptr;
78         }
79         std::vector<gid_t> pgrous(progroups);
80         progroups = getgroups(progroups, pgrous.data());
81         if (progroups == -1) {
82             napi_throw_error(env, "-1", "getgroups");
83             return nullptr;
84         }
85         pgrous.resize(static_cast<size_t>(progroups));
86         gid_t proegid = getegid();
87         if (std::find(pgrous.begin(), pgrous.end(), proegid) == pgrous.end()) {
88             pgrous.push_back(proegid);
89         }
90         std::vector<uint32_t> array;
91         for (auto iter = pgrous.begin(); iter != pgrous.end(); iter++) {
92             auto receive = static_cast<uint32_t>(*iter);
93             array.push_back(receive);
94         }
95         NAPI_CALL(env, napi_create_array(env, &result));
96         size_t len = array.size();
97         for (size_t i = 0; i < len; i++) {
98             napi_value numvalue = nullptr;
99             NAPI_CALL(env, napi_create_uint32(env, array[i], &numvalue));
100             NAPI_CALL(env, napi_set_element(env, result, i, numvalue));
101         }
102         return result;
103     }
104 
GetPid(napi_env env) const105     napi_value Process::GetPid(napi_env env) const
106     {
107         napi_value result = nullptr;
108         auto proPid = static_cast<int32_t>(getpid());
109         napi_create_int32(env, proPid, &result);
110         return result;
111     }
112 
GetPpid(napi_env env) const113     napi_value Process::GetPpid(napi_env env) const
114     {
115         napi_value result = nullptr;
116         auto proPpid = static_cast<int32_t>(getppid());
117         napi_create_int32(env, proPpid, &result);
118         return result;
119     }
120 
Chdir(napi_env env,napi_value args) const121     void Process::Chdir(napi_env env, napi_value args) const
122     {
123         size_t prolen = 0;
124         if (napi_get_value_string_utf8(env, args, nullptr, 0, &prolen) != napi_ok) {
125             HILOG_ERROR("Process:: can not get args size");
126             return;
127         }
128         std::string result = "";
129         result.reserve(prolen + 1);
130         result.resize(prolen);
131         if (napi_get_value_string_utf8(env, args, result.data(), prolen + 1, &prolen) != napi_ok) {
132             HILOG_ERROR("Process:: can not get args value");
133             return;
134         }
135         int proerr = 0;
136         proerr = uv_chdir(result.c_str());
137         if (proerr) {
138             napi_throw_error(env, "-1", "chdir");
139             return;
140         }
141     }
142 
Kill(napi_env env,napi_value signal,napi_value proid)143     napi_value Process::Kill(napi_env env, napi_value signal, napi_value proid)
144     {
145         int32_t pid = 0;
146         int32_t sig = 0;
147         napi_get_value_int32(env, proid, &pid);
148         napi_get_value_int32(env, signal, &sig);
149         uv_pid_t ownPid = uv_os_getpid();
150         // 64:The maximum valid signal value is 64.
151         if (sig > 64 && (!pid || pid == -1 || pid == ownPid || pid == -ownPid)) {
152             napi_throw_error(env, "0", "process exit");
153             return nullptr;
154         }
155         bool flag = false;
156         int err = uv_kill(pid, sig);
157         if (!err) {
158             flag = true;
159         }
160         napi_value result = nullptr;
161         NAPI_CALL(env, napi_get_boolean(env, flag, &result));
162         return result;
163     }
164 
Uptime(napi_env env) const165     napi_value Process::Uptime(napi_env env) const
166     {
167         napi_value result = nullptr;
168         double runsystime = 0.0;
169         auto systimer = GetSysTimer();
170         if (systimer > 0) {
171             runsystime = static_cast<double>(systimer);
172             NAPI_CALL(env, napi_create_double(env, runsystime, &result));
173         } else {
174             napi_throw_error(env, "-1", "Failed to get systimer");
175             return nullptr;
176         }
177         return result;
178     }
179 
Exit(napi_env env,napi_value number) const180     void Process::Exit(napi_env env, napi_value number) const
181     {
182         int32_t result = 0;
183         napi_get_value_int32(env, number, &result);
184         ProcessExit(result);
185     }
186 
Cwd(napi_env env) const187     napi_value Process::Cwd(napi_env env) const
188     {
189         napi_value result = nullptr;
190         char buf[260 * NUM_OF_DATA] = { 0 }; // 260:Only numbers path String size is 260.
191         size_t length = sizeof(buf);
192         int err = uv_cwd(buf, &length);
193         if (err) {
194             napi_throw_error(env, "1", "uv_cwd");
195             return nullptr;
196         }
197         napi_create_string_utf8(env, buf, length, &result);
198         return result;
199     }
200 
Abort() const201     void Process::Abort() const
202     {
203         std::abort();
204     }
205 
On(napi_env env,napi_value str,napi_value function)206     void Process::On(napi_env env, napi_value str, napi_value function)
207     {
208         std::string result = "";
209         size_t bufferSize = 0;
210         if (napi_get_value_string_utf8(env, str, nullptr, NAPI_RETURN_ZERO, &bufferSize) != napi_ok) {
211             HILOG_ERROR("Process:: can not get str size");
212             return;
213         }
214         result.reserve(bufferSize + NAPI_RETURN_ONE);
215         result.resize(bufferSize);
216         if (napi_get_value_string_utf8(env, str, result.data(), bufferSize + NAPI_RETURN_ONE,
217                                        &bufferSize) != napi_ok) {
218             HILOG_ERROR("Process:: can not get str value");
219             return;
220         }
221         if (function == nullptr) {
222             HILOG_ERROR("Process:: function is nullptr");
223             return;
224         }
225         napi_ref myCallRef = nullptr;
226         napi_status status = napi_create_reference(env, function, 1, &myCallRef);
227         if (status != napi_ok) {
228             HILOG_ERROR("Process:: napi_create_reference is failed");
229             return;
230         }
231         if (!result.empty()) {
232             size_t pos = g_events.find(result);
233             if (pos == std::string::npos) {
234                 HILOG_ERROR("Process:: illegal event");
235                 return;
236             }
237             std::unique_lock<std::mutex> lock(g_sharedTimedMutex);
238             eventMap.insert(std::make_pair(result, myCallRef));
239         }
240     }
241 
Off(napi_env env,napi_value str)242     napi_value Process::Off(napi_env env, napi_value str)
243     {
244         size_t bufferSize = 0;
245         bool flag = false;
246         if (napi_get_value_string_utf8(env, str, nullptr, 0, &bufferSize) != napi_ok) {
247             HILOG_ERROR("Process:: can not get str size");
248             return nullptr;
249         }
250         std::string result = "";
251         result.reserve(bufferSize + 1);
252         result.resize(bufferSize);
253         if (napi_get_value_string_utf8(env, str, result.data(), bufferSize + 1, &bufferSize) != napi_ok) {
254             HILOG_ERROR("Process:: can not get str value");
255             return nullptr;
256         }
257         std::string temp = "";
258         temp = result;
259         auto iter = eventMap.equal_range(temp);
260         while (iter.first != iter.second) {
261             NAPI_CALL(env, napi_delete_reference(env, iter.first->second));
262             std::unique_lock<std::mutex> lock(g_sharedTimedMutex);
263             iter.first = eventMap.erase(iter.first);
264             flag = true;
265         }
266         napi_value convertResult = nullptr;
267         NAPI_CALL(env, napi_get_boolean(env, flag, &convertResult));
268         return convertResult;
269     }
270 
GetTid(napi_env env) const271     napi_value Process::GetTid(napi_env env) const
272     {
273         napi_value result = nullptr;
274         auto proTid = static_cast<int32_t>(GetThreadId());
275         napi_create_int64(env, proTid, &result);
276         return result;
277     }
278 
IsIsolatedProcess(napi_env env) const279     napi_value Process::IsIsolatedProcess(napi_env env) const
280     {
281         napi_value result = nullptr;
282         bool flag = true;
283         auto prouid = static_cast<int32_t>(getuid());
284         auto uid = prouid % PER_USER_RANGE;
285         if ((uid >= 99000 && uid <= 99999) || // 99999:Only isolateuid numbers between 99000 and 99999.
286             (uid >= 9000 && uid <= 98999)) { // 98999:Only appuid numbers between 9000 and 98999.
287             NAPI_CALL(env, napi_get_boolean(env, flag, &result));
288             return result;
289         }
290         flag = false;
291         NAPI_CALL(env, napi_get_boolean(env, flag, &result));
292         return result;
293     }
294 
IsAppUid(napi_env env,napi_value uid) const295     napi_value Process::IsAppUid(napi_env env, napi_value uid) const
296     {
297         int32_t number = 0;
298         napi_value result = nullptr;
299         bool flag = true;
300         napi_get_value_int32(env, uid, &number);
301         if (number > 0) {
302             const auto appId = number % PER_USER_RANGE;
303             if (appId >= FIRST_APPLICATION_UID && appId <= LAST_APPLICATION_UID) {
304                 napi_get_boolean(env, flag, &result);
305                 return result;
306             }
307         }
308         flag = false;
309         NAPI_CALL(env, napi_get_boolean(env, flag, &result));
310         return result;
311     }
312 
Is64Bit(napi_env env) const313     napi_value Process::Is64Bit(napi_env env) const
314     {
315         napi_value result = nullptr;
316         bool flag = true;
317         auto size = sizeof(char*);
318         flag = (size == NUM_OF_DATA) ? false : true;
319         NAPI_CALL(env, napi_get_boolean(env, flag, &result));
320         return result;
321     }
322 
GetEnvironmentVar(napi_env env,napi_value name) const323     napi_value Process::GetEnvironmentVar(napi_env env, napi_value name) const
324     {
325         napi_value convertResult = nullptr;
326         char buf[260 * NUM_OF_DATA] = { 0 }; // 260:Only numbers path String size is 260.
327         size_t length = sizeof(buf);
328         size_t bufferSize = 0;
329         if (napi_get_value_string_utf8(env, name, nullptr, 0, &bufferSize) != napi_ok) {
330             HILOG_ERROR("Process:: can not get name size");
331             return nullptr;
332         }
333         std::string result = "";
334         result.reserve(bufferSize + 1);
335         result.resize(bufferSize);
336         if (napi_get_value_string_utf8(env, name, result.data(), bufferSize + 1, &bufferSize) != napi_ok) {
337             HILOG_ERROR("Process:: can not get name value");
338             return nullptr;
339         }
340         std::string temp = "";
341         temp = result;
342         auto envNum = uv_os_getenv(temp.c_str(), buf, &length);
343         if (envNum == UV_ENOENT) {
344             NAPI_CALL(env, napi_get_undefined(env, &convertResult));
345             return convertResult;
346         }
347         napi_create_string_utf8(env, buf, strlen(buf), &convertResult);
348         return convertResult;
349     }
350 
GetUidForName(napi_env env,napi_value name) const351     napi_value Process::GetUidForName(napi_env env, napi_value name) const
352     {
353         napi_value convertResult = nullptr;
354         size_t bufferSize = 0;
355         if (napi_get_value_string_utf8(env, name, nullptr, 0, &bufferSize) != napi_ok) {
356             HILOG_ERROR("Process:: can not get name size");
357             return nullptr;
358         }
359         std::string result = "";
360         result.reserve(bufferSize + 1);
361         result.resize(bufferSize);
362         if (napi_get_value_string_utf8(env, name, result.data(), bufferSize + 1, &bufferSize) != napi_ok) {
363             HILOG_ERROR("Process:: can not get name value");
364             return nullptr;
365         }
366         struct passwd user;
367         int32_t uid = 0;
368         struct passwd *bufp = nullptr;
369         long bufLen = sysconf(_SC_GETPW_R_SIZE_MAX);
370         if (bufLen == -1) {
371             bufLen = 16384; // 16384:Should be more than enough
372         }
373 
374         std::string buf;
375         buf.reserve(bufLen + 1);
376         buf.resize(bufLen);
377         if (getpwnam_r(result.c_str(), &user, buf.data(), bufLen, &bufp) == 0 && bufp != nullptr) {
378             uid = static_cast<int32_t>(bufp->pw_uid);
379             napi_create_int32(env, uid, &convertResult);
380             return convertResult;
381         }
382         napi_create_int32(env, (-1), &convertResult);
383         return convertResult;
384     }
385 
GetThreadPriority(napi_env env,napi_value tid) const386     napi_value Process::GetThreadPriority(napi_env env, napi_value tid) const
387     {
388         errno = 0;
389         napi_value result = nullptr;
390         int32_t proTid = 0;
391         napi_get_value_int32(env, tid, &proTid);
392         int32_t pri = getpriority(PRIO_PROCESS, proTid);
393         if (errno) {
394             napi_throw_error(env, "-1", "Invalid tid");
395             return nullptr;
396         }
397         napi_create_int32(env, pri, &result);
398         return result;
399     }
400 
GetStartRealtime(napi_env env) const401     napi_value Process::GetStartRealtime(napi_env env) const
402     {
403         napi_value result = nullptr;
404         double startRealtime = GetProcessStartRealtime();
405         napi_create_double(env, startRealtime, &result);
406         return result;
407     }
408 
ConvertTime(time_t tvsec,int64_t tvnsec) const409     int Process::ConvertTime(time_t tvsec, int64_t tvnsec) const
410     {
411         return int(tvsec * 1000) + int(tvnsec / 1000000); // 98999:Only converttime numbers is 1000 and 1000000.
412     }
413 
GetPastCputime(napi_env env) const414     napi_value Process::GetPastCputime(napi_env env) const
415     {
416         struct timespec times = {0, 0};
417         napi_value result = nullptr;
418         auto res = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &times);
419         if (res) {
420             return 0;
421         }
422         int when =  ConvertTime(times.tv_sec, times.tv_nsec);
423         napi_create_int32(env, when, &result);
424         return result;
425     }
426 
GetSystemConfig(napi_env env,napi_value name) const427     napi_value Process::GetSystemConfig(napi_env env, napi_value name) const
428     {
429         int32_t number = 0;
430         napi_value result = nullptr;
431         napi_get_value_int32(env, name, &number);
432         auto configinfo = static_cast<int32_t>(sysconf(number));
433         napi_create_int32(env, configinfo, &result);
434         return result;
435     }
436 
ClearReference(napi_env env)437     void Process::ClearReference(napi_env env)
438     {
439         auto iter = eventMap.begin();
440         while (iter != eventMap.end()) {
441             napi_status status = napi_delete_reference(env, iter->second);
442             if (status != napi_ok) {
443                 napi_throw_error(env, nullptr, "ClearReference failed");
444                 return;
445             }
446             iter++;
447         }
448         eventMap.clear();
449     }
450 
IsAppUid(napi_env env,napi_value uid) const451     napi_value ProcessManager::IsAppUid(napi_env env, napi_value uid) const
452     {
453         int32_t number = 0;
454         napi_value result = nullptr;
455         bool flag = true;
456         napi_get_value_int32(env, uid, &number);
457         if (number > 0) {
458             const auto appId = number % PER_USER_RANGE;
459             if (appId >= FIRST_APPLICATION_UID && appId <= LAST_APPLICATION_UID) {
460                 napi_get_boolean(env, flag, &result);
461                 return result;
462             }
463         }
464         flag = false;
465         NAPI_CALL(env, napi_get_boolean(env, flag, &result));
466         return result;
467     }
468 
GetUidForName(napi_env env,napi_value name) const469     napi_value ProcessManager::GetUidForName(napi_env env, napi_value name) const
470     {
471         napi_value convertResult = nullptr;
472         size_t bufferSize = 0;
473         if (napi_get_value_string_utf8(env, name, nullptr, 0, &bufferSize) != napi_ok) {
474             HILOG_ERROR("ProcessManager:: can not get name size");
475             return nullptr;
476         }
477         std::string result = "";
478         result.reserve(bufferSize + 1);
479         result.resize(bufferSize);
480         if (napi_get_value_string_utf8(env, name, result.data(), bufferSize + 1, &bufferSize) != napi_ok) {
481             HILOG_ERROR("ProcessManager:: can not get name value");
482             return nullptr;
483         }
484         struct passwd user;
485         int32_t uid = 0;
486         struct passwd *bufp = nullptr;
487         long bufLen = sysconf(_SC_GETPW_R_SIZE_MAX);
488         if (bufLen == -1) {
489             bufLen = 16384; // 16384:Should be more than enough
490         }
491 
492         std::string buf;
493         buf.reserve(bufLen + 1);
494         buf.resize(bufLen);
495         if (getpwnam_r(result.c_str(), &user, buf.data(), bufLen, &bufp) == 0 && bufp != nullptr) {
496             uid = static_cast<int32_t>(bufp->pw_uid);
497             napi_create_int32(env, uid, &convertResult);
498             return convertResult;
499         }
500         napi_create_int32(env, (-1), &convertResult);
501         return convertResult;
502     }
503 
GetThreadPriority(napi_env env,napi_value tid) const504     napi_value ProcessManager::GetThreadPriority(napi_env env, napi_value tid) const
505     {
506         errno = 0;
507         napi_value result = nullptr;
508         int32_t proTid = 0;
509         napi_get_value_int32(env, tid, &proTid);
510         int32_t pri = GetThreadPRY(proTid);
511         if (errno) {
512             napi_throw_error(env, "401", "Parameter error. The type of Parameter must be number and a valid tid.");
513             return nullptr;
514         }
515         napi_create_int32(env, pri, &result);
516         return result;
517     }
518 
GetSystemConfig(napi_env env,napi_value name) const519     napi_value ProcessManager::GetSystemConfig(napi_env env, napi_value name) const
520     {
521         int32_t number = 0;
522         napi_value result = nullptr;
523         napi_get_value_int32(env, name, &number);
524         int32_t configinfo = GetSysConfig(number);
525         napi_create_int32(env, configinfo, &result);
526         return result;
527     }
528 
GetEnvironmentVar(napi_env env,napi_value name) const529     napi_value ProcessManager::GetEnvironmentVar(napi_env env, napi_value name) const
530     {
531         size_t bufferSize = 0;
532         if (napi_get_value_string_utf8(env, name, nullptr, 0, &bufferSize) != napi_ok) {
533             HILOG_ERROR("ProcessManager:: can not get name size");
534             return nullptr;
535         }
536         std::string result = "";
537         result.reserve(bufferSize + 1);
538         result.resize(bufferSize);
539         if (napi_get_value_string_utf8(env, name, result.data(), bufferSize + 1, &bufferSize) != napi_ok) {
540             HILOG_ERROR("ProcessManager:: can not get name value");
541             return nullptr;
542         }
543         std::string temp = "";
544         temp = result;
545         char buf[260 * NUM_OF_DATA] = { 0 }; // 260:Only numbers path String size is 260.
546         size_t length = sizeof(buf);
547         auto envNum = uv_os_getenv(temp.c_str(), buf, &length);
548         napi_value convertResult = nullptr;
549         if (envNum == UV_ENOENT) {
550             NAPI_CALL(env, napi_get_undefined(env, &convertResult));
551             return convertResult;
552         }
553         napi_create_string_utf8(env, buf, strlen(buf), &convertResult);
554         return convertResult;
555     }
556 
Exit(napi_env env,napi_value number) const557     void ProcessManager::Exit(napi_env env, napi_value number) const
558     {
559         int32_t result = 0;
560         napi_get_value_int32(env, number, &result);
561         ProcessExit(result);
562     }
563 
Kill(napi_env env,napi_value signal,napi_value proid)564     napi_value ProcessManager::Kill(napi_env env, napi_value signal, napi_value proid)
565     {
566         int32_t pid = 0;
567         int32_t sig = 0;
568         napi_get_value_int32(env, proid, &pid);
569         napi_get_value_int32(env, signal, &sig);
570         uv_pid_t ownPid = uv_os_getpid();
571         // 64:The maximum valid signal value is 64.
572         if (sig > 64 && (!pid || pid == -1 || pid == ownPid || pid == -ownPid)) {
573             napi_throw_error(env, "401", "Parameter error. The type of signal must be number,and from 1 to 64.");
574             return nullptr;
575         }
576         bool flag = false;
577         int err = uv_kill(pid, sig);
578         if (!err) {
579             flag = true;
580         }
581         napi_value result = nullptr;
582         NAPI_CALL(env, napi_get_boolean(env, flag, &result));
583         return result;
584     }
585 } // namespace OHOS::JsSysModule::Process
586