On Sat, 20 Apr 2013 01:35, clo...@igalia.com said:

> I think it would be a good idea to add this feature to libgcrypt.

See attached patch against master.  It is not tested, though.  You may
backport it to 1.5 and use it like this:

#if GCRYPT_VERSION_NUMBER > 0x010502
    gcry_control (GCRYCTL_DISABLE_PRIV_DROP, 0);
#endif /* libgcrypt > 1.5.2 */

> However, I don't think that it would help us with this specific Debian
> bug because it would be implemented as an optional feature.

I can't understand what you want to say.

> And the suid application (sudo/su/passwd/...) can't know anything about
> libgcrypt, so it can't set this flag or any other libgcrypt flag.

The application (sudo,su,passwd) needs to set this flag!  No library is
able to know what the applications wants.  Optionally you may put
wrappers in the mentioned libraries, but that makes things more
complicated and fragile.


Shalom-Salam,

   Werner

-- 
Die Gedanken sind frei.  Ausnahmen regelt ein Bundesgesetz.
>From ae46d6646795ce79743d43927f913ce1ec6bddfe Mon Sep 17 00:00:00 2001
From: Werner Koch <w...@gnupg.org>
Date: Thu, 18 Apr 2013 14:40:43 +0200
Subject: [PATCH] Add control commands to disable mlock and setuid dropping.

* src/gcrypt.h.in (GCRYCTL_DISABLE_LOCKED_SECMEM): New.
(GCRYCTL_DISABLE_PRIV_DROP): New.
* src/global.c (_gcry_vcontrol): Implement them.
* src/secmem.h (GCRY_SECMEM_FLAG_NO_MLOCK): New.
(GCRY_SECMEM_FLAG_NO_PRIV_DROP): New.
* src/secmem.c (no_mlock, no_priv_drop): New.
(_gcry_secmem_set_flags, _gcry_secmem_get_flags): Set and get them.
(lock_pool): Handle no_mlock and no_priv_drop.

Signed-off-by: Werner Koch <w...@gnupg.org>
---
 doc/gcrypt.texi |   18 ++++++++++++++++++
 src/gcrypt.h.in |    4 +++-
 src/global.c    |   13 +++++++++++++
 src/secmem.c    |   29 +++++++++++++++++++++--------
 src/secmem.h    |    2 ++
 5 files changed, 57 insertions(+), 9 deletions(-)

diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index d4c4194..4d24475 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -679,6 +679,24 @@ Many applications do not require secure memory, so they should disable
 it right away.  This command should be executed right after
 @code{gcry_check_version}.
 
+@item GCRYCTL_DISABLE_LOCKED_SECMEM; Arguments: none
+This command disables the use of the mlock call for secure memory.
+Disabling the use of mlock may for example be done if an encrypted
+swap space is in use.  This command should be executed right after
+@code{gcry_check_version}.
+
+@item GCRYCTL_DISABLE_PRIV_DROP; Arguments: none
+This command sets a global flag to tell the secure memory subsystem
+that it shall not drop privileges after secure memory has been
+allocated.  This command is commonly used right after
+@code{gcry_check_version} but may also be used right away at program
+startup.  It won't have an effect after the secure memory pool has
+been initialized.  WARNING: A process running setuid(root) is a severe
+security risk.  Processes making use of Libgcrypt or other complex
+code should drop these extra privileges as soon as possible.  If this
+command has been used the caller is responsible for dropping the
+privileges.
+
 @item GCRYCTL_INIT_SECMEM; Arguments: int nbytes
 This command is used to allocate a pool of secure memory and thus
 enabling the use of secure memory.  It also drops all extra privileges
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index f472b02..27a29ec 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -302,7 +302,9 @@ enum gcry_ctl_cmds
     GCRYCTL_DISABLE_HWF = 63,
     GCRYCTL_SET_ENFORCED_FIPS_FLAG = 64,
     GCRYCTL_SET_PREFERRED_RNG_TYPE = 65,
-    GCRYCTL_GET_CURRENT_RNG_TYPE = 66
+    GCRYCTL_GET_CURRENT_RNG_TYPE = 66,
+    GCRYCTL_DISABLE_LOCKED_SECMEM = 67,
+    GCRYCTL_DISABLE_PRIV_DROP = 68
   };
 
 /* Perform various operations defined by CMD. */
diff --git a/src/global.c b/src/global.c
index f873897..a6fe980 100644
--- a/src/global.c
+++ b/src/global.c
@@ -2,6 +2,7 @@
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
  *               2004, 2005, 2006, 2008, 2011,
  *               2012  Free Software Foundation, Inc.
+ * Copyright (C) 2013 g10 Code GmbH
  *
  * This file is part of Libgcrypt.
  *
@@ -687,6 +688,18 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
       }
       break;
 
+    case GCRYCTL_DISABLE_LOCKED_SECMEM:
+      _gcry_set_preferred_rng_type (0);
+      _gcry_secmem_set_flags ((_gcry_secmem_get_flags ()
+			       | GCRY_SECMEM_FLAG_NO_MLOCK));
+      break;
+
+    case GCRYCTL_DISABLE_PRIV_DROP:
+      _gcry_set_preferred_rng_type (0);
+      _gcry_secmem_set_flags ((_gcry_secmem_get_flags ()
+			       | GCRY_SECMEM_FLAG_NO_PRIV_DROP));
+      break;
+
     default:
       _gcry_set_preferred_rng_type (0);
       err = GPG_ERR_INV_OP;
diff --git a/src/secmem.c b/src/secmem.c
index 107c662..c350bc9 100644
--- a/src/secmem.c
+++ b/src/secmem.c
@@ -1,6 +1,7 @@
 /* secmem.c  -	memory allocation from a secure heap
  * Copyright (C) 1998, 1999, 2000, 2001, 2002,
  *               2003, 2007 Free Software Foundation, Inc.
+ * Copyright (C) 2013 g10 Code GmbH
  *
  * This file is part of Libgcrypt.
  *
@@ -78,6 +79,8 @@ static int show_warning;
 static int not_locked;
 static int no_warning;
 static int suspend_warning;
+static int no_mlock;
+static int no_priv_drop;
 
 /* Stats.  */
 static unsigned int cur_alloced, cur_blocks;
@@ -241,7 +244,7 @@ lock_pool (void *p, size_t n)
   int err;
 
   cap_set_proc (cap_from_text ("cap_ipc_lock+ep"));
-  err = mlock (p, n);
+  err = no_mlock? 0 : mlock (p, n);
   if (err && errno)
     err = errno;
   cap_set_proc (cap_from_text ("cap_ipc_lock+p"));
@@ -282,22 +285,27 @@ lock_pool (void *p, size_t n)
     }
   else
     {
-      err = mlock (p, n);
+      err = no_mlock? 0 : mlock (p, n);
       if (err && errno)
 	err = errno;
     }
 #else /* !HAVE_BROKEN_MLOCK */
-  err = mlock (p, n);
+  err = no_mlock? 0 : mlock (p, n);
   if (err && errno)
     err = errno;
 #endif /* !HAVE_BROKEN_MLOCK */
 
+  /* Test whether we are running setuid(0).  */
   if (uid && ! geteuid ())
     {
-      /* check that we really dropped the privs.
-       * Note: setuid(0) should always fail */
-      if (setuid (uid) || getuid () != geteuid () || !setuid (0))
-	log_fatal ("failed to reset uid: %s\n", strerror (errno));
+      /* Yes, we are.  */
+      if (!no_priv_drop)
+        {
+          /* Check that we really dropped the privs.
+           * Note: setuid(0) should always fail */
+          if (setuid (uid) || getuid () != geteuid () || !setuid (0))
+            log_fatal ("failed to reset uid: %s\n", strerror (errno));
+        }
     }
 
   if (err)
@@ -339,7 +347,8 @@ lock_pool (void *p, size_t n)
 #else
   (void)p;
   (void)n;
-  log_info ("Please note that you don't have secure memory on this system\n");
+  if (!no_mlock)
+    log_info ("Please note that you don't have secure memory on this system\n");
 #endif
 }
 
@@ -424,6 +433,8 @@ _gcry_secmem_set_flags (unsigned flags)
   was_susp = suspend_warning;
   no_warning = flags & GCRY_SECMEM_FLAG_NO_WARNING;
   suspend_warning = flags & GCRY_SECMEM_FLAG_SUSPEND_WARNING;
+  no_mlock      = flags & GCRY_SECMEM_FLAG_NO_MLOCK;
+  no_priv_drop = flags & GCRY_SECMEM_FLAG_NO_PRIV_DROP;
 
   /* and now issue the warning if it is not longer suspended */
   if (was_susp && !suspend_warning && show_warning)
@@ -445,6 +456,8 @@ _gcry_secmem_get_flags (void)
   flags = no_warning ? GCRY_SECMEM_FLAG_NO_WARNING : 0;
   flags |= suspend_warning ? GCRY_SECMEM_FLAG_SUSPEND_WARNING : 0;
   flags |= not_locked ? GCRY_SECMEM_FLAG_NOT_LOCKED : 0;
+  flags |= no_mlock ? GCRY_SECMEM_FLAG_NO_MLOCK : 0;
+  flags |= no_priv_drop ? GCRY_SECMEM_FLAG_NO_PRIV_DROP : 0;
 
   SECMEM_UNLOCK;
 
diff --git a/src/secmem.h b/src/secmem.h
index 29e151a..3577381 100644
--- a/src/secmem.h
+++ b/src/secmem.h
@@ -35,5 +35,7 @@ int _gcry_private_is_secure (const void *p);
 #define GCRY_SECMEM_FLAG_NO_WARNING      (1 << 0)
 #define GCRY_SECMEM_FLAG_SUSPEND_WARNING (1 << 1)
 #define GCRY_SECMEM_FLAG_NOT_LOCKED      (1 << 2)
+#define GCRY_SECMEM_FLAG_NO_MLOCK        (1 << 3)
+#define GCRY_SECMEM_FLAG_NO_PRIV_DROP    (1 << 4)
 
 #endif /* G10_SECMEM_H */
-- 
1.7.7.1

Reply via email to