diff options
author | Jeremy Allison <jra@samba.org> | 2010-01-26 16:51:57 -0800 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2010-01-26 16:51:57 -0800 |
commit | 899bd0005f56dcc1e95c3988d41ab3f628bb15db (patch) | |
tree | 633dfaaf9f240a6571c49fc4da2fc7a2f0e5def9 /source3/lib | |
parent | 2dd301e5cd6ff97943c4bf9c7cd9b820d6193b45 (diff) | |
download | samba-899bd0005f56dcc1e95c3988d41ab3f628bb15db.tar.gz samba-899bd0005f56dcc1e95c3988d41ab3f628bb15db.tar.bz2 samba-899bd0005f56dcc1e95c3988d41ab3f628bb15db.zip |
Fix bug #7067 - Linux asynchronous IO (aio) can cause smbd to fail to respond to a read or write.
Only works on Linux kernels 2.6.26 and above. Grants CAP_KILL capability
to allow Linux threads under different euids to send signals to each other.
Jeremy.
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/system.c | 65 |
1 files changed, 61 insertions, 4 deletions
diff --git a/source3/lib/system.c b/source3/lib/system.c index a58d9037a7..9c1da3a78b 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -883,6 +883,11 @@ char *sys_getwd(char *s) #if defined(HAVE_POSIX_CAPABILITIES) +/* This define hasn't made it into the glibc capabilities header yet. */ +#ifndef SECURE_NO_SETUID_FIXUP +#define SECURE_NO_SETUID_FIXUP 2 +#endif + /************************************************************************** Try and abstract process capabilities (for systems that have them). ****************************************************************************/ @@ -913,6 +918,32 @@ static bool set_process_capability(enum smbd_capability capability, } #endif +#if defined(HAVE_PRCTL) && defined(PR_SET_SECUREBITS) && defined(SECURE_NO_SETUID_FIXUP) + /* New way of setting capabilities as "sticky". */ + + /* + * Use PR_SET_SECUREBITS to prevent setresuid() + * atomically dropping effective capabilities on + * uid change. Only available in Linux kernels + * 2.6.26 and above. + * + * See here: + * http://www.kernel.org/doc/man-pages/online/pages/man7/capabilities.7.html + * for details. + * + * Specifically the CAP_KILL capability we need + * to allow Linux threads under different euids + * to send signals to each other. + */ + + if (prctl(PR_SET_SECUREBITS, 1 << SECURE_NO_SETUID_FIXUP)) { + DEBUG(0,("set_process_capability: " + "prctl PR_SET_SECUREBITS failed with error %s\n", + strerror(errno) )); + return false; + } +#endif + cap = cap_get_proc(); if (cap == NULL) { DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n", @@ -941,6 +972,11 @@ static bool set_process_capability(enum smbd_capability capability, cap_vals[num_cap_vals++] = CAP_LEASE; #endif break; + case KILL_CAPABILITY: +#ifdef CAP_KILL + cap_vals[num_cap_vals++] = CAP_KILL; +#endif + break; } SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals)); @@ -950,16 +986,37 @@ static bool set_process_capability(enum smbd_capability capability, return True; } - cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals, - enable ? CAP_SET : CAP_CLEAR); + /* + * Ensure the capability is effective. We assume that as a root + * process it's always permitted. + */ + + if (cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals, + enable ? CAP_SET : CAP_CLEAR) == -1) { + DEBUG(0, ("set_process_capability: cap_set_flag effective " + "failed (%d): %s\n", + (int)capability, + strerror(errno))); + cap_free(cap); + return false; + } /* We never want to pass capabilities down to our children, so make * sure they are not inherited. */ - cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR); + if (cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, + cap_vals, CAP_CLEAR) == -1) { + DEBUG(0, ("set_process_capability: cap_set_flag inheritable " + "failed (%d): %s\n", + (int)capability, + strerror(errno))); + cap_free(cap); + return false; + } if (cap_set_proc(cap) == -1) { - DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n", + DEBUG(0, ("set_process_capability: cap_set_flag (%d) failed: %s\n", + (int)capability, strerror(errno))); cap_free(cap); return False; |