From mboxrd@z Thu Jan 1 00:00:00 1970
From: bugzilla-daemon@bugzilla.kernel.org
Subject: [Bug 31192] New: ioctl SG_GET_REQUEST_TABLE returns 64-bit structure
to 32-bit app.
Date: Wed, 16 Mar 2011 13:24:13 GMT
Message-ID:
Mime-Version: 1.0
Content-Type: text/plain; charset="UTF-8"
Return-path:
Received: from demeter2.kernel.org ([140.211.167.42]:43374 "EHLO
demeter2.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
with ESMTP id S1752804Ab1CPNYP (ORCPT
); Wed, 16 Mar 2011 09:24:15 -0400
Received: from demeter2.kernel.org (localhost.localdomain [127.0.0.1])
by demeter2.kernel.org (8.14.4/8.14.3) with ESMTP id p2GDOEkB018332
(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO)
for ; Wed, 16 Mar 2011 13:24:14 GMT
Sender: linux-scsi-owner@vger.kernel.org
List-Id: linux-scsi@vger.kernel.org
To: linux-scsi@vger.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=31192
Summary: ioctl SG_GET_REQUEST_TABLE returns 64-bit structure to
32-bit app.
Product: SCSI Drivers
Version: 2.5
Kernel Version: 2.6.18-194.32.1.el5
Platform: All
OS/Version: Linux
Tree: Mainline
Status: NEW
Severity: normal
Priority: P1
Component: Other
AssignedTo: scsi_drivers-other@kernel-bugs.osdl.org
ReportedBy: jbyers@stonefly.com
CC: jbyers@stonefly.com
Regression: No
The 'sg' module ioctl 'SG_GET_REQUEST_TABLE', when run on an
2.6.18-194.32.1.el5 x86_64 kernel, from a 32-bit application
seems to return the 64-bit version of the
sg_req_info_t[SG_MAX_QUEUE] table, not the 32-bit version.
Because there is a pointer in the sg_req_info_t structure,
the returned size is (4 * SG_MAX_QUEUE) = 64 bytes too
large, and it corrupts neighboring user memory, as well as
not returning the correct data.
Although there is code in 'fs/compat_ioctl.c' that looks to
be handling the 32-bit user to 64-bit kernel conversion, the
"COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE)" line in
'include/linux/compat_ioctl.h' conflicts with it and seems
to prevent the conversion code from being called.
The same ioctl called from a 64-bit app works fine.
The problem looks to still be present in the newest kernel
source, although I haven't tested it.
It seems like the "COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE)"
line should be removed from 'compat_ioctl.h' ('compat_ioctl.c'
in the newest kernel).
~ Jeff Byers ~
# gcc -m32 -Wall -o sg_get_request_table sg_get_request_table.c
# ./sg_get_request_table /dev/sg1
SG Request Table:
Memory fence damaged:
0xff90c034: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xff90c044: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xff90c054: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xff90c064: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xff90c074: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0xff90c084: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0xff90c094: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0xff90c0a4: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
============================
// Test sg 'SG_GET_REQUEST_TABLE ioctl.
// Build with:
// gcc -m32 -Wall -o sg_get_request_table sg_get_request_table.c
// gcc -m64 -Wall -o sg_get_request_table sg_get_request_table.c
#include
#include
#include
#include
#include
#include
#include /* take care: fetches glibc's /usr/include/scsi/sg.h */
static void hex_dump(const unsigned char *buf, int len, const char *str);
static int memunchr(const void *s, int c, size_t n);
int main(int argc, char * argv[])
{
int sg_fd;
int idx;
unsigned char fence[128];
sg_req_info_t req_info[SG_MAX_QUEUE] = {{0}};
if (2 != argc) {
printf("Usage: '%s '\n", argv[0]);
return 1;
}
if ((sg_fd = open(argv[1], O_RDONLY)) < 0) {
perror("error opening given file name");
return 1;
}
printf("SG Request Table:\n");
memset(req_info, 0xFF, sizeof(req_info));
memset(fence, 0xFF, sizeof(fence));
if (ioctl(sg_fd, SG_GET_REQUEST_TABLE, &req_info) < 0) {
perror("SG_GET_REQUEST_TABLE ioctl error");
return 1;
}
for(idx=0; idx < SG_MAX_QUEUE; idx++){
if(req_info[idx].req_state == 0)
continue;
printf("req_info[%u]: req_state=%u, pack_id=%u, usr_ptr=%p,
duration=%u\n",
idx, req_info[idx].req_state, req_info[idx].pack_id,
req_info[idx].usr_ptr, req_info[idx].duration);
}
if (memunchr(fence, 0xFF, sizeof(fence)) != 0){
hex_dump(fence, sizeof(fence), "Memory fence damaged:");
}
close(sg_fd);
return 0;
}
static void hex_dump(const unsigned char *buf, int len, const char *str)
{
printf("%s\n", str);
int idx;
for(idx=0; idx < len; idx++){
if ((idx > 0) && ((idx & 0x0F) == 0)){
printf("\n");
}
if ((idx & 0x0F) == 0){
printf("%p:", &buf[idx]);
}
printf(" %02x", buf[idx]);
}
printf("\n");
return;
}
static int memunchr(const void *s, int c, size_t n)
{
unsigned char *ptr = (unsigned char *)s;
for(; n > 0; n--){
if (*ptr++ != c)
return 1;
}
return 0;
}
--
Configure bugmail: https://bugzilla.kernel.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are watching the assignee of the bug.