]> granicus.if.org Git - strace/commitdiff
Fix lame kernel version checking code
authorDenys Vlasenko <vda.linux@googlemail.com>
Thu, 15 Mar 2012 13:36:28 +0000 (14:36 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Thu, 15 Mar 2012 13:36:28 +0000 (14:36 +0100)
The code "os_release[0] >= '3'" is not good for any
finer-grained checks such as "kernel >= 3.2.1".
Let's proactively fix it.

* strace.c: Change os_release from string to integer.
(get_os_release): Parse uname.release to KERNEL_VERSION
representation.
(init): Convert kernel version check to KERNEL_VERSION.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
strace.c

index 15fc1b6f1a43facbc750af928b6480ce9a98d88d..22962a64eca5ae6f620ebe40148fa187960d236d 100644 (file)
--- a/strace.c
+++ b/strace.c
@@ -144,7 +144,7 @@ static struct tcb **tcbtab;
 static unsigned int nprocs, tcbtabsize;
 static const char *progname;
 
-static char *os_release; /* from uname() */
+static unsigned os_release; /* generated from uname()'s u.release */
 
 static int detach(struct tcb *tcp);
 static int trace(void);
@@ -1169,15 +1169,31 @@ test_ptrace_seize(void)
 #  define test_ptrace_seize() ((void)0)
 # endif
 
-static void
+static unsigned
 get_os_release(void)
 {
+       unsigned rel;
+       const char *p;
        struct utsname u;
        if (uname(&u) < 0)
                perror_msg_and_die("uname");
-       os_release = strdup(u.release);
-       if (!os_release)
-               die_out_of_memory();
+       /* u.release has this form: "3.2.9[-some-garbage]" */
+       rel = 0;
+       p = u.release;
+       for (;;) {
+               if (!(*p >= '0' && *p <= '9'))
+                       error_msg_and_die("Bad OS release string: '%s'", u.release);
+               /* Note: this open-codes KERNEL_VERSION(): */
+               rel = (rel << 8) | atoi(p);
+               if (rel >= KERNEL_VERSION(1,0,0))
+                       break;
+               while (*p >= '0' && *p <= '9')
+                       p++;
+               if (*p != '.')
+                       error_msg_and_die("Bad OS release string: '%s'", u.release);
+               p++;
+       }
+       return rel;
 }
 
 /*
@@ -1200,7 +1216,7 @@ init(int argc, char *argv[])
 
        strace_tracer_pid = getpid();
 
-       get_os_release();
+       os_release = get_os_release();
 
        /* Allocate the initial tcbtab.  */
        tcbtabsize = argc;      /* Surely enough for all -p args.  */
@@ -1896,7 +1912,7 @@ trace(void)
                 * PTRACE_GETEVENTMSG returns old pid starting from Linux 3.0.
                 * On 2.6 and earlier, it can return garbage.
                 */
-               if (event == PTRACE_EVENT_EXEC && os_release[0] >= '3') {
+               if (event == PTRACE_EVENT_EXEC && os_release >= KERNEL_VERSION(3,0,0)) {
                        long old_pid = 0;
                        if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, (long) &old_pid) >= 0
                         && old_pid > 0