+static int uwrap_setgid_args(gid_t gid,
+ gid_t *new_rgid,
+ gid_t *new_egid,
+ gid_t *new_sgid)
+{
+ struct uwrap_thread *id = uwrap_tls_id;
+
+ UWRAP_LOG(UWRAP_LOG_TRACE,
+ "gid %d -> %d",
+ id->rgid, gid);
+
+ if (gid == (gid_t)-1) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (id->euid == 0) {
+ *new_sgid = *new_rgid = gid;
+ } else if (gid != id->rgid &&
+ gid != id->sgid) {
+ errno = EPERM;
+ return -1;
+ }
+
+ *new_egid = gid;
+
+ return 0;
+}
+
+static int uwrap_setgid_thread(gid_t gid)
+{
+ gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
+ int rc;
+
+ rc = uwrap_setgid_args(gid, &new_rgid, &new_egid, &new_sgid);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return uwrap_setresgid_thread(new_rgid, new_egid, new_sgid);
+}
+
+static int uwrap_setgid(gid_t gid)
+{
+ gid_t new_rgid = -1, new_egid = -1, new_sgid = -1;
+ int rc;
+
+ rc = uwrap_setgid_args(gid, &new_rgid, &new_egid, &new_sgid);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return uwrap_setresgid(new_rgid, new_egid, new_sgid);
+}
+