• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3  * Licensed under the Mulan PSL v2.
4  * You can use this software according to the terms and conditions of the Mulan PSL v2.
5  * You may obtain a copy of Mulan PSL v2 at:
6  *     http://license.coscl.org.cn/MulanPSL2
7  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8  * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9  * PURPOSE.
10  * See the Mulan PSL v2 for more details.
11  */
12 #include "drv_process_mgr.h"
13 #include <stdint.h>
14 #include <securec.h>
15 #include <dlfcn.h>
16 #include <pthread.h>
17 #include <ipclib.h>
18 #include <spawn_ext.h>
19 #include <sys/wait.h>
20 #include <signal.h>
21 #include <fileio.h>
22 #include <priorities.h>
23 #include <tee_log.h>
24 #include <drv_thread.h>
25 #include <spawn_init.h>
26 #include <get_elf_info.h>
27 #include <target_type.h>
28 #include <tee_drv_internal.h>
29 #include <mem_ops.h>
30 #include <mem_page_ops.h>
31 #include "drv_fd_ops.h"
32 #include "drv_dyn_policy_mgr.h"
33 #include "task_mgr.h"
34 #include "base_drv_node.h"
35 #include <ipclib_hal.h>
36 
37 static const char *g_drv_loader = "/tarunner.elf";
38 static const char *g_drv_a32_loader = "/tarunner_a32.elf";
39 
40 /*
41  * channel and msghdl used for send/receive ipc msg
42  * between drvmgr and drv process, locked by g_drv_spawn_mtx
43  */
44 static cref_t g_drv_spawn_sync_channel;
45 static cref_t g_drv_spawn_sync_msghdl;
46 
create_spawn_sync_msg_info(void)47 int32_t create_spawn_sync_msg_info(void)
48 {
49     int32_t ret = ipc_create_channel_native(DRV_SPAWN_SYNC_NAME, &g_drv_spawn_sync_channel);
50     if (ret != 0) {
51         /* called by drvmgr main, use tloge instead of tloge */
52         tloge("create spawn sync channel fail\n");
53         return -1;
54     }
55 
56     g_drv_spawn_sync_msghdl = ipc_msg_create_hdl();
57     if (!check_ref_valid(g_drv_spawn_sync_msghdl)) {
58         tloge("create spawn sync hdl fail\n");
59         return -1;
60     }
61 
62     return 0;
63 }
64 
65 /*
66  * process argv and env which will be passed to driver loader by kernel,
67  * all this buffer should be in drvmgr map pages, otherwise will cannot
68  * find map_page in find_map_page called by vspace_stream_sync.
69  * Now, only the stack of main thread or the  global value added to map pages,
70  * so in order to spawn in other thread, we use global value as the spawn buffer.
71  */
72 static char g_spawn_buffer[sizeof(struct spawn_drv_buffer) * 2];
73 static char *g_argv[ARGV_MAX] = { 0 };
74 static char *g_env[ENV_MAX] = { 0 };
75 static pthread_mutex_t g_drv_spawn_mtx = PTHREAD_MUTEX_INITIALIZER;
76 
spawn_driver(const struct drv_spawn_param * param,int32_t loader_type,char * argv[],char * env[],uint32_t * taskid)77 static int32_t spawn_driver(const struct drv_spawn_param *param, int32_t loader_type,
78     char *argv[], char *env[], uint32_t *taskid)
79 {
80     pid_t pid;
81     tid_t tid;
82     posix_spawnattr_t spawnattr;
83 
84     int32_t ret = spawnattr_init(&spawnattr);
85     if (ret != 0) {
86         tloge("spawnattr init failed\n");
87         return -1;
88     }
89 
90     ret = spawnattr_setstack(&spawnattr, param->stack_size);
91     if (ret != 0) {
92         tloge("set stack size:0x%x failed\n", param->stack_size);
93         return -1;
94     }
95 
96     ret = spawnattr_setheap(&spawnattr, param->heap_size);
97     if (ret != 0) {
98         tloge("set heap size:0x%x failed\n", param->heap_size);
99         return -1;
100     }
101 
102     spawn_uuid_t uuid;
103     uuid.uuid_valid = 0; /* drvloader in ramfs, not tafs */
104     if (memcpy_s(&uuid.uuid, sizeof(uuid.uuid), &param->uuid, sizeof(param->uuid)) != 0) {
105         tloge("set uuid failed\n");
106         return -1;
107     }
108     spawnattr_setuuid(&spawnattr, &uuid);
109 
110     spawnattr.ptid = 0;
111 
112     const char *drv_loader = g_drv_loader;
113     if (loader_type == ELF_TARUNNER_A32)
114         drv_loader = g_drv_a32_loader;
115 
116     ret = posix_spawn_ex(&pid, drv_loader, NULL, &spawnattr, argv, env, &tid);
117     if (ret != 0) {
118         tloge("spawn driver failed ret:0x%x\n", ret);
119         return -1;
120     }
121 
122     *taskid = pid_to_taskid((uint32_t)tid, (uint32_t)pid);
123 
124     return 0;
125 }
126 
drv_name_to_path(const struct drv_spawn_param * drv_param,char * drv_path,int32_t path_len)127 static int32_t drv_name_to_path(const struct drv_spawn_param *drv_param, char *drv_path, int32_t path_len)
128 {
129     bool base_drv_flag = get_base_drv_flag(drv_param->drv_name, strlen(drv_param->drv_name));
130     if (base_drv_flag) {
131         int32_t ret = snprintf_s(drv_path, path_len, (path_len - 1), "/%s%s", drv_param->drv_name, ".elf");
132         if (ret < 0) {
133             tloge("get drv path failed\n");
134             return -1;
135         }
136     } else {
137         int32_t ret = snprintf_s(drv_path, path_len, (path_len - 1), "%s/%s%s",
138                                  TAFS_MOUNTPOINT, drv_param->drv_name, ".elf");
139         if (ret < 0) {
140             tloge("get drv path failed\n");
141             return -1;
142         }
143     }
144 
145     tlogd("get drv path is %s\n", drv_path);
146 
147     return 0;
148 }
149 
init_spawn_argv(const char * drv_name,uint32_t drv_name_len,const char * path_name,uint32_t path_len,struct argv_base_buffer * argv)150 static int32_t init_spawn_argv(const char *drv_name, uint32_t drv_name_len,
151     const char *path_name, uint32_t path_len, struct argv_base_buffer *argv)
152 {
153     /* uncommit default is true */
154     if (strncpy_s(argv->task_name, sizeof(argv->task_name), drv_name, drv_name_len) != 0) {
155         tloge("set loader path failed\n");
156         return -1;
157     }
158 
159     if (strncpy_s(argv->task_path, sizeof(argv->task_path), path_name, path_len) != 0) {
160         tloge("set task path name failed\n");
161         return -1;
162     }
163 
164     return 0;
165 }
166 
init_spawn_buffer(struct spawn_drv_buffer * buffer)167 static void init_spawn_buffer(struct spawn_drv_buffer *buffer)
168 {
169     g_argv[ARGV_ELF_PATH_INDEX] = (char *)g_drv_loader;
170     g_argv[ARGV_TASK_NAME_INDEX] = buffer->argv.task_name;
171     g_argv[ARGV_TASK_PATH_INDEX] = buffer->argv.task_path;
172     g_argv[ARGV_UNCOMMIT_INDEX] = buffer->argv.uncommit;
173 
174     g_env[ENV_PRIORITY_INDEX] = buffer->env.priority;
175     g_env[ENV_UID_INDEX] = buffer->env.uid;
176     g_env[ENV_TARGET_TYPE_INDEX] = buffer->env.target_type;
177     g_env[ENV_DRV_INDEX_INDEX] = buffer->env_drv.drv_index;
178     g_env[ENV_THREAD_LIMIT_INDEX] = buffer->env_drv.thread_limit;
179     g_env[ENV_STACK_SIZE_INDEX] = buffer->env_drv.stack_size;
180 }
181 
init_spawn_env(const struct drv_spawn_param * drv_param,struct spawn_drv_buffer * buffer)182 static int32_t init_spawn_env(const struct drv_spawn_param *drv_param, struct spawn_drv_buffer *buffer)
183 {
184     struct env_param eparam = { 0 };
185     eparam.priority = PRIO_TEE_DRV;
186     eparam.target_type = DRV_TARGET_TYPE;
187     eparam.drv_index = drv_param->drv_index;
188     eparam.thread_limit = drv_param->thread_limit;
189     eparam.stack_size = drv_param->stack_size;
190 
191     int32_t ret = set_env_for_task(&eparam, &(drv_param->uuid), &(buffer->env));
192     if (ret != 0)
193         return -1;
194 
195     ret = set_drv_env_for_task(&eparam, &(buffer->env_drv));
196     if (ret != 0)
197         return -1;
198 
199     return 0;
200 }
201 
get_drv_loader(const char * name)202 static int32_t get_drv_loader(const char *name)
203 {
204     char ehdr[EH_SIZE];
205     int32_t loader = ELF_NOT_SUPPORT;
206 
207     int32_t fd = open(name, O_RDONLY);
208     if (fd < 0) {
209         tloge("cannot open file %d\n", fd);
210         return loader;
211     }
212 
213     if (read(fd, ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
214         tloge("read file failed, name=%s\n", name);
215         goto close_fd;
216     }
217 
218     int32_t elf_class = get_elf_class(ehdr, sizeof(ehdr));
219     int32_t elf_type  = get_elf_type(ehdr, sizeof(ehdr), elf_class);
220     if (elf_type != ET_DYN) {
221         tloge("not support elf_type:0x%x\n", elf_type);
222         goto close_fd;
223     }
224 
225     if (elf_class == ELFCLASS64)
226         loader = ELF_TARUNNER;
227     else
228         loader = ELF_TARUNNER_A32;
229 
230 close_fd:
231     close(fd);
232 
233     return loader;
234 }
235 
236 #define MAX_WAIT_RETRY_COUNT 16
wait_drv_spawn_msg(uint32_t taskid)237 static int32_t wait_drv_spawn_msg(uint32_t taskid)
238 {
239     struct src_msginfo info = { 0 }; /* store sender msg info */
240     struct spawn_sync_msg msg = { 0 };
241 
242     int32_t ret;
243     uint32_t retry_count = 0;
244 
245 wait_retry:
246     /*
247      * To prevent other process send invalid msg, drvmgr should retry when the sender pid
248      * not match the spawn process pid.
249      * And in order to prevent other process send msg all the time, drvmgr will return fail
250      * when retry MAX_WAIT_RETRY_COUNT.
251      */
252     if (retry_count >= MAX_WAIT_RETRY_COUNT) {
253         tloge("wait drv msg retry_count:%u, should retry fail\n", retry_count);
254         return -1;
255     }
256 
257     retry_count++;
258     ret = ipc_msg_receive(g_drv_spawn_sync_channel, &msg, sizeof(msg), g_drv_spawn_sync_msghdl,
259                           &info, WAIT_DRV_MSG_MAX_TIME);
260     if (ret == E_EX_TIMER_TIMEOUT) {
261         tloge("wait drv:0x%x spawn msg timeout:%u\n", taskid, WAIT_DRV_MSG_MAX_TIME);
262         return -1;
263     }
264 
265     if (ret != 0) {
266         tloge("get drv:0x%x msg receiver fail ret:0x%x\n", taskid, ret);
267         return -1;
268     }
269 
270     if (info.src_pid != taskid_to_pid(taskid)) {
271         tloge("sender:0x%x is not spawn process:0x%x, just wait again\n",
272             info.src_pid, taskid);
273         goto wait_retry;
274     }
275 
276     if (msg.msg_id != PROCESS_INIT_SUCC) {
277         tloge("spawn task:0x%x init fail\n", taskid);
278         return -1;
279     }
280 
281     tlogd("get drv:0x%x spawn msg succ\n", taskid);
282 
283     return 0;
284 }
285 
286 #define DRV_KILL_WAIT_MAX_COUNT 5
drv_kill_task(uint32_t taskid)287 void drv_kill_task(uint32_t taskid)
288 {
289     if (kill((pid_t)taskid_to_pid(taskid), 0) == 0) {
290         int32_t i;
291         int32_t status;
292         for (i = 0; i < DRV_KILL_WAIT_MAX_COUNT; i++) {
293             if (wait(&status) == (pid_t)taskid_to_pid(taskid)) {
294                 tloge("wait drv:0x%x exit succ\n", taskid);
295                 break;
296             }
297         }
298 
299         if (i == DRV_KILL_WAIT_MAX_COUNT)
300             tloge("wait drv:0x%x exit failed\n", taskid);
301     } else {
302         tloge("kill drv:0x%x failed\n", taskid);
303     }
304 }
305 
prepare_spawn_params(const struct drv_spawn_param * drv_param,uint32_t * taskid)306 static int32_t prepare_spawn_params(const struct drv_spawn_param *drv_param, uint32_t *taskid)
307 {
308     int32_t func_ret = -1;
309     int32_t ret = drv_mutex_lock(&g_drv_spawn_mtx);
310     if (ret != 0) {
311         tloge("get drv spawn mtx failed\n");
312         return -1;
313     }
314 
315     /* make spawn_buffer in one page */
316     struct spawn_drv_buffer *spawn_buffer = (struct spawn_drv_buffer *)g_spawn_buffer;
317     (void)memset_s(g_spawn_buffer, sizeof(g_spawn_buffer), 0, sizeof(g_spawn_buffer));
318     if (((uintptr_t)g_spawn_buffer & (PAGE_SIZE - 1)) + sizeof(struct spawn_drv_buffer) > PAGE_SIZE)
319         spawn_buffer = (struct spawn_drv_buffer *)(g_spawn_buffer + sizeof(struct spawn_drv_buffer));
320 
321     init_spawn_buffer(spawn_buffer);
322 
323     if (init_spawn_env(drv_param, spawn_buffer) != 0)
324         goto unlock_spawn_mtx;
325 
326     char drv_path[ARGV_SIZE] = { 0 };
327     ret = drv_name_to_path(drv_param, drv_path, sizeof(drv_path));
328     if (ret != 0)
329         goto unlock_spawn_mtx;
330 
331     ret = init_spawn_argv(drv_param->drv_name, (strlen(drv_param->drv_name) + 1),
332         drv_path, (strlen(drv_path) + 1), &(spawn_buffer->argv));
333     if (ret != 0)
334         goto unlock_spawn_mtx;
335 
336     int32_t loader_type = get_drv_loader(drv_path);
337     if (loader_type == ELF_NOT_SUPPORT) {
338         tloge("get drv loader ret:0x%x fail\n", loader_type);
339         goto unlock_spawn_mtx;
340     }
341 
342     ret = spawn_driver(drv_param, loader_type, g_argv, g_env, taskid);
343     if (ret != 0)
344         goto unlock_spawn_mtx;
345 
346     ret = wait_drv_spawn_msg(*taskid);
347     if (ret != 0) {
348         tloge("wait drv spawn msg fail\n");
349         drv_kill_task(*taskid);
350         goto unlock_spawn_mtx;
351     }
352 
353     func_ret = 0;
354 
355 unlock_spawn_mtx:
356     ret = pthread_mutex_unlock(&g_drv_spawn_mtx);
357     if (ret != 0)
358         tloge("something wrong, unlock mtx in drv spawn fail:0x%x\n", ret);
359 
360     return func_ret;
361 }
362 
set_drv_name_and_uuid(const struct task_node * node,struct drv_spawn_param * param)363 static int32_t set_drv_name_and_uuid(const struct task_node *node, struct drv_spawn_param *param)
364 {
365     if (memcpy_s(&param->drv_name, (sizeof(param->drv_name) - 1),
366         node->tlv.drv_conf->mani.service_name, node->tlv.drv_conf->mani.service_name_size) != 0) {
367         tloge("copy name:%s fail\n", node->tlv.drv_conf->mani.service_name);
368         return -1;
369     }
370 
371     param->drv_name[node->tlv.drv_conf->mani.service_name_size] = '\0';
372 
373     if (memcpy_s(&param->uuid, sizeof(param->uuid),
374         &node->tlv.uuid, sizeof(node->tlv.uuid)) != 0) {
375         tloge("copy uuid:0x%x fail\n", node->tlv.uuid.timeLow);
376         return -1;
377     }
378 
379     return 0;
380 }
381 
set_drv_thread_limit(const struct task_node * node,struct drv_spawn_param * param)382 static void set_drv_thread_limit(const struct task_node *node, struct drv_spawn_param *param)
383 {
384     param->thread_limit = node->tlv.drv_conf->drv_basic_info.thread_limit;
385     tlogd("thread limit:%u\n", param->thread_limit);
386 }
387 
set_drv_stack_size(const struct task_node * node,struct drv_spawn_param * param)388 static int32_t set_drv_stack_size(const struct task_node *node, struct drv_spawn_param *param)
389 {
390     uint32_t stack_size = node->tlv.drv_conf->mani.stack_size;
391     uint32_t stack_size_align = PAGE_ALIGN_UP(stack_size);
392     if (stack_size_align < stack_size) {
393         tloge("invalid stack_size:0x%x\n", stack_size);
394         return -1;
395     }
396 
397     if (stack_size_align < DRV_DEFAULT_STACK_SIZE) {
398         tloge("stack_size:0x%x use default:0x%x", stack_size_align, DRV_DEFAULT_STACK_SIZE);
399         stack_size_align = DRV_DEFAULT_STACK_SIZE;
400     }
401 
402     param->stack_size = stack_size_align;
403 
404     return 0;
405 }
406 
set_drv_heap_size(const struct task_node * node,struct drv_spawn_param * param)407 static int32_t set_drv_heap_size(const struct task_node *node, struct drv_spawn_param *param)
408 {
409     uint32_t heap_size = node->tlv.drv_conf->mani.data_size;
410     uint32_t heap_size_align = PAGE_ALIGN_UP(heap_size);
411     if (heap_size_align < heap_size) {
412         tloge("invalid heap_size:0x%x\n", heap_size);
413         return -1;
414     }
415 
416     uint32_t stack_size = param->stack_size;
417     uint32_t thread_limit = param->thread_limit;
418     uint32_t extra_stack_size = stack_size * thread_limit;
419     if (extra_stack_size < stack_size) {
420         tloge("stack_size:0x%x and thread_limit:%u is overflow\n", stack_size, thread_limit);
421         return -1;
422     }
423 
424     if (heap_size_align + extra_stack_size < heap_size_align) {
425         tloge("heap_size:0x%x and extra_stack_size:0x%x is overflow\n", heap_size_align, extra_stack_size);
426         return -1;
427     }
428 
429     heap_size_align += extra_stack_size;
430     param->heap_size = heap_size_align;
431 
432     return 0;
433 }
434 
get_drv_channel(const char * drv_name,cref_t * ch)435 static int32_t get_drv_channel(const char *drv_name, cref_t *ch)
436 {
437     cref_t channel;
438     int32_t ret = ipc_get_ch_from_path(drv_name, &channel);
439     if (ret != 0) {
440         tloge("get drv:%s channel fail:0x%x\n", drv_name, ret);
441         return -1;
442     }
443 
444     tlogd("get drv:%s channel:0x%llx succ\n", drv_name, channel);
445 
446     *ch = channel;
447 
448     return 0;
449 }
450 
send_cmd_perm_msg(uint64_t drv_vaddr,uint32_t drv_size,cref_t channel)451 static int32_t send_cmd_perm_msg(uint64_t drv_vaddr, uint32_t drv_size, cref_t channel)
452 {
453     char buf[SYSCAL_MSG_BUFFER_SIZE] = { 0 };
454     struct drv_req_msg_t *msg = (struct drv_req_msg_t *)buf;
455     struct drv_reply_msg_t *rmsg = (struct drv_reply_msg_t *)buf;
456 
457     msg->args[DRV_REGISTER_CMD_ADDR_INDEX] = drv_vaddr;
458     msg->args[DRV_REGISTER_CMD_SIZE_INDEX] = drv_size;
459 
460     msg->header.send.msg_id = REGISTER_DRV_CMD_PERM;
461     msg->header.send.msg_size = sizeof(struct drv_req_msg_t);
462 
463     int32_t ret = ipc_msg_call(channel, msg, msg->header.send.msg_size, rmsg, SYSCAL_MSG_BUFFER_SIZE, -1);
464     if (ret != 0) {
465         tloge("msg call:0x%x fail ret:0x%x\n", REGISTER_DRV_CMD_PERM, ret);
466         return -1;
467     }
468 
469     return rmsg->header.reply.ret_val;
470 }
471 
send_cmd_perm_to_drv(const struct task_node * node)472 static int32_t send_cmd_perm_to_drv(const struct task_node *node)
473 {
474     int32_t ret = -1;
475     uint32_t self_pid = get_self_taskid();
476     if (self_pid < 0) {
477         tloge("get self pid fail\n");
478         return ret;
479     }
480 
481     if (node->tlv.drv_conf->cmd_perm_list_size == 0) {
482         tlogd("no cmd perm, just return\n");
483         return 0;
484     }
485 
486     uint32_t tmp_size = node->tlv.drv_conf->cmd_perm_list_size * sizeof(struct drv_cmd_perm_info_t);
487     void *tmp_addr = alloc_sharemem_aux(&node->tlv.uuid, tmp_size);
488     if (tmp_addr == NULL) {
489         tloge("alloc share mem:0x%x fail\n", tmp_size);
490         return ret;
491     }
492 
493     if (memcpy_s(tmp_addr, tmp_size, node->tlv.drv_conf->cmd_perm_list, tmp_size) != 0) {
494         tloge("copy cmd perm to share mem fail\n");
495         goto free_addr;
496     }
497 
498     ret = send_cmd_perm_msg((uint64_t)(uintptr_t)tmp_addr, tmp_size, node->drv_task.channel);
499 
500 free_addr:
501     if (free_sharemem(tmp_addr, tmp_size) != 0)
502         tloge("free share mem fail\n");
503 
504     return ret;
505 }
506 
spawn_driver_handle(struct task_node * node)507 int32_t spawn_driver_handle(struct task_node *node)
508 {
509     if (node == NULL || node->tlv.drv_conf == NULL || node->drv_task.drv_index < 0) {
510         tloge("spawn invalid node\n");
511         return -1;
512     }
513 
514     struct drv_spawn_param param;
515     (void)memset_s(&param, sizeof(param), 0, sizeof(param));
516     param.drv_index = (uint32_t)node->drv_task.drv_index;
517 
518     if (set_drv_name_and_uuid(node, &param) != 0)
519         return -1;
520 
521     set_drv_thread_limit(node, &param);
522 
523     if (set_drv_stack_size(node, &param) != 0)
524         return -1;
525 
526     /* set heap size must call after set_drv_stack_size and set thread_limit */
527     if (set_drv_heap_size(node, &param) != 0)
528         return -1;
529 
530     uint32_t taskid;
531     int32_t ret = prepare_spawn_params(&param, &taskid);
532     if (ret != 0) {
533         tloge("spawn drv:%s fail\n", param.drv_name);
534         return -1;
535     }
536 
537     ret = get_drv_channel(param.drv_name, &node->drv_task.channel);
538     if (ret != 0)
539         goto kill_task;
540 
541     ret = send_cmd_perm_to_drv(node);
542     if (ret != 0)
543         goto release_channel;
544 
545     node->pid = taskid_to_pid(taskid);
546 
547     return 0;
548 
549 release_channel:
550     if (ipc_release_from_path(node->tlv.drv_conf->mani.service_name, node->drv_task.channel) != 0)
551         tloge("release drv:%s channel:0x%llx failed\n", node->tlv.drv_conf->mani.service_name, node->drv_task.channel);
552     node->drv_task.channel = -1;
553 
554 kill_task:
555     drv_kill_task(taskid);
556 
557     return -1;
558 }
559 
release_driver(struct task_node * node)560 void release_driver(struct task_node *node)
561 {
562     if (node == NULL || node->target_type != DRV_TARGET_TYPE || node->tlv.drv_conf == NULL) {
563         tloge("invalid node\n");
564         return;
565     }
566 
567     if (node->drv_task.register_policy) {
568         del_dynamic_policy_to_drv(&node->tlv.uuid);
569         node->drv_task.register_policy = false;
570     }
571 
572     if (check_ref_valid(node->drv_task.channel)) {
573         if (ipc_release_from_path(node->tlv.drv_conf->mani.service_name, node->drv_task.channel) != 0)
574             tloge("release drv:%s channel:0x%llx failed\n",
575                 node->tlv.drv_conf->mani.service_name, node->drv_task.channel);
576         node->drv_task.channel = -1;
577     }
578 
579     if (node->pid != (uint32_t)INVALID_CALLER_PID) {
580         drv_kill_task(node->pid);
581         node->pid = (uint32_t)INVALID_CALLER_PID;
582     }
583 }
584