void
mgt_sandbox_solaris_privsep(void)
{
	if (priv_ineffect(PRIV_PROC_SETID)) {
                if (getgid() != params->gid)
                        XXXAZ(setgid(params->gid));
                if (getuid() != params->uid)
                        XXXAZ(setuid(params->uid));
        } else {
                REPORT(LOG_INFO, "Privilege %s missing, will not change uid/gid",
		    PRIV_PROC_SETID);
        }
}
示例#2
0
文件: dladm.c 项目: andreiw/polaris
int
main(int argc, char *argv[])
{
	int	i;
	cmd_t	*cmdp;

	(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define	TEXT_DOMAIN "SYS_TEST"
#endif
	(void) textdomain(TEXT_DOMAIN);

	progname = argv[0];

	if (argc < 2)
		usage();

	if (!priv_ineffect(PRIV_SYS_NET_CONFIG) ||
	    !priv_ineffect(PRIV_NET_RAWACCESS)) {
		(void) fprintf(stderr,
		    gettext("%s: insufficient privileges\n"), progname);
		exit(1);
	}

	for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
		cmdp = &cmds[i];
		if (strcmp(argv[1], cmdp->c_name) == 0) {
			cmdp->c_fn(argc - 1, &argv[1]);
			exit(0);
		}
	}

	(void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
	    progname, argv[1]);
	usage();

	return (0);
}
static void
vjs_privsep(enum jail_gen_e jge)
{
	(void)jge;

	if (priv_ineffect(PRIV_PROC_SETID)) {
		if (getgid() != mgt_param.gid)
			XXXAZ(setgid(mgt_param.gid));
		if (getuid() != mgt_param.uid)
			XXXAZ(setuid(mgt_param.uid));
	} else {
		MGT_complain(C_SECURITY,
		    "Privilege %s missing, will not change uid/gid",
		    PRIV_PROC_SETID);
	}
}
static void
mgt_sandbox_solaris_privsep(enum sandbox_e who)
{
	(void)who;

	if (priv_ineffect(PRIV_PROC_SETID)) {
                if (getgid() != mgt_param.gid)
                        XXXAZ(setgid(mgt_param.gid));
                if (getuid() != mgt_param.uid)
                        XXXAZ(setuid(mgt_param.uid));
        } else {
                REPORT(LOG_INFO,
		    "Privilege %s missing, will not change uid/gid",
		    PRIV_PROC_SETID);
        }
}
示例#5
0
int
main(int argc, char *argv[])
{
	char c;
	char log_severity[16] = "";
	JavaVMInitArgs vm_args;
	JavaVMOption vm_opts[5];
	int nopts = 0;
	const char *classpath;
	const char *libpath;
	size_t len;
	const char *err_desc;
	JNIEnv *env;
	jmethodID poold_getinstancewcl_mid;
	jmethodID poold_run_mid;
	jobject log_severity_string = NULL;
	jobject log_severity_obj = NULL;
	jclass severity_class;
	jmethodID severity_cons_mid;
	jfieldID base_log_fid;
	pthread_t hdl_thread;
	FILE *p;

	(void) pthread_mutex_lock(&jvm_lock);
	pname = pu_getpname(argv[0]);
	openlog(pname, 0, LOG_DAEMON);
	(void) chdir("/");

	(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)		/* Should be defined with cc -D. */
#define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it wasn't. */
#endif
	(void) textdomain(TEXT_DOMAIN);

	opterr = 0;
	while ((c = getopt(argc, argv, "l:P")) != EOF) {
		switch (c) {
		case 'l':	/* -l option */
			lflag++;
			(void) strlcpy(log_severity, optarg,
			    sizeof (log_severity));
			log_dest = LD_TERMINAL;
			break;
		default:
			usage();
			/*NOTREACHED*/
		}
	}

	/*
	 * Check permission
	 */
	if (!priv_ineffect(PRIV_SYS_RES_CONFIG))
		pu_die(gettext(ERR_PRIVILEGE), PRIV_SYS_RES_CONFIG);

	/*
	 * In order to avoid problems with arbitrary thread selection
	 * when handling asynchronous signals, dedicate a thread to
	 * look after these signals.
	 */
	if (sigemptyset(&hdl_set) < 0 ||
	    sigaddset(&hdl_set, SIGHUP) < 0 ||
	    sigaddset(&hdl_set, SIGTERM) < 0 ||
	    sigaddset(&hdl_set, SIGINT) < 0 ||
	    pthread_sigmask(SIG_BLOCK, &hdl_set, NULL) ||
	    pthread_create(&hdl_thread, NULL, handle_sig, NULL))
		pu_die(gettext("can't install signal handler"));

	/*
	 * If the -l flag is supplied, terminate the SMF service and
	 * run interactively from the command line.
	 */
	if (lflag) {
		char *cmd = "/usr/sbin/svcadm disable -st " SMF_SVC_INSTANCE;

		if (getenv("SMF_FMRI") != NULL)
			pu_die("-l option illegal: %s\n", SMF_SVC_INSTANCE);
		/*
		 * Since disabling a service isn't synchronous, use the
		 * synchronous option from svcadm to achieve synchronous
		 * behaviour.
		 * This is not very satisfactory, but since this is only
		 * for use in debugging scenarios, it will do until there
		 * is a C API to synchronously shutdown a service in SMF.
		 */
		if ((p = popen(cmd, "w")) == NULL || pclose(p) != 0)
			pu_die("could not temporarily disable service: %s\n",
			    SMF_SVC_INSTANCE);
	} else {
		/*
		 * Check if we are running as a SMF service. If we
		 * aren't, terminate this process after enabling the
		 * service.
		 */
		if (getenv("SMF_FMRI") == NULL) {
			char *cmd = "/usr/sbin/svcadm enable -s " \
			    SMF_SVC_INSTANCE;
			if ((p = popen(cmd, "w")) == NULL || pclose(p) != 0)
				pu_die("could not enable "
				    "service: %s\n", SMF_SVC_INSTANCE);
			return (E_PO_SUCCESS);
		}
	}

	/*
	 * Establish the classpath and LD_LIBRARY_PATH for native
	 * methods, and get the interpreter going.
	 */
	if ((classpath = getenv("POOLD_CLASSPATH")) == NULL) {
		classpath = POOLD_DEF_CLASSPATH;
	} else {
		const char *cur = classpath;

		/*
		 * Check the components to make sure they're absolute
		 * paths.
		 */
		while (cur != NULL && *cur) {
			if (*cur != '/')
				pu_die(gettext(
				    "POOLD_CLASSPATH must contain absolute "
				    "components\n"));
			cur = strchr(cur + 1, ':');
		}
	}
	vm_opts[nopts].optionString = malloc(len = strlen(classpath) +
	    strlen("-Djava.class.path=") + 1);
	(void) strlcpy(vm_opts[nopts].optionString, "-Djava.class.path=", len);
	(void) strlcat(vm_opts[nopts++].optionString, classpath, len);

	if ((libpath = getenv("POOLD_LD_LIBRARY_PATH")) == NULL)
		libpath = POOLD_DEF_LIBPATH;
	vm_opts[nopts].optionString = malloc(len = strlen(libpath) +
	    strlen("-Djava.library.path=") + 1);
	(void) strlcpy(vm_opts[nopts].optionString, "-Djava.library.path=",
	    len);
	(void) strlcat(vm_opts[nopts++].optionString, libpath, len);

	vm_opts[nopts++].optionString = "-Xrs";
	vm_opts[nopts++].optionString = "-enableassertions";

	vm_args.options = vm_opts;
	vm_args.nOptions = nopts;
	vm_args.ignoreUnrecognized = JNI_FALSE;
	vm_args.version = 0x00010002;

	if (JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args) < 0)
		pu_die(gettext("can't create Java VM"));

	/*
	 * Locate the Poold class and construct an instance.  A side
	 * effect of this is that the poold instance's logHelper will be
	 * initialized, establishing loggers for logging errors from
	 * this point on.  (Note, in the event of an unanticipated
	 * exception, poold will invoke die() itself.)
	 */
	err_desc = gettext("JVM-related error initializing poold\n");
	if ((poold_class = (*env)->FindClass(env, POOLD_CLASS_DESC)) == NULL)
		goto destroy;
	if ((poold_getinstancewcl_mid = (*env)->GetStaticMethodID(env,
	    poold_class, "getInstanceWithConsoleLogging", "("
	    CLASS_FIELD_DESC(SEVERITY_CLASS_DESC) ")"
	    CLASS_FIELD_DESC(POOLD_CLASS_DESC))) == NULL)
		goto destroy;
	if ((poold_run_mid = (*env)->GetMethodID(env, poold_class, "run",
	    "()V")) == NULL)
		goto destroy;
	if ((severity_class = (*env)->FindClass(env, SEVERITY_CLASS_DESC))
	    == NULL)
		goto destroy;
	if ((severity_cons_mid = (*env)->GetStaticMethodID(env, severity_class,
	    "getSeverityWithName", "(" CLASS_FIELD_DESC(STRING_CLASS_DESC) ")"
	    CLASS_FIELD_DESC(SEVERITY_CLASS_DESC))) == NULL)
		goto destroy;

	/*
	 * -l <level> was specified, indicating that messages are to be
	 * logged to the console only.
	 */
	if (strlen(log_severity) > 0) {
		if ((log_severity_string = (*env)->NewStringUTF(env,
		    log_severity)) == NULL)
			goto destroy;
		if ((log_severity_obj = (*env)->CallStaticObjectMethod(env,
		    severity_class, severity_cons_mid, log_severity_string)) ==
		    NULL) {
			err_desc = gettext("invalid level specified\n");
			goto destroy;
		}
	} else
		log_severity_obj = NULL;

	if ((poold_instance = (*env)->CallStaticObjectMethod(env, poold_class,
	    poold_getinstancewcl_mid, log_severity_obj)) == NULL)
		goto destroy;

	/*
	 * Grab a global reference to poold for use in our signal
	 * handlers.
	 */
	poold_instance = (*env)->NewGlobalRef(env, poold_instance);

	/*
	 * Ready LD_JAVA logging.
	 */
	err_desc = gettext("cannot initialize logging\n");
	if ((log_severity_string = (*env)->NewStringUTF(env, "err")) == NULL)
		goto destroy;
	if (!(severity_err = (*env)->CallStaticObjectMethod(env, severity_class,
	    severity_cons_mid, log_severity_string)))
		goto destroy;
	if (!(severity_err = (*env)->NewGlobalRef(env, severity_err)))
		goto destroy;

	if ((log_severity_string = (*env)->NewStringUTF(env, "notice")) == NULL)
		goto destroy;
	if (!(severity_notice = (*env)->CallStaticObjectMethod(env,
	    severity_class, severity_cons_mid, log_severity_string)))
		goto destroy;
	if (!(severity_notice = (*env)->NewGlobalRef(env, severity_notice)))
		goto destroy;

	if (!(base_log_fid = (*env)->GetStaticFieldID(env, poold_class,
	    "BASE_LOG", CLASS_FIELD_DESC(LOGGER_CLASS_DESC))))
		goto destroy;
	if (!(base_log = (*env)->GetStaticObjectField(env, poold_class,
	    base_log_fid)))
		goto destroy;
	if (!(base_log = (*env)->NewGlobalRef(env, base_log)))
		goto destroy;
	if (!(log_mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env,
	    base_log), "log", "(" CLASS_FIELD_DESC(LEVEL_CLASS_DESC)
	    CLASS_FIELD_DESC(STRING_CLASS_DESC) ")V")))
		goto destroy;
	log_dest = LD_JAVA;

	/*
	 * If invoked directly and -l is specified, forking is not
	 * desired.
	 */
	if (!lflag)
		switch (forkall()) {
		case 0:
			(void) setsid();
			(void) fclose(stdin);
			(void) fclose(stdout);
			(void) fclose(stderr);
			break;
		case -1:
			pu_die(gettext("cannot fork"));
			/*NOTREACHED*/
		default:
			return (E_PO_SUCCESS);
		}

	instance_running = 1;
	(void) pthread_mutex_unlock(&jvm_lock);

	(*env)->CallVoidMethod(env, poold_instance, poold_run_mid);

	(void) pthread_mutex_lock(&jvm_lock);
	if ((*env)->ExceptionOccurred(env)) {
		goto destroy;
	}
	if (jvm) {
		(*jvm)->DestroyJavaVM(jvm);
		jvm = NULL;
	}
	(void) pthread_mutex_unlock(&jvm_lock);
	return (E_PO_SUCCESS);

