Source-Changes-HG archive

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

[src/trunk]: src/sys/fs/udf Fix filename creation and deleting with illegal f...



details:   https://anonhg.NetBSD.org/src/rev/3bc7c474e026
branches:  trunk
changeset: 813417:3bc7c474e026
user:      reinoud <reinoud%NetBSD.org@localhost>
date:      Wed Jan 27 00:06:49 2016 +0000

description:
Fix filename creation and deleting with illegal file names. UDF has a
machanism for it but it allowed to create a file with a name it considered
illegal that then couldn't be deleted with the same name.

Fixes PR kern/50608. When confirmed, it can be closed.

diffstat:

 sys/fs/udf/udf_subr.c |  67 ++++++++++++++++++++++++++++++--------------------
 1 files changed, 40 insertions(+), 27 deletions(-)

diffs (153 lines):

diff -r 13bf71659690 -r 3bc7c474e026 sys/fs/udf/udf_subr.c
--- a/sys/fs/udf/udf_subr.c     Tue Jan 26 23:49:46 2016 +0000
+++ b/sys/fs/udf/udf_subr.c     Wed Jan 27 00:06:49 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_subr.c,v 1.135 2015/12/19 03:16:09 dholland Exp $ */
+/* $NetBSD: udf_subr.c,v 1.136 2016/01/27 00:06:49 reinoud Exp $ */
 
 /*
  * Copyright (c) 2006, 2008 Reinoud Zandijk
@@ -29,7 +29,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.135 2015/12/19 03:16:09 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.136 2016/01/27 00:06:49 reinoud Exp $");
 #endif /* not lint */
 
 
@@ -4486,7 +4486,8 @@
        struct dirhash       *dirh;
        struct dirhash_entry *dirh_ep;
        struct fileid_desc *fid;
-       struct dirent *dirent;
+       struct dirent *dirent, *s_dirent;
+       struct charspec osta_charspec;
        uint64_t diroffset;
        uint32_t lb_size;
        int hit, error;
@@ -4504,18 +4505,28 @@
        dirh = dir_node->dir_hash;
 
        /* allocate temporary space for fid */
-       lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size);
-       fid     = malloc(lb_size, M_UDFTEMP, M_WAITOK);
-       dirent  = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK);
+       lb_size  = udf_rw32(dir_node->ump->logical_vol->lb_size);
+       fid      = malloc(lb_size, M_UDFTEMP, M_WAITOK);
+       dirent   = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK);
+       s_dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK);
 
        DPRINTF(DIRHASH, ("dirhash_lookup looking for `%*.*s`\n",
                namelen, namelen, name));
 
+       /* convert given unix name to canonical unix name */
+       udf_osta_charset(&osta_charspec);
+       unix_to_udf_name((char *) fid->data, &fid->l_fi,
+               name, namelen, &osta_charspec);
+       udf_to_unix_name(s_dirent->d_name, NAME_MAX,
+               (char *) fid->data, fid->l_fi,
+               &osta_charspec);
+       s_dirent->d_namlen = strlen(s_dirent->d_name);
+
        /* search our dirhash hits */
        memset(icb_loc, 0, sizeof(*icb_loc));
        dirh_ep = NULL;
        for (;;) {
-               hit = dirhash_lookup(dirh, name, namelen, &dirh_ep);
+               hit = dirhash_lookup(dirh, s_dirent->d_name, s_dirent->d_namlen, &dirh_ep);
                /* if no hit, abort the search */
                if (!hit)
                        break;
@@ -4532,16 +4543,7 @@
                        dirent->d_namlen, dirent->d_namlen, dirent->d_name));
 
                /* see if its our entry */
-#ifdef DIAGNOSTIC
-               if (dirent->d_namlen != namelen) {
-                       printf("WARNING: dirhash_lookup() returned wrong "
-                               "d_namelen: %d and ought to be %d\n",
-                               dirent->d_namlen, namelen);
-                       printf("\tlooked for `%s' and got `%s'\n",
-                               name, dirent->d_name);
-               }
-#endif
-               if (strncmp(dirent->d_name, name, namelen) == 0) {
+               if (strncmp(dirent->d_name, s_dirent->d_name, s_dirent->d_namlen) == 0) {
                        *found = 1;
                        *icb_loc = fid->icb;
                        break;
@@ -4549,6 +4551,7 @@
        }
        free(fid, M_UDFTEMP);
        free(dirent, M_UDFTEMP);
+       free(s_dirent, M_UDFTEMP);
 
        dirhash_put(dir_node->dir_hash);
 
@@ -4718,12 +4721,11 @@
        struct dirhash_entry *dirh_ep;
        struct file_entry    *fe  = dir_node->fe;
        struct fileid_desc *fid;
-       struct dirent *dirent;
+       struct dirent *dirent, *s_dirent;
+       struct charspec osta_charspec;
        uint64_t diroffset;
        uint32_t lb_size, fidsize;
        int found, error;
-       char const *name  = cnp->cn_nameptr;
-       int namelen = cnp->cn_namelen;
        int hit, refcnt;
 
        /* get our dirhash and make sure its read in */
@@ -4740,16 +4742,26 @@
                assert(dir_node->efe);
        }
 
-       /* allocate temporary space for fid */
-       lb_size = udf_rw32(dir_node->ump->logical_vol->lb_size);
-       fid     = malloc(lb_size, M_UDFTEMP, M_WAITOK);
-       dirent  = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK);
+       /* allocate temporary space for fid and dirents */
+       lb_size  = udf_rw32(dir_node->ump->logical_vol->lb_size);
+       fid      = malloc(lb_size, M_UDFTEMP, M_WAITOK);
+       dirent   = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK);
+       s_dirent = malloc(sizeof(struct dirent), M_UDFTEMP, M_WAITOK);
+
+       /* convert given unix name to canonical unix name */
+       udf_osta_charset(&osta_charspec);
+       unix_to_udf_name((char *) fid->data, &fid->l_fi,
+               cnp->cn_nameptr, cnp->cn_namelen, &osta_charspec);
+       udf_to_unix_name(s_dirent->d_name, NAME_MAX,
+               (char *) fid->data, fid->l_fi,
+               &osta_charspec);
+       s_dirent->d_namlen = strlen(s_dirent->d_name);
 
        /* search our dirhash hits */
        found = 0;
        dirh_ep = NULL;
        for (;;) {
-               hit = dirhash_lookup(dirh, name, namelen, &dirh_ep);
+               hit = dirhash_lookup(dirh, s_dirent->d_name, s_dirent->d_namlen, &dirh_ep);
                /* if no hit, abort the search */
                if (!hit)
                        break;
@@ -4763,8 +4775,8 @@
                        break;
 
                /* see if its our entry */
-               KASSERT(dirent->d_namlen == namelen);
-               if (strncmp(dirent->d_name, name, namelen) == 0) {
+               KASSERT(dirent->d_namlen == s_dirent->d_namlen);
+               if (strncmp(dirent->d_name, s_dirent->d_name, s_dirent->d_namlen) == 0) {
                        found = 1;
                        break;
                }
@@ -4845,6 +4857,7 @@
 error_out:
        free(fid, M_UDFTEMP);
        free(dirent, M_UDFTEMP);
+       free(s_dirent, M_UDFTEMP);
 
        dirhash_put(dir_node->dir_hash);
 



Home | Main Index | Thread Index | Old Index