sandbox: write uid/gid map as init
This avoids PR_SET_DUMPABLE in the parent process. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
		
							parent
							
								
									94895bbacb
								
							
						
					
					
						commit
						f41fd94628
					
				| @ -58,10 +58,6 @@ type ( | ||||
| 		InitParams | ||||
| 		// Custom [exec.Cmd] initialisation function. | ||||
| 		CommandContext func(ctx context.Context) (cmd *exec.Cmd) | ||||
| 		// mapped uid in user namespace | ||||
| 		Uid int | ||||
| 		// mapped gid in user namespace | ||||
| 		Gid int | ||||
| 
 | ||||
| 		// param encoder for shim and init | ||||
| 		setup *gob.Encoder | ||||
| @ -86,6 +82,10 @@ type ( | ||||
| 		// Initial process argv. | ||||
| 		Args []string | ||||
| 
 | ||||
| 		// Mapped Uid in user namespace. | ||||
| 		Uid int | ||||
| 		// Mapped Gid in user namespace. | ||||
| 		Gid int | ||||
| 		// Hostname value in UTS namespace. | ||||
| 		Hostname string | ||||
| 		// Sequential container setup ops. | ||||
| @ -140,8 +140,6 @@ func (p *Container) Start() error { | ||||
| 			syscall.CLONE_NEWPID | | ||||
| 			syscall.CLONE_NEWNS, | ||||
| 
 | ||||
| 		UidMappings: []syscall.SysProcIDMap{{p.Uid, syscall.Getuid(), 1}}, | ||||
| 		GidMappings: []syscall.SysProcIDMap{{p.Gid, syscall.Getgid(), 1}}, | ||||
| 		// remain privileged for setup | ||||
| 		AmbientCaps: []uintptr{CAP_SYS_ADMIN}, | ||||
| 
 | ||||
| @ -200,6 +198,8 @@ func (p *Container) Serve() error { | ||||
| 	return setup.Encode( | ||||
| 		&initParams{ | ||||
| 			p.InitParams, | ||||
| 			syscall.Getuid(), | ||||
| 			syscall.Getgid(), | ||||
| 			len(p.ExtraFiles), | ||||
| 			fmsg.Load(), | ||||
| 		}, | ||||
|  | ||||
| @ -9,6 +9,7 @@ import ( | ||||
| 	"os/exec" | ||||
| 	"path" | ||||
| 	"slices" | ||||
| 	"syscall" | ||||
| 	"testing" | ||||
| 	"time" | ||||
| 
 | ||||
| @ -65,6 +66,8 @@ func TestContainer(t *testing.T) { | ||||
| 
 | ||||
| 			container := sandbox.New(ctx, os.Args[0], "-test.v", | ||||
| 				"-test.run=TestHelperCheckContainer", "--", "check", tc.host) | ||||
| 			container.Uid = 1000 | ||||
| 			container.Gid = 100 | ||||
| 			container.Hostname = tc.host | ||||
| 			container.CommandContext = func(ctx context.Context) *exec.Cmd { | ||||
| 				return exec.CommandContext(ctx, os.Args[0], "-test.v", | ||||
| @ -154,6 +157,14 @@ func TestHelperCheckContainer(t *testing.T) { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	t.Run("user", func(t *testing.T) { | ||||
| 		if uid := syscall.Getuid(); uid != 1000 { | ||||
| 			t.Errorf("Getuid: %d, want 1000", uid) | ||||
| 		} | ||||
| 		if gid := syscall.Getgid(); gid != 100 { | ||||
| 			t.Errorf("Getgid: %d, want 100", gid) | ||||
| 		} | ||||
| 	}) | ||||
| 	t.Run("hostname", func(t *testing.T) { | ||||
| 		if name, err := os.Hostname(); err != nil { | ||||
| 			t.Fatalf("cannot get hostname: %v", err) | ||||
|  | ||||
| @ -33,6 +33,7 @@ const ( | ||||
| type initParams struct { | ||||
| 	InitParams | ||||
| 
 | ||||
| 	HostUid, HostGid int | ||||
| 	// extra files count | ||||
| 	Count int | ||||
| 	// verbosity pass through | ||||
| @ -43,10 +44,6 @@ func Init(exit func(code int)) { | ||||
| 	runtime.LockOSThread() | ||||
| 	fmsg.Prepare("init") | ||||
| 
 | ||||
| 	if err := internal.SetDumpable(internal.SUID_DUMP_DISABLE); err != nil { | ||||
| 		log.Fatalf("cannot set SUID_DUMP_DISABLE: %s", err) | ||||
| 	} | ||||
| 
 | ||||
| 	if os.Getpid() != 1 { | ||||
| 		log.Fatal("this process must run as pid 1") | ||||
| 	} | ||||
| @ -80,6 +77,29 @@ func Init(exit func(code int)) { | ||||
| 		offsetSetup = int(setupFile.Fd() + 1) | ||||
| 	} | ||||
| 
 | ||||
| 	// write uid/gid map here so parent does not need to set dumpable | ||||
| 	if err := internal.SetDumpable(internal.SUID_DUMP_USER); err != nil { | ||||
| 		log.Fatalf("cannot set SUID_DUMP_USER: %s", err) | ||||
| 	} | ||||
| 	if err := os.WriteFile("/proc/self/uid_map", | ||||
| 		append([]byte{}, strconv.Itoa(params.Uid)+" "+strconv.Itoa(params.HostUid)+" 1\n"...), | ||||
| 		0); err != nil { | ||||
| 		log.Fatalf("%v", err) | ||||
| 	} | ||||
| 	if err := os.WriteFile("/proc/self/setgroups", | ||||
| 		[]byte("deny\n"), | ||||
| 		0); err != nil && !os.IsNotExist(err) { | ||||
| 		log.Fatalf("%v", err) | ||||
| 	} | ||||
| 	if err := os.WriteFile("/proc/self/gid_map", | ||||
| 		append([]byte{}, strconv.Itoa(params.Gid)+" "+strconv.Itoa(params.HostGid)+" 1\n"...), | ||||
| 		0); err != nil { | ||||
| 		log.Fatalf("%v", err) | ||||
| 	} | ||||
| 	if err := internal.SetDumpable(internal.SUID_DUMP_DISABLE); err != nil { | ||||
| 		log.Fatalf("cannot set SUID_DUMP_DISABLE: %s", err) | ||||
| 	} | ||||
| 
 | ||||
| 	if params.Hostname != "" { | ||||
| 		if err := syscall.Sethostname([]byte(params.Hostname)); err != nil { | ||||
| 			log.Fatalf("cannot set hostname: %v", err) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user