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