redmine

Added options "--forget-privthread-info" and "--secure-thread-splitting"

... ... @@ -109,6 +109,8 @@ enum flags_enum {
DETACH_MISCELLANEA = 33|OPTION_LONGOPTONLY,
ADDPERMITTEDHOOKFILES = 34|OPTION_LONGOPTONLY,
SECCOMP_FILTER = 35|OPTION_LONGOPTONLY,
FORGET_PRIVTHREAD_INFO = 36|OPTION_LONGOPTONLY,
SECURETHREADSPLITTING = 37|OPTION_LONGOPTONLY,
};
typedef enum flags_enum flags_t;
... ...
... ... @@ -84,12 +84,16 @@ static const struct option long_options[] =
{"detach-miscellanea", optional_argument, NULL, DETACH_MISCELLANEA},
#endif
#ifdef CAPABILITIES_SUPPORT
# ifdef SECCOMP_SUPPORT
{"secure-thread-splitting",optional_argument, NULL, SECURETHREADSPLITTING},
# endif
{"thread-splitting", optional_argument, NULL, THREADSPLITTING},
{"check-execvp-args", optional_argument, NULL, CHECK_EXECVP_ARGS},
{"add-permitted-hook-files",required_argument, NULL, ADDPERMITTEDHOOKFILES},
# ifdef SECCOMP_SUPPORT
{"seccomp-filter", optional_argument, NULL, SECCOMP_FILTER},
# endif
{"forget-privthread-info",optional_argument, NULL, FORGET_PRIVTHREAD_INFO},
#endif
#ifdef GETMNTENT_SUPPORT
{"mountpoints", optional_argument, NULL, MOUNTPOINTS},
... ... @@ -710,6 +714,15 @@ int parse_parameter(ctx_t *ctx_p, uint16_t param_id, char *arg, paramsource_t pa
break;
}
#ifdef CAPABILITIES_SUPPORT
# ifdef SECCOMP_SUPPORT
case SECURETHREADSPLITTING: {
ctx_p->flags[THREADSPLITTING]++;
ctx_p->flags[CHECK_EXECVP_ARGS]++;
ctx_p->flags[SECCOMP_FILTER]++;
ctx_p->flags[FORGET_PRIVTHREAD_INFO]++;
break;
}
# endif
case SYNCHANDLERUID: {
struct passwd *pwd = getpwnam(arg);
ctx_p->flags[param_id]++;
... ... @@ -1479,6 +1492,10 @@ int ctx_check(ctx_t *ctx_p) {
ret = errno = EINVAL;
error("Conflicting options: This value of \"--threading\" cannot be used in conjunction with \"--pre-exit-hook\".");
}
if (ctx_p->flags[THREADING] && ctx_p->flags[SECCOMP_FILTER]) {
ret = errno = EINVAL;
error("Conflicting options: This value of \"--threading\" cannot be used in conjunction with \"--seccomp-filter\".");
}
if (ctx_p->flags[SKIPINITSYNC] && ctx_p->flags[EXITONNOEVENTS]) {
ret = errno = EINVAL;
error("Conflicting options: \"--skip-initialsync\" and \"--exit-on-no-events\" cannot be used together.");
... ...
... ... @@ -1030,6 +1030,12 @@ Is not set by default.
.SH SECURITY OPTIONS
.B \-\-secure\-thread\-splitting
.RS
Implies "\-\-thread\-splitting \-\-check\-execvp\-arguments \-\-seccomp\-filter
\-\-forget\-privthread\-info".
.RE
.B \-u, \-\-uid
.I uid
.RS
... ... @@ -1212,6 +1218,14 @@ too. Otherwise in case of
security bug a hacker will be able to use execvp() with any arguments
with root privileges.
But there's an ability to change a code of the privileged thread from
non\-privileged. To prevent it use
.B \-\-seccomp\-filter
option. It will forbid call of
.BR mprotect (2)
syscall, so the non\-privileged will be unable to drop protection from memory
ages.
Is not set by default.
.RE
... ... @@ -1279,9 +1293,25 @@ rt_sigaction
nanosleep
.RE
This option requires
.BR \-\-threading =off
due to forbidding
.BR mprotect (2)
syscall that is required by
.BR pthread_create (3)
function.
Is not set by default.
.RE
.B \-\-forget\-privthread\-info
.RS
Just sets pthread_t variable for the privileged thread to zero. It complicates
attack on the privileged thread, but makes call of
.BR pthread_join (3)
on a privileged thread end impossible.
.RE
.B \-\-chroot
.I chroot\-directory
.RS
... ...
... ... @@ -1196,6 +1196,9 @@ int privileged_init(ctx_t *ctx_p)
SAFE ( pthread_create(&pthread_thread, NULL, (void *(*)(void *))privileged_handler, ctx_p), return errno);
if (ctx_p->flags[FORGET_PRIVTHREAD_INFO])
pthread_thread = 0;
if (ctx_p->flags[DETACH_NETWORK] == DN_NONPRIVILEGED) {
SAFE ( cap_enable(CAP_TO_MASK(CAP_SYS_ADMIN)), return errno; );
SAFE ( unshare(CLONE_NEWNET), return errno; );
... ... @@ -1248,7 +1251,13 @@ int privileged_deinit(ctx_t *ctx_p)
),
ret = errno
);
SAFE ( pthread_join(pthread_thread, NULL), ret = errno );
if (ctx_p->flags[FORGET_PRIVTHREAD_INFO]) {
pthread_mutex_lock(&pthread_mutex_privileged);
pthread_mutex_unlock(&pthread_mutex_privileged);
} else {
SAFE ( pthread_join(pthread_thread, NULL), ret = errno );
}
SAFE ( pthread_mutex_destroy(&pthread_mutex_privileged), ret = errno );
SAFE ( pthread_mutex_destroy(&pthread_mutex_action_entrance), ret = errno );
... ...