Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=83292e0a9c3f1c326b28fbf8cb70a8ce81a98163
Commit:     83292e0a9c3f1c326b28fbf8cb70a8ce81a98163
Parent:     43fdf27470b216ebdef47e09ff83bed2f2894b13
Author:     David S. Miller <[EMAIL PROTECTED]>
AuthorDate: Thu Jul 12 14:16:22 2007 -0700
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Mon Jul 16 04:04:33 2007 -0700

    [SPARC64]: Fix MD property lifetime bugs.
    
    Property values cannot be referenced outside of
    mdesc_grab()/mdesc_release() pairs.  The only major
    offender was the VIO bus layer, easily fixed.
    
    Add some commentary to mdesc.h describing these rules.
    
    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
---
 arch/sparc64/kernel/vio.c   |   39 ++++++++++++++++++++++++++++-----------
 include/asm-sparc64/mdesc.h |   22 ++++++++++++++++++++--
 include/asm-sparc64/vio.h   |    7 +++++--
 3 files changed, 53 insertions(+), 15 deletions(-)

diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c
index 64f0825..8b269aa 100644
--- a/arch/sparc64/kernel/vio.c
+++ b/arch/sparc64/kernel/vio.c
@@ -44,12 +44,11 @@ static const struct vio_device_id *vio_match_device(
 
        while (matches->type[0] || matches->compat[0]) {
                int match = 1;
-               if (matches->type[0]) {
-                       match &= type
-                               && !strcmp(matches->type, type);
-               }
+               if (matches->type[0])
+                       match &= !strcmp(matches->type, type);
+
                if (matches->compat[0]) {
-                       match &= compat &&
+                       match &= len &&
                                find_in_proplist(compat, matches->compat, len);
                }
                if (match)
@@ -205,15 +204,30 @@ static struct vio_dev *vio_create_one(struct mdesc_handle 
*hp, u64 mp,
        const char *type, *compat;
        struct device_node *dp;
        struct vio_dev *vdev;
-       int err, clen;
+       int err, tlen, clen;
 
-       type = mdesc_get_property(hp, mp, "device-type", NULL);
+       type = mdesc_get_property(hp, mp, "device-type", &tlen);
        if (!type) {
-               type = mdesc_get_property(hp, mp, "name", NULL);
-               if (!type)
+               type = mdesc_get_property(hp, mp, "name", &tlen);
+               if (!type) {
                        type = mdesc_node_name(hp, mp);
+                       tlen = strlen(type) + 1;
+               }
+       }
+       if (tlen > VIO_MAX_TYPE_LEN) {
+               printk(KERN_ERR "VIO: Type string [%s] is too long.\n",
+                      type);
+               return NULL;
        }
+
        compat = mdesc_get_property(hp, mp, "device-type", &clen);
+       if (!compat) {
+               clen = 0;
+       } else if (clen > VIO_MAX_COMPAT_LEN) {
+               printk(KERN_ERR "VIO: Compat len %d for [%s] is too long.\n",
+                      clen, type);
+               return NULL;
+       }
 
        vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
        if (!vdev) {
@@ -222,8 +236,11 @@ static struct vio_dev *vio_create_one(struct mdesc_handle 
*hp, u64 mp,
        }
 
        vdev->mp = mp;
-       vdev->type = type;
-       vdev->compat = compat;
+       memcpy(vdev->type, type, tlen);
+       if (compat)
+               memcpy(vdev->compat, compat, clen);
+       else
+               memset(vdev->compat, 0, sizeof(vdev->compat));
        vdev->compat_len = clen;
 
        vdev->channel_id = ~0UL;
diff --git a/include/asm-sparc64/mdesc.h b/include/asm-sparc64/mdesc.h
index bbb0c0b..dc372df 100644
--- a/include/asm-sparc64/mdesc.h
+++ b/include/asm-sparc64/mdesc.h
@@ -23,8 +23,28 @@ extern u64 mdesc_node_by_name(struct mdesc_handle *handle,
             (__node) != MDESC_NODE_NULL; \
             __node = mdesc_node_by_name(__hdl, __node, __name))
 
+/* Access to property values returned from mdesc_get_property() are
+ * only valid inside of a mdesc_grab()/mdesc_release() sequence.
+ * Once mdesc_release() is called, the memory backed up by these
+ * pointers may reference freed up memory.
+ *
+ * Therefore callers must make copies of any property values
+ * they need.
+ *
+ * These same rules apply to mdesc_node_name().
+ */
 extern const void *mdesc_get_property(struct mdesc_handle *handle,
                                      u64 node, const char *name, int *lenp);
+extern const char *mdesc_node_name(struct mdesc_handle *hp, u64 node);
+
+/* MD arc iteration, the standard sequence is:
+ *
+ *     unsigned long arc;
+ *     mdesc_for_each_arc(arc, handle, node, MDESC_ARC_TYPE_{FWD,BACK}) {
+ *             unsigned long target = mdesc_arc_target(handle, arc);
+ *             ...
+ *     }
+ */
 
 #define MDESC_ARC_TYPE_FWD     "fwd"
 #define MDESC_ARC_TYPE_BACK    "back"
@@ -38,8 +58,6 @@ extern u64 mdesc_next_arc(struct mdesc_handle *handle, u64 
from,
 
 extern u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc);
 
-extern const char *mdesc_node_name(struct mdesc_handle *hp, u64 node);
-
 extern void mdesc_update(void);
 
 extern void sun4v_mdesc_init(void);
diff --git a/include/asm-sparc64/vio.h b/include/asm-sparc64/vio.h
index a8a53e6..83c9642 100644
--- a/include/asm-sparc64/vio.h
+++ b/include/asm-sparc64/vio.h
@@ -264,12 +264,15 @@ static inline u32 vio_dring_avail(struct vio_dring_state 
*dr,
                ((dr->prod - dr->cons) & (ring_size - 1)));
 }
 
+#define VIO_MAX_TYPE_LEN       64
+#define VIO_MAX_COMPAT_LEN     64
+
 struct vio_dev {
        u64                     mp;
        struct device_node      *dp;
 
-       const char              *type;
-       const char              *compat;
+       char                    type[VIO_MAX_TYPE_LEN];
+       char                    compat[VIO_MAX_COMPAT_LEN];
        int                     compat_len;
 
        unsigned long           channel_id;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to