Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/fs/udf Posix requires the va_size of a symlink to be pat...



details:   https://anonhg.NetBSD.org/src/rev/cf10db1691d3
branches:  trunk
changeset: 331057:cf10db1691d3
user:      reinoud <reinoud%NetBSD.org@localhost>
date:      Tue Jul 29 15:48:22 2014 +0000

description:
Posix requires the va_size of a symlink to be pathlength for symbolic links.
This fixes yet another atf case.

diffstat:

 sys/fs/udf/udf_vnops.c |  109 ++++++++++++++++++++++++++++++++----------------
 1 files changed, 73 insertions(+), 36 deletions(-)

diffs (206 lines):

diff -r 8bf394916789 -r cf10db1691d3 sys/fs/udf/udf_vnops.c
--- a/sys/fs/udf/udf_vnops.c    Tue Jul 29 15:36:43 2014 +0000
+++ b/sys/fs/udf/udf_vnops.c    Tue Jul 29 15:48:22 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_vnops.c,v 1.93 2014/07/29 11:10:12 reinoud Exp $ */
+/* $NetBSD: udf_vnops.c,v 1.94 2014/07/29 15:48:22 reinoud Exp $ */
 
 /*
  * Copyright (c) 2006, 2008 Reinoud Zandijk
@@ -32,7 +32,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.93 2014/07/29 11:10:12 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.94 2014/07/29 15:48:22 reinoud Exp $");
 #endif /* not lint */
 
 
@@ -67,6 +67,9 @@
 
 #define VTOI(vnode) ((struct udf_node *) (vnode)->v_data)
 
+/* forward declarations */
+static int udf_do_readlink(struct udf_node *udf_node, uint64_t filesize,
+       uint8_t *targetbuf, int *length);
 
 /* externs */
 extern int prtactive;
@@ -865,10 +868,10 @@
        uint64_t filesize, blkssize;
        uint32_t nlink;
        uint32_t offset, a_l;
-       uint8_t *filedata;
+       uint8_t *filedata, *targetbuf;
        uid_t uid;
        gid_t gid;
-       int error;
+       int length, error;
 
        DPRINTF(CALL, ("udf_getattr called\n"));
 
@@ -939,6 +942,22 @@
        if (vap->va_type == VDIR)
                vap->va_nlink++;
 
+       /*
+        * BUG-ALERT: Posix requires the va_size to be pathlength for symbolic
+        * links.
+        */
+       if (vap->va_type == VLNK) {
+               /* claim temporary buffers for translation */
+               targetbuf = malloc(PATH_MAX+1, M_UDFTEMP, M_WAITOK);
+               error = udf_do_readlink(udf_node, filesize, targetbuf, &length);
+               if (!error) {
+                       vap->va_size = length;
+                       KASSERT(length == strlen(targetbuf));
+               }
+               free(targetbuf, M_UDFTEMP);
+               /* XXX return error? */
+       }
+
        /* access times */
        udf_timestamp_to_timespec(ump, atime,    &vap->va_atime);
        udf_timestamp_to_timespec(ump, mtime,    &vap->va_mtime);
@@ -1730,49 +1749,30 @@
 
 /* --------------------------------------------------------------------- */
 
