@@ -38,6 +38,10 @@ import (
3838 "gvisor.dev/gvisor/pkg/usermem"
3939)
4040
41+ const (
42+ securityCapability = linux .XATTR_SECURITY_PREFIX + "capability"
43+ )
44+
4145// LoadArgs holds specifications for an executable file to be loaded.
4246type LoadArgs struct {
4347 // MemoryManager is the memory manager to load the executable into.
@@ -236,6 +240,18 @@ func loadExecutable(ctx context.Context, args LoadArgs) (loadedELF, *arch.Contex
236240 return loadedELF {}, nil , nil , nil , linuxerr .ELOOP
237241}
238242
243+ // ImageInfo represents the information for the loaded image.
244+ type ImageInfo struct {
245+ // The target operating system of the image.
246+ OS abi.OS
247+ // AMD64 context.
248+ Arch * arch.Context64
249+ // The base name of the binary.
250+ Name string
251+ // The binary's file capability.
252+ FileCaps string
253+ }
254+
239255// Load loads args.File into a MemoryManager. If args.File is nil, the path
240256// args.Filename is resolved and loaded instead.
241257//
@@ -245,48 +261,55 @@ func loadExecutable(ctx context.Context, args LoadArgs) (loadedELF, *arch.Contex
245261// Preconditions:
246262// - The Task MemoryManager is empty.
247263// - Load is called on the Task goroutine.
248- func Load (ctx context.Context , args LoadArgs , extraAuxv []arch.AuxEntry , vdso * VDSO ) (abi. OS , * arch. Context64 , string , * syserr.Error ) {
264+ func Load (ctx context.Context , args LoadArgs , extraAuxv []arch.AuxEntry , vdso * VDSO ) (ImageInfo , * syserr.Error ) {
249265 // Load the executable itself.
250266 loaded , ac , file , newArgv , err := loadExecutable (ctx , args )
251267 if err != nil {
252- return 0 , nil , "" , syserr .NewDynamic (fmt .Sprintf ("failed to load %s: %v" , args .Filename , err ), syserr .FromError (err ).ToLinux ())
268+ return ImageInfo {} , syserr .NewDynamic (fmt .Sprintf ("failed to load %s: %v" , args .Filename , err ), syserr .FromError (err ).ToLinux ())
253269 }
254270 defer file .DecRef (ctx )
271+ xattr , err := file .GetXattr (ctx , & vfs.GetXattrOptions {Name : securityCapability , Size : linux .XATTR_CAPS_SZ_3 })
272+ switch {
273+ case linuxerr .Equals (linuxerr .ENODATA , err ), linuxerr .Equals (linuxerr .ENOTSUP , err ):
274+ xattr = ""
275+ case err != nil :
276+ return ImageInfo {}, syserr .NewDynamic (fmt .Sprintf ("failed to read file capabilities of %s: %v" , args .Filename , err ), syserr .FromError (err ).ToLinux ())
277+ }
255278
256279 // Load the VDSO.
257280 vdsoAddr , err := loadVDSO (ctx , args .MemoryManager , vdso , loaded )
258281 if err != nil {
259- return 0 , nil , "" , syserr .NewDynamic (fmt .Sprintf ("error loading VDSO: %v" , err ), syserr .FromError (err ).ToLinux ())
282+ return ImageInfo {} , syserr .NewDynamic (fmt .Sprintf ("error loading VDSO: %v" , err ), syserr .FromError (err ).ToLinux ())
260283 }
261284
262285 // Setup the heap. brk starts at the next page after the end of the
263286 // executable. Userspace can assume that the remainder of the page after
264287 // loaded.end is available for its use.
265288 e , ok := loaded .end .RoundUp ()
266289 if ! ok {
267- return 0 , nil , "" , syserr .NewDynamic (fmt .Sprintf ("brk overflows: %#x" , loaded .end ), errno .ENOEXEC )
290+ return ImageInfo {} , syserr .NewDynamic (fmt .Sprintf ("brk overflows: %#x" , loaded .end ), errno .ENOEXEC )
268291 }
269292 args .MemoryManager .BrkSetup (ctx , e )
270293
271294 // Allocate our stack.
272295 stack , err := allocStack (ctx , args .MemoryManager , ac )
273296 if err != nil {
274- return 0 , nil , "" , syserr .NewDynamic (fmt .Sprintf ("Failed to allocate stack: %v" , err ), syserr .FromError (err ).ToLinux ())
297+ return ImageInfo {} , syserr .NewDynamic (fmt .Sprintf ("Failed to allocate stack: %v" , err ), syserr .FromError (err ).ToLinux ())
275298 }
276299
277300 // Push the original filename to the stack, for AT_EXECFN.
278301 if _ , err := stack .PushNullTerminatedByteSlice ([]byte (args .Filename )); err != nil {
279- return 0 , nil , "" , syserr .NewDynamic (fmt .Sprintf ("Failed to push exec filename: %v" , err ), syserr .FromError (err ).ToLinux ())
302+ return ImageInfo {} , syserr .NewDynamic (fmt .Sprintf ("Failed to push exec filename: %v" , err ), syserr .FromError (err ).ToLinux ())
280303 }
281304 execfn := stack .Bottom
282305
283306 // Push 16 random bytes on the stack which AT_RANDOM will point to.
284307 var b [16 ]byte
285308 if _ , err := rand .Read (b [:]); err != nil {
286- return 0 , nil , "" , syserr .NewDynamic (fmt .Sprintf ("Failed to read random bytes: %v" , err ), syserr .FromError (err ).ToLinux ())
309+ return ImageInfo {} , syserr .NewDynamic (fmt .Sprintf ("Failed to read random bytes: %v" , err ), syserr .FromError (err ).ToLinux ())
287310 }
288311 if _ , err = stack .PushNullTerminatedByteSlice (b [:]); err != nil {
289- return 0 , nil , "" , syserr .NewDynamic (fmt .Sprintf ("Failed to push random bytes: %v" , err ), syserr .FromError (err ).ToLinux ())
312+ return ImageInfo {} , syserr .NewDynamic (fmt .Sprintf ("Failed to push random bytes: %v" , err ), syserr .FromError (err ).ToLinux ())
290313 }
291314 random := stack .Bottom
292315
@@ -311,7 +334,7 @@ func Load(ctx context.Context, args LoadArgs, extraAuxv []arch.AuxEntry, vdso *V
311334
312335 sl , err := stack .Load (newArgv , args .Envv , auxv )
313336 if err != nil {
314- return 0 , nil , "" , syserr .NewDynamic (fmt .Sprintf ("Failed to load stack: %v" , err ), syserr .FromError (err ).ToLinux ())
337+ return ImageInfo {} , syserr .NewDynamic (fmt .Sprintf ("Failed to load stack: %v" , err ), syserr .FromError (err ).ToLinux ())
315338 }
316339
317340 m := args .MemoryManager
@@ -331,5 +354,10 @@ func Load(ctx context.Context, args LoadArgs, extraAuxv []arch.AuxEntry, vdso *V
331354 name = name [:linux .TASK_COMM_LEN - 1 ]
332355 }
333356
334- return loaded .os , ac , name , nil
357+ return ImageInfo {
358+ OS : loaded .os ,
359+ Arch : ac ,
360+ Name : name ,
361+ FileCaps : xattr ,
362+ }, nil
335363}
0 commit comments