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.
Index: usr.sbin/cron/user.c
===================================================================
RCS file: /var/cvs/src/usr.sbin/cron/user.c,v
retrieving revision 1.20
diff -u -p -r1.20 user.c
--- usr.sbin/cron/user.c 7 Jun 2017 23:36:43 -0000 1.20
+++ usr.sbin/cron/user.c 18 Jan 2018 23:14:20 -0000
@@ -28,6 +28,7 @@
#include <string.h>
#include <syslog.h>
#include <time.h> /* for structs.h */
+#include <unistd.h>
#include "macros.h"
#include "structs.h"
@@ -64,11 +65,16 @@ load_user(int crontab_fd, struct passwd
FILE *file;
user *u;
entry *e;
- int status, save_errno;
+ int fd, status, save_errno;
char **envp = NULL, **tenvp;
- if (!(file = fdopen(crontab_fd, "r"))) {
+ if ((fd = dup(crontab_fd)) == -1) {
+ syslog(LOG_ERR, "(%s) DUP (%m)", name);
+ return (NULL);
+ }
+ if (!(file = fdopen(fd, "r"))) {
syslog(LOG_ERR, "(%s) FDOPEN (%m)", name);
+ close(fd);
return (NULL);
}
CrontabFilename = name;