コード例 #1
0
ファイル: ipmgmt_main.c プロジェクト: 0xffea/illumos-gate
/*
 * Set the uid of this daemon to the "netadm" user. Finish the following
 * operations before setuid() because they need root privileges:
 *
 *    - create the /etc/svc/volatile/ipadm directory;
 *    - change its uid/gid to "netadm"/"netadm";
 */
static int
ipmgmt_init_privileges()
{
	struct stat	statbuf;
	int		err;

	/* create the IPADM_TMPFS_DIR directory */
	if (stat(IPADM_TMPFS_DIR, &statbuf) < 0) {
		if (mkdir(IPADM_TMPFS_DIR, (mode_t)0755) < 0) {
			err = errno;
			goto fail;
		}
	} else {
		if ((statbuf.st_mode & S_IFMT) != S_IFDIR) {
			err = ENOTDIR;
			goto fail;
		}
	}

	if ((chmod(IPADM_TMPFS_DIR, 0755) < 0) ||
	    (chown(IPADM_TMPFS_DIR, UID_NETADM, GID_NETADM) < 0)) {
		err = errno;
		goto fail;
	}

	/*
	 * initialize any NGZ specific network information before dropping
	 * privileges. We need these privileges to plumb IP interfaces handed
	 * down from the GZ (for dlpi_open() etc.) and also to configure the
	 * address itself (for any IPI_PRIV ioctls like SLIFADDR)
	 */
	ipmgmt_ngz_init();

	/*
	 * Apply all protocol module properties. We need to apply all protocol
	 * properties before we drop root privileges.
	 */
	ipmgmt_init_prop();

	/*
	 * limit the privileges of this daemon and set the uid of this
	 * daemon to UID_NETADM
	 */
	if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, UID_NETADM,
	    GID_NETADM, NULL) == -1) {
		err = EPERM;
		goto fail;
	}

	return (0);
fail:
	(void) ipmgmt_log(LOG_ERR, "failed to initialize the daemon: %s",
	    strerror(err));
	return (err);
}
コード例 #2
0
ファイル: sped.c プロジェクト: CoryXie/opensolaris
/* ARGSUSED */
int
main(int argc, char **argv)
{
	MyName = argv[0];

	(void) setlocale(LC_ALL, "");
	(void) textdomain(TEXT_DOMAIN);

	(void) _create_daemon_lock(SPED, DAEMON_UID, DAEMON_GID);

	/*
	 * Initialize the daemon to basic + sys_nfs
	 */
	if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET,
	    DAEMON_UID, DAEMON_GID, PRIV_SYS_NFS, (char *)NULL) == -1) {
		(void) fprintf(stderr, gettext("%s PRIV_SYS_NFS privilege "
		    "missing\n"), MyName);
		exit(1);
	}

	daemonize();

	/* Basic privileges we don't need, remove from E/P. */
	__fini_daemon_priv(PRIV_PROC_EXEC, PRIV_PROC_FORK, PRIV_FILE_LINK_ANY,
	    PRIV_PROC_SESSION, PRIV_PROC_INFO, (char *)NULL);

	switch (_enter_daemon_lock(SPED)) {
		case 0:
			break;

		case -1:
			syslog(LOG_ERR, "error locking for %s: %s", SPED,
			    strerror(errno));
			exit(3);

		default:
			/* daemon was already running */
			exit(0);
	}
	openlog(MyName, LOG_PID | LOG_NDELAY, LOG_DAEMON);

	/* Initialize daemon subsystems */
	daemon_init();

	/* start services */
	return (start_svcs());
}
コード例 #3
0
ファイル: libvirtd.c プロジェクト: 6WIND/libvirt
static int
daemonSetupPrivs(void)
{
    chown("/var/run/libvirt", SYSTEM_UID, SYSTEM_UID);

    if (__init_daemon_priv(PU_RESETGROUPS | PU_CLEARLIMITSET,
                           SYSTEM_UID, SYSTEM_UID, PRIV_XVM_CONTROL, NULL)) {
        VIR_ERROR(_("additional privileges are required"));
        return -1;
    }

    if (priv_set(PRIV_OFF, PRIV_ALLSETS, PRIV_FILE_LINK_ANY, PRIV_PROC_INFO,
                 PRIV_PROC_SESSION, PRIV_PROC_EXEC, PRIV_PROC_FORK, NULL)) {
        VIR_ERROR(_("failed to set reduced privileges"));
        return -1;
    }

    return 0;
}
コード例 #4
0
ファイル: dlmgmt_main.c プロジェクト: alhazred/onarm
/*
 * Set the uid of this daemon to the "dladm" user. Finish the following
 * operations before setuid() because they need root privileges:
 *
 *    - create the /etc/svc/volatile/dladm directory;
 *    - change its uid/gid to "dladm"/"sys";
 *    - open the dld control node
 */
