From 485787f0dfa64bbada7c971ec44f04a1095b4229 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 28 Jun 2012 13:41:19 -0700 Subject: [PATCH] Move back to using per-thread credentials on Linux. Fixes the glibc native AIO lost wakeup problem. See this post: https://lists.samba.org/archive/samba-technical/2012-June/085101.html for details. Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Fri Jun 29 03:57:45 CEST 2012 on sn-devel-104 --- lib/replace/libreplace.m4 | 4 +++- lib/replace/wscript | 4 ++-- lib/util/setid.c | 50 ++++++++++++++++++++++++++++++++------- source3/configure.in | 19 ++++++++++++++- source3/lib/util_sec.c | 18 +++++++------- source3/wscript | 12 +++++++++- tests/summary.c | 2 +- 7 files changed, 85 insertions(+), 24 deletions(-) diff --git a/lib/replace/libreplace.m4 b/lib/replace/libreplace.m4 index ad0f90411e7..d298b9242b5 100644 --- a/lib/replace/libreplace.m4 +++ b/lib/replace/libreplace.m4 @@ -124,8 +124,10 @@ AC_CHECK_HEADERS(sys/mount.h mntent.h) AC_CHECK_HEADERS(stropts.h) AC_CHECK_HEADERS(unix.h) AC_CHECK_HEADERS(malloc.h) +AC_CHECK_HEADERS(syscall.h) +AC_CHECK_HEADERS(sys/syscall.h) -AC_CHECK_FUNCS(seteuid setreuid setresuid setegid setregid setresgid) +AC_CHECK_FUNCS(syscall setuid seteuid setreuid setresuid setgid setegid setregid setresgid setgroups) AC_CHECK_FUNCS(chroot bzero strerror strerror_r memalign posix_memalign getpagesize) AC_CHECK_FUNCS(vsyslog setlinebuf mktime ftruncate chsize rename) AC_CHECK_FUNCS(waitpid wait4 strlcpy strlcat initgroups memmove strdup) diff --git a/lib/replace/wscript b/lib/replace/wscript index 68138cf8edb..157296b2983 100644 --- a/lib/replace/wscript +++ b/lib/replace/wscript @@ -163,7 +163,7 @@ def configure(conf): conf.CHECK_FUNCS('shl_load shl_unload shl_findsym') conf.CHECK_FUNCS('pipe strftime srandom random srand rand usleep setbuffer') - conf.CHECK_FUNCS('lstat getpgrp utime utimes seteuid setreuid setresuid setegid') + conf.CHECK_FUNCS('lstat getpgrp utime utimes setuid seteuid setreuid setresuid setgid setegid') conf.CHECK_FUNCS('setregid setresgid chroot strerror vsyslog setlinebuf mktime') conf.CHECK_FUNCS('ftruncate chsize rename waitpid wait4') conf.CHECK_FUNCS('initgroups pread pwrite strndup strcasestr') @@ -207,7 +207,7 @@ def configure(conf): conf.CHECK_FUNCS('if_nametoindex strerror_r') conf.CHECK_FUNCS('getdirentries getdents syslog') conf.CHECK_FUNCS('gai_strerror get_current_dir_name') - conf.CHECK_FUNCS('timegm getifaddrs freeifaddrs mmap setgroups setsid') + conf.CHECK_FUNCS('timegm getifaddrs freeifaddrs mmap setgroups syscall setsid') conf.CHECK_FUNCS('getgrent_r getgrgid_r getgrnam_r getgrouplist getpagesize') conf.CHECK_FUNCS('getpwent_r getpwnam_r getpwuid_r epoll_create') diff --git a/lib/util/setid.c b/lib/util/setid.c index 8b2efc076f3..66c06397ee6 100644 --- a/lib/util/setid.c +++ b/lib/util/setid.c @@ -70,10 +70,22 @@ int samba_setgroups(size_t setlen, const gid_t *gidset); #include "../lib/util/setid.h" +#if defined(USE_LINUX_THREAD_CREDENTIALS) +#if defined(HAVE_SYSCALL_H) +#include +#endif + +#if defined(HAVE_SYS_SYSCALL_H) +#include +#endif +#endif + /* All the setXX[ug]id functions and setgroups Samba uses. */ int samba_setresuid(uid_t ruid, uid_t euid, uid_t suid) { -#if defined(HAVE_SETRESUID) +#if defined(USE_LINUX_THREAD_CREDENTIALS) + return syscall(SYS_setresuid, ruid, euid, suid); +#elif defined(HAVE_SETRESUID) return setresuid(ruid, euid, suid); #else errno = ENOSYS; @@ -83,7 +95,9 @@ int samba_setresuid(uid_t ruid, uid_t euid, uid_t suid) int samba_setresgid(gid_t rgid, gid_t egid, gid_t sgid) { -#if defined(HAVE_SETRESGID) +#if defined(USE_LINUX_THREAD_CREDENTIALS) + return syscall(SYS_setresgid, rgid, egid, sgid); +#elif defined(HAVE_SETRESGID) return setresgid(rgid, egid, sgid); #else errno = ENOSYS; @@ -93,7 +107,9 @@ int samba_setresgid(gid_t rgid, gid_t egid, gid_t sgid) int samba_setreuid(uid_t ruid, uid_t euid) { -#if defined(HAVE_SETREUID) +#if defined(USE_LINUX_THREAD_CREDENTIALS) + return syscall(SYS_setreuid, ruid, euid); +#elif defined(HAVE_SETREUID) return setreuid(ruid, euid); #else errno = ENOSYS; @@ -103,7 +119,9 @@ int samba_setreuid(uid_t ruid, uid_t euid) int samba_setregid(gid_t rgid, gid_t egid) { -#if defined(HAVE_SETREGID) +#if defined(USE_LINUX_THREAD_CREDENTIALS) + return syscall(SYS_setregid, rgid, egid); +#elif defined(HAVE_SETREGID) return setregid(rgid, egid); #else errno = ENOSYS; @@ -113,7 +131,10 @@ int samba_setregid(gid_t rgid, gid_t egid) int samba_seteuid(uid_t euid) { -#if defined(HAVE_SETEUID) +#if defined(USE_LINUX_THREAD_CREDENTIALS) + /* seteuid is not a separate system call. */ + return syscall(SYS_setresuid, -1, euid, -1); +#elif defined(HAVE_SETEUID) return seteuid(euid); #else errno = ENOSYS; @@ -123,7 +144,10 @@ int samba_seteuid(uid_t euid) int samba_setegid(gid_t egid) { -#if defined(HAVE_SETEGID) +#if defined(USE_LINUX_THREAD_CREDENTIALS) + /* setegid is not a separate system call. */ + return syscall(SYS_setresgid, -1, egid, -1); +#elif defined(HAVE_SETEGID) return setegid(egid); #else errno = ENOSYS; @@ -133,7 +157,9 @@ int samba_setegid(gid_t egid) int samba_setuid(uid_t uid) { -#if defined(HAVE_SETUID) +#if defined(USE_LINUX_THREAD_CREDENTIALS) + return syscall(SYS_setuid, uid); +#elif defined(HAVE_SETUID) return setuid(uid); #else errno = ENOSYS; @@ -143,7 +169,9 @@ int samba_setuid(uid_t uid) int samba_setgid(gid_t gid) { -#if defined(HAVE_SETGID) +#if defined(USE_LINUX_THREAD_CREDENTIALS) + return syscall(SYS_setgid, gid); +#elif defined(HAVE_SETGID) return setgid(gid); #else errno = ENOSYS; @@ -156,6 +184,7 @@ int samba_setuidx(int flags, uid_t uid) #if defined(HAVE_SETUIDX) return setuidx(flags, uid); #else + /* USE_LINUX_THREAD_CREDENTIALS doesn't have this. */ errno = ENOSYS; return -1; #endif @@ -166,6 +195,7 @@ int samba_setgidx(int flags, gid_t gid) #if defined(HAVE_SETGIDX) return setgidx(flags, gid); #else + /* USE_LINUX_THREAD_CREDENTIALS doesn't have this. */ errno = ENOSYS; return -1; #endif @@ -173,7 +203,9 @@ int samba_setgidx(int flags, gid_t gid) int samba_setgroups(size_t setlen, const gid_t *gidset) { -#if defined(HAVE_SETGROUPS) +#if defined(USE_LINUX_THREAD_CREDENTIALS) + return syscall(SYS_setgroups, setlen, gidset); +#elif defined(HAVE_SETGROUPS) return setgroups(setlen, gidset); #else errno = ENOSYS; diff --git a/source3/configure.in b/source3/configure.in index 5df54cfff9d..ba376f08a99 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -953,7 +953,7 @@ AC_CHECK_FUNCS(setsid glob strpbrk crypt16 getauthuid) AC_CHECK_FUNCS(sigprocmask sigblock sigaction sigset innetgr setnetgrent getnetgrent endnetgrent) AC_CHECK_FUNCS(initgroups select rdchk getgrnam getgrent pathconf) AC_CHECK_FUNCS(getgrset) -AC_CHECK_FUNCS(setpriv setgidx setuidx setgroups sysconf) +AC_CHECK_FUNCS(setpriv setgidx setuidx setgroups syscall sysconf) AC_CHECK_FUNCS(atexit grantpt posix_fallocate) AC_CHECK_FUNCS(fallocate) AC_CHECK_FUNCS(fseeko setluid getpwanam) @@ -2766,6 +2766,23 @@ AC_CHECK_FUNCS(getpagesize) # look for a method of setting the effective uid seteuid=no; +case "$host_os" in +*linux*) +if test $seteuid = no; then +AC_CACHE_CHECK([for Linux thread-specific credentials],samba_cv_USE_LINUX_THREAD_CREDENTIALS,[ +AC_TRY_RUN([ +#define AUTOCONF_TEST 1 +#define USE_LINUX_THREAD_CREDENTIALS 1 +#include "confdefs.h" +#include "${srcdir-.}/lib/util_sec.c"], + samba_cv_USE_LINUX_THREAD_CREDENTIALS=yes,samba_cv_USE_LINUX_THREAD_CREDENTIALS=no,samba_cv_USE_LINUX_THREAD_CREDENTIALS=cross)]) +if test x"$samba_cv_USE_LINUX_THREAD_CREDENTIALS" = x"yes"; then + seteuid=yes;AC_DEFINE(USE_SETREUID,1,[Whether we can use Linux thread-specific credentials]) +fi +fi +;; +esac + if test $seteuid = no; then AC_CACHE_CHECK([for setreuid],samba_cv_USE_SETREUID,[ AC_TRY_RUN([ diff --git a/source3/lib/util_sec.c b/source3/lib/util_sec.c index bbb75dbbd4a..cee11d9f960 100644 --- a/source3/lib/util_sec.c +++ b/source3/lib/util_sec.c @@ -134,7 +134,7 @@ static void assert_gid(gid_t rgid, gid_t egid) ****************************************************************************/ void gain_root_privilege(void) { -#if USE_SETRESUID +#if defined(USE_SETRESUID) || defined(USE_LINUX_THREAD_CREDENTIALS) samba_setresuid(0,0,0); #endif @@ -164,7 +164,7 @@ void gain_root_privilege(void) ****************************************************************************/ void gain_root_group_privilege(void) { -#if USE_SETRESUID +#if defined(USE_SETRESUID) || defined(USE_LINUX_THREAD_CREDENTIALS) samba_setresgid(0,0,0); #endif @@ -201,7 +201,7 @@ void gain_root_group_privilege(void) ****************************************************************************/ void set_effective_uid(uid_t uid) { -#if USE_SETRESUID +#if defined(USE_SETRESUID) || defined(USE_LINUX_THREAD_CREDENTIALS) /* Set the effective as well as the real uid. */ if (samba_setresuid(uid,uid,-1) == -1) { if (errno == EAGAIN) { @@ -233,7 +233,7 @@ void set_effective_uid(uid_t uid) ****************************************************************************/ void set_effective_gid(gid_t gid) { -#if USE_SETRESUID +#if defined(USE_SETRESUID) || defined(USE_LINUX_THREAD_CREDENTIALS) samba_setresgid(-1,gid,-1); #endif @@ -272,7 +272,7 @@ void save_re_uid(void) void restore_re_uid_fromroot(void) { -#if USE_SETRESUID +#if defined(USE_SETRESUID) || defined(USE_LINUX_THREAD_CREDENTIALS) samba_setresuid(saved_ruid, saved_euid, -1); #elif USE_SETREUID samba_setreuid(saved_ruid, -1); @@ -311,7 +311,7 @@ void save_re_gid(void) ****************************************************************************/ void restore_re_gid(void) { -#if USE_SETRESUID +#if defined(USE_SETRESUID) || defined(USE_LINUX_THREAD_CREDENTIALS) samba_setresgid(saved_rgid, saved_egid, -1); #elif USE_SETREUID samba_setregid(saved_rgid, -1); @@ -339,7 +339,7 @@ int set_re_uid(void) { uid_t uid = geteuid(); -#if USE_SETRESUID +#if defined(USE_SETRESUID) || defined(USE_LINUX_THREAD_CREDENTIALS) samba_setresuid(geteuid(), -1, -1); #endif @@ -378,7 +378,7 @@ void become_user_permanently(uid_t uid, gid_t gid) gain_root_privilege(); gain_root_group_privilege(); -#if USE_SETRESUID +#if defined(USE_SETRESUID) || defined(USE_LINUX_THREAD_CREDENTIALS) samba_setresgid(gid,gid,gid); samba_setgid(gid); samba_setresuid(uid,uid,uid); @@ -422,7 +422,7 @@ static int have_syscall(void) { errno = 0; -#if USE_SETRESUID +#if defined(USE_SETRESUID) || defined(USE_LINUX_THREAD_CREDENTIALS) samba_setresuid(-1,-1,-1); #endif diff --git a/source3/wscript b/source3/wscript index 5b21c3bf31c..449bf20e057 100755 --- a/source3/wscript +++ b/source3/wscript @@ -80,7 +80,7 @@ def configure(conf): conf.CHECK_FUNCS('setsid glob strpbrk crypt16 getauthuid') conf.CHECK_FUNCS('sigprocmask sigblock sigaction sigset innetgr') conf.CHECK_FUNCS('initgroups select poll rdchk getgrnam getgrent pathconf') - conf.CHECK_FUNCS('setpriv setgidx setuidx setgroups sysconf') + conf.CHECK_FUNCS('setpriv setgidx setuidx setgroups syscall sysconf') conf.CHECK_FUNCS('atexit grantpt fallocate posix_fallocate') conf.CHECK_FUNCS('fseeko setluid') conf.CHECK_FUNCS('getpwnam', headers='sys/types.h pwd.h') @@ -729,6 +729,16 @@ int i; i = PAM_RADIO_TYPE; conf.DEFINE('WITH_PAM_MODULES', 1) seteuid = False + if not seteuid: + seteuid = conf.CHECK_CODE(''' + #define AUTOCONF_TEST 1 + #define USE_LINUX_THREAD_CREDENTIALS 1 + #include "./lib/util_sec.c" + ''', + 'USE_LINUX_THREAD_CREDENTIALS', + addmain=False, + execute=True, + msg="Checking whether we can use Linux thread-specific credentials") if not seteuid: seteuid = conf.CHECK_CODE(''' #define AUTOCONF_TEST 1 diff --git a/tests/summary.c b/tests/summary.c index a019fbfb2e0..bd0c1624306 100644 --- a/tests/summary.c +++ b/tests/summary.c @@ -13,7 +13,7 @@ main() printf("WARNING: No automated network interface determination\n"); #endif -#if !(defined(USE_SETEUID) || defined(USE_SETREUID) || defined(USE_SETRESUID) || defined(USE_SETUIDX)) +#if !(defined(USE_SETEUID) || defined(USE_SETREUID) || defined(USE_SETRESUID) || defined(USE_SETUIDX) || defined(USE_LINUX_THREAD_CREDENTIALS)) printf("ERROR: no seteuid method available\n"); exit(1); #endif -- 2.34.1