@@ -235,6 +235,15 @@ module type DAEMONPIDPATH = sig
235235  val  name  : string 
236236
237237  val  pid_location  : Pid .path 
238+ 
239+   (*  To check if a pid is valid, look up its process name, and some commandline
240+      arg containing domid if domid is not part of its process name, check that 
241+      they are contained in /proc/<pid>/cmdline. 
242+      The expected cmdline items are set by (expected_cmdline_items domid) for 
243+      each service. Note that the parameter "domid" here is required as 
244+      otherwise we can not distinguish between the process instances of the same 
245+      service for different domains. *)  
246+   val  expected_cmdline_items  : domid :int   -> string  list 
238247end 
239248
240249module  DaemonMgmt  (D  : DAEMONPIDPATH ) =  struct 
@@ -256,31 +265,66 @@ module DaemonMgmt (D : DAEMONPIDPATH) = struct
256265
257266  let  name =  D. name
258267
259-   let  pid  ~xs   domid  = 
268+   (*  For process id, look up its process name, and some commandline arg
269+      containing domid if domid is not part of its process name, check that 
270+      they are contained in /proc/<pid>/cmdline. *)  
271+   let  is_cmdline_valid  ~pid   ~pid_source   expected_args  = 
260272    try 
261-       match  D. pid_location with 
262-       |  (File  file  | Path_of  {file; _} ) when  Sys. file_exists (file domid) ->
263-           let  path =  file domid in 
264-           let  ( let *  ) =  Option. bind in 
265-           let *  pid =  Unixext. pidfile_read path in 
266-           Unixext. with_file path [Unix. O_RDONLY ] 0  (fun  fd  ->
267-               try 
268-                 Unix. lockf fd Unix. F_TRLOCK  0  ;
269-                 (*  we succeeded taking the lock: original process is dead.
270-                  * some other process might've reused its pid *)  
271-                 None 
272-               with  Unix. Unix_error  (Unix. EAGAIN, _ , _ ) -> 
273-                 (*  cannot obtain lock: process is alive *) 
274-                 Some  pid
275-           )
276-       |  Xenstore  key  |  Path_of  {key; _}  ->
277-           (*  backward compatibility during update installation: only has
278-              xenstore pid available *)  
279-           let  pid =  xs.Xs. read (key domid) in 
280-           Some  (int_of_string pid)
273+       let  cmdline_str = 
274+         Printf. sprintf " /proc/%d/cmdline"   pid |>  Unixext. string_of_file
275+       in 
276+       match  cmdline_str with 
277+       |  ""  ->
278+           (*  from man proc:
279+              /proc/[pid]/cmdline 
280+              This read-only file holds the complete command line for the process, 
281+              unless the process is a zombie. In the latter case, there is nothing 
282+              in this file: that is, a read on this file will return 0 characters. 
283+              This applies when the VM is being shut down. *)  
284+           false 
281285      |  _  ->
282-           None 
283-     with  _  ->  None 
286+           let  cmdline =  Astring.String. cuts ~sep: " \000 "   cmdline_str in 
287+           let  valid = 
288+             List. for_all (fun  arg  -> List. mem arg cmdline) expected_args
289+           in 
290+           if  not  valid then 
291+             error " %s: pid read from %s not valid (pid = %d)"   D. name pid_source
292+               pid ;
293+           valid
294+     with  _  ->  false 
295+ 
296+   let  pid  ~xs   domid  = 
297+     let  ( let *  ) =  Option. bind in 
298+     let *  pid, pid_source = 
299+       try 
300+         match  D. pid_location with 
301+         |  (File  file  | Path_of  {file; _} ) when  Sys. file_exists (file domid) ->
302+             let  path =  file domid in 
303+             let *  pid =  Unixext. pidfile_read path in 
304+             Unixext. with_file path [Unix. O_RDONLY ] 0  (fun  fd  ->
305+                 try 
306+                   Unix. lockf fd Unix. F_TRLOCK  0  ;
307+                   (*  we succeeded taking the lock: original process is dead.
308+                    * some other process might've reused its pid *)  
309+                   None 
310+                 with  Unix. Unix_error  (Unix. EAGAIN, _ , _ ) -> 
311+                   (*  cannot obtain lock: process is alive *) 
312+                   Some  (pid, " pidfile"  )
313+             )
314+         |  Xenstore  key  |  Path_of  {key; _}  ->
315+             (*  case 1: backward compatibility during update installation: only has
316+                  xenstore pid available. 
317+                case 2: pidfile(file domid) got removed unexpectly *)  
318+             let  pid =  xs.Xs. read (key domid) in 
319+             Some  (int_of_string pid, " xenstore"  )
320+         |  _  ->
321+             None 
322+       with  _  ->  None 
323+     in 
324+     if  is_cmdline_valid ~pid  ~pid_source  (D. expected_cmdline_items ~domid ) then 
325+       Some  pid
326+     else 
327+       None 
284328
285329  let  is_running  ~xs   domid  = 
286330    match  pid ~xs  domid with 
@@ -362,6 +406,8 @@ module Qemu = struct
362406    let  name =  name
363407
364408    let  pid_location =  Pid. Path_of  {key=  pidxenstore_path; file=  pidfile_path}
409+ 
410+     let  expected_cmdline_items  ~domid   =  [Printf. sprintf " qemu-dm-%d"   domid]
365411  end )
366412
367413  module  SignalMask  =  D. SignalMask 
@@ -404,12 +450,16 @@ module Qemu = struct
404450end 
405451
406452module  Vgpu  =  struct 
453+   let  domain_arg  domid  =  Printf. sprintf " --domain=%d"   domid
454+ 
407455  module  D  =  DaemonMgmt  (struct 
408456    let  name =  " vgpu" 
409457
410458    let  pid_path  domid  =  Printf. sprintf " /local/domain/%d/vgpu-pid"   domid
411459
412460    let  pid_location =  Pid. Xenstore  pid_path
461+ 
462+     let  expected_cmdline_items  ~domid   =  [! Xc_resources. vgpu; domain_arg domid]
413463  end )
414464
415465  (* * An NVidia Virtual Compute Service vGPU has a class attribute
@@ -507,7 +557,7 @@ module Vgpu = struct
507557    let  suspend_file =  Printf. sprintf Device_common. demu_save_path domid in 
508558    let  base_args = 
509559      [
510-         " --domain= "   ^  string_of_int  domid
560+         domain_arg  domid
511561      ; " --vcpus="   ^  string_of_int vcpus
512562      ; " --suspend="   ^  suspend_file
513563      ]
@@ -612,6 +662,9 @@ module Varstored = struct
612662    let  name =  name
613663
614664    let  pid_location =  Pid. Path_of  {key=  pidxenstore_path; file=  pidfile_path}
665+ 
666+     let  expected_cmdline_items  ~domid   = 
667+       [! Xc_resources. varstored; pidfile_path domid]
615668  end )
616669
617670  let  efivars_resume_path = 
@@ -686,6 +739,8 @@ module Swtpm = struct
686739    let  name =  " swtpm" 
687740
688741    let  pid_location =  Pid. File  pidfile_path
742+ 
743+     let  expected_cmdline_items  ~domid   =  [Printf. sprintf " swtpm-%d"   domid]
689744  end )
690745
691746  let  xs_path  ~domid   =  Device_common. get_private_path domid ^  " /vtpm" 
@@ -809,13 +864,19 @@ module PV_Vnc = struct
809864  let  pidxenstore_path  domid  = 
810865    Printf. sprintf " /local/domain/%d/vncterm-pid"   domid
811866
867+   let  vnc_console_path  domid  =  Printf. sprintf " /local/domain/%d/console"   domid
868+ 
812869  module  D  =  DaemonMgmt  (struct 
813870    let  name =  " vncterm" 
814871
815872    let  pid_location =  Pid. Xenstore  pidxenstore_path
816-   end )
817873
818-   let  vnc_console_path  domid  =  Printf. sprintf " /local/domain/%d/console"   domid
874+     let  expected_cmdline_items  ~domid   = 
875+       [
876+         ! Xc_resources. vncterm (*  vncterm binary path *) 
877+       ; vnc_console_path domid (*  xenstore console path *) 
878+       ]
879+   end )
819880
820881  let  vnc_port_path  domid  = 
821882    Printf. sprintf " /local/domain/%d/console/vnc-port"   domid
@@ -825,36 +886,15 @@ module PV_Vnc = struct
825886
826887  let  pid  ~xs   domid  =  D. pid ~xs  domid
827888
828-   (*  Look up the commandline args for the vncterm pid; *) 
829-   (*  Check that they include the vncterm binary path and the xenstore console
830-      path for the supplied domid. *)  
831-   let  is_cmdline_valid  domid  pid  = 
832-     try 
833-       let  cmdline = 
834-         Printf. sprintf " /proc/%d/cmdline"   pid
835-         |>  Unixext. string_of_file
836-         |>  Astring.String. cuts ~sep: " \000 " 
837-       in 
838-       List. mem ! Xc_resources. vncterm cmdline
839-       &&  List. mem (vnc_console_path domid) cmdline
840-     with  _  ->  false 
841- 
842-   let  is_vncterm_running  ~xs   domid  = 
843-     match  pid ~xs  domid with 
844-     |  None  ->
845-         false 
846-     |  Some  p  ->
847-         D. is_running ~xs  domid &&  is_cmdline_valid domid p
848- 
849889  let  get_vnc_port  ~xs   domid  = 
850-     if  not  (is_vncterm_running  ~xs  domid) then 
890+     if  not  (D. is_running  ~xs  domid) then 
851891      None 
852892    else 
853893      try  Some  (Socket. Port  (int_of_string (xs.Xs. read (vnc_port_path domid))))
854894      with  _  ->  None 
855895
856896  let  get_tc_port  ~xs   domid  = 
857-     if  not  (is_vncterm_running  ~xs  domid) then 
897+     if  not  (D. is_running  ~xs  domid) then 
858898      None 
859899    else 
860900      try  Some  (int_of_string (xs.Xs. read (tc_port_path domid)))
@@ -913,7 +953,7 @@ module PV_Vnc = struct
913953    let  l = 
914954      [
915955        " -x" 
916-       ; Printf. sprintf  " /local/domain/%d/console "   domid
956+       ; vnc_console_path  domid
917957      ; " -T" 
918958      ; (*  listen for raw connections *) 
919959        " -v" 
0 commit comments