Skip to content

Commit

Permalink
s3: smbd: Create and use a common function for generating a fileid - …
Browse files Browse the repository at this point in the history
…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. We can now guarentee returning a itime-based
fileid in a normal share (storing dos attributes in an EA).

Remove knownfail.d/fileid-unique

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

Signed-off-by: Jeremy Allison <[email protected]>
Reviewed-by: Christof Schmitt <[email protected]>

Autobuild-User(master): Jeremy Allison <[email protected]>
Autobuild-Date(master): Sat Jan  8 06:35:22 UTC 2022 on sn-devel-184
  • Loading branch information
jrasamba committed Jan 8, 2022
1 parent 29d69c2 commit 23fbf0b
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 5 deletions.
2 changes: 0 additions & 2 deletions selftest/knownfail.d/fileid-unique

This file was deleted.

1 change: 1 addition & 0 deletions source3/include/proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
52 changes: 52 additions & 0 deletions source3/lib/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,58 @@ 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) time. Used to generate
the fileid.
********************************************************************/

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);

/*
* In case the system clock is poor granularity
* (happens on VM or docker images) then mix in
* 8 bits of randomness.
*/
generate_random_buffer((unsigned char *)&rval, 1);
mixin = rval;

/*
* Shift up by 55 bits. This gives us approx 114 years
* of headroom.
*/
mixin <<= 55;

/* And OR into the nttime. */
tval |= mixin;

/*
* Convert to a unix timespec, ignoring any
* constraints on seconds being higher than
* TIME_T_MAX or lower than TIME_T_MIN. These
* are only needed to allow unix display time functions
* to work correctly, and this is being used to
* generate a fileid. All we care about is the
* NTTIME being valid across all NTTIME ranges
* (which we carefully ensured above).
*/

itime = nt_time_to_unix_timespec_raw(tval);

/* And set as a generated itime. */
update_stat_ex_itime(dst, itime);
}

/*******************************************************************
A stat() wrapper.
********************************************************************/
Expand Down
6 changes: 3 additions & 3 deletions source3/smbd/open.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 23fbf0b

Please sign in to comment.