Skip to content

Commit

Permalink
Merge branch 'master' of github.com:yo8192/fcron
Browse files Browse the repository at this point in the history
  • Loading branch information
yo8192 committed May 29, 2024
2 parents c92e985 + f49f631 commit 87e8f95
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 30 deletions.
3 changes: 3 additions & 0 deletions config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@
#undef FOREGROUND
#undef RUN_NON_PRIVILEGED

/* 0 for no delay for any user, 60s is the default */
#undef MAX_FCRONTAB_RELOAD_DELAY_SECONDS

/* Define if we should use sete[ug]id() funcs */
#undef USE_SETE_ID

Expand Down
42 changes: 42 additions & 0 deletions configure.in
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,33 @@ WARNING :
AC_MSG_RESULT(no)
)

max_fcrontab_reload_delay_seconds=60
AC_MSG_CHECKING(max fcrontab reload delay seconds)
AC_ARG_WITH(max-fcrontab-reload-delay-seconds,
[ --with-max-fcrontab-reload-delay-seconds=INTEGER
The maximum delay, in seconds, before (re)loading the fcrontab as a non-root user
(there is never any delay for root). By default, the delay to (re)load the fcrontab
for a non-root user is at least one full second and at most sixty seconds,
depending on circumstances when the (re)load happens.
A value of 0 for this argument means no delay for any user, ever.
A value between 1 and 59 (inclusive) will ensure that the non-root delay is always at least 1s,
and never more than the given number of seconds.
A value greater than or equal to 60 has no effect.],
[
case "$withval" in
("" | *[!0123456789]*)
AC_MSG_ERROR(Invalid argument : please use a non-negative integer.)
;;
*)
max_fcrontab_reload_delay_seconds="$withval"
;;
esac

AC_MSG_RESULT([$withval])
])
MAX_FCRONTAB_RELOAD_DELAY_SECONDS="$max_fcrontab_reload_delay_seconds"
AC_SUBST(MAX_FCRONTAB_RELOAD_DELAY_SECONDS)
AC_DEFINE_UNQUOTED([MAX_FCRONTAB_RELOAD_DELAY_SECONDS], [$max_fcrontab_reload_delay_seconds])

if test "$fcrondyn" = ""; then
dnl As it stands gettimeofday() is required to have fcrondyn
Expand Down Expand Up @@ -1096,6 +1123,21 @@ else
echo "no"
fi

echo "Max fcrontab reload delay seconds : $max_fcrontab_reload_delay_seconds"

if test "$max_fcrontab_reload_delay_seconds" -lt "1" ; then
AC_MSG_WARN([

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
WARNING:
This option --with-max-fcrontab-reload-delay-seconds=0, allows a
non-privileged user to immediately (re)load fcrontab.
This allows the possibility of SIGHUP denial of service to block the daemon.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

])
fi

