[PATCH] new x86 personality detection

Denys Vlasenko dvlasenk at redhat.com
Mon Feb 11 14:12:23 UTC 2013


On 02/11/2013 01:46 PM, Denys Vlasenko wrote:
> On 02/11/2013 12:45 PM, Denys Vlasenko wrote:
>> This patch implements a (hopefully) correct way to check for
>> syscall bitness on x86.
>>
>> I tested it to work when stracing normal 32-bit binaries,
>> can't test the above example till this evening.
>> But it should work too (famous last words?).
>>
>> Please review.
> 
> Looks like we had a bug on X32:
> 
> 	if (check_errno && is_negated_errno(x86_64_regs.rax)) {
> 
> If we build in X32 environment, above we check only lower 32 bits of rax
> - because is_negated_errno() takes _long_ parameter, which is 32-bit
> on X32. Therefore e.g. llseek returning a valid offset of 0xfffffffe
> will be mishandled as returning errno 2.
> 
> The updated patch also includes fix for this bug.

...the slight problem that my code... doesn't fix the bug :(

+is_negated_errno_ll(unsigned long long val)
+{
+	unsigned long long max = -(long long) nerrnos;
+#if SUPPORTED_PERSONALITIES > 1
+	if (current_wordsize < sizeof(val)) {
+		val = (unsigned int) val;
+		max = (unsigned int) max;
+	}
+#endif
+	return val > max;
+}

The above _always_ falls into "if", since current_wordsize == 4
even for native X32.
Looks like I'll have to resort to x32-specific checking function:

+static inline int
+is_negated_errno_x32(unsigned long long val)
+{
+       unsigned long long max = -(long long) nerrnos;
+       /*
+        * current_wordsize == 4 even in personality 0 (X32)
+        * but truncation _must not_ be done in it.
+        * can't check current_wordsize here!
+        */
+       if (current_personality != 0) {
+               val = (uint32_t) val;
+               max = (uint32_t) max;
+       }
+       return val > max;
+}

-- 
vda





More information about the Strace-devel mailing list