On Mon, 05 Feb 2018 09:21:32 +1300, Theo Buehler wrote:

> The load_user() function gets a file descriptor from process_crontab().
> It fdopen()s it directly and fclose()s the resulting stream. Then
> process_crontab() closes the stream a second time before exiting.
>
> Since crontab_fd is not load_user()'s descriptor, let's dup it before
> opening the stream.

Alternately, we could just pass in a FILE * to load_user().

 - todd

Index: usr.sbin/cron/database.c
===================================================================
RCS file: /cvs/src/usr.sbin/cron/database.c,v
retrieving revision 1.36
diff -u -p -u -r1.36 database.c
--- usr.sbin/cron/database.c    25 Oct 2017 17:08:58 -0000      1.36
+++ usr.sbin/cron/database.c    5 Feb 2018 02:18:37 -0000
@@ -170,9 +170,10 @@ process_crontab(int dfd, const char *una
                struct stat *statbuf, cron_db *new_db, cron_db *old_db)
 {
        struct passwd *pw = NULL;
-       int crontab_fd = -1;
+       FILE *crontab_fp = NULL;
        user *u, *new_u;
        mode_t tabmask, tabperm;
+       int fd;
 
        /* Note: pw must remain NULL for system crontab (see below). */
        if (fname[0] != '/' && (pw = getpwnam(uname)) == NULL) {
@@ -182,16 +183,20 @@ process_crontab(int dfd, const char *una
                goto next_crontab;
        }
 
-       crontab_fd = openat(dfd, fname,
-           O_RDONLY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC);
-       if (crontab_fd < 0) {
+       fd = openat(dfd, fname, O_RDONLY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC);
+       if (fd < 0) {
                /* crontab not accessible?
                 */
                syslog(LOG_ERR, "(%s) CAN'T OPEN (%s)", uname, fname);
                goto next_crontab;
        }
+       if (!(crontab_fp = fdopen(fd, "r"))) {
+               syslog(LOG_ERR, "(%s) FDOPEN (%m)", fname);
+               close(fd);
+               goto next_crontab;
+       }
 
-       if (fstat(crontab_fd, statbuf) < 0) {
+       if (fstat(fileno(crontab_fp), statbuf) < 0) {
                syslog(LOG_ERR, "(%s) FSTAT FAILED (%s)", uname, fname);
                goto next_crontab;
        }
@@ -233,7 +238,7 @@ process_crontab(int dfd, const char *una
                syslog(LOG_INFO, "(%s) RELOAD (%s)", uname, fname);
        }
 
-       new_u = load_user(crontab_fd, pw, fname);
+       new_u = load_user(crontab_fp, pw, fname);
        if (new_u != NULL) {
                /* Insert user into the new database and remove from old. */
                new_u->mtime = statbuf->st_mtim;
@@ -249,7 +254,7 @@ process_crontab(int dfd, const char *una
        }
 
  next_crontab:
-       if (crontab_fd >= 0) {
-               close(crontab_fd);
+       if (crontab_fp != NULL) {
+               fclose(crontab_fp);
        }
 }
Index: usr.sbin/cron/funcs.h
===================================================================
RCS file: /cvs/src/usr.sbin/cron/funcs.h,v
retrieving revision 1.28
diff -u -p -u -r1.28 funcs.h
--- usr.sbin/cron/funcs.h       14 Nov 2015 13:09:14 -0000      1.28
+++ usr.sbin/cron/funcs.h       5 Feb 2018 02:18:56 -0000
@@ -48,7 +48,7 @@ char          *env_get(char *, char **),
                **env_copy(char **),
                **env_set(char **, char *);
 
-user           *load_user(int, struct passwd *, const char *),
+user           *load_user(FILE *, struct passwd *, const char *),
                *find_user(cron_db *, const char *);
 
 entry          *load_entry(FILE *,
Index: usr.sbin/cron/user.c
===================================================================
RCS file: /cvs/src/usr.sbin/cron/user.c,v
retrieving revision 1.20
diff -u -p -u -r1.20 user.c
--- usr.sbin/cron/user.c        7 Jun 2017 23:36:43 -0000       1.20
+++ usr.sbin/cron/user.c        5 Feb 2018 02:17:51 -0000
@@ -58,19 +58,14 @@ parse_error(const char *msg)
 }
 
 user *
-load_user(int crontab_fd, struct passwd        *pw, const char *name)
+load_user(FILE *file, struct passwd *pw, const char *name)
 {
        char envstr[MAX_ENVSTR];
-       FILE *file;
        user *u;
        entry *e;
        int status, save_errno;
        char **envp = NULL, **tenvp;
 
-       if (!(file = fdopen(crontab_fd, "r"))) {
-               syslog(LOG_ERR, "(%s) FDOPEN (%m)", name);
-               return (NULL);
-       }
        CrontabFilename = name;
        LineNumber = 0;
 
@@ -134,6 +129,5 @@ load_user(int crontab_fd, struct passwd     
  done:
        if (envp != NULL)
                env_free(envp);
-       fclose(file);
        return (u);
 }

Reply via email to