static int
dlmgmt_init_privileges()
{
	struct stat	statbuf;

	/*
	 * Create the DLMGMT_TMPFS_DIR directory.
	 */
	if (stat(DLMGMT_TMPFS_DIR, &statbuf) < 0) {
		if (mkdir(DLMGMT_TMPFS_DIR, (mode_t)0755) < 0)
			return (errno);
	} else {
		if ((statbuf.st_mode & S_IFMT) != S_IFDIR)
			return (ENOTDIR);
	}

	if ((chmod(DLMGMT_TMPFS_DIR, 0755) < 0) ||
	    (chown(DLMGMT_TMPFS_DIR, UID_DLADM, GID_SYS) < 0)) {
		return (EPERM);
	}

	/*
	 * When dlmgmtd is started at boot, "ALL" privilege is required
	 * to open the dld control node.
	 */
	if ((dld_control_fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
		return (errno);

	if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, UID_DLADM,
	    GID_SYS, NULL) == -1) {
		(void) close(dld_control_fd);
		dld_control_fd = -1;
		return (EPERM);
	}

	return (0);
}
コード例 #5
0
ファイル: nfsd.c プロジェクト: CadeLaRen/illumos-gate
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);
}
コード例 #6
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);
}
コード例 #7
0
ファイル: rmvolmgr.c プロジェクト: AlainODea/illumos-gate
static int
rmvolmgr(int argc, char **argv)
{
	const char	*opts = "chnsv";
	DBusError	error;
	boolean_t	daemonize;
	rmm_error_t	rmm_error;
	int		c;

	while ((c = getopt(argc, argv, opts)) != EOF) {
		switch (c) {
		case 'c':
			opt_c = B_TRUE;
			break;
		case 'n':
			opt_n = B_TRUE;
			break;
		case 's':
			opt_s = B_TRUE;
			break;
		case 'v':
			rmm_debug = 1;
			break;
		case '?':
		case 'h':
			usage();
			return (0);
		default:
			usage();
			return (1);
		}
	}

	if (opt_s) {
		if (geteuid() != 0) {
			(void) fprintf(stderr,
			    gettext("system instance must have euid 0\n"));
			return (1);
		}

		get_smf_properties();

		if (opt_c) {
			rmm_vold_actions_enabled = B_FALSE;
		}
		if (opt_n) {
			rmm_vold_mountpoints_enabled = B_FALSE;
		}


		/*
		 * Drop unused privileges. Remain root for HAL interaction
		 * and to create legacy symlinks.
		 *
		 * Need PRIV_FILE_DAC_WRITE to write to users'
		 * /tmp/.removable/notify* files.
		 */
		if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET,
		    0, 0,
		    rmm_vold_actions_enabled ? PRIV_FILE_DAC_WRITE : NULL,
		    NULL) == -1) {
			(void) fprintf(stderr,
			    gettext("failed to drop privileges"));
			return (1);
		}
		/* basic privileges we don't need */
		(void) priv_set(PRIV_OFF, PRIV_PERMITTED, PRIV_PROC_EXEC,
		    PRIV_PROC_INFO, PRIV_FILE_LINK_ANY, PRIV_PROC_SESSION,
		    NULL);

	} else {
		if (opt_c) {
			rmm_vold_actions_enabled = B_FALSE;
		}
		if (opt_n) {
			rmm_vold_mountpoints_enabled = B_FALSE;
		}
	}

	daemonize = (getenv("RMVOLMGR_NODAEMON") == NULL);

	if (daemonize && daemon(0, 0) < 0) {
		dprintf("daemonizing failed: %s", strerror(errno));
		return (1);
	}

	if (opt_s) {
		__fini_daemon_priv(PRIV_PROC_FORK, NULL);
	}

	/*
	 * signal mainloop integration using pipes
	 */
	if (pipe(sigexit_pipe) != 0) {
		dprintf("pipe failed %s\n", strerror(errno));
		return (1);
	}
	sigexit_ioch = g_io_channel_unix_new(sigexit_pipe[0]);
	if (sigexit_ioch == NULL) {
		dprintf("g_io_channel_unix_new failed\n");
		return (1);
	}
	g_io_add_watch(sigexit_ioch, G_IO_IN, sigexit_ioch_func, NULL);
	signal(SIGTERM, sigexit);
	signal(SIGINT, sigexit);
	signal(SIGHUP, SIG_IGN);
	signal(SIGUSR1, SIG_IGN);
	signal(SIGUSR2, SIG_IGN);

	if ((hal_ctx = rmm_hal_init(rmm_device_added, rmm_device_removed,
	    rmm_property_modified, rmm_device_condition,
	    &error, &rmm_error)) == NULL) {
		dbus_error_free(&error);
		return (1);
	}

	/* user instance should claim devices */
	if (!opt_s) {
		if (!rmm_hal_claim_branch(hal_ctx, HAL_BRANCH_LOCAL)) {
			(void) fprintf(stderr,
			    gettext("cannot claim branch\n"));
			return (1);
		}
	}

	rmm_mount_all();

	if ((mainloop = g_main_loop_new(NULL, B_FALSE)) == NULL) {
		dprintf("Cannot create main loop\n");
		return (1);
	}

	g_main_loop_run(mainloop);

	return (0);
}
コード例 #8
0
ファイル: nfs4cbd.c プロジェクト: CoryXie/opensolaris
int
main(int argc, char *argv[])
{
	int pid;
	int i;
	struct protob *protobp;
	struct flock f;
	pid_t pi;
	struct svcpool_args cb_svcpool;

	MyName = "nfs4cbd";
	Mysvc4 = nfs4svc;

#ifndef	DEBUG
	/*
	 * 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();
#endif

	/*
	 * create a child to continue our work
	 * Parent's exit will tell mount command we're ready to go
	 */
	if ((pi = fork()) > 0) {
		exit(0);
	}

	if (pi == -1) {
		(void) syslog(LOG_ERR,
			"Could not start NFS4_CALLBACK service");
		exit(1);
	}

	(void) _create_daemon_lock(NFS4CBD, DAEMON_UID, DAEMON_GID);

	svcsetprio();

	if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET,
	    DAEMON_UID, DAEMON_GID, PRIV_SYS_NFS, (char *)NULL) == -1) {
		(void) fprintf(stderr, "%s must be run with sufficient"
			" privileges\n", argv[0]);
		exit(1);
	}
	/* Basic privileges we don't need, remove from E/P. */
	__fini_daemon_priv(PRIV_PROC_EXEC, PRIV_PROC_FORK, PRIV_FILE_LINK_ANY,
	    PRIV_PROC_SESSION, PRIV_PROC_INFO, (char *)NULL);

	/*
	 * 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(NFS4CBD);
	switch (pid) {
	case 0:
		break;
	case -1:
		syslog(LOG_ERR, "error locking for %s: %s", NFS4CBD,
		    strerror(errno));
		exit(2);
	default:
		/* daemon was already running */
		exit(0);
	}

	openlog(MyName, LOG_PID | LOG_NDELAY, LOG_DAEMON);

	cb_svcpool.id = NFS_CB_SVCPOOL_ID;
	cb_svcpool.maxthreads = 0;
	cb_svcpool.redline = 0;
	cb_svcpool.qsize = 0;
	cb_svcpool.timeout = 0;
	cb_svcpool.stksize = 0;
	cb_svcpool.max_same_xprt = 0;

	/* create a SVC_POOL for the nfsv4 callback deamon */
	if (_nfssys(SVCPOOL_CREATE, &cb_svcpool)) {
		(void) syslog(LOG_ERR, "can't setup NFS_CB SVCPOOL: Exiting");
		exit(1);
	}

	/*
	 * Set up blocked thread to do LWP creation on behalf of the kernel.
	 */
	if (svcwait(NFS_CB_SVCPOOL_ID)) {
		(void) syslog(LOG_ERR,
		    "Can't set up NFS_CB LWP creator: Exiting");
		exit(1);
	}


	/*
	 * Build a protocol block list for registration.
	 */
	protobp = (struct protob *)malloc(sizeof (struct protob));
	protobp->serv = "NFS4_CALLBACK";
	protobp->versmin = NFS_CB;
	protobp->versmax = NFS_CB;
	protobp->program = NFS4_CALLBACK;
	protobp->next = NULL;

	if (do_all(protobp, NULL, 0) == -1) {
		exit(1);
	}

	free(protobp);

	if (num_fds == 0) {
		(void) syslog(LOG_ERR,
		"Could not start NFS4_CALLBACK service for any protocol");
		exit(1);
	}

	end_listen_fds = num_fds;
	/*
	 * 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);
}
コード例 #9
0
ファイル: ilbd_main.c プロジェクト: CoryXie/opensolaris
int
main(int argc, char **argv)
{
	int	s;
	int	c;

	(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define	TEXT_DOMAIN "SYS_TEST"
#endif
	static const char daemon_dir[] = DAEMON_DIR;

	(void) textdomain(TEXT_DOMAIN);

	while ((c = getopt(argc, argv, ":V?d(debug)")) != -1) {
		switch ((char)c) {
		case '?': Usage(argv[0]);
			/* not reached */
			break;
		case 'V': print_version(argv[0]);
			/* not reached */
			break;
		case 'd': ilbd_enable_debug();
			break;
		default: Usage(argv[0]);
			/* not reached */
			break;
		}
	}

	/*
	 * Whenever the daemon starts, it needs to start with a clean
	 * slate in the kernel. We need sys_ip_config privilege for
	 * this.
	 */
	ilbd_reset_kernel_state();

	/* Increase the limit on the number of file descriptors. */
	set_rlim();

	/*
	 * ilbd daemon starts off as root, just so it can create
	 * /var/run/daemon if one does not exist. After that is done
	 * the daemon switches to "daemon" uid. This is similar to what
	 * rpcbind does.
	 */
	if (mkdir(daemon_dir, DAEMON_DIR_MODE) == 0 || errno == EEXIST) {
		(void) chmod(daemon_dir, DAEMON_DIR_MODE);
		(void) chown(daemon_dir, DAEMON_UID, DAEMON_GID);
	} else {
		perror("main: mkdir failed");
		exit(errno);
	}
	/*
	 * Now lets switch ilbd as uid = daemon, gid = daemon with a
	 * trimmed down privilege set
	 */
	if (__init_daemon_priv(PU_RESETGROUPS | PU_LIMITPRIVS | PU_INHERITPRIVS,
	    DAEMON_UID, DAEMON_GID, PRIV_PROC_OWNER, PRIV_PROC_AUDIT,
	    PRIV_NET_ICMPACCESS, PRIV_SYS_IP_CONFIG, NULL) == -1) {
		(void) fprintf(stderr, "Insufficient privileges\n");
		exit(EXIT_FAILURE);
	}

	/*
	 * Opens a PF_UNIX socket to the client. No privilege needed
	 * for this.
	 */
	s = ilbd_create_client_socket();

	/*
	 * Daemonify if ilbd is not running with -d option
	 * Need proc_fork privilege for this
	 */
	if (!is_debugging_on()) {
		logdebug("daemonizing...");
		if (daemon(0, 0) != 0) {
			logperror("daemon failed");
			exit(EXIT_FAILURE);
		}
	}
	(void) priv_set(PRIV_OFF, PRIV_INHERITABLE, PRIV_PROC_OWNER,
	    PRIV_PROC_AUDIT, NULL);

	/* if daemonified then set up syslog */
	if (!is_debugging_on())
		openlog("ilbd", LOG_PID, LOG_DAEMON);

	i_ilbd_setup_lists();

	main_loop(s);

	/*
	 * if we come here, then we experienced an error or a shutdown
	 * indicator, so clean up after ourselves.
	 */
	logdebug("main(): terminating");

	(void) remove(SOCKET_PATH);
	ilbd_reset_kernel_state();

	return (0);
}
コード例 #10
0
ファイル: reparsed.c プロジェクト: AlainODea/illumos-gate
int
main(int argc, char *argv[])
{
	pid_t pid;
	int c, error;
	struct rlimit rlset;
	char *defval;

	/*
	 * There is no check for non-global zone and Trusted Extensions.
	 * Reparsed works in both of these environments as long as the
	 * services that use reparsed are supported.
	 */

	MyName = argv[0];
	if (geteuid() != 0) {
		syslog(LOG_ERR, "%s must be run as root", MyName);
		exit(1);
	}

	while ((c = getopt(argc, argv, REPARSED_CMD_OPTS)) != EOF) {
		switch (c) {
		case 'v':
			verbose++;
			break;
		default:
			usage();
		}
	}

	daemonize();
	openlog(MyName, LOG_PID | LOG_NDELAY, LOG_DAEMON);

	(void) _create_daemon_lock(REPARSED, DAEMON_UID, DAEMON_GID);
	(void) enable_extended_FILE_stdio(-1, -1);
	switch (_enter_daemon_lock(REPARSED)) {
	case 0:
		break;
	case -1:
		syslog(LOG_ERR, "Error locking for %s", REPARSED);
		exit(2);
	default:
		/* daemon was already running */
		exit(0);
	}

	(void) signal(SIGHUP, warn_hup);

	/*
	 * Make the process a privilege aware daemon.
	 * Only "basic" privileges are required.
	 *
	 */
	if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 0, 0,
	    (char *)NULL) == -1) {
		syslog(LOG_ERR, "should be run with sufficient privileges");
		exit(3);
	}

	/*
	 * Clear basic privileges not required by reparsed.
	 */
	__fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION,
	    PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL);

	return (start_reparsed_svcs());
}