On Sun, 2012-12-02 at 00:29 +0000, Sami Kerola wrote:
Earlier use of MAXHOSTNAMELEN is not posix compliant, though it
usually
results to be correct value. Using sysconf() is more correct, and avoids
rather nasty gethostname() catch. If a hostname length is exactly the
maximum a character buffer which has lenght of MAXHOSTNAMELEN will not be
null terminated. That will leave the later string operations vulnerable
to buffer overflow.
There are a few problems within the patch, please fix them. Comments
below:
diff --git a/src/crontab.c b/src/crontab.c
index 0e4c851..28e75a0 100644
@@ -453,9 +457,9 @@ static char *host_specific_filename(const char *filename, int
prefix)
*/
static char safename[MAX_FNAME];
- char hostname[MAXHOSTNAMELEN];
+ char *hostname = xgethostname();
- if (gethostname(hostname, sizeof hostname) != 0)
+ if (hostname == NULL)
return NULL;
if (prefix) {
You are not free()ing the hostname before you return from the function.
diff --git a/src/database.c b/src/database.c
index 61764d7..50bfd1b 100644
--- a/src/database.c
+++ b/src/database.c
@@ -255,7 +255,7 @@ cluster_host_is_local(void)
char filename[MAXNAMLEN+1];
int is_local;
FILE *f;
- char hostname[MAXHOSTNAMELEN], myhostname[MAXHOSTNAMELEN];
+ char *hostname, *myhostname;
if (!EnableClustering)
return (1);
@@ -275,14 +275,18 @@ cluster_host_is_local(void)
is_local = 0;
if (glue_strings(filename, sizeof filename, SPOOL_DIR, CRON_HOSTNAME, '/')) {
if ((f = fopen(filename, "r"))) {
+ hostname = xgethostname();
+ myhostname = xgethostname();
Why do you call xgethostname() for the hostname
when it is of fixed size
at most MAXHOSTNAMELEN? It could be a static length buffer.
- if (EOF != get_string(hostname, MAXHOSTNAMELEN, f,
"\n") &&
- gethostname(myhostname, MAXHOSTNAMELEN) == 0) {
+ if (!hostname && !myhostname &&
+ EOF != get_string(hostname, MAXHOSTNAMELEN, f, "\n")) {
This
condition doesn't look right as you seem to have the first two
conditions negated.
is_local = (strcmp(myhostname, hostname) == 0);
} else {
Debug(DLOAD, ("cluster: hostname comparison error\n"));
}
+ free(hostname);
+ free(myhostname);
fclose(f);
} else {
Debug(DLOAD, ("cluster: file %s not found\n", filename));
diff --git a/src/do_command.c b/src/do_command.c
index cf2b7ab..f4ed647 100644
--- a/src/do_command.c
+++ b/src/do_command.c
@@ -413,12 +413,14 @@ static int child_process(entry * e, char **jobenv) {
&& strncmp(MailCmd,"off",4) && !SyslogOutput) {
char **env;
char mailcmd[MAX_COMMAND];
- char hostname[MAXHOSTNAMELEN];
+ char *hostname;
char *content_type = env_get("CONTENT_TYPE", jobenv),
*content_transfer_encoding =
env_get("CONTENT_TRANSFER_ENCODING", jobenv);
- gethostname(hostname, MAXHOSTNAMELEN);
+ do
+ hostname = xgethostname();
+ while (hostname == NULL && usleep(1000));
Why this cycle here?
if (MailCmd[0] == '\0') {
if (snprintf(mailcmd, sizeof mailcmd, MAILFMT, MAILARG, mailfrom)
@@ -439,6 +441,7 @@ static int child_process(entry * e, char **jobenv) {
fprintf(mail, "To: %s\n", mailto);
fprintf(mail, "Subject: Cron <%s@%s> %s\n",
usernm, first_word(hostname, "."), e->cmd);
+ free(hostname);
#ifdef MAIL_DATE
fprintf(mail, "Date: %s\n", arpadate(&StartTime));
diff --git a/src/funcs.h b/src/funcs.h
index 4d95d22..d9afd48 100644
--- a/src/funcs.h
+++ b/src/funcs.h
@@ -73,7 +73,8 @@ int load_database(cron_db *),
allowed(const char * ,const char * ,const char *),
strdtb(char *);
-size_t strlens(const char *, ...);
+size_t strlens(const char *, ...),
+ get_hostname_max(void);
char *env_get(const char *, char **),
*arpadate(time_t *),
@@ -81,7 +82,8 @@ char *env_get(const char *, char **),
*first_word(const char *, const char *),
**env_init(void),
**env_copy(char **),
- **env_set(char **, char *);
+ **env_set(char **, char *),
+ *xgethostname(void);
user *load_user(int, struct passwd *, const char *, const char *, const char *),
*find_user(cron_db *, const char *, const char *);
diff --git a/src/misc.c b/src/misc.c
index 106f10e..e696171 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -391,7 +391,8 @@ int get_string(char *string, int size, FILE * file, const char
*terms) {
while (EOF != (ch = get_char(file)) && !strchr(terms, ch)) {
if (size > 1) {
- *string++ = (char) ch;
+ *string = (char) ch;
+ string++;
This is the same code.
size--;
}
}
@@ -738,6 +739,33 @@ size_t strlens(const char *last, ...) {
return (ret);
}
+size_t get_hostname_max(void) {
+ long len = sysconf(_SC_HOST_NAME_MAX);
+
+ if (0 < len)
+ return len;
+#ifdef MAXHOSTNAMELEN
+ return MAXHOSTNAMELEN;
+#elif HOST_NAME_MAX
+ return HOST_NAME_MAX;
+#endif
This does not make much sense as other code depends on MAXHOSTNAMELEN
being defined.
+ return 64;
+}
+
+char *xgethostname(void) {
+ char *name;
+ size_t sz = get_hostname_max() + 1;
+
+ name = malloc(sizeof (char) * sz);
+ if (!name)
+ return NULL;
+ if (gethostname(name, sz) != 0)
+ return NULL;
+
+ name[sz - 1] = '\0';
+ return name;
+}
+
/* Return the offset from GMT in seconds (algorithm taken from sendmail).
*
* warning:
--
Tomas Mraz
No matter how far down the wrong road you've gone, turn back.
Turkish proverb