@@ -130,6 +130,56 @@ func cvdDataHome() (string, error) {
130130 }
131131 return "" , fmt .Errorf ("failed to find cvd data home dir" )
132132}
133+
134+ func resolveHostPath (path string ) string {
135+ if strings .TrimSpace (path ) == "" {
136+ return ""
137+ }
138+ absPath , err := filepath .Abs (path )
139+ if err != nil {
140+ return ""
141+ }
142+ if _ , err := os .Stat (absPath ); err != nil {
143+ return ""
144+ }
145+ if strings .HasPrefix (absPath , "/dev/" ) || strings .HasPrefix (absPath , "/sys/" ) || strings .HasPrefix (absPath , "/proc/" ) {
146+ return ""
147+ }
148+ return absPath
149+ }
150+
151+ func collectMountSpecs (pathsToMount []string , hostOut , productOut , cvdDataHome , podcvdHomeDir string ) []string {
152+ bindMap := make (map [string ]string )
153+ bindMap ["/host_out" ] = fmt .Sprintf ("%s:/host_out:O" , hostOut )
154+ bindMap ["/product_out" ] = fmt .Sprintf ("%s:/product_out:O" , productOut )
155+ bindMap ["/root/.local/share/cvd" ] = fmt .Sprintf ("%s:/root/.local/share/cvd:ro" , cvdDataHome )
156+ bindMap ["/podcvd_home" ] = fmt .Sprintf ("%s:/podcvd_home:rw" , podcvdHomeDir )
157+ for _ , p := range pathsToMount {
158+ if spec , ok := bindMap [p ]; ok {
159+ host := strings .SplitN (spec , ":" , 2 )[0 ]
160+ if host != p {
161+ log .Printf ("warning: container path %q is already mounted to %q, cannot mount %q\n " , p , host , p )
162+ }
163+ continue
164+ }
165+ pInfo , err := os .Stat (p )
166+ if err != nil {
167+ log .Printf ("warning: failed to stat path %q to mount: %v\n " , p , err )
168+ continue
169+ }
170+ opt := "ro"
171+ if pInfo .IsDir () {
172+ opt = "O"
173+ }
174+ bindMap [p ] = fmt .Sprintf ("%s:%s:%s" , p , p , opt )
175+ }
176+ var specs []string
177+ for _ , spec := range bindMap {
178+ specs = append (specs , spec )
179+ }
180+ return specs
181+ }
182+
133183func appendPortFlags (flags []string , hostIP string , protocol string , portStart int , portEnd int ) []string {
134184 for port := portStart ; port <= portEnd ; port ++ {
135185 flags = append (flags , "-p" , fmt .Sprintf ("%s:%d:%d/%s" , hostIP , port , port , protocol ))
@@ -219,6 +269,22 @@ func createAndStartContainer(ccm CuttlefishContainerManager, cvdArgs *CvdArgs) (
219269 if err := os .MkdirAll (podcvdHomeDir , 0755 ); err != nil {
220270 return "" , fmt .Errorf ("failed to create podcvd home dir: %w" , err )
221271 }
272+ var pathsToMount []string
273+ for _ , arg := range cvdArgs .SubCommandArgs {
274+ path := arg
275+ if strings .Contains (arg , "=" ) {
276+ path = strings .SplitN (arg , "=" , 2 )[1 ]
277+ }
278+ absPath := resolveHostPath (path )
279+ if absPath == "" {
280+ continue
281+ }
282+ pathsToMount = append (pathsToMount , absPath )
283+ if realPath , err := filepath .EvalSymlinks (absPath ); err == nil && realPath != absPath {
284+ pathsToMount = append (pathsToMount , realPath )
285+ }
286+ }
287+ mountSpecs := collectMountSpecs (pathsToMount , hostOut , productOut , cvdDataHome , podcvdHomeDir )
222288
223289 extraFlags := []string {
224290 "-e" , "ANDROID_HOST_OUT=/host_out" ,
@@ -230,71 +296,14 @@ func createAndStartContainer(ccm CuttlefishContainerManager, cvdArgs *CvdArgs) (
230296 "--cap-add" , "NET_RAW" ,
231297 "--pids-limit" , "8192" ,
232298 }
299+ for _ , spec := range mountSpecs {
300+ extraFlags = append (extraFlags , "-v" , spec )
301+ }
233302 clientID := os .Getenv (envClientID )
234303 if clientID != "" {
235304 extraFlags = append (extraFlags , "--label" , fmt .Sprintf ("%s=%s" , labelClientID , clientID ))
236305 }
237306
238- bindMap := make (map [string ]string )
239- bindMap ["/host_out" ] = fmt .Sprintf ("%s:/host_out:O" , hostOut )
240- bindMap ["/product_out" ] = fmt .Sprintf ("%s:/product_out:O" , productOut )
241- bindMap ["/root/.local/share/cvd" ] = fmt .Sprintf ("%s:/root/.local/share/cvd:ro" , cvdDataHome )
242- bindMap ["/podcvd_home" ] = fmt .Sprintf ("%s:/podcvd_home:rw" , podcvdHomeDir )
243- for _ , arg := range cvdArgs .SubCommandArgs {
244- path := arg
245- if strings .Contains (arg , "=" ) {
246- path = strings .SplitN (arg , "=" , 2 )[1 ]
247- }
248-
249- // 1. Filter out empty strings which would incorrectly mount the CWD
250- if strings .TrimSpace (path ) == "" {
251- continue
252- }
253-
254- absPath , err := filepath .Abs (path )
255- if err != nil {
256- continue
257- }
258- if _ , err := os .Stat (absPath ); err != nil {
259- continue
260- }
261- // Prevent mounting critical system directories
262- if strings .HasPrefix (absPath , "/dev/" ) || strings .HasPrefix (absPath , "/sys/" ) || strings .HasPrefix (absPath , "/proc/" ) {
263- continue
264- }
265-
266- pathsToMount := []string {absPath }
267-
268- // 2. Resolve symlinks and track the target file to ensure it's accessible inside
269- if realPath , err := filepath .EvalSymlinks (absPath ); err == nil && realPath != absPath {
270- pathsToMount = append (pathsToMount , realPath )
271- }
272-
273- // 3. Add to mount configuration while preventing duplicates
274- for _ , p := range pathsToMount {
275- if spec , ok := bindMap [p ]; ok {
276- host := strings .SplitN (spec , ":" , 2 )[0 ]
277- if host != p {
278- log .Printf ("warning: container path %q is already mounted to %q, cannot mount %q\n " , p , host , p )
279- }
280- continue
281- }
282- pInfo , err := os .Stat (p )
283- if err != nil {
284- log .Printf ("warning: failed to stat path %q to mount: %v\n " , p , err )
285- continue
286- }
287- opt := "ro"
288- if pInfo .IsDir () {
289- opt = "O"
290- }
291- bindMap [p ] = fmt .Sprintf ("%s:%s:%s" , p , p , opt )
292- }
293- }
294- for _ , mountSpec := range bindMap {
295- extraFlags = append (extraFlags , "-v" , mountSpec )
296- }
297-
298307 var lastErr error
299308 for retryCount := 0 ; retryCount < 10 ; retryCount ++ {
300309 groupNameIpAddrMap , err := Ipv4AddressesByGroupNames (ccm , true )
0 commit comments