@@ -888,6 +888,8 @@ func (e *execveCall) getProcess() *process {
888888 if idx := bytes .IndexByte (e .Path [:], 0 ); idx >= 0 {
889889 // Fast path if we already have the path.
890890 p .path = string (e .Path [:idx ])
891+ // Keep the basename in case we can't get the process name.
892+ p .name = filepath .Base (p .path )
891893 } else {
892894 // Attempt to get the path from the /prox/<pid>/exe symlink.
893895 var err error
@@ -896,9 +898,13 @@ func (e *execveCall) getProcess() *process {
896898 if pe , ok := err .(* os.PathError ); ok && strings .Contains (pe .Path , "(deleted)" ) {
897899 // Keep the deleted path from the PathError.
898900 p .path = pe .Path
901+ // Keep the basename in case we can't get the process name.
902+ p .name = filepath .Base (strings .TrimSuffix (p .path , " (deleted)" ))
899903 } else {
900904 // Fallback to the truncated path.
901905 p .path = string (e .Path [:]) + " ..."
906+ // Don't trim the ellipsis to indicate this may be incorrect.
907+ p .name = filepath .Base (p .path )
902908 }
903909 }
904910 }
@@ -943,8 +949,24 @@ func (e *execveCall) getProcess() *process {
943949 }
944950 }
945951
946- // Get name from first argument.
947- p .name = filepath .Base (p .args [0 ])
952+ // Carefully get the process name; we may have zero arguments.
953+ if len (p .args ) != 0 {
954+ // Get name from first argument.
955+ p .name = filepath .Base (p .args [0 ])
956+ } else {
957+ // Attempt to get name from /proc/<pid>/comm — only available since 2.6.33.
958+ comm , err := os .ReadFile (fmt .Sprintf ("/proc/%d/comm" , e .Meta .PID ))
959+ if err == nil {
960+ p .name = strings .TrimRight (string (comm ), "\x00 " )
961+ if len (p .name ) == 16 {
962+ // The name may have been truncated if it is TASK_COMM_LEN long.
963+ p .name += "..."
964+ }
965+ } else if p .name == "" {
966+ // This should never happen.
967+ p .name = "(unknown)"
968+ }
969+ }
948970
949971 if e .creds != nil {
950972 p .hasCreds = true
0 commit comments