diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2007-07-12 17:16:22 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-16 07:04:33 -0400 |
commit | 83292e0a9c3f1c326b28fbf8cb70a8ce81a98163 (patch) | |
tree | 38794e806ba5fe8d10234c5c24a4efa22180c05c /arch | |
parent | 43fdf27470b216ebdef47e09ff83bed2f2894b13 (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.c | 39 |
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; |