mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Ensure that dirent's d_off field is initialized
We have the d_off field in struct dirent for providing the seek offset of the next directory entry. Several filesystems were not initializing the field, which ends up being copied out to userland. Reported by: Syed Faraz Abrar <faraz@elttam.com> Reviewed by: kib MFC after: 3 days Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D27792
This commit is contained in:
parent
663de81f85
commit
90f580b954
4 changed files with 36 additions and 18 deletions
|
|
@ -367,6 +367,7 @@ autofs_readdir_one(struct uio *uio, const char *name, int fileno,
|
|||
return (EINVAL);
|
||||
|
||||
dirent.d_fileno = fileno;
|
||||
dirent.d_off = uio->uio_offset + reclen;
|
||||
dirent.d_reclen = reclen;
|
||||
dirent.d_type = DT_DIR;
|
||||
dirent.d_namlen = namlen;
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ smbfs_readvdir(struct vnode *vp, struct uio *uio, struct ucred *cred)
|
|||
(np->n_parent ? np->n_parentino : 2);
|
||||
if (de.d_fileno == 0)
|
||||
de.d_fileno = 0x7ffffffd + offset;
|
||||
de.d_off = offset + 1;
|
||||
de.d_namlen = offset + 1;
|
||||
de.d_name[0] = '.';
|
||||
de.d_name[1] = '.';
|
||||
|
|
@ -152,6 +153,7 @@ smbfs_readvdir(struct vnode *vp, struct uio *uio, struct ucred *cred)
|
|||
bzero((caddr_t)&de, DE_SIZE);
|
||||
de.d_reclen = DE_SIZE;
|
||||
de.d_fileno = ctx->f_attr.fa_ino;
|
||||
de.d_off = offset + 1;
|
||||
de.d_type = (ctx->f_attr.fa_attr & SMB_FA_DIR) ? DT_DIR : DT_REG;
|
||||
de.d_namlen = ctx->f_nmlen;
|
||||
bcopy(ctx->f_name, de.d_name, de.d_namlen);
|
||||
|
|
|
|||
|
|
@ -1187,6 +1187,7 @@ tmpfs_dir_getdotdent(struct tmpfs_mount *tm, struct tmpfs_node *node,
|
|||
MPASS(uio->uio_offset == TMPFS_DIRCOOKIE_DOT);
|
||||
|
||||
dent.d_fileno = node->tn_id;
|
||||
dent.d_off = TMPFS_DIRCOOKIE_DOTDOT;
|
||||
dent.d_type = DT_DIR;
|
||||
dent.d_namlen = 1;
|
||||
dent.d_name[0] = '.';
|
||||
|
|
@ -1212,7 +1213,7 @@ tmpfs_dir_getdotdent(struct tmpfs_mount *tm, struct tmpfs_node *node,
|
|||
*/
|
||||
static int
|
||||
tmpfs_dir_getdotdotdent(struct tmpfs_mount *tm, struct tmpfs_node *node,
|
||||
struct uio *uio)
|
||||
struct uio *uio, off_t next)
|
||||
{
|
||||
struct tmpfs_node *parent;
|
||||
struct dirent dent;
|
||||
|
|
@ -1233,6 +1234,7 @@ tmpfs_dir_getdotdotdent(struct tmpfs_mount *tm, struct tmpfs_node *node,
|
|||
dent.d_fileno = parent->tn_id;
|
||||
TMPFS_NODE_UNLOCK(parent);
|
||||
|
||||
dent.d_off = next;
|
||||
dent.d_type = DT_DIR;
|
||||
dent.d_namlen = 2;
|
||||
dent.d_name[0] = '.';
|
||||
|
|
@ -1262,7 +1264,7 @@ tmpfs_dir_getdents(struct tmpfs_mount *tm, struct tmpfs_node *node,
|
|||
struct uio *uio, int maxcookies, u_long *cookies, int *ncookies)
|
||||
{
|
||||
struct tmpfs_dir_cursor dc;
|
||||
struct tmpfs_dirent *de;
|
||||
struct tmpfs_dirent *de, *nde;
|
||||
off_t off;
|
||||
int error;
|
||||
|
||||
|
|
@ -1283,18 +1285,19 @@ tmpfs_dir_getdents(struct tmpfs_mount *tm, struct tmpfs_node *node,
|
|||
error = tmpfs_dir_getdotdent(tm, node, uio);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
uio->uio_offset = TMPFS_DIRCOOKIE_DOTDOT;
|
||||
uio->uio_offset = off = TMPFS_DIRCOOKIE_DOTDOT;
|
||||
if (cookies != NULL)
|
||||
cookies[(*ncookies)++] = off = uio->uio_offset;
|
||||
cookies[(*ncookies)++] = off;
|
||||
/* FALLTHROUGH */
|
||||
case TMPFS_DIRCOOKIE_DOTDOT:
|
||||
error = tmpfs_dir_getdotdotdent(tm, node, uio);
|
||||
de = tmpfs_dir_first(node, &dc);
|
||||
off = tmpfs_dirent_cookie(de);
|
||||
error = tmpfs_dir_getdotdotdent(tm, node, uio, off);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
de = tmpfs_dir_first(node, &dc);
|
||||
uio->uio_offset = tmpfs_dirent_cookie(de);
|
||||
uio->uio_offset = off;
|
||||
if (cookies != NULL)
|
||||
cookies[(*ncookies)++] = off = uio->uio_offset;
|
||||
cookies[(*ncookies)++] = off;
|
||||
/* EOF. */
|
||||
if (de == NULL)
|
||||
return (0);
|
||||
|
|
@ -1309,13 +1312,17 @@ tmpfs_dir_getdents(struct tmpfs_mount *tm, struct tmpfs_node *node,
|
|||
off = tmpfs_dirent_cookie(de);
|
||||
}
|
||||
|
||||
/* Read as much entries as possible; i.e., until we reach the end of
|
||||
* the directory or we exhaust uio space. */
|
||||
/*
|
||||
* Read as much entries as possible; i.e., until we reach the end of the
|
||||
* directory or we exhaust uio space.
|
||||
*/
|
||||
do {
|
||||
struct dirent d;
|
||||
|
||||
/* Create a dirent structure representing the current
|
||||
* tmpfs_node and fill it. */
|
||||
/*
|
||||
* Create a dirent structure representing the current tmpfs_node
|
||||
* and fill it.
|
||||
*/
|
||||
if (de->td_node == NULL) {
|
||||
d.d_fileno = 1;
|
||||
d.d_type = DT_WHT;
|
||||
|
|
@ -1359,20 +1366,27 @@ tmpfs_dir_getdents(struct tmpfs_mount *tm, struct tmpfs_node *node,
|
|||
MPASS(de->td_namelen < sizeof(d.d_name));
|
||||
(void)memcpy(d.d_name, de->ud.td_name, de->td_namelen);
|
||||
d.d_reclen = GENERIC_DIRSIZ(&d);
|
||||
dirent_terminate(&d);
|
||||
|
||||
/* Stop reading if the directory entry we are treating is
|
||||
* bigger than the amount of data that can be returned. */
|
||||
/*
|
||||
* Stop reading if the directory entry we are treating is bigger
|
||||
* than the amount of data that can be returned.
|
||||
*/
|
||||
if (d.d_reclen > uio->uio_resid) {
|
||||
error = EJUSTRETURN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy the new dirent structure into the output buffer and
|
||||
* advance pointers. */
|
||||
nde = tmpfs_dir_next(node, &dc);
|
||||
d.d_off = tmpfs_dirent_cookie(nde);
|
||||
dirent_terminate(&d);
|
||||
|
||||
/*
|
||||
* Copy the new dirent structure into the output buffer and
|
||||
* advance pointers.
|
||||
*/
|
||||
error = uiomove(&d, d.d_reclen, uio);
|
||||
if (error == 0) {
|
||||
de = tmpfs_dir_next(node, &dc);
|
||||
de = nde;
|
||||
if (cookies != NULL) {
|
||||
off = tmpfs_dirent_cookie(de);
|
||||
MPASS(*ncookies < maxcookies);
|
||||
|
|
|
|||
|
|
@ -1425,6 +1425,7 @@ mqfs_readdir(struct vop_readdir_args *ap)
|
|||
if (!pn->mn_fileno)
|
||||
mqfs_fileno_alloc(mi, pn);
|
||||
entry.d_fileno = pn->mn_fileno;
|
||||
entry.d_off = offset + entry.d_reclen;
|
||||
for (i = 0; i < MQFS_NAMELEN - 1 && pn->mn_name[i] != '\0'; ++i)
|
||||
entry.d_name[i] = pn->mn_name[i];
|
||||
entry.d_namlen = i;
|
||||
|
|
|
|||
Loading…
Reference in a new issue