• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "cmdmonitor.h"
33 #include <securec.h>
34 #include "smc.h"
35 #include "tc_ns_log.h"
36 #include "tzdriver_compat.h"
37 
38 const char g_cmdMonitorWhiteTable[][TASK_COMM_LEN] = {
39 #ifdef DEF_ENG
40     {"tee_test_ut"},
41 #endif
42 };
43 const uint32_t g_whiteTableThreadNum = sizeof(g_cmdMonitorWhiteTable) /
44     TASK_COMM_LEN;
45 
46 static int g_cmdNeedArchiveLog = 0;
47 static LINUX_LIST_HEAD(g_cmdMonitorList);
48 static int g_cmdMonitorListSize = 0;
49 /* report 2 hours */
50 #define MAX_CMD_MONITOR_LIST 200
51 #define MAX_AGENT_CALL_COUNT 250
52 static DEFINE_MUTEX(g_cmdMonitorLock);
53 struct CmdMonitor {
54     struct list_head list;
55     struct timespec sendTime;
56     int count;
57     bool returned;
58     bool isReported;
59     int pid;
60     int tid;
61     char pName[TASK_COMM_LEN];
62     char tName[TASK_COMM_LEN];
63     unsigned int lastCmdId;
64     long long timeTotal;
65     int agentCallCount;
66 };
67 static struct delayed_work g_cmdMonitorWork;
68 static struct delayed_work g_cmdMonitorWorkArchive;
69 static int g_teeDetectTaCrash = 0;
70 enum {
71     TYPE_CRASH_TA = 1,
72     TYPE_CRASH_TEE = 2,
73 };
74 
TzDebugArchiveLog(void)75 void TzDebugArchiveLog(void)
76 {
77     schedule_delayed_work(&g_cmdMonitorWorkArchive, MsecsToJiffies(0));
78 }
79 
CmdMonitorTaCrash(int32_t type)80 void CmdMonitorTaCrash(int32_t type)
81 {
82     g_teeDetectTaCrash = ((type == TYPE_CRASH_TEE) ? TYPE_CRASH_TEE :
83         TYPE_CRASH_TA);
84     TzDebugArchiveLog();
85 }
86 
IsThreadInWhiteTable(const char * tName)87 static bool IsThreadInWhiteTable(const char *tName)
88 {
89     uint32_t i;
90 
91     if (tName == NULL) {
92         return false;
93     }
94 
95     for (i = 0; i < g_whiteTableThreadNum; i++) {
96         if (!strcmp(tName, g_cmdMonitorWhiteTable[i])) {
97             return true;
98         }
99     }
100     return false;
101 }
102 
IsThreadReported(unsigned int tid)103 bool IsThreadReported(unsigned int tid)
104 {
105     bool ret = false;
106     struct CmdMonitor *monitor = NULL;
107 
108     mutex_lock(&g_cmdMonitorLock);
109     list_for_each_entry(monitor, &g_cmdMonitorList, list) {
110         if (monitor->tid == tid) {
111             ret = (monitor->isReported ||
112                 monitor->agentCallCount > MAX_AGENT_CALL_COUNT);
113             break;
114         }
115     }
116     mutex_unlock(&g_cmdMonitorLock);
117     return ret;
118 }
119 
CmdMonitorResetContext(void)120 void CmdMonitorResetContext(void)
121 {
122     struct CmdMonitor *monitor = NULL;
123     int pid = OsCurrTaskGet()->processID;
124     int tid = OsCurrTaskGet()->taskID;
125 
126     mutex_lock(&g_cmdMonitorLock);
127     list_for_each_entry(monitor, &g_cmdMonitorList, list) {
128         if (monitor->pid == pid && monitor->tid == tid) {
129             monitor->sendTime = CurrentKernelTime();
130             if (monitor->agentCallCount + 1 < 0) {
131                 tloge("agent call count add overflow\n");
132             } else {
133                 monitor->agentCallCount++;
134             }
135             break;
136         }
137     }
138     mutex_unlock(&g_cmdMonitorLock);
139 }
140 
CmdMonitorTick(void)141 static void CmdMonitorTick(void)
142 {
143     long long timeDif;
144     struct CmdMonitor *monitor = NULL;
145     struct CmdMonitor *tmp = NULL;
146     struct timespec nowTime = CurrentKernelTime();
147 
148     mutex_lock(&g_cmdMonitorLock);
149     list_for_each_entry_safe(monitor, tmp, &g_cmdMonitorList, list) {
150         if (monitor->returned == true) {
151             g_cmdMonitorListSize--;
152             tloge("[CmdMonitorTick] pid:%d, pName:%s, tid:%d, tName:%s, \
153 lastCmdId:%u, count:%d, agent call count:%d, timeTotal:%lld us returned, remained command(s):%d\n",
154                 monitor->pid, monitor->pName, monitor->tid,
155                 monitor->tName, monitor->lastCmdId,
156                 monitor->count, monitor->agentCallCount,
157                 monitor->timeTotal, g_cmdMonitorListSize);
158             list_del(&monitor->list);
159             free(monitor);
160             monitor = NULL;
161             continue;
162         }
163         /* not return, we need to check  */
164 
165         /*
166         * get time value D (timeDif=nowTime-sendTime), we do not care about overflow
167         * 1 year means 1000 * (60*60*24*365) = 0x757B12C00
168         * only 5bytes, will not overflow
169         */
170         timeDif = MSEC_PER_SEC * (nowTime.tv_sec - monitor->sendTime.tv_sec) +
171             (nowTime.tv_nsec - monitor->sendTime.tv_nsec) / NSEC_PER_MSEC;
172 
173         /* Temporally change timeout to 25s, we log the teeos log,and report */
174         if ((timeDif > TEMPORALLY_CHAGE_TIMEOUT) && (!monitor->isReported)) {
175             monitor->isReported = true;
176             /* print tee stask */
177             tloge("[CmdMonitorTick] pid:%d, pName:%s, tid:%d, tName:%s, \
178 lastCmdId:%u, agent call count:%d, timeDif:%lld ms and report\n",
179                 monitor->pid, monitor->pName, monitor->tid,
180                 monitor->tName, monitor->lastCmdId,
181                 monitor->agentCallCount, timeDif);
182             /* threads out of white table need info dump */
183             if (!(IsThreadInWhiteTable(monitor->tName))) {
184                 ShowCmdBitmapWithLock();
185                 g_cmdNeedArchiveLog = 1;
186                 WakeupTcSiq();
187             }
188         } else if (timeDif > 1 * MSEC_PER_SEC) {
189             tloge("[CmdMonitorTick] pid=%d, pName=%s, tid=%d, \
190 lastCmdId=%u, agent call count:%d, timeDif=%lld ms\n",
191                   monitor->pid, monitor->pName, monitor->tid,
192                   monitor->lastCmdId, monitor->agentCallCount,
193                   timeDif);
194         }
195     }
196     if (g_cmdMonitorListSize > 0) {
197         /* if have cmd in monitor list, we need tick */
198         schedule_delayed_work(&g_cmdMonitorWork, MsecsToJiffies(MSEC_PER_SEC));
199     }
200     mutex_unlock(&g_cmdMonitorLock);
201 }
CmdMonitorTickfn(struct work_struct * work)202 static void CmdMonitorTickfn(struct work_struct *work)
203 {
204     (void)(work);
205     CmdMonitorTick();
206 }
207 
CmdMonitorArchivefn(struct work_struct * work)208 static void CmdMonitorArchivefn(struct work_struct *work)
209 {
210     (void)(work);
211 }
212 
InitMonitorLocked(void)213 static struct CmdMonitor *InitMonitorLocked(void)
214 {
215     struct CmdMonitor *newItem = NULL;
216 
217     newItem = calloc(1, sizeof(*newItem));
218     if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)newItem)) {
219         tloge("[CmdMonitorTick]calloc failed\n");
220         return NULL;
221     }
222     newItem->sendTime = CurrentKernelTime();
223     newItem->count = 1;
224     newItem->agentCallCount = 0;
225     newItem->returned = false;
226     newItem->isReported = false;
227     newItem->pid = OsCurrTaskGet()->processID;
228     newItem->tid = OsCurrTaskGet()->taskID;
229 
230     LosProcessCB *runProcess = OS_PCB_FROM_PID(newItem->pid);
231     if (strncpy_s(newItem->pName, TASK_COMM_LEN, runProcess->processName, OS_PCB_NAME_LEN) != EOK) {
232         free(newItem);
233         newItem = NULL;
234         return NULL;
235     }
236     if (strncpy_s(newItem->tName, TASK_COMM_LEN, OsCurrTaskGet()->taskName, OS_TCB_NAME_LEN) != EOK) {
237         free(newItem);
238         newItem = NULL;
239         return NULL;
240     }
241     INIT_LIST_HEAD(&newItem->list);
242     list_add_tail(&newItem->list, &g_cmdMonitorList);
243     g_cmdMonitorListSize++;
244     return newItem;
245 }
246 
CmdMonitorLog(const TcNsSmcCmd * cmd)247 void CmdMonitorLog(const TcNsSmcCmd *cmd)
248 {
249     int foundFlag = 0;
250     int pid;
251     int tid;
252     struct CmdMonitor *monitor = NULL;
253     struct CmdMonitor *newItem = NULL;
254 
255     if (cmd == NULL) {
256         return;
257     }
258     pid = OsCurrTaskGet()->processID;
259     tid = OsCurrTaskGet()->taskID;
260     mutex_lock(&g_cmdMonitorLock);
261     do {
262         list_for_each_entry(monitor, &g_cmdMonitorList, list) {
263             if (monitor->pid == pid && monitor->tid == tid) {
264                 foundFlag = 1;
265                 /* restart */
266                 monitor->sendTime = CurrentKernelTime();
267                 monitor->count++;
268                 monitor->returned = false;
269                 monitor->isReported = false;
270                 monitor->lastCmdId = cmd->cmdId;
271                 monitor->agentCallCount = 0;
272                 break;
273             }
274         }
275         if (foundFlag == 0) {
276             if (g_cmdMonitorListSize > MAX_CMD_MONITOR_LIST - 1) {
277                 tloge("[CmdMonitorTick]MAX_CMD_MONITOR_LIST\n");
278                 break;
279             }
280             newItem = InitMonitorLocked();
281             if (newItem == NULL) {
282                 tloge("[CmdMonitorTick]init_monitor failed\n");
283                 break;
284             }
285             newItem->lastCmdId = cmd->cmdId;
286             /* the first cmd will cause timer */
287             if (g_cmdMonitorListSize == 1) {
288                 schedule_delayed_work(&g_cmdMonitorWork,
289                     MsecsToJiffies(MSEC_PER_SEC));
290             }
291         }
292     } while (0);
293     mutex_unlock(&g_cmdMonitorLock);
294 }
295 
CmdMonitorLogend(void)296 void CmdMonitorLogend(void)
297 {
298     int pid;
299     int tid;
300     struct CmdMonitor *monitor = NULL;
301 
302     pid = OsCurrTaskGet()->processID;
303     tid = OsCurrTaskGet()->taskID;
304     mutex_lock(&g_cmdMonitorLock);
305     list_for_each_entry(monitor, &g_cmdMonitorList, list) {
306         if (monitor->pid == pid && monitor->tid == tid &&
307             monitor->returned == false) {
308             struct timespec nowTime = CurrentKernelTime();
309             /*
310             * get time value D (timeDif=nowTime-sendTime), we do not care about overflow
311             * 1 year means 1000000 * (60*60*24*365) = 0x1CAE8C13E000
312             * only 6bytes, will not overflow
313             */
314             long long timeDif = USEC_PER_SEC *
315                 (nowTime.tv_sec - monitor->sendTime.tv_sec) +
316                 (nowTime.tv_nsec - monitor->sendTime.tv_nsec) / NSEC_PER_USEC;
317             monitor->timeTotal += timeDif;
318             monitor->returned = true;
319             break;
320         }
321     }
322     mutex_unlock(&g_cmdMonitorLock);
323 }
324 
DoCmdNeedArchivelog(void)325 void DoCmdNeedArchivelog(void)
326 {
327     if (g_cmdNeedArchiveLog == 1) {
328         g_cmdNeedArchiveLog = 0;
329         schedule_delayed_work(&g_cmdMonitorWorkArchive,
330             MsecsToJiffies(MSEC_PER_SEC));
331     }
332 }
InitCmdMonitor(void)333 void InitCmdMonitor(void)
334 {
335     InitDeferrableWork((struct delayed_work *)(uintptr_t)&g_cmdMonitorWork, CmdMonitorTickfn);
336     InitDeferrableWork((struct delayed_work *)(uintptr_t)&g_cmdMonitorWorkArchive, CmdMonitorArchivefn);
337 }
338