@@ -859,8 +859,10 @@ func (e *inetReleaseCall) Update(s *state) error {
859859// kernels it needs to dump fixed-size arrays in 8-byte chunks. As the total
860860// number of fetchargs available is limited, we have to dump only the first
861861// 128 bytes of every argument.
862- const maxProgArgLen = 128
863- const maxProgArgs = 5
862+ const (
863+ maxProgArgLen = 128
864+ maxProgArgs = 5
865+ )
864866
865867type execveCall struct {
866868 Meta tracing.Metadata `kprobe:"metadata"`
@@ -880,38 +882,78 @@ type execveCall struct {
880882func (e * execveCall ) getProcess () * process {
881883 p := & process {
882884 pid : e .Meta .PID ,
883- path : readCString (e .Path [:]),
884885 created : kernelTime (e .Meta .Timestamp ),
885886 }
886- p .name = filepath .Base (p .path )
887- var argc int
888- for argc = 0 ; argc <= maxProgArgs ; argc ++ {
889- if e .Ptrs [argc ] == 0 {
890- break
887+
888+ if idx := bytes .IndexByte (e .Path [:], 0 ); idx >= 0 {
889+ // Fast path if we already have the path.
890+ p .path = string (e .Path [:idx ])
891+ } else {
892+ // Attempt to get the path from the /prox/<pid>/exe symlink.
893+ var err error
894+ p .path , err = filepath .EvalSymlinks (fmt .Sprintf ("/proc/%d/exe" , e .Meta .PID ))
895+ if err != nil {
896+ if pe , ok := err .(* os.PathError ); ok && strings .Contains (pe .Path , "(deleted)" ) {
897+ // Keep the deleted path from the PathError.
898+ p .path = pe .Path
899+ } else {
900+ // Fallback to the truncated path.
901+ p .path = string (e .Path [:]) + " ..."
902+ }
891903 }
892904 }
893- p .args = make ([]string , argc )
894- params := [maxProgArgs ][]byte {
905+
906+ // Check for truncation of arg list or arguments.
907+ params := [... ][]byte {
895908 e .Param0 [:],
896909 e .Param1 [:],
897910 e .Param2 [:],
898911 e .Param3 [:],
899912 e .Param4 [:],
900913 }
901- limit := argc
902- if limit > maxProgArgs {
903- limit = maxProgArgs
904- p .args [limit ] = "..."
914+ var (
915+ argc int
916+ truncatedArg bool
917+ )
918+ for argc = 0 ; argc < len (e .Ptrs ); argc ++ {
919+ if e .Ptrs [argc ] == 0 {
920+ break
921+ }
922+ if argc < len (params ) && bytes .IndexByte (params [argc ], 0 ) < 0 {
923+ truncatedArg = true
924+ }
925+ }
926+ if argc > maxProgArgs || truncatedArg {
927+ // Attempt to get complete args list from /proc/<pid>/cmdline.
928+ cmdline , err := os .ReadFile (fmt .Sprintf ("/proc/%d/cmdline" , e .Meta .PID ))
929+ if err == nil {
930+ p .args = strings .Split (strings .TrimRight (string (cmdline ), "\x00 " ), "\x00 " )
931+ }
905932 }
906- for i := 0 ; i < limit ; i ++ {
907- p .args [i ] = readCString (params [i ])
933+
934+ if p .args == nil {
935+ // Fallback to arg list if unsuccessful or no truncation.
936+ p .args = make ([]string , argc )
937+ if argc > maxProgArgs {
938+ argc = maxProgArgs
939+ p .args [argc ] = "..."
940+ }
941+ for i , par := range params [:argc ] {
942+ p .args [i ] = readCString (par )
943+ }
908944 }
909- if p .hasCreds = e .creds != nil ; p .hasCreds {
945+
946+ // Get name from first argument.
947+ p .name = filepath .Base (p .args [0 ])
948+
949+ if e .creds != nil {
950+ p .hasCreds = true
910951 p .uid = e .creds .UID
911952 p .gid = e .creds .GID
912953 p .euid = e .creds .EUID
913954 p .egid = e .creds .EGID
914955 }
956+
915957 return p
916958}
917959
0 commit comments