]> git.ipfire.org Git - thirdparty/samba.git/commit
s3:smbd: let mkdir_internal() work more atomically using a temporary name
authorStefan Metzmacher <metze@samba.org>
Thu, 1 Aug 2024 12:37:55 +0000 (14:37 +0200)
committerStefan Metzmacher <metze@samba.org>
Wed, 21 Aug 2024 08:02:30 +0000 (08:02 +0000)
commit7baeeece2dd563d404352e5f3e34661d1cbc2b03
treea3a966d42b55192b65e1958911f61cc68a79b406
parent460e280d3af70c38b04219e414ea3b6439caaed6
s3:smbd: let mkdir_internal() work more atomically using a temporary name

Currently we do this in mkdir_internal():

mkdirat(client_name);
if (EEXIST) {
   return EEXIST;
}
prepare_acls(client_name);

Note 'prepare_acls()' is a placeholder for the complex steps
it is doing to prepare the directory. During these steps
we have the problem that other clients already see
the directory and are able to create files or subdirectories
in it and these may not inherit the correct acls as
the their parent directory is not created completely.

I think I found a good strategie even without relying on
renameat2(RENAME_NOREPLACE).

We would do this instead:

tmp_name = ".::TMPNAME:D:$PID:client_name"
mkdirat(tmp_name, mode=client_mode);
prepare_acls(tmp_name);
mkdirat(client_name, mode=0);
if (EEXIST) {
   unlinkat(tmp_name);
   return EEXIST;
}
renameat(tmp_name, client_name);

So instead of having a long windows during prepare_acls,
we just have a short window between mkdirat(client_name, mode=0)
and renameat(tmp_name, client_name);
And in that short window the directory with the client_name
has a mode of 0, so it's not possible for other clients
to create files or subdirs in it.

As the mkdirat(client_name, mode=0) still catches
EEXIST the race where two clients try to create
the same client_name is closed as before,
so we don't need any other protection.

Following patches will make use of renameat2(RENAME_NOREPLACE),
but this already a very good improvement.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
selftest/knownfail.d/samba3.smb2.create.mkdir-visible [deleted file]
source3/smbd/dir.c
source3/smbd/globals.h
source3/smbd/open.c
source3/smbd/proto.h
source3/smbd/smb2_reply.c