cifs: remove header_preamble_size where it is always 0
Since header_preamble_size is 0 for SMB2+ we can remove it in those code paths that are only invoked from SMB2. Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
49f466bdbd
commit
1fc6ad2f10
|
@ -95,8 +95,7 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
|
|||
|
||||
#ifdef CONFIG_CIFS_SMB311
|
||||
static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len,
|
||||
__u32 non_ctxlen,
|
||||
size_t hdr_preamble_size)
|
||||
__u32 non_ctxlen)
|
||||
{
|
||||
__u16 neg_count;
|
||||
__u32 nc_offset, size_of_pad_before_neg_ctxts;
|
||||
|
@ -110,12 +109,11 @@ static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len,
|
|||
|
||||
/* Make sure that negotiate contexts start after gss security blob */
|
||||
nc_offset = le32_to_cpu(pneg_rsp->NegotiateContextOffset);
|
||||
if (nc_offset < non_ctxlen - hdr_preamble_size /* RFC1001 len */) {
|
||||
if (nc_offset < non_ctxlen) {
|
||||
printk_once(KERN_WARNING "invalid negotiate context offset\n");
|
||||
return 0;
|
||||
}
|
||||
size_of_pad_before_neg_ctxts = nc_offset -
|
||||
(non_ctxlen - hdr_preamble_size);
|
||||
size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen;
|
||||
|
||||
/* Verify that at least minimal negotiate contexts fit within frame */
|
||||
if (len < nc_offset + (neg_count * sizeof(struct smb2_neg_context))) {
|
||||
|
@ -134,7 +132,7 @@ static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len,
|
|||
int
|
||||
smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
|
||||
{
|
||||
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)(buf + srvr->vals->header_preamble_size);
|
||||
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
|
||||
struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)shdr;
|
||||
__u64 mid;
|
||||
__u32 clc_len; /* calculated length */
|
||||
|
@ -183,8 +181,7 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
|
|||
}
|
||||
return 1;
|
||||
}
|
||||
if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE -
|
||||
srvr->vals->header_preamble_size) {
|
||||
if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE) {
|
||||
cifs_dbg(VFS, "SMB length greater than maximum, mid=%llu\n",
|
||||
mid);
|
||||
return 1;
|
||||
|
@ -227,8 +224,7 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
|
|||
|
||||
#ifdef CONFIG_CIFS_SMB311
|
||||
if (shdr->Command == SMB2_NEGOTIATE)
|
||||
clc_len += get_neg_ctxt_len(shdr, len, clc_len,
|
||||
srvr->vals->header_preamble_size);
|
||||
clc_len += get_neg_ctxt_len(shdr, len, clc_len);
|
||||
#endif /* SMB311 */
|
||||
if (len != clc_len) {
|
||||
cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n",
|
||||
|
@ -253,7 +249,7 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
|
|||
*/
|
||||
if (clc_len < len) {
|
||||
printk_once(KERN_WARNING
|
||||
"SMB2 server sent bad RFC1001 len %d not %u\n",
|
||||
"SMB2 server sent bad RFC1001 len %d not %d\n",
|
||||
len, clc_len);
|
||||
return 0;
|
||||
}
|
||||
|
@ -401,7 +397,7 @@ smb2_calc_size(void *buf, struct TCP_Server_Info *srvr)
|
|||
int offset; /* the offset from the beginning of SMB to data area */
|
||||
int data_length; /* the length of the variable length data area */
|
||||
/* Structure Size has already been checked to make sure it is 64 */
|
||||
int len = srvr->vals->header_preamble_size + le16_to_cpu(shdr->StructureSize);
|
||||
int len = le16_to_cpu(shdr->StructureSize);
|
||||
|
||||
/*
|
||||
* StructureSize2, ie length of fixed parameter area has already
|
||||
|
@ -422,12 +418,12 @@ smb2_calc_size(void *buf, struct TCP_Server_Info *srvr)
|
|||
* for some commands, typically those with odd StructureSize,
|
||||
* so we must add one to the calculation.
|
||||
*/
|
||||
if (offset + srvr->vals->header_preamble_size + 1 < len) {
|
||||
cifs_dbg(VFS, "data area offset %zu overlaps SMB2 header %d\n",
|
||||
offset + srvr->vals->header_preamble_size + 1, len);
|
||||
if (offset + 1 < len) {
|
||||
cifs_dbg(VFS, "data area offset %d overlaps SMB2 header %d\n",
|
||||
offset + 1, len);
|
||||
data_length = 0;
|
||||
} else {
|
||||
len = srvr->vals->header_preamble_size + offset + data_length;
|
||||
len = offset + data_length;
|
||||
}
|
||||
}
|
||||
calc_size_exit:
|
||||
|
|
|
@ -1521,8 +1521,6 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
unsigned int sub_offset;
|
||||
unsigned int print_len;
|
||||
unsigned int print_offset;
|
||||
struct cifs_ses *ses = tcon->ses;
|
||||
struct TCP_Server_Info *server = ses->server;
|
||||
|
||||
cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
|
||||
|
||||
|
@ -1546,7 +1544,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
|
||||
err_buf = err_iov.iov_base;
|
||||
if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
|
||||
err_iov.iov_len + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) {
|
||||
err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE) {
|
||||
kfree(utf16_path);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
@ -1559,13 +1557,12 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
print_len = le16_to_cpu(symlink->PrintNameLength);
|
||||
print_offset = le16_to_cpu(symlink->PrintNameOffset);
|
||||
|
||||
if (err_iov.iov_len + server->vals->header_preamble_size <
|
||||
SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
|
||||
if (err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
|
||||
kfree(utf16_path);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (err_iov.iov_len + server->vals->header_preamble_size <
|
||||
if (err_iov.iov_len <
|
||||
SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
|
||||
kfree(utf16_path);
|
||||
return -ENOENT;
|
||||
|
@ -2233,7 +2230,7 @@ crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
|
|||
{
|
||||
struct smb2_transform_hdr *tr_hdr =
|
||||
(struct smb2_transform_hdr *)rqst->rq_iov[0].iov_base;
|
||||
unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20 - server->vals->header_preamble_size;
|
||||
unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
|
||||
int rc = 0;
|
||||
struct scatterlist *sg;
|
||||
u8 sign[SMB2_SIGNATURE_SIZE] = {};
|
||||
|
@ -2459,7 +2456,7 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
memmove(buf + server->vals->header_preamble_size, iov[2].iov_base, buf_data_size);
|
||||
memmove(buf, iov[2].iov_base, buf_data_size);
|
||||
|
||||
server->total_read = buf_data_size + page_data_size;
|
||||
|
||||
|
@ -2565,7 +2562,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
|||
return 0;
|
||||
}
|
||||
|
||||
data_offset = server->ops->read_data_offset(buf) + server->vals->header_preamble_size;
|
||||
data_offset = server->ops->read_data_offset(buf);
|
||||
#ifdef CONFIG_CIFS_SMB_DIRECT
|
||||
use_rdma_mr = rdata->mr;
|
||||
#endif
|
||||
|
@ -2661,12 +2658,11 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
|
|||
unsigned int npages;
|
||||
struct page **pages;
|
||||
unsigned int len;
|
||||
unsigned int buflen = server->pdu_size + server->vals->header_preamble_size;
|
||||
unsigned int buflen = server->pdu_size;
|
||||
int rc;
|
||||
int i = 0;
|
||||
|
||||
len = min_t(unsigned int, buflen, server->vals->read_rsp_size -
|
||||
server->vals->header_preamble_size +
|
||||
len = min_t(unsigned int, buflen, server->vals->read_rsp_size +
|
||||
sizeof(struct smb2_transform_hdr)) - HEADER_SIZE(server) + 1;
|
||||
|
||||
rc = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, len);
|
||||
|
@ -2674,8 +2670,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
|
|||
return rc;
|
||||
server->total_read += rc;
|
||||
|
||||
len = le32_to_cpu(tr_hdr->OriginalMessageSize) +
|
||||
server->vals->header_preamble_size -
|
||||
len = le32_to_cpu(tr_hdr->OriginalMessageSize) -
|
||||
server->vals->read_rsp_size;
|
||||
npages = DIV_ROUND_UP(len, PAGE_SIZE);
|
||||
|
||||
|
@ -2702,8 +2697,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
|
|||
if (rc)
|
||||
goto free_pages;
|
||||
|
||||
rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size -
|
||||
server->vals->header_preamble_size,
|
||||
rc = decrypt_raw_data(server, buf, server->vals->read_rsp_size,
|
||||
pages, npages, len);
|
||||
if (rc)
|
||||
goto free_pages;
|
||||
|
@ -2740,7 +2734,7 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
|
|||
struct mid_q_entry *mid_entry;
|
||||
|
||||
/* switch to large buffer if too big for a small one */
|
||||
if (pdu_length + server->vals->header_preamble_size > MAX_CIFS_SMALL_BUFFER_SIZE) {
|
||||
if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE) {
|
||||
server->large_buf = true;
|
||||
memcpy(server->bigbuf, buf, server->total_read);
|
||||
buf = server->bigbuf;
|
||||
|
@ -2748,13 +2742,12 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
|
|||
|
||||
/* now read the rest */
|
||||
length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
|
||||
pdu_length - HEADER_SIZE(server) + 1 +
|
||||
server->vals->header_preamble_size);
|
||||
pdu_length - HEADER_SIZE(server) + 1);
|
||||
if (length < 0)
|
||||
return length;
|
||||
server->total_read += length;
|
||||
|
||||
buf_size = pdu_length + server->vals->header_preamble_size - sizeof(struct smb2_transform_hdr);
|
||||
buf_size = pdu_length - sizeof(struct smb2_transform_hdr);
|
||||
length = decrypt_raw_data(server, buf, buf_size, NULL, 0, 0);
|
||||
if (length)
|
||||
return length;
|
||||
|
@ -2783,7 +2776,7 @@ smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid)
|
|||
struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
|
||||
unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
|
||||
|
||||
if (pdu_length + server->vals->header_preamble_size < sizeof(struct smb2_transform_hdr) +
|
||||
if (pdu_length < sizeof(struct smb2_transform_hdr) +
|
||||
sizeof(struct smb2_sync_hdr)) {
|
||||
cifs_dbg(VFS, "Transform message is too small (%u)\n",
|
||||
pdu_length);
|
||||
|
@ -2792,14 +2785,14 @@ smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid)
|
|||
return -ECONNABORTED;
|
||||
}
|
||||
|
||||
if (pdu_length + server->vals->header_preamble_size < orig_len + sizeof(struct smb2_transform_hdr)) {
|
||||
if (pdu_length < orig_len + sizeof(struct smb2_transform_hdr)) {
|
||||
cifs_dbg(VFS, "Transform message is broken\n");
|
||||
cifs_reconnect(server);
|
||||
wake_up(&server->response_q);
|
||||
return -ECONNABORTED;
|
||||
}
|
||||
|
||||
if (pdu_length + server->vals->header_preamble_size > CIFSMaxBufSize + MAX_HEADER_SIZE(server))
|
||||
if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server))
|
||||
return receive_encrypted_read(server, mid);
|
||||
|
||||
return receive_encrypted_standard(server, mid);
|
||||
|
@ -2810,8 +2803,7 @@ smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
|||
{
|
||||
char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
|
||||
|
||||
return handle_read_data(server, mid, buf, server->pdu_size +
|
||||
server->vals->header_preamble_size,
|
||||
return handle_read_data(server, mid, buf, server->pdu_size,
|
||||
NULL, 0, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -491,8 +491,7 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp,
|
|||
if (len_of_ctxts < sizeof(struct smb2_neg_context))
|
||||
break;
|
||||
|
||||
pctx = (struct smb2_neg_context *)(offset +
|
||||
server->vals->header_preamble_size + (char *)rsp);
|
||||
pctx = (struct smb2_neg_context *)(offset + (char *)rsp);
|
||||
clen = le16_to_cpu(pctx->DataLength);
|
||||
if (clen > len_of_ctxts)
|
||||
break;
|
||||
|
@ -1213,7 +1212,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
|
|||
if (rc)
|
||||
goto out;
|
||||
|
||||
if (offsetof(struct smb2_sess_setup_rsp, Buffer) - ses->server->vals->header_preamble_size !=
|
||||
if (offsetof(struct smb2_sess_setup_rsp, Buffer) !=
|
||||
le16_to_cpu(rsp->SecurityBufferOffset)) {
|
||||
cifs_dbg(VFS, "Invalid security buffer offset %d\n",
|
||||
le16_to_cpu(rsp->SecurityBufferOffset));
|
||||
|
@ -1661,7 +1660,7 @@ parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp,
|
|||
unsigned int remaining;
|
||||
char *name;
|
||||
|
||||
data_offset = (char *)rsp + server->vals->header_preamble_size + le32_to_cpu(rsp->CreateContextsOffset);
|
||||
data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset);
|
||||
remaining = le32_to_cpu(rsp->CreateContextsLength);
|
||||
cc = (struct create_context *)data_offset;
|
||||
while (remaining >= sizeof(struct create_context)) {
|
||||
|
@ -2327,13 +2326,12 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
}
|
||||
|
||||
static int
|
||||
validate_iov(struct TCP_Server_Info *server,
|
||||
unsigned int offset, unsigned int buffer_length,
|
||||
validate_iov(unsigned int offset, unsigned int buffer_length,
|
||||
struct kvec *iov, unsigned int min_buf_size)
|
||||
{
|
||||
unsigned int smb_len = iov->iov_len;
|
||||
char *end_of_smb = smb_len + server->vals->header_preamble_size + (char *)iov->iov_base;
|
||||
char *begin_of_buf = server->vals->header_preamble_size + offset + (char *)iov->iov_base;
|
||||
char *end_of_smb = smb_len + (char *)iov->iov_base;
|
||||
char *begin_of_buf = offset + (char *)iov->iov_base;
|
||||
char *end_of_buf = begin_of_buf + buffer_length;
|
||||
|
||||
|
||||
|
@ -2363,18 +2361,17 @@ validate_iov(struct TCP_Server_Info *server,
|
|||
* Caller must free buffer.
|
||||
*/
|
||||
static int
|
||||
validate_and_copy_iov(struct TCP_Server_Info *server,
|
||||
unsigned int offset, unsigned int buffer_length,
|
||||
validate_and_copy_iov(unsigned int offset, unsigned int buffer_length,
|
||||
struct kvec *iov, unsigned int minbufsize,
|
||||
char *data)
|
||||
{
|
||||
char *begin_of_buf = server->vals->header_preamble_size + offset + (char *)(iov->iov_base);
|
||||
char *begin_of_buf = offset + (char *)iov->iov_base;
|
||||
int rc;
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
rc = validate_iov(server, offset, buffer_length, iov, minbufsize);
|
||||
rc = validate_iov(offset, buffer_length, iov, minbufsize);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -2454,8 +2451,7 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
}
|
||||
}
|
||||
|
||||
rc = validate_and_copy_iov(ses->server,
|
||||
le16_to_cpu(rsp->OutputBufferOffset),
|
||||
rc = validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset),
|
||||
le32_to_cpu(rsp->OutputBufferLength),
|
||||
&rsp_iov, min_len, *data);
|
||||
|
||||
|
@ -3406,8 +3402,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
goto qdir_exit;
|
||||
}
|
||||
|
||||
rc = validate_iov(server,
|
||||
le16_to_cpu(rsp->OutputBufferOffset),
|
||||
rc = validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
|
||||
le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
|
||||
info_buf_size);
|
||||
if (rc)
|
||||
|
@ -3742,7 +3737,7 @@ build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level,
|
|||
req->InputBufferOffset =
|
||||
cpu_to_le16(sizeof(struct smb2_query_info_req) - 1);
|
||||
req->OutputBufferLength = cpu_to_le32(
|
||||
outbuf_len + sizeof(struct smb2_query_info_rsp) - 1 - server->vals->header_preamble_size);
|
||||
outbuf_len + sizeof(struct smb2_query_info_rsp) - 1);
|
||||
|
||||
iov->iov_base = (char *)req;
|
||||
iov->iov_len = total_len;
|
||||
|
@ -3759,7 +3754,6 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
int rc = 0;
|
||||
int resp_buftype;
|
||||
struct cifs_ses *ses = tcon->ses;
|
||||
struct TCP_Server_Info *server = ses->server;
|
||||
struct smb2_fs_full_size_info *info = NULL;
|
||||
int flags = 0;
|
||||
|
||||
|
@ -3780,10 +3774,9 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
}
|
||||
rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
|
||||
|
||||
info = (struct smb2_fs_full_size_info *)(server->vals->header_preamble_size +
|
||||
info = (struct smb2_fs_full_size_info *)(
|
||||
le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
|
||||
rc = validate_iov(server,
|
||||
le16_to_cpu(rsp->OutputBufferOffset),
|
||||
rc = validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
|
||||
le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
|
||||
sizeof(struct smb2_fs_full_size_info));
|
||||
if (!rc)
|
||||
|
@ -3804,7 +3797,6 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
int rc = 0;
|
||||
int resp_buftype, max_len, min_len;
|
||||
struct cifs_ses *ses = tcon->ses;
|
||||
struct TCP_Server_Info *server = ses->server;
|
||||
unsigned int rsp_len, offset;
|
||||
int flags = 0;
|
||||
|
||||
|
@ -3840,20 +3832,20 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
|
||||
rsp_len = le32_to_cpu(rsp->OutputBufferLength);
|
||||
offset = le16_to_cpu(rsp->OutputBufferOffset);
|
||||
rc = validate_iov(server, offset, rsp_len, &rsp_iov, min_len);
|
||||
rc = validate_iov(offset, rsp_len, &rsp_iov, min_len);
|
||||
if (rc)
|
||||
goto qfsattr_exit;
|
||||
|
||||
if (level == FS_ATTRIBUTE_INFORMATION)
|
||||
memcpy(&tcon->fsAttrInfo, server->vals->header_preamble_size + offset
|
||||
memcpy(&tcon->fsAttrInfo, offset
|
||||
+ (char *)rsp, min_t(unsigned int,
|
||||
rsp_len, max_len));
|
||||
else if (level == FS_DEVICE_INFORMATION)
|
||||
memcpy(&tcon->fsDevInfo, server->vals->header_preamble_size + offset
|
||||
memcpy(&tcon->fsDevInfo, offset
|
||||
+ (char *)rsp, sizeof(FILE_SYSTEM_DEVICE_INFO));
|
||||
else if (level == FS_SECTOR_SIZE_INFORMATION) {
|
||||
struct smb3_fs_ss_info *ss_info = (struct smb3_fs_ss_info *)
|
||||
(server->vals->header_preamble_size + offset + (char *)rsp);
|
||||
(offset + (char *)rsp);
|
||||
tcon->ss_flags = le32_to_cpu(ss_info->Flags);
|
||||
tcon->perf_sector_size =
|
||||
le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
|
||||
|
|
Loading…
Reference in New Issue