destroy:
	if (lflag && (*env)->ExceptionOccurred(env))
		(*env)->ExceptionDescribe(env);
	pu_die(err_desc);
}
示例#6
0
int
main(int ac, char *av[])
{
	char *dir = "/";
	int allflag = 0;
	int df_allflag = 0;
	int opt_cnt = 0;
	int maxservers = 1;	/* zero allows inifinte number of threads */
	int maxservers_set = 0;
	int logmaxservers = 0;
	int pid;
	int i;
	char *provider = (char *)NULL;
	char *df_provider = (char *)NULL;
	struct protob *protobp0, *protobp;
	NETSELDECL(proto) = NULL;
	NETSELDECL(df_proto) = NULL;
	NETSELPDECL(providerp);
	char *defval;
	boolean_t can_do_mlp;
	uint_t dss_npaths = 0;
	char **dss_pathnames = NULL;
	sigset_t sgset;
	char name[PATH_MAX], value[PATH_MAX];
	int ret, bufsz;

	int pipe_fd = -1;

	MyName = *av;

	/*
	 * Initializations that require more privileges than we need to run.
	 */
	(void) _create_daemon_lock(NFSD, DAEMON_UID, DAEMON_GID);
	svcsetprio();

	can_do_mlp = priv_ineffect(PRIV_NET_BINDMLP);
	if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET,
	    DAEMON_UID, DAEMON_GID, PRIV_SYS_NFS,
	    can_do_mlp ? PRIV_NET_BINDMLP : NULL, NULL) == -1) {
		(void) fprintf(stderr, "%s should be run with"
		    " sufficient privileges\n", av[0]);
		exit(1);
	}

	(void) enable_extended_FILE_stdio(-1, -1);

	/*
	 * Read in the values from SMF first before we check
	 * command line options so the options override SMF values.
	 */
	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("max_connections", value, DEFAULT_INSTANCE,
	    SCF_TYPE_INTEGER, NFSD, &bufsz);
	if (ret == SA_OK) {
		errno = 0;
		max_conns_allowed = strtol(value, (char **)NULL, 10);
		if (errno != 0)
			max_conns_allowed = -1;
	}

	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("listen_backlog", value, DEFAULT_INSTANCE,
	    SCF_TYPE_INTEGER, NFSD, &bufsz);
	if (ret == SA_OK) {
		errno = 0;
		listen_backlog = strtol(value, (char **)NULL, 10);
		if (errno != 0) {
			listen_backlog = 32;
		}
	}

	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("protocol", value, DEFAULT_INSTANCE,
	    SCF_TYPE_ASTRING, NFSD, &bufsz);
	if ((ret == SA_OK) && strlen(value) > 0) {
		df_proto = strdup(value);
		opt_cnt++;
		if (strncasecmp("ALL", value, 3) == 0) {
			free(df_proto);
			df_proto = NULL;
			df_allflag = 1;
		}
	}

	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("device", value, DEFAULT_INSTANCE,
	    SCF_TYPE_ASTRING, NFSD, &bufsz);
	if ((ret == SA_OK) && strlen(value) > 0) {
		df_provider = strdup(value);
		opt_cnt++;
	}

	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("servers", value, DEFAULT_INSTANCE,
	    SCF_TYPE_INTEGER, NFSD, &bufsz);
	if (ret == SA_OK) {
		errno = 0;
		maxservers = strtol(value, (char **)NULL, 10);
		if (errno != 0)
			maxservers = 1;
		else
			maxservers_set = 1;
	}

	bufsz = 4;
	ret = nfs_smf_get_prop("server_versmin", value, DEFAULT_INSTANCE,
	    SCF_TYPE_INTEGER, NFSD, &bufsz);
	if (ret == SA_OK)
		nfs_server_vers_min = strtol(value, (char **)NULL, 10);

	bufsz = 4;
	ret = nfs_smf_get_prop("server_versmax", value, DEFAULT_INSTANCE,
	    SCF_TYPE_INTEGER, NFSD, &bufsz);
	if (ret == SA_OK)
		nfs_server_vers_max = strtol(value, (char **)NULL, 10);

	bufsz = PATH_MAX;
	ret = nfs_smf_get_prop("server_delegation", value, DEFAULT_INSTANCE,
	    SCF_TYPE_ASTRING, NFSD, &bufsz);
	if (ret == SA_OK)
		if (strncasecmp(value, "off", 3) == 0)
			nfs_server_delegation = FALSE;

	/*
	 * Conflict options error messages.
	 */
	if (opt_cnt > 1) {
		(void) fprintf(stderr, "\nConflicting options, only one of "
		    "the following options can be specified\n"
		    "in SMF:\n"
		    "\tprotocol=ALL\n"
		    "\tprotocol=protocol\n"
		    "\tdevice=devicename\n\n");
		usage();
	}
	opt_cnt = 0;

	while ((i = getopt(ac, av, "ac:p:s:t:l:")) != EOF) {
		switch (i) {
		case 'a':
			free(df_proto);
			df_proto = NULL;
			free(df_provider);
			df_provider = NULL;

			allflag = 1;
			opt_cnt++;
			break;

		case 'c':
			max_conns_allowed = atoi(optarg);
			break;

		case 'p':
			proto = optarg;
			df_allflag = 0;
			opt_cnt++;
			break;

		/*
		 * DSS: NFSv4 distributed stable storage.
		 *
		 * This is a Contracted Project Private interface, for
		 * the sole use of Sun Cluster HA-NFS. See PSARC/2006/313.
		 */
		case 's':
			if (strlen(optarg) < MAXPATHLEN) {
				/* first "-s" option encountered? */
				if (dss_pathnames == NULL) {
					/*
					 * Allocate maximum possible space
					 * required given cmdline arg count;
					 * "-s <path>" consumes two args.
					 */
					size_t sz = (ac / 2) * sizeof (char *);
					dss_pathnames = (char **)malloc(sz);
					if (dss_pathnames == NULL) {
						(void) fprintf(stderr, "%s: "
						    "dss paths malloc failed\n",
						    av[0]);
						exit(1);
					}
					(void) memset(dss_pathnames, 0, sz);
				}
				dss_pathnames[dss_npaths] = optarg;
				dss_npaths++;
			} else {
				(void) fprintf(stderr,
				    "%s: -s pathname too long.\n", av[0]);
			}
			break;

		case 't':
			provider = optarg;
			df_allflag = 0;
			opt_cnt++;
			break;

		case 'l':
			listen_backlog = atoi(optarg);
			break;

		case '?':
			usage();
			/* NOTREACHED */
		}
	}

	allflag = df_allflag;
	if (proto == NULL)
		proto = df_proto;
	if (provider == NULL)
		provider = df_provider;

	/*
	 * Conflict options error messages.
	 */
	if (opt_cnt > 1) {
		(void) fprintf(stderr, "\nConflicting options, only one of "
		    "the following options can be specified\n"
		    "on the command line:\n"
		    "\t-a\n"
		    "\t-p protocol\n"
		    "\t-t transport\n\n");
		usage();
	}

	if (proto != NULL &&
	    strncasecmp(proto, NC_UDP, strlen(NC_UDP)) == 0) {
		if (nfs_server_vers_max == NFS_V4) {
			if (nfs_server_vers_min == NFS_V4) {
				fprintf(stderr,
				    "NFS version 4 is not supported "
				    "with the UDP protocol.  Exiting\n");
				exit(3);
			} else {
				fprintf(stderr,
				    "NFS version 4 is not supported "
				    "with the UDP protocol.\n");
			}
		}
	}

	/*
	 * If there is exactly one more argument, it is the number of
	 * servers.
	 */
	if (optind == ac - 1) {
		maxservers = atoi(av[optind]);
		maxservers_set = 1;
	}
	/*
	 * If there are two or more arguments, then this is a usage error.
	 */
	else if (optind < ac - 1)
		usage();
	/*
	 * Check the ranges for min/max version specified
	 */
	else if ((nfs_server_vers_min > nfs_server_vers_max) ||
	    (nfs_server_vers_min < NFS_VERSMIN) ||
	    (nfs_server_vers_max > NFS_VERSMAX))
		usage();
	/*
	 * There are no additional arguments, and we haven't set maxservers
	 * explicitly via the config file, we use a default number of
	 * servers.  We will log this.
	 */
	else if (maxservers_set == 0)
		logmaxservers = 1;

	/*
	 * Basic Sanity checks on options
	 *
	 * max_conns_allowed must be positive, except for the special
	 * value of -1 which is used internally to mean unlimited, -1 isn't
	 * documented but we allow it anyway.
	 *
	 * maxservers must be positive
	 * listen_backlog must be positive or zero
	 */
	if (((max_conns_allowed != -1) && (max_conns_allowed <= 0)) ||
	    (listen_backlog < 0) || (maxservers <= 0)) {
		usage();
	}

	/*
	 * Set current dir to server root
	 */
	if (chdir(dir) < 0) {
		(void) fprintf(stderr, "%s:  ", MyName);
		perror(dir);
		exit(1);
	}

