/* * 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); }
/* 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()); }
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; }
/* * 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); }
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); }
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); }
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); }
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); }
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); }
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()); }