RE: An Operand Constraint Problem in __copy_user?

Shawn C. Jury (jury@email-bosnia.22sig.army.mil)
Thu, 24 Oct 1996 18:55:04 +-100


I have had the same problem. I have not had the time to check into it any further though. I plan on recompiling the code with the -g option and doing a trace with gdb. I will see if it dumps core at the same place. I have an IDE CDROM though. When I start workman, it comes up with only one track on a CD and when I try to play that track it dumps core. I will look into it with the source code. I am running 2.1.5 also. BTW, it runs fine under 2.0.23 and 2.1.3 (I didn't try it with 2.1.4).

Shawn

----------
From: Bruce Elliott[SMTP:belliott@accessone.com]
Sent: Thursday, October 24, 1996 15:17
To: linux-kernel@vger.rutgers.edu
Subject: An Operand Constraint Problem in __copy_user?

I noticed that workman (SCSI) doesn't work under 2.1.5. It was apparently
broken somewhere in 2.1.2, 2.1.3, or 2.1.4, as it did work under 2.1.1,
but not with 2.1.4. The underlying problem appears to be a bad register
assignment when copying the number of tracks to the user from sr_ioctl.c.

Specifically, edx is assigned for the mod 4 byte count, although it is also
used in exception handling. (See the asm stuff below.) I have rebuilt
2.1.5, and there appears to be only one place where this happens.

I have the cdrom stuff in a module, if that makes any difference in the
compiling environment.

Since size = 2, it appears that gcc noticed that "size" and "size & 3" are
the same, and decided that it didn't need to allocate another register.

I don't claim to understand the gcc rules here, but I would guess that the
"q" constraint is too loose. I would guess that "ab" could be used to
avoid this.

The code is from 2.1.5, using gcc-2.7.2.

case CDROMREADTOCHDR:
{
struct cdrom_tochdr tochdr;
char * buffer;

sr_cmd[0] = SCMD_READ_TOC;
sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5);
sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
sr_cmd[6] = 0;
sr_cmd[7] = 0; /* MSB of length (12) */
sr_cmd[8] = 12; /* LSB of length */
sr_cmd[9] = 0;

buffer = (unsigned char *) scsi_malloc(512);
if(!buffer) return -ENOMEM;

result = do_ioctl(target, sr_cmd, buffer, 12);

tochdr.cdth_trk0 = buffer[2];
tochdr.cdth_trk1 = buffer[3];

scsi_free(buffer, 512);

err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tochdr));
if (err)
return err;
copy_to_user ((void *) arg, &tochdr, sizeof (struct cdrom_tochdr));

return result;
}

[ Lots of code omitted. ]

.L768:
leal 162(%esp),%ecx
movl %ecx,%esi
movl 40(%esp),%edx This is the "normal" full-count setup
movl 20(%esp),%ecx
movl 212(%esp),%edi
movl 84(%esp),%eax
#APP
movl $3f,%edx <===================================
incl 984(%eax)
rep; movsl
testb $2,%dl <-----------------------------------
je 1f
movsw
subb $2,%dl <-----------------------------------
1: testb $1,%dl <-----------------------------------
je 2f
movsb
decb %dl <-----------------------------------
2: decl 984(%eax)
3: lea 0(%edx,%ecx,4),%edx
#NO_APP
.L767:
movl %ebp,%eax
popl %ebx
popl %esi
popl %edi
popl %ebp
addl $180,%esp
ret

B. D. Elliott bde@accessone.com (Seattle)