kern_return_t S_exec_init (struct trivfs_protid *protid, auth_t auth, process_t proc) { mach_port_t host_priv, startup; error_t err; if (! protid || ! protid->isroot) return EPERM; _hurd_port_set (&_hurd_ports[INIT_PORT_PROC], proc); /* Consume. */ _hurd_port_set (&_hurd_ports[INIT_PORT_AUTH], auth); /* Consume. */ /* Do initial setup with the proc server. */ _hurd_proc_init (save_argv, NULL, 0); procserver = getproc (); /* Have the proc server notify us when the canonical ints and ports change. This will generate an immediate callback giving us the initial boot-time canonical sets. */ { struct iouser *user; struct trivfs_protid *cred; mach_port_t right; err = iohelp_create_empty_iouser (&user); assert_perror (err); err = trivfs_open (fsys, user, 0, MACH_PORT_NULL, &cred); assert_perror (err); right = ports_get_send_right (cred); proc_execdata_notify (procserver, right, MACH_MSG_TYPE_COPY_SEND); mach_port_deallocate (mach_task_self (), right); } err = get_privileged_ports (&host_priv, NULL); assert_perror (err); proc_register_version (procserver, host_priv, "exec", "", HURD_VERSION); err = proc_getmsgport (procserver, 1, &startup); assert_perror (err); mach_port_deallocate (mach_task_self (), procserver); /* Call startup_essential task last; init assumes we are ready to run once we call it. */ err = startup_essential_task (startup, mach_task_self (), MACH_PORT_NULL, "exec", host_priv); assert_perror (err); mach_port_deallocate (mach_task_self (), startup); mach_port_deallocate (mach_task_self (), host_priv); return 0; }
kern_return_t trivfs_S_fsys_getroot (struct trivfs_control *cntl, mach_port_t reply_port, mach_msg_type_name_t reply_port_type, mach_port_t dotdot, uid_t *uids, size_t nuids, uid_t *gids, size_t ngids, int flags, retry_type *do_retry, char *retry_name, mach_port_t *newpt, mach_msg_type_name_t *newpttype) { int perms; error_t err = 0; mach_port_t new_realnode; struct trivfs_protid *cred; struct iouser *user; if (!cntl) return EOPNOTSUPP; if (trivfs_getroot_hook) { err = (*trivfs_getroot_hook) (cntl, reply_port, reply_port_type, dotdot, uids, nuids, gids, ngids, flags, do_retry, retry_name, newpt, newpttype); if (err != EAGAIN) return err; } if ((flags & O_WRITE & trivfs_allow_open) != (flags & O_WRITE)) return EROFS; if ((flags & (O_READ|O_WRITE|O_EXEC) & trivfs_allow_open) != (flags & (O_READ|O_WRITE|O_EXEC))) return EACCES; /* O_CREAT and O_EXCL are not meaningful here; O_NOLINK and O_NOTRANS will only be useful when trivfs supports translators (which it doesn't now). */ flags &= O_HURD; flags &= ~(O_CREAT|O_EXCL|O_NOLINK|O_NOTRANS); struct idvec idvec = { .ids = uids, .num = nuids, .alloced = nuids, }; if (_is_privileged (&idvec)) /* Privileged users should be given all our rights. */ err = io_duplicate (cntl->underlying, &new_realnode); else /* Non-privileged, restrict rights. */ err = io_restrict_auth (cntl->underlying, &new_realnode, uids, nuids, gids, ngids); if (err) return err; err = iohelp_create_complex_iouser (&user, uids, nuids, gids, ngids); if (err) return err; /* Validate permissions. */ if (! trivfs_check_access_hook) file_check_access (new_realnode, &perms); else (*trivfs_check_access_hook) (cntl, user, new_realnode, &perms); if ((flags & (O_READ|O_WRITE|O_EXEC) & perms) != (flags & (O_READ|O_WRITE|O_EXEC))) err = EACCES; if (!err && trivfs_check_open_hook) err = (*trivfs_check_open_hook) (cntl, user, flags); if (!err) { if (! trivfs_open_hook) { err = trivfs_open (cntl, user, flags, new_realnode, &cred); if (!err) mach_port_deallocate (mach_task_self (), dotdot); } else err = (*trivfs_open_hook) (cntl, user, dotdot, flags, new_realnode, &cred); } if (err) { mach_port_deallocate (mach_task_self (), new_realnode); iohelp_free_iouser (user); } else { *do_retry = FS_RETRY_NORMAL; *retry_name = '\0'; *newpt = ports_get_right (cred); *newpttype = MACH_MSG_TYPE_MAKE_SEND; ports_port_deref (cred); } return err; }
kern_return_t trivfs_S_dir_lookup (struct trivfs_protid *cred, mach_port_t reply, mach_msg_type_name_t reply_type, char *filename, int flags, mode_t mode, retry_type *retry_type, char *retry_name, mach_port_t *retrypt, mach_msg_type_name_t *retrypt_type) { int perms; error_t err; struct trivfs_protid *newcred; if (!cred) return EOPNOTSUPP; if (filename[0]) return ENOTDIR; /* This is a null-pathname "reopen" call; do the right thing. */ /* Burn off flags we don't actually implement */ flags &= O_HURD; flags &= ~(O_CREAT|O_EXCL|O_NOLINK|O_NOTRANS); /* Validate permissions */ if (! trivfs_check_access_hook) file_check_access (cred->realnode, &perms); else (*trivfs_check_access_hook) (cred->po->cntl, cred->user, cred->realnode, &perms); if ((flags & (O_READ|O_WRITE|O_EXEC) & perms) != (flags & (O_READ|O_WRITE|O_EXEC))) return EACCES; /* Execute the open */ err = 0; if (trivfs_check_open_hook) err = (*trivfs_check_open_hook) (cred->po->cntl, cred->user, flags); if (!err) { struct iouser *user; err = iohelp_dup_iouser (&user, cred->user); if (err) return err; err = trivfs_open (cred->po->cntl, user, flags, cred->realnode, &newcred); if (err) iohelp_free_iouser (user); else mach_port_mod_refs (mach_task_self (), cred->realnode, MACH_PORT_RIGHT_SEND, +1); } if (err) return err; *retry_type = FS_RETRY_NORMAL; *retry_name = '\0'; *retrypt = ports_get_right (newcred); *retrypt_type = MACH_MSG_TYPE_MAKE_SEND; ports_port_deref (newcred); return 0; }