hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/scsi/ses.c
....@@ -1,25 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * SCSI Enclosure Services
34 *
45 * Copyright (C) 2008 James Bottomley <James.Bottomley@HansenPartnership.com>
5
- *
6
-**-----------------------------------------------------------------------------
7
-**
8
-** This program is free software; you can redistribute it and/or
9
-** modify it under the terms of the GNU General Public License
10
-** version 2 as published by the Free Software Foundation.
11
-**
12
-** This program is distributed in the hope that it will be useful,
13
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
14
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
-** GNU General Public License for more details.
16
-**
17
-** You should have received a copy of the GNU General Public License
18
-** along with this program; if not, write to the Free Software
19
-** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
-**
21
-**-----------------------------------------------------------------------------
22
-*/
6
+ */
237
248 #include <linux/slab.h>
259 #include <linux/module.h>
....@@ -449,8 +433,8 @@
449433 }
450434 #endif /* 0 */
451435
452
-static void ses_process_descriptor(struct enclosure_component *ecomp,
453
- unsigned char *desc)
436
+static int ses_process_descriptor(struct enclosure_component *ecomp,
437
+ unsigned char *desc, int max_desc_len)
454438 {
455439 int eip = desc[0] & 0x10;
456440 int invalid = desc[0] & 0x80;
....@@ -461,22 +445,32 @@
461445 unsigned char *d;
462446
463447 if (invalid)
464
- return;
448
+ return 0;
465449
466450 switch (proto) {
467451 case SCSI_PROTOCOL_FCP:
468452 if (eip) {
453
+ if (max_desc_len <= 7)
454
+ return 1;
469455 d = desc + 4;
470456 slot = d[3];
471457 }
472458 break;
473459 case SCSI_PROTOCOL_SAS:
460
+
474461 if (eip) {
462
+ if (max_desc_len <= 27)
463
+ return 1;
475464 d = desc + 4;
476465 slot = d[3];
477466 d = desc + 8;
478
- } else
467
+ } else {
468
+ if (max_desc_len <= 23)
469
+ return 1;
479470 d = desc + 4;
471
+ }
472
+
473
+
480474 /* only take the phy0 addr */
481475 addr = (u64)d[12] << 56 |
482476 (u64)d[13] << 48 |
....@@ -493,6 +487,8 @@
493487 }
494488 ecomp->slot = slot;
495489 scomp->addr = addr;
490
+
491
+ return 0;
496492 }
497493
498494 struct efd {
....@@ -506,9 +502,6 @@
506502 struct efd *efd = data;
507503 int i;
508504 struct ses_component *scomp;
509
-
510
- if (!edev->component[0].scratch)
511
- return 0;
512505
513506 for (i = 0; i < edev->components; i++) {
514507 scomp = edev->component[i].scratch;
....@@ -565,7 +558,7 @@
565558 /* skip past overall descriptor */
566559 desc_ptr += len + 4;
567560 }
568
- if (ses_dev->page10)
561
+ if (ses_dev->page10 && ses_dev->page10_len > 9)
569562 addl_desc_ptr = ses_dev->page10 + 8;
570563 type_ptr = ses_dev->page1_types;
571564 components = 0;
....@@ -573,17 +566,22 @@
573566 for (j = 0; j < type_ptr[1]; j++) {
574567 char *name = NULL;
575568 struct enclosure_component *ecomp;
569
+ int max_desc_len;
576570
577571 if (desc_ptr) {
578
- if (desc_ptr >= buf + page7_len) {
572
+ if (desc_ptr + 3 >= buf + page7_len) {
579573 desc_ptr = NULL;
580574 } else {
581575 len = (desc_ptr[2] << 8) + desc_ptr[3];
582576 desc_ptr += 4;
583
- /* Add trailing zero - pushes into
584
- * reserved space */
585
- desc_ptr[len] = '\0';
586
- name = desc_ptr;
577
+ if (desc_ptr + len > buf + page7_len)
578
+ desc_ptr = NULL;
579
+ else {
580
+ /* Add trailing zero - pushes into
581
+ * reserved space */
582
+ desc_ptr[len] = '\0';
583
+ name = desc_ptr;
584
+ }
587585 }
588586 }
589587 if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
....@@ -595,14 +593,20 @@
595593 components++,
596594 type_ptr[0],
597595 name);
598
- else
596
+ else if (components < edev->components)
599597 ecomp = &edev->component[components++];
598
+ else
599
+ ecomp = ERR_PTR(-EINVAL);
600600
601601 if (!IS_ERR(ecomp)) {
602
- if (addl_desc_ptr)
603
- ses_process_descriptor(
604
- ecomp,
605
- addl_desc_ptr);
602
+ if (addl_desc_ptr) {
603
+ max_desc_len = ses_dev->page10_len -
604
+ (addl_desc_ptr - ses_dev->page10);
605
+ if (ses_process_descriptor(ecomp,
606
+ addl_desc_ptr,
607
+ max_desc_len))
608
+ addl_desc_ptr = NULL;
609
+ }
606610 if (create)
607611 enclosure_component_register(
608612 ecomp);
....@@ -619,9 +623,11 @@
619623 /* these elements are optional */
620624 type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_TARGET_PORT ||
621625 type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_INITIATOR_PORT ||
622
- type_ptr[0] == ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS))
626
+ type_ptr[0] == ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS)) {
623627 addl_desc_ptr += addl_desc_ptr[1] + 2;
624
-
628
+ if (addl_desc_ptr + 1 >= ses_dev->page10 + ses_dev->page10_len)
629
+ addl_desc_ptr = NULL;
630
+ }
625631 }
626632 }
627633 kfree(buf);
....@@ -720,6 +726,7 @@
720726 type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE)
721727 components += type_ptr[1];
722728 }
729
+
723730 ses_dev->page1 = buf;
724731 ses_dev->page1_len = len;
725732 buf = NULL;
....@@ -761,9 +768,11 @@
761768 buf = NULL;
762769 }
763770 page2_not_supported:
764
- scomp = kcalloc(components, sizeof(struct ses_component), GFP_KERNEL);
765
- if (!scomp)
766
- goto err_free;
771
+ if (components > 0) {
772
+ scomp = kcalloc(components, sizeof(struct ses_component), GFP_KERNEL);
773
+ if (!scomp)
774
+ goto err_free;
775
+ }
767776
768777 edev = enclosure_register(cdev->parent, dev_name(&sdev->sdev_gendev),
769778 components, &ses_enclosure_callbacks);
....@@ -843,7 +852,8 @@
843852 kfree(ses_dev->page2);
844853 kfree(ses_dev);
845854
846
- kfree(edev->component[0].scratch);
855
+ if (edev->components)
856
+ kfree(edev->component[0].scratch);
847857
848858 put_device(&edev->edev);
849859 enclosure_unregister(edev);