summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>1997-10-29 02:59:22 +0000
committerAndrew Tridgell <tridge@samba.org>1997-10-29 02:59:22 +0000
commit2bbd8d2cbc5cf1901859a181bc9ec29822995e51 (patch)
tree938447c1250559bf4c8a3468b03e721449f5db73
parent68ad7b91999216e5721207b5a79c3a66be7cf420 (diff)
downloadsamba-2bbd8d2cbc5cf1901859a181bc9ec29822995e51.tar.gz
damn. We need root privilages to do semaphore operations even if we
have done the semget() as root. The problem is that become_root() and unbecome_root() are so slow! I've provided two options. The default is to set the semaphores (but _not_ the shared memory) world writeable so that a become_root() isn't needed. Otherwise you can define SECURE_SEMAPHORES and pay the performance penalty.
-rw-r--r--source/locking/shmem_sysv.c71
-rw-r--r--source/utils/status.c1
2 files changed, 44 insertions, 28 deletions
diff --git a/source/locking/shmem_sysv.c b/source/locking/shmem_sysv.c
index e3f40418d97..8832902820a 100644
--- a/source/locking/shmem_sysv.c
+++ b/source/locking/shmem_sysv.c
@@ -39,6 +39,14 @@ extern int DEBUGLEVEL;
#define IPC_PERMS 0644
#endif
+#ifdef SECURE_SEMAPHORES
+/* secure semaphores are slow because we have to do a become_root()
+ on every call! */
+#define SEMAPHORE_PERMS IPC_PERMS
+#else
+#define SEMAPHORE_PERMS 0666
+#endif
+
#ifdef SEMMSL
#define SHMEM_HASH_SIZE (SEMMSL-1)
#else
@@ -92,45 +100,49 @@ static BOOL shm_initialize_called = False;
static int read_only;
-static BOOL sem_lock(int i)
+static BOOL sem_change(int i, int op)
{
+#ifdef SECURE_SEMAPHORES
+ extern struct current_user current_user;
+ int became_root=0;
+#endif
struct sembuf sb;
+ int ret;
+
if (read_only) return True;
-
- sb.sem_num = i;
- sb.sem_op = -1;
- sb.sem_flg = SEM_UNDO;
- if (semop(sem_id, &sb, 1) != 0) {
- DEBUG(0,("ERROR: IPC lock failed on semaphore %d\n", i));
- return False;
+#ifdef SECURE_SEMAPHORES
+ if (current_user.uid != 0) {
+ become_root(0);
+ became_root = 1;
}
-
- return True;
-}
-
-static BOOL sem_unlock(int i)
-{
- struct sembuf sb;
- if (read_only) return True;
+#endif
sb.sem_num = i;
- sb.sem_op = 1;
+ sb.sem_op = op;
sb.sem_flg = SEM_UNDO;
- if (semop(sem_id, &sb, 1) != 0) {
- DEBUG(0,("ERROR: IPC unlock failed on semaphore %d\n", i));
- return False;
+ ret = semop(sem_id, &sb, 1);
+
+ if (ret != 0) {
+ DEBUG(0,("ERROR: sem_change(%d,%d) failed (%s)\n",
+ i, op, strerror(errno)));
}
- return True;
+#ifdef SECURE_SEMAPHORES
+ if (became_root) {
+ unbecome_root(0);
+ }
+#endif
+
+ return ret == 0;
}
static BOOL global_lock(void)
{
global_lock_count++;
if (global_lock_count == 1)
- return sem_lock(0);
+ return sem_change(0, -1);
return True;
}
@@ -138,7 +150,7 @@ static BOOL global_unlock(void)
{
global_lock_count--;
if (global_lock_count == 0)
- return sem_unlock(0);
+ return sem_change(0, 1);
return True;
}
@@ -461,8 +473,7 @@ static int shm_get_userdef_off(void)
******************************************************************/
static BOOL shm_lock_hash_entry(unsigned int entry)
{
- DEBUG(0,("hash lock %d\n", entry));
- return sem_lock(entry+1);
+ return sem_change(entry+1, -1);
}
/*******************************************************************
@@ -470,8 +481,7 @@ static BOOL shm_lock_hash_entry(unsigned int entry)
******************************************************************/
static BOOL shm_unlock_hash_entry(unsigned int entry)
{
- DEBUG(0,("hash unlock %d\n", entry));
- return sem_unlock(entry+1);
+ return sem_change(entry+1, 1);
}
@@ -545,7 +555,7 @@ struct shmem_ops *sysv_shm_open(int ronly)
while (hash_size > 1) {
sem_id = semget(SEMAPHORE_KEY, hash_size+1,
- IPC_CREAT | IPC_EXCL | IPC_PERMS);
+ IPC_CREAT|IPC_EXCL| SEMAPHORE_PERMS);
if (sem_id != -1 || errno != EINVAL) break;
hash_size--;
}
@@ -584,6 +594,11 @@ struct shmem_ops *sysv_shm_open(int ronly)
DEBUG(0,("ERROR: root did not create the semaphore\n"));
return NULL;
}
+
+ sem_ds.sem_perm.mode = SEMAPHORE_PERMS;
+ if (semctl(sem_id, 0, IPC_SET, su) != 0) {
+ DEBUG(0,("ERROR shm_open : can't IPC_SET\n"));
+ }
}
diff --git a/source/utils/status.c b/source/utils/status.c
index f124d79939c..1a05f2b1afe 100644
--- a/source/utils/status.c
+++ b/source/utils/status.c
@@ -58,6 +58,7 @@ unsigned int Ucrit_IsActive = 0; /* added by OH */
void unbecome_root(BOOL restore_dir) {}
connection_struct Connections[MAX_CONNECTIONS];
files_struct Files[MAX_OPEN_FILES];
+struct current_user current_user;
static void print_share_mode(share_mode_entry *e, char *fname)