fs: cifs: Initialize filesystem timestamp ranges
Fill in the appropriate limits to avoid inconsistencies in the vfs cached inode times when timestamps are outside the permitted range. Also fixed cnvrtDosUnixTm calculations to avoid int overflow while computing maximum date. References: http://cifs.com/ https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-cifs/d416ff7c-c536-406e-a951-4f04b2fd1d2b Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com> Acked-by: Jeff Layton <jlayton@kernel.org> Cc: sfrench@samba.org Cc: linux-cifs@vger.kernel.org
This commit is contained in:
parent
1fcb79c1b2
commit
cb7a69e605
|
@ -56,6 +56,15 @@
|
|||
#include "dfs_cache.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* DOS dates from 1980/1/1 through 2107/12/31
|
||||
* Protocol specifications indicate the range should be to 119, which
|
||||
* limits maximum year to 2099. But this range has not been checked.
|
||||
*/
|
||||
#define SMB_DATE_MAX (127<<9 | 12<<5 | 31)
|
||||
#define SMB_DATE_MIN (0<<9 | 1<<5 | 1)
|
||||
#define SMB_TIME_MAX (23<<11 | 59<<5 | 29)
|
||||
|
||||
int cifsFYI = 0;
|
||||
bool traceSMB;
|
||||
bool enable_oplocks = true;
|
||||
|
@ -142,6 +151,7 @@ cifs_read_super(struct super_block *sb)
|
|||
struct inode *inode;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifs_tcon *tcon;
|
||||
struct timespec64 ts;
|
||||
int rc = 0;
|
||||
|
||||
cifs_sb = CIFS_SB(sb);
|
||||
|
@ -161,6 +171,18 @@ cifs_read_super(struct super_block *sb)
|
|||
/* BB FIXME fix time_gran to be larger for LANMAN sessions */
|
||||
sb->s_time_gran = 100;
|
||||
|
||||
if (tcon->unix_ext) {
|
||||
ts = cifs_NTtimeToUnix(0);
|
||||
sb->s_time_min = ts.tv_sec;
|
||||
ts = cifs_NTtimeToUnix(cpu_to_le64(S64_MAX));
|
||||
sb->s_time_max = ts.tv_sec;
|
||||
} else {
|
||||
ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MIN), 0, 0);
|
||||
sb->s_time_min = ts.tv_sec;
|
||||
ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MAX), cpu_to_le16(SMB_TIME_MAX), 0);
|
||||
sb->s_time_max = ts.tv_sec;
|
||||
}
|
||||
|
||||
sb->s_magic = CIFS_MAGIC_NUMBER;
|
||||
sb->s_op = &cifs_super_ops;
|
||||
sb->s_xattr = cifs_xattr_handlers;
|
||||
|
|
|
@ -949,8 +949,8 @@ static const int total_days_of_prev_months[] = {
|
|||
struct timespec64 cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset)
|
||||
{
|
||||
struct timespec64 ts;
|
||||
time64_t sec;
|
||||
int min, days, month, year;
|
||||
time64_t sec, days;
|
||||
int min, day, month, year;
|
||||
u16 date = le16_to_cpu(le_date);
|
||||
u16 time = le16_to_cpu(le_time);
|
||||
SMB_TIME *st = (SMB_TIME *)&time;
|
||||
|
@ -966,15 +966,15 @@ struct timespec64 cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset)
|
|||
sec += 60 * 60 * st->Hours;
|
||||
if (st->Hours > 24)
|
||||
cifs_dbg(VFS, "illegal hours %d\n", st->Hours);
|
||||
days = sd->Day;
|
||||
day = sd->Day;
|
||||
month = sd->Month;
|
||||
if (days < 1 || days > 31 || month < 1 || month > 12) {
|
||||
cifs_dbg(VFS, "illegal date, month %d day: %d\n", month, days);
|
||||
days = clamp(days, 1, 31);
|
||||
if (day < 1 || day > 31 || month < 1 || month > 12) {
|
||||
cifs_dbg(VFS, "illegal date, month %d day: %d\n", month, day);
|
||||
day = clamp(day, 1, 31);
|
||||
month = clamp(month, 1, 12);
|
||||
}
|
||||
month -= 1;
|
||||
days += total_days_of_prev_months[month];
|
||||
days = day + total_days_of_prev_months[month];
|
||||
days += 3652; /* account for difference in days between 1980 and 1970 */
|
||||
year = sd->Year;
|
||||
days += year * 365;
|
||||
|
|
Loading…
Reference in New Issue