Re: [Yaffs] Maybe using a YFREED string in yaffs_DeleteSymLi…

Top Page
Attachments:
Message as email
+ (text/plain)
Delete this message
Reply to this message
Author: Chris David
Date:  
To: yaffs
CC: manningc2
Subject: Re: [Yaffs] Maybe using a YFREED string in yaffs_DeleteSymLink
Hi Charles,

I just realized I sent two messagens (with two patches) yesterday to
the wrong email address yesterday. Grumble, grumble....

Anyways, here is one....


On Wednesday 02 December 2009 12:58:52 Charles Manning wrote:
>
> What do you mean by "no longer mountable"?
>


here is the console output:

# echo 0x2018 > /sys/module/yaffs/parameters/yaffs_traceMask
# dmesg -n 8
# mount -t yaffs2 /dev/mtdblock6 /mnt/nand_var/
yaffs: dev is 32505862 name is "mtdblock6"
yaffs: passed flags ""
yaffs: Attempting MTD mount on 31.6, "mtdblock6"
yaffs_ScanBackwards starts  intstartblk 1 intendblk 896...
Block scanning block 1 state 2 seq 4097
Block scanning block 2 state 2 seq 4098
Block scanning block 3 state 3 seq 0
Block empty
Block scanning block 4 state 2 seq 4209
=== many similar messages deleted ===
Block scanning block 896 state 3 seq 0
Block empty
123 blocks to be sorted...
...done
123 blocks to be scanned
 Allocating from 142 63
 Allocating from 142 62
=== many similar messages deleted ===
 Allocating from 142 3
 Allocating from 142 2
mount: wrong fs type, bad option, bad superblock on /dev/mtdblock6,
       missing codepage or other error
       In some cases useful info is found in syslog - try
       dmesg | tail  or so


And then the fs is not mounted.

So, after analyzing what is happening, I determined that it made it to here:
yaffs_guts.c:6720
  case YAFFS_OBJECT_TYPE_SYMLINK:
    if (oh) {
      in->variant.symLinkVariant.alias = yaffs_CloneString(oh->alias);
      if (!in->variant.symLinkVariant.alias)
         alloc_failed = 1;
    }
    break;


I modified it to print out oh->alias, and also oh->name. oh->alias is
the empty string, which causes yaffs_CloneString(oh->alias) to return
NULL. oh->name had value "deleted". This what led me to discover the
issue.


Later On Wednesday 02 December 2009 Charles Manning wrote:
> Thanks David
>


You can call me Chris (my first name).

> There is definitely a problem if you unlink a symlink.
>
> I am a bit concerned about the apporach you propose because I don't like the
> idea of using the object after it has been deleted.
>
> Instead I propose to do something like:
> static int yaffs_DeleteSymLink(yaffs_Object * in)
> {
>          YFREE(in->variant.symLinkVariant.alias);
> +      in->variant.symLinkVariant = NULL;
>         return yaffs_DoGenericObjectDeletion(in);
> }

>
> then handling a NULL value properly where need be.
>
> -- Charles
>


Thanks for taking the time to review this. I see your point. I think
you mean:

 +      in->variant.symLinkVariant.alias = NULL;
                                   ^^^^^


So, I went down this path and below is the patch. (note this one
should apply successfully on CVS, unlike my last patch...)

I took care to allow mounting a filesystem in the condition my
"unmountable filesystem" is currently in. I left this comment in the
code in a couple spots to prevent others from changing the critical
part.

/* Note there used to be a bug where for
* deleted symlinks, .alias was copied
* from after a free. Therefore, the
* value of oh->alias must not be
* depended upon for deleted symlinks.
*/

I'm not sure I like this patch. It will work, but it seems to have
added many tests. I have tested this a little. I plan to test it
more. One thing I cannot easily test is the YAFFS1 case.

yaffs_CloneString() does not differentiate between being passed an empty
string to copy, and running out of memory. I was afraid to change it.
Perhaps that approach would have resulted in a smaller patch.

