svn commit: r229929 - stable/9/sys/fs/pseudofs
Peter Holm
pho at FreeBSD.org
Tue Jan 10 11:41:03 UTC 2012
Author: pho
Date: Tue Jan 10 11:41:02 2012
New Revision: 229929
URL: http://svn.freebsd.org/changeset/base/229929
Log:
MFC: r227550, r227576
Handle invalid large values for getdirentries(2) data buffer size.
Fix build, use %d for int value formatting.
Modified:
stable/9/sys/fs/pseudofs/pseudofs_vnops.c
Directory Properties:
stable/9/sys/ (props changed)
stable/9/sys/amd64/include/xen/ (props changed)
stable/9/sys/boot/ (props changed)
stable/9/sys/boot/i386/efi/ (props changed)
stable/9/sys/boot/ia64/efi/ (props changed)
stable/9/sys/boot/ia64/ski/ (props changed)
stable/9/sys/boot/powerpc/boot1.chrp/ (props changed)
stable/9/sys/boot/powerpc/ofw/ (props changed)
stable/9/sys/cddl/contrib/opensolaris/ (props changed)
stable/9/sys/conf/ (props changed)
stable/9/sys/contrib/dev/acpica/ (props changed)
stable/9/sys/contrib/octeon-sdk/ (props changed)
stable/9/sys/contrib/pf/ (props changed)
stable/9/sys/contrib/x86emu/ (props changed)
Modified: stable/9/sys/fs/pseudofs/pseudofs_vnops.c
==============================================================================
--- stable/9/sys/fs/pseudofs/pseudofs_vnops.c Tue Jan 10 08:41:10 2012 (r229928)
+++ stable/9/sys/fs/pseudofs/pseudofs_vnops.c Tue Jan 10 11:41:02 2012 (r229929)
@@ -710,6 +710,13 @@ pfs_iterate(struct thread *td, struct pr
return (0);
}
+/* Directory entry list */
+struct pfsentry {
+ STAILQ_ENTRY(pfsentry) link;
+ struct dirent entry;
+};
+STAILQ_HEAD(pfsdirentlist, pfsentry);
+
/*
* Return directory entries.
*/
@@ -722,12 +729,14 @@ pfs_readdir(struct vop_readdir_args *va)
pid_t pid = pvd->pvd_pid;
struct proc *p, *proc;
struct pfs_node *pn;
- struct dirent *entry;
struct uio *uio;
+ struct pfsentry *pfsent, *pfsent2;
+ struct pfsdirentlist lst;
off_t offset;
int error, i, resid;
- char *buf, *ent;
+ STAILQ_INIT(&lst);
+ error = 0;
KASSERT(pd->pn_info == vn->v_mount->mnt_data,
("%s(): pn_info does not match mountpoint", __func__));
PFS_TRACE(("%s pid %lu", pd->pn_name, (unsigned long)pid));
@@ -747,8 +756,6 @@ pfs_readdir(struct vop_readdir_args *va)
if (resid == 0)
PFS_RETURN (0);
- /* can't do this while holding the proc lock... */
- buf = malloc(resid, M_IOV, M_WAITOK | M_ZERO);
sx_slock(&allproc_lock);
pfs_lock(pd);
@@ -756,7 +763,6 @@ pfs_readdir(struct vop_readdir_args *va)
if (!pfs_visible(curthread, pd, pid, &proc)) {
sx_sunlock(&allproc_lock);
pfs_unlock(pd);
- free(buf, M_IOV);
PFS_RETURN (ENOENT);
}
KASSERT(pid == NO_PID || proc != NULL,
@@ -770,57 +776,64 @@ pfs_readdir(struct vop_readdir_args *va)
PROC_UNLOCK(proc);
pfs_unlock(pd);
sx_sunlock(&allproc_lock);
- free(buf, M_IOV);
PFS_RETURN (0);
}
}
/* fill in entries */
- ent = buf;
while (pfs_iterate(curthread, proc, pd, &pn, &p) != -1 &&
resid >= PFS_DELEN) {
- entry = (struct dirent *)ent;
- entry->d_reclen = PFS_DELEN;
- entry->d_fileno = pn_fileno(pn, pid);
+ if ((pfsent = malloc(sizeof(struct pfsentry), M_IOV,
+ M_NOWAIT | M_ZERO)) == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ pfsent->entry.d_reclen = PFS_DELEN;
+ pfsent->entry.d_fileno = pn_fileno(pn, pid);
/* PFS_DELEN was picked to fit PFS_NAMLEN */
for (i = 0; i < PFS_NAMELEN - 1 && pn->pn_name[i] != '\0'; ++i)
- entry->d_name[i] = pn->pn_name[i];
- entry->d_name[i] = 0;
- entry->d_namlen = i;
+ pfsent->entry.d_name[i] = pn->pn_name[i];
+ pfsent->entry.d_name[i] = 0;
+ pfsent->entry.d_namlen = i;
switch (pn->pn_type) {
case pfstype_procdir:
KASSERT(p != NULL,
("reached procdir node with p == NULL"));
- entry->d_namlen = snprintf(entry->d_name,
+ pfsent->entry.d_namlen = snprintf(pfsent->entry.d_name,
PFS_NAMELEN, "%d", p->p_pid);
/* fall through */
case pfstype_root:
case pfstype_dir:
case pfstype_this:
case pfstype_parent:
- entry->d_type = DT_DIR;
+ pfsent->entry.d_type = DT_DIR;
break;
case pfstype_file:
- entry->d_type = DT_REG;
+ pfsent->entry.d_type = DT_REG;
break;
case pfstype_symlink:
- entry->d_type = DT_LNK;
+ pfsent->entry.d_type = DT_LNK;
break;
default:
panic("%s has unexpected node type: %d", pn->pn_name, pn->pn_type);
}
- PFS_TRACE(("%s", entry->d_name));
+ PFS_TRACE(("%s", pfsent->entry.d_name));
+ STAILQ_INSERT_TAIL(&lst, pfsent, link);
offset += PFS_DELEN;
resid -= PFS_DELEN;
- ent += PFS_DELEN;
}
if (proc != NULL)
PROC_UNLOCK(proc);
pfs_unlock(pd);
sx_sunlock(&allproc_lock);
- PFS_TRACE(("%zd bytes", ent - buf));
- error = uiomove(buf, ent - buf, uio);
- free(buf, M_IOV);
+ i = 0;
+ STAILQ_FOREACH_SAFE(pfsent, &lst, link, pfsent2) {
+ if (error == 0)
+ error = uiomove(&pfsent->entry, PFS_DELEN, uio);
+ free(pfsent, M_IOV);
+ i++;
+ }
+ PFS_TRACE(("%d bytes", i * PFS_DELEN));
PFS_RETURN (error);
}
More information about the svn-src-stable-9
mailing list