diff options
author | scottl <scottl@FreeBSD.org> | 2002-08-04 16:42:20 +0000 |
---|---|---|
committer | scottl <scottl@FreeBSD.org> | 2002-08-04 16:42:20 +0000 |
commit | e0f60db94f5036899acf8724bb839c38f0135934 (patch) | |
tree | f6bd5413689492f8413516e5def8883c795f54cb /sys/fs | |
parent | fe9a9d5bc504712effcb45b218d52d5e0d6c480a (diff) | |
download | FreeBSD-src-e0f60db94f5036899acf8724bb839c38f0135934.zip FreeBSD-src-e0f60db94f5036899acf8724bb839c38f0135934.tar.gz |
Simplify the handling of a fragmented file_id descriptor. Also
de-obfuscate the file_char flags.
Diffstat (limited to 'sys/fs')
-rw-r--r-- | sys/fs/udf/ecma167-udf.h | 5 | ||||
-rw-r--r-- | sys/fs/udf/udf_vnops.c | 96 |
2 files changed, 50 insertions, 51 deletions
diff --git a/sys/fs/udf/ecma167-udf.h b/sys/fs/udf/ecma167-udf.h index b8b6eaa..149a4da 100644 --- a/sys/fs/udf/ecma167-udf.h +++ b/sys/fs/udf/ecma167-udf.h @@ -318,6 +318,11 @@ struct fileid_desc { uint8_t data[1]; } __attribute__ ((packed)); #define UDF_FID_SIZE 38 +#define UDF_FILE_CHAR_VIS (1 << 0) /* Visible */ +#define UDF_FILE_CHAR_DIR (1 << 1) /* Directory */ +#define UDF_FILE_CHAR_DEL (1 << 2) /* Deleted */ +#define UDF_FILE_CHAR_PAR (1 << 3) /* Parent Directory */ +#define UDF_FILE_CHAR_META (1 << 4) /* Stream metadata */ /* File Entry [4/14.9] */ struct file_entry { diff --git a/sys/fs/udf/udf_vnops.c b/sys/fs/udf/udf_vnops.c index 6701a9b..9141d3b 100644 --- a/sys/fs/udf/udf_vnops.c +++ b/sys/fs/udf/udf_vnops.c @@ -546,7 +546,7 @@ udf_readdir(struct vop_readdir_args *a) struct fileid_desc *fid; struct udf_uiodir uiodir; u_long *cookies = NULL; - uint8_t *data; + uint8_t *data, *buf; int ncookies; int error = 0, offset, off, size, de_size, fid_size, fsize; int total_fid_size = 0, frag_size = 0, fid_fragment = 0; @@ -611,19 +611,24 @@ udf_readdir(struct vop_readdir_args *a) */ if (off + fid_size > size || off + fid->l_iu + fid->l_fi + fid_size > size) { - struct fileid_desc *fid_buf; - uint8_t *buf; /* Copy what we have of the fid into a buffer */ frag_size = size - off; - MALLOC(buf, uint8_t*, max(frag_size, fid_size), - M_UDFFID, M_NOWAIT | M_ZERO); - if (buf == NULL) - panic("No memory?"); + if (frag_size >= udfmp->bsize) { + printf("udf: invalid FID fragment\n"); + break; + } + + /* + * File ID descriptors can only be at most one + * logical sector in size. + */ + MALLOC(buf, uint8_t*, udfmp->bsize, M_UDFFID, + M_WAITOK | M_ZERO); bcopy(fid, buf, frag_size); /* Reduce all of the casting magic */ - fid_buf = (struct fileid_desc*)buf; + fid = (struct fileid_desc*)buf; if (bp != NULL) brelse(bp); @@ -646,26 +651,18 @@ udf_readdir(struct vop_readdir_args *a) /* * Now that we have enough of the fid to work with, - * allocate a new fid, copy the fragment into it, - * and copy the rest of the fid from the new + * copy in the rest of the fid from the new * allocation. */ - total_fid_size = fid_size + fid_buf->l_iu + - fid_buf->l_fi; - MALLOC(fid, struct fileid_desc *, total_fid_size, - M_UDFFID, M_NOWAIT | M_ZERO); - if (fid == NULL) { - if (bp != NULL) - brelse(bp); - error = ENOMEM; + total_fid_size = fid_size + fid->l_iu + fid->l_fi; + if (total_fid_size > udfmp->bsize) { + printf("udf: invalid FID\n"); break; } - bcopy(fid_buf, fid, frag_size); - bcopy(data, &((uint8_t*)(fid))[frag_size], + bcopy(data, &buf[frag_size], total_fid_size - frag_size); fid_fragment = 1; - FREE(buf, M_UDFFID); } else { total_fid_size = fid->l_iu + fid->l_fi + fid_size; } @@ -677,7 +674,7 @@ udf_readdir(struct vop_readdir_args *a) } /* Is this a deleted file? */ - if (fid->file_char & 0x4) + if (fid->file_char & UDF_FILE_CHAR_DEL) goto update_offset; if (fid->l_iu != 0) { @@ -685,7 +682,7 @@ udf_readdir(struct vop_readdir_args *a) goto update_offset; } - if ((fid->l_fi == 0) && (fid->file_char & 0x08)) { + if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) { /* Do up the '.' and '..' entries. Dummy values are * used for the cookies since the offset here is * usually zero, and NFS doesn't like that value @@ -704,8 +701,8 @@ udf_readdir(struct vop_readdir_args *a) dir.d_namlen = udf_transname(&fid->data[fid->l_iu], &dir.d_name[0], fid->l_fi); dir.d_fileno = udf_getid(&fid->icb); - dir.d_type = (fid->file_char & 0x02) ? DT_DIR : - DT_UNKNOWN; + dir.d_type = (fid->file_char & UDF_FILE_CHAR_DIR) ? + DT_DIR : DT_UNKNOWN; dir.d_reclen = GENERIC_DIRSIZ(&dir); uiodir.dirent = &dir; error = udf_uiodir(&uiodir, dir.d_reclen, uio, off); @@ -847,10 +844,10 @@ udf_lookup(struct vop_cachedlookup_args *a) char *nameptr; long namelen; ino_t id = 0; - uint8_t *data; + uint8_t *data, *buf; int offset, off, error, size; int numdirpasses, fid_size, fsize, icb_len; - int total_fid_size = 0, fid_fragment = 0; + int total_fid_size = 0, fid_fragment = 0, frag_size = 0; dvp = a->a_dvp; node = VTON(dvp); @@ -900,20 +897,24 @@ lookloop: */ if (off + fid_size > size || off + fid_size + fid->l_iu + fid->l_fi > size) { - struct fileid_desc *fid_buf; - uint8_t *buf; - int frag_size = 0; - /* Copy what we have of the fid into a buffer */ frag_size = size - off; - MALLOC(buf, uint8_t*, max(frag_size, fid_size), - M_UDFFID, M_NOWAIT | M_ZERO); - if (buf == NULL) - panic("No memory?"); + if (frag_size >= udfmp->bsize) { + printf("udf: invalid FID fragment\n"); + break; + } + + /* + * File ID descriptors can only be at most one + * logical sector in size. + * Copy what we have of the fid into a buffer + */ + MALLOC(buf, uint8_t*, udfmp->bsize, M_UDFFID, + M_WAITOK | M_ZERO); bcopy(fid, buf, frag_size); /* Reduce all of the casting magic */ - fid_buf = (struct fileid_desc*)buf; + fid = (struct fileid_desc*)buf; if (bp != NULL) brelse(bp); @@ -936,26 +937,19 @@ lookloop: /* * Now that we have enough of the fid to work with, - * allocate a new fid, copy the fragment into it, - * and copy the rest of the fid from the new + * copy the rest of the fid from the new * allocation. */ - total_fid_size = fid_size + fid_buf->l_iu + - fid_buf->l_fi; - MALLOC(fid, struct fileid_desc *, total_fid_size, - M_UDFFID, M_NOWAIT | M_ZERO); - if (fid == NULL) { - if (bp != NULL) - brelse(bp); - return (ENOMEM); + total_fid_size = fid_size + fid->l_iu + fid->l_fi; + if (total_fid_size > udfmp->bsize) { + printf("udf: invalid FID\n"); + break; } - bcopy(fid_buf, fid, frag_size); - bcopy(data, &((uint8_t*)(fid))[frag_size], + bcopy(data, &buf[frag_size], total_fid_size - frag_size); off = (total_fid_size - frag_size + 3) & ~0x03; fid_fragment = 1; - FREE(buf, M_UDFFID); } else { /* * Update the offset here to avoid looking at this fid @@ -970,10 +964,10 @@ lookloop: goto continue_lookup; /* Is this a deleted file? */ - if (fid->file_char & 0x4) + if (fid->file_char & UDF_FILE_CHAR_DEL) goto continue_lookup; - if ((fid->l_fi == 0) && (fid->file_char & 0x08)) { + if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) { if (flags & ISDOTDOT) { id = udf_getid(&fid->icb); break; |