#ifndef DEBUG
	pipe_fd = daemonize_init();
#endif

	openlog(MyName, LOG_PID | LOG_NDELAY, LOG_DAEMON);

	/*
	 * establish our lock on the lock file and write our pid to it.
	 * exit if some other process holds the lock, or if there's any
	 * error in writing/locking the file.
	 */
	pid = _enter_daemon_lock(NFSD);
	switch (pid) {
	case 0:
		break;
	case -1:
		fprintf(stderr, "error locking for %s: %s\n", NFSD,
		    strerror(errno));
		exit(2);
	default:
		/* daemon was already running */
		exit(0);
	}

	/*
	 * If we've been given a list of paths to be used for distributed
	 * stable storage, and provided we're going to run a version
	 * that supports it, setup the DSS paths.
	 */
	if (dss_pathnames != NULL && nfs_server_vers_max >= DSS_VERSMIN) {
		if (dss_init(dss_npaths, dss_pathnames) != 0) {
			fprintf(stderr, "%s", "dss_init failed. Exiting.\n");
			exit(1);
		}
	}

	/*
	 * Block all signals till we spawn other
	 * threads.
	 */
	(void) sigfillset(&sgset);
	(void) thr_sigsetmask(SIG_BLOCK, &sgset, NULL);

	if (logmaxservers) {
		fprintf(stderr,
		    "Number of servers not specified. Using default of %d.\n",
		    maxservers);
	}

	/*
	 * Make sure to unregister any previous versions in case the
	 * user is reconfiguring the server in interesting ways.
	 */
	svc_unreg(NFS_PROGRAM, NFS_VERSION);
	svc_unreg(NFS_PROGRAM, NFS_V3);
	svc_unreg(NFS_PROGRAM, NFS_V4);
	svc_unreg(NFS_ACL_PROGRAM, NFS_ACL_V2);
	svc_unreg(NFS_ACL_PROGRAM, NFS_ACL_V3);

	/*
	 * Set up kernel RPC thread pool for the NFS server.
	 */
	if (nfssvcpool(maxservers)) {
		fprintf(stderr, "Can't set up kernel NFS service: %s. "
		    "Exiting.\n", strerror(errno));
		exit(1);
	}

	/*
	 * Set up blocked thread to do LWP creation on behalf of the kernel.
	 */
	if (svcwait(NFS_SVCPOOL_ID)) {
		fprintf(stderr, "Can't set up NFS pool creator: %s. Exiting.\n",
		    strerror(errno));
		exit(1);
	}

	/*
	 * RDMA start and stop thread.
	 * Per pool RDMA listener creation and
	 * destructor thread.
	 *
	 * start rdma services and block in the kernel.
	 * (only if proto or provider is not set to TCP or UDP)
	 */
	if ((proto == NULL) && (provider == NULL)) {
		if (svcrdma(NFS_SVCPOOL_ID, nfs_server_vers_min,
		    nfs_server_vers_max, nfs_server_delegation)) {
			fprintf(stderr,
			    "Can't set up RDMA creator thread : %s\n",
			    strerror(errno));
		}
	}

	/*
	 * Now open up for signal delivery
	 */

	(void) thr_sigsetmask(SIG_UNBLOCK, &sgset, NULL);
	sigset(SIGTERM, sigflush);
	sigset(SIGUSR1, quiesce);

	/*
	 * Build a protocol block list for registration.
	 */
	protobp0 = protobp = (struct protob *)malloc(sizeof (struct protob));
	protobp->serv = "NFS";
	protobp->versmin = nfs_server_vers_min;
	protobp->versmax = nfs_server_vers_max;
	protobp->program = NFS_PROGRAM;

	protobp->next = (struct protob *)malloc(sizeof (struct protob));
	protobp = protobp->next;
	protobp->serv = "NFS_ACL";		/* not used */
	protobp->versmin = nfs_server_vers_min;
	/* XXX - this needs work to get the version just right */
	protobp->versmax = (nfs_server_vers_max > NFS_ACL_V3) ?
	    NFS_ACL_V3 : nfs_server_vers_max;
	protobp->program = NFS_ACL_PROGRAM;
	protobp->next = (struct protob *)NULL;

	if (allflag) {
		if (do_all(protobp0, nfssvc) == -1) {
			fprintf(stderr, "setnetconfig failed : %s\n",
			    strerror(errno));
			exit(1);
		}
	} else if (proto) {
		/* there's more than one match for the same protocol */
		struct netconfig *nconf;
		NCONF_HANDLE *nc;
		bool_t	protoFound = FALSE;
		if ((nc = setnetconfig()) == (NCONF_HANDLE *) NULL) {
			fprintf(stderr, "setnetconfig failed : %s\n",
			    strerror(errno));
			goto done;
		}
		while (nconf = getnetconfig(nc)) {
			if (strcmp(nconf->nc_proto, proto) == 0) {
				protoFound = TRUE;
				do_one(nconf->nc_device, NULL,
				    protobp0, nfssvc);
			}
		}
		(void) endnetconfig(nc);
		if (protoFound == FALSE) {
			fprintf(stderr,
			    "couldn't find netconfig entry for protocol %s\n",
			    proto);
		}
	} else if (provider)
		do_one(provider, proto, protobp0, nfssvc);
	else {
		for (providerp = defaultproviders;
		    *providerp != NULL; providerp++) {
			provider = *providerp;
			do_one(provider, NULL, protobp0, nfssvc);
		}
	}
