From 9efe590a8ed8fc6efc6ae667e0c03e3eecd0622b Mon Sep 17 00:00:00 2001 From: Bram Matthys Date: Wed, 11 Aug 2021 15:29:45 +0200 Subject: [PATCH] Newlog and fishy timestamp handling: * New macro IsInvalidChannelTS() which evaluates to ts < 750000 * Check for faulty creation time ("fishy timestamp") at ALL places where channel->creationtime is set. * Also, important, changed behavior: if !IsInvalidChannelTS then: 1) We print our warning 2) We pretend ts is our channel creationtime (which may be TStime() if the channel did not previously exist) 3) We allow the command through and allow it to merge (in case of SJOIN) This makes it so we still log the error (noisy) but on the other hand we won't get "infected" by fishy timestamps since we will never set them, no matter what happens. --- include/struct.h | 2 ++ src/modules/channeldb.c | 5 ++++- src/modules/mode.c | 30 ++++++++++++++++++------------ src/modules/sjoin.c | 24 ++++++++++++------------ 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/include/struct.h b/include/struct.h index 1e3d6b198..092e5c190 100644 --- a/include/struct.h +++ b/include/struct.h @@ -2007,6 +2007,8 @@ struct Link { } value; }; +#define IsInvalidChannelTS(x) ((x) < 750000) /**< Invalid channel creation time */ + /** * @addtogroup CommonStructs * @{ diff --git a/src/modules/channeldb.c b/src/modules/channeldb.c index 2dcce5d63..83099d5a3 100644 --- a/src/modules/channeldb.c +++ b/src/modules/channeldb.c @@ -506,7 +506,10 @@ int read_channeldb(void) R_SAFE(unrealdb_read_str(db, &mode_lock)); /* If we got this far, we can create/initialize the channel with the above */ channel = make_channel(chname); - channel->creationtime = creationtime; + if (IsInvalidChannelTS(creationtime)) + channel->creationtime = TStime(); + else + channel->creationtime = creationtime; safe_strdup(channel->topic, topic); safe_strdup(channel->topic_nick, topic_nick); channel->topic_time = topic_time; diff --git a/src/modules/mode.c b/src/modules/mode.c index 9a5168c9d..1160b48d6 100644 --- a/src/modules/mode.c +++ b/src/modules/mode.c @@ -417,25 +417,31 @@ void _do_mode(Channel *channel, Client *client, MessageTag *recv_mtags, int parc { if (sendts > 0) { - if (!channel->creationtime || sendts < channel->creationtime) + if (IsInvalidChannelTS(sendts)) { + unreal_log(ULOG_WARNING, "mode", "MODE_INVALID_TIMESTAMP", NULL, + "MODE for channel $channel has invalid timestamp $send_timestamp (from $client.name on $client.user.servername)\n" + "Buffer: $modebuf $parabuf", + log_data_channel("channel", channel), + log_data_integer("send_timestamp", sendts), + log_data_string("modebuf", modebuf), + log_data_string("parabuf", parabuf)); + /* Yeah, so what to do in this case? + * Don't set channel->creationtime + * and assume merging. + */ + sendts = channel->creationtime; + } else + if (sendts < channel->creationtime) + { + /* Our timestamp is wrong (or this is a new channel) */ tschange = 1; channel->creationtime = sendts; - if (sendts < 750000) - { - sendto_realops( - "Warning! Possible desync: MODE for channel %s ('%s %s') has fishy timestamp (%lld) (from %s/%s)", - channel->name, modebuf, parabuf, (long long)sendts, client->direction->name, client->name); - ircd_log(LOG_ERROR, "Possible desync: MODE for channel %s ('%s %s') has fishy timestamp (%lld) (from %s/%s)", - channel->name, modebuf, parabuf, (long long)sendts, client->direction->name, client->name); - } - /* new chan or our timestamp is wrong */ - /* now works for double-bounce prevention */ } if (sendts > channel->creationtime && channel->creationtime) { - /* theirs is wrong but we let it pass anyway */ + /* Their timestamp is wrong */ sendts = channel->creationtime; sendto_one(client, NULL, ":%s MODE %s + %lld", me.name, channel->name, (long long)channel->creationtime); diff --git a/src/modules/sjoin.c b/src/modules/sjoin.c index 7822289b3..6ff4cf2a6 100644 --- a/src/modules/sjoin.c +++ b/src/modules/sjoin.c @@ -178,16 +178,25 @@ CMD_FUNC(cmd_sjoin) if (parc < 5) nomode = 1; - ts = (time_t)atol(parv[1]); - channel = find_channel(parv[2]); if (!channel) { channel = make_channel(parv[2]); - channel->creationtime = ts; oldts = -1; } + ts = (time_t)atol(parv[1]); + + if (IsInvalidChannelTS(ts)) + { + unreal_log(ULOG_WARNING, "sjoin", "SJOIN_INVALID_TIMESTAMP", NULL, + "SJOIN for channel $channel has invalid timestamp $send_timestamp (from $client)", + log_data_channel("channel", channel), + log_data_integer("send_timestamp", ts)); + /* Pretend they match our creation time (matches U6 behavior in m_mode.c) */ + ts = channel->creationtime; + } + if (channel->creationtime > ts) { removeours = 1; @@ -208,15 +217,6 @@ CMD_FUNC(cmd_sjoin) oldts = channel->creationtime; } - // FIXME: make it so services cannot screw this up so easily --- if possible... - if (ts < 750000) - { - if (ts != 0) - sendto_ops - ("Warning! Possible desync: SJOIN for channel %s has a fishy timestamp (%lld) [%s/%s]", - channel->name, (long long)ts, client->name, client->direction->name); - } - parabuf[0] = '\0'; modebuf[0] = '+'; modebuf[1] = '\0';