From 6d360a15d93e88448a09bbd3e9daa7ca71920d74 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 11 Jun 2003 18:14:34 +0000 Subject: avoid races in getting high watermark (This used to be commit df0df941d84386a7de5c97149c6c06d01a8720d0) --- source3/sam/idmap_tdb.c | 38 ++++++++++++++++++++++++++++++++------ 1 file 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; -- cgit