done:

	free(protobp);
	free(protobp0);

	if (num_fds == 0) {
		fprintf(stderr, "Could not start NFS service for any protocol."
		    " Exiting.\n");
		exit(1);
	}

	end_listen_fds = num_fds;

	/*
	 * nfsd is up and running as far as we are concerned.
	 */
	daemonize_fini(pipe_fd);

	/*
	 * Get rid of unneeded privileges.
	 */
	__fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION,
	    PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL);

	/*
	 * Poll for non-data control events on the transport descriptors.
	 */
	poll_for_action();

	/*
	 * If we get here, something failed in poll_for_action().
	 */
	return (1);
}
示例#7
0
文件: util.c 项目: budisfg/spine
void checkAsRoot() {
	#ifndef __CYGWIN__
	#ifdef SOLAR_PRIV
	priv_set_t *privset;
	char *p;

	/* Get the basic set */
	privset = priv_str_to_set("basic", ",", NULL);
	if (privset == NULL) {
		die("ERROR: Could not get basic privset from priv_str_to_set().");
	} else {
		p = priv_set_to_str(privset, ',', 0);
		SPINE_LOG_DEBUG(("DEBUG: Basic privset is: '%s'.", p != NULL ? p : "Unknown"));
	}

	/* Add priviledge to send/receive ICMP packets */
	if (priv_addset(privset, PRIV_NET_ICMPACCESS) < 0 ) {
		SPINE_LOG_DEBUG(("Warning: Addition of PRIV_NET_ICMPACCESS to privset failed: '%s'.", strerror(errno)));
	}

	/* Compute the set of privileges that are never needed */
	priv_inverse(privset);

	/* Remove the set of unneeded privs from Permitted (and by
	 * implication from Effective) */
	if (setppriv(PRIV_OFF, PRIV_PERMITTED, privset) < 0) {
		SPINE_LOG_DEBUG(("Warning: Dropping privileges from PRIV_PERMITTED failed: '%s'.", strerror(errno)));
	}

	/* Remove unneeded priv set from Limit to be safe */
	if (setppriv(PRIV_OFF, PRIV_LIMIT, privset) < 0) {
		SPINE_LOG_DEBUG(("Warning: Dropping privileges from PRIV_LIMIT failed: '%s'.", strerror(errno)));
	}

	boolean_t pe = priv_ineffect(PRIV_NET_ICMPACCESS);
	SPINE_LOG_DEBUG(("DEBUG: Privilege PRIV_NET_ICMPACCESS is: '%s'.", pe != 0 ? "Enabled" : "Disabled"));

	set.icmp_avail = pe;

	/* Free the privset */
	priv_freeset(privset);
	free(p);
	#else
	if (hasCaps() != TRUE) {
		seteuid(0);
	
		if (geteuid() != 0) {
			SPINE_LOG_DEBUG(("WARNING: Spine NOT running asroot.  This is required if using ICMP.  Please run \"chmod +s;chown root:root spine\" to resolve."));
			set.icmp_avail = FALSE;
		}else{
			SPINE_LOG_DEBUG(("DEBUG: Spine is running asroot."));
			set.icmp_avail = TRUE;
			seteuid(getuid());
		}
	} else {
		SPINE_LOG_DEBUG(("DEBUG: Spine has cap_net_raw capability."));
		set.icmp_avail = TRUE;
	}
	#endif
	#endif
}
示例#8
0
文件: mountd.c 项目: andreiw/polaris
int
main(int argc, char *argv[])
{
	int	pid;
	int	c;
	int	rpc_svc_mode = RPC_SVC_MT_AUTO;
	int	maxthreads;
	int	maxrecsz = RPC_MAXDATASIZE;
	bool_t	exclbind = TRUE;
	bool_t	can_do_mlp;
	long	thr_flags = (THR_NEW_LWP|THR_DAEMON);

	/*
	 * Mountd requires uid 0 for:
	 *	/etc/rmtab updates (we could chown it to daemon)
	 *	/etc/dfs/dfstab reading (it wants to lock out share which
	 *		doesn't do any locking before first truncate;
	 *		NFS share does; should use fcntl locking instead)
	 *	Needed privileges:
	 *		auditing
	 *		nfs syscall
	 *		file dac search (so it can stat all files)
	 *	Optional privileges:
	 *		MLP
	 */
	can_do_mlp = priv_ineffect(PRIV_NET_BINDMLP);
	if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, -1, -1,
	    PRIV_SYS_NFS, PRIV_PROC_AUDIT, PRIV_FILE_DAC_SEARCH,
	    can_do_mlp ? PRIV_NET_BINDMLP : NULL, NULL) == -1) {
		(void) fprintf(stderr,
			"%s must be run as with sufficient privileges\n",
			argv[0]);
		exit(1);
	}

	maxthreads = 0;

	while ((c = getopt(argc, argv, "vrm:")) != EOF) {
		switch (c) {
		case 'v':
			verbose++;
			break;
		case 'r':
			rejecting = 1;
			break;
		case 'm':
			maxthreads = atoi(optarg);
			if (maxthreads < 1) {
				(void) fprintf(stderr,
	"%s: must specify positive maximum threads count, using default\n",
						argv[0]);
				maxthreads = 0;
			}
			break;
		}
	}

	/*
	 * Read in the NFS version values from config file.
	 */
	if ((defopen(NFSADMIN)) == 0) {
		char *defval;
		int defvers;

		if ((defval = defread("NFS_SERVER_VERSMIN=")) != NULL) {
			errno = 0;
			defvers = strtol(defval, (char **)NULL, 10);
			if (errno == 0) {
				mount_vers_min = defvers;
				/*
				 * special because NFSv2 is
				 * supported by mount v1 & v2
				 */
				if (defvers == NFS_VERSION)
					mount_vers_min = MOUNTVERS;
			}
		}
		if ((defval = defread("NFS_SERVER_VERSMAX=")) != NULL) {
			errno = 0;
			defvers = strtol(defval, (char **)NULL, 10);
			if (errno == 0) {
				mount_vers_max = defvers;
			}
		}

		/* close defaults file */
		defopen(NULL);
	}

	/*
	 * Sanity check versions,
	 * even though we may get versions > MOUNTVERS3, we still need
	 * to start nfsauth service, so continue on regardless of values.
	 */
	if (mount_vers_min > mount_vers_max) {
		syslog(LOG_NOTICE, "NFS_SERVER_VERSMIN > NFS_SERVER_VERSMAX");
		mount_vers_max = mount_vers_min;
	}
	(void) setlocale(LC_ALL, "");
	(void) rwlock_init(&sharetab_lock, USYNC_THREAD, NULL);
	(void) mutex_init(&mnttab_lock, USYNC_THREAD, NULL);
	netgroup_init();

