diff options
author | Andreas Schneider <asn@samba.org> | 2017-07-11 11:59:33 +0200 |
---|---|---|
committer | Andreas Schneider <asn@samba.org> | 2017-07-13 07:14:53 +0200 |
commit | b5168be4128d7585c30ba98da31926cd3d0066e5 (patch) | |
tree | b784d7a1f7ad30e04342e5ee846f3ad3ffa2eb69 | |
parent | 0580449fc4749f7340c1904f90b385f809430e72 (diff) | |
download | uid_wrapper-b5168be4128d7585c30ba98da31926cd3d0066e5.tar.gz uid_wrapper-b5168be4128d7585c30ba98da31926cd3d0066e5.tar.xz uid_wrapper-b5168be4128d7585c30ba98da31926cd3d0066e5.zip |
uwrap: Add support to initialize groups while forking
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
-rw-r--r-- | src/uid_wrapper.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/uid_wrapper.c b/src/uid_wrapper.c index ded857a..6e39eb6 100644 --- a/src/uid_wrapper.c +++ b/src/uid_wrapper.c @@ -815,6 +815,66 @@ int pthread_create(pthread_t *thread, * UWRAP ID HANDLING *********************************************************/ +#define GROUP_STRING_SIZE 16384 + +/** + * This function exports all the IDs of the current user so if + * we fork and then exec we can setup uid_wrapper in the new process + * with those IDs. + */ +static void uwrap_export_ids(struct uwrap_thread *id) +{ + char groups_str[GROUP_STRING_SIZE] = {0}; + size_t groups_str_size = sizeof(groups_str); + char unsigned_str[32] = {0}; + int i; + + /* UIDS */ + snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->ruid); + setenv("UID_WRAPPER_INITIAL_RUID", unsigned_str, 1); + + snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->euid); + setenv("UID_WRAPPER_INITIAL_EUID", unsigned_str, 1); + + snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->suid); + setenv("UID_WRAPPER_INITIAL_SUID", unsigned_str, 1); + + /* GIDS */ + snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->rgid); + setenv("UID_WRAPPER_INITIAL_RGID", unsigned_str, 1); + + snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->egid); + setenv("UID_WRAPPER_INITIAL_EGID", unsigned_str, 1); + + snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->sgid); + setenv("UID_WRAPPER_INITIAL_SGID", unsigned_str, 1); + + /* GROUPS */ + snprintf(unsigned_str, sizeof(unsigned_str), "%u", id->ngroups); + setenv("UID_WRAPPER_INITIAL_GROUPS_COUNT", unsigned_str, 1); + + for (i = 0; i < id->ngroups; i++) { + size_t groups_str_len = strlen(groups_str); + size_t groups_str_avail = groups_str_size - groups_str_len; + size_t len; + + len = snprintf(unsigned_str, sizeof(unsigned_str), ",%u", id->groups[i]); + if (len <= 1) { + continue; + } + if (len < groups_str_avail) { + snprintf(groups_str + groups_str_len, + groups_str_size - groups_str_len, + "%s", + i == 0 ? unsigned_str + 1 : unsigned_str); + } + } + + if (id->ngroups > 0) { + setenv("UID_WRAPPER_INITIAL_GROUPS", groups_str, 1); + } +} + static void uwrap_thread_prepare(void) { struct uwrap_thread *id = uwrap_tls_id; @@ -859,6 +919,8 @@ static void uwrap_thread_child(void) return; } + uwrap_export_ids(id); + /* * "Garbage collector" - Inspired by DESTRUCTOR. * All threads (except one which called fork()) are dead now.. Dave @@ -884,6 +946,105 @@ static void uwrap_thread_child(void) UWRAP_UNLOCK_ALL; } +/* + * This initializes uid_wrapper with the IDs exported to the environment. Those + * are normally set after we forked and executed. + */ +static void uwrap_init_env(struct uwrap_thread *id) +{ + const char *env; + int ngroups = 0; + + env = getenv("UID_WRAPPER_INITIAL_RUID"); + if (env != NULL && env[0] != '\0') { + UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize ruid with %s", env); + id->ruid = strtoul(env, (char **)NULL, 10); + unsetenv("UID_WRAPPER_INITIAL_RUID"); + } + + env = getenv("UID_WRAPPER_INITIAL_EUID"); + if (env != NULL && env[0] != '\0') { + UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize euid with %s", env); + id->euid = strtoul(env, (char **)NULL, 10); + unsetenv("UID_WRAPPER_INITIAL_EUID"); + } + + env = getenv("UID_WRAPPER_INITIAL_SUID"); + if (env != NULL && env[0] != '\0') { + UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize suid with %s", env); + id->suid = strtoul(env, (char **)NULL, 10); + unsetenv("UID_WRAPPER_INITIAL_SUID"); + } + + env = getenv("UID_WRAPPER_INITIAL_RGID"); + if (env != NULL && env[0] != '\0') { + UWRAP_LOG(UWRAP_LOG_DEBUG, "Initialize ruid with %s", env); + id->rgid = strtoul(env, (char **)NULL, 10); + unsetenv("UID_WRAPPER_INITIAL_RGID"); + } + + env = getenv("UID_WRAPPER_INITIAL_EGID"); + if (env != NULL && env[0] != '\0') { + UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize egid with %s", env); + id->egid = strtoul(env, (char **)NULL, 10); + unsetenv("UID_WRAPPER_INITIAL_EGID"); + } + + env = getenv("UID_WRAPPER_INITIAL_SGID"); + if (env != NULL && env[0] != '\0') { + UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize sgid with %s", env); + id->sgid = strtoul(env, (char **)NULL, 10); + unsetenv("UID_WRAPPER_INITIAL_SGID"); + } + + env = getenv("UID_WRAPPER_INITIAL_GROUPS_COUNT"); + if (env != NULL && env[0] != '\0') { + ngroups = strtol(env, (char **)NULL, 10); + unsetenv("UID_WRAPPER_INITIAL_GROUPS_COUNT"); + } + + if (ngroups > 0) { + int i = 0; + + id->ngroups = 0; + + free(id->groups); + id->groups = malloc(sizeof(gid_t) * ngroups); + if (id->groups == NULL) { + UWRAP_LOG(UWRAP_LOG_ERROR, + "Unable to allocate memory"); + exit(-1); + } + + env = getenv("UID_WRAPPER_INITIAL_GROUPS"); + if (env != NULL && env[0] != '\0') { + char *groups_str = NULL; + char *saveptr = NULL; + const char *p = NULL; + + groups_str = strdup(env); + if (groups_str == NULL) { + exit(-1); + } + + p = strtok_r(groups_str, ",", &saveptr); + while (p != NULL) { + id->groups[i] = strtol(p, (char **)NULL, 10); + i++; + + p = strtok_r(NULL, ",", &saveptr); + } + } + + if (i != ngroups) { + exit(-1); + } + + UWRAP_LOG(UWRAP_LOG_DEBUG, "Initalize groups with %s", env); + id->ngroups = ngroups; + } +} + static void uwrap_init(void) { const char *env; @@ -972,6 +1133,8 @@ static void uwrap_init(void) } } + uwrap_init_env(id); + id->enabled = true; UWRAP_LOG(UWRAP_LOG_DEBUG, |