Skip to content

Commit ff83efb

Browse files
committed
Create virtual copy of host ldconfig binary before calling fexecve()
Signed-off-by: Christopher Desiniotis <[email protected]>
1 parent 63d366e commit ff83efb

File tree

1 file changed

+72
-3
lines changed

1 file changed

+72
-3
lines changed

src/nvc_ldcache.c

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,18 @@
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);
3640
static int adjust_privileges(struct error *, uid_t, gid_t, bool);
3741
static int limit_resources(struct error *);
3842
static 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

4047
static inline bool
4148
secure_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+
355424
int
356425
nvc_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

Comments
 (0)