@@ -102,20 +102,13 @@ func (w *bufferWriter) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, error) {
102102//
103103// +stateify savable
104104type auxvData struct {
105- kernfs.DynamicBytesFile
106-
107- task * kernel.Task
105+ mm * mm.MemoryManager
108106}
109107
110- var _ dynamicInode = (* auxvData )(nil )
111-
112108// Generate implements vfs.DynamicBytesSource.Generate.
113109func (d * auxvData ) Generate (ctx context.Context , buf * bytes.Buffer ) error {
114- if d .task .ExitState () == kernel .TaskExitDead {
115- return linuxerr .ESRCH
116- }
117- m , err := getMMIncRef (d .task )
118- if err != nil {
110+ m := d .mm
111+ if m == nil || ! m .IncUsers () {
119112 // Return empty file.
120113 return nil
121114 }
@@ -228,25 +221,19 @@ func GetMetadata(ctx context.Context, mm *mm.MemoryManager, buf *bytes.Buffer, t
228221 return nil
229222}
230223
231- // metadataData implements vfs.DynamicBytesSource for proc metadata fields like:
232- //
233- // - /proc/[pid]/cmdline
234- // - /proc/[pid]/environ
224+ // cmdlineData implements vfs.DynamicBytesSource for /proc/[pid]/cmdline:
235225//
236226// +stateify savable
237- type metadataData struct {
227+ type cmdlineData struct {
238228 kernfs.DynamicBytesFile
239229
240230 task * kernel.Task
241-
242- // arg is the type of exec argument this file contains.
243- metaType MetadataType
244231}
245232
246- var _ dynamicInode = (* metadataData )(nil )
233+ var _ dynamicInode = (* cmdlineData )(nil )
247234
248235// Generate implements vfs.DynamicBytesSource.Generate.
249- func (d * metadataData ) Generate (ctx context.Context , buf * bytes.Buffer ) error {
236+ func (d * cmdlineData ) Generate (ctx context.Context , buf * bytes.Buffer ) error {
250237 if d .task .ExitState () == kernel .TaskExitDead {
251238 return linuxerr .ESRCH
252239 }
@@ -256,7 +243,25 @@ func (d *metadataData) Generate(ctx context.Context, buf *bytes.Buffer) error {
256243 return nil
257244 }
258245 defer m .DecUsers (ctx )
259- return GetMetadata (ctx , m , buf , d .metaType )
246+ return GetMetadata (ctx , m , buf , Cmdline )
247+ }
248+
249+ // environData implements vfs.DynamicBytesSource for /proc/[pid]/environ:
250+ //
251+ // +stateify savable
252+ type environData struct {
253+ mm * mm.MemoryManager
254+ }
255+
256+ // Generate implements vfs.DynamicBytesSource.Generate.
257+ func (d * environData ) Generate (ctx context.Context , buf * bytes.Buffer ) error {
258+ m := d .mm
259+ if m == nil || ! m .IncUsers () {
260+ // Return empty file.
261+ return nil
262+ }
263+ defer m .DecUsers (ctx )
264+ return GetMetadata (ctx , m , buf , Environ )
260265}
261266
262267// +stateify savable
@@ -444,11 +449,20 @@ func (f *memInode) init(ctx context.Context, creds *auth.Credentials, devMajor,
444449
445450// Open implements kernfs.Inode.Open.
446451func (f * memInode ) Open (ctx context.Context , rp * vfs.ResolvingPath , d * kernfs.Dentry , opts vfs.OpenOptions ) (* vfs.FileDescription , error ) {
447- // TODO(gvisor.dev/issue/260): Add check for PTRACE_MODE_ATTACH_FSCREDS
448- // Permission to read this file is governed by PTRACE_MODE_ATTACH_FSCREDS
449- // Since we dont implement setfsuid/setfsgid we can just use PTRACE_MODE_ATTACH
450- if ! kernel .ContextCanTrace (ctx , f .task , true ) {
451- return nil , linuxerr .EACCES
452+ m := getMM (f .task )
453+ for {
454+ // TODO(gvisor.dev/issue/260): Add check for PTRACE_MODE_ATTACH_FSCREDS
455+ // Permission to read this file is governed by PTRACE_MODE_ATTACH_FSCREDS
456+ // Since we dont implement setfsuid/setfsgid we can just use PTRACE_MODE_ATTACH
457+ if ! kernel .ContextCanTrace (ctx , f .task , true ) {
458+ return nil , linuxerr .EACCES
459+ }
460+ // Check that the task still has the same mm (hasn't called execve).
461+ m2 := getMM (f .task )
462+ if m == m2 {
463+ break
464+ }
465+ m = m2
452466 }
453467 if err := checkTaskState (f .task ); err != nil {
454468 return nil , err
@@ -624,7 +638,6 @@ func (d *limitsData) Generate(ctx context.Context, buf *bytes.Buffer) error {
624638 } else {
625639 fmt .Fprintf (buf , "%-20d " , l .Max )
626640 }
627-
628641 if u := lt .Unit (); u != "" {
629642 fmt .Fprintf (buf , "%-10s" , u )
630643 }
@@ -634,41 +647,99 @@ func (d *limitsData) Generate(ctx context.Context, buf *bytes.Buffer) error {
634647 return nil
635648}
636649
637- // mapsData implements vfs.DynamicBytesSource for /proc/[pid]/maps .
650+ // mmFile implements vfs.DynamicBytesSource for files that links with a process mm .
638651//
639652// +stateify savable
640- type mapsData struct {
653+ type mmFile struct {
641654 kernfs.DynamicBytesFile
642655
643- task * kernel.Task
656+ ftype mmFileType
657+ task * kernel.Task
644658}
645659
646- var _ dynamicInode = (* mapsData )(nil )
660+ type mmFileType int
661+
662+ const (
663+ mapsMMFile mmFileType = iota
664+ smapsMMFile
665+ auxvMMFile
666+ environMMFile
667+ cmdlineMMFile
668+ )
669+
670+ var _ dynamicInode = (* mmFile )(nil )
671+
672+ func (f * mmFile ) Init (ctx context.Context , creds * auth.Credentials , devMajor , devMinor uint32 , ino uint64 , data vfs.DynamicBytesSource , perm linux.FileMode ) {
673+ f .DynamicBytesFile .Init (ctx , creds , devMajor , devMinor , ino , nil , perm )
674+ f .SetDataSourceProvider (f )
675+ }
676+
677+ // DataSource implements kernfs.DataSourceProvider.DataSource()
678+ func (f * mmFile ) DataSource (ctx context.Context ) (vfs.DynamicBytesSource , error ) {
679+ m := getMM (f .task )
680+ for {
681+ if ! kernel .ContextCanTrace (ctx , f .task , false ) {
682+ return nil , linuxerr .EACCES
683+ }
684+ // Check that the task still has the same mm (hasn't called execve).
685+ m2 := getMM (f .task )
686+ if m == m2 {
687+ break
688+ }
689+ m = m2
690+ }
691+ switch f .ftype {
692+ case mapsMMFile :
693+ return & mapsData {mm : m }, nil
694+ case smapsMMFile :
695+ return & smapsData {mm : m }, nil
696+ case environMMFile :
697+ return & environData {mm : m }, nil
698+ case auxvMMFile :
699+ return & auxvData {mm : m }, nil
700+ default :
701+ panic (fmt .Sprintf ("unknown file type: %d" , f .ftype ))
702+ }
703+ }
704+
705+ var _ kernfs.DataSourceProvider = (* mmFile )(nil )
706+
707+ // Generate implements vfs.DynamicBytesSource.Generate.
708+ func (f * mmFile ) Generate (ctx context.Context , buf * bytes.Buffer ) error {
709+ panic ("unreachable" )
710+ }
711+
712+ // mapsData implements vfs.DynamicBytesSource for /proc/[pid]/maps.
713+ //
714+ // +stateify savable
715+ type mapsData struct {
716+ mm * mm.MemoryManager
717+ }
647718
648719// Generate implements vfs.DynamicBytesSource.Generate.
649720func (d * mapsData ) Generate (ctx context.Context , buf * bytes.Buffer ) error {
650- if mm := getMM ( d . task ); mm != nil {
651- mm . ReadMapsDataInto ( ctx , mm . MapsCallbackFuncForBuffer ( buf ))
721+ if d . mm == nil || ! d . mm . IncUsers () {
722+ return nil
652723 }
724+ defer d .mm .DecUsers (ctx )
725+ d .mm .ReadMapsDataInto (ctx , d .mm .MapsCallbackFuncForBuffer (buf ))
653726 return nil
654727}
655728
656729// smapsData implements vfs.DynamicBytesSource for /proc/[pid]/smaps.
657730//
658731// +stateify savable
659732type smapsData struct {
660- kernfs.DynamicBytesFile
661-
662- task * kernel.Task
733+ mm * mm.MemoryManager
663734}
664735
665- var _ dynamicInode = (* smapsData )(nil )
666-
667736// Generate implements vfs.DynamicBytesSource.Generate.
668737func (d * smapsData ) Generate (ctx context.Context , buf * bytes.Buffer ) error {
669- if mm := getMM ( d . task ); mm != nil {
670- mm . ReadSmapsDataInto ( ctx , buf )
738+ if d . mm == nil || ! d . mm . IncUsers () {
739+ return nil
671740 }
741+ defer d .mm .DecUsers (ctx )
742+ d .mm .ReadSmapsDataInto (ctx , buf )
672743 return nil
673744}
674745
0 commit comments