echo -n "Load average support : "
if test "$getloadavg" -eq 1 -o -n "$proc"; then
echo "yes"
Expand Down
9 changes: 5 additions & 4 deletions fcrondyn_svr.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ print_fields(int fd, unsigned char *details)
char field_user[] = "|USER ";
char field_rq[] = "|R&Q ";
char field_options[] = "|OPTIONS ";
char field_schedule[] = "|SCHEDULE ";
char field_schedule[] = "|SCHEDULE ";
char field_until[] = "|LAVG 1,5,15 UNTIL STRICT";
char field_pid[] = "|PID ";
char field_index[] = "|INDEX";
Expand Down Expand Up @@ -456,9 +456,10 @@ print_line(int fd, struct cl_t *line, unsigned char *details, pid_t pid,
ftime = localtime(&until);
len +=
snprintf(buf + len, sizeof(buf) - len,
" %04d-%02d-%02d %02d:%02d %s",
" %04d-%02d-%02d %02d:%02d:%02d %s",
(ftime->tm_year + 1900), (ftime->tm_mon + 1),
ftime->tm_mday, ftime->tm_hour, ftime->tm_min,
ftime->tm_sec,
(is_strict(line->cl_option)) ? "Y" : "N");
}
else
Expand All @@ -469,9 +470,9 @@ print_line(int fd, struct cl_t *line, unsigned char *details, pid_t pid,
if (bit_test(details, FIELD_SCHEDULE)) {
ftime = localtime(&(line->cl_nextexe));
len +=
snprintf(buf + len, sizeof(buf) - len, "|%04d-%02d-%02d %02d:%02d",
snprintf(buf + len, sizeof(buf) - len, "|%04d-%02d-%02d %02d:%02d:%02d",
(ftime->tm_year + 1900), (ftime->tm_mon + 1),
ftime->tm_mday, ftime->tm_hour, ftime->tm_min);
ftime->tm_mday, ftime->tm_hour, ftime->tm_min, ftime->tm_sec);
}
len += snprintf(buf + len, sizeof(buf) - len, "|%s\n", line->cl_shell);

Expand Down
59 changes: 33 additions & 26 deletions fcronsighup.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,37 +86,44 @@ sig_daemon(void)
/* SIGHUP is sent once 10s before the next minute to avoid
* some bad users to block daemon by sending it SIGHUP all the time */
{
/* we don't need to make root wait */
if (uid != rootuid) {
time_t t = 0;
int sl = 0;
int max_delay_s = 60;
#ifdef MAX_FCRONTAB_RELOAD_DELAY_SECONDS
max_delay_s = MAX_FCRONTAB_RELOAD_DELAY_SECONDS;
#endif
if (uid == rootuid) {
/* we don't need to make root wait */
max_delay_s = 0;
}

if (max_delay_s > 0) {
time_t now_epoch = 0;
int delay_s = 0;
time_t *target_time_epoch = NULL;
struct tm *target_time_tm = NULL;
FILE *fp = NULL;
int fd = 0;
struct tm *tm = NULL;
char sigfile[PATH_LEN];
char buf[PATH_LEN];

sigfile[0] = '\0';
t = time(NULL);
tm = localtime(&t);

if ((sl = 60 - (t % 60) - 10) < 0) {
if ((tm->tm_min = tm->tm_min + 2) >= 60) {
tm->tm_hour++;
tm->tm_min -= 60;
}
snprintf(buf, sizeof(buf), "%02d:%02d", tm->tm_hour, tm->tm_min);
sl = 60 - (t % 60) + 50;
now_epoch = time(NULL);

if (now_epoch % 60 < 50) {
/* clocktime is < ##:##:50, so target 10s before the end of the current minute */
delay_s = 50 - (now_epoch % 60);
} else {
/* clocktime is >= ##:##:50, so target 10s before the end of the next minute */
delay_s = 50 + (60 - (now_epoch % 60));
}
else {
if (++tm->tm_min >= 60) {
tm->tm_hour++;
tm->tm_min -= 60;
}
snprintf(buf, sizeof(buf), "%02d:%02d", tm->tm_hour, tm->tm_min);

if (delay_s > max_delay_s) {
delay_s = max_delay_s;
}
fprintf(stderr, "Modifications will be taken into account"
" at %s.\n", buf);

target_time_epoch = now_epoch + delay_s;
target_time_tm = localtime(&target_time_epoch);

fprintf(stderr, "Modifications will be taken into account at %02d:%02d:%02d.\n",
target_time_tm->tm_hour, target_time_tm->tm_min, target_time_tm->tm_sec);

/* if fcrontabs is too long, snprintf will not be able to add "/fcrontab.sig"
* string at the end of sigfile */
Expand Down Expand Up @@ -167,7 +174,7 @@ sig_daemon(void)
}
#endif /* ! HAVE_FLOCK */

sleep(sl);
sleep(delay_s);

/* also closes the underlying file descriptor fd: */
xfclose_check(&fp, sigfile);
Expand All @@ -178,7 +185,7 @@ sig_daemon(void)
error_e("Could not remove %s");
}
else
/* we are root */
/* we are root, or config MAX_FCRONTAB_RELOAD_DELAY_SECONDS=0 is set */
fprintf(stderr,
"Modifications will be taken into account" " right now.\n");

Expand Down

0 comments on commit 87e8f95

Please sign in to comment.