diff options
author | Andrew Tridgell <tridge@samba.org> | 2000-06-11 06:24:54 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2000-06-11 06:24:54 +0000 |
commit | 0fb1dbe7fa0da5a1374e4a8cb9c3e922c9a08c8d (patch) | |
tree | 07b6abd39ec717219fee0dee47650088fdac333a /source3 | |
parent | 8843a6379d7c1cf59f0f3673cbc567b09994b7d2 (diff) | |
download | samba-0fb1dbe7fa0da5a1374e4a8cb9c3e922c9a08c8d.tar.gz samba-0fb1dbe7fa0da5a1374e4a8cb9c3e922c9a08c8d.tar.bz2 samba-0fb1dbe7fa0da5a1374e4a8cb9c3e922c9a08c8d.zip |
fixed Linux capabilities handling
I used a trick where CAP_LEASE isn't claimed until it is needed. This
means we avoid a system call per setreuid(), and never call capset()
unless a user tries to get a oplock on a file that they don't own
(This used to be commit afa98d511f70f455d599c3a36dd25e49fe74ac09)
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/includes.h | 12 | ||||
-rw-r--r-- | source3/smbd/oplock_linux.c | 60 |
2 files changed, 39 insertions, 33 deletions
diff --git a/source3/include/includes.h b/source3/include/includes.h index a30a8448ad..432fd09f0b 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -868,18 +868,6 @@ int setresgid(gid_t rgid, gid_t egid, gid_t sgid); #include <dlfcn.h> #endif -#if HAVE_KERNEL_OPLOCKS_LINUX -#ifndef F_SETLEASE -#define F_SETLEASE 1024 -#endif -#ifndef F_GETLEASE -#define F_GETLEASE 1025 -#endif -#ifndef CAP_LEASE -#define CAP_LEASE 28 -#endif -#endif - extern int DEBUGLEVEL; #endif /* _INCLUDES_H */ diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 73a14b3e88..ae0a72d0f6 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -31,18 +31,18 @@ static unsigned signals_received; static unsigned signals_processed; static int fd_pending; /* the fd of the current pending SIGIO */ -/* these can be removed when they are in libc */ -typedef struct __user_cap_header_struct { - uint32 version; - int pid; -} *cap_user_header_t; - -typedef struct __user_cap_data_struct { - uint32 effective; - uint32 permitted; - uint32 inheritable; -} *cap_user_data_t; +#ifndef F_SETLEASE +#define F_SETLEASE 1024 +#endif + +#ifndef F_GETLEASE +#define F_GETLEASE 1025 +#endif + +#ifndef CAP_LEASE +#define CAP_LEASE 28 +#endif /**************************************************************************** handle a SIGIO, incrementing the signals_received and blocking SIGIO @@ -55,19 +55,37 @@ static void sigio_handler(int signal, siginfo_t *info, void *unused) } /**************************************************************************** -try to gain the CAP_LEASE capability +try to gain a linux capability ****************************************************************************/ -static void set_lease_capability(void) +static void set_capability(unsigned capability) { - cap_user_header_t header; - cap_user_data_t data; - if (capget(header, data) == -1) { - DEBUG(3,("Unable to get kernel capabilities\n")); +#ifndef _LINUX_CAPABILITY_VERSION +#define _LINUX_CAPABILITY_VERSION 0x19980330 +#endif + /* these can be removed when they are in glibc headers */ + struct { + uint32 version; + int pid; + } header; + struct { + uint32 effective; + uint32 permitted; + uint32 inheritable; + } data; + + header.version = _LINUX_CAPABILITY_VERSION; + header.pid = 0; + + if (capget(&header, &data) == -1) { + DEBUG(3,("Unable to get kernel capabilities (%s)\n", strerror(errno))); return; } - data->effective |= (1<<CAP_LEASE); - if (capset(header, data) == -1) { - DEBUG(3,("Unable to set CAP_LEASE capability\n")); + + data.effective |= (1<<capability); + + if (capset(&header, &data) == -1) { + DEBUG(3,("Unable to set %d capability (%s)\n", + capability, strerror(errno))); } } @@ -81,7 +99,7 @@ static int linux_setlease(int fd, int leasetype) int ret; ret = fcntl(fd, F_SETLEASE, leasetype); if (ret == -1 && errno == EACCES) { - set_lease_capability(); + set_capability(CAP_LEASE); ret = fcntl(fd, F_SETLEASE, leasetype); } |