@@ -88,18 +88,32 @@ func Essential(logger *slog.Logger, tmpSizeMiB uint32) error {
8888
8989// Workspace mounts a virtiofs share at the given mount point, retrying up to
9090// maxRetries times to allow the host to expose the filesystem. On success the
91- // mount point is chowned to uid:gid.
92- func Workspace (logger * slog.Logger , mountPoint , tag string , uid , gid , maxRetries int ) error {
91+ // mount point is chowned to uid:gid. When readOnly is true the mount is
92+ // performed with MS_RDONLY so the guest cannot write to it.
93+ func Workspace (logger * slog.Logger , mountPoint , tag string , uid , gid , maxRetries int , readOnly bool ) error {
9394 if err := os .MkdirAll (mountPoint , 0o755 ); err != nil {
9495 return fmt .Errorf ("creating workspace mount point %s: %w" , mountPoint , err )
9596 }
9697
98+ flags := uintptr (syscall .MS_NOSUID | syscall .MS_NODEV )
99+ if readOnly {
100+ flags |= syscall .MS_RDONLY
101+ }
102+
97103 var lastErr error
98104 for i := range maxRetries {
99- lastErr = syscall .Mount (tag , mountPoint , "virtiofs" , syscall . MS_NOSUID | syscall . MS_NODEV , "" )
105+ lastErr = syscall .Mount (tag , mountPoint , "virtiofs" , flags , "" )
100106 if lastErr == nil {
101- if err := os .Chown (mountPoint , uid , gid ); err != nil {
102- return fmt .Errorf ("chown workspace %s: %w" , mountPoint , err )
107+ // Skip chown on read-only mounts: chown returns EROFS on a
108+ // filesystem mounted with MS_RDONLY. Ownership is cosmetic
109+ // anyway since the mount prevents writes regardless.
110+ if ! readOnly {
111+ if err := os .Chown (mountPoint , uid , gid ); err != nil {
112+ // Clean up the mount so we don't leave a mounted
113+ // filesystem that the caller thinks failed.
114+ _ = syscall .Unmount (mountPoint , 0 )
115+ return fmt .Errorf ("chown workspace %s: %w" , mountPoint , err )
116+ }
103117 }
104118 return nil
105119 }
0 commit comments