66#include <linux/types.h>
77
88#include <sys/capability.h>
9+ #include <sys/mman.h>
910#include <sys/mount.h>
1011#include <sys/prctl.h>
1112#include <sys/resource.h>
13+ #include <sys/sendfile.h>
14+ #include <sys/stat.h>
1215#include <sys/syscall.h>
1316#include <sys/types.h>
1417#include <sys/wait.h>
1518
1619#include <errno.h>
20+ #include <fcntl.h>
1721#include <paths.h>
1822#include <sched.h>
1923#ifdef WITH_SECCOMP
@@ -36,6 +40,9 @@ static int adjust_capabilities(struct error *, uid_t, bool);
3640static int adjust_privileges (struct error * , uid_t , gid_t , bool );
3741static int limit_resources (struct error * );
3842static int limit_syscalls (struct error * );
43+ static ssize_t sendfile_nointr (int , int , off_t * , size_t );
44+ static int open_as_memfd (struct error * , const char * );
45+
3946
4047static inline bool
4148secure_mode (void )
@@ -242,7 +249,7 @@ limit_resources(struct error *err)
242249 limit = (struct rlimit ){64 , 64 };
243250 if (setrlimit (RLIMIT_NOFILE , & limit ) < 0 )
244251 goto fail ;
245- limit = (struct rlimit ){1024 * 1024 , 1024 * 1024 };
252+ limit = (struct rlimit ){2 * 1024 * 1024 , 2 * 1024 * 1024 };
246253 if (setrlimit (RLIMIT_FSIZE , & limit ) < 0 )
247254 goto fail ;
248255 return (0 );
@@ -279,14 +286,15 @@ limit_syscalls(struct error *err)
279286 SCMP_SYS (getegid ),
280287 SCMP_SYS (geteuid ),
281288 SCMP_SYS (getgid ),
282- SCMP_SYS (getpgrp ),
289+ SCMP_SYS (getpgrp ),
283290 SCMP_SYS (getpid ),
284291 SCMP_SYS (gettid ),
285292 SCMP_SYS (gettimeofday ),
286293 SCMP_SYS (getuid ),
287294 SCMP_SYS (_llseek ),
288295 SCMP_SYS (lseek ),
289296 SCMP_SYS (lstat ),
297+ SCMP_SYS (memfd_create ),
290298 SCMP_SYS (mkdir ),
291299 SCMP_SYS (mmap ),
292300 SCMP_SYS (mprotect ),
@@ -303,6 +311,7 @@ limit_syscalls(struct error *err)
303311 SCMP_SYS (rt_sigaction ),
304312 SCMP_SYS (rt_sigprocmask ),
305313 SCMP_SYS (rt_sigreturn ),
314+ SCMP_SYS (sendfile ),
306315 SCMP_SYS (stat ),
307316 SCMP_SYS (symlink ),
308317 SCMP_SYS (tgkill ),
@@ -352,6 +361,66 @@ limit_syscalls(struct error *err)
352361}
353362#endif /* WITH_SECCOMP */
354363
364+
365+ static ssize_t
366+ sendfile_nointr (int out_fd , int in_fd , off_t * offset , size_t count )
367+ {
368+ ssize_t ret ;
369+
370+ do {
371+ ret = sendfile (out_fd , in_fd , offset , count );
372+ } while (ret < 0 && errno == EINTR );
373+
374+ return ret ;
375+ }
376+
377+ static int
378+ open_as_memfd (struct error * err , const char * path )
379+ {
380+ int fd , memfd , ret ;
381+ ssize_t bytes_sent = 0 ;
382+ struct stat st = {0 };
383+ off_t offset = 0 ;
384+
385+ if ((fd = xopen (err , path , O_RDONLY )) < 0 )
386+ return (-1 );
387+
388+ log_info ("creating a virtual copy of the ldconfig binary" );
389+ memfd = memfd_create (path , MFD_ALLOW_SEALING | MFD_CLOEXEC );
390+ if (memfd == -1 ) {
391+ error_set (err , "error creating memfd for path: %s" , path );
392+ return (-1 );
393+ }
394+
395+ ret = fstat (fd , & st );
396+ if (ret == -1 ) {
397+ error_set (err , "error running fstat for path: %s" , path );
398+ goto fail ;
399+ }
400+
401+ while (bytes_sent < st .st_size ) {
402+ ssize_t sent ;
403+ sent = sendfile_nointr (memfd , fd , & offset , st .st_size - bytes_sent );
404+ if (sent == -1 ) {
405+ error_set (err , "failed to copy ldconfig binary to virtual copy" );
406+ goto fail ;
407+ }
408+ bytes_sent += sent ;
409+ }
410+
411+ if (fcntl (memfd , F_ADD_SEALS , F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE ) == -1 ) {
412+ error_set (err , "failed to seal virtual copy of the ldconfig binary" );
413+ goto fail ;
414+ }
415+
416+ close (fd );
417+ return memfd ;
418+ fail :
419+ close (fd );
420+ close (memfd );
421+ return (-1 );
422+ }
423+
355424int
356425nvc_ldcache_update (struct nvc_context * ctx , const struct nvc_container * cnt )
357426{
@@ -374,7 +443,7 @@ nvc_ldcache_update(struct nvc_context *ctx, const struct nvc_container *cnt)
374443 * Force proc to be remounted since we're creating a PID namespace and fexecve depends on it.
375444 */
376445 ++ argv [0 ];
377- if ((fd = xopen (& ctx -> err , argv [0 ], O_RDONLY | O_CLOEXEC )) < 0 )
446+ if ((fd = open_as_memfd (& ctx -> err , argv [0 ])) < 0 )
378447 return (-1 );
379448 host_ldconfig = true;
380449 log_infof ("executing %s from host at %s" , argv [0 ], cnt -> cfg .rootfs );
0 commit comments