Skip to content

Commit aa3149d

Browse files
authored
[sanitizer] intercept getservent_r, getservbyname_r, getservbyport_r (llvm#133339)
1 parent d18faf6 commit aa3149d

File tree

4 files changed

+145
-0
lines changed

4 files changed

+145
-0
lines changed

compiler-rt/lib/msan/tests/msan_test.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4908,5 +4908,74 @@ TEST(MemorySanitizer, timer_create) {
49084908
EXPECT_POISONED(timer2);
49094909
timer_delete(timer);
49104910
}
4911+
4912+
TEST(MemorySanitizer, getservent_r) {
4913+
struct servent result_buf;
4914+
struct servent *result;
4915+
char buf[1024];
4916+
EXPECT_POISONED(result_buf);
4917+
EXPECT_POISONED(result);
4918+
EXPECT_POISONED(buf);
4919+
ASSERT_EQ(getservent_r(&result_buf, buf, sizeof(buf), &result), 0);
4920+
EXPECT_NOT_POISONED(result);
4921+
ASSERT_NE(result, nullptr);
4922+
EXPECT_NOT_POISONED(result_buf);
4923+
EXPECT_NOT_POISONED(buf);
4924+
}
4925+
4926+
TEST(MemorySanitizer, getservbyname_r) {
4927+
struct servent result_buf;
4928+
struct servent *result;
4929+
char buf[1024];
4930+
EXPECT_POISONED(result_buf);
4931+
EXPECT_POISONED(result);
4932+
EXPECT_POISONED(buf);
4933+
ASSERT_EQ(
4934+
getservbyname_r("ssh", nullptr, &result_buf, buf, sizeof(buf), &result),
4935+
0);
4936+
EXPECT_NOT_POISONED(result);
4937+
// If this fails, check /etc/services if "ssh" exists. I picked this because
4938+
// it should exist everywhere, if it doesn't, I am sorry. Disable the test
4939+
// then please.
4940+
ASSERT_NE(result, nullptr);
4941+
EXPECT_NOT_POISONED(result_buf);
4942+
EXPECT_NOT_POISONED(buf);
4943+
}
4944+
4945+
TEST(MemorySanitizer, getservbyname_r_unknown) {
4946+
struct servent result_buf;
4947+
struct servent *result;
4948+
char buf[1024];
4949+
EXPECT_POISONED(result_buf);
4950+
EXPECT_POISONED(result);
4951+
EXPECT_POISONED(buf);
4952+
ASSERT_EQ(getservbyname_r("invalidhadfuiasdhi", nullptr, &result_buf, buf,
4953+
sizeof(buf), &result),
4954+
0);
4955+
EXPECT_NOT_POISONED(result);
4956+
ASSERT_EQ(result, nullptr);
4957+
EXPECT_POISONED(result_buf);
4958+
EXPECT_POISONED(buf);
4959+
}
4960+
4961+
TEST(MemorySanitizer, getservbyport_r) {
4962+
struct servent result_buf;
4963+
struct servent *result;
4964+
char buf[1024];
4965+
EXPECT_POISONED(result_buf);
4966+
EXPECT_POISONED(result);
4967+
EXPECT_POISONED(buf);
4968+
ASSERT_EQ(getservbyport_r(htons(22), nullptr, &result_buf, buf, sizeof(buf),
4969+
&result),
4970+
0);
4971+
EXPECT_NOT_POISONED(result);
4972+
// If this fails, check /etc/services if "ssh" exists. I picked this because
4973+
// it should exist everywhere, if it doesn't, I am sorry. Disable the test
4974+
// then please.
4975+
ASSERT_NE(result, nullptr);
4976+
EXPECT_NOT_POISONED(result_buf);
4977+
EXPECT_NOT_POISONED(buf);
4978+
}
4979+
49114980
#endif
49124981
} // namespace

compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10279,6 +10279,66 @@ INTERCEPTOR(SSIZE_T, freadlink, int fd, char *buf, SIZE_T bufsiz) {
1027910279
# define INIT_FREADLINK
1028010280
#endif
1028110281

10282+
UNUSED static void HandleGetServentReentrantResult(
10283+
void *ctx, int res, struct __sanitizer_servent *result_buf, char *buf,
10284+
SIZE_T buflen, struct __sanitizer_servent **result) {
10285+
if (res)
10286+
return;
10287+
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (char *)result, sizeof(void *));
10288+
if (*result) {
10289+
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (char *)*result,
10290+
sizeof(__sanitizer_servent));
10291+
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
10292+
}
10293+
}
10294+
10295+
#if SANITIZER_INTERCEPT_GETSERVENT_R
10296+
INTERCEPTOR(int, getservent_r, struct __sanitizer_servent *result_buf,
10297+
char *buf, SIZE_T buflen, struct __sanitizer_servent **result) {
10298+
void *ctx;
10299+
COMMON_INTERCEPTOR_ENTER(ctx, getservent_r, result_buf, buf, buflen, result);
10300+
int res = REAL(getservent_r)(result_buf, buf, buflen, result);
10301+
HandleGetServentReentrantResult(ctx, res, result_buf, buf, buflen, result);
10302+
return res;
10303+
}
10304+
# define INIT_GETSERVENT_R COMMON_INTERCEPT_FUNCTION(getservent_r)
10305+
#else
10306+
# define INIT_GETSERVENT_R
10307+
#endif
10308+
10309+
#if SANITIZER_INTERCEPT_GETSERVBYNAME_R
10310+
INTERCEPTOR(int, getservbyname_r, const char *name, const char *proto,
10311+
struct __sanitizer_servent *result_buf, char *buf, SIZE_T buflen,
10312+
struct __sanitizer_servent **result) {
10313+
void *ctx;
10314+
COMMON_INTERCEPTOR_ENTER(ctx, getservbyname_r, name, proto, result_buf, buf,
10315+
buflen, result);
10316+
COMMON_INTERCEPTOR_READ_STRING(ctx, name, internal_strlen(name));
10317+
int res = REAL(getservbyname_r)(name, proto, result_buf, buf, buflen, result);
10318+
HandleGetServentReentrantResult(ctx, res, result_buf, buf, buflen, result);
10319+
return res;
10320+
}
10321+
# define INIT_GETSERVBYNAME_R COMMON_INTERCEPT_FUNCTION(getservbyname_r)
10322+
#else
10323+
# define INIT_GETSERVBYNAME_R
10324+
#endif
10325+
10326+
#if SANITIZER_INTERCEPT_GETSERVBYPORT_R
10327+
INTERCEPTOR(int, getservbyport_r, int port, const char *proto,
10328+
struct __sanitizer_servent *result_buf, char *buf, SIZE_T buflen,
10329+
struct __sanitizer_servent **result) {
10330+
void *ctx;
10331+
COMMON_INTERCEPTOR_ENTER(ctx, getservbyport_r, port, proto, result_buf, buf,
10332+
buflen, result);
10333+
int res = REAL(getservbyport_r)(port, proto, result_buf, buf, buflen, result);
10334+
HandleGetServentReentrantResult(ctx, res, result_buf, buf, buflen, result);
10335+
return res;
10336+
}
10337+
# define INIT_GETSERVBYPORT_R COMMON_INTERCEPT_FUNCTION(getservbyport_r)
10338+
#else
10339+
# define INIT_GETSERVBYPORT_R
10340+
#endif
10341+
1028210342
#include "sanitizer_common_interceptors_netbsd_compat.inc"
1028310343

1028410344
namespace __sanitizer {
@@ -10604,4 +10664,7 @@ static void InitializeCommonInterceptors() {
1060410664
INIT_FREADLINK;
1060510665

1060610666
INIT___PRINTF_CHK;
10667+
INIT_GETSERVENT_R;
10668+
INIT_GETSERVBYNAME_R;
10669+
INIT_GETSERVBYPORT_R;
1060710670
}

compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,10 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
645645
# define SI_MAC_OS_DEPLOYMENT_MIN_13_00 0
646646
#endif
647647
#define SANITIZER_INTERCEPT_FREADLINK (SI_MAC && SI_MAC_OS_DEPLOYMENT_MIN_13_00)
648+
#define SANITIZER_INTERCEPT_GETSERVENT_R SI_GLIBC
649+
#define SANITIZER_INTERCEPT_GETSERVBYNAME_R SI_GLIBC
650+
#define SANITIZER_INTERCEPT_GETSERVBYPORT_R SI_GLIBC
651+
648652
// This macro gives a way for downstream users to override the above
649653
// interceptor macros irrespective of the platform they are on. They have
650654
// to do two things:

compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,6 +1509,15 @@ extern unsigned IOCTL_KIOCSOUND;
15091509
extern unsigned IOCTL_PIO_SCRNMAP;
15101510
#endif
15111511

1512+
# if SANITIZER_GLIBC
1513+
struct __sanitizer_servent {
1514+
char *s_name;
1515+
char **s_aliases;
1516+
int s_port;
1517+
char *s_proto;
1518+
};
1519+
# endif
1520+
15121521
extern const int si_SEGV_MAPERR;
15131522
extern const int si_SEGV_ACCERR;
15141523
} // namespace __sanitizer

0 commit comments

Comments
 (0)