summaryrefslogtreecommitdiffstats
path: root/usr.sbin/cron
diff options
context:
space:
mode:
authormillert <millert@openbsd.org>2017-06-07 17:59:36 +0000
committermillert <millert@openbsd.org>2017-06-07 17:59:36 +0000
commitf64f78fdcec057c9198eb39401b383191138d63d (patch)
tree3b0cbb15d187efec269bdda9232350a334de0fdc /usr.sbin/cron
parentPrepare the terminal driver for filling multiple columns in parallel, (diff)
downloadwireguard-openbsd-f64f78fdcec057c9198eb39401b383191138d63d.tar.xz
wireguard-openbsd-f64f78fdcec057c9198eb39401b383191138d63d.zip
When running at jobs, open the at spool and use the directory fd
with openat(), fstatat() and unlinkat(). This is similar to how we run cron jobs and eliminates the need for run_job() to find the basename of the at file. OK deraadt@
Diffstat (limited to 'usr.sbin/cron')
-rw-r--r--usr.sbin/cron/atrun.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/usr.sbin/cron/atrun.c b/usr.sbin/cron/atrun.c
index 78798b960ff..d1414d42592 100644
--- a/usr.sbin/cron/atrun.c
+++ b/usr.sbin/cron/atrun.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: atrun.c,v 1.43 2016/01/11 14:23:50 millert Exp $ */
+/* $OpenBSD: atrun.c,v 1.44 2017/06/07 17:59:36 millert Exp $ */
/*
* Copyright (c) 2002-2003 Todd C. Miller <Todd.Miller@courtesan.com>
@@ -51,7 +51,7 @@
#include "funcs.h"
#include "globals.h"
-static void run_job(atjob *, char *);
+static void run_job(const atjob *, int, const char *);
static int
strtot(const char *nptr, char **endptr, time_t *tp)
@@ -169,20 +169,32 @@ atrun(at_db *db, double batch_maxload, time_t now)
char atfile[PATH_MAX];
struct stat sb;
double la;
+ int dfd, len;
atjob *job, *tjob, *batch = NULL;
if (db == NULL)
return;
+ if ((dfd = open(_PATH_AT_SPOOL, O_RDONLY|O_DIRECTORY)) == -1) {
+ syslog(LOG_ERR, "(CRON) OPEN FAILED (%s)", _PATH_AT_SPOOL);
+ return;
+ }
+
TAILQ_FOREACH_SAFE(job, &db->jobs, entries, tjob) {
/* Skip jobs in the future */
if (job->run_time > now)
continue;
- snprintf(atfile, sizeof(atfile), "%s/%lld.%c", _PATH_AT_SPOOL,
+ len = snprintf(atfile, sizeof(atfile), "%lld.%c",
(long long)job->run_time, job->queue);
+ if (len >= sizeof(atfile)) {
+ TAILQ_REMOVE(&db->jobs, job, entries);
+ free(job);
+ continue;
+ }
- if (lstat(atfile, &sb) != 0 || !S_ISREG(sb.st_mode)) {
+ if (fstatat(dfd, atfile, &sb, AT_SYMLINK_NOFOLLOW) != 0 ||
+ !S_ISREG(sb.st_mode)) {
TAILQ_REMOVE(&db->jobs, job, entries);
free(job);
continue; /* disapeared or not a file */
@@ -200,7 +212,7 @@ atrun(at_db *db, double batch_maxload, time_t now)
batch = job;
} else {
/* normal at job */
- run_job(job, atfile);
+ run_job(job, dfd, atfile);
TAILQ_REMOVE(&db->jobs, job, entries);
free(job);
}
@@ -212,19 +224,22 @@ atrun(at_db *db, double batch_maxload, time_t now)
&& (batch_maxload == 0.0 ||
((getloadavg(&la, 1) == 1) && la <= batch_maxload))
) {
- snprintf(atfile, sizeof(atfile), "%s/%lld.%c", _PATH_AT_SPOOL,
+ len = snprintf(atfile, sizeof(atfile), "%lld.%c",
(long long)batch->run_time, batch->queue);
- run_job(batch, atfile);
+ if (len < sizeof(atfile))
+ run_job(batch, dfd, atfile);
TAILQ_REMOVE(&db->jobs, batch, entries);
free(job);
}
+
+ close(dfd);
}
/*
* Run the specified job contained in atfile.
*/
static void
-run_job(atjob *job, char *atfile)
+run_job(const atjob *job, int dfd, const char *atfile)
{
struct stat sb;
struct passwd *pw;
@@ -241,15 +256,11 @@ run_job(atjob *job, char *atfile)
char *nargv[2], *nenvp[1];
/* Open the file and unlink it so we don't try running it again. */
- if ((fd = open(atfile, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0)) < 0) {
+ if ((fd = openat(dfd, atfile, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0)) < 0) {
syslog(LOG_ERR, "(CRON) CAN'T OPEN (%s)", atfile);
return;
}
- unlink(atfile);
-
- /* We don't want the atjobs dir in the log messages. */
- if ((cp = strrchr(atfile, '/')) != NULL)
- atfile = cp + 1;
+ unlinkat(dfd, atfile, 0);
/* Fork so other pending jobs don't have to wait for us to finish. */
switch (fork()) {