Skip to content

Commit e281c17

Browse files
Abseil Teamcopybara-github
authored andcommitted
Try to use file descriptors in the 2000+ range to avoid mis-behaving client
interference. PiperOrigin-RevId: 707171366 Change-Id: I8b79eda8e20bbb25016389ce10a899c3a870de72
1 parent caec5f1 commit e281c17

File tree

1 file changed

+39
-4
lines changed

1 file changed

+39
-4
lines changed

absl/debugging/symbolize_elf.inc

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#include <elf.h>
5353
#include <fcntl.h>
5454
#include <link.h> // For ElfW() macro.
55+
#include <sys/resource.h>
5556
#include <sys/stat.h>
5657
#include <sys/types.h>
5758
#include <unistd.h>
@@ -376,6 +377,40 @@ class Symbolizer {
376377
SymbolCacheLine symbol_cache_[SYMBOL_CACHE_LINES];
377378
};
378379

380+
// Protect against client code closing low-valued file descriptors it doesn't
381+
// actually own, as has happened in b/384213477.
382+
int SaferOpen(const char *fname, int flags) {
383+
static int high_fd = [] {
384+
struct rlimit rlim{};
385+
const int rc = getrlimit(RLIMIT_NOFILE, &rlim);
386+
if (rc == 0 && rlim.rlim_cur >= 2000) {
387+
const int max_fd = static_cast<int>(rlim.rlim_cur);
388+
389+
// This will return 2000 on reasonably-configured systems.
390+
return std::min<int>(2000, max_fd - 1000);
391+
}
392+
ABSL_RAW_LOG(WARNING, "Unable to get high fd: rc=%d, limit=%ld", //
393+
rc, static_cast<long>(rlim.rlim_cur));
394+
return -1;
395+
}();
396+
if (high_fd >= 1000) {
397+
const int fd = open(fname, flags);
398+
if (fd != -1 && fd < high_fd) {
399+
// Try to relocate fd to high range.
400+
const int fd2 = fcntl(fd, F_DUPFD, high_fd);
401+
if (fd2 != -1) {
402+
// Successfully obtained high fd. Use it.
403+
close(fd);
404+
return fd2;
405+
}
406+
}
407+
// Either open failed and fd==-1, or fd is already above high_fd, or fcntl
408+
// failed and fd is valid (but low).
409+
return fd;
410+
}
411+
return open(fname, flags);
412+
}
413+
379414
static std::atomic<Symbolizer *> g_cached_symbolizer;
380415

381416
} // namespace
@@ -1064,7 +1099,7 @@ static ABSL_ATTRIBUTE_NOINLINE bool ReadAddrMap(
10641099
snprintf(maps_path, sizeof(maps_path), "/proc/self/task/%d/maps", getpid());
10651100

10661101
int maps_fd;
1067-
NO_INTR(maps_fd = open(maps_path, O_RDONLY));
1102+
NO_INTR(maps_fd = SaferOpen(maps_path, O_RDONLY));
10681103
FileDescriptor wrapped_maps_fd(maps_fd);
10691104
if (wrapped_maps_fd.get() < 0) {
10701105
ABSL_RAW_LOG(WARNING, "%s: errno=%d", maps_path, errno);
@@ -1338,7 +1373,7 @@ static void MaybeOpenFdFromSelfExe(ObjFile *obj) {
13381373
if (memcmp(obj->start_addr, ELFMAG, SELFMAG) != 0) {
13391374
return;
13401375
}
1341-
int fd = open("/proc/self/exe", O_RDONLY);
1376+
int fd = SaferOpen("/proc/self/exe", O_RDONLY);
13421377
if (fd == -1) {
13431378
return;
13441379
}
@@ -1362,15 +1397,15 @@ static void MaybeOpenFdFromSelfExe(ObjFile *obj) {
13621397

13631398
static bool MaybeInitializeObjFile(ObjFile *obj) {
13641399
if (obj->fd < 0) {
1365-
obj->fd = open(obj->filename, O_RDONLY);
1400+
obj->fd = SaferOpen(obj->filename, O_RDONLY);
13661401

13671402
if (obj->fd < 0) {
13681403
// Getting /proc/self/exe here means that we were hinted.
13691404
if (strcmp(obj->filename, "/proc/self/exe") == 0) {
13701405
// /proc/self/exe may be inaccessible (due to setuid, etc.), so try
13711406
// accessing the binary via argv0.
13721407
if (argv0_value != nullptr) {
1373-
obj->fd = open(argv0_value, O_RDONLY);
1408+
obj->fd = SaferOpen(argv0_value, O_RDONLY);
13741409
}
13751410
} else {
13761411
MaybeOpenFdFromSelfExe(obj);

0 commit comments

Comments
 (0)