19
19
#include "utils.h"
20
20
#include "xfuncs.h"
21
21
22
- #define CGROUP_DEVICE_ALLOW "devices.allow"
23
- #define CGROUP_DEVICE_STR "c %u:%u %s"
24
-
25
22
static char * mount_files (struct error * , const struct nvc_container * , const char * , char * [], size_t );
26
23
static char * mount_device (struct error * , const struct nvc_container * , const char * );
27
24
static char * mount_ipc (struct error * , const struct nvc_container * , const char * );
25
+ static char * mount_procfs (struct error * , const struct nvc_container * );
26
+ static char * mount_procfs_gpu (struct error * , const struct nvc_container * , const char * );
28
27
static void unmount (const char * );
29
28
static int setup_cgroup (struct error * , const char * , dev_t );
30
29
static int symlink_library (struct error * , const char * , const char * , const char * , const char * , uid_t , gid_t );
@@ -129,10 +128,95 @@ mount_ipc(struct error *err, const struct nvc_container *cnt, const char *ipc)
129
128
return (NULL );
130
129
}
131
130
131
+ static char *
132
+ mount_procfs (struct error * err , const struct nvc_container * cnt )
133
+ {
134
+ char path [PATH_MAX ];
135
+ char * ptr , * mnt , * param ;
136
+ mode_t mode ;
137
+ char * buf = NULL ;
138
+ const char * files [] = {
139
+ NV_PROC_DRIVER "/params" ,
140
+ NV_PROC_DRIVER "/version" ,
141
+ NV_PROC_DRIVER "/registry" ,
142
+ };
143
+
144
+ if (path_resolve (err , path , cnt -> cfg .rootfs , NV_PROC_DRIVER ) < 0 )
145
+ return (NULL );
146
+ log_infof ("mounting tmpfs at %s" , path );
147
+ if (xmount (err , "tmpfs" , path , "tmpfs" , 0 , "mode=0555" ) < 0 )
148
+ return (NULL );
149
+
150
+ ptr = path + strlen (path );
151
+
152
+ for (size_t i = 0 ; i < nitems (files ); ++ i ) {
153
+ if (file_mode (err , files [i ], & mode ) < 0 ) {
154
+ if (err -> code == ENOENT )
155
+ continue ;
156
+ goto fail ;
157
+ }
158
+ if (file_read_text (err , files [i ], & buf ) < 0 )
159
+ goto fail ;
160
+ /* Prevent NVRM from ajusting the device nodes. */
161
+ if (i == 0 && (param = strstr (buf , "ModifyDeviceFiles: 1" )) != NULL )
162
+ param [19 ] = '0' ;
163
+ if (path_append (err , path , basename (files [i ])) < 0 )
164
+ goto fail ;
165
+ if (file_create (err , path , buf , cnt -> uid , cnt -> gid , mode ) < 0 )
166
+ goto fail ;
167
+ * ptr = '\0' ;
168
+ free (buf );
169
+ buf = NULL ;
170
+ }
171
+ if (xmount (err , NULL , path , NULL , MS_REMOUNT | MS_NODEV |MS_NOSUID |MS_NOEXEC , NULL ) < 0 )
172
+ goto fail ;
173
+ if ((mnt = xstrdup (err , path )) == NULL )
174
+ goto fail ;
175
+ return (mnt );
176
+
177
+ fail :
178
+ * ptr = '\0' ;
179
+ free (buf );
180
+ unmount (path );
181
+ return (NULL );
182
+ }
183
+
184
+ static char *
185
+ mount_procfs_gpu (struct error * err , const struct nvc_container * cnt , const char * busid )
186
+ {
187
+ char path [PATH_MAX ] = {0 };
188
+ char * gpu = NULL ;
189
+ char * mnt = NULL ;
190
+ mode_t mode ;
191
+
192
+ if (xasprintf (err , & gpu , "%s/gpus/%s" , NV_PROC_DRIVER , busid ) < 0 )
193
+ return (NULL );
194
+ if (file_mode (err , gpu , & mode ) < 0 )
195
+ goto fail ;
196
+ if (path_resolve (err , path , cnt -> cfg .rootfs , gpu ) < 0 )
197
+ goto fail ;
198
+ if (file_create (err , path , NULL , cnt -> uid , cnt -> gid , mode ) < 0 )
199
+ goto fail ;
200
+
201
+ log_infof ("mounting %s at %s" , gpu , path );
202
+ if (xmount (err , gpu , path , NULL , MS_BIND , NULL ) < 0 )
203
+ goto fail ;
204
+ if (xmount (err , NULL , path , NULL , MS_BIND |MS_REMOUNT | MS_RDONLY |MS_NODEV |MS_NOSUID |MS_NOEXEC , NULL ) < 0 )
205
+ goto fail ;
206
+ if ((mnt = xstrdup (err , path )) == NULL )
207
+ goto fail ;
208
+
209
+ fail :
210
+ if (mnt == NULL )
211
+ unmount (path );
212
+ free (gpu );
213
+ return (mnt );
214
+ }
215
+
132
216
static void
133
217
unmount (const char * path )
134
218
{
135
- if (path == NULL )
219
+ if (path == NULL || strempty ( path ) )
136
220
return ;
137
221
umount2 (path , MNT_DETACH );
138
222
file_remove (NULL , path );
@@ -145,14 +229,14 @@ setup_cgroup(struct error *err, const char *cgroup, dev_t id)
145
229
FILE * fs ;
146
230
int rv = -1 ;
147
231
148
- if (path_join (err , path , cgroup , CGROUP_DEVICE_ALLOW ) < 0 )
232
+ if (path_join (err , path , cgroup , "devices.allow" ) < 0 )
149
233
return (-1 );
150
234
if ((fs = xfopen (err , path , "a" )) == NULL )
151
235
return (-1 );
152
236
153
237
log_infof ("whitelisting device node %u:%u" , major (id ), minor (id ));
154
238
/* XXX dprintf doesn't seem to catch the write errors, flush the stream explicitly instead. */
155
- if (fprintf (fs , CGROUP_DEVICE_STR , major (id ), minor (id ), "rwm" ) < 0 || fflush (fs ) == EOF || ferror (fs )) {
239
+ if (fprintf (fs , "c %u:%u rw" , major (id ), minor (id )) < 0 || fflush (fs ) == EOF || ferror (fs )) {
156
240
error_set (err , "write error: %s" , path );
157
241
goto fail ;
158
242
}
@@ -208,6 +292,7 @@ symlink_libraries(struct error *err, const struct nvc_container *cnt, const char
208
292
int
209
293
nvc_driver_mount (struct nvc_context * ctx , const struct nvc_container * cnt , const struct nvc_driver_info * info )
210
294
{
295
+ char * procfs_mnt = NULL ;
211
296
char * * files_mnt = NULL ;
212
297
char * * ipcs_mnt = NULL ;
213
298
char * * devs_mnt = NULL ;
@@ -225,6 +310,10 @@ nvc_driver_mount(struct nvc_context *ctx, const struct nvc_container *cnt, const
225
310
if (nsenter (& ctx -> err , cnt -> mnt_ns , CLONE_NEWNS ) < 0 )
226
311
return (-1 );
227
312
313
+ /* Procfs mount */
314
+ if ((procfs_mnt = mount_procfs (& ctx -> err , cnt )) == NULL )
315
+ goto fail ;
316
+
228
317
/* File mounts */
229
318
nfiles_mnt = 3 ;
230
319
files_mnt = mnt = array_new (& ctx -> err , nfiles_mnt );
@@ -279,6 +368,7 @@ nvc_driver_mount(struct nvc_context *ctx, const struct nvc_container *cnt, const
279
368
280
369
fail :
281
370
if (rv < 0 ) {
371
+ unmount (procfs_mnt );
282
372
for (size_t i = 0 ; files_mnt != NULL && i < nfiles_mnt ; ++ i )
283
373
unmount (files_mnt [i ]);
284
374
for (size_t i = 0 ; ipcs_mnt != NULL && i < nipcs_mnt ; ++ i )
@@ -290,6 +380,7 @@ nvc_driver_mount(struct nvc_context *ctx, const struct nvc_container *cnt, const
290
380
rv = nsenterat (& ctx -> err , ctx -> mnt_ns , CLONE_NEWNS );
291
381
}
292
382
383
+ free (procfs_mnt );
293
384
array_free (files_mnt , nfiles_mnt );
294
385
array_free (ipcs_mnt , nipcs_mnt );
295
386
array_free (devs_mnt , ndevs_mnt );
@@ -299,7 +390,8 @@ nvc_driver_mount(struct nvc_context *ctx, const struct nvc_container *cnt, const
299
390
int
300
391
nvc_device_mount (struct nvc_context * ctx , const struct nvc_container * cnt , const struct nvc_device * dev )
301
392
{
302
- char * mnt = NULL ;
393
+ char * dev_mnt = NULL ;
394
+ char * proc_mnt = NULL ;
303
395
struct stat s ;
304
396
int rv = -1 ;
305
397
@@ -311,14 +403,16 @@ nvc_device_mount(struct nvc_context *ctx, const struct nvc_container *cnt, const
311
403
if (nsenter (& ctx -> err , cnt -> mnt_ns , CLONE_NEWNS ) < 0 )
312
404
return (-1 );
313
405
406
+ if ((proc_mnt = mount_procfs_gpu (& ctx -> err , cnt , dev -> busid )) == NULL )
407
+ goto fail ;
314
408
if (!(cnt -> flags & OPT_NO_DEVBIND )) {
315
409
if (xstat (& ctx -> err , dev -> node .path , & s ) < 0 )
316
410
return (-1 );
317
411
if (s .st_rdev != dev -> node .id ) {
318
412
error_setx (& ctx -> err , "invalid device node: %s" , dev -> node .path );
319
413
return (-1 );
320
414
}
321
- if ((mnt = mount_device (& ctx -> err , cnt , dev -> node .path )) == NULL )
415
+ if ((dev_mnt = mount_device (& ctx -> err , cnt , dev -> node .path )) == NULL )
322
416
goto fail ;
323
417
}
324
418
if (!(cnt -> flags & OPT_NO_CGROUPS )) {
@@ -329,12 +423,14 @@ nvc_device_mount(struct nvc_context *ctx, const struct nvc_container *cnt, const
329
423
330
424
fail :
331
425
if (rv < 0 ) {
332
- unmount (mnt );
426
+ unmount (proc_mnt );
427
+ unmount (dev_mnt );
333
428
assert_func (nsenterat (NULL , ctx -> mnt_ns , CLONE_NEWNS ));
334
429
} else {
335
430
rv = nsenterat (& ctx -> err , ctx -> mnt_ns , CLONE_NEWNS );
336
431
}
337
432
338
- free (mnt );
433
+ free (proc_mnt );
434
+ free (dev_mnt );
339
435
return (rv );
340
436
}
0 commit comments