Exemple #1
0
static int			/* ERRNO if error, 0 if successful. */
sam_inval_dev_call(
	void *arg,		/* Pointer to arguments. */
	int size,
	cred_t *credp)
{
	sam_fsinval_arg_t  args;
	dev_t rdev;

	if (secpolicy_fs_config(credp, NULL)) {
		return (EINVAL);
	}

	if (size != sizeof (args) ||
	    copyin(arg, (caddr_t)&args, sizeof (args))) {
		return (EFAULT);
	}

	rdev = expldev(args.rdev);
	bflush(rdev);
	binval(rdev);
	return (0);
}
Exemple #2
0
/*ARGSUSED2*/
int
dh_k4_clnt_loadinfo(caddr_t usrdata, caddr_t *kdata, model_t model)
{
	size_t nlen;
	int error = 0;
	char *userbufptr;
	dh_k4_clntdata_t *data;
	char netname[MAXNETNAMELEN+1];
	struct netbuf *syncaddr;
	struct knetconfig *knconf;

	/* map opaque data to des specific strucutre */
	data = kmem_alloc(sizeof (*data), KM_SLEEP);

#ifdef _SYSCALL32_IMPL
	if (model != DATAMODEL_NATIVE) {
		struct des_clnt_data32 data32;

		if (copyin(usrdata, &data32, sizeof (data32)) == -1) {
			error = EFAULT;
		} else {
			data->syncaddr.maxlen = data32.syncaddr.maxlen;
			data->syncaddr.len = data32.syncaddr.len;
			data->syncaddr.buf =
			    (caddr_t)(uintptr_t)data32.syncaddr.buf;
			data->knconf =
			    (struct knetconfig *)(uintptr_t)data32.knconf;
			data->netname = (caddr_t)(uintptr_t)data32.netname;
			data->netnamelen = data32.netnamelen;
		}
	} else
#endif /* _SYSCALL32_IMPL */
	if (copyin(usrdata, data, sizeof (*data)))
		error = EFAULT;

	if (error == 0) {
		syncaddr = &data->syncaddr;
		if (syncaddr->len < MINAUTHLEN || syncaddr->len > MAXAUTHLEN)
			error = EINVAL;
		else {
			userbufptr = syncaddr->buf;
			syncaddr->buf = kmem_alloc(syncaddr->len, KM_SLEEP);
			syncaddr->maxlen = syncaddr->len;
			if (copyin(userbufptr, syncaddr->buf, syncaddr->len)) {
				kmem_free(syncaddr->buf, syncaddr->len);
				syncaddr->buf = NULL;
				error = EFAULT;
			} else {
				(void) copyinstr(data->netname, netname,
				    sizeof (netname), &nlen);
				if (nlen != 0) {
					data->netname =
					    kmem_alloc(nlen, KM_SLEEP);
					bcopy(netname, data->netname, nlen);
					data->netnamelen = (int)nlen;
				}
			}
		}
	}

	if (!error) {
		/*
		 * Allocate space for a knetconfig structure and
		 * its strings and copy in from user-land.
		 */
		knconf = kmem_alloc(sizeof (*knconf), KM_SLEEP);
#ifdef _SYSCALL32_IMPL
		if (model != DATAMODEL_NATIVE) {
			struct knetconfig32 knconf32;

			if (copyin(data->knconf, &knconf32,
			    sizeof (knconf32)) == -1) {
				kmem_free(knconf, sizeof (*knconf));
				kmem_free(syncaddr->buf, syncaddr->len);
				syncaddr->buf = NULL;
				kmem_free(data->netname, nlen);
				error = EFAULT;
			} else {
				knconf->knc_semantics = knconf32.knc_semantics;
				knconf->knc_protofmly =
				    (caddr_t)(uintptr_t)knconf32.knc_protofmly;
				knconf->knc_proto =
				    (caddr_t)(uintptr_t)knconf32.knc_proto;
				knconf->knc_rdev = expldev(knconf32.knc_rdev);
			}
		} else
#endif /* _SYSCALL32_IMPL */
		if (copyin(data->knconf, knconf, sizeof (*knconf))) {
			kmem_free(knconf, sizeof (*knconf));
			kmem_free(syncaddr->buf, syncaddr->len);
			syncaddr->buf = NULL;
			kmem_free(data->netname, nlen);
			error = EFAULT;
		}
	}

	if (!error) {
		size_t nmoved_tmp;
		char *p, *pf;

		pf = kmem_alloc(KNC_STRSIZE, KM_SLEEP);
		p = kmem_alloc(KNC_STRSIZE, KM_SLEEP);
		error = copyinstr(knconf->knc_protofmly, pf,
		    KNC_STRSIZE, &nmoved_tmp);
		if (error) {
			kmem_free(pf, KNC_STRSIZE);
			kmem_free(p, KNC_STRSIZE);
			kmem_free(knconf, sizeof (*knconf));
			kmem_free(syncaddr->buf, syncaddr->len);
			kmem_free(data->netname, nlen);
		}

		if (!error) {
			error = copyinstr(knconf->knc_proto,
			    p, KNC_STRSIZE, &nmoved_tmp);
			if (error) {
				kmem_free(pf, KNC_STRSIZE);
				kmem_free(p, KNC_STRSIZE);
				kmem_free(knconf, sizeof (*knconf));
				kmem_free(syncaddr->buf, syncaddr->len);
				kmem_free(data->netname, nlen);
			}
		}

		if (!error) {
			knconf->knc_protofmly = pf;
			knconf->knc_proto = p;
		}
	}

	if (error) {
		*kdata = NULL;
		kmem_free(data, sizeof (*data));
		return (error);
	}

	data->knconf = knconf;
	*kdata = (caddr_t)data;
	return (0);
}
Exemple #3
0
static int				/* ERRNO if error, 0 if ok */
syscall_mount_response(
	sam_mount_t *mp,		/* pointer to mount entry. */
	sam_fsmount_arg_t *mount)	/* pointer to daemon mount response */
{
	sam_handle_t *fhandle;
	sam_node_t *ip;			/* pointer to rm inode */
	vnode_t	*vp;
	int	error = 0;
	sam_fs_fifo_ctl_t *fifo_ctl;
	dev_t rdev;

	fhandle = (sam_handle_t *)&mount->handle;
	fifo_ctl = (sam_fs_fifo_ctl_t *)fhandle->fifo_cmd.ptr;
	if ((ip = syscall_valid_ino(mp, fhandle)) == NULL) {
			return (ECANCELED);
	}
	vp = SAM_ITOV(ip);
	mutex_enter(&ip->daemon_mutex);

	/*
	 * Is inode still waiting for the mount?
	 */
	if (ip->daemon_busy && ip->seqno == fhandle->seqno) {
		if (fifo_ctl && (fifo_ctl->fifo.magic == FS_FIFO_MAGIC)) {
			fifo_ctl->ret_err = mount->ret_err;
			rdev = expldev(mount->rdev);
			if ((mount->ret_err == 0) && rdev) {
				offset_t size;
				sam_resource_t *resource;
				offset_t section_size = 0;

				RW_LOCK_OS(&ip->inode_rwl, RW_WRITER);
				/*
				 * Get the rm_info record. Preserve the file
				 * size, since it includes the size of all VSNs.
				 * Use size from rm_info record when reading
				 * existing optical disk file (rm_info not
				 * valid).
				 */
				size = ip->di.rm.size;

				resource =
				    (sam_resource_t *)mount->resource.p32;
				if (curproc->p_model != DATAMODEL_ILP32) {
					resource =
					    (sam_resource_t *)
					    mount->resource.p64;
				}
				if (copyin((char *)&resource->archive.rm_info,
				    (char *)&ip->di.rm,
				    sizeof (sam_arch_rminfo_t))) {
					error = EFAULT;
				} else {
					/*
					 * If the bof was written, or the
					 * rm_info was not valid, get all the
					 * resource record.
					 */
					if ((ip->di.rm.ui.flags &
					    RM_BOF_WRITTEN) ||
					    !(ip->di.rm.ui.flags & RM_VALID)) {
						sam_archive_t *ap;

			ap = &fifo_ctl->fifo.param.fs_load.resource.archive;
						copyin(
						    (char *)&resource->archive,
						    (char *)ap,
						    sizeof (sam_archive_t));
						ap->rm_info.valid = 1;
					}
					/*
					 * Preserve size of file for volume
					 * overflow. Do not change size when
					 * reading existing optical disk file.
					 */
					if ((ip->di.rm.ui.flags &
					    RM_BOF_WRITTEN) ||
					    (ip->di.rm.ui.flags & RM_VALID)) {
						section_size = ip->di.rm.size;
						ip->di.rm.size = size;
					}
					/* Removable info valid */
					ip->di.rm.ui.flags |= RM_VALID;

					/*
					 * Set "space" from mount arg for writes
					 * and tape.  Set from section size of
					 * the file when reading from optical
					 * disk.
					 */
					ip->space = mount->space;
					if ((ip->di.rm.media &
					    DT_CLASS_MASK) == DT_OPTICAL) {
						char access;

						copyin(
						    (char *)&resource->access,
						    (char *)&access,
						    sizeof (char));
						if (access == FREAD) {
							ip->space =
							    section_size;
						}
					}
					ip->rdev = rdev;
					ip->mt_handle =
					    (void *)mount->mt_handle.p32;
					if (curproc->p_model !=
					    DATAMODEL_ILP32) {
				ip->mt_handle = (void *)mount->mt_handle.p64;
					}
					ip->io_count = 0;
					TRACE(T_SAM_IOCTL_MNT, vp,
					    ip->di.id.ino, (sam_tr_t)size,
					    ip->rdev);

					if (!(ip->di.rm.ui.flags &
					    RM_STRANGER) &&
					    (ip->di.rm.info.rm.mau == 0)) {
						error = EINVAL;
						fifo_ctl->ret_err = EINVAL;
					}

					if (!(ip->di.rm.ui.flags &
					    RM_BOF_WRITTEN)) {
						if ((ip->di.rm.media &
						    DT_CLASS_MASK) ==
						    DT_OPTICAL) {


				ip->stage_off =	ip->di.rm.info.rm.position *
				    ip->di.rm.info.rm.mau +
				    ip->di.rm.info.rm.file_offset * 512;


						}
					}
				}
				ip->size = ip->di.rm.size;
				RW_UNLOCK_OS(&ip->inode_rwl, RW_WRITER);
			} else {
				if (mount->ret_err == 0) {
					/* No error with rdev == 0 */
					fifo_ctl->ret_err = ENODEV;
				}
				TRACE(T_SAM_IOCTL_EMNT, vp,
				    ip->di.id.ino, 1, mount->ret_err);
			}
		} else {
			if (mount->ret_err == 0)  error = ECANCELED;
			TRACE(T_SAM_IOCTL_EMNT, vp,
			    ip->di.id.ino, 2, mount->ret_err);
		}
		/* Signal 1 thread waiting on mount. */
		ip->daemon_busy = 0;
		cv_signal(&ip->daemon_cv);
	} else {
		if (mount->ret_err == 0)  error = ECANCELED;
		TRACE(T_SAM_IOCTL_EMNT, vp, ip->di.id.ino, 3, mount->ret_err);
	}
	mutex_exit(&ip->daemon_mutex);
	VN_RELE(vp);
	return (error);
}