-int
-udf_readlink(void *v)
+static int
+udf_do_readlink(struct udf_node *udf_node, uint64_t filesize,
+       uint8_t *targetbuf, int *length)
 {
-       struct vop_readlink_args /* {
-               struct vnode *a_vp;
-               struct uio *a_uio;
-               kauth_cred_t a_cred;
-       } */ *ap = v;
-       struct vnode *vp = ap->a_vp;
-       struct uio *uio = ap->a_uio;
-       kauth_cred_t cred = ap->a_cred;
-       struct udf_node *udf_node;
        struct pathcomp pathcomp;
-       struct vattr vattr;
-       uint8_t *pathbuf, *targetbuf, *tmpname;
+       uint8_t *pathbuf, *tmpname;
        uint8_t *pathpos, *targetpos;
        char *mntonname;
        int pathlen, targetlen, namelen, mntonnamelen, len, l_ci;
        int first, error;
 
-       DPRINTF(CALL, ("udf_readlink called\n"));
-
-       udf_node = VTOI(vp);
-       error = VOP_GETATTR(vp, &vattr, cred);
-       if (error)
-               return error;
-
-       /* claim temporary buffers for translation */
        pathbuf   = malloc(UDF_SYMLINKBUFLEN, M_UDFTEMP, M_WAITOK);
-       targetbuf = malloc(PATH_MAX+1, M_UDFTEMP, M_WAITOK);
        tmpname   = malloc(PATH_MAX+1, M_UDFTEMP, M_WAITOK);
        memset(pathbuf, 0, UDF_SYMLINKBUFLEN);
        memset(targetbuf, 0, PATH_MAX);
 
        /* read contents of file in our temporary buffer */
        error = vn_rdwr(UIO_READ, udf_node->vnode,
-               pathbuf, vattr.va_size, 0,
+               pathbuf, filesize, 0,
                UIO_SYSSPACE, IO_NODELOCKED | IO_ALTSEMANTICS,
                FSCRED, NULL, NULL);
        if (error) {
                /* failed to read in symlink contents */
                free(pathbuf, M_UDFTEMP);
-               free(targetbuf, M_UDFTEMP);
                free(tmpname, M_UDFTEMP);
                return error;
        }
@@ -1787,7 +1787,7 @@
 
        error = 0;
        first = 1;
-       while (vattr.va_size - pathlen >= UDF_PATH_COMP_SIZE) {
+       while (filesize - pathlen >= UDF_PATH_COMP_SIZE) {
                len = UDF_PATH_COMP_SIZE;
                memcpy(&pathcomp, pathpos, len);
                l_ci = pathcomp.l_ci;
@@ -1808,7 +1808,7 @@
                        }
                        memcpy(targetpos, mntonname, mntonnamelen);
                        targetpos += mntonnamelen; targetlen -= mntonnamelen;
-                       if (vattr.va_size-pathlen > UDF_PATH_COMP_SIZE+l_ci) {
+                       if (filesize-pathlen > UDF_PATH_COMP_SIZE+l_ci) {
                                /* more follows, so must be directory */
                                *targetpos++ = '/'; targetlen--;
                        }
@@ -1849,7 +1849,7 @@
                        }
                        memcpy(targetpos, tmpname, namelen);
                        targetpos += namelen; targetlen -= namelen;
-                       if (vattr.va_size-pathlen > UDF_PATH_COMP_SIZE+l_ci) {
+                       if (filesize-pathlen > UDF_PATH_COMP_SIZE+l_ci) {
                                /* more follows, so must be directory */
                                *targetpos++ = '/'; targetlen--;
                        }
@@ -1866,17 +1866,54 @@
 
        }
        /* all processed? */
-       if (vattr.va_size - pathlen > 0)
+       if (filesize - pathlen > 0)
                error = EINVAL;
 
+       free(pathbuf, M_UDFTEMP);
+       free(tmpname, M_UDFTEMP);
+
+       *length = PATH_MAX - targetlen;
+       return error;
+}
+
+
+int
+udf_readlink(void *v)
+{
+       struct vop_readlink_args /* {
+               struct vnode *a_vp;
+               struct uio *a_uio;
+               kauth_cred_t a_cred;
+       } */ *ap = v;
+       struct vnode *vp = ap->a_vp;
+       struct udf_node *udf_node = VTOI(vp);
+       struct file_entry    *fe  = udf_node->fe;
+       struct extfile_entry *efe = udf_node->efe;
+       struct uio *uio = ap->a_uio;
+       uint64_t filesize;
+       uint8_t *targetbuf;
+       int length;
+       int error;
+
+       DPRINTF(CALL, ("udf_readlink called\n"));
+
+       if (fe) {
+               filesize = udf_rw64(fe->inf_len);
+       } else {
+               assert(udf_node->efe);
+               filesize = udf_rw64(efe->inf_len);
+       }
+
+       /* claim temporary buffers for translation */
+       targetbuf = malloc(PATH_MAX+1, M_UDFTEMP, M_WAITOK);
+
+       error = udf_do_readlink(udf_node, filesize, targetbuf, &length);
+
        /* uiomove() to destination */
        if (!error)
-               uiomove(targetbuf, PATH_MAX - targetlen, uio);
+               uiomove(targetbuf, length, uio);
 
-       free(pathbuf, M_UDFTEMP);
        free(targetbuf, M_UDFTEMP);
-       free(tmpname, M_UDFTEMP);
-
        return error;
 }
 



Home | Main Index | Thread Index | Old Index