diff options
author | Andrew Tridgell <tridge@samba.org> | 1997-10-29 01:59:54 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 1997-10-29 01:59:54 +0000 |
commit | 4fd96fddd2b13f60c4eb13263bac2a62a2795dcc (patch) | |
tree | 93c269b25da65f647dcca036b8d3682021142d68 /source3/locking/shmem_sysv.c | |
parent | b925b3d20c8e85c7b65a0ad599248443ae12905c (diff) | |
download | samba-4fd96fddd2b13f60c4eb13263bac2a62a2795dcc.tar.gz samba-4fd96fddd2b13f60c4eb13263bac2a62a2795dcc.tar.bz2 samba-4fd96fddd2b13f60c4eb13263bac2a62a2795dcc.zip |
clean up the hash entry code a bit. Got rid of lp_shmem_hash_size()
and made it private to the 2 shmem implementations. Added new
shmops->hash_size() function.
Added code to handle the IPC system limits by looping decreasing the
size of the resources (semaphores and shared memory) that we request
until we get under the system limits, which can be quite low on some
systems!
Added checks that the creator of the IPC objects is root. Otherwise we
would be open to a security hole where someone pre-creates the shared
memory segment and attaches.
(This used to be commit 6b6f624b63137d4750200e8cb4961b1402513632)
Diffstat (limited to 'source3/locking/shmem_sysv.c')
-rw-r--r-- | source3/locking/shmem_sysv.c | 70 |
1 files changed, 55 insertions, 15 deletions
diff --git a/source3/locking/shmem_sysv.c b/source3/locking/shmem_sysv.c index 36d0cca27f..e3f40418d9 100644 --- a/source3/locking/shmem_sysv.c +++ b/source3/locking/shmem_sysv.c @@ -39,6 +39,14 @@ extern int DEBUGLEVEL; #define IPC_PERMS 0644 #endif +#ifdef SEMMSL +#define SHMEM_HASH_SIZE (SEMMSL-1) +#else +#define SHMEM_HASH_SIZE 63 +#endif + +#define MIN_SHM_SIZE 10240 + static int shm_id; static int sem_id; static int shm_size; @@ -487,6 +495,16 @@ static BOOL shm_get_usage(int *bytes_free, return True; } + +/******************************************************************* +hash a number into a hash_entry + ******************************************************************/ +static unsigned shm_hash_size(void) +{ + return hash_size; +} + + static struct shmem_ops shmops = { shm_close, shm_alloc, @@ -497,12 +515,13 @@ static struct shmem_ops shmops = { shm_lock_hash_entry, shm_unlock_hash_entry, shm_get_usage, + shm_hash_size, }; /******************************************************************* open the shared memory ******************************************************************/ -struct shmem_ops *sysv_shm_open(int size, int ronly) +struct shmem_ops *sysv_shm_open(int ronly) { BOOL created_new = False; BOOL other_processes; @@ -513,17 +532,23 @@ struct shmem_ops *sysv_shm_open(int size, int ronly) read_only = ronly; - shm_size = size; + shm_size = lp_shmem_size(); - DEBUG(4,("Trying sysv shmem open of size %d\n", size)); + DEBUG(4,("Trying sysv shmem open of size %d\n", shm_size)); /* first the semaphore */ sem_id = semget(SEMAPHORE_KEY, 0, 0); if (sem_id == -1) { if (read_only) return NULL; - sem_id = semget(SEMAPHORE_KEY, lp_shmem_hash_size()+1, - IPC_CREAT | IPC_EXCL | IPC_PERMS); + hash_size = SHMEM_HASH_SIZE; + + while (hash_size > 1) { + sem_id = semget(SEMAPHORE_KEY, hash_size+1, + IPC_CREAT | IPC_EXCL | IPC_PERMS); + if (sem_id != -1 || errno != EINVAL) break; + hash_size--; + } if (sem_id == -1) { DEBUG(0,("Can't create or use semaphore %s\n", @@ -532,7 +557,7 @@ struct shmem_ops *sysv_shm_open(int size, int ronly) if (sem_id != -1) { su.val = 1; - for (i=0;i<lp_shmem_hash_size()+1;i++) { + for (i=0;i<hash_size+1;i++) { if (semctl(sem_id, i, SETVAL, su) != 0) { DEBUG(1,("Failed to init semaphore %d\n", i)); } @@ -552,10 +577,16 @@ struct shmem_ops *sysv_shm_open(int size, int ronly) if (semctl(sem_id, 0, IPC_STAT, su) != 0) { DEBUG(0,("ERROR shm_open : can't IPC_STAT\n")); } - hash_size = sem_ds.sem_nsems; - if (hash_size != lp_shmem_hash_size()+1) { - DEBUG(0,("WARNING: nsems=%d\n", hash_size)); + hash_size = sem_ds.sem_nsems-1; + + if (!read_only) { + if (sem_ds.sem_perm.cuid != 0 || sem_ds.sem_perm.cgid != 0) { + DEBUG(0,("ERROR: root did not create the semaphore\n")); + return NULL; + } } + + if (!global_lock()) return NULL; @@ -566,7 +597,12 @@ struct shmem_ops *sysv_shm_open(int size, int ronly) /* if that failed then create one */ if (shm_id == -1) { if (read_only) return NULL; - shm_id = shmget(SHMEM_KEY, shm_size, IPC_CREAT | IPC_EXCL); + while (shm_size > MIN_SHM_SIZE) { + shm_id = shmget(SHMEM_KEY, shm_size, + IPC_CREAT | IPC_EXCL | IPC_PERMS); + if (shm_id != -1 || errno != EINVAL) break; + shm_size *= 0.9; + } created_new = (shm_id != -1); } @@ -592,19 +628,23 @@ struct shmem_ops *sysv_shm_open(int size, int ronly) DEBUG(0,("ERROR shm_open : can't IPC_STAT\n")); } - /* set the permissions */ if (!read_only) { - shm_ds.shm_perm.mode = IPC_PERMS; - shmctl(shm_id, IPC_SET, &shm_ds); + if (shm_ds.shm_perm.cuid != 0 || shm_ds.shm_perm.cgid != 0) { + DEBUG(0,("ERROR: root did not create the shmem\n")); + global_unlock(); + return NULL; + } } + shm_size = shm_ds.shm_segsz; + other_processes = (shm_ds.shm_nattch > 1); if (!read_only && !other_processes) { memset((char *)shm_header_p, 0, shm_size); shm_initialize(shm_size); - shm_create_hash_table(lp_shmem_hash_size()); - DEBUG(1,("Initialised IPC area of size %d\n", shm_size)); + shm_create_hash_table(hash_size); + DEBUG(3,("Initialised IPC area of size %d\n", shm_size)); } else if (!shm_validate_header(shm_size)) { /* existing file is corrupt, samba admin should remove it by hand */ |