summaryrefslogtreecommitdiff
path: root/source3/sam
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2003-06-11 18:14:34 +0000
committerSimo Sorce <idra@samba.org>2003-06-11 18:14:34 +0000
commit6d360a15d93e88448a09bbd3e9daa7ca71920d74 (patch)
treef6db32df579208d8d30df52a0e2115f6f7f4b0e4 /source3/sam
parenta7e1bbbd06a4a7c2cd6ff4fed8bdc8455b9a75d6 (diff)
downloadsamba-6d360a15d93e88448a09bbd3e9daa7ca71920d74.tar.gz
samba-6d360a15d93e88448a09bbd3e9daa7ca71920d74.tar.bz2
samba-6d360a15d93e88448a09bbd3e9daa7ca71920d74.zip
avoid races in getting high watermark
(This used to be commit df0df941d84386a7de5c97149c6c06d01a8720d0)
Diffstat (limited to 'source3/sam')
-rw-r--r--source3/sam/idmap_tdb.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/source3/sam/idmap_tdb.c b/source3/sam/idmap_tdb.c
index 278269e819..209f9066e0 100644
--- a/source3/sam/idmap_tdb.c
+++ b/source3/sam/idmap_tdb.c
@@ -48,6 +48,7 @@ static struct idmap_state {
/* Allocate either a user or group id from the pool */
static NTSTATUS db_allocate_id(unid_t *id, int id_type)
{
+ BOOL ret;
int hwm;
if (!id) return NT_STATUS_INVALID_PARAMETER;
@@ -59,30 +60,55 @@ static NTSTATUS db_allocate_id(unid_t *id, int id_type)
return NT_STATUS_INTERNAL_DB_ERROR;
}
+ /* check it is in the range */
if (hwm > idmap_state.uid_high) {
DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %u)\n", idmap_state.uid_high));
return NT_STATUS_UNSUCCESSFUL;
}
- (*id).uid = hwm++;
+ /* fetch a new id and increment it */
+ ret = tdb_change_uint32_atomic(idmap_tdb, HWM_USER, &hwm, 1);
+ if (!ret) {
+ DEBUG(0, ("idmap_tdb: Fatal error while fetching a new id\n!"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* recheck it is in the range */
+ if (hwm > idmap_state.uid_high) {
+ DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %u)\n", idmap_state.uid_high));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ (*id).uid = hwm;
- /* Store new high water mark */
- tdb_store_int32(idmap_tdb, HWM_USER, hwm);
break;
case ID_GROUPID:
if ((hwm = tdb_fetch_int32(idmap_tdb, HWM_GROUP)) == -1) {
return NT_STATUS_INTERNAL_DB_ERROR;
}
+ /* check it is in the range */
if (hwm > idmap_state.gid_high) {
DEBUG(0, ("idmap Fatal Error: GID range full!! (max: %u)\n", idmap_state.gid_high));
return NT_STATUS_UNSUCCESSFUL;
}
- (*id).gid = hwm++;
+ /* fetch a new id and increment it */
+ ret = tdb_change_uint32_atomic(idmap_tdb, HWM_USER, &hwm, 1);
+
+ if (!ret) {
+ DEBUG(0, ("idmap_tdb: Fatal error while fetching a new id\n!"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* recheck it is in the range */
+ if (hwm > idmap_state.uid_high) {
+ DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %u)\n", idmap_state.uid_high));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ (*id).gid = hwm;
- /* Store new high water mark */
- tdb_store_int32(idmap_tdb, HWM_GROUP, hwm);
break;
default:
return NT_STATUS_INVALID_PARAMETER;