aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Schneider <asn@samba.org>2017-07-11 11:59:33 +0200
committerAndreas Schneider <asn@samba.org>2017-07-13 07:14:53 +0200
commitb5168be4128d7585c30ba98da31926cd3d0066e5 (patch)
treeb784d7a1f7ad30e04342e5ee846f3ad3ffa2eb69
parent0580449fc4749f7340c1904f90b385f809430e72 (diff)
downloaduid_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.c163
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,