[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