Is it important that a deleted symlink goes into the dev->deletedDir?


--- yaffs2.orig/yaffs_guts.c    2009-11-10 17:40:41.000000000 -0800
+++ yaffs2.fixed7/yaffs_guts.c  2009-12-02 11:23:36.000000000 -0800
@@ -3803,10 +3803,14 @@
                        /* Do nothing */
                        break;
                case YAFFS_OBJECT_TYPE_SYMLINK:
-                       yaffs_strncpy(oh->alias,
-                                     in->variant.symLinkVariant.alias,
-                                     YAFFS_MAX_ALIAS_LENGTH);
-                       oh->alias[YAFFS_MAX_ALIAS_LENGTH] = 0;
+                       if (! in->variant.symLinkVariant.alias)
+                               oh->alias[0] = 0;
+                       else {
+                               yaffs_strncpy(oh->alias,
+                                             in->variant.symLinkVariant.alias,
+                                             YAFFS_MAX_ALIAS_LENGTH);
+                               oh->alias[YAFFS_MAX_ALIAS_LENGTH] = 0;
+                       }
                        break;
                }


@@ -5089,6 +5093,8 @@
        case YAFFS_OBJECT_TYPE_FILE:
                return obj->variant.fileVariant.fileSize;
        case YAFFS_OBJECT_TYPE_SYMLINK:
+               if (!obj->variant.symLinkVariant.alias)
+                       return 0;
                return yaffs_strlen(obj->variant.symLinkVariant.alias);
        default:
                return 0;
@@ -5236,6 +5242,7 @@
 static int yaffs_DeleteSymLink(yaffs_Object *in)
 {
        YFREE(in->variant.symLinkVariant.alias);
+       in->variant.symLinkVariant.alias = NULL;


        return yaffs_DoGenericObjectDeletion(in);
 }
@@ -5974,10 +5981,20 @@
                                                /* Do nothing */
                                                break;
                                        case YAFFS_OBJECT_TYPE_SYMLINK:
-                                               in->variant.symLinkVariant.alias =
-                                                   yaffs_CloneString(oh->alias);
-                                               if (!in->variant.symLinkVariant.alias)
-                                                       alloc_failed = 1;
+                                               /* Note there used to be a bug where for
+                                                * deleted symlinks, .alias was copied
+                                                * from after a free.  Therefore, the
+                                                * value of oh->alias must not be
+                                                * depended upon for deleted symlinks.
+                                                */
+                                               if (oh->parentObjectId == YAFFS_OBJECTID_DELETED)
+                                                       in->variant.symLinkVariant.alias = NULL;
+                                               else {
+                                                       in->variant.symLinkVariant.alias =
+                                                       yaffs_CloneString(oh->alias);
+                                                       if (!in->variant.symLinkVariant.alias)
+                                                               alloc_failed = 1;
+                                               }
                                                break;
                                        }


@@ -6098,10 +6115,14 @@
                yaffs_SetObjectName(in, oh->name);


                if (in->variantType == YAFFS_OBJECT_TYPE_SYMLINK) {
-                       in->variant.symLinkVariant.alias =
-                                                   yaffs_CloneString(oh->alias);
-                       if (!in->variant.symLinkVariant.alias)
-                               alloc_failed = 1; /* Not returned to caller */
+                       if (oh->parentObjectId == YAFFS_OBJECTID_DELETED)
+                               in->variant.symLinkVariant.alias = NULL;
+                       else {
+                               in->variant.symLinkVariant.alias =
+                                       yaffs_CloneString(oh->alias);
+                               if (!in->variant.symLinkVariant.alias)
+                                       alloc_failed = 1; /* Not reted to be a bug where for
+                                                * deleted symlinks, .alias was copied
+                                                * from after a free.  Therefore, the
+                                                * value of oh->alias must not be
+                                                * depended upon for deleted symlinks.
+                                                */
+
+                                               if (oh && oh->parentObjectId == YAFFS_OBJECTID_DELETED)
+                                                       in->variant.symLinkVariant.alias = NULL;
+