summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2000-06-11 06:24:54 +0000
committerAndrew Tridgell <tridge@samba.org>2000-06-11 06:24:54 +0000
commit0fb1dbe7fa0da5a1374e4a8cb9c3e922c9a08c8d (patch)
tree07b6abd39ec717219fee0dee47650088fdac333a
parent8843a6379d7c1cf59f0f3673cbc567b09994b7d2 (diff)
downloadsamba-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)
-rw-r--r--source3/include/includes.h12
-rw-r--r--source3/smbd/oplock_linux.c60
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);
}