summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRobin Hack <hack.robin@gmail.com>2015-01-23 15:25:16 +0100
committerAndreas Schneider <asn@cryptomilk.org>2015-01-28 17:17:07 +0100
commitfbdd2d46249235aac3adaa9f20b707d6aedb0bfc (patch)
tree77a6d8791423425ddd1c6ff3ce3b5216a342d70e /lib
parentc6a1e6058eeb9234f7bd41124cf4532288e8b776 (diff)
downloadsamba-fbdd2d46249235aac3adaa9f20b707d6aedb0bfc.tar.gz
uwrap: Extend support for (set|get)groups libc functions and syscalls.
Signed-off-by: Robin Hack <hack.robin@gmail.com> Reviewed-by: Andreas Schneider <asn@samba.org> Reviewed-by: Stefan Metzmacher <metze@samba.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/uid_wrapper/uid_wrapper.c93
1 files changed, 82 insertions, 11 deletions
diff --git a/lib/uid_wrapper/uid_wrapper.c b/lib/uid_wrapper/uid_wrapper.c
index a2ad6665bc7..efc4407c7e2 100644
--- a/lib/uid_wrapper/uid_wrapper.c
+++ b/lib/uid_wrapper/uid_wrapper.c
@@ -226,8 +226,8 @@ struct uwrap_thread {
gid_t egid;
gid_t sgid;
- gid_t *groups;
int ngroups;
+ gid_t *groups;
struct uwrap_thread *next;
struct uwrap_thread *prev;
@@ -252,6 +252,9 @@ struct uwrap {
gid_t egid;
gid_t sgid;
+ int ngroups;
+ gid_t *groups;
+
/* Real uid and gid of user who run uid wrapper */
uid_t myuid;
gid_t mygid;
@@ -536,7 +539,7 @@ static int uwrap_new_id(pthread_t tid, bool do_alloc)
return -1;
}
- id->groups = malloc(sizeof(gid_t) * 1);
+ id->groups = malloc(sizeof(gid_t) * uwrap.ngroups);
if (id->groups == NULL) {
UWRAP_LOG(UWRAP_LOG_ERROR, "Unable to allocate memory");
SAFE_FREE(id);
@@ -559,8 +562,12 @@ static int uwrap_new_id(pthread_t tid, bool do_alloc)
id->egid = uwrap.egid;
id->sgid = uwrap.sgid;
- id->ngroups = 1;
- id->groups[0] = uwrap.mygid;
+ id->ngroups = uwrap.ngroups;
+ if (uwrap.groups != NULL) {
+ memcpy(id->groups, uwrap.groups, sizeof(gid_t) * uwrap.ngroups);
+ } else {
+ id->groups = NULL;
+ }
return 0;
}
@@ -644,9 +651,42 @@ static void uwrap_init(void)
if (root != NULL && root[0] == '1') {
uwrap.ruid = uwrap.euid = uwrap.suid = 0;
uwrap.rgid = uwrap.egid = uwrap.sgid = 0;
+
+ uwrap.groups = malloc(sizeof(gid_t) * 1);
+ if (uwrap.groups == NULL) {
+ UWRAP_LOG(UWRAP_LOG_ERROR,
+ "Unable to allocate memory");
+ exit(-1);
+ }
+
+ uwrap.ngroups = 1;
+ uwrap.groups[0] = 0;
+
} else {
uwrap.ruid = uwrap.euid = uwrap.suid = uwrap.myuid;
uwrap.rgid = uwrap.egid = uwrap.sgid = uwrap.mygid;
+
+ uwrap.ngroups = libc_getgroups(0, NULL);
+ if (uwrap.ngroups == -1) {
+ UWRAP_LOG(UWRAP_LOG_ERROR,
+ "Unable to call libc_getgroups in uwrap_init.");
+ exit(-1);
+ }
+ uwrap.groups = malloc(sizeof(gid_t) * uwrap.ngroups);
+ if (uwrap.groups == NULL) {
+ UWRAP_LOG(UWRAP_LOG_ERROR, "Unable to allocate memory");
+ exit(-1);
+ }
+ if (libc_getgroups(uwrap.ngroups, uwrap.groups) == -1) {
+ UWRAP_LOG(UWRAP_LOG_ERROR,
+ "Unable to call libc_getgroups again in uwrap_init.");
+ uwrap.ngroups = 0;
+ /*
+ * Deallocation of uwrap.groups is handled by
+ * library destructor.
+ */
+ exit(-1);
+ }
}
rc = uwrap_new_id(tid, true);
@@ -1075,9 +1115,12 @@ static int uwrap_setgroups_thread(size_t size, const gid_t *list)
UWRAP_LOCK(uwrap_id);
if (size == 0) {
- free(id->groups);
- id->groups = NULL;
+ SAFE_FREE(id->groups);
id->ngroups = 0;
+ if (pthread_equal(id->tid, uwrap.tid)) {
+ SAFE_FREE(uwrap.groups);
+ uwrap.ngroups = 0;
+ }
} else if (size > 0) {
gid_t *tmp;
@@ -1087,9 +1130,21 @@ static int uwrap_setgroups_thread(size_t size, const gid_t *list)
goto out;
}
id->groups = tmp;
-
id->ngroups = size;
memcpy(id->groups, list, size * sizeof(gid_t));
+
+ if (pthread_equal(id->tid, uwrap.tid)) {
+ tmp = realloc(uwrap.groups, sizeof(gid_t) * size);
+ if (tmp == NULL) {
+ /* How to return back id->groups? */
+ errno = ENOMEM;
+ goto out;
+ }
+
+ uwrap.groups = tmp;
+ uwrap.ngroups = size;
+ memcpy(uwrap.groups, list, size * sizeof(gid_t));
+ }
}
rc = 0;
@@ -1108,14 +1163,16 @@ static int uwrap_setgroups(size_t size, const gid_t *list)
if (size == 0) {
for (id = uwrap.ids; id; id = id->next) {
- free(id->groups);
- id->groups = NULL;
+ SAFE_FREE(id->groups);
id->ngroups = 0;
+
}
+ SAFE_FREE(uwrap.groups);
+ uwrap.ngroups = 0;
} else if (size > 0) {
- for (id = uwrap.ids; id; id = id->next) {
- gid_t *tmp;
+ gid_t *tmp;
+ for (id = uwrap.ids; id; id = id->next) {
tmp = realloc(id->groups, sizeof(gid_t) * size);
if (tmp == NULL) {
errno = ENOMEM;
@@ -1126,6 +1183,18 @@ static int uwrap_setgroups(size_t size, const gid_t *list)
id->ngroups = size;
memcpy(id->groups, list, size * sizeof(gid_t));
}
+
+ tmp = realloc(uwrap.groups, sizeof(gid_t) * size);
+ if (tmp == NULL) {
+ /* How to return back id->groups? */
+ errno = ENOMEM;
+ goto out;
+ }
+
+ uwrap.groups = tmp;
+ uwrap.ngroups = size;
+ memcpy(uwrap.groups, list, size * sizeof(gid_t));
+
}
rc = 0;
@@ -1401,6 +1470,8 @@ void uwrap_destructor(void)
u = uwrap.ids;
}
+ SAFE_FREE(uwrap.groups);
+
if (uwrap.libc.handle != NULL) {
dlclose(uwrap.libc.handle);
}