mirror of
				https://github.com/isar/libmdbx.git
				synced 2025-11-04 05:08:57 +08:00 
			
		
		
		
	mdbx: доработка osal_bootid() для LXC (backport).
				
					
				
			Из LXC-контейнера не доступен файл хостовой системы "/proc/sys/kernel/random/boot_id". Вместо него, при каждом старте контейнера, создается и заполняется случайными данными собственный boot_id смонтированный через bind из tmpfs. https://github.com/lxc/lxc/issues/3027 Поэтому полноценный контроль по boot_id не возможен, так как при рестарте LXC-контейнера (но не хоста) boot_id будет меняться, хотя данные в unified page cache сохраняются. Таким образом, при рестарте LXC-контейнера, libmdbx будет производить откат БД до крайней точки устойчивой фиксации, что может приводить к утрате данных пользователя в случаях когда они могли быть сохранены. Однако, улучшить ситуацию пока не представляется возможным, как минимум до доступности boot_id хостовой системы изнутри LXC-контейнера. Этот коммит частично улучшает ситуацию тем, что позволяет использовать фейковый/замещенный boot_id размещенный в файловой системе с типом tmpfs при работе внутри LXC-контейнера.
This commit is contained in:
		
							
								
								
									
										168
									
								
								src/osal.c
									
									
									
									
									
								
							
							
						
						
									
										168
									
								
								src/osal.c
									
									
									
									
									
								
							@@ -3011,6 +3011,29 @@ __cold static LSTATUS mdbx_RegGetValue(HKEY hKey, LPCSTR lpSubKey,
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static size_t hamming_weight(size_t v) {
 | 
			
		||||
  const size_t m1 = (size_t)UINT64_C(0x5555555555555555);
 | 
			
		||||
  const size_t m2 = (size_t)UINT64_C(0x3333333333333333);
 | 
			
		||||
  const size_t m4 = (size_t)UINT64_C(0x0f0f0f0f0f0f0f0f);
 | 
			
		||||
  const size_t h01 = (size_t)UINT64_C(0x0101010101010101);
 | 
			
		||||
  v -= (v >> 1) & m1;
 | 
			
		||||
  v = (v & m2) + ((v >> 2) & m2);
 | 
			
		||||
  v = (v + (v >> 4)) & m4;
 | 
			
		||||
  return (v * h01) >> (sizeof(v) * 8 - 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline size_t hw64(uint64_t v) {
 | 
			
		||||
  size_t r = hamming_weight((size_t)v);
 | 
			
		||||
  if (sizeof(v) > sizeof(r))
 | 
			
		||||
    r += hamming_weight((size_t)(v >> sizeof(r) * 4 >> sizeof(r) * 4));
 | 
			
		||||
  return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool check_uuid(bin128_t uuid) {
 | 
			
		||||
  size_t hw = hw64(uuid.x) + hw64(uuid.y) + hw64(uuid.x ^ uuid.y);
 | 
			
		||||
  return (hw >> 6) == 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__cold MDBX_MAYBE_UNUSED static bool
 | 
			
		||||
bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) {
 | 
			
		||||
  if (n > 31) {
 | 
			
		||||
@@ -3044,7 +3067,7 @@ bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) {
 | 
			
		||||
      s->y += aligned.y;
 | 
			
		||||
    } else
 | 
			
		||||
      bootid_collect(s, p, n);
 | 
			
		||||
    return true;
 | 
			
		||||
    return check_uuid(*s);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (n)
 | 
			
		||||
@@ -3052,28 +3075,53 @@ bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) {
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
  bin128_t bin = {{0, 0}};
 | 
			
		||||
#if defined(__linux__) || defined(__gnu_linux__)
 | 
			
		||||
 | 
			
		||||
__cold static bool is_inside_lxc(void) {
 | 
			
		||||
  bool inside_lxc = false;
 | 
			
		||||
  FILE *mounted = setmntent("/proc/mounts", "r");
 | 
			
		||||
  if (mounted) {
 | 
			
		||||
    const struct mntent *ent;
 | 
			
		||||
    while (nullptr != (ent = getmntent(mounted))) {
 | 
			
		||||
      if (strcmp(ent->mnt_fsname, "lxcfs") == 0 &&
 | 
			
		||||
          strncmp(ent->mnt_dir, "/proc/", 6) == 0) {
 | 
			
		||||
        inside_lxc = true;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    endmntent(mounted);
 | 
			
		||||
  }
 | 
			
		||||
  return inside_lxc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__cold static bool proc_read_uuid(const char *path, bin128_t *target) {
 | 
			
		||||
  const int fd = open(path, O_RDONLY | O_NOFOLLOW);
 | 
			
		||||
  if (fd != -1) {
 | 
			
		||||
    struct statfs fs;
 | 
			
		||||
    char buf[42];
 | 
			
		||||
    const ssize_t len =
 | 
			
		||||
        (fstatfs(fd, &fs) == 0 &&
 | 
			
		||||
         (fs.f_type == /* procfs */ 0x9FA0 ||
 | 
			
		||||
          (fs.f_type == /* tmpfs */ 0x1021994 && is_inside_lxc())))
 | 
			
		||||
            ? read(fd, buf, sizeof(buf))
 | 
			
		||||
            : -1;
 | 
			
		||||
    const int err = close(fd);
 | 
			
		||||
    assert(err == 0);
 | 
			
		||||
    (void)err;
 | 
			
		||||
    if (len > 0)
 | 
			
		||||
      return bootid_parse_uuid(target, buf, len);
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
#endif /* Linux */
 | 
			
		||||
 | 
			
		||||
__cold bin128_t osal_bootid(void) {
 | 
			
		||||
  bin128_t uuid = {{0, 0}};
 | 
			
		||||
  bool got_machineid = false, got_boottime = false, got_bootseq = false;
 | 
			
		||||
 | 
			
		||||
#if defined(__linux__) || defined(__gnu_linux__)
 | 
			
		||||
  {
 | 
			
		||||
    const int fd =
 | 
			
		||||
        open("/proc/sys/kernel/random/boot_id", O_RDONLY | O_NOFOLLOW);
 | 
			
		||||
    if (fd != -1) {
 | 
			
		||||
      struct statfs fs;
 | 
			
		||||
      char buf[42];
 | 
			
		||||
      const ssize_t len =
 | 
			
		||||
          (fstatfs(fd, &fs) == 0 && fs.f_type == /* procfs */ 0x9FA0)
 | 
			
		||||
              ? read(fd, buf, sizeof(buf))
 | 
			
		||||
              : -1;
 | 
			
		||||
      const int err = close(fd);
 | 
			
		||||
      assert(err == 0);
 | 
			
		||||
      (void)err;
 | 
			
		||||
      if (len > 0 && bootid_parse_uuid(&bin, buf, len))
 | 
			
		||||
        return bin;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (proc_read_uuid("/proc/sys/kernel/random/boot_id", &uuid))
 | 
			
		||||
    return uuid;
 | 
			
		||||
#endif /* Linux */
 | 
			
		||||
 | 
			
		||||
#if defined(__APPLE__) || defined(__MACH__)
 | 
			
		||||
@@ -3081,16 +3129,15 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
    char buf[42];
 | 
			
		||||
    size_t len = sizeof(buf);
 | 
			
		||||
    if (!sysctlbyname("kern.bootsessionuuid", buf, &len, nullptr, 0) &&
 | 
			
		||||
        bootid_parse_uuid(&bin, buf, len))
 | 
			
		||||
      return bin;
 | 
			
		||||
        bootid_parse_uuid(&uuid, buf, len))
 | 
			
		||||
      return uuid;
 | 
			
		||||
 | 
			
		||||
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) &&                                \
 | 
			
		||||
    __MAC_OS_X_VERSION_MIN_REQUIRED > 1050
 | 
			
		||||
    uuid_t uuid;
 | 
			
		||||
    uuid_t hostuuid;
 | 
			
		||||
    struct timespec wait = {0, 1000000000u / 42};
 | 
			
		||||
    if (!gethostuuid(uuid, &wait) &&
 | 
			
		||||
        bootid_parse_uuid(&bin, uuid, sizeof(uuid)))
 | 
			
		||||
      got_machineid = true;
 | 
			
		||||
    if (!gethostuuid(hostuuid, &wait))
 | 
			
		||||
      got_machineid = bootid_parse_uuid(&uuid, hostuuid, sizeof(hostuuid));
 | 
			
		||||
#endif /* > 10.5 */
 | 
			
		||||
 | 
			
		||||
    struct timeval boottime;
 | 
			
		||||
@@ -3128,7 +3175,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
                         "MachineGuid", &buf.MachineGuid,
 | 
			
		||||
                         &len) == ERROR_SUCCESS &&
 | 
			
		||||
        len < sizeof(buf))
 | 
			
		||||
      got_machineid = bootid_parse_uuid(&bin, &buf.MachineGuid, len);
 | 
			
		||||
      got_machineid = bootid_parse_uuid(&uuid, &buf.MachineGuid, len);
 | 
			
		||||
 | 
			
		||||
    if (!got_machineid) {
 | 
			
		||||
      /* again, Windows is madness */
 | 
			
		||||
@@ -3146,7 +3193,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
                           "DigitalProductId", &buf.DigitalProductId,
 | 
			
		||||
                           &len) == ERROR_SUCCESS &&
 | 
			
		||||
          len > 42 && len < sizeof(buf)) {
 | 
			
		||||
        bootid_collect(&bin, &buf.DigitalProductId, len);
 | 
			
		||||
        bootid_collect(&uuid, &buf.DigitalProductId, len);
 | 
			
		||||
        got_machineid = true;
 | 
			
		||||
      }
 | 
			
		||||
      len = sizeof(buf);
 | 
			
		||||
@@ -3154,7 +3201,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
                           "DigitalProductId", &buf.DigitalProductId,
 | 
			
		||||
                           &len) == ERROR_SUCCESS &&
 | 
			
		||||
          len > 42 && len < sizeof(buf)) {
 | 
			
		||||
        bootid_collect(&bin, &buf.DigitalProductId, len);
 | 
			
		||||
        bootid_collect(&uuid, &buf.DigitalProductId, len);
 | 
			
		||||
        got_machineid = true;
 | 
			
		||||
      }
 | 
			
		||||
      len = sizeof(buf);
 | 
			
		||||
@@ -3162,7 +3209,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
                           "DigitalProductId", &buf.DigitalProductId,
 | 
			
		||||
                           &len) == ERROR_SUCCESS &&
 | 
			
		||||
          len > 42 && len < sizeof(buf)) {
 | 
			
		||||
        bootid_collect(&bin, &buf.DigitalProductId, len);
 | 
			
		||||
        bootid_collect(&uuid, &buf.DigitalProductId, len);
 | 
			
		||||
        got_machineid = true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -3174,7 +3221,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
    if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, "BootId",
 | 
			
		||||
                         &buf.BootId, &len) == ERROR_SUCCESS &&
 | 
			
		||||
        len > 1 && len < sizeof(buf)) {
 | 
			
		||||
      bootid_collect(&bin, &buf.BootId, len);
 | 
			
		||||
      bootid_collect(&uuid, &buf.BootId, len);
 | 
			
		||||
      got_bootseq = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -3182,7 +3229,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
    if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, "BaseTime",
 | 
			
		||||
                         &buf.BaseTime, &len) == ERROR_SUCCESS &&
 | 
			
		||||
        len >= sizeof(buf.BaseTime) && buf.BaseTime) {
 | 
			
		||||
      bootid_collect(&bin, &buf.BaseTime, len);
 | 
			
		||||
      bootid_collect(&uuid, &buf.BaseTime, len);
 | 
			
		||||
      got_boottime = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -3198,7 +3245,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
          buf.SysTimeOfDayInfoHacked.BootTime.QuadPart -
 | 
			
		||||
          buf.SysTimeOfDayInfoHacked.BootTimeBias;
 | 
			
		||||
      if (UnbiasedBootTime) {
 | 
			
		||||
        bootid_collect(&bin, &UnbiasedBootTime, sizeof(UnbiasedBootTime));
 | 
			
		||||
        bootid_collect(&uuid, &UnbiasedBootTime, sizeof(UnbiasedBootTime));
 | 
			
		||||
        got_boottime = true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -3206,7 +3253,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
    if (!got_boottime) {
 | 
			
		||||
      uint64_t boottime = windows_bootime();
 | 
			
		||||
      if (boottime) {
 | 
			
		||||
        bootid_collect(&bin, &boottime, sizeof(boottime));
 | 
			
		||||
        bootid_collect(&uuid, &boottime, sizeof(boottime));
 | 
			
		||||
        got_boottime = true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -3223,8 +3270,8 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
            (int *)
 | 
			
		||||
#endif
 | 
			
		||||
                mib,
 | 
			
		||||
            ARRAY_LENGTH(mib), &buf, &len, NULL, 0) == 0)
 | 
			
		||||
      got_machineid = bootid_parse_uuid(&bin, buf, len);
 | 
			
		||||
            ARRAY_LENGTH(mib), &buf, &len, nullptr, 0) == 0)
 | 
			
		||||
      got_machineid = bootid_parse_uuid(&uuid, buf, len);
 | 
			
		||||
  }
 | 
			
		||||
#endif /* CTL_HW && HW_UUID */
 | 
			
		||||
 | 
			
		||||
@@ -3238,8 +3285,8 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
            (int *)
 | 
			
		||||
#endif
 | 
			
		||||
                mib,
 | 
			
		||||
            ARRAY_LENGTH(mib), &buf, &len, NULL, 0) == 0)
 | 
			
		||||
      got_machineid = bootid_parse_uuid(&bin, buf, len);
 | 
			
		||||
            ARRAY_LENGTH(mib), &buf, &len, nullptr, 0) == 0)
 | 
			
		||||
      got_machineid = bootid_parse_uuid(&uuid, buf, len);
 | 
			
		||||
  }
 | 
			
		||||
