rpms/vixie-cron/devel vixie-cron-4.1-60_seconds.patch,NONE,1.1
fedora-cvs-commits at redhat.com
fedora-cvs-commits at redhat.com
Thu Jan 12 18:14:40 UTC 2006
- Previous message (by thread): rpms/system-config-bind/FC-4 .cvsignore, 1.22, 1.23 sources, 1.38, 1.39 system-config-bind.spec, 1.49, 1.50
- Next message (by thread): rpms/system-config-display/devel .cvsignore, 1.23, 1.24 sources, 1.25, 1.26 system-config-display.spec, 1.29, 1.30
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Author: jvdias
Update of /cvs/dist/rpms/vixie-cron/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv7341
Added Files:
vixie-cron-4.1-60_seconds.patch
Log Message:
DO NOT APPLY THIS PATCH!
This is checked in just to record the work done to ensure that at least
60 seconds elapse between job runs, which it turns out is not required -
the important thing is that the same job cannot be run twice in the same
minute, not that 60 seconds must elapse between job runs.
The mechanism to communicate the actual job run time to the crond main
process may be of some use in the future...
vixie-cron-4.1-60_seconds.patch:
cron.c | 43 ++++++++++++++++++++++++++++++++-
do_command.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 115 insertions(+), 3 deletions(-)
--- NEW FILE vixie-cron-4.1-60_seconds.patch ---
--- vixie-cron-4.1/cron.c.60_seconds 2006-01-11 15:16:47.000000000 -0500
+++ vixie-cron-4.1/cron.c 2006-01-11 20:02:08.000000000 -0500
@@ -37,12 +37,14 @@
sigchld_handler(int),
sighup_handler(int),
sigchld_reaper(void),
+ sigusr1_handler(int),
quit(int),
parse_args(int c, char *v[]);
static volatile sig_atomic_t got_sighup, got_sigchld;
-static int timeRunning, virtualTime, clockTime;
+static int timeRunning, virtualTime, clockTime, drift;
static long GMToff;
+static struct timeval time_last_job_run_tv={0,0};
static void
usage(void) {
@@ -86,6 +88,8 @@
sact.sa_handler = quit;
(void) sigaction(SIGINT, &sact, NULL);
(void) sigaction(SIGTERM, &sact, NULL);
+ sact.sa_handler = sigusr1_handler;
+ (void) sigaction(SIGUSR1, &sact, NULL);
acquire_daemonlock(0);
set_cron_uid();
@@ -137,6 +141,7 @@
set_time(TRUE);
run_reboot_jobs(&database);
timeRunning = virtualTime = clockTime;
+ drift = 0;
/*
* Too many clocks, not enough time (Al. Einstein)
@@ -151,6 +156,9 @@
while (TRUE) {
int timeDiff;
enum timejump wakeupKind;
+ struct timeval tv;
+ struct timezone tz={0,0};
+ struct timespec ts;
/* ... wait for the time (in minutes) to change ... */
do {
@@ -159,6 +167,31 @@
} while (clockTime == timeRunning);
timeRunning = clockTime;
+ /* Ensure at least 60 seconds have elapsed between successive job runs.
+ */
+ drift = 0;
+ if ( time_last_job_run_tv.tv_sec > 0 )
+ {
+ gettimeofday(&tv,&tz);
+ double time_since_last_job =
+ ( (((double)tv.tv_sec) + (((double)tv.tv_usec)/1000000.0))
+ -( ((double)time_last_job_run_tv.tv_sec)
+ +(((double)time_last_job_run_tv.tv_usec)/1000000.0)
+ )
+ );
+ memset(&time_last_job_run_tv,0,sizeof(struct timeval));
+ if( time_since_last_job < 60.0 )
+ {
+ double delay = (60.0 - time_since_last_job)
+ + (tv.tv_usec ? (((double)(1000000 - tv.tv_usec))/1000000.0) : 0);
+ ts.tv_sec = delay ;
+ drift = ts.tv_sec ;
+ ts.tv_nsec = ( delay - (double)ts.tv_sec ) * 1000000000;
+ Debug(DSCH,("DELAY: %lu %lu\n",ts.tv_sec,ts.tv_nsec));
+ nanosleep(&ts,0L);
+ }
+ }
+
/*
* Calculate how the current time differs from our virtual
* clock. Classify the change into one of 4 cases.
@@ -362,7 +395,7 @@
int seconds_to_wait;
t1 = time(NULL) + GMToff;
- seconds_to_wait = (int)(target * SECONDS_PER_MINUTE - t1) + 1;
+ seconds_to_wait = (int)(target * SECONDS_PER_MINUTE - t1) + 1 + drift;
Debug(DSCH, ("[%ld] Target time=%ld, sec-to-wait=%d\n",
(long)getpid(), (long)target*SECONDS_PER_MINUTE, seconds_to_wait))
@@ -399,6 +432,12 @@
}
static void
+sigusr1_handler(int x) {
+ struct timezone tz={0,0}; /* UTC */
+ gettimeofday(&time_last_job_run_tv,&tz);
+}
+
+static void
quit(int x) {
(void) unlink(_PATH_CRON_PID);
_exit(0);
--- vixie-cron-4.1/do_command.c.60_seconds 2006-01-11 15:16:47.000000000 -0500
+++ vixie-cron-4.1/do_command.c 2006-01-11 18:57:44.000000000 -0500
@@ -25,15 +25,38 @@
#include "cron.h"
+/* Allow the job user process the 'CAP_KILL' capability to signal the time of
+ job execution to the main cron process - need capability includes:
+*/
+#include <sys/syscall.h>
+#include <sys/capability.h>
+#include <sys/prctl.h>
+#ifndef SYS_capset
+#ifndef __NR_capset
+#error __NR_capset and SYS_capset undefined
+#else
+#define SYS_capset __NR_capset
+#endif
+#endif
+#ifndef SYS_capget
+#ifndef __NR_capget
+#error __NR_capget and SYS_capget undefined
+#else
+#define SYS_capset __NR_capget
+#endif
+#endif
+
static void child_process(entry *, user *);
static int safe_p(const char *, const char *);
+static pid_t crond_pid;
void
do_command(entry *e, user *u) {
Debug(DPROC, ("[%ld] do_command(%s, (%s,%ld,%ld))\n",
(long)getpid(), e->cmd, u->name,
(long)e->pwd->pw_uid, (long)e->pwd->pw_gid))
-
+
+ crond_pid = getpid();
/* fork to become asynchronous -- parent process is done immediately,
* and continues to run the normal cron code, which means return to
* tick(). the child and grandchild don't leave this function, alive.
@@ -67,6 +90,28 @@
int children = 0;
char **jobenv=0L;
+ struct __user_cap_header_struct caphead;
+ struct __user_cap_data_struct cap;
+
+ /* Before we set the security context, allow the job user to inherit the CAP_KILL capability: */
+
+ memset(&caphead, 0, sizeof(caphead));
+ memset(&cap, 0, sizeof(cap));
+ caphead.version = _LINUX_CAPABILITY_VERSION;
+ caphead.pid = 0;
+
+ if ( syscall(SYS_capget, &caphead, &cap) < 0)
+ syslog(LOG_INFO, "CRON (%s) ERROR: cannot get process capabilities:", strerror(errno));
+
+ cap.inheritable |= CAP_KILL ;
+
+ if ( syscall(SYS_capset, &caphead, &cap) < 0)
+ syslog(LOG_INFO, "CRON (%s) ERROR: cannot set process capabilities:", strerror(errno));
+
+ if ( prctl(PR_SET_KEEPCAPS,1,0,0,0) < 0 )
+ syslog(LOG_INFO, "CRON (%s) ERROR: cannot prctl(PR_SET_KEEPCAPS..):", strerror(errno));
+
+
/* Set up the Red Hat security context for both mail/minder and job processes:
*/
if ( cron_set_job_security_context( e, u, &jobenv ) != 0 )
@@ -75,6 +120,17 @@
exit(ERROR_EXIT);
}
+ /* Now we are the job user, running in user context with non-root capabilities.
+ * Add the CAP_KILL capability to our effective capability set:
+ */
+ if ( syscall(SYS_capget, &caphead, &cap) < 0)
+ syslog(LOG_INFO, "CRON (%s) ERROR: cannot get process capabilities:", strerror(errno));
+
+ cap.effective = cap.permitted ;
+
+ if ( syscall(SYS_capset, &caphead, &cap) < 0)
+ syslog(LOG_INFO, "CRON (%s) ERROR: cannot set process capabilities:", strerror(errno));
+
Debug(DPROC, ("[%ld] child_process('%s')\n", (long)getpid(), e->cmd))
#ifdef CAPITALIZE_FOR_PS
@@ -230,8 +286,25 @@
_exit(OK_EXIT);
}
# endif /*DEBUGGING*/
+ /* tell crond main process we are running the job */
+ if( kill(crond_pid, SIGUSR1) == -1 )
+ syslog(LOG_INFO, "CRON (%s) ERROR: kill failed: %s", e->pwd->pw_name, strerror(errno));
+
+ /* drop capabilities */
+ cap.permitted = 0;
+ cap.effective = 0;
+ cap.inheritable=0;
+ if( syscall(SYS_capset, &caphead, &cap) < 0 )
+ syslog(LOG_INFO, "CRON (%s) ERROR: capset (DROP) failed: %s", e->pwd->pw_name,
+ strerror(errno));
+ if( prctl(PR_SET_KEEPCAPS,0,0,0,0) < 0 )
+ syslog(LOG_INFO, "CRON (%s) ERROR: prctl clear KEEPCAPS failed: %s", e->pwd->pw_name,
+ strerror(errno));
+ /*** RUN THE COMMAND ***/
+
execle(shell, shell, "-c", e->cmd, (char *)0, jobenv);
+
fprintf(stderr, "execl: couldn't exec `%s'\n", shell);
perror("execl");
_exit(ERROR_EXIT);
- Previous message (by thread): rpms/system-config-bind/FC-4 .cvsignore, 1.22, 1.23 sources, 1.38, 1.39 system-config-bind.spec, 1.49, 1.50
- Next message (by thread): rpms/system-config-display/devel .cvsignore, 1.23, 1.24 sources, 1.25, 1.26 system-config-display.spec, 1.29, 1.30
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the fedora-cvs-commits
mailing list