mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-20 19:23:57 +08:00
SCSI fixes on 20180706
This is two minor bug fixes (aacraid, target) and a fix for a potential exploit in the way sg handles teardown. Signed-off-by: James E.J. Bottomley <jejb@linux.vnet.ibm.com> -----BEGIN PGP SIGNATURE----- iJwEABMIAEQWIQTnYEDbdso9F2cI+arnQslM7pishQUCWz/hBSYcamFtZXMuYm90 dG9tbGV5QGhhbnNlbnBhcnRuZXJzaGlwLmNvbQAKCRDnQslM7pishUkIAP9JKGYO rcoNxusKsTi6tMEeUFzX1Mu0IkUr9ApcsCJMyAEAyRL5+b77PoZG8NgQBBo99iFE 8DMbxsNbBMbTzDqbfzk= =ttS3 -----END PGP SIGNATURE----- Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi Pull SCSI fixes from James Bottomley: "This is two minor bug fixes (aacraid, target) and a fix for a potential exploit in the way sg handles teardown" * tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: scsi: sg: mitigate read/write abuse scsi: aacraid: Fix PD performance regression over incorrect qd being set scsi: target: Fix truncated PR-in ReadKeys response
This commit is contained in:
commit
624434af25
@ -1974,7 +1974,6 @@ static void aac_set_safw_attr_all_targets(struct aac_dev *dev)
|
||||
u32 lun_count, nexus;
|
||||
u32 i, bus, target;
|
||||
u8 expose_flag, attribs;
|
||||
u8 devtype;
|
||||
|
||||
lun_count = aac_get_safw_phys_lun_count(dev);
|
||||
|
||||
@ -1992,23 +1991,23 @@ static void aac_set_safw_attr_all_targets(struct aac_dev *dev)
|
||||
continue;
|
||||
|
||||
if (expose_flag != 0) {
|
||||
devtype = AAC_DEVTYPE_RAID_MEMBER;
|
||||
goto update_devtype;
|
||||
dev->hba_map[bus][target].devtype =
|
||||
AAC_DEVTYPE_RAID_MEMBER;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nexus != 0 && (attribs & 8)) {
|
||||
devtype = AAC_DEVTYPE_NATIVE_RAW;
|
||||
dev->hba_map[bus][target].devtype =
|
||||
AAC_DEVTYPE_NATIVE_RAW;
|
||||
dev->hba_map[bus][target].rmw_nexus =
|
||||
nexus;
|
||||
} else
|
||||
devtype = AAC_DEVTYPE_ARC_RAW;
|
||||
dev->hba_map[bus][target].devtype =
|
||||
AAC_DEVTYPE_ARC_RAW;
|
||||
|
||||
dev->hba_map[bus][target].scan_counter = dev->scan_counter;
|
||||
|
||||
aac_set_safw_target_qd(dev, bus, target);
|
||||
|
||||
update_devtype:
|
||||
dev->hba_map[bus][target].devtype = devtype;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,7 @@ static int sg_version_num = 30536; /* 2 digits for each component */
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/cred.h> /* for sg_check_file_access() */
|
||||
|
||||
#include "scsi.h"
|
||||
#include <scsi/scsi_dbg.h>
|
||||
@ -209,6 +210,33 @@ static void sg_device_destroy(struct kref *kref);
|
||||
sdev_prefix_printk(prefix, (sdp)->device, \
|
||||
(sdp)->disk->disk_name, fmt, ##a)
|
||||
|
||||
/*
|
||||
* The SCSI interfaces that use read() and write() as an asynchronous variant of
|
||||
* ioctl(..., SG_IO, ...) are fundamentally unsafe, since there are lots of ways
|
||||
* to trigger read() and write() calls from various contexts with elevated
|
||||
* privileges. This can lead to kernel memory corruption (e.g. if these
|
||||
* interfaces are called through splice()) and privilege escalation inside
|
||||
* userspace (e.g. if a process with access to such a device passes a file
|
||||
* descriptor to a SUID binary as stdin/stdout/stderr).
|
||||
*
|
||||
* This function provides protection for the legacy API by restricting the
|
||||
* calling context.
|
||||
*/
|
||||
static int sg_check_file_access(struct file *filp, const char *caller)
|
||||
{
|
||||
if (filp->f_cred != current_real_cred()) {
|
||||
pr_err_once("%s: process %d (%s) changed security contexts after opening file descriptor, this is not allowed.\n",
|
||||
caller, task_tgid_vnr(current), current->comm);
|
||||
return -EPERM;
|
||||
}
|
||||
if (uaccess_kernel()) {
|
||||
pr_err_once("%s: process %d (%s) called from kernel context, this is not allowed.\n",
|
||||
caller, task_tgid_vnr(current), current->comm);
|
||||
return -EACCES;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sg_allow_access(struct file *filp, unsigned char *cmd)
|
||||
{
|
||||
struct sg_fd *sfp = filp->private_data;
|
||||
@ -393,6 +421,14 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
|
||||
struct sg_header *old_hdr = NULL;
|
||||
int retval = 0;
|
||||
|
||||
/*
|
||||
* This could cause a response to be stranded. Close the associated
|
||||
* file descriptor to free up any resources being held.
|
||||
*/
|
||||
retval = sg_check_file_access(filp, __func__);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
|
||||
return -ENXIO;
|
||||
SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
|
||||
@ -580,9 +616,11 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
|
||||
struct sg_header old_hdr;
|
||||
sg_io_hdr_t *hp;
|
||||
unsigned char cmnd[SG_MAX_CDB_SIZE];
|
||||
int retval;
|
||||
|
||||
if (unlikely(uaccess_kernel()))
|
||||
return -EINVAL;
|
||||
retval = sg_check_file_access(filp, __func__);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
|
||||
return -ENXIO;
|
||||
|
@ -3727,11 +3727,16 @@ core_scsi3_pri_read_keys(struct se_cmd *cmd)
|
||||
* Check for overflow of 8byte PRI READ_KEYS payload and
|
||||
* next reservation key list descriptor.
|
||||
*/
|
||||
if ((add_len + 8) > (cmd->data_length - 8))
|
||||
break;
|
||||
|
||||
put_unaligned_be64(pr_reg->pr_res_key, &buf[off]);
|
||||
off += 8;
|
||||
if (off + 8 <= cmd->data_length) {
|
||||
put_unaligned_be64(pr_reg->pr_res_key, &buf[off]);
|
||||
off += 8;
|
||||
}
|
||||
/*
|
||||
* SPC5r17: 6.16.2 READ KEYS service action
|
||||
* The ADDITIONAL LENGTH field indicates the number of bytes in
|
||||
* the Reservation key list. The contents of the ADDITIONAL
|
||||
* LENGTH field are not altered based on the allocation length
|
||||
*/
|
||||
add_len += 8;
|
||||
}
|
||||
spin_unlock(&dev->t10_pr.registration_lock);
|
||||
|
Loading…
Reference in New Issue
Block a user