#endif /* CTL_KERN && KERN_HOSTUUID */
 | 
			
		||||
 | 
			
		||||
@@ -3247,16 +3294,33 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
  if (!got_machineid) {
 | 
			
		||||
    char buf[42];
 | 
			
		||||
    size_t len = sizeof(buf);
 | 
			
		||||
    if (sysctlbyname("machdep.dmi.system-uuid", buf, &len, NULL, 0) == 0)
 | 
			
		||||
      got_machineid = bootid_parse_uuid(&bin, buf, len);
 | 
			
		||||
    if (sysctlbyname("machdep.dmi.system-uuid", buf, &len, nullptr, 0) == 0)
 | 
			
		||||
      got_machineid = bootid_parse_uuid(&uuid, buf, len);
 | 
			
		||||
  }
 | 
			
		||||
#endif /* __NetBSD__ */
 | 
			
		||||
 | 
			
		||||
#if !(defined(_WIN32) || defined(_WIN64))
 | 
			
		||||
  if (!got_machineid) {
 | 
			
		||||
    int fd = open("/etc/machine-id", O_RDONLY);
 | 
			
		||||
    if (fd == -1)
 | 
			
		||||
      fd = open("/var/lib/dbus/machine-id", O_RDONLY);
 | 
			
		||||
    if (fd != -1) {
 | 
			
		||||
      char buf[42];
 | 
			
		||||
      const ssize_t len = read(fd, buf, sizeof(buf));
 | 
			
		||||
      const int err = close(fd);
 | 
			
		||||
      assert(err == 0);
 | 
			
		||||
      (void)err;
 | 
			
		||||
      if (len > 0)
 | 
			
		||||
        got_machineid = bootid_parse_uuid(&uuid, buf, len);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
#endif /* !Windows */
 | 
			
		||||
 | 
			
		||||
#if _XOPEN_SOURCE_EXTENDED
 | 
			
		||||
  if (!got_machineid) {
 | 
			
		||||
    const int hostid = gethostid();
 | 
			
		||||
    if (hostid > 0) {
 | 
			
		||||
      bootid_collect(&bin, &hostid, sizeof(hostid));
 | 
			
		||||
    const long hostid = gethostid();
 | 
			
		||||
    if (hostid != 0 && hostid != -1) {
 | 
			
		||||
      bootid_collect(&uuid, &hostid, sizeof(hostid));
 | 
			
		||||
      got_machineid = true;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -3264,8 +3328,8 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
 | 
			
		||||
  if (!got_machineid) {
 | 
			
		||||
  lack:
 | 
			
		||||
    bin.x = bin.y = 0;
 | 
			
		||||
    return bin;
 | 
			
		||||
    uuid.x = uuid.y = 0;
 | 
			
		||||
    return uuid;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------*/
 | 
			
		||||
@@ -3280,9 +3344,9 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
            (int *)
 | 
			
		||||
#endif
 | 
			
		||||
                mib,
 | 
			
		||||
            ARRAY_LENGTH(mib), &boottime, &len, NULL, 0) == 0 &&
 | 
			
		||||
            ARRAY_LENGTH(mib), &boottime, &len, nullptr, 0) == 0 &&
 | 
			
		||||
        len == sizeof(boottime) && boottime.tv_sec) {
 | 
			
		||||
      bootid_collect(&bin, &boottime, len);
 | 
			
		||||
      bootid_collect(&uuid, &boottime, len);
 | 
			
		||||
      got_boottime = true;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -3299,11 +3363,11 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
          switch (kn->data_type) {
 | 
			
		||||
          case KSTAT_DATA_INT32:
 | 
			
		||||
          case KSTAT_DATA_UINT32:
 | 
			
		||||
            bootid_collect(&bin, &kn->value, sizeof(int32_t));
 | 
			
		||||
            bootid_collect(&uuid, &kn->value, sizeof(int32_t));
 | 
			
		||||
            got_boottime = true;
 | 
			
		||||
          case KSTAT_DATA_INT64:
 | 
			
		||||
          case KSTAT_DATA_UINT64:
 | 
			
		||||
            bootid_collect(&bin, &kn->value, sizeof(int64_t));
 | 
			
		||||
            bootid_collect(&uuid, &kn->value, sizeof(int64_t));
 | 
			
		||||
            got_boottime = true;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
@@ -3319,12 +3383,12 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
    const struct utmpx id = {.ut_type = BOOT_TIME};
 | 
			
		||||
    const struct utmpx *entry = getutxid(&id);
 | 
			
		||||
    if (entry) {
 | 
			
		||||
      bootid_collect(&bin, entry, sizeof(*entry));
 | 
			
		||||
      bootid_collect(&uuid, entry, sizeof(*entry));
 | 
			
		||||
      got_boottime = true;
 | 
			
		||||
      while (unlikely((entry = getutxid(&id)) != nullptr)) {
 | 
			
		||||
        /* have multiple reboot records, assuming we can distinguish next
 | 
			
		||||
         * bootsession even if RTC is wrong or absent */
 | 
			
		||||
        bootid_collect(&bin, entry, sizeof(*entry));
 | 
			
		||||
        bootid_collect(&uuid, entry, sizeof(*entry));
 | 
			
		||||
        got_bootseq = true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -3353,7 +3417,7 @@ __cold MDBX_INTERNAL_FUNC bin128_t osal_bootid(void) {
 | 
			
		||||
      goto lack;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return bin;
 | 
			
		||||
  return uuid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__cold int mdbx_get_sysraminfo(intptr_t *page_size, intptr_t *total_pages,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user