Blame view

redmine authored
1
/*
redmine authored
2
    clsync - file tree sync utility based on inotify
redmine authored
3

redmine authored
4
    Copyright (C) 2013  Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
redmine authored
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

redmine authored
20
#include "macros.h"
redmine authored
21

Andrew Savchenko authored
22 23
#include <stdlib.h>
#include <string.h>
redmine authored
24 25 26
#ifdef CAPABILITIES_SUPPORT
# include <unistd.h>
# include <sys/mman.h>
redmine authored
27 28 29 30
# ifdef SECCOMP_SUPPORT
#  include <sys/stat.h>
#  include <fcntl.h>
# endif
redmine authored
31
#endif
Andrew Savchenko authored
32

redmine authored
33 34 35
#include <sys/ipc.h>			// shmget()
#include <sys/shm.h>			// shmget()

redmine authored
36
#include "malloc.h"
redmine authored
37
#include "error.h"
redmine authored
38 39 40 41 42 43 44 45
#include "configuration.h"

#ifdef CAPABILITIES_SUPPORT
long pagesize;
# ifdef SECCOMP_SUPPORT
int  devzero_fd;
# endif
#endif
redmine authored
46

Andrew Savchenko authored
47
void *xmalloc(size_t size) {
redmine authored
48
	debug(20, "(%li)", size);
Andrew Savchenko authored
49
#ifdef PARANOID
redmine authored
50
	size++;	// Just in case
Andrew Savchenko authored
51
#endif
redmine authored
52

Andrew Savchenko authored
53
	void *ret = malloc(size);
redmine authored
54

redmine authored
55 56
	if (ret == NULL)
		critical("(%li): Cannot allocate memory.", size);
redmine authored
57

redmine authored
58 59 60
#ifdef PARANOID
	memset(ret, 0, size);
#endif
redmine authored
61 62 63
	return ret;
}

Andrew Savchenko authored
64
void *xcalloc(size_t nmemb, size_t size) {
redmine authored
65
	debug(20, "(%li, %li)", nmemb, size);
Andrew Savchenko authored
66
#ifdef PARANOID
redmine authored
67 68
	nmemb++; // Just in case
	size++;	 // Just in case
Andrew Savchenko authored
69
#endif
redmine authored
70

Andrew Savchenko authored
71
	void *ret = calloc(nmemb, size);
redmine authored
72

redmine authored
73 74
	if (ret == NULL)
		critical("(%li): Cannot allocate memory.", size);
redmine authored
75

redmine authored
76
//	memset(ret, 0, nmemb*size);	// Just in case
redmine authored
77 78 79
	return ret;
}

Andrew Savchenko authored
80
void *xrealloc(void *oldptr, size_t size) {
redmine authored
81
	debug(20, "(%p, %li)", oldptr, size);
Andrew Savchenko authored
82
#ifdef PARANOID
redmine authored
83
	size++;	// Just in case
Andrew Savchenko authored
84
#endif
redmine authored
85

Andrew Savchenko authored
86
	void *ret = realloc(oldptr, size);
redmine authored
87

redmine authored
88 89 90 91 92 93 94 95 96
	if (ret == NULL)
		critical("(%p, %li): Cannot reallocate memory.", oldptr, size);

	return ret;
}

#ifdef CAPABILITIES_SUPPORT
void *malloc_align(size_t size) {
	size_t total_size;
redmine authored
97
	void *ret = NULL;
redmine authored
98 99 100 101 102 103
	debug(20, "(%li)", size);
# ifdef PARANOID
	size++;	 // Just in case
# endif

	total_size  = size;
redmine authored
104 105

	// Rounding total_size up to a number of times pagesize
redmine authored
106 107 108 109 110 111
	total_size += pagesize-1;
	total_size /= pagesize;
	total_size *= pagesize;

	if (posix_memalign(&ret, pagesize, total_size))
		critical("(%li): Cannot allocate memory.", size);
redmine authored
112

redmine authored
113 114 115 116 117 118
# ifdef PARANOID
	if (ret == NULL)
		critical("(%li): ptr == NULL.", size);
# endif

//	memset(ret, 0, nmemb*size);	// Just in case
redmine authored
119 120
	return ret;
}
redmine authored
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138

void *calloc_align(size_t nmemb, size_t size) {
	size_t total_size;
	void *ret;
	debug(20, "(%li, %li)", nmemb, size);
# ifdef PARANOID
	nmemb++; // Just in case
	size++;	 // Just in case
# endif

	total_size = nmemb*size;
	ret = malloc_align(total_size);
	memset(ret, 0, total_size);

	return ret;
}

char *strdup_protect(const char *src, int prot) {
redmine authored
139
	size_t len = strlen(src)+1;
redmine authored
140 141 142 143 144 145 146
	char *dst  = malloc_align(len);
	strcpy(dst, src);
	if (mprotect(dst, len, prot))
		critical("(%p, 0x%o): Got error from mprotect(%p, %lu, 0x%o)", src, prot, dst, len, prot);

	return dst;
}
redmine authored
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177

# ifdef SECCOMP_SUPPORT
int is_protected(void *addr) {
	char *_addr = addr, t;
	int is_protected;
	t = *_addr;

	is_protected = (read(devzero_fd, addr, 1) == -1);

	if (!is_protected)
		*_addr = t;

	return is_protected;
}
# endif

#endif

int memory_init() {
#ifdef CAPABILITIES_SUPPORT
	pagesize   = sysconf(_SC_PAGE_SIZE);

	if (pagesize == -1)
		critical("Got error from sysconf(_SC_PAGE_SIZE)");

# ifdef SECCOMP_SUPPORT
	devzero_fd = open(DEVZERO, O_RDONLY);

	if (devzero_fd == -1)
		critical("Got error while open(\""DEVZERO"\", O_RDONLY)");
# endif
redmine authored
178 179
#endif

redmine authored
180 181 182
	return 0;
}

redmine authored
183
void *shm_malloc_try(size_t size) {
redmine authored
184
	void *ret;
redmine authored
185 186 187
#ifdef PARANOID
	size++;
#endif
redmine authored
188 189
	int privileged_shmid = shmget(0, size, IPC_PRIVATE|IPC_CREAT|0600);
	struct shmid_ds shmid_ds;
redmine authored
190 191
	if (privileged_shmid == -1) return NULL;

redmine authored
192
	ret = shmat(privileged_shmid, NULL, 0);
redmine authored
193
	if ((long)ret == -1) return NULL;
redmine authored
194 195 196 197 198 199 200 201 202
	debug(15, "ret == %p", ret);

	// Forbidding access for others to the pointer
	shmctl(privileged_shmid, IPC_STAT, &shmid_ds);
	shmid_ds.shm_perm.mode = 0;
	shmctl(privileged_shmid, IPC_SET,  &shmid_ds);

	// Checking that nobody else attached to the shared memory before access forbidding
	shmctl(privileged_shmid, IPC_STAT, &shmid_ds);
redmine authored
203 204 205 206 207 208 209 210 211 212 213 214 215 216
	if (shmid_ds.shm_lpid != shmid_ds.shm_cpid) {
		error("A process (pid %u) attached to my shared memory. It's a security problem. Emergency exit.");
		shmdt (ret);
		return NULL;
	}

	return ret;
}

void *shm_malloc(size_t size) {
	void *ret;

	ret = shm_malloc_try(size);
	critical_on (ret == NULL);
redmine authored
217 218 219 220

	return ret;
}

redmine authored
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
void *shm_calloc(size_t nmemb, size_t size) {
	void *ret;
	size_t total_size;
#ifdef PARANOID
	nmemb++;
	size++;
#endif

	total_size = nmemb * size;

	ret = shm_malloc(total_size);
	critical_on (ret == NULL);

	memset(ret, 0, total_size);
	return ret;
}

redmine authored
238 239 240 241 242
void shm_free(void *ptr) {
	debug(25, "(%p)", ptr);
	shmdt(ptr);
}