diff options
author | Simo Sorce <idra@samba.org> | 2003-06-11 18:14:34 +0000 |
---|---|---|
committer | Simo Sorce <idra@samba.org> | 2003-06-11 18:14:34 +0000 |
commit | 6d360a15d93e88448a09bbd3e9daa7ca71920d74 (patch) | |
tree | f6db32df579208d8d30df52a0e2115f6f7f4b0e4 /source3/sam | |
parent | a7e1bbbd06a4a7c2cd6ff4fed8bdc8455b9a75d6 (diff) | |
download | samba-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.c | 38 |
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; |