Skip to content
This repository was archived by the owner on Jan 6, 2025. It is now read-only.

Commit 44327d2

Browse files
author
Sarah Jelinek
authored
Merge pull request #40 from GBuella/mmap_fix
Fixes related to calling syscall_no_intercept
2 parents 5766039 + f76ef06 commit 44327d2

File tree

10 files changed

+158
-61
lines changed

10 files changed

+158
-61
lines changed

doc/generated/libsyscall_intercept.3

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,17 +98,32 @@ after a clone syscall creating a thread returns in a child thread:
9898
.IP
9999
.nf
100100
\f[C]
101-
long\ (*intercept_hook_point_clone_child)(void);
101+
void\ (*intercept_hook_point_clone_child)(void);
102102
\f[]
103103
.fi
104104
.PP
105105
Using \f[C]intercept_hook_point_clone_child\f[], one can be notified of
106-
thread creations easily, and even override the syscall\[aq]s return
107-
value in the child thread (which is normally zero).
108-
Note: overriding the zero return value is discouraged \-\- this syscall
109-
is usually issued by libc, and a non\-zero return value is interpreted
110-
as the execution remaining in the parent thread, thus using attempting
111-
to use the same stack space as the actual parent thread.
106+
thread creations.
107+
.PP
108+
To make it easy to detect syscall return values indicating errors, one
109+
can use the syscall_error_code function:
110+
.IP
111+
.nf
112+
\f[C]
113+
int\ syscall_error_code(long\ result);
114+
\f[]
115+
.fi
116+
.PP
117+
When passed a return value from syscall_no_intercept, this function can
118+
translate it to an error code equivalent to a libc error code:
119+
.IP
120+
.nf
121+
\f[C]
122+
int\ fd\ =\ (int)syscall_no_intercept(SYS_open,\ "file",\ O_RDWR);
123+
if\ (syscall_error_code(fd)\ !=\ 0)
124+
\ \ \ \ fprintf(stderr,\ strerror(syscall_error_code(fd)));
125+
\f[]
126+
.fi
112127
.SH ENVIRONMENT VARIABLES
113128
.PP
114129
Three environment variables control the operation of the library:

doc/libsyscall_intercept.3.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,19 @@ void (*intercept_hook_point_clone_child)(void);
101101
Using `intercept_hook_point_clone_child`, one can be notified of thread
102102
creations.
103103

104+
To make it easy to detect syscall return values indicating errors, one
105+
can use the syscall_error_code function:
106+
```c
107+
int syscall_error_code(long result);
108+
```
109+
When passed a return value from syscall_no_intercept, this function
110+
can translate it to an error code equivalent to a libc error code:
111+
```c
112+
int fd = (int)syscall_no_intercept(SYS_open, "file", O_RDWR);
113+
if (syscall_error_code(fd) != 0)
114+
fprintf(stderr, strerror(syscall_error_code(fd)));
115+
```
116+
104117
# ENVIRONMENT VARIABLES #
105118
Three environment variables control the operation of the library:
106119

examples/syscall_logger.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545

4646
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
4747

48-
long log_fd;
48+
int log_fd;
4949

5050
static char buffer[0x20000];
5151
static size_t buffer_offset;
@@ -849,7 +849,8 @@ start(void)
849849
if (path == NULL)
850850
syscall_no_intercept(SYS_exit_group, 3);
851851

852-
log_fd = syscall_no_intercept(SYS_open, path, O_CREAT | O_RDWR, 0700);
852+
log_fd = (int)syscall_no_intercept(SYS_open,
853+
path, O_CREAT | O_RDWR, (mode_t)0700);
853854

854855
if (log_fd < 0)
855856
syscall_no_intercept(SYS_exit_group, 4);

include/libsyscall_intercept_hook_point.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,20 @@ extern void (*intercept_hook_point_clone_child)(void);
6969
*/
7070
long syscall_no_intercept(long syscall_number, ...);
7171

72+
/*
73+
* syscall_error_code - examines a return value from
74+
* syscall_no_intercept, and returns an error code if said
75+
* return value indicates an error.
76+
*/
77+
static inline int
78+
syscall_error_code(long result)
79+
{
80+
if (result < 0 && result >= -0x1000)
81+
return (int)-result;
82+
83+
return 0;
84+
}
85+
7286
/*
7387
* The syscall intercepting library checks for the
7488
* INTERCEPT_HOOK_CMDLINE_FILTER environment variable, with which one can

src/entry.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ entry_point(void)
6666
* chars at a time. See syscall_hook_in_process_allowed below.
6767
*/
6868
static bool
69-
match_with_file_end(const char *expected, long fd)
69+
match_with_file_end(const char *expected, int fd)
7070
{
7171
char file_c; /* next character from file */
7272
const char *c; /* next character from the expected string */
@@ -76,7 +76,8 @@ match_with_file_end(const char *expected, long fd)
7676

7777
c = expected;
7878

79-
while (syscall_no_intercept(SYS_read, fd, &file_c, 1) == 1) {
79+
while (syscall_no_intercept(SYS_read, fd, &file_c, (size_t)1)
80+
== (ssize_t)1) {
8081
if (file_c == '\0') /* this probably never happens */
8182
break;
8283

@@ -98,15 +99,16 @@ match_with_file_end(const char *expected, long fd)
9899
int
99100
syscall_hook_in_process_allowed(void)
100101
{
101-
long fd;
102+
int fd;
102103
bool result;
103104
const char *filter;
104105

105106
filter = getenv("INTERCEPT_HOOK_CMDLINE_FILTER");
106107
if (filter == NULL)
107108
return 1;
108109

109-
fd = syscall_no_intercept(SYS_open, "/proc/self/cmdline", O_RDONLY, 0);
110+
fd = (int)syscall_no_intercept(SYS_open,
111+
"/proc/self/cmdline", O_RDONLY, (mode_t)0);
110112

111113
if (fd < 0)
112114
return 0;

src/intercept.c

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -448,21 +448,65 @@ log_header(void)
448448
}
449449

450450
/*
451-
* xabort - speaks for itself
451+
* xabort_errno - print a message to stderr, and exit the process.
452452
* Calling abort() in libc might result other syscalls being called
453453
* by libc.
454+
*
455+
* If error_code is not zero, it is also printed.
454456
*/
455457
void
456-
xabort(const char *msg)
458+
xabort_errno(int error_code, const char *msg)
457459
{
458460
static const char main_msg[] = " libsyscall_intercept error\n";
459461

460-
if (msg != NULL)
461-
syscall_no_intercept(SYS_write, 2, msg, strlen(msg));
462-
syscall_no_intercept(SYS_write, 2, main_msg, sizeof(main_msg));
462+
if (msg != NULL) {
463+
/* not using libc - inline strlen */
464+
size_t len = 0;
465+
while (msg[len] != '\0')
466+
++len;
467+
syscall_no_intercept(SYS_write, 2, msg, len);
468+
}
469+
470+
if (error_code != 0) {
471+
char buf[0x10];
472+
size_t len = 1;
473+
char *c = buf + sizeof(buf) - 1;
474+
475+
/* not using libc - inline sprintf */
476+
do {
477+
*c-- = error_code % 10;
478+
++len;
479+
error_code /= 10;
480+
} while (error_code != 0);
481+
*c = ' ';
482+
483+
syscall_no_intercept(SYS_write, 2, c, len);
484+
}
485+
486+
syscall_no_intercept(SYS_write, 2, main_msg, sizeof(main_msg) - 1);
463487
syscall_no_intercept(SYS_exit_group, 1);
464488

465-
__builtin_trap();
489+
__builtin_unreachable();
490+
}
491+
492+
/*
493+
* xabort - print a message to stderr, and exit the process.
494+
*/
495+
void
496+
xabort(const char *msg)
497+
{
498+
xabort_errno(0, msg);
499+
}
500+
501+
/*
502+
* xabort_on_syserror -- examines the return value of syscall_no_intercept,
503+
* and calls xabort_errno if the said return value indicates an error.
504+
*/
505+
void
506+
xabort_on_syserror(long syscall_result, const char *msg)
507+
{
508+
if (syscall_error_code(syscall_result) != 0)
509+
xabort_errno(syscall_error_code(syscall_result), msg);
466510
}
467511

468512
/*

src/intercept.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,11 @@ void intercept_patch_with_postfix(unsigned char *syscall_addr,
6262

6363
#define INTERCEPTOR_EXIT_CODE 111
6464

65-
__attribute__((noreturn)) void xabort(const char *);
65+
__attribute__((noreturn)) void xabort_errno(int error_code, const char *msg);
66+
67+
__attribute__((noreturn)) void xabort(const char *msg);
68+
69+
void xabort_on_syserror(long syscall_result, const char *msg);
6670

6771
struct range {
6872
unsigned char *address;

src/intercept_desc.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,14 @@
5757
* only be present in the original file.
5858
* Note on naming: memory has segments, the object file has sections.
5959
*/
60-
static long
60+
static int
6161
open_orig_file(const struct intercept_desc *desc)
6262
{
63-
long fd;
63+
int fd;
6464

6565
fd = syscall_no_intercept(SYS_open, desc->path, O_RDONLY);
6666

67-
if (fd < 0) {
68-
syscall_no_intercept(SYS_write, 2,
69-
desc->path, strlen(desc->path));
70-
xabort(" open_orig_file");
71-
}
67+
xabort_on_syserror(fd, __func__);
7268

7369
return fd;
7470
}
@@ -106,7 +102,7 @@ add_text_info(struct intercept_desc *desc, const Elf64_Shdr *header,
106102
* See: man elf
107103
*/
108104
static void
109-
find_sections(struct intercept_desc *desc, long fd)
105+
find_sections(struct intercept_desc *desc, int fd)
110106
{
111107
Elf64_Ehdr elf_header;
112108

@@ -293,7 +289,7 @@ mark_jump(const struct intercept_desc *desc, const unsigned char *addr)
293289
*/
294290
static void
295291
find_jumps_in_section_syms(struct intercept_desc *desc, Elf64_Shdr *section,
296-
long fd)
292+
int fd)
297293
{
298294
assert(section->sh_type == SHT_SYMTAB ||
299295
section->sh_type == SHT_DYNSYM);
@@ -344,7 +340,7 @@ find_jumps_in_section_syms(struct intercept_desc *desc, Elf64_Shdr *section,
344340
*/
345341
static void
346342
find_jumps_in_section_rela(struct intercept_desc *desc, Elf64_Shdr *section,
347-
long fd)
343+
int fd)
348344
{
349345
assert(section->sh_type == SHT_RELA);
350346

@@ -691,7 +687,7 @@ find_syscalls(struct intercept_desc *desc)
691687

692688
desc->count = 0;
693689

694-
long fd = open_orig_file(desc);
690+
int fd = open_orig_file(desc);
695691

696692
find_sections(desc, fd);
697693
debug_dump(

src/intercept_util.c

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
#include "intercept_util.h"
3434
#include "intercept.h"
35+
#include "libsyscall_intercept_hook_point.h"
3536

3637
#include <assert.h>
3738
#include <inttypes.h>
@@ -48,58 +49,57 @@
4849
#include <sched.h>
4950
#include <linux/limits.h>
5051

51-
static long log_fd = -1;
52+
static int log_fd = -1;
5253

5354
void *
5455
xmmap_anon(size_t size)
5556
{
56-
void *addr = (void *) syscall_no_intercept(SYS_mmap,
57+
long addr = syscall_no_intercept(SYS_mmap,
5758
NULL, size,
5859
PROT_READ | PROT_WRITE,
59-
MAP_PRIVATE | MAP_ANON, -1, 0);
60+
MAP_PRIVATE | MAP_ANON, -1, (off_t)0);
6061

61-
if (addr == MAP_FAILED)
62-
xabort("xmmap_anon");
62+
xabort_on_syserror(addr, __func__);
6363

64-
return addr;
64+
return (void *) addr;
6565
}
6666

6767
void *
6868
xmremap(void *addr, size_t old, size_t new)
6969
{
70-
addr = (void *) syscall_no_intercept(SYS_mremap, addr,
70+
long new_addr = syscall_no_intercept(SYS_mremap, addr,
7171
old, new, MREMAP_MAYMOVE);
7272

73-
if (addr == MAP_FAILED)
74-
xabort("xmremap");
73+
xabort_on_syserror(new_addr, __func__);
7574

76-
return addr;
75+
return (void *) new_addr;
7776
}
7877

7978
void
8079
xmunmap(void *addr, size_t len)
8180
{
82-
if (syscall_no_intercept(SYS_munmap, addr, len) != 0)
83-
xabort("xmunmap");
81+
long result = syscall_no_intercept(SYS_munmap, addr, len);
82+
83+
xabort_on_syserror(result, __func__);
8484
}
8585

8686
long
8787
xlseek(long fd, unsigned long off, int whence)
8888
{
8989
long result = syscall_no_intercept(SYS_lseek, fd, off, whence);
9090

91-
if (result < 0)
92-
xabort("xlseek");
91+
xabort_on_syserror(result, __func__);
9392

9493
return result;
9594
}
9695

9796
void
9897
xread(long fd, void *buffer, size_t size)
9998
{
100-
if (syscall_no_intercept(SYS_read, fd,
101-
(long)buffer, (long)size) != (long)size)
102-
xabort("xread");
99+
long result = syscall_no_intercept(SYS_read, fd, buffer, size);
100+
101+
if (result != (long)size)
102+
xabort_errno(syscall_error_code(result), __func__);
103103
}
104104

105105
/*
@@ -130,10 +130,9 @@ intercept_setup_log(const char *path_base, const char *trunc)
130130

131131
intercept_log_close();
132132

133-
log_fd = syscall_no_intercept(SYS_open, path, flags, 0700);
133+
log_fd = (int)syscall_no_intercept(SYS_open, path, flags, (mode_t)0700);
134134

135-
if (log_fd < 0)
136-
xabort("setup_log");
135+
xabort_on_syserror(log_fd, "opening log");
137136
}
138137

139138
/*
@@ -1520,7 +1519,7 @@ intercept_log(const char *buffer, size_t len)
15201519
{
15211520
if (log_fd >= 0)
15221521
syscall_no_intercept(SYS_write, log_fd,
1523-
(long)buffer, (long)len);
1522+
buffer, len);
15241523
}
15251524

15261525
/*

0 commit comments

Comments
 (0)