vtdaemon.c revision ea2722793e684f62dd496ede6243eacea967b82e
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER START
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The contents of this file are subject to the terms of the
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Common Development and Distribution License (the "License").
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * You may not use this file except in compliance with the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fa9e4066f08beec538e775443c5be79dd423fcabahrens * See the License for the specific language governing permissions
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and limitations under the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * When distributing Covered Code, include this CDDL HEADER in each
fa9e4066f08beec538e775443c5be79dd423fcabahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If applicable, add the following below this CDDL HEADER, with the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * fields enclosed by brackets "[]" replaced with your own identifying
fa9e4066f08beec538e775443c5be79dd423fcabahrens * information: Portions Copyright [yyyy] [name of copyright owner]
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER END
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Use is subject to license terms.
55434c770c89aa1b84474f2559a106803511aba0ek * vtdaemon is responsible for the session secure switch via hotkeys.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * vtdaemon itself, like ttymon(1M), is also running on a virtual
fa9e4066f08beec538e775443c5be79dd423fcabahrens * console device (/dev/vt/1), and provides a text console session
fa9e4066f08beec538e775443c5be79dd423fcabahrens * for password input and authentication. The /dev/vt/1 special text
fa9e4066f08beec538e775443c5be79dd423fcabahrens * console is reserved and end users cannot switch to it via hotkeys.
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarks * The hotkey event request can come from either kernel or Xserver,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and a door server is setup to handle the request:
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 1) All text console hotkeys (e.g. "Alt + F#") are intercepted by
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the kernel console driver which sends a door upcall to the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * vtdaemon via door_upcall (target_vt).
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 2) All Xserver hotkeys ("Alt + Ctrl + F#") are intercepted by
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Xserver which sends a door call to the vtdaemon via
fa9e4066f08beec538e775443c5be79dd423fcabahrens * door_call (target_vt).
fa9e4066f08beec538e775443c5be79dd423fcabahrens * server_for_door receives and handles any door server requests:
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Firstly, check source session:
fa9e4066f08beec538e775443c5be79dd423fcabahrens * . If it's from kernel for a text console source session,
55434c770c89aa1b84474f2559a106803511aba0ek * then directly go to check the target session.
55434c770c89aa1b84474f2559a106803511aba0ek * . If it's from Xserver for a graphical source session and the vt
55434c770c89aa1b84474f2559a106803511aba0ek * associated with the Xserver is currently active:
55434c770c89aa1b84474f2559a106803511aba0ek * check if a user has logged in, if true, issue an internal
55434c770c89aa1b84474f2559a106803511aba0ek * VT_EV_LOCK event to the main thread to request lock for
55434c770c89aa1b84474f2559a106803511aba0ek * the graphical source session; else, directly go to check
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the target session.
55434c770c89aa1b84474f2559a106803511aba0ek * . otherwise, discard this request.
55434c770c89aa1b84474f2559a106803511aba0ek * Secondly, check the target session
fa9e4066f08beec538e775443c5be79dd423fcabahrens * . if the target session is a text one that no one has logged in
fa9e4066f08beec538e775443c5be79dd423fcabahrens * or a graphical one, issue an internal VT_EV_ACTIVATE event to
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the main thread to request the actual VT switch.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * . otherwise, the target session is a text one that someone has
fa9e4066f08beec538e775443c5be79dd423fcabahrens * logged in, issue an internal VT_EV_AUTH event to the main
fa9e4066f08beec538e775443c5be79dd423fcabahrens * thread to request authentication for the target session.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * The main thread of vtdaemon is a loop waiting for internal events
fa9e4066f08beec538e775443c5be79dd423fcabahrens * which come from door call threads:
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 1) VT_EV_AUTH to authenticate for target session:
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * firstly switch to the vtdaemon special text console;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * then prompt for password (target_owner on target_vt),
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * e.g. "User Bob's password on vt/#: ".
fa9e4066f08beec538e775443c5be79dd423fcabahrens * if the password is correct (authentication succeeds),
fa9e4066f08beec538e775443c5be79dd423fcabahrens * then actually issue the VT switch; otherwise, ignore
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the request.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 2) VT_EV_LOCK to lock the graphical source session:
fa9e4066f08beec538e775443c5be79dd423fcabahrens * activate screenlock for this graphical session.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * vtdaemon just invokes existing front-end command line
fa9e4066f08beec538e775443c5be79dd423fcabahrens * tools (e.g. xscreensaver-command -lock for JDS) to
fa9e4066f08beec538e775443c5be79dd423fcabahrens * lock the display.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 3) VT_EV_ACTIVATE to directly switch to the target session
fa9e4066f08beec538e775443c5be79dd423fcabahrens * There is a system/vtdaemon:default SMF service for vtdaemon.
104e2ed78d9ef0a0f89f320108b8ca29ca3850d5perrin * There's a "hotkeys" property (BOOLEAN) in the
104e2ed78d9ef0a0f89f320108b8ca29ca3850d5perrin * system/vtdaemon:default SMF service, which allows authorized
104e2ed78d9ef0a0f89f320108b8ca29ca3850d5perrin * users to dynamically enable or disable VT switch via hotkeys.
104e2ed78d9ef0a0f89f320108b8ca29ca3850d5perrin * Its default value is TRUE (enabled).
fa9e4066f08beec538e775443c5be79dd423fcabahrens * There's a "secure" property (BOOLEAN) in the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * system/vtdaemon:default SMF service, which allows authorized
fa9e4066f08beec538e775443c5be79dd423fcabahrens * users to dynamically enable or disable hotkeys are secure.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If disabled, the user can freely switch to any session without
fa9e4066f08beec538e775443c5be79dd423fcabahrens * authentication. Its default value is TRUE (enabled).
fa9e4066f08beec538e775443c5be79dd423fcabahrens * By default, there's only 16 virtual console device nodes (from
fa9e4066f08beec538e775443c5be79dd423fcabahrens * /dev/vt/0 to /dev/vt/15). There's a property "nodecount"
fa9e4066f08beec538e775443c5be79dd423fcabahrens * (default value is 16) in the system/vtdaemon:default SMF
fa9e4066f08beec538e775443c5be79dd423fcabahrens * service, so authorized users can configure it to have more
fa9e4066f08beec538e775443c5be79dd423fcabahrens * or less virtual console device nodes.
104e2ed78d9ef0a0f89f320108b8ca29ca3850d5perrin * Xserver needs to switch back to previous active vt via VT_EV_X_EXIT
fa9e4066f08beec538e775443c5be79dd423fcabahrens * door event request when it's exiting, so vtdaemon always needs to
104e2ed78d9ef0a0f89f320108b8ca29ca3850d5perrin * be there even if the hotkeys switch is disabled, otherwise the screen
fa9e4066f08beec538e775443c5be79dd423fcabahrens * will be just blank when Xserver exits.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The door file /var/run/vt/vtdaemon_door
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Defaults for updating expired passwords */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic boolean_t vt_hotkeys = B_TRUE; /* '-k' option to disable */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic boolean_t vt_secure = B_TRUE; /* '-s' option to disable */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* protecting vt_hotkeys_pending and vt_auth_doing */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int vtnodecount = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int vt_audit_start(adt_session_data_t **, pid_t);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void vt_audit_event(adt_session_data_t *, au_event_t, int);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void vt_check_source_audit(void);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) snprintf(dpy, sizeof (dpy), "%d", display_num);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) execl("/usr/lib/vtxlock", "vtxlock", dpy, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* parent */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Find the login process and user logged in on the target vt.
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (VT_IS_SYSTEM_CONSOLE(target_vt)) /* system console */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* see if this is the entry we want */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (strncmp(u->ut_line, ttyntail, sizeof (u->ut_line)) == 0)) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock sizeof (u->ut_user));
fa9e4066f08beec538e775443c5be79dd423fcabahrens static int is_tipline = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens static struct cons_getterm cons_term = { sizeof (termbuf), termbuf};
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
893a6d32980d24be1349478f44169009d4801c25ahrens if ((fd = open(VT_DAEMON_CONSOLE_FILE, O_WRONLY)) < 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (-1);
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarks * In tipline case, the system console is always
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarks * available, so ignore this request.
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarks return (-1);
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarks * The hotkey request and corresponding target_vt number can come
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarks * from either kernel or Xserver (or other user applications).
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarks * In kernel we've validated the hotkey request, but Xserver (or
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarks * other user applications) cannot do it, so here we still try
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarks * to validate it.
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarks * VT_GETSTATE is only valid for first 16 VTs for historical reasons.
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarks * Fortunately, in practice, Xserver can only send the hotkey
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarks * request of target_vt number from 1 to 12 (Ctrl + Alt + F1 to F2).
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarks return (0);
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarks return (-1);
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarks return (0);
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarks/* events written to fd 0 and read from fd 1 */
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarks/* events written to fd 1 and read from fd 0 */
72fc53bc90bd3b199d29d03ee68adb4a5a17d35bmarkstypedef struct vt_evt {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) write(eventstream[channel], pevt, sizeof (vt_evt_t));
fa9e4066f08beec538e775443c5be79dd423fcabahrens rval = read(eventstream[channel], pevt, sizeof (vt_evt_t));
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (rval > 0);
7f6e3e7d4ebf3d6d45073854bef004ca26f8e918perrin while (rval == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens struct pam_response **, void *);
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*ARGSUSED*/
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The SIGINT (ctl_c) will restart the authentication, and re-prompt
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the end user to input the password.
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (c);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic char *
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((c = vt_getchar(daemonfd)) != '\n' && c != '\r' &&
fa9e4066f08beec538e775443c5be79dd423fcabahrens input[i++] = (char)c;
fa9e4066f08beec538e775443c5be79dd423fcabahrens * vt_conv: vtdaemon PAM conversation function.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * SIGINT/EINTR is handled in vt_getinput()/vt_poll().
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*ARGSUSED*/
fa9e4066f08beec538e775443c5be79dd423fcabahrens *response = calloc(num_msg, sizeof (struct pam_response));
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < num_msg; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Bad message */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Fix up final newline:
fa9e4066f08beec538e775443c5be79dd423fcabahrens * remove from prompts, add back for messages.
fa9e4066f08beec538e775443c5be79dd423fcabahrens switch (m->msg_style) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* FALLTHROUGH */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* the user may want to see this */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* error, service module won't clean up */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Service modules don't clean up responses if an error is returned.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Free responses here.
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (k = 0; k < i; k++, r++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Clear before freeing -- maybe a password */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock/* Get PASSREQ from default file */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /* ignore case */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * VT_CLEAR_SCREEN_STR is the console terminal escape sequence used to
fa9e4066f08beec538e775443c5be79dd423fcabahrens * clear the current screen. The vt special console (/dev/vt/1) is
fa9e4066f08beec538e775443c5be79dd423fcabahrens * just reserved for vtdaemon, and the TERM/termcap of it is always
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the local sun-color, which is always supported by our kernel terminal
fa9e4066f08beec538e775443c5be79dd423fcabahrens * emulator.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock char user_name[sizeof (((struct utmpx *)0)->ut_line) + 1] = {'\0'};
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if ((err = pam_start("vtdaemon", user_name, &pam_conv,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * firstly switch to the vtdaemon special console
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and clear the current screen
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Fetch audit handle.
fa9e4066f08beec538e775443c5be79dd423fcabahrens "\nUnlock user %s on the system console\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Only audit failed unlock here, successful unlock
fa9e4066f08beec538e775443c5be79dd423fcabahrens * will be audited after switching to target vt.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Should be PAM_SUCCESS to reach here.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Free audit handle.
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* main thread (lock and auth) */
fa9e4066f08beec538e775443c5be79dd423fcabahrens pollfds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (pollfds[0].revents && eventstream_read(1, &ve)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* new request */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* directly activate target vt */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* check the target session */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((fd = open(VT_DAEMON_CONSOLE_FILE, O_RDONLY)) < 0)
5730cc9a43c5f11a472d7536ed81facfd10f1e2emaybee (void) snprintf(vtname, sizeof (vtname), "/dev/vt/%d", state.v_active);
5730cc9a43c5f11a472d7536ed81facfd10f1e2emaybee * Xserver registers its pid into kernel to associate it with
5730cc9a43c5f11a472d7536ed81facfd10f1e2emaybee * its vt upon startup for each graphical display. So here we can
5730cc9a43c5f11a472d7536ed81facfd10f1e2emaybee * check if the pid is of the Xserver for the current active
5730cc9a43c5f11a472d7536ed81facfd10f1e2emaybee * display when we receive a special VT_EV_X_EXIT request from
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee * a process. If the request does not come from the current
5730cc9a43c5f11a472d7536ed81facfd10f1e2emaybee * active Xserver, it is discarded.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * check if the pid is of the Xserver for the current active display,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * return true when it is, and then also return other associated
5730cc9a43c5f11a472d7536ed81facfd10f1e2emaybee * information with the Xserver.
5730cc9a43c5f11a472d7536ed81facfd10f1e2emaybeevt_get_disp_info(pid_t x_pid, int *logged_in, int *display_num)
5730cc9a43c5f11a472d7536ed81facfd10f1e2emaybee * Maybe last switch action is being taken and the lock is ongoing,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * here we must reject the newly request.
5dc8af33db998034aea16c6b24b8d6c00fddc1a0maybee /* cleared in vt_do_active and vt_do_auth */
5730cc9a43c5f11a472d7536ed81facfd10f1e2emaybee /* check source session for this hotkeys request */
5730cc9a43c5f11a472d7536ed81facfd10f1e2emaybee if (pid == 0) {
b19a79ec1a527828a60c4d325ccd8dcbeb2b2e8bperrin /* ok, it comes from kernel. */
5730cc9a43c5f11a472d7536ed81facfd10f1e2emaybee /* then only need to check target session */
5730cc9a43c5f11a472d7536ed81facfd10f1e2emaybee * check if it comes from current active X graphical session,
5730cc9a43c5f11a472d7536ed81facfd10f1e2emaybee * if not, ignore this request.
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!vt_get_disp_info(pid, &logged_in, &display_num)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The main routine for the door server that deals with secure hotkeys
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensserver_for_door(void *cookie, char *args, size_t alen, door_desc_t *dp,
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* LINTED E_BAD_PTR_CAST_ALIGN */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Xserver will issue this event requesting to switch back
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * to previous active vt when it's exiting and the associated
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * vt is currently active.
fa9e4066f08beec538e775443c5be79dd423fcabahrens DOOR_UNREF | DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens syslog(LOG_ERR, "door_create failed: %s", strerror(errno));
fa9e4066f08beec538e775443c5be79dd423fcabahrens * check to see if vtdaemon is already running.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The idea here is that we want to open the path to which we will
fa9e4066f08beec538e775443c5be79dd423fcabahrens * attach our door, lock it, and then make sure that no-one has beat us
fa9e4066f08beec538e775443c5be79dd423fcabahrens * to fattach(3c)ing onto it.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * fattach(3c) is really a mount, so there are actually two possible
fa9e4066f08beec538e775443c5be79dd423fcabahrens * vnodes we could be dealing with. Our strategy is as follows:
fa9e4066f08beec538e775443c5be79dd423fcabahrens * - If the file we opened is a regular file (common case):
fa9e4066f08beec538e775443c5be79dd423fcabahrens * There is no fattach(3c)ed door, so we have a chance of becoming
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the running vtdaemon. We attempt to lock the file: if it is
fa9e4066f08beec538e775443c5be79dd423fcabahrens * already locked, that means someone else raced us here, so we
fa9e4066f08beec538e775443c5be79dd423fcabahrens * lose and give up.
55434c770c89aa1b84474f2559a106803511aba0ek * - If the file we opened is a namefs file:
55434c770c89aa1b84474f2559a106803511aba0ek * This means there is already an established door fattach(3c)'ed
55434c770c89aa1b84474f2559a106803511aba0ek * to the rendezvous path. We've lost the race, so we give up.
55434c770c89aa1b84474f2559a106803511aba0ek * Note that in this case we also try to grab the file lock, and
55434c770c89aa1b84474f2559a106803511aba0ek * will succeed in acquiring it since the vnode locked by the
55434c770c89aa1b84474f2559a106803511aba0ek * "winning" vtdaemon was a regular one, and the one we locked was
55434c770c89aa1b84474f2559a106803511aba0ek * the fattach(3c)'ed door node. At any rate, no harm is done.
55434c770c89aa1b84474f2559a106803511aba0ek * Lock the file to synchronize
55434c770c89aa1b84474f2559a106803511aba0ek * Someone else raced us here and grabbed the lock file
55434c770c89aa1b84474f2559a106803511aba0ek * first. A warning here and exit.
55434c770c89aa1b84474f2559a106803511aba0ek * There is already something fattach()'ed to this file.
55434c770c89aa1b84474f2559a106803511aba0ek * Lets see what the door is up to.
55434c770c89aa1b84474f2559a106803511aba0ek if (door_info(doorfd, &info) == 0 && info.di_target != -1) {
55434c770c89aa1b84474f2559a106803511aba0ek * We must create and lock everyone but root out of VT_TMPDIR
55434c770c89aa1b84474f2559a106803511aba0ek * since anyone can open any UNIX domain socket, regardless of
55434c770c89aa1b84474f2559a106803511aba0ek * its file system permissions.
55434c770c89aa1b84474f2559a106803511aba0ek if (mkdir(VT_TMPDIR, S_IRWXU|S_IROTH|S_IXOTH|S_IRGRP|S_IXGRP) < 0 &&
return (B_FALSE);
return (B_FALSE);
return (B_TRUE);
int opt;
int active;
switch (opt) {
if (!mkvtdir())
if (!eventstream_init())
if (!make_daemon_exclusive())
(void) close(i);
(void) setsid();
if (daemonfd != 0)
vt_check_source_audit(void)
int fd;
int source_vt;
int real_vt;