Fix capability verification
authorPanu Matilainen <pmatilai@redhat.com>
Fri, 14 Nov 2008 07:47:43 +0000 (09:47 +0200)
committerPanu Matilainen <pmatilai@redhat.com>
Fri, 14 Nov 2008 07:47:43 +0000 (09:47 +0200)
- the previous implementation was pretty busted up, cap_size() is the
  size of external representation, not sizeof(*cap_t) as pointed out by
  Andrew Morgan
- check for cap_compare() in configure and use it if available (it's
  a Linux-specific extension to the posix draft and only very recent
  libcap has it)
- if cap_compare() isn't available, use internal variant that does it
  the hard way by converting the capabilities to external presentation
  and comparing those

configure.ac
lib/verify.c

index 7c5b1dd..b0f90ad 100644 (file)
@@ -751,7 +751,14 @@ esac],
 
 AS_IF([test "$with_cap" = yes],[
   AC_CHECK_HEADER([sys/capability.h],[
-    AC_CHECK_LIB(cap,[cap_get_file],[with_cap=yes],[
+    AC_CHECK_LIB(cap,[cap_get_file], [
+      with_cap=yes
+      save_LIBS="$LIBS"
+      AC_CHECK_LIB(cap,[cap_compare], [
+        AC_DEFINE(HAVE_CAP_COMPARE, 1, [Have cap_compare function?])
+      ])
+      LIBS="$save_LIBS"
+    ],[
       AC_MSG_ERROR([--with-cap given, but libcap not found])])
   ],[
     AC_MSG_ERROR([--with-cap given, but sys/capability.h not found])
index e485f03..877eb93 100644 (file)
 
 extern int _rpmds_unspecified_epoch_noise;
 
+/* If cap_compare() (Linux extension) not available, do it the hard way */
+#if WITH_CAP && !defined(HAVE_CAP_COMPARE)
+static int cap_compare(cap_t acap, cap_t bcap)
+{
+    int rc = 0;
+    size_t asize = cap_size(acap);
+    size_t bsize = cap_size(bcap);
+
+    if (asize != bsize) {
+       rc = 1;
+    } else {
+       char *abuf = xcalloc(asize, sizeof(*abuf));
+       char *bbuf = xcalloc(bsize, sizeof(*bbuf));
+       cap_copy_ext(abuf, acap, asize);
+       cap_copy_ext(bbuf, bcap, bsize);
+       rc = memcmp(abuf, bbuf, asize);
+       free(abuf);
+       free(bbuf);
+    }
+    return rc;
+}
+#endif
+       
 int rpmVerifyFile(const rpmts ts, const rpmfi fi,
                rpmVerifyAttrs * res, rpmVerifyAttrs omitMask)
 {
@@ -196,11 +219,10 @@ int rpmVerifyFile(const rpmts ts, const rpmfi fi,
        if (!fcap) {
            fcap = cap_from_text("=");
        }
-
-       /* TODO: use cap_compare() if available */
-       if (memcmp(cap, fcap, cap_size(cap)) != 0) 
-           *res |= RPMVERIFY_CAPS;
        
+       if (cap_compare(cap, fcap) != 0)
+           *res |= RPMVERIFY_CAPS;
+
        cap_free(fcap);
        cap_free(cap);
     }