aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-07-12 17:16:22 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-16 07:04:33 -0400
commit83292e0a9c3f1c326b28fbf8cb70a8ce81a98163 (patch)
tree38794e806ba5fe8d10234c5c24a4efa22180c05c /arch
parent43fdf27470b216ebdef47e09ff83bed2f2894b13 (diff)
[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 <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc64/kernel/vio.c39
1 files changed, 28 insertions, 11 deletions
diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c
index 64f082555bcd..8b269aabff07 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(
44 44
45 while (matches->type[0] || matches->compat[0]) { 45 while (matches->type[0] || matches->compat[0]) {
46 int match = 1; 46 int match = 1;
47 if (matches->type[0]) { 47 if (matches->type[0])
48 match &= type 48 match &= !strcmp(matches->type, type);
49 && !strcmp(matches->type, type); 49
50 }
51 if (matches->compat[0]) { 50 if (matches->compat[0]) {
52 match &= compat && 51 match &= len &&
53 find_in_proplist(compat, matches->compat, len); 52 find_in_proplist(compat, matches->compat, len);
54 } 53 }
55 if (match) 54 if (match)
@@ -205,15 +204,30 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
205 const char *type, *compat; 204 const char *type, *compat;
206 struct device_node *dp; 205 struct device_node *dp;
207 struct vio_dev *vdev; 206 struct vio_dev *vdev;
208 int err, clen; 207 int err, tlen, clen;
209 208
210 type = mdesc_get_property(hp, mp, "device-type", NULL); 209 type = mdesc_get_property(hp, mp, "device-type", &tlen);
211 if (!type) { 210 if (!type) {
212 type = mdesc_get_property(hp, mp, "name", NULL); 211 type = mdesc_get_property(hp, mp, "name", &tlen);
213 if (!type) 212 if (!type) {
214 type = mdesc_node_name(hp, mp); 213 type = mdesc_node_name(hp, mp);
214 tlen = strlen(type) + 1;
215 }
216 }
217 if (tlen > VIO_MAX_TYPE_LEN) {
218 printk(KERN_ERR "VIO: Type string [%s] is too long.\n",
219 type);
220 return NULL;
215 } 221 }
222
216 compat = mdesc_get_property(hp, mp, "device-type", &clen); 223 compat = mdesc_get_property(hp, mp, "device-type", &clen);
224 if (!compat) {
225 clen = 0;
226 } else if (clen > VIO_MAX_COMPAT_LEN) {
227 printk(KERN_ERR "VIO: Compat len %d for [%s] is too long.\n",
228 clen, type);
229 return NULL;
230 }
217 231
218 vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); 232 vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
219 if (!vdev) { 233 if (!vdev) {
@@ -222,8 +236,11 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
222 } 236 }
223 237
224 vdev->mp = mp; 238 vdev->mp = mp;
225 vdev->type = type; 239 memcpy(vdev->type, type, tlen);
226 vdev->compat = compat; 240 if (compat)
241 memcpy(vdev->compat, compat, clen);
242 else
243 memset(vdev->compat, 0, sizeof(vdev->compat));
227 vdev->compat_len = clen; 244 vdev->compat_len = clen;
228 245
229 vdev->channel_id = ~0UL; 246 vdev->channel_id = ~0UL;