#if !defined(TEXT_DOMAIN)
#define	TEXT_DOMAIN "SYS_TEST"
#endif
	(void) textdomain(TEXT_DOMAIN);

	/* Don't drop core if the NFS module isn't loaded. */
	(void) signal(SIGSYS, SIG_IGN);

	(void) signal(SIGHUP, sigexit);
	(void) signal(SIGCLD, sigexit);

	switch (fork()) {
	case 0:		/* child */
		break;
	case -1:
		perror("mountd: can't fork");
		exit(1);
	default:	/* parent */
		for (;;)
			(void) pause();
		/* NOTREACHED */
	}

	(void) signal(SIGHUP, SIG_DFL);
	(void) signal(SIGCLD, SIG_DFL);

	/*
	 * If we coredump it'll be in /core
	 */
	if (chdir("/") < 0)
		syslog(LOG_ERR, "chdir /: %m");

	/*
	 * Close existing file descriptors, open "/dev/null" as
	 * standard input, output, and error, and detach from
	 * controlling terminal.
	 */
	closefrom(0);
	(void) open("/dev/null", O_RDONLY);
	(void) open("/dev/null", O_WRONLY);
	(void) dup(1);
	(void) setsid();

	openlog("mountd", LOG_PID, LOG_DAEMON);

	/*
	 * establish our lock on the lock file and write our pid to it.
	 * exit if some other process holds the lock, or if there's any
	 * error in writing/locking the file.
	 */
	pid = _enter_daemon_lock(MOUNTD);
	switch (pid) {
	case 0:
		break;
	case -1:
		syslog(LOG_ERR, "error locking for %s: %s", MOUNTD,
		    strerror(errno));
		exit(2);
	default:
		/* daemon was already running */
		exit(0);
	}

	audit_mountd_setup();	/* BSM */

	/*
	 * Tell RPC that we want automatic thread mode.
	 * A new thread will be spawned for each request.
	 */
	if (!rpc_control(RPC_SVC_MTMODE_SET, &rpc_svc_mode)) {
		syslog(LOG_ERR, "unable to set automatic MT mode");
		exit(1);
	}

	/*
	 * Enable non-blocking mode and maximum record size checks for
	 * connection oriented transports.
	 */
	if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrecsz)) {
		syslog(LOG_INFO, "unable to set RPC max record size");
	}

	/*
	 * Prevent our non-priv udp and tcp ports bound w/wildcard addr
	 * from being hijacked by a bind to a more specific addr.
	 */
	if (!rpc_control(__RPC_SVC_EXCLBIND_SET, &exclbind)) {
		syslog(LOG_INFO,  "warning: unable to set udp/tcp EXCLBIND");
	}

	/*
	 * If the -m argument was specified, then set the
	 * maximum number of threads to the value specified.
	 */
	if (maxthreads > 0 && !rpc_control(RPC_SVC_THRMAX_SET, &maxthreads)) {
		syslog(LOG_ERR, "unable to set maxthreads");
		exit(1);
	}

	/*
	 * Make sure to unregister any previous versions in case the
	 * user is reconfiguring the server in interesting ways.
	 */
	svc_unreg(MOUNTPROG, MOUNTVERS);
	svc_unreg(MOUNTPROG, MOUNTVERS_POSIX);
	svc_unreg(MOUNTPROG, MOUNTVERS3);

	/*
	 * Create the nfsauth thread with same signal disposition
	 * as the main thread. We need to create a separate thread
	 * since mountd() will be both an RPC server (for remote
	 * traffic) _and_ a doors server (for kernel upcalls).
	 */
	if (thr_create(NULL, 0, nfsauth_svc, 0, thr_flags, &nfsauth_thread)) {
		syslog(LOG_ERR, gettext("Failed to create NFSAUTH svc thread"));
		exit(2);
	}

	/*
	 * Create datagram and connection oriented services
	 */
	if (mount_vers_max >= MOUNTVERS) {
		if (svc_create(mnt, MOUNTPROG, MOUNTVERS, "datagram_v") == 0) {
			syslog(LOG_ERR,
				"couldn't register datagram_v MOUNTVERS");
			exit(1);
		}
		if (svc_create(mnt, MOUNTPROG, MOUNTVERS, "circuit_v") == 0) {
			syslog(LOG_ERR,
				"couldn't register circuit_v MOUNTVERS");
			exit(1);
		}
	}
	if (mount_vers_max >= MOUNTVERS_POSIX) {
		if (svc_create(mnt, MOUNTPROG, MOUNTVERS_POSIX,
							"datagram_v") == 0) {
			syslog(LOG_ERR,
				"couldn't register datagram_v MOUNTVERS_POSIX");
			exit(1);
		}
		if (svc_create(mnt, MOUNTPROG, MOUNTVERS_POSIX,
							"circuit_v") == 0) {
			syslog(LOG_ERR,
				"couldn't register circuit_v MOUNTVERS_POSIX");
			exit(1);
		}
	}

	if (mount_vers_max >= MOUNTVERS3) {
		if (svc_create(mnt, MOUNTPROG, MOUNTVERS3, "datagram_v") == 0) {
			syslog(LOG_ERR,
				"couldn't register datagram_v MOUNTVERS3");
			exit(1);
		}
		if (svc_create(mnt, MOUNTPROG, MOUNTVERS3, "circuit_v") == 0) {
			syslog(LOG_ERR,
				"couldn't register circuit_v MOUNTVERS3");
			exit(1);
		}
	}

	/*
	 * Start serving
	 */
	rmtab_load();
	(void) kill(getppid(), SIGHUP);

	/* Get rid of the most dangerous basic privileges. */
	__fini_daemon_priv(PRIV_PROC_EXEC, PRIV_PROC_INFO, PRIV_PROC_SESSION,
	    (char *)NULL);

	svc_run();
	syslog(LOG_ERR, "Error: svc_run shouldn't have returned");
	abort();
	/* NOTREACHED */
	return (0);
}
示例#9
0
文件: zfs_util.c 项目: derzzle/zfs
static int
zpool_import_by_guid(uint64_t searchguid)
{
	int err = 0;
	nvlist_t *pools = NULL;
	nvpair_t *elem;
	nvlist_t *config;
	nvlist_t *found_config = NULL;
	nvlist_t *policy = NULL;
	boolean_t first;
	int flags = ZFS_IMPORT_NORMAL;
	uint32_t rewind_policy = ZPOOL_NO_REWIND;
	uint64_t pool_state, txg = -1ULL;
	importargs_t idata = { 0 };
#ifdef ZFS_AUTOIMPORT_ZPOOL_STATUS_OK_ONLY
	char *msgid;
	zpool_status_t reason;
	zpool_errata_t errata;
#endif

	if ((g_zfs = libzfs_init()) == NULL)
		return (1);

	idata.unique = B_TRUE;

	/* In the future, we can capture further policy and include it here */
	if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
	    nvlist_add_uint64(policy, ZPOOL_REWIND_REQUEST_TXG, txg) != 0 ||
	    nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
		goto error;

	if (!priv_ineffect(PRIV_SYS_CONFIG)) {
		printf("cannot discover pools: permission denied\n");
		nvlist_free(policy);
		return (1);
	}

	idata.guid = searchguid;

	pools = zpool_search_import(g_zfs, &idata);

	if (pools == NULL && idata.exists) {
		printf("cannot import '%llu': a pool with that guid is already "
		    "created/imported\n", searchguid);
		err = 1;
	} else if (pools == NULL) {
		printf("cannot import '%llu': no such pool available\n",
		    searchguid);
		err = 1;
	}

	if (err == 1) {
		nvlist_free(policy);
		return (1);
	}

	/*
	 * At this point we have a list of import candidate configs. Even though
	 * we were searching by guid, we still need to post-process the list to
	 * deal with pool state.
	 */
	err = 0;
	elem = NULL;
	first = B_TRUE;
	while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {

		verify(nvpair_value_nvlist(elem, &config) == 0);

		verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
		    &pool_state) == 0);
		if (pool_state == POOL_STATE_DESTROYED)
			continue;

		verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY,
		    policy) == 0);

		uint64_t guid;

		/*
		 * Search for a pool by guid.
		 */
		verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
		    &guid) == 0);

		if (guid == searchguid)
			found_config = config;
	}

	/*
	 * If we were searching for a specific pool, verify that we found a
	 * pool, and then do the import.
	 */
	if (err == 0) {
		if (found_config == NULL) {
			printf("cannot import '%llu': no such pool available\n",
			    searchguid);
			err = B_TRUE;
		} else {
#ifdef ZFS_AUTOIMPORT_ZPOOL_STATUS_OK_ONLY
			reason = zpool_import_status(config, &msgid, &errata);
			if (reason == ZPOOL_STATUS_OK)
				err |= do_import(found_config, NULL, NULL, NULL,
				    flags);
			else
				err = 1;
#else
			err |= do_import(found_config, NULL, NULL, NULL, flags);
#endif
		}
	}

error:
	nvlist_free(pools);
	nvlist_free(policy);
	libzfs_fini(g_zfs);

	return (err ? 1 : 0);
}
示例#10
0
/*
 * If the system is labeled then we need to
 * have a uniquely-named auto_home map for each zone.
 * The maps are made unique by appending the zonename.
 * The home directory is made unique by prepending /zone/<zonename>
 * for each zone that is dominated by the current zone.
 * The current zone's home directory mount point is not changed.
 *
 * For each auto_home_<zonename> a default template map is created
 * only if it doesn't exist yet. The default entry is used to declare
 * local home directories created within each zone. For example:
 *
 *	+auto_home_public
 *      * -fstype=lofs :/zone/public/export/home/&
 */
static void
loadzone_maps(char *mntpnt, char *map, char *opts, char **stack, char ***stkptr)
{
	zoneid_t *zids = NULL;
	zoneid_t my_zoneid;
	uint_t nzents_saved;
	uint_t nzents;
	int i;

	if (!priv_ineffect(PRIV_SYS_MOUNT))
		return;

	if (zone_list(NULL, &nzents) != 0) {
		return;
	}
	my_zoneid = getzoneid();
again:
	if (nzents == 0)
		return;

	zids = malloc(nzents * sizeof (zoneid_t));
	nzents_saved = nzents;

	if (zone_list(zids, &nzents) != 0) {
		free(zids);
		return;
	}
	if (nzents != nzents_saved) {
		/* list changed, try again */
		free(zids);
		goto again;
	}

	for (i = 0; i < nzents; i++) {
		char zonename[ZONENAME_MAX];
		char zoneroot[MAXPATHLEN];

		if (getzonenamebyid(zids[i], zonename, ZONENAME_MAX) != -1) {
			char appended_map[MAXPATHLEN];
			char prepended_mntpnt[MAXPATHLEN];
			char map_path[MAXPATHLEN];
			int fd;

			(void) snprintf(appended_map, sizeof (appended_map),
			    "%s_%s", map, zonename);

			/* for current zone, leave mntpnt alone */
			if (zids[i] != my_zoneid) {
				(void) snprintf(prepended_mntpnt,
				    sizeof (prepended_mntpnt),
				    "/zone/%s%s", zonename, mntpnt);
				if (zone_getattr(zids[i], ZONE_ATTR_ROOT,
				    zoneroot, sizeof (zoneroot)) == -1)
					continue;
			} else {
				(void) strcpy(prepended_mntpnt, mntpnt);
				zoneroot[0] = '\0';
			}

			dirinit(prepended_mntpnt, appended_map, opts, 0, stack,
			    stkptr);
			/*
			 * Next create auto_home_<zone> maps for each zone
			 */

			(void) snprintf(map_path, sizeof (map_path),
			    "/etc/%s", appended_map);
			/*
			 * If the map file doesn't exist create a template
			 */
			if ((fd = open(map_path, O_RDWR | O_CREAT | O_EXCL,
			    S_IRUSR | S_IWUSR | S_IRGRP| S_IROTH)) != -1) {
				int len;
				char map_rec[MAXPATHLEN];

				len = snprintf(map_rec, sizeof (map_rec),
				    "+%s\n*\t-fstype=lofs\t:%s/export/home/&\n",
				    appended_map, zoneroot);
				if (len <= sizeof (map_rec))
					(void) write(fd, map_rec, len);
				(void) close(fd);
			}
		}
	}
	free(zids);
}
示例#11
0
int
main(int argc, char *argv[])
{
	char c;
	pool_conf_t *conf = NULL;
	const char *static_conf_loc;

	(void) getpname(argv[0]);
	(void) setlocale(LC_ALL, "");
	(void) textdomain(TEXT_DOMAIN);


	while ((c = getopt(argc, argv, "cdensx")) != EOF) {
		switch (c) {
		case 'c':	/* Create (or modify) system configuration */
			Cflag++;
			break;
		case 'd':	/* Disable the pools facility */
			Dflag++;
			break;
		case 'e':	/* Enable the pools facility */
			Eflag++;
			break;
		case 'n':	/* Don't actually do anything */
			Nflag++;
			break;
		case 's':	/* Update the submitted configuration */
			Sflag++;
			break;
		case 'x':	/* Delete current system configuration */
			Xflag++;
			break;
		case '?':
		default:
			usage();
			/*NOTREACHED*/
		}
	}

	/*
	 * Not all flags can be used at the same time.
	 */
	if ((Cflag || Sflag || Dflag || Eflag) && Xflag)
		usage();

	if ((Dflag || Eflag) && (Cflag || Sflag || Xflag))
		usage();

	if (Dflag && Eflag)
		usage();

	argc -= optind;
	argv += optind;

	if (! (Cflag || Sflag)) {
		if (argc != 0)
			usage();
	} else {
		if (argc == 0)
			static_conf_loc = pool_static_location();
		else if (argc == 1)
			static_conf_loc = argv[0];
		else
			usage();
	}

	if (!Nflag && (Cflag + Dflag + Eflag + Xflag != 0) &&
	    !priv_ineffect(PRIV_SYS_RES_CONFIG))
		die(gettext(ERR_PERMISSIONS));

	if (Dflag) {
		if (pool_set_status(POOL_DISABLED) != PO_SUCCESS)
			die(gettext(ERR_DISABLE));
	} else if (Eflag) {
		if (pool_set_status(POOL_ENABLED) != PO_SUCCESS) {
			if (errno == EEXIST)
				die(gettext(ERR_ENABLE
				    ": System has active processor sets\n"));
			else
				die(gettext(ERR_ENABLE));
		}
	} else {
		if ((conf = pool_conf_alloc()) == NULL)
			die(gettext(ERR_NOMEM));

		if (Cflag + Sflag + Xflag == 0) {
			/*
			 * No flags means print current system configuration
			 */
			config_print(conf);
		} else if (!Nflag && Xflag) {
			/*
			 * Destroy active pools configuration and
			 * remove the state file.
			 */
			config_destroy(conf);
		} else {
			/*
			 * Commit a new configuration.
			 */
			if (Cflag)
				config_commit(conf, static_conf_loc);
			else {
				/*
				 * Dump the dynamic state to the
				 * specified location
				 */
				if (!Nflag && Sflag) {
					if (pool_conf_open(conf,
					    pool_dynamic_location(), PO_RDONLY)
					!= PO_SUCCESS)
						die(gettext(ERR_OPEN_DYNAMIC),
						get_errstr());
					if (pool_conf_export(conf,
					    static_conf_loc, POX_NATIVE) !=
					    PO_SUCCESS)
						die(gettext(ERR_EXPORT_DYNAMIC),
						static_conf_loc, get_errstr());
					(void) pool_conf_close(conf);
				}
			}
		}
		pool_conf_free(conf);
	}
	return (E_PO_SUCCESS);
}