clsync
malloc.c
Go to the documentation of this file.
1 /*
2  clsync - file tree sync utility based on inotify
3 
4  Copyright (C) 2013 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
5 
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "macros.h"
21 
22 #include <stdlib.h>
23 #include <string.h>
24 #ifdef CAPABILITIES_SUPPORT
25 # include <unistd.h>
26 # include <sys/mman.h>
27 # ifdef SECCOMP_SUPPORT
28 # include <sys/stat.h>
29 # include <fcntl.h>
30 # endif
31 #endif
32 
33 #include <sys/ipc.h> // shmget()
34 #include <sys/shm.h> // shmget()
35 
36 #include "malloc.h"
37 #include "error.h"
38 #include "configuration.h"
39 
40 #ifdef CAPABILITIES_SUPPORT
41 long pagesize;
42 # ifdef SECCOMP_SUPPORT
43 int devzero_fd;
44 # endif
45 #endif
46 
47 void *xmalloc ( size_t size )
48 {
49  debug ( 20, "(%li)", size );
50 #ifdef PARANOID
51  size++; // Just in case
52 #endif
53  void *ret = malloc ( size );
54 
55  if ( unlikely(ret == NULL) )
56  critical ( "(%li): Cannot allocate memory.", size );
57 
58 #ifdef PARANOID
59  memset ( ret, 0, size );
60 #endif
61  return ret;
62 }
63 
64 void *xcalloc ( size_t nmemb, size_t size )
65 {
66  debug ( 20, "(%li, %li)", nmemb, size );
67 #ifdef PARANOID
68  nmemb++; // Just in case
69  size++; // Just in case
70 #endif
71  void *ret = calloc ( nmemb, size );
72 
73  if ( unlikely(ret == NULL) )
74  critical ( "(%li): Cannot allocate memory.", size );
75 
76 // memset(ret, 0, nmemb*size); // Just in case
77  return ret;
78 }
79 
80 void *xrealloc ( void *oldptr, size_t size )
81 {
82  debug ( 20, "(%p, %li)", oldptr, size );
83 #ifdef PARANOID
84  size++; // Just in case
85 #endif
86  void *ret = realloc ( oldptr, size );
87 
88  if ( unlikely(ret == NULL) )
89  critical ( "(%p, %li): Cannot reallocate memory.", oldptr, size );
90 
91  return ret;
92 }
93 
94 char *xstrncpy ( char *dest, const char *src, size_t n )
95 {
96  char *ret = strncpy ( dest, src, n - 1 );
97  if ( likely(n > 0) )
98  dest[n-1] = 0;
99  else
100  dest[0] = 0;
101 
102  return ret;
103 }
104 
105 #ifdef CAPABILITIES_SUPPORT
106 void *malloc_align ( size_t size )
107 {
108  size_t total_size;
109  void *ret = NULL;
110  debug ( 20, "(%li)", size );
111 # ifdef PARANOID
112  size++; // Just in case
113 # endif
114  total_size = size;
115  // Rounding total_size up to a number of times pagesize
116  total_size += pagesize - 1;
117  total_size /= pagesize;
118  total_size *= pagesize;
119 
120  if ( unlikely ( posix_memalign ( &ret, pagesize, total_size ) ) )
121  critical ( "(%li): Cannot allocate memory.", size );
122 
123 # ifdef PARANOID
124 
125  if ( unlikely ( ret == NULL ))
126  critical ( "(%li): ptr == NULL.", size );
127 
128 # endif
129 // memset(ret, 0, nmemb*size); // Just in case
130  return ret;
131 }
132 
133 void *calloc_align ( size_t nmemb, size_t size )
134 {
135  size_t total_size;
136  void *ret;
137  debug ( 20, "(%li, %li)", nmemb, size );
138 # ifdef PARANOID
139  nmemb++; // Just in case
140  size++; // Just in case
141 # endif
142  total_size = nmemb * size;
143  ret = malloc_align ( total_size );
144  memset ( ret, 0, total_size );
145  return ret;
146 }
147 
148 char *strdup_protect ( const char *src, int prot )
149 {
150  size_t len = strlen ( src ) + 1;
151  char *dst = malloc_align ( len );
152  strcpy ( dst, src );
153 
154  if ( unlikely ( mprotect ( dst, len, prot ) ) )
155  critical ( "(%p, 0x%o): Got error from mprotect(%p, %lu, 0x%o)", src, prot, dst, len, prot );
156 
157  return dst;
158 }
159 
160 # ifdef SECCOMP_SUPPORT
161 int is_protected ( void *addr )
162 {
163  char *_addr = addr, t;
164  int is_protected;
165  t = *_addr;
166  is_protected = ( read ( devzero_fd, addr, 1 ) == -1 );
167 
168  if ( !is_protected )
169  *_addr = t;
170 
171  return is_protected;
172 }
173 # endif
174 
175 #endif
176 
178 {
179 #ifdef CAPABILITIES_SUPPORT
180  pagesize = sysconf ( _SC_PAGE_SIZE );
181 
182  if ( unlikely ( pagesize == -1 ) )
183  critical ( "Got error from sysconf(_SC_PAGE_SIZE)" );
184 
185 # ifdef SECCOMP_SUPPORT
186  devzero_fd = open ( DEVZERO, O_RDONLY );
187 
188  if ( unlikely ( devzero_fd == -1 ) )
189  critical ( "Got error while open(\""DEVZERO"\", O_RDONLY)" );
190 
191 # endif
192 #endif
193  return 0;
194 }
195 
196 void *shm_malloc_try ( size_t size )
197 {
198  void *ret;
199 #ifdef PARANOID
200  size++;
201 #endif
202  int privileged_shmid = shmget ( 0, size, IPC_PRIVATE | IPC_CREAT | 0600 );
203  struct shmid_ds shmid_ds;
204 
205  if ( unlikely ( privileged_shmid == -1 ) ) return NULL;
206 
207  ret = shmat ( privileged_shmid, NULL, 0 );
208 
209  if ( unlikely ( ( long ) ret == -1 ) ) return NULL;
210 
211  debug ( 15, "ret == %p", ret );
212  // Forbidding access for others to the pointer
213  shmctl ( privileged_shmid, IPC_STAT, &shmid_ds );
214  shmid_ds.shm_perm.mode = 0;
215  shmctl ( privileged_shmid, IPC_SET, &shmid_ds );
216  // Checking that nobody else attached to the shared memory before access forbidding
217  shmctl ( privileged_shmid, IPC_STAT, &shmid_ds );
218 
219  if ( unlikely ( shmid_ds.shm_lpid != shmid_ds.shm_cpid ) ) {
220  error ( "A process (pid %u) attached to my shared memory. It's a security problem. Emergency exit." );
221  shmdt ( ret );
222  return NULL;
223  }
224 
225  return ret;
226 }
227 
228 void *shm_malloc ( size_t size )
229 {
230  void *ret;
231  ret = shm_malloc_try ( size );
232  critical_on ( ret == NULL );
233  return ret;
234 }
235 
236 void *shm_calloc ( size_t nmemb, size_t size )
237 {
238  void *ret;
239  size_t total_size;
240 #ifdef PARANOID
241  nmemb++;
242  size++;
243 #endif
244  total_size = nmemb * size;
245  ret = shm_malloc ( total_size );
246  critical_on ( ret == NULL );
247  memset ( ret, 0, total_size );
248  return ret;
249 }
250 
251 void shm_free ( void *ptr )
252 {
253  debug ( 25, "(%p)", ptr );
254  shmdt ( ptr );
255 }
256 
xstrncpy
char * xstrncpy(char *dest, const char *src, size_t n)
Definition: malloc.c:94
unlikely
#define unlikely(x)
Definition: macros.h:29
shm_free
void shm_free(void *ptr)
Definition: malloc.c:251
macros.h
memory_init
int memory_init()
Definition: malloc.c:177
shm_malloc_try
void * shm_malloc_try(size_t size)
Definition: malloc.c:196
error
#define error(...)
Definition: error.h:36
DEVZERO
#define DEVZERO
Definition: configuration.h:197
error.h
malloc.h
debug
#define debug(debug_level,...)
Definition: error.h:50
critical
#define critical(...)
Definition: error.h:32
configuration.h
likely
#define likely(x)
Definition: macros.h:26
critical_on
#define critical_on(cond)
Definition: error.h:33
shm_malloc
void * shm_malloc(size_t size)
Definition: malloc.c:228
shm_calloc
void * shm_calloc(size_t nmemb, size_t size)
Definition: malloc.c:236