Skip to content

Commit 7746c5f

Browse files
committed
Ignore device number mismatch on overlay filesystem (Linux only)
1 parent c719b4f commit 7746c5f

File tree

1 file changed

+58
-4
lines changed

1 file changed

+58
-4
lines changed

src/linux/elf.c

+58-4
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <sys/sysmacros.h>
3232
#include <sys/types.h>
3333
#include <sys/stat.h>
34+
#include <sys/statfs.h>
3435
#include <limits.h>
3536
#include <unistd.h>
3637
#include "injector_internal.h"
@@ -45,6 +46,16 @@
4546
#define Elf_Sym Elf32_Sym
4647
#endif
4748

49+
// #define INJECTOR_DEBUG_ELF_C 1
50+
51+
#ifdef INJECTOR_DEBUG_ELF_C
52+
#undef DEBUG
53+
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
54+
#else
55+
#undef DEBUG
56+
#define DEBUG(...) do {} while(0)
57+
#endif
58+
4859
typedef struct {
4960
int dlfunc_type; /* -1, DLFUNC_POSIX or DLFUNC_INTERNAL */
5061
FILE *fp;
@@ -288,6 +299,7 @@ static int search_and_open_libc(FILE **fp_out, pid_t pid, size_t *addr, libc_typ
288299
injector__set_errmsg("failed to open %s. (error: %s)", buf, strerror(errno));
289300
return INJERR_OTHER;
290301
}
302+
DEBUG("Open %s\n", buf);
291303
/* /libc.so.6 or /libc-2.{DIGITS}.so or /ld-musl-{arch}.so.1 */
292304
if (regcomp(&reg, "/libc(\\.so\\.6|-2\\.[0-9]+\\.so)|/ld-musl-.+?\\.so\\.1", REG_EXTENDED) != 0) {
293305
injector__set_errmsg("regcomp failed!");
@@ -297,6 +309,7 @@ static int search_and_open_libc(FILE **fp_out, pid_t pid, size_t *addr, libc_typ
297309
unsigned long saddr, eaddr;
298310
unsigned long long offset, inode;
299311
unsigned int dev_major, dev_minor;
312+
DEBUG(" %s", buf);
300313
if (sscanf(buf, "%lx-%lx %*s %llx %x:%x %llu", &saddr, &eaddr, &offset, &dev_major, &dev_minor, &inode) != 6) {
301314
continue;
302315
}
@@ -325,7 +338,9 @@ static int search_and_open_libc(FILE **fp_out, pid_t pid, size_t *addr, libc_typ
325338
}
326339
regfree(&reg);
327340
*p = '\0';
328-
return open_libc(fp_out, strchr(buf, '/'), pid, makedev(dev_major, dev_minor), inode);
341+
p = strchr(buf, '/');
342+
DEBUG(" libc in /proc/PID/maps: '%s'\n", p);
343+
return open_libc(fp_out, p, pid, makedev(dev_major, dev_minor), inode);
329344
}
330345
fclose(fp);
331346
injector__set_errmsg("Could not find libc");
@@ -387,19 +402,58 @@ static int open_libc(FILE **fp_out, const char *path, pid_t pid, dev_t dev, ino_
387402
return 0;
388403
}
389404

405+
static inline int is_on_overlay_fs(int fd)
406+
{
407+
struct statfs sbuf;
408+
if (fstatfs(fd, &sbuf) != 0) {
409+
DEBUG(" fstatfs() error %s\n", strerror(errno));
410+
return -1;
411+
}
412+
#ifndef OVERLAYFS_SUPER_MAGIC
413+
#define OVERLAYFS_SUPER_MAGIC 0x794c7630
414+
#endif
415+
return (sbuf.f_type == OVERLAYFS_SUPER_MAGIC) ? 1 : 0;
416+
}
417+
390418
static FILE *fopen_with_ino(const char *path, dev_t dev, ino_t ino)
391419
{
420+
DEBUG(" checking: '%s' ...", path);
392421
struct stat sbuf;
393422
FILE *fp = fopen(path, "r");
394423

395424
if (fp == NULL) {
425+
DEBUG(" fopen() error %s\n", strerror(errno));
396426
return NULL;
397427
}
398-
if (fstat(fileno(fp), &sbuf) != 0 || sbuf.st_dev != dev || sbuf.st_ino != ino) {
399-
fclose(fp);
400-
return NULL;
428+
429+
if (fstat(fileno(fp), &sbuf) != 0) {
430+
DEBUG(" fstat() error %s\n", strerror(errno));
431+
goto cleanup;
432+
}
433+
if (sbuf.st_ino != ino) {
434+
DEBUG(" unexpected inode number: expected %llu but %llu\n",
435+
(unsigned long long)ino, (unsigned long long)sbuf.st_ino);
436+
goto cleanup;
401437
}
438+
if (sbuf.st_dev != dev) {
439+
int rv = is_on_overlay_fs(fileno(fp));
440+
if (rv < 0) {
441+
goto cleanup;
442+
}
443+
if (rv != 1) {
444+
DEBUG(" unexpected device number: expected %llu but %llu\n",
445+
(unsigned long long)dev, (unsigned long long)sbuf.st_dev);
446+
goto cleanup;
447+
}
448+
DEBUG(" ignore device number mismatch (expected %llu but %llu) on overlay file system ... ",
449+
(unsigned long long)dev, (unsigned long long)sbuf.st_dev);
450+
}
451+
452+
DEBUG(" OK\n");
402453
return fp;
454+
cleanup:
455+
fclose(fp);
456+
return NULL;
403457
}
404458

405459
static int read_elf_ehdr(FILE *fp, Elf_Ehdr *ehdr)

0 commit comments

Comments
 (0)