Example #1
0
/*
 * readlink reads the link of `curproc' or `file'
 */
static int
procfs_readlink(struct vop_readlink_args *ap)
{
	char buf[16];		/* should be enough */
	struct proc *procp;
	struct vnode *vp = ap->a_vp;
	struct pfsnode *pfs = VTOPFS(vp);
	char *fullpath, *freepath;
	int error, len;

	switch (pfs->pfs_type) {
	case Pcurproc:
		if (pfs->pfs_fileno != PROCFS_FILENO(0, Pcurproc))
			return (EINVAL);

		len = ksnprintf(buf, sizeof(buf), "%ld", (long)curproc->p_pid);

		return (uiomove(buf, len, ap->a_uio));
	/*
	 * There _should_ be no way for an entire process to disappear
	 * from under us...
	 */
	case Pfile:
		procp = pfs_pfind(pfs->pfs_pid);
		if (procp == NULL || procp->p_ucred == NULL) {
			kprintf("procfs_readlink: pid %d disappeared\n",
			    pfs->pfs_pid);
			if (procp)
				PRELE(procp);
			return (uiomove("unknown", sizeof("unknown") - 1,
			    ap->a_uio));
		}
		error = cache_fullpath(procp, &procp->p_textnch, &fullpath, &freepath, 0);
		if (error != 0) {
			if (procp)
				PRELE(procp);
			return (uiomove("unknown", sizeof("unknown") - 1,
			    ap->a_uio));
		}
		error = uiomove(fullpath, strlen(fullpath), ap->a_uio);
		kfree(freepath, M_TEMP);
		if (procp)
			PRELE(procp);
		return (error);
	default:
		return (EINVAL);
	}
}
Example #2
0
/*
 * Symbolic Links
 */
static int
cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana)
{
	ISO_RRIP_SLINK_COMPONENT *pcomp;
	ISO_RRIP_SLINK_COMPONENT *pcompe;
	int error, len, wlen, cont;
	char *outbuf, *inbuf, *freebuf;

	pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component;
	pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length));
	len = *ana->outlen;
	outbuf = ana->outbuf;
	cont = ana->cont;
	freebuf = NULL;

	/*
	 * Gathering a Symbolic name from each component with path
	 */
	for (;
	     pcomp < pcompe;
	     pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ
						  + isonum_711(pcomp->clen))) {

		if (!cont) {
			if (len < ana->maxlen) {
				len++;
				*outbuf++ = '/';
			}
		}
		cont = 0;

		inbuf = "..";
		wlen = 0;

		switch (*pcomp->cflag) {

		case ISO_SUSP_CFLAG_CURRENT:
			/* Inserting Current */
			wlen = 1;
			break;

		case ISO_SUSP_CFLAG_PARENT:
			/* Inserting Parent */
			wlen = 2;
			break;

		case ISO_SUSP_CFLAG_ROOT:
			/* Inserting slash for ROOT */
			/* start over from beginning(?) */
			outbuf -= len;
			len = 0;
			break;

		case ISO_SUSP_CFLAG_VOLROOT:
			/* Inserting a mount point i.e. "/cdrom" */
			/* same as above */
			outbuf -= len;
			len = 0;
			error = cache_fullpath(NULL, &ana->imp->im_mountp->mnt_ncmountpt,
					       &inbuf, &freebuf, 0);
			if (error)
				goto bad;
			wlen = strlen(inbuf);
			break;

		case ISO_SUSP_CFLAG_HOST:
			/* Inserting hostname i.e. "kurt.tools.de" */
			inbuf = hostname;
			wlen = strlen(hostname);
			break;

		case ISO_SUSP_CFLAG_CONTINUE:
			cont = 1;
			/* fall thru */
		case 0:
			/* Inserting component */
			wlen = isonum_711(pcomp->clen);
			inbuf = pcomp->name;
			break;
		default:
			kprintf("RRIP with incorrect flags?");
			wlen = ana->maxlen + 1;
			break;
		}

		if (len + wlen > ana->maxlen)
			goto bad;

		bcopy(inbuf,outbuf,wlen);
		outbuf += wlen;
		len += wlen;

		if (freebuf != NULL) {
			kfree(freebuf, M_TEMP);
			freebuf = NULL;
		}
	}
	ana->outbuf = outbuf;
	*ana->outlen = len;
	ana->cont = cont;

	if (!isonum_711(p->flags)) {
		ana->fields &= ~ISO_SUSP_SLINK;
		return ISO_SUSP_SLINK;
	}
	return 0;

bad:
	if (freebuf != NULL)
		kfree(freebuf, M_TEMP);
	ana->cont = 1;
	ana->fields = 0;
	ana->outbuf -= *ana->outlen;
	*ana->outlen = 0;
	return 0;
}
Example #3
0
/*
 * Invent attributes for pfsnode (vp) and store
 * them in (vap).
 * Directories lengths are returned as zero since
 * any real length would require the genuine size
 * to be computed, and nothing cares anyway.
 *
 * this is relatively minimal for procfs.
 *
 * procfs_getattr(struct vnode *a_vp, struct vattr *a_vap)
 */
static int
procfs_getattr(struct vop_getattr_args *ap)
{
	struct pfsnode *pfs = VTOPFS(ap->a_vp);
	struct vattr *vap = ap->a_vap;
	struct proc *procp;
	int error;

	/*
	 * First make sure that the process and its credentials 
	 * still exist.
	 */
	switch (pfs->pfs_type) {
	case Proot:
	case Pcurproc:
		procp = NULL;
		break;

	default:
		procp = pfs_pfind(pfs->pfs_pid);
		if (procp == NULL || procp->p_ucred == NULL) {
			error = ENOENT;
			goto done;
		}
	}

	error = 0;

	/* start by zeroing out the attributes */
	VATTR_NULL(vap);

	/* next do all the common fields */
	vap->va_type = ap->a_vp->v_type;
	vap->va_mode = pfs->pfs_mode;
	vap->va_fileid = pfs->pfs_fileno;
	vap->va_flags = 0;
	vap->va_blocksize = PAGE_SIZE;
	vap->va_bytes = vap->va_size = 0;
	vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];

	/*
	 * Make all times be current TOD.
	 * It would be possible to get the process start
	 * time from the p_stat structure, but there's
	 * no "file creation" time stamp anyway, and the
	 * p_stat structure is not addressible if u. gets
	 * swapped out for that process.
	 */
	nanotime(&vap->va_ctime);
	vap->va_atime = vap->va_mtime = vap->va_ctime;

	/*
	 * If the process has exercised some setuid or setgid
	 * privilege, then rip away read/write permission so
	 * that only root can gain access.
	 */
	switch (pfs->pfs_type) {
	case Pctl:
	case Pregs:
	case Pfpregs:
	case Pdbregs:
	case Pmem:
		if (procp->p_flag & P_SUGID)
			vap->va_mode &= ~((VREAD|VWRITE)|
					  ((VREAD|VWRITE)>>3)|
					  ((VREAD|VWRITE)>>6));
		break;
	default:
		break;
	}

	/*
	 * now do the object specific fields
	 *
	 * The size could be set from struct reg, but it's hardly
	 * worth the trouble, and it puts some (potentially) machine
	 * dependent data into this machine-independent code.  If it
	 * becomes important then this function should break out into
	 * a per-file stat function in the corresponding .c file.
	 */

	vap->va_nlink = 1;
	if (procp) {
		vap->va_uid = procp->p_ucred->cr_uid;
		vap->va_gid = procp->p_ucred->cr_gid;
	}

	switch (pfs->pfs_type) {
	case Proot:
		/*
		 * Set nlink to 1 to tell fts(3) we don't actually know.
		 */
		vap->va_nlink = 1;
		vap->va_uid = 0;
		vap->va_gid = 0;
		vap->va_size = vap->va_bytes = DEV_BSIZE;
		break;

	case Pcurproc: {
		char buf[16];		/* should be enough */
		vap->va_uid = 0;
		vap->va_gid = 0;
		vap->va_size = vap->va_bytes =
		    ksnprintf(buf, sizeof(buf), "%ld", (long)curproc->p_pid);
		break;
	}

	case Pproc:
		vap->va_nlink = nproc_targets;
		vap->va_size = vap->va_bytes = DEV_BSIZE;
		break;

	case Pfile: {
		char *fullpath, *freepath;
		error = cache_fullpath(procp, &procp->p_textnch, &fullpath, &freepath, 0);
		if (error == 0) {
			vap->va_size = strlen(fullpath);
			kfree(freepath, M_TEMP);
		} else {
			vap->va_size = sizeof("unknown") - 1;
			error = 0;
		}
		vap->va_bytes = vap->va_size;
		break;
	}

	case Pmem:
		/*
		 * If we denied owner access earlier, then we have to
		 * change the owner to root - otherwise 'ps' and friends
		 * will break even though they are setgid kmem. *SIGH*
		 */
		if (procp->p_flag & P_SUGID)
			vap->va_uid = 0;
		else
			vap->va_uid = procp->p_ucred->cr_uid;
		break;

	case Pregs:
		vap->va_bytes = vap->va_size = sizeof(struct reg);
		break;

	case Pfpregs:
		vap->va_bytes = vap->va_size = sizeof(struct fpreg);
		break;

        case Pdbregs:
                vap->va_bytes = vap->va_size = sizeof(struct dbreg);
                break;

	case Ptype:
	case Pmap:
	case Pctl:
	case Pstatus:
	case Pnote:
	case Pnotepg:
	case Pcmdline:
	case Prlimit:
		break;

	default:
		panic("procfs_getattr");
	}
done:
	if (procp)
		PRELE(procp);
	return (error);
}