diff options
author | Andreas Schneider <asn@samba.org> | 2015-10-30 13:40:45 +0100 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2015-11-05 09:23:16 +0100 |
commit | 6e30b2e63854c9c7067f176c84468aece17641f7 (patch) | |
tree | d237afe9cd73e45fff605d7dba9c8cb32b7b1f1c /lib | |
parent | be0cb8ab4d68680f0c4b1ec1db994781056d61b2 (diff) | |
download | samba-6e30b2e63854c9c7067f176c84468aece17641f7.tar.gz |
uwrap: Allow setgid calls only for privileged users
Signed-off-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.c | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/lib/uid_wrapper/uid_wrapper.c b/lib/uid_wrapper/uid_wrapper.c index fe05f0ac258..d720e533e4e 100644 --- a/lib/uid_wrapper/uid_wrapper.c +++ b/lib/uid_wrapper/uid_wrapper.c @@ -1467,6 +1467,61 @@ static int uwrap_setregid(gid_t rgid, gid_t egid) } #endif +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); +} + /* * SETUID */ @@ -1600,7 +1655,7 @@ int setgid(gid_t gid) } uwrap_init(); - return uwrap_setresgid(gid, -1, -1); + return uwrap_setgid(gid); } #ifdef HAVE_SETEGID @@ -1850,7 +1905,7 @@ static long int uwrap_syscall (long int sysno, va_list vp) { gid_t gid = (gid_t) va_arg(vp, gid_t); - rc = uwrap_setresgid_thread(gid, -1, -1); + rc = uwrap_setgid_thread(gid); } break; case SYS_setregid: |