a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross/*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * CDDL HEADER START
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross *
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * The contents of this file are subject to the terms of the
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Common Development and Distribution License (the "License").
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * You may not use this file except in compliance with the License.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross *
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * or http://www.opensolaris.org/os/licensing.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * See the License for the specific language governing permissions
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * and limitations under the License.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross *
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * When distributing Covered Code, include this CDDL HEADER in each
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * If applicable, add the following below this CDDL HEADER, with the
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross *
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * CDDL HEADER END
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross/*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross/*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * SMBFS I/O Daemon (SMF service)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <sys/types.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <sys/stat.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <sys/note.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <sys/queue.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <errno.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <fcntl.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <signal.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <stdarg.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <stdio.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <string.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <strings.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <stdlib.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <synch.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <time.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <unistd.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <ucred.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <wait.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <priv_utils.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <err.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <door.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <libscf.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <locale.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <thread.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <assert.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <netsmb/smb_lib.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic boolean_t d_flag = B_FALSE;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross/* Keep a list of child processes. */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rosstypedef struct _child {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross LIST_ENTRY(_child) list;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross pid_t pid;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross uid_t uid;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross} child_t;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic LIST_HEAD(, _child) child_list = { 0 };
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossmutex_t cl_mutex = DEFAULTMUTEX;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic const char smbiod_path[] = "/usr/lib/smbfs/smbiod";
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic const char door_path[] = SMBIOD_SVC_DOOR;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossvoid svc_dispatch(void *cookie, char *argp, size_t argsz,
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross door_desc_t *dp, uint_t n_desc);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic int cmd_start(uid_t uid, gid_t gid);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic int new_child(uid_t uid, gid_t gid);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic void svc_sigchld(void);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic void child_gone(uid_t, pid_t, int);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic void svc_cleanup(void);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic child_t *
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rosschild_find_by_pid(pid_t pid)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross{
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross child_t *cp;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross assert(MUTEX_HELD(&cl_mutex));
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross LIST_FOREACH(cp, &child_list, list) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (cp->pid == pid)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross return (cp);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross return (NULL);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross}
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic child_t *
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rosschild_find_by_uid(uid_t uid)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross{
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross child_t *cp;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross assert(MUTEX_HELD(&cl_mutex));
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross LIST_FOREACH(cp, &child_list, list) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (cp->uid == uid)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross return (cp);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross return (NULL);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross}
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross/*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Find out if the service is already running.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Return: true, false.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic boolean_t
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossalready_running(void)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross{
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross door_info_t info;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross int fd, rc;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if ((fd = open(door_path, O_RDONLY)) < 0)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross return (B_FALSE);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross rc = door_info(fd, &info);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross close(fd);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (rc < 0)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross return (B_FALSE);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross return (B_TRUE);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross}
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross/*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * This function will fork off a child process,
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * from which only the child will return.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross *
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * The parent exit status is taken as the SMF start method
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * success or failure, so the parent waits (via pipe read)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * for the child to finish initialization before it exits.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Use SMF error codes only on exit.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic int
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossdaemonize_init(void)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross{
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross int pid, st;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross int pfds[2];
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross chdir("/");
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (pipe(pfds) < 0) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross perror("pipe");
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross exit(SMF_EXIT_ERR_FATAL);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if ((pid = fork1()) == -1) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross perror("fork");
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross exit(SMF_EXIT_ERR_FATAL);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * If we're the parent process, wait for either the child to send us
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * the appropriate exit status over the pipe or for the read to fail
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * (presumably with 0 for EOF if our child terminated abnormally).
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * If the read fails, exit with either the child's exit status if it
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * exited or with SMF_EXIT_ERR_FATAL if it died from a fatal signal.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (pid != 0) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* parent */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross close(pfds[1]);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (read(pfds[0], &st, sizeof (st)) == sizeof (st))
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross _exit(st);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (waitpid(pid, &st, 0) == pid && WIFEXITED(st))
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross _exit(WEXITSTATUS(st));
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross _exit(SMF_EXIT_ERR_FATAL);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* child */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross close(pfds[0]);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross return (pfds[1]);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross}
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic void
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossdaemonize_fini(int pfd, int rc)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross{
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* Tell parent we're ready. */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross (void) write(pfd, &rc, sizeof (rc));
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross close(pfd);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross}
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossint
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossmain(int argc, char **argv)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross{
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross sigset_t oldmask, tmpmask;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross struct sigaction sa;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross struct rlimit rl;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross int door_fd = -1, tmp_fd = -1, pfd = -1;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross int c, sig;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross int rc = SMF_EXIT_ERR_FATAL;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross boolean_t created = B_FALSE, attached = B_FALSE;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* set locale and text domain for i18n */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross (void) setlocale(LC_ALL, "");
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross (void) textdomain(TEXT_DOMAIN);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross while ((c = getopt(argc, argv, "d")) != -1) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross switch (c) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross case 'd':
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* Do debug messages. */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross d_flag = B_TRUE;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross break;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross default:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr, "Usage: %s [-d]\n", argv[0]);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross return (SMF_EXIT_ERR_CONFIG);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (already_running()) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr, "%s: already running", argv[0]);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross return (rc);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Raise the fd limit to max
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * errors here are non-fatal
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (getrlimit(RLIMIT_NOFILE, &rl) != 0) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr, "getrlimit failed, err %d\n", errno);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross } else if (rl.rlim_cur < rl.rlim_max) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross rl.rlim_cur = rl.rlim_max;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (setrlimit(RLIMIT_NOFILE, &rl) != 0)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr, "setrlimit "
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross "RLIMIT_NOFILE %d, err %d",
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross (int)rl.rlim_cur, errno);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Want all signals blocked, as we're doing
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * synchronous delivery via sigwait below.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross sigfillset(&tmpmask);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross sigprocmask(SIG_BLOCK, &tmpmask, &oldmask);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Do want SIGCHLD, and will waitpid().
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross sa.sa_flags = SA_NOCLDSTOP;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross sa.sa_handler = SIG_DFL;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross sigemptyset(&sa.sa_mask);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross sigaction(SIGCHLD, &sa, NULL);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Daemonize, unless debugging.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (d_flag) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* debug: run in foregound (not a service) */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross putenv("SMBFS_DEBUG=1");
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross } else {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* Non-debug: start daemon in the background. */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross pfd = daemonize_init();
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Create directory for all smbiod doors.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if ((mkdir(SMBIOD_RUNDIR, 0755) < 0) && errno != EEXIST) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross perror(SMBIOD_RUNDIR);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto out;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Create a file for the main service door.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross unlink(door_path);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross tmp_fd = open(door_path, O_RDWR|O_CREAT|O_EXCL, 0644);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (tmp_fd < 0) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross perror(door_path);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto out;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross close(tmp_fd);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross tmp_fd = -1;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross created = B_TRUE;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* Setup the door service. */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross door_fd = door_create(svc_dispatch, NULL,
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross DOOR_REFUSE_DESC | DOOR_NO_CANCEL);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (door_fd == -1) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross perror("svc door_create");
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto out;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fdetach(door_path);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (fattach(door_fd, door_path) < 0) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr, "%s: fattach failed, %s\n",
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross door_path, strerror(errno));
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto out;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross attached = B_TRUE;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Initializations done. Tell start method we're up.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross rc = SMF_EXIT_OK;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (pfd != -1) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross daemonize_fini(pfd, rc);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross pfd = -1;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Main thread just waits for signals.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossagain:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross sig = sigwait(&tmpmask);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (d_flag)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr, "main: sig=%d\n", sig);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross switch (sig) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross case SIGINT:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross case SIGTERM:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * The whole process contract gets a SIGTERM
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * at once. Give children a chance to exit
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * so we can do normal SIGCHLD cleanup.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Prevent new door_open calls.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fdetach(door_path);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross attached = B_FALSE;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross alarm(2);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto again;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross case SIGALRM:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross break; /* normal termination */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross case SIGCHLD:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross svc_sigchld();
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto again;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross case SIGCONT:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto again;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross default:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* Unexpected signal. */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr, "svc_main: unexpected sig=%d\n", sig);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross break;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossout:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (attached)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fdetach(door_path);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (door_fd != -1)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross door_revoke(door_fd);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (created)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross unlink(door_path);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* NB: door threads gone now. */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross svc_cleanup();
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* If startup error, report to parent. */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (pfd != -1)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross daemonize_fini(pfd, rc);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross return (rc);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross}
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross/*ARGSUSED*/
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossvoid
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rosssvc_dispatch(void *cookie, char *argp, size_t argsz,
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross door_desc_t *dp, uint_t n_desc)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross{
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross ucred_t *ucred = NULL;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross uid_t uid;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross gid_t gid;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross int32_t cmd, rc;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Allow a NULL arg call to check if this
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * daemon is running. Just return zero.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (argp == NULL) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross rc = 0;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto out;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Get the caller's credentials.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * (from client side of door)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (door_ucred(&ucred) != 0) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross rc = EACCES;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto out;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross uid = ucred_getruid(ucred);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross gid = ucred_getrgid(ucred);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Arg is just an int command code.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Reply is also an int.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (argsz != sizeof (cmd)) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross rc = EINVAL;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto out;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross bcopy(argp, &cmd, sizeof (cmd));
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross switch (cmd) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross case SMBIOD_START:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross rc = cmd_start(uid, gid);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross break;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross default:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross rc = EINVAL;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto out;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossout:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (ucred != NULL)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross ucred_free(ucred);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross door_return((void *)&rc, sizeof (rc), NULL, 0);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross}
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross/*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Start a per-user smbiod, if not already running.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossint
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rosscmd_start(uid_t uid, gid_t gid)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross{
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross char door_file[64];
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross child_t *cp;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross int pid, fd = -1;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross mutex_lock(&cl_mutex);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross cp = child_find_by_uid(uid);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (cp != NULL) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* This UID already has an IOD. */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross mutex_unlock(&cl_mutex);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (d_flag) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr, "cmd_start: uid %d"
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross " already has an iod\n", uid);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross return (0);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * OK, create a new child.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross cp = malloc(sizeof (*cp));
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (cp == NULL) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross mutex_unlock(&cl_mutex);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross return (ENOMEM);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross cp->pid = 0; /* update below */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross cp->uid = uid;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross LIST_INSERT_HEAD(&child_list, cp, list);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross mutex_unlock(&cl_mutex);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * The child will not have permission to create or
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * destroy files in SMBIOD_RUNDIR so do that here.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross snprintf(door_file, sizeof (door_file),
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross SMBIOD_USR_DOOR, cp->uid);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross unlink(door_file);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fd = open(door_file, O_RDWR|O_CREAT|O_EXCL, 0600);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (fd < 0) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross perror(door_file);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto errout;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (fchown(fd, uid, gid) < 0) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross perror(door_file);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto errout;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross close(fd);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fd = -1;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if ((pid = fork1()) == -1) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross perror("fork");
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto errout;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (pid == 0) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross (void) new_child(uid, gid);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross _exit(1);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* parent */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross cp->pid = pid;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (d_flag) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr, "cmd_start: uid %d new iod, pid %d\n",
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross uid, pid);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross return (0);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rosserrout:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (fd != -1)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross close(fd);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross mutex_lock(&cl_mutex);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross LIST_REMOVE(cp, list);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross mutex_unlock(&cl_mutex);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross free(cp);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross return (errno);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross}
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross/*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Assume the passed credentials (from the door client),
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * drop any extra privileges, and exec the per-user iod.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic int
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossnew_child(uid_t uid, gid_t gid)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross{
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross char *argv[2];
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross int flags, rc;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross flags = PU_RESETGROUPS | PU_LIMITPRIVS | PU_INHERITPRIVS;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross rc = __init_daemon_priv(flags, uid, gid, PRIV_NET_ACCESS, NULL);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (rc != 0)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross return (errno);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross argv[0] = "smbiod";
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross argv[1] = NULL;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross (void) execv(smbiod_path, argv);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross return (errno);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross}
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic void
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rosssvc_sigchld(void)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross{
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross child_t *cp;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross pid_t pid;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross int err, status, found = 0;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross mutex_lock(&cl_mutex);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross found++;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (d_flag)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr, "svc_sigchld: pid %d\n", (int)pid);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross cp = child_find_by_pid(pid);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (cp == NULL) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr, "Unknown pid %d\n", (int)pid);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross continue;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross child_gone(cp->uid, cp->pid, status);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross LIST_REMOVE(cp, list);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross free(cp);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross err = errno;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross mutex_unlock(&cl_mutex);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* ECHILD is the normal end of loop. */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (pid < 0 && err != ECHILD)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr, "svc_sigchld: waitpid err %d\n", err);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (found == 0)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr, "svc_sigchld: no children?\n");
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross}
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic void
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rosschild_gone(uid_t uid, pid_t pid, int status)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross{
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross char door_file[64];
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross int x;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (d_flag)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr, "child_gone: uid %d pid %d\n",
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross uid, (int)pid);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross snprintf(door_file, sizeof (door_file),
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross SMBIOD_RUNDIR "/%d", uid);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross unlink(door_file);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (WIFEXITED(status)) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross x = WEXITSTATUS(status);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (x != 0) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr,
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross "uid %d, pid %d exit %d",
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross uid, (int)pid, x);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (WIFSIGNALED(status)) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross x = WTERMSIG(status);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr,
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross "uid %d, pid %d signal %d",
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross uid, (int)pid, x);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross}
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross/*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Final cleanup before exit. Unlink child doors, etc.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Called while single threaded, so no locks needed here.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * The list is normally empty by now due to svc_sigchld
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * calls during shutdown. But in case there were any
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * straglers, do cleanup here. Don't bother freeing any
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * list elements here, as we're exiting.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossstatic void
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rosssvc_cleanup(void)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross{
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross child_t *cp;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross LIST_FOREACH(cp, &child_list, list) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross child_gone(cp->uid, cp->pid, 0);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross}