@@ -2552,8 +2552,28 @@ int collect_filemap(struct vma_area *vma)
25522552
25532553static int open_fe_fd (struct file_desc * fd , int * new_fd )
25542554{
2555+ struct reg_file_info * rfi ;
25552556 int tmp ;
25562557
2558+ rfi = container_of (fd , struct reg_file_info , d );
2559+
2560+ if (rfi -> deferred_thread_fd ) {
2561+ /*
2562+ * This is a live-thread /proc/<pid>/task/<tid>/... fd.
2563+ * The thread doesn't exist yet (created later by the
2564+ * restorer via clone()), so open /dev/null as a
2565+ * placeholder. The restorer will reopen the correct
2566+ * path after threads are created.
2567+ */
2568+ tmp = open ("/dev/null" , rfi -> rfe -> flags & O_ACCMODE );
2569+ if (tmp < 0 ) {
2570+ pr_perror ("Can't open /dev/null for deferred proc fd" );
2571+ return -1 ;
2572+ }
2573+ * new_fd = tmp ;
2574+ return 0 ;
2575+ }
2576+
25572577 tmp = open_path (fd , do_open_reg , NULL );
25582578 if (tmp < 0 )
25592579 return -1 ;
@@ -2596,6 +2616,121 @@ struct file_desc *try_collect_special_file(u32 id, int optional)
25962616 return fdesc ;
25972617}
25982618
2619+ /*
2620+ * On restore, fix up paths like proc/<pid>/task/<tid>/... where
2621+ * tid != pid. These paths can't be opened at prepare_fds() time
2622+ * because non-leader threads don't exist yet -- they are created
2623+ * later by the restorer blob via clone(). Two cases:
2624+ *
2625+ * 1) Dead thread (tid not in pstree): create a TASK_HELPER process
2626+ * with vPID=tid and rewrite the path to proc/<tid>/task/<tid>/...
2627+ * so it resolves through the helper's /proc entry.
2628+ *
2629+ * 2) Live thread (tid in pstree as TASK_THREAD): rewrite the path
2630+ * to proc/<pid>/task/<pid>/... so it points to the thread-group
2631+ * leader, which does exist at prepare_fds() time.
2632+ */
2633+ static int fixup_thread_proc_path (struct reg_file_info * rfi )
2634+ {
2635+ char * path = rfi -> path ;
2636+ char * task_str , * tid_str , * tid_end ;
2637+ pid_t pid , tid ;
2638+ char * new_path ;
2639+ struct pid * tid_node ;
2640+
2641+ /*
2642+ * rfi->path looks like "proc/<pid>/task/<tid>/..." (leading
2643+ * slash already stripped). We only care about procfs paths.
2644+ */
2645+ if (strncmp (path , "proc/" , 5 ))
2646+ return 0 ;
2647+
2648+ /* Parse the pid: "proc/<pid>/task/..." */
2649+ pid = strtol (path + 5 , & task_str , 10 );
2650+ if (pid == 0 || * task_str != '/' )
2651+ return 0 ;
2652+
2653+ /* Check for "/task/<tid>" */
2654+ if (strncmp (task_str , "/task/" , 6 ))
2655+ return 0 ;
2656+
2657+ tid_str = task_str + 6 ;
2658+ tid = strtol (tid_str , & tid_end , 10 );
2659+ if (tid == 0 || (* tid_end != '/' && * tid_end != '\0' ))
2660+ return 0 ;
2661+
2662+ /* If pid == tid the path already refers to the leader */
2663+ if (pid == tid )
2664+ return 0 ;
2665+
2666+ tid_node = pstree_pid_by_virt (tid );
2667+
2668+ /*
2669+ * If the TID belongs to a process (not a thread), the path
2670+ * will resolve on restore without any fixup.
2671+ */
2672+ if (tid_node && tid_node -> state != TASK_THREAD )
2673+ return 0 ;
2674+
2675+ if (!tid_node ) {
2676+ /*
2677+ * Dead thread: tid is not in the process tree.
2678+ * Create a TASK_HELPER with vPID=tid so that
2679+ * /proc/<tid>/task/<tid>/... resolves on restore.
2680+ */
2681+ struct pstree_item * helper ;
2682+
2683+ helper = lookup_create_item (tid );
2684+ if (!helper )
2685+ return -1 ;
2686+
2687+ if (helper -> pid -> state == TASK_UNDEF ) {
2688+ helper -> sid = root_item -> sid ;
2689+ helper -> pgid = root_item -> pgid ;
2690+ helper -> pid -> ns [0 ].virt = tid ;
2691+ helper -> parent = root_item ;
2692+ helper -> ids = root_item -> ids ;
2693+ if (init_pstree_helper (helper )) {
2694+ pr_err ("Can't init helper for dead thread %d\n" , tid );
2695+ return -1 ;
2696+ }
2697+ list_add_tail (& helper -> sibling , & root_item -> children );
2698+ pr_info ("Added a helper for restoring dead thread /proc/%d/task/%d\n" ,
2699+ pid , tid );
2700+ }
2701+
2702+ /*
2703+ * "proc/" + tid + "/task/" + tid + tid_end + '\0'
2704+ * Use PATH_MAX as a safe upper bound.
2705+ */
2706+ new_path = xmalloc (PATH_MAX );
2707+ if (!new_path )
2708+ return -1 ;
2709+
2710+ snprintf (new_path , PATH_MAX , "proc/%d/task/%d%s" ,
2711+ tid , tid , tid_end );
2712+ pr_info ("Rewrote dead thread path: %s -> %s\n" ,
2713+ rfi -> path , new_path );
2714+ } else {
2715+ /*
2716+ * Live thread: the thread exists in the pstree but
2717+ * won't be created until the restorer blob runs
2718+ * clone(), which is after prepare_fds(). Mark this
2719+ * file as deferred -- open_fe_fd() will open /dev/null
2720+ * as a placeholder, and the restorer will reopen the
2721+ * correct path after threads exist.
2722+ */
2723+ rfi -> deferred_thread_fd = true;
2724+ rfi -> orig_path = rfi -> path ;
2725+ pr_info ("Deferred live thread proc path: %s\n" , rfi -> path );
2726+ return 0 ;
2727+ }
2728+
2729+ rfi -> path = new_path ;
2730+
2731+ return 0 ;
2732+ }
2733+
25992734static int collect_one_regfile (void * o , ProtobufCMessage * base , struct cr_img * i )
26002735{
26012736 struct reg_file_info * rfi = o ;
@@ -2609,6 +2744,11 @@ static int collect_one_regfile(void *o, ProtobufCMessage *base, struct cr_img *i
26092744 rfi -> path = rfi -> rfe -> name + 1 ;
26102745 rfi -> remap = NULL ;
26112746 rfi -> size_mode_checked = false;
2747+ rfi -> deferred_thread_fd = false;
2748+ rfi -> orig_path = NULL ;
2749+
2750+ if (fixup_thread_proc_path (rfi ))
2751+ return -1 ;
26122752
26132753 pr_info ("Collected [%s] ID %#x\n" , rfi -> path , rfi -> rfe -> id );
26142754 return file_desc_add (& rfi -> d , rfi -> rfe -> id , & reg_desc_ops );
0 commit comments