1 /**
2  * Copyright (C) Mellanox Technologies Ltd. 2001-2017.  ALL RIGHTS RESERVED.
3  *
4  * See file LICENSE for terms.
5  */
6 
7 #ifdef HAVE_CONFIG_H
8 #  include "config.h"
9 #endif
10 
11 #include <errno.h>
12 #include <unistd.h>
13 #include <sys/mman.h>
14 #include <sys/syscall.h>
15 
16 #include <ucm/event/event.h>
17 #include <ucm/util/log.h>
18 #include <ucm/util/reloc.h>
19 #include <ucm/util/replace.h>
20 #include <ucm/mmap/mmap.h>
21 #include <ucs/sys/compiler.h>
22 #include <ucs/sys/preprocessor.h>
23 
24 #ifndef MAP_FAILED
25 #define MAP_FAILED ((void*)-1)
26 #endif
27 
28 #ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
29 pthread_mutex_t ucm_reloc_get_orig_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
30 #else
31 pthread_mutex_t ucm_reloc_get_orig_lock;
32 static void ucm_reloc_get_orig_lock_init(void) __attribute__((constructor(101)));
ucm_reloc_get_orig_lock_init(void)33 static void ucm_reloc_get_orig_lock_init(void)
34 {
35 	pthread_mutexattr_t attr;
36 
37 	pthread_mutexattr_init(&attr);
38 	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
39 	pthread_mutex_init(&ucm_reloc_get_orig_lock, &attr);
40 }
41 #endif
42 pthread_t volatile ucm_reloc_get_orig_thread = (pthread_t)-1;
43 
44 UCM_DEFINE_REPLACE_FUNC(mmap,    void*, MAP_FAILED, void*, size_t, int, int, int, off_t)
45 UCM_DEFINE_REPLACE_FUNC(munmap,  int,   -1,         void*, size_t)
46 #if HAVE_MREMAP
47 UCM_DEFINE_REPLACE_FUNC(mremap,  void*, MAP_FAILED, void*, size_t, size_t, int)
48 #endif
49 UCM_DEFINE_REPLACE_FUNC(shmat,   void*, MAP_FAILED, int, const void*, int)
50 UCM_DEFINE_REPLACE_FUNC(shmdt,   int,   -1,         const void*)
51 UCM_DEFINE_REPLACE_FUNC(sbrk,    void*, MAP_FAILED, intptr_t)
52 UCM_DEFINE_REPLACE_FUNC(brk,     int,   -1,         void*)
53 UCM_DEFINE_REPLACE_FUNC(madvise, int,   -1,         void*, size_t, int)
54 
55 UCM_DEFINE_SELECT_FUNC(mmap, void*, MAP_FAILED, SYS_mmap, void*, size_t, int, int, int, off_t)
56 UCM_DEFINE_SELECT_FUNC(munmap, int, -1, SYS_munmap, void*, size_t)
57 #if HAVE_MREMAP
58 UCM_DEFINE_SELECT_FUNC(mremap, void*, MAP_FAILED, SYS_mremap, void*, size_t, size_t, int)
59 #endif
60 UCM_DEFINE_SELECT_FUNC(madvise, int, -1, SYS_madvise, void*, size_t, int)
61 
62 #if UCM_BISTRO_HOOKS
63 #if HAVE_DECL_SYS_SHMAT
64 
65 UCM_DEFINE_SELECT_FUNC(shmat, void*, MAP_FAILED, SYS_shmat, int, const void*, int)
66 
67 #elif HAVE_DECL_SYS_IPC
68 #  ifndef IPCOP_shmat
69 #    define IPCOP_shmat 21
70 #  endif
71 
72 _UCM_DEFINE_DLSYM_FUNC(shmat, ucm_orig_dlsym_shmat, ucm_override_shmat,
73                        void*, MAP_FAILED, int, const void*, int)
74 
75 void *ucm_orig_shmat(int shmid, const void *shmaddr, int shmflg)
76 {
77     unsigned long res;
78     void *addr;
79 
80     if (ucm_mmap_hook_mode() == UCM_MMAP_HOOK_RELOC) {
81         return ucm_orig_dlsym_shmat(shmid, shmaddr, shmflg);
82     } else {
83         /* Using IPC syscall of shmat implementation */
84         res = syscall(SYS_ipc, IPCOP_shmat, shmid, shmflg, &addr, shmaddr);
85 
86         return res ? MAP_FAILED : addr;
87     }
88 }
89 
90 #endif
91 
92 #if HAVE_DECL_SYS_SHMDT
93 
94 UCM_DEFINE_SELECT_FUNC(shmdt, int, -1, SYS_shmdt, const void*)
95 
96 #elif HAVE_DECL_SYS_IPC
97 #  ifndef IPCOP_shmdt
98 #    define IPCOP_shmdt 22
99 #  endif
100 
101 _UCM_DEFINE_DLSYM_FUNC(shmdt, ucm_orig_dlsym_shmdt, ucm_override_shmdt,
102                        int, -1, const void*)
103 
104 int ucm_orig_shmdt(const void *shmaddr)
105 {
106     if (ucm_mmap_hook_mode() == UCM_MMAP_HOOK_RELOC) {
107         return ucm_orig_dlsym_shmdt(shmaddr);
108     } else {
109         /* Using IPC syscall of shmdt implementation */
110         return syscall(SYS_ipc, IPCOP_shmdt, 0, 0, 0, shmaddr);
111     }
112 }
113 
114 #endif
115 
116 #if HAVE___CURBRK
117 extern void *__curbrk;
118 #endif
119 
120 _UCM_DEFINE_DLSYM_FUNC(brk, ucm_orig_dlsym_brk, ucm_override_brk, int, -1, void*)
121 
ucm_brk_syscall(void * addr)122 void *ucm_brk_syscall(void *addr)
123 {
124     return (void*)syscall(SYS_brk, addr);
125 }
126 
ucm_orig_brk(void * addr)127 int ucm_orig_brk(void *addr)
128 {
129     void *new_addr;
130 
131 #if HAVE___CURBRK
132     __curbrk =
133 #endif
134     new_addr = ucm_brk_syscall(addr);
135 
136     if (new_addr < addr) {
137         errno = ENOMEM;
138         return -1;
139     } else {
140         return 0;
141     }
142 }
143 
_UCM_DEFINE_DLSYM_FUNC(sbrk,ucm_orig_dlsym_sbrk,ucm_override_sbrk,void *,MAP_FAILED,intptr_t)144 _UCM_DEFINE_DLSYM_FUNC(sbrk, ucm_orig_dlsym_sbrk, ucm_override_sbrk,
145                        void*, MAP_FAILED, intptr_t)
146 
147 void *ucm_orig_sbrk(intptr_t increment)
148 {
149     void *prev;
150 
151     if (ucm_mmap_hook_mode() == UCM_MMAP_HOOK_RELOC) {
152         return ucm_orig_dlsym_sbrk(increment);
153     } else {
154         prev = ucm_brk_syscall(0);
155         return ucm_orig_brk(UCS_PTR_BYTE_OFFSET(prev, increment)) ? (void*)-1 : prev;
156     }
157 }
158 
159 #else /* UCM_BISTRO_HOOKS */
160 
161 UCM_DEFINE_DLSYM_FUNC(sbrk, void*, MAP_FAILED, intptr_t)
162 UCM_DEFINE_DLSYM_FUNC(shmat, void*, MAP_FAILED, int, const void*, int)
163 UCM_DEFINE_DLSYM_FUNC(shmdt, int, -1, const void*)
164 
165 #endif /* UCM_BISTRO_HOOKS */
166