redmine

Fixed an IPC shm leak

... ... @@ -65,6 +65,7 @@
#define DEFAULT_RETRIES 1
#define DEFAULT_VERBOSE 3
#define DEFAULT_DUMPDIR "/tmp/clsync-dump-%label%"
#define DEFAULT_DETACH_IPC 1
#define FANOTIFY_FLAGS (FAN_CLOEXEC|FAN_UNLIMITED_QUEUE|FAN_UNLIMITED_MARKS)
#define FANOTIFY_EVFLAGS (O_LARGEFILE|O_RDONLY|O_CLOEXEC)
... ...
... ... @@ -127,6 +127,7 @@ enum flags_enum {
MODSIGN = 43|OPTION_LONGOPTONLY,
CANCEL_SYSCALLS = 44|OPTION_LONGOPTONLY,
EXITONSYNCSKIP = 45|OPTION_LONGOPTONLY,
DETACH_IPC = 46|OPTION_LONGOPTONLY,
};
typedef enum flags_enum flags_t;
... ...
... ... @@ -217,6 +217,8 @@ void _critical(const char *const function_name, const char *fmt, ...) {
if (error_mutex_p != NULL)
pthread_mutex_unlock(error_mutex_p);
error_deinit();
exit(errno);
return;
... ... @@ -340,9 +342,40 @@ void error_init(void *_outputmethod, int *_quiet, int *_verbose, int *_debug) {
verbose = _verbose;
debug = _debug;
pthread_mutex_init_shared(&error_mutex_p);
openlog(NULL, SYSLOG_FLAGS, SYSLOG_FACILITY);
return;
}
ipc_type_t ipc_type;
void error_init_ipc(ipc_type_t _ipc_type) {
static pthread_mutex_t error_mutex = PTHREAD_MUTEX_INITIALIZER;
ipc_type = _ipc_type;
switch (ipc_type) {
case IPCT_SHARED:
pthread_mutex_init_shared(&error_mutex_p);
break;
case IPCT_PRIVATE:
error_mutex_p = &error_mutex;
pthread_mutex_init(error_mutex_p, NULL);
break;
default:
critical ("Unknown ipc_type: %i", ipc_type);
}
return;
}
void error_deinit() {
switch (ipc_type) {
case IPCT_SHARED:
pthread_mutex_destroy_shared(error_mutex_p);
break;
case IPCT_PRIVATE:
break;
}
return;
}
... ...
... ... @@ -56,7 +56,15 @@ extern void _info(const char *const function_name, const char *fmt, ...);
#define critical_or_warning(cond, ...) ((cond) ? _critical : _warning)(__FUNCTION__, __VA_ARGS__)
enum ipc_type {
IPCT_PRIVATE,
IPCT_SHARED,
};
typedef enum ipc_type ipc_type_t;
extern void error_init(void *_outputmethod, int *_quiet, int *_verbose, int *_debug);
extern void error_init_ipc(ipc_type_t ipc_type);
extern void error_deinit();
enum outputmethod {
OM_STDERR = 0,
... ...
... ... @@ -86,6 +86,7 @@ static const struct option long_options[] =
#endif
#ifdef UNSHARE_SUPPORT
{"detach-network", required_argument, NULL, DETACH_NETWORK},
{"detach-ipc", required_argument, NULL, DETACH_IPC},
{"detach-miscellanea", optional_argument, NULL, DETACH_MISCELLANEA},
#endif
#ifdef CAPABILITIES_SUPPORT
... ... @@ -2275,6 +2276,7 @@ int main(int _argc, char *_argv[]) {
ctx_p->synchandler_uid = getuid();
ctx_p->synchandler_gid = getgid();
ctx_p->flags[CAPS_INHERIT] = DEFAULT_CAPS_INHERIT;
ctx_p->flags[DETACH_IPC] = DEFAULT_DETACH_IPC;
parse_parameter(ctx_p, LABEL, strdup(DEFAULT_LABEL), PS_DEFAULTS);
ncpus = sysconf(_SC_NPROCESSORS_ONLN); // Get number of available logical CPUs
... ... @@ -2396,6 +2398,10 @@ int main(int _argc, char *_argv[]) {
error("Got error from unshare("TOSTR(a)")");\
ret = errno;\
}
if (ctx_p->flags[DETACH_IPC]) {
unshare(CLONE_NEWUTS);
error_init_ipc(ctx_p->flags[SPLITTING] == SM_PROCESS ? IPCT_SHARED : IPCT_PRIVATE);
}
if (ctx_p->flags[DETACH_MISCELLANEA]) {
unshare(CLONE_NEWIPC);
unshare(CLONE_NEWUTS);
... ... @@ -2825,11 +2831,11 @@ int main(int _argc, char *_argv[]) {
// == /RUNNING ==
if (ctx_p->pidfile != NULL) {
if (unlink(ctx_p->pidfile)) {
error("Cannot unlink pidfile \"%s\"",
ctx_p->pidfile);
ret = errno;
}
if (unlink(ctx_p->pidfile)) {
error("Cannot unlink pidfile \"%s\"",
ctx_p->pidfile);
ret = errno;
}
}
if (ctx_p->statusfile != NULL) {
... ... @@ -2863,17 +2869,18 @@ int main(int _argc, char *_argv[]) {
main_cleanup(ctx_p);
if (ctx_p->watchdirsize)
free(ctx_p->watchdir);
free(ctx_p->watchdir);
if (ctx_p->watchdirwslashsize)
free(ctx_p->watchdirwslash);
free(ctx_p->watchdirwslash);
if (ctx_p->destdirsize)
free(ctx_p->destdir);
free(ctx_p->destdir);
if (ctx_p->destdirwslashsize)
free(ctx_p->destdirwslash);
error_deinit();
ctx_cleanup(ctx_p);
debug(1, "finished, exitcode: %i: %s.", ret, strerror(ret));
free(ctx_p);
... ...
... ... @@ -180,16 +180,17 @@ int memory_init() {
return 0;
}
void *shm_malloc(size_t size) {
void *shm_malloc_try(size_t size) {
void *ret;
#ifdef PARANOID
size++;
#endif
int privileged_shmid = shmget(0, size, IPC_PRIVATE|IPC_CREAT|0600);
struct shmid_ds shmid_ds;
critical_on (privileged_shmid == -1)
if (privileged_shmid == -1) return NULL;
ret = shmat(privileged_shmid, NULL, 0);
critical_on((long)ret == -1);
if ((long)ret == -1) return NULL;
debug(15, "ret == %p", ret);
// Forbidding access for others to the pointer
... ... @@ -199,8 +200,20 @@ void *shm_malloc(size_t size) {
// Checking that nobody else attached to the shared memory before access forbidding
shmctl(privileged_shmid, IPC_STAT, &shmid_ds);
if (shmid_ds.shm_lpid != shmid_ds.shm_cpid)
critical("A process (pid %u) attached to my shared memory. It's a security problem. Emergency exit.");
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);
return ret;
}
... ...
... ... @@ -31,6 +31,7 @@ extern int is_protected(void *addr);
# endif
#endif
extern void *shm_malloc(size_t size);
extern void *shm_malloc_try(size_t size);
extern void *shm_calloc(size_t nmemb, size_t size);
extern void shm_free(void *ptr);
... ...
... ... @@ -1663,6 +1663,15 @@ Don't do anything.
The default value is "non\-privileged".
.RE
.B \-\-detach\-ipc
.RS
.B [Linux only]
Make an own IPC namespace.
Is set by default.
.RE
.B \-\-detach\-miscellanea
.RS
.B [Linux only]
... ...
... ... @@ -24,7 +24,7 @@
int pthread_mutex_init_shared(pthread_mutex_t **mutex_p) {
static pthread_mutex_t mutex_initial = PTHREAD_MUTEX_INITIALIZER;
*mutex_p = shm_malloc(sizeof(**mutex_p));
*mutex_p = shm_malloc_try(sizeof(**mutex_p));
memcpy(*mutex_p, &mutex_initial, sizeof(mutex_initial));
pthread_mutexattr_t attr;
... ...