From faac71c002f7c7a98741f991b25937b24f309df0 Mon Sep 17 00:00:00 2001 From: Jan Kryl Date: Thu, 27 Feb 2014 06:19:06 -0500 Subject: 4632 ndmp debug log belongs to /var/log 4645 double free in ndmpd when undefined SMF property is read 4644 NDMP plugin-path configurable should be empty by default Reviewed by: Albert Lee Reviewed by: Marcel Telka Reviewed by: Dan McDonald Approved by: Robert Mustacchi --- usr/src/cmd/ndmpd/include/ndmpd_prop.h | 2 + usr/src/cmd/ndmpd/ndmp.xml | 5 +- usr/src/cmd/ndmpd/ndmp/ndmpd.h | 2 - usr/src/cmd/ndmpd/ndmp/ndmpd_comm.c | 6 -- usr/src/cmd/ndmpd/ndmp/ndmpd_common.h | 4 +- usr/src/cmd/ndmpd/ndmp/ndmpd_log.c | 113 ++++++++++++------------------- usr/src/cmd/ndmpd/ndmp/ndmpd_log.h | 7 +- usr/src/cmd/ndmpd/ndmp/ndmpd_main.c | 119 +++++++++++++++++---------------- usr/src/cmd/ndmpd/ndmp/ndmpd_prop.c | 2 + 9 files changed, 116 insertions(+), 144 deletions(-) (limited to 'usr/src/cmd/ndmpd') diff --git a/usr/src/cmd/ndmpd/include/ndmpd_prop.h b/usr/src/cmd/ndmpd/include/ndmpd_prop.h index b8066daf98..e486b3086f 100644 --- a/usr/src/cmd/ndmpd/include/ndmpd_prop.h +++ b/usr/src/cmd/ndmpd/include/ndmpd_prop.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ /* @@ -114,6 +115,7 @@ typedef enum { NDMP_OVERWRITE_QTN, NDMP_ZFS_FORCE_OVERRIDE, NDMP_DRIVE_TYPE, + NDMP_DEBUG_MODE, NDMP_MAXALL } ndmpd_cfg_id_t; diff --git a/usr/src/cmd/ndmpd/ndmp.xml b/usr/src/cmd/ndmpd/ndmp.xml index b2d36d7061..da788ea2c5 100644 --- a/usr/src/cmd/ndmpd/ndmp.xml +++ b/usr/src/cmd/ndmpd/ndmp.xml @@ -117,8 +117,9 @@ POSSIBILITY OF SUCH DAMAGE. - - + + + diff --git a/usr/src/cmd/ndmpd/ndmp/ndmpd.h b/usr/src/cmd/ndmpd/ndmp/ndmpd.h index 2472ca04bc..3a39a04a7d 100644 --- a/usr/src/cmd/ndmpd/ndmp/ndmpd.h +++ b/usr/src/cmd/ndmpd/ndmp/ndmpd.h @@ -972,8 +972,6 @@ extern void ndmp_door_fini(void); extern boolean_t ndmp_door_check(void); extern int ndmp_get_max_tok_seq(void); -extern boolean_t set_debug_level(boolean_t); -extern boolean_t get_debug_level(void); extern int get_zfsvolname(char *, int, char *); extern int ndmp_create_snapshot(char *, char *); diff --git a/usr/src/cmd/ndmpd/ndmp/ndmpd_comm.c b/usr/src/cmd/ndmpd/ndmp/ndmpd_comm.c index 4acd554f92..08e525516f 100644 --- a/usr/src/cmd/ndmpd/ndmp/ndmpd_comm.c +++ b/usr/src/cmd/ndmpd/ndmp/ndmpd_comm.c @@ -767,10 +767,6 @@ ndmpd_main(void) char *propval; ndmp_load_params(); - if (ndmp_log_open_file() != 0) { - NDMP_LOG(LOG_ERR, - "Could not open log file properly."); - } /* * Find ndmp port number to be used. If ndmpd is run as command line @@ -789,8 +785,6 @@ ndmpd_main(void) if (ndmp_run(ndmp_port, connection_handler) == -1) perror("ndmp_run ERROR"); - - ndmp_log_close_file(); } /* diff --git a/usr/src/cmd/ndmpd/ndmp/ndmpd_common.h b/usr/src/cmd/ndmpd/ndmp/ndmpd_common.h index de79d38699..846f64e66f 100644 --- a/usr/src/cmd/ndmpd/ndmp/ndmpd_common.h +++ b/usr/src/cmd/ndmpd/ndmp/ndmpd_common.h @@ -37,6 +37,9 @@ */ /* Copyright (c) 2007, The Storage Networking Industry Association. */ /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */ +/* + * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + */ #ifndef _NDMP_COMMON_H #define _NDMP_COMMON_H @@ -62,7 +65,6 @@ #define INT_MAXCMD 12 -extern mutex_t log_lock; extern mutex_t ndmpd_zfs_fd_lock; /* Connection data structure. */ diff --git a/usr/src/cmd/ndmpd/ndmp/ndmpd_log.c b/usr/src/cmd/ndmpd/ndmp/ndmpd_log.c index 8f9b2e6d5b..0447e1c792 100644 --- a/usr/src/cmd/ndmpd/ndmp/ndmpd_log.c +++ b/usr/src/cmd/ndmpd/ndmp/ndmpd_log.c @@ -38,6 +38,9 @@ */ /* Copyright (c) 2007, The Storage Networking Industry Association. */ /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */ +/* + * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + */ #include #include @@ -56,12 +59,14 @@ #include "ndmpd.h" #include "ndmpd_common.h" +#define LOG_PATH "/var/log/ndmp" #define LOG_FNAME "ndmplog.%d" #define LOG_FILE_CNT 5 #define LOG_FILE_SIZE 4 * 1024 * 1024 #define LOG_SIZE_INT 256 -static boolean_t debug_level = 0; +static boolean_t debug = B_FALSE; +static boolean_t log_to_stderr = B_FALSE; static FILE *logfp; static int ndmp_synclog = 1; @@ -72,8 +77,7 @@ static int ndmp_synclog = 1; * that must be written to the log file. The following mutex is used * to allow only one thread to write into the log file. */ -mutex_t log_lock; -mutex_t idx_lock; +static mutex_t log_lock; static char *priority_str[] = { "EMERGENCY", @@ -100,7 +104,7 @@ mk_pathname(char *fname, char *path, int idx) char *fmt; int len; - len = strlen(path); + len = strnlen(path, PATH_MAX); fmt = (path[len - 1] == '/') ? "%s%s" : "%s/%s"; /* LINTED variable format specifier */ @@ -120,24 +124,16 @@ mk_pathname(char *fname, char *path, int idx) static int openlogfile(char *fname, char *mode) { - int rv; + assert(fname != NULL && *fname != '\0' && + mode != NULL && *mode != '\0'); - if (fname == NULL || *fname == '\0' || mode == NULL || *mode == '\0') + if ((logfp = fopen(fname, mode)) == NULL) { + perror("Error opening logfile"); return (-1); - - (void) mutex_lock(&log_lock); - rv = 0; - if (logfp != NULL) { - NDMP_LOG(LOG_DEBUG, "Log file already opened."); - rv = -1; - } else if ((logfp = fopen(fname, mode)) == NULL) { - syslog(LOG_ERR, "Error opening logfile %s, %m.", fname); - syslog(LOG_ERR, "Using system log for logging."); - rv = -1; } + (void) mutex_init(&log_lock, 0, NULL); - (void) mutex_unlock(&log_lock); - return (rv); + return (0); } @@ -192,26 +188,35 @@ log_append(char *msg) /* * ndmp_log_openfile * - * Open the log file either for append or write mode. + * Open the log file either for append or write mode. This function should + * be called while ndmpd is still running single-threaded and in foreground. */ int -ndmp_log_open_file(void) +ndmp_log_open_file(boolean_t to_stderr, boolean_t override_debug) { - char *fname, *mode; + char *fname, *mode, *lpath; char oldfname[PATH_MAX]; - char *lpath; struct stat64 st; int i; - /* Create the debug path if doesn't exist */ + log_to_stderr = to_stderr; + + /* read debug property if it isn't overriden by cmd line option */ + if (override_debug) + debug = B_TRUE; + else + debug = ndmpd_get_prop_yorn(NDMP_DEBUG_MODE) ? B_TRUE : B_FALSE; + + /* Create the debug path if it doesn't exist */ lpath = ndmpd_get_prop(NDMP_DEBUG_PATH); if ((lpath == NULL) || (*lpath == NULL)) - lpath = "/var/ndmp"; + lpath = LOG_PATH; if (stat64(lpath, &st) < 0) { if (mkdirp(lpath, 0755) < 0) { - NDMP_LOG(LOG_ERR, "Could not create log path %s: %m.", - lpath); + (void) fprintf(stderr, + "Could not create log path %s: %s\n", + lpath, strerror(errno)); lpath = "/var"; } } @@ -224,7 +229,7 @@ ndmp_log_open_file(void) * and if the last file {logfilename}.5 exist, it will be overwritten * with {logfilename}.4. */ - if (get_debug_level()) { + if (debug) { i = LOG_FILE_CNT - 1; while (i >= 0) { fname = mk_pathname(LOG_FNAME, lpath, i); @@ -236,9 +241,9 @@ ndmp_log_open_file(void) fname = mk_pathname(LOG_FNAME, lpath, i + 1); if (rename(oldfname, fname)) - syslog(LOG_DEBUG, - "Could not rename from %s to %s", - oldfname, fname); + (void) fprintf(stderr, + "Could not rename %s to %s: %s\n", + oldfname, fname, strerror(errno)); i--; } } @@ -248,7 +253,7 @@ ndmp_log_open_file(void) /* * Append only if debug is not enable. */ - if (get_debug_level()) + if (debug) mode = "w"; else mode = "a"; @@ -264,49 +269,11 @@ ndmp_log_open_file(void) void ndmp_log_close_file(void) { - (void) mutex_lock(&log_lock); if (logfp != NULL) { (void) fclose(logfp); logfp = NULL; } - (void) mutex_unlock(&log_lock); -} - -/* - * set_debug_level - * - * Sets the current debug level. - * Parameters: - * level (input) - new debug level. - * - * Returns: - * old debug level. - */ -boolean_t -set_debug_level(boolean_t level) -{ - boolean_t old = debug_level; - - debug_level = level; - return (old); -} - - -/* - * get_debug_level - * - * Returns the current debug level. - * - * Parameters: - * None. - * - * Returns: - * debug level. - */ -boolean_t -get_debug_level(void) -{ - return (debug_level); + (void) mutex_destroy(&log_lock); } void @@ -320,7 +287,7 @@ ndmp_log(ulong_t priority, char *ndmp_log_info, char *fmt, ...) char buf[PATH_MAX+KILOBYTE]; char *errstr; - if ((priority == LOG_DEBUG) && (debug_level == FALSE)) + if ((priority == LOG_DEBUG) && !debug) return; (void) mutex_lock(&log_lock); @@ -379,5 +346,9 @@ ndmp_log(ulong_t priority, char *ndmp_log_info, char *fmt, ...) if (logfp != NULL) log_append(ndmp_log_buf); + /* if ndmpd is running in foreground print log message to stderr */ + if (log_to_stderr) + (void) fprintf(stderr, "%s\n", ndmp_log_buf); + (void) mutex_unlock(&log_lock); } diff --git a/usr/src/cmd/ndmpd/ndmp/ndmpd_log.h b/usr/src/cmd/ndmpd/ndmp/ndmpd_log.h index 4f5b74bbcd..d761615f2d 100644 --- a/usr/src/cmd/ndmpd/ndmp/ndmpd_log.h +++ b/usr/src/cmd/ndmpd/ndmp/ndmpd_log.h @@ -38,6 +38,9 @@ */ /* Copyright (c) 2007, The Storage Networking Industry Association. */ /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */ +/* + * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + */ #ifndef _NDMPD_LOG_H #define _NDMPD_LOG_H @@ -51,9 +54,7 @@ typedef void log_func_t(ulong_t, char *, ...); extern log_func_t log_debug; extern log_func_t log_error; -extern boolean_t set_debug_level(boolean_t); -extern boolean_t get_debug_level(void); -extern int ndmp_log_open_file(void); +extern int ndmp_log_open_file(boolean_t, boolean_t); extern void ndmp_log_close_file(void); #endif /* _NDMPD_LOG_H */ diff --git a/usr/src/cmd/ndmpd/ndmp/ndmpd_main.c b/usr/src/cmd/ndmpd/ndmp/ndmpd_main.c index 6e541242fe..ea98c3f2b2 100644 --- a/usr/src/cmd/ndmpd/ndmp/ndmpd_main.c +++ b/usr/src/cmd/ndmpd/ndmp/ndmpd_main.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ /* @@ -74,11 +75,14 @@ mod_init() ndmp_plugin_t *(*plugin_init)(int); ndmp_pl = NULL; - if ((plname = ndmpd_get_prop(NDMP_PLUGIN_PATH)) == NULL) + + plname = ndmpd_get_prop(NDMP_PLUGIN_PATH); + if (plname == NULL || *plname == '\0') return (0); if ((mod_plp = dlopen(plname, RTLD_LOCAL | RTLD_NOW)) == NULL) { - syslog(LOG_ERR, "Error loading the plug-in %s", plname); + NDMP_LOG(LOG_ERR, "Error loading the plug-in %s: %s", + plname, dlerror()); return (0); } @@ -88,7 +92,7 @@ mod_init() return (0); } if ((ndmp_pl = plugin_init(NDMP_PLUGIN_VERSION)) == NULL) { - syslog(LOG_ERR, "Error loading the plug-in %s", plname); + NDMP_LOG(LOG_ERR, "Error loading the plug-in %s", plname); return (-1); } return (0); @@ -115,10 +119,8 @@ mod_fini() } static void -daemonize_init(char *arg) +set_privileges(void) { - sigset_t set, oset; - pid_t pid; priv_set_t *pset = priv_allocset(); /* @@ -144,10 +146,17 @@ daemonize_init(char *arg) } if (pset == NULL || setppriv(PRIV_SET, PRIV_EFFECTIVE, pset) != 0) { - syslog(LOG_ERR, "Failed to set least required privileges to " - "the service."); + (void) fprintf(stderr, + "Failed to set least required privileges to the service\n"); } priv_freeset(pset); +} + +static void +daemonize_init(void) +{ + sigset_t set, oset; + pid_t pid; /* * Block all signals prior to the fork and leave them blocked in the @@ -160,8 +169,8 @@ daemonize_init(char *arg) (void) sigprocmask(SIG_BLOCK, &set, &oset); if ((pid = fork()) == -1) { - openlog(arg, LOG_PID | LOG_NDELAY, LOG_DAEMON); - syslog(LOG_ERR, "Failed to start process in background."); + (void) fprintf(stderr, + "Failed to start process in background.\n"); exit(SMF_EXIT_ERR_CONFIG); } @@ -172,20 +181,6 @@ daemonize_init(char *arg) (void) setsid(); (void) sigprocmask(SIG_SETMASK, &oset, NULL); (void) chdir("/"); - (void) umask(0); -} - -static void -daemonize_fini(void) -{ - int fd; - - if ((fd = open("/dev/null", O_RDWR)) >= 0) { - (void) fcntl(fd, F_DUP2FD, STDIN_FILENO); - (void) fcntl(fd, F_DUP2FD, STDOUT_FILENO); - (void) fcntl(fd, F_DUP2FD, STDERR_FILENO); - (void) close(fd); - } } /* @@ -203,12 +198,12 @@ daemonize_fini(void) int main(int argc, char *argv[]) { - char c; struct sigaction act; sigset_t set; - void *arg = 0; - - openlog(argv[0], LOG_PID | LOG_NDELAY, LOG_DAEMON); + char c; + void *arg = NULL; + boolean_t run_in_foreground = B_FALSE; + boolean_t override_debug = B_FALSE; /* * Check for existing ndmpd door server (make sure ndmpd is not already @@ -216,50 +211,46 @@ main(int argc, char *argv[]) */ if (ndmp_door_check()) { /* ndmpd is already running, exit. */ + (void) fprintf(stderr, "ndmpd is already running.\n"); return (0); } - /* load ENVs */ - if (ndmpd_load_prop()) { - syslog(LOG_ERR, - "%s SMF properties initialization failed.", argv[0]); - exit(SMF_EXIT_ERR_CONFIG); - } - /* Global zone check */ if (getzoneid() != GLOBAL_ZONEID) { - syslog(LOG_ERR, "Local zone not supported."); + (void) fprintf(stderr, "Non-global zone not supported.\n"); exit(SMF_EXIT_ERR_FATAL); } /* Trusted Solaris check */ if (is_system_labeled()) { - syslog(LOG_ERR, "Trusted Solaris not supported."); + (void) fprintf(stderr, "Trusted Solaris not supported.\n"); exit(SMF_EXIT_ERR_FATAL); } + /* load SMF configuration */ + if (ndmpd_load_prop()) { + (void) fprintf(stderr, + "SMF properties initialization failed.\n"); + exit(SMF_EXIT_ERR_CONFIG); + } + opterr = 0; - while ((c = getopt(argc, argv, ":d")) != -1) { + while ((c = getopt(argc, argv, "df")) != -1) { switch (c) { case 'd': - (void) set_debug_level(TRUE); + override_debug = B_TRUE; + break; + case 'f': + run_in_foreground = B_TRUE; break; default: - syslog(LOG_ERR, "%s: Invalid option -%c.", + (void) fprintf(stderr, "%s: Invalid option -%c.\n", argv[0], optopt); - syslog(LOG_ERR, "Usage: %s [-d]", argv[0]); + (void) fprintf(stderr, "Usage: %s [-df]\n", argv[0]); exit(SMF_EXIT_ERR_CONFIG); } - } - closelog(); - /* - * close any open file descriptors which are greater - * than STDERR_FILENO - */ - closefrom(STDERR_FILENO + 1); - /* set up signal handler */ (void) sigfillset(&set); (void) sigdelset(&set, SIGABRT); /* always unblocked for ASSERT() */ @@ -278,31 +269,41 @@ main(int argc, char *argv[]) (void) sigdelset(&set, SIGUSR1); (void) sigdelset(&set, SIGPIPE); - (void) daemonize_init(argv[0]); - + set_privileges(); + (void) umask(077); openlog(argv[0], LOG_PID | LOG_NDELAY, LOG_DAEMON); - (void) mutex_init(&log_lock, 0, NULL); + + /* + * Open log file before we detach from terminal in case that open + * fails and error message is printed to stderr. + */ + if (ndmp_log_open_file(run_in_foreground, override_debug) != 0) + exit(SMF_EXIT_ERR_FATAL); + + if (!run_in_foreground) + daemonize_init(); + (void) mutex_init(&ndmpd_zfs_fd_lock, 0, NULL); if (mod_init() != 0) { - syslog(LOG_ERR, "Failed to load the plugin module."); + NDMP_LOG(LOG_ERR, "Failed to load the plugin module."); exit(SMF_EXIT_ERR_CONFIG); } /* libzfs init */ if ((zlibh = libzfs_init()) == NULL) { - syslog(LOG_ERR, "Failed to initialize ZFS library."); + NDMP_LOG(LOG_ERR, "Failed to initialize ZFS library."); exit(SMF_EXIT_ERR_CONFIG); } /* initialize and start the door server */ if (ndmp_door_init()) { - syslog(LOG_ERR, "Can not start ndmpd door server."); + NDMP_LOG(LOG_ERR, "Can not start ndmpd door server."); exit(SMF_EXIT_ERR_CONFIG); } if (tlm_init() == -1) { - syslog(LOG_ERR, "Failed to initialize tape manager."); + NDMP_LOG(LOG_ERR, "Failed to initialize tape manager."); exit(SMF_EXIT_ERR_CONFIG); } @@ -326,7 +327,7 @@ main(int argc, char *argv[]) case SIGHUP: /* Refresh SMF properties */ if (ndmpd_load_prop()) - syslog(LOG_ERR, + NDMP_LOG(LOG_ERR, "Service properties initialization " "failed."); break; @@ -343,11 +344,11 @@ main(int argc, char *argv[]) } (void) mutex_destroy(&ndmpd_zfs_fd_lock); - (void) mutex_destroy(&log_lock); libzfs_fini(zlibh); mod_fini(); ndmp_door_fini(); - daemonize_fini(); + ndmp_log_close_file(); + return (SMF_EXIT_OK); } diff --git a/usr/src/cmd/ndmpd/ndmp/ndmpd_prop.c b/usr/src/cmd/ndmpd/ndmp/ndmpd_prop.c index 98365035ca..f1c413b330 100644 --- a/usr/src/cmd/ndmpd/ndmp/ndmpd_prop.c +++ b/usr/src/cmd/ndmpd/ndmp/ndmpd_prop.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ /* @@ -90,6 +91,7 @@ ndmpd_cfg_param_t ndmpd_cfg_table[] = {"overwrite-quarantine", "", 0, NDMP_CF_NOTINIT}, {"zfs-force-override", "", 0, NDMP_CF_NOTINIT}, {"drive-type", "", 0, NDMP_CF_NOTINIT}, + {"debug-mode", "", 0, NDMP_CF_NOTINIT}, }; /* -- cgit v1.2.3