From 4fc4efeb6afd9dcf2661df8a5b01ee1dc112d822 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 5 Jan 2022 11:40:46 -0800 Subject: [PATCH] s3: smbd: Create and use a common function for generating a fileid - create_clock_itime(). This first gets the clock_gettime_mono() value, converts to an NTTIME (as this is what is stored in the dos attribute EA), then mixes in 8 bits of randomness shifted up by 55 bits to cope with poor resolution clocks to avoid duplicate inodes. Using 8 bits of randomness on top of an NTTIME gives us around 114 years headroom. The top bit is then set to avoid collisions with system inode numbers. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14928 Signed-off-by: Jeremy Allison --- source3/include/proto.h | 1 + source3/lib/system.c | 43 +++++++++++++++++++++++++++++++++++++++++ source3/smbd/open.c | 6 +++--- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index 6154b1ab26d..dba728b3d86 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -175,6 +175,7 @@ void update_stat_ex_create_time(struct stat_ex *dst, struct timespec create_time void update_stat_ex_file_id(struct stat_ex *dst, uint64_t file_id); void update_stat_ex_from_saved_stat(struct stat_ex *dst, const struct stat_ex *src); +void create_clock_itime(struct stat_ex *dst); int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times); int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, diff --git a/source3/lib/system.c b/source3/lib/system.c index 671fc2760a0..9f62748a3f7 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -310,6 +310,49 @@ void init_stat_ex_from_stat (struct stat_ex *dst, dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_FILE_ID; } +/******************************************************************* + Create a clock-derived itime (imaginary) birthtime. +********************************************************************/ + +void create_clock_itime(struct stat_ex *dst) +{ + NTTIME tval; + struct timespec itime; + uint64_t mixin; + uint8_t rval; + + /* Start with the system clock. */ + clock_gettime_mono(&itime); + + /* Convert to NTTIME. */ + tval = unix_timespec_to_nt_time(itime); + + /* Generate a random byte. */ + generate_random_buffer((unsigned char *)&rval, 1); + mixin = rval; + + /* + * Shift up by 55 bits. This gives us 114 years + * of headroom. + */ + mixin <<= 55; + + /* + * Set the top bit to differentiate this + * from a system inode. + */ + mixin |= 0x8000000000000000LL; + + /* And OR into the nttime. */ + tval |= mixin; + + /* Convert back to a timespec. */ + itime = nt_time_to_full_timespec(tval); + + /* And set as a generated itime. */ + update_stat_ex_itime(dst, itime); +} + /******************************************************************* A stat() wrapper. ********************************************************************/ diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e3bb304292e..cf5c620fe21 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -4129,13 +4129,13 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, * If we created a file and it's not a stream, this is the point where * we set the itime (aka invented time) that get's stored in the DOS * attribute xattr. The value is going to be either what the filesystem - * provided or a copy of the creation date. + * provided or a generated itime value. * * Either way, we turn the itime into a File-ID, unless the filesystem * provided one (unlikely). */ if (info == FILE_WAS_CREATED && !is_named_stream(smb_fname)) { - smb_fname->st.st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_ITIME; + create_clock_itime(&smb_fname->st); if (lp_store_dos_attributes(SNUM(conn)) && smb_fname->st.st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID) @@ -4317,7 +4317,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, return NT_STATUS_NOT_A_DIRECTORY; } - smb_dname->st.st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_ITIME; + create_clock_itime(&smb_dname->st); if (lp_store_dos_attributes(SNUM(conn))) { if (smb_dname->st.st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID) -- 2.30.2