From bd6df50781f819bb0c67c810e6f0e3efbc245a74 Mon Sep 17 00:00:00 2001 From: bluhm Date: Wed, 20 Aug 2014 20:10:17 +0000 Subject: [PATCH] Replace gethostbyaddr(3) with getnameinfo(3). Remove the sigprocmask() that was necessary for gethostbyaddr() because the latter is not signal safe. Change the return code semantics of priv_getnameinfo() to match getnameinfo(3). input and OK jca@ --- usr.sbin/syslogd/privsep.c | 66 +++++++++++++++++++------------------- usr.sbin/syslogd/syslogd.c | 38 ++++++---------------- usr.sbin/syslogd/syslogd.h | 4 +-- 3 files changed, 45 insertions(+), 63 deletions(-) diff --git a/usr.sbin/syslogd/privsep.c b/usr.sbin/syslogd/privsep.c index 8144e10ba1f..482ced704c8 100644 --- a/usr.sbin/syslogd/privsep.c +++ b/usr.sbin/syslogd/privsep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: privsep.c,v 1.37 2014/08/20 19:16:27 bluhm Exp $ */ +/* $OpenBSD: privsep.c,v 1.38 2014/08/20 20:10:17 bluhm Exp $ */ /* * Copyright (c) 2003 Anil Madhavapeddy @@ -68,7 +68,7 @@ enum cmd_types { PRIV_OPEN_CONFIG, /* open config file for reading only */ PRIV_CONFIG_MODIFIED, /* check if config file has been modified */ PRIV_GETADDRINFO, /* resolve host/service names */ - PRIV_GETHOSTBYADDR, /* resolve numeric address into hostname */ + PRIV_GETNAMEINFO, /* resolve numeric address into hostname */ PRIV_DONE_CONFIG_PARSE /* signal that the initial config parse is done */ }; @@ -76,7 +76,7 @@ static int priv_fd = -1; static volatile pid_t child_pid = -1; static char config_file[MAXPATHLEN]; static struct stat cf_info; -static int allow_gethostbyaddr = 0; +static int allow_getnameinfo = 0; static volatile sig_atomic_t cur_state = STATE_INIT; /* Queue for the allowed logfiles */ @@ -100,12 +100,12 @@ static int may_read(int, void *, size_t); int priv_init(char *conf, int numeric, int lockfd, int nullfd, char *argv[]) { - int i, fd, socks[2], cmd, addr_len, addr_af, result, restart; + int i, fd, socks[2], cmd, addr_len, result, restart; size_t path_len, hostname_len, servname_len; char path[MAXPATHLEN], hostname[MAXHOSTNAMELEN]; char servname[MAXHOSTNAMELEN]; + struct sockaddr_storage addr; struct stat cf_stat; - struct hostent *hp; struct passwd *pw; struct addrinfo hints, *res0; struct sigaction sa; @@ -191,11 +191,11 @@ priv_init(char *conf, int numeric, int lockfd, int nullfd, char *argv[]) if (stat(config_file, &cf_info) < 0) err(1, "stat config file failed"); - /* Save whether or not the child can have access to gethostbyaddr(3) */ + /* Save whether or not the child can have access to getnameinfo(3) */ if (numeric > 0) - allow_gethostbyaddr = 0; + allow_getnameinfo = 0; else - allow_gethostbyaddr = 1; + allow_getnameinfo = 1; TAILQ_INIT(&lognames); increase_state(STATE_CONFIG); @@ -322,24 +322,24 @@ priv_init(char *conf, int numeric, int lockfd, int nullfd, char *argv[]) } break; - case PRIV_GETHOSTBYADDR: - dprintf("[priv]: msg PRIV_GETHOSTBYADDR received\n"); - if (!allow_gethostbyaddr) - errx(1, "rejected attempt to gethostbyaddr"); - /* Expecting: length, address, address family */ + case PRIV_GETNAMEINFO: + dprintf("[priv]: msg PRIV_GETNAMEINFO received\n"); + if (!allow_getnameinfo) + errx(1, "rejected attempt to getnameinfo"); + /* Expecting: length, sockaddr */ must_read(socks[0], &addr_len, sizeof(int)); - if (addr_len <= 0 || addr_len > sizeof(hostname)) + if (addr_len <= 0 || addr_len > sizeof(addr)) _exit(1); - must_read(socks[0], hostname, addr_len); - must_read(socks[0], &addr_af, sizeof(int)); - hp = gethostbyaddr(hostname, addr_len, addr_af); - if (hp == NULL) { + must_read(socks[0], &addr, addr_len); + if (getnameinfo((struct sockaddr *)&addr, addr_len, + hostname, sizeof(hostname), NULL, 0, + NI_NOFQDN|NI_NAMEREQD|NI_DGRAM) != 0) { addr_len = 0; must_write(socks[0], &addr_len, sizeof(int)); } else { - addr_len = strlen(hp->h_name) + 1; + addr_len = strlen(hostname) + 1; must_write(socks[0], &addr_len, sizeof(int)); - must_write(socks[0], hp->h_name, addr_len); + must_write(socks[0], hostname, addr_len); } break; default: @@ -656,8 +656,8 @@ priv_config_parse_done(void) must_write(priv_fd, &cmd, sizeof(int)); } -/* Name/service to address translation. Response is placed into addr, and - * the length is returned (zero on error) */ +/* Name/service to address translation. Response is placed into addr. + * Return 0 for success or < 0 for error like getaddrinfo(3) */ int priv_getaddrinfo(char *host, char *serv, struct sockaddr *addr, size_t addr_len) @@ -701,36 +701,36 @@ priv_getaddrinfo(char *host, char *serv, struct sockaddr *addr, return (0); } -/* Reverse address resolution; response is placed into res, and length of - * response is returned (zero on error) */ +/* Reverse address resolution; response is placed into host. + * Return 0 for success or < 0 for error like getnameinfo(3) */ int -priv_gethostbyaddr(char *addr, int addr_len, int af, char *res, size_t res_len) +priv_getnameinfo(struct sockaddr *sa, socklen_t salen, char *host, + size_t hostlen) { int cmd, ret_len; if (priv_fd < 0) errx(1, "%s called from privileged portion", __func__); - cmd = PRIV_GETHOSTBYADDR; + cmd = PRIV_GETNAMEINFO; must_write(priv_fd, &cmd, sizeof(int)); - must_write(priv_fd, &addr_len, sizeof(int)); - must_write(priv_fd, addr, addr_len); - must_write(priv_fd, &af, sizeof(int)); + must_write(priv_fd, &salen, sizeof(int)); + must_write(priv_fd, sa, salen); /* Expect back an integer size, and then a string of that length */ must_read(priv_fd, &ret_len, sizeof(int)); /* Check there was no error (indicated by a return of 0) */ if (!ret_len) - return 0; + return (-1); /* Check we don't overflow the passed in buffer */ - if (res_len < ret_len) + if (hostlen < ret_len) errx(1, "%s: overflow attempt in return", __func__); /* Read the resolved hostname */ - must_read(priv_fd, res, ret_len); - return ret_len; + must_read(priv_fd, host, ret_len); + return (0); } /* Pass the signal through to child */ diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c index 9452ff2a180..5b6de913314 100644 --- a/usr.sbin/syslogd/syslogd.c +++ b/usr.sbin/syslogd/syslogd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: syslogd.c,v 1.113 2014/08/20 19:16:27 bluhm Exp $ */ +/* $OpenBSD: syslogd.c,v 1.114 2014/08/20 20:10:17 bluhm Exp $ */ /* * Copyright (c) 1983, 1988, 1993, 1994 @@ -250,7 +250,7 @@ volatile sig_atomic_t WantDie; volatile sig_atomic_t DoInit; struct filed *cfline(char *, char *); -void cvthname(struct sockaddr_in *, char *, size_t); +void cvthname(struct sockaddr *, char *, size_t); int decode(const char *, const CODE *); void dodie(int); void doinit(int); @@ -587,7 +587,7 @@ main(int argc, char *argv[]) (struct sockaddr *)&frominet, &len); if (i > 0) { line[i] = '\0'; - cvthname(&frominet, resolve, + cvthname((struct sockaddr *)&frominet, resolve, sizeof resolve); dprintf("cvthname res: %s\n", resolve); printline(resolve, line); @@ -1096,38 +1096,20 @@ reapchild(int signo) * Return a printable representation of a host address. */ void -cvthname(struct sockaddr_in *f, char *result, size_t res_len) +cvthname(struct sockaddr *f, char *result, size_t res_len) { - sigset_t omask, nmask; - char *p, *ip; - int ret_len; - - if (f->sin_family != AF_INET) { + if (getnameinfo(f, f->sa_len, result, res_len, NULL, 0, + NI_NUMERICHOST|NI_NUMERICSERV|NI_DGRAM) != 0) { dprintf("Malformed from address\n"); strlcpy(result, "???", res_len); return; } - - ip = inet_ntoa(f->sin_addr); - dprintf("cvthname(%s)\n", ip); - if (NoDNS) { - strlcpy(result, ip, res_len); + dprintf("cvthname(%s)\n", result); + if (NoDNS) return; - } - sigemptyset(&nmask); - sigaddset(&nmask, SIGHUP); - sigprocmask(SIG_BLOCK, &nmask, &omask); - - ret_len = priv_gethostbyaddr((char *)&f->sin_addr, - sizeof(struct in_addr), f->sin_family, result, res_len); - - sigprocmask(SIG_SETMASK, &omask, NULL); - if (ret_len == 0) { - dprintf("Host name for your address (%s) unknown\n", ip); - strlcpy(result, ip, res_len); - } else if ((p = strchr(result, '.')) && strcmp(p + 1, LocalDomain) == 0) - *p = '\0'; + if (priv_getnameinfo(f, f->sa_len, result, res_len) != 0) + dprintf("Host name for your address (%s) unknown\n", result); } void diff --git a/usr.sbin/syslogd/syslogd.h b/usr.sbin/syslogd/syslogd.h index 1c32c9aae99..e637bc43030 100644 --- a/usr.sbin/syslogd/syslogd.h +++ b/usr.sbin/syslogd/syslogd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: syslogd.h,v 1.10 2014/08/20 19:33:43 bluhm Exp $ */ +/* $OpenBSD: syslogd.h,v 1.11 2014/08/20 20:10:17 bluhm Exp $ */ /* * Copyright (c) 2003 Anil Madhavapeddy @@ -29,7 +29,7 @@ FILE *priv_open_config(void); void priv_config_parse_done(void); int priv_config_modified(void); int priv_getaddrinfo(char *, char *, struct sockaddr *, size_t); -int priv_gethostbyaddr(char *, int, int, char *, size_t); +int priv_getnameinfo(struct sockaddr *, socklen_t, char *, size_t); /* Terminal message */ char *ttymsg(struct iovec *, int, char *, int